[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @package Joomla.Administrator 5 * @subpackage com_installer 6 * 7 * @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org> 8 * @license GNU General Public License version 2 or later; see LICENSE.txt 9 */ 10 11 namespace Joomla\Component\Installer\Administrator\Model; 12 13 use Joomla\CMS\Changelog\Changelog; 14 use Joomla\CMS\Extension\ExtensionHelper; 15 use Joomla\CMS\Factory; 16 use Joomla\CMS\Installer\Installer; 17 use Joomla\CMS\Language\Text; 18 use Joomla\CMS\Layout\FileLayout; 19 use Joomla\CMS\MVC\Factory\MVCFactoryInterface; 20 use Joomla\CMS\Plugin\PluginHelper; 21 use Joomla\CMS\Table\Extension; 22 use Joomla\Component\Templates\Administrator\Table\StyleTable; 23 use Joomla\Database\DatabaseQuery; 24 use Joomla\Database\ParameterType; 25 26 // phpcs:disable PSR1.Files.SideEffects 27 \defined('_JEXEC') or die; 28 // phpcs:enable PSR1.Files.SideEffects 29 30 /** 31 * Installer Manage Model 32 * 33 * @since 1.5 34 */ 35 class ManageModel extends InstallerModel 36 { 37 /** 38 * Constructor. 39 * 40 * @param array $config An optional associative array of configuration settings. 41 * @param MVCFactoryInterface $factory The factory. 42 * 43 * @see \Joomla\CMS\MVC\Model\ListModel 44 * @since 1.6 45 */ 46 public function __construct($config = array(), MVCFactoryInterface $factory = null) 47 { 48 if (empty($config['filter_fields'])) { 49 $config['filter_fields'] = array( 50 'status', 51 'name', 52 'client_id', 53 'client', 'client_translated', 54 'type', 'type_translated', 55 'folder', 'folder_translated', 56 'package_id', 57 'extension_id', 58 'creationDate', 59 ); 60 } 61 62 parent::__construct($config, $factory); 63 } 64 65 /** 66 * Method to auto-populate the model state. 67 * 68 * Note. Calling getState in this method will result in recursion. 69 * 70 * @param string $ordering An optional ordering field. 71 * @param string $direction An optional direction (asc|desc). 72 * 73 * @return void 74 * 75 * @throws \Exception 76 * 77 * @since 1.6 78 */ 79 protected function populateState($ordering = 'name', $direction = 'asc') 80 { 81 $app = Factory::getApplication(); 82 83 // Load the filter state. 84 $this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string')); 85 $this->setState('filter.client_id', $this->getUserStateFromRequest($this->context . '.filter.client_id', 'filter_client_id', null, 'int')); 86 $this->setState('filter.package_id', $this->getUserStateFromRequest($this->context . '.filter.package_id', 'filter_package_id', null, 'int')); 87 $this->setState('filter.status', $this->getUserStateFromRequest($this->context . '.filter.status', 'filter_status', '', 'string')); 88 $this->setState('filter.type', $this->getUserStateFromRequest($this->context . '.filter.type', 'filter_type', '', 'string')); 89 $this->setState('filter.folder', $this->getUserStateFromRequest($this->context . '.filter.folder', 'filter_folder', '', 'string')); 90 $this->setState('filter.core', $this->getUserStateFromRequest($this->context . '.filter.core', 'filter_core', '', 'string')); 91 92 $this->setState('message', $app->getUserState('com_installer.message')); 93 $this->setState('extension_message', $app->getUserState('com_installer.extension_message')); 94 $app->setUserState('com_installer.message', ''); 95 $app->setUserState('com_installer.extension_message', ''); 96 97 parent::populateState($ordering, $direction); 98 } 99 100 /** 101 * Enable/Disable an extension. 102 * 103 * @param array $eid Extension ids to un/publish 104 * @param int $value Publish value 105 * 106 * @return boolean True on success 107 * 108 * @throws \Exception 109 * 110 * @since 1.5 111 */ 112 public function publish(&$eid = array(), $value = 1) 113 { 114 if (!Factory::getUser()->authorise('core.edit.state', 'com_installer')) { 115 Factory::getApplication()->enqueueMessage(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), 'error'); 116 117 return false; 118 } 119 120 $result = true; 121 122 /* 123 * Ensure eid is an array of extension ids 124 * @todo: If it isn't an array do we want to set an error and fail? 125 */ 126 if (!is_array($eid)) { 127 $eid = array($eid); 128 } 129 130 // Get a table object for the extension type 131 $table = new Extension($this->getDatabase()); 132 133 // Enable the extension in the table and store it in the database 134 foreach ($eid as $i => $id) { 135 $table->load($id); 136 137 if ($table->type == 'template') { 138 $style = new StyleTable($this->getDatabase()); 139 140 if ($style->load(array('template' => $table->element, 'client_id' => $table->client_id, 'home' => 1))) { 141 Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_ERROR_DISABLE_DEFAULT_TEMPLATE_NOT_PERMITTED'), 'notice'); 142 unset($eid[$i]); 143 continue; 144 } 145 146 // Parent template cannot be disabled if there are children 147 if ($style->load(['parent' => $table->element, 'client_id' => $table->client_id])) { 148 Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_ERROR_DISABLE_PARENT_TEMPLATE_NOT_PERMITTED'), 'notice'); 149 unset($eid[$i]); 150 continue; 151 } 152 } 153 154 if ($table->protected == 1) { 155 $result = false; 156 Factory::getApplication()->enqueueMessage(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), 'error'); 157 } else { 158 $table->enabled = $value; 159 } 160 161 $context = $this->option . '.' . $this->name; 162 163 PluginHelper::importPlugin('extension'); 164 Factory::getApplication()->triggerEvent('onExtensionChangeState', array($context, $eid, $value)); 165 166 if (!$table->store()) { 167 $this->setError($table->getError()); 168 $result = false; 169 } 170 } 171 172 // Clear the cached extension data and menu cache 173 $this->cleanCache('_system'); 174 $this->cleanCache('com_modules'); 175 $this->cleanCache('mod_menu'); 176 177 return $result; 178 } 179 180 /** 181 * Refreshes the cached manifest information for an extension. 182 * 183 * @param int|int[] $eid extension identifier (key in #__extensions) 184 * 185 * @return boolean result of refresh 186 * 187 * @since 1.6 188 */ 189 public function refresh($eid) 190 { 191 if (!is_array($eid)) { 192 $eid = array($eid => 0); 193 } 194 195 // Get an installer object for the extension type 196 $installer = Installer::getInstance(); 197 $result = 0; 198 199 // Uninstall the chosen extensions 200 foreach ($eid as $id) { 201 $result |= $installer->refreshManifestCache($id); 202 } 203 204 return $result; 205 } 206 207 /** 208 * Remove (uninstall) an extension 209 * 210 * @param array $eid An array of identifiers 211 * 212 * @return boolean True on success 213 * 214 * @throws \Exception 215 * 216 * @since 1.5 217 */ 218 public function remove($eid = array()) 219 { 220 if (!Factory::getUser()->authorise('core.delete', 'com_installer')) { 221 Factory::getApplication()->enqueueMessage(Text::_('JERROR_CORE_DELETE_NOT_PERMITTED'), 'error'); 222 223 return false; 224 } 225 226 /* 227 * Ensure eid is an array of extension ids in the form id => client_id 228 * @todo: If it isn't an array do we want to set an error and fail? 229 */ 230 if (!is_array($eid)) { 231 $eid = array($eid => 0); 232 } 233 234 // Get an installer object for the extension type 235 $installer = Installer::getInstance(); 236 $row = new \Joomla\CMS\Table\Extension($this->getDatabase()); 237 238 // Uninstall the chosen extensions 239 $msgs = array(); 240 $result = false; 241 242 foreach ($eid as $id) { 243 $id = trim($id); 244 $row->load($id); 245 $result = false; 246 247 // Do not allow to uninstall locked extensions. 248 if ((int) $row->locked === 1) { 249 $msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_ERROR_LOCKED_EXTENSION', $row->name, $id); 250 251 continue; 252 } 253 254 $langstring = 'COM_INSTALLER_TYPE_TYPE_' . strtoupper($row->type); 255 $rowtype = Text::_($langstring); 256 257 if (strpos($rowtype, $langstring) !== false) { 258 $rowtype = $row->type; 259 } 260 261 if ($row->type) { 262 $result = $installer->uninstall($row->type, $id); 263 264 // Build an array of extensions that failed to uninstall 265 if ($result === false) { 266 // There was an error in uninstalling the package 267 $msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_ERROR', $rowtype); 268 269 continue; 270 } 271 272 // Package uninstalled successfully 273 $msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_SUCCESS', $rowtype); 274 $result = true; 275 276 continue; 277 } 278 279 // There was an error in uninstalling the package 280 $msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_ERROR', $rowtype); 281 } 282 283 $msg = implode('<br>', $msgs); 284 $app = Factory::getApplication(); 285 $app->enqueueMessage($msg); 286 $this->setState('action', 'remove'); 287 $this->setState('name', $installer->get('name')); 288 $app->setUserState('com_installer.message', $installer->message); 289 $app->setUserState('com_installer.extension_message', $installer->get('extension_message')); 290 291 // Clear the cached extension data and menu cache 292 $this->cleanCache('_system'); 293 $this->cleanCache('com_modules'); 294 $this->cleanCache('com_plugins'); 295 $this->cleanCache('mod_menu'); 296 297 return $result; 298 } 299 300 /** 301 * Method to get the database query 302 * 303 * @return DatabaseQuery The database query 304 * 305 * @since 1.6 306 */ 307 protected function getListQuery() 308 { 309 $db = $this->getDatabase(); 310 $query = $db->getQuery(true) 311 ->select('*') 312 ->select('2*protected+(1-protected)*enabled AS status') 313 ->from('#__extensions') 314 ->where('state = 0'); 315 316 // Process select filters. 317 $status = $this->getState('filter.status', ''); 318 $type = $this->getState('filter.type'); 319 $clientId = $this->getState('filter.client_id', ''); 320 $folder = $this->getState('filter.folder'); 321 $core = $this->getState('filter.core', ''); 322 $packageId = $this->getState('filter.package_id', ''); 323 324 if ($status !== '') { 325 if ($status === '2') { 326 $query->where('protected = 1'); 327 } elseif ($status === '3') { 328 $query->where('protected = 0'); 329 } else { 330 $status = (int) $status; 331 $query->where($db->quoteName('protected') . ' = 0') 332 ->where($db->quoteName('enabled') . ' = :status') 333 ->bind(':status', $status, ParameterType::INTEGER); 334 } 335 } 336 337 if ($type) { 338 $query->where($db->quoteName('type') . ' = :type') 339 ->bind(':type', $type); 340 } 341 342 if ($clientId !== '') { 343 $clientId = (int) $clientId; 344 $query->where($db->quoteName('client_id') . ' = :clientid') 345 ->bind(':clientid', $clientId, ParameterType::INTEGER); 346 } 347 348 if ($packageId !== '') { 349 $packageId = (int) $packageId; 350 $query->where( 351 '((' . $db->quoteName('package_id') . ' = :packageId1) OR ' 352 . '(' . $db->quoteName('extension_id') . ' = :packageId2))' 353 ) 354 ->bind([':packageId1',':packageId2'], $packageId, ParameterType::INTEGER); 355 } 356 357 if ($folder) { 358 $folder = $folder === '*' ? '' : $folder; 359 $query->where($db->quoteName('folder') . ' = :folder') 360 ->bind(':folder', $folder); 361 } 362 363 // Filter by core extensions. 364 if ($core === '1' || $core === '0') { 365 $coreExtensionIds = ExtensionHelper::getCoreExtensionIds(); 366 $method = $core === '1' ? 'whereIn' : 'whereNotIn'; 367 $query->$method($db->quoteName('extension_id'), $coreExtensionIds); 368 } 369 370 // Process search filter (extension id). 371 $search = $this->getState('filter.search'); 372 373 if (!empty($search) && stripos($search, 'id:') === 0) { 374 $ids = (int) substr($search, 3); 375 $query->where($db->quoteName('extension_id') . ' = :eid') 376 ->bind(':eid', $ids, ParameterType::INTEGER); 377 } 378 379 // Note: The search for name, ordering and pagination are processed by the parent InstallerModel class (in extension.php). 380 381 return $query; 382 } 383 384 /** 385 * Load the changelog details for a given extension. 386 * 387 * @param integer $eid The extension ID 388 * @param string $source The view the changelog is for, this is used to determine which version number to show 389 * 390 * @return string The output to show in the modal. 391 * 392 * @since 4.0.0 393 */ 394 public function loadChangelog($eid, $source) 395 { 396 // Get the changelog URL 397 $eid = (int) $eid; 398 $db = $this->getDatabase(); 399 $query = $db->getQuery(true) 400 ->select( 401 $db->quoteName( 402 [ 403 'extensions.element', 404 'extensions.type', 405 'extensions.folder', 406 'extensions.changelogurl', 407 'extensions.manifest_cache', 408 'extensions.client_id' 409 ] 410 ) 411 ) 412 ->select($db->quoteName('updates.version', 'updateVersion')) 413 ->from($db->quoteName('#__extensions', 'extensions')) 414 ->join( 415 'LEFT', 416 $db->quoteName('#__updates', 'updates'), 417 $db->quoteName('updates.extension_id') . ' = ' . $db->quoteName('extensions.extension_id') 418 ) 419 ->where($db->quoteName('extensions.extension_id') . ' = :eid') 420 ->bind(':eid', $eid, ParameterType::INTEGER); 421 $db->setQuery($query); 422 423 $extensions = $db->loadObjectList(); 424 $this->translate($extensions); 425 $extension = array_shift($extensions); 426 427 if (!$extension->changelogurl) { 428 return ''; 429 } 430 431 $changelog = new Changelog(); 432 $changelog->setVersion($source === 'manage' ? $extension->version : $extension->updateVersion); 433 $changelog->loadFromXml($extension->changelogurl); 434 435 // Read all the entries 436 $entries = array( 437 'security' => array(), 438 'fix' => array(), 439 'addition' => array(), 440 'change' => array(), 441 'remove' => array(), 442 'language' => array(), 443 'note' => array() 444 ); 445 446 array_walk( 447 $entries, 448 function (&$value, $name) use ($changelog) { 449 if ($field = $changelog->get($name)) { 450 $value = $changelog->get($name)->data; 451 } 452 } 453 ); 454 455 $layout = new FileLayout('joomla.installer.changelog'); 456 $output = $layout->render($entries); 457 458 return $output; 459 } 460 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |