* @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Installer\Administrator\Model; use Exception; use Joomla\CMS\Form\Form; use Joomla\CMS\MVC\Model\AdminModel; use Joomla\CMS\Object\CMSObject; use Joomla\Component\Installer\Administrator\Helper\InstallerHelper; use Joomla\Database\ParameterType; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Item Model for an update site. * * @since 4.0.0 */ class UpdatesiteModel extends AdminModel { /** * The type alias for this content type. * * @var string * @since 4.0.0 */ public $typeAlias = 'com_installer.updatesite'; /** * Method to get the row form. * * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * * @return Form|boolean A Form object on success, false on failure * * @throws Exception * * @since 4.0.0 */ public function getForm($data = [], $loadData = true) { // Get the form. $form = $this->loadForm('com_installer.updatesite', 'updatesite', ['control' => 'jform', 'load_data' => $loadData]); if (empty($form)) { return false; } return $form; } /** * Method to get the data that should be injected in the form. * * @return mixed The data for the form. * * @since 4.0.0 */ protected function loadFormData() { $data = $this->getItem(); $this->preprocessData('com_installer.updatesite', $data); return $data; } /** * Method to get a single record. * * @param integer $pk The id of the primary key. * * @return CMSObject|boolean Object on success, false on failure. * * @since 4.0.0 */ public function getItem($pk = null) { $item = parent::getItem($pk); $db = $this->getDatabase(); $updateSiteId = (int) $item->get('update_site_id'); $query = $db->getQuery(true) ->select( $db->quoteName( [ 'update_sites.extra_query', 'extensions.type', 'extensions.element', 'extensions.folder', 'extensions.client_id', 'extensions.checked_out' ] ) ) ->from($db->quoteName('#__update_sites', 'update_sites')) ->join( 'INNER', $db->quoteName('#__update_sites_extensions', 'update_sites_extensions'), $db->quoteName('update_sites_extensions.update_site_id') . ' = ' . $db->quoteName('update_sites.update_site_id') ) ->join( 'INNER', $db->quoteName('#__extensions', 'extensions'), $db->quoteName('extensions.extension_id') . ' = ' . $db->quoteName('update_sites_extensions.extension_id') ) ->where($db->quoteName('update_sites.update_site_id') . ' = :updatesiteid') ->bind(':updatesiteid', $updateSiteId, ParameterType::INTEGER); $db->setQuery($query); $extension = new CMSObject($db->loadAssoc()); $downloadKey = InstallerHelper::getDownloadKey($extension); $item->set('extra_query', $downloadKey['value'] ?? ''); $item->set('downloadIdPrefix', $downloadKey['prefix'] ?? ''); $item->set('downloadIdSuffix', $downloadKey['suffix'] ?? ''); return $item; } /** * Method to save the form data. * * @param array $data The form data. * * @return boolean True on success, False on error. * * @since 4.0.0 */ public function save($data): bool { // Apply the extra_query. Always empty when saving a free extension's update site. if (isset($data['extra_query'])) { $data['extra_query'] = $data['downloadIdPrefix'] . $data['extra_query'] . $data['downloadIdSuffix']; } // Force Joomla to recheck for updates $data['last_check_timestamp'] = 0; $result = parent::save($data); if (!$result) { return $result; } // Delete update records forcing Joomla to fetch them again, applying the new extra_query. $db = $this->getDatabase(); $query = $db->getQuery(true) ->delete($db->quoteName('#__updates')) ->where($db->quoteName('update_site_id') . ' = :updateSiteId'); $query->bind(':updateSiteId', $data['update_site_id'], ParameterType::INTEGER); try { $db->setQuery($query)->execute(); } catch (Exception $e) { // No problem if this fails for any reason. } return true; } }