1<?php 2/** 3 * @package Joomla.Administrator 4 * @subpackage com_installer 5 * 6 * @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved. 7 * @license GNU General Public License version 2 or later; see LICENSE.txt 8 */ 9 10defined('_JEXEC') or die; 11 12JLoader::register('InstallerModel', __DIR__ . '/extension.php'); 13 14/** 15 * Installer Manage Model 16 * 17 * @since 1.5 18 */ 19class InstallerModelManage extends InstallerModel 20{ 21 /** 22 * Constructor. 23 * 24 * @param array $config An optional associative array of configuration settings. 25 * 26 * @see JController 27 * @since 1.6 28 */ 29 public function __construct($config = array()) 30 { 31 if (empty($config['filter_fields'])) 32 { 33 $config['filter_fields'] = array( 34 'status', 35 'name', 36 'client_id', 37 'client', 'client_translated', 38 'type', 'type_translated', 39 'folder', 'folder_translated', 40 'package_id', 41 'extension_id', 42 ); 43 } 44 45 parent::__construct($config); 46 } 47 48 /** 49 * Method to auto-populate the model state. 50 * 51 * Note. Calling getState in this method will result in recursion. 52 * 53 * @param string $ordering An optional ordering field. 54 * @param string $direction An optional direction (asc|desc). 55 * 56 * @return void 57 * 58 * @since 1.6 59 */ 60 protected function populateState($ordering = 'name', $direction = 'asc') 61 { 62 $app = JFactory::getApplication(); 63 64 // Load the filter state. 65 $this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string')); 66 $this->setState('filter.client_id', $this->getUserStateFromRequest($this->context . '.filter.client_id', 'filter_client_id', null, 'int')); 67 $this->setState('filter.status', $this->getUserStateFromRequest($this->context . '.filter.status', 'filter_status', '', 'string')); 68 $this->setState('filter.type', $this->getUserStateFromRequest($this->context . '.filter.type', 'filter_type', '', 'string')); 69 $this->setState('filter.folder', $this->getUserStateFromRequest($this->context . '.filter.folder', 'filter_folder', '', 'string')); 70 71 $this->setState('message', $app->getUserState('com_installer.message')); 72 $this->setState('extension_message', $app->getUserState('com_installer.extension_message')); 73 $app->setUserState('com_installer.message', ''); 74 $app->setUserState('com_installer.extension_message', ''); 75 76 parent::populateState($ordering, $direction); 77 } 78 79 /** 80 * Enable/Disable an extension. 81 * 82 * @param array $eid Extension ids to un/publish 83 * @param int $value Publish value 84 * 85 * @return boolean True on success 86 * 87 * @since 1.5 88 */ 89 public function publish(&$eid = array(), $value = 1) 90 { 91 $user = JFactory::getUser(); 92 93 if (!$user->authorise('core.edit.state', 'com_installer')) 94 { 95 JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED')); 96 97 return false; 98 } 99 100 $result = true; 101 102 /* 103 * Ensure eid is an array of extension ids 104 * TODO: If it isn't an array do we want to set an error and fail? 105 */ 106 if (!is_array($eid)) 107 { 108 $eid = array($eid); 109 } 110 111 // Get a table object for the extension type 112 $table = JTable::getInstance('Extension'); 113 JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_templates/tables'); 114 115 // Enable the extension in the table and store it in the database 116 foreach ($eid as $i => $id) 117 { 118 $table->load($id); 119 120 if ($table->type == 'template') 121 { 122 $style = JTable::getInstance('Style', 'TemplatesTable'); 123 124 if ($style->load(array('template' => $table->element, 'client_id' => $table->client_id, 'home' => 1))) 125 { 126 JError::raiseNotice(403, JText::_('COM_INSTALLER_ERROR_DISABLE_DEFAULT_TEMPLATE_NOT_PERMITTED')); 127 unset($eid[$i]); 128 continue; 129 } 130 } 131 132 if ($table->protected == 1) 133 { 134 $result = false; 135 JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED')); 136 } 137 else 138 { 139 $table->enabled = $value; 140 } 141 142 $context = $this->option . '.' . $this->name; 143 JPluginHelper::importPlugin('extension'); 144 JEventDispatcher::getInstance()->trigger('onExtensionChangeState', array($context, $eid, $value)); 145 146 if (!$table->store()) 147 { 148 $this->setError($table->getError()); 149 $result = false; 150 } 151 } 152 153 // Clear the cached extension data and menu cache 154 $this->cleanCache('_system', 0); 155 $this->cleanCache('_system', 1); 156 $this->cleanCache('com_modules', 0); 157 $this->cleanCache('com_modules', 1); 158 $this->cleanCache('mod_menu', 0); 159 $this->cleanCache('mod_menu', 1); 160 161 return $result; 162 } 163 164 /** 165 * Refreshes the cached manifest information for an extension. 166 * 167 * @param int $eid extension identifier (key in #__extensions) 168 * 169 * @return boolean result of refresh 170 * 171 * @since 1.6 172 */ 173 public function refresh($eid) 174 { 175 if (!is_array($eid)) 176 { 177 $eid = array($eid => 0); 178 } 179 180 // Get an installer object for the extension type 181 $installer = JInstaller::getInstance(); 182 $result = 0; 183 184 // Uninstall the chosen extensions 185 foreach ($eid as $id) 186 { 187 $result |= $installer->refreshManifestCache($id); 188 } 189 190 return $result; 191 } 192 193 /** 194 * Remove (uninstall) an extension 195 * 196 * @param array $eid An array of identifiers 197 * 198 * @return boolean True on success 199 * 200 * @since 1.5 201 */ 202 public function remove($eid = array()) 203 { 204 $user = JFactory::getUser(); 205 206 if (!$user->authorise('core.delete', 'com_installer')) 207 { 208 JError::raiseWarning(403, JText::_('JERROR_CORE_DELETE_NOT_PERMITTED')); 209 210 return false; 211 } 212 213 /* 214 * Ensure eid is an array of extension ids in the form id => client_id 215 * TODO: If it isn't an array do we want to set an error and fail? 216 */ 217 if (!is_array($eid)) 218 { 219 $eid = array($eid => 0); 220 } 221 222 // Get an installer object for the extension type 223 $installer = JInstaller::getInstance(); 224 $row = JTable::getInstance('extension'); 225 226 // Uninstall the chosen extensions 227 $msgs = array(); 228 $result = false; 229 230 foreach ($eid as $id) 231 { 232 $id = trim($id); 233 $row->load($id); 234 $result = false; 235 236 $langstring = 'COM_INSTALLER_TYPE_TYPE_' . strtoupper($row->type); 237 $rowtype = JText::_($langstring); 238 239 if (strpos($rowtype, $langstring) !== false) 240 { 241 $rowtype = $row->type; 242 } 243 244 if ($row->type) 245 { 246 $result = $installer->uninstall($row->type, $id); 247 248 // Build an array of extensions that failed to uninstall 249 if ($result === false) 250 { 251 // There was an error in uninstalling the package 252 $msgs[] = JText::sprintf('COM_INSTALLER_UNINSTALL_ERROR', $rowtype); 253 254 continue; 255 } 256 257 // Package uninstalled successfully 258 $msgs[] = JText::sprintf('COM_INSTALLER_UNINSTALL_SUCCESS', $rowtype); 259 $result = true; 260 261 continue; 262 } 263 264 // There was an error in uninstalling the package 265 $msgs[] = JText::sprintf('COM_INSTALLER_UNINSTALL_ERROR', $rowtype); 266 } 267 268 $msg = implode('<br />', $msgs); 269 $app = JFactory::getApplication(); 270 $app->enqueueMessage($msg); 271 $this->setState('action', 'remove'); 272 $this->setState('name', $installer->get('name')); 273 $app->setUserState('com_installer.message', $installer->message); 274 $app->setUserState('com_installer.extension_message', $installer->get('extension_message')); 275 276 // Clear the cached extension data and menu cache 277 $this->cleanCache('_system', 0); 278 $this->cleanCache('_system', 1); 279 $this->cleanCache('com_modules', 0); 280 $this->cleanCache('com_modules', 1); 281 $this->cleanCache('com_plugins', 0); 282 $this->cleanCache('com_plugins', 1); 283 $this->cleanCache('mod_menu', 0); 284 $this->cleanCache('mod_menu', 1); 285 286 return $result; 287 } 288 289 /** 290 * Method to get the database query 291 * 292 * @return JDatabaseQuery The database query 293 * 294 * @since 1.6 295 */ 296 protected function getListQuery() 297 { 298 $query = $this->getDbo()->getQuery(true) 299 ->select('*') 300 ->select('2*protected+(1-protected)*enabled AS status') 301 ->from('#__extensions') 302 ->where('state = 0'); 303 304 // Process select filters. 305 $status = $this->getState('filter.status'); 306 $type = $this->getState('filter.type'); 307 $clientId = $this->getState('filter.client_id'); 308 $folder = $this->getState('filter.folder'); 309 310 if ($status != '') 311 { 312 if ($status == '2') 313 { 314 $query->where('protected = 1'); 315 } 316 elseif ($status == '3') 317 { 318 $query->where('protected = 0'); 319 } 320 else 321 { 322 $query->where('protected = 0') 323 ->where('enabled = ' . (int) $status); 324 } 325 } 326 327 if ($type) 328 { 329 $query->where('type = ' . $this->_db->quote($type)); 330 } 331 332 if ($clientId != '') 333 { 334 $query->where('client_id = ' . (int) $clientId); 335 } 336 337 if ($folder != '') 338 { 339 $query->where('folder = ' . $this->_db->quote($folder == '*' ? '' : $folder)); 340 } 341 342 // Process search filter (extension id). 343 $search = $this->getState('filter.search'); 344 345 if (!empty($search) && stripos($search, 'id:') === 0) 346 { 347 $query->where('extension_id = ' . (int) substr($search, 3)); 348 } 349 350 // Note: The search for name, ordering and pagination are processed by the parent InstallerModel class (in extension.php). 351 352 return $query; 353 } 354} 355