| [ Index ] |
PHP Cross Reference of Joomla 2.5.4 DE |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * @package Joomla.Platform 4 * @subpackage Installer 5 * 6 * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved. 7 * @license GNU General Public License version 2 or later; see LICENSE 8 */ 9 10 defined('JPATH_PLATFORM') or die; 11 12 jimport('joomla.base.adapterinstance'); 13 jimport('joomla.installer.packagemanifest'); 14 15 /** 16 * Package installer 17 * 18 * @package Joomla.Platform 19 * @subpackage Installer 20 * @since 11.1 21 */ 22 class JInstallerPackage extends JAdapterInstance 23 { 24 /** 25 * Method of system 26 * 27 * @var string 28 * 29 * @since 11.1 30 */ 31 protected $route = 'install'; 32 33 /** 34 * Load language from a path 35 * 36 * @param string $path The path of the language. 37 * 38 * @return void 39 * 40 * @since 11.1 41 */ 42 public function loadLanguage($path) 43 { 44 $this->manifest = $this->parent->getManifest(); 45 $extension = 'pkg_' . strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->packagename, 'cmd')); 46 $lang = JFactory::getLanguage(); 47 $source = $path; 48 $lang->load($extension . '.sys', $source, null, false, false) 49 || $lang->load($extension . '.sys', JPATH_SITE, null, false, false) 50 || $lang->load($extension . '.sys', $source, $lang->getDefault(), false, false) 51 || $lang->load($extension . '.sys', JPATH_SITE, $lang->getDefault(), false, false); 52 } 53 54 /** 55 * Custom install method 56 * 57 * @return int The extension id 58 * 59 * @since 11.1 60 */ 61 public function install() 62 { 63 // Get the extension manifest object 64 $this->manifest = $this->parent->getManifest(); 65 66 // Manifest Document Setup Section 67 68 // Set the extensions name 69 $filter = JFilterInput::getInstance(); 70 $name = (string) $this->manifest->packagename; 71 $name = $filter->clean($name, 'cmd'); 72 $this->set('name', $name); 73 74 $element = 'pkg_' . $filter->clean($this->manifest->packagename, 'cmd'); 75 $this->set('element', $element); 76 77 // Get the component description 78 $description = (string) $this->manifest->description; 79 if ($description) 80 { 81 $this->parent->set('message', JText::_($description)); 82 } 83 else 84 { 85 $this->parent->set('message', ''); 86 } 87 88 // Set the installation path 89 $files = $this->manifest->files; 90 $group = (string) $this->manifest->packagename; 91 if (!empty($group)) 92 { 93 $this->parent->setPath('extension_root', JPATH_MANIFESTS . '/packages/' . implode(DIRECTORY_SEPARATOR, explode('/', $group))); 94 } 95 else 96 { 97 $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_PACK', JText::_('JLIB_INSTALLER_' . strtoupper($this->route)))); 98 return false; 99 } 100 101 /** 102 * --------------------------------------------------------------------------------------------- 103 * Installer Trigger Loading 104 * --------------------------------------------------------------------------------------------- 105 */ 106 // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet) 107 $this->scriptElement = $this->manifest->scriptfile; 108 $manifestScript = (string) $this->manifest->scriptfile; 109 110 if ($manifestScript) 111 { 112 $manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript; 113 114 if (is_file($manifestScriptFile)) 115 { 116 // load the file 117 include_once $manifestScriptFile; 118 } 119 120 // Set the class name 121 $classname = $element . 'InstallerScript'; 122 123 if (class_exists($classname)) 124 { 125 // create a new instance 126 $this->parent->manifestClass = new $classname($this); 127 // and set this so we can copy it later 128 $this->set('manifest_script', $manifestScript); 129 // Note: if we don't find the class, don't bother to copy the file 130 } 131 } 132 133 // run preflight if possible (since we know we're not an update) 134 ob_start(); 135 ob_implicit_flush(false); 136 137 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight')) 138 { 139 if ($this->parent->manifestClass->preflight($this->route, $this) === false) 140 { 141 // Install failed, rollback changes 142 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PACKAGE_INSTALL_CUSTOM_INSTALL_FAILURE')); 143 144 return false; 145 } 146 } 147 148 $msg = ob_get_contents(); // create msg object; first use here 149 ob_end_clean(); 150 151 // Filesystem Processing Section 152 153 if ($folder = $files->attributes()->folder) 154 { 155 $source = $this->parent->getPath('source') . '/' . $folder; 156 } 157 else 158 { 159 $source = $this->parent->getPath('source'); 160 } 161 162 // Install all necessary files 163 if (count($this->manifest->files->children())) 164 { 165 $i = 0; 166 foreach ($this->manifest->files->children() as $child) 167 { 168 $file = $source . '/' . $child; 169 if (is_dir($file)) 170 { 171 // If it's actually a directory then fill it up 172 $package = array(); 173 $package['dir'] = $file; 174 $package['type'] = JInstallerHelper::detectType($file); 175 } 176 else 177 { 178 // If it's an archive 179 $package = JInstallerHelper::unpack($file); 180 } 181 $tmpInstaller = new JInstaller; 182 $installResult = $tmpInstaller->install($package['dir']); 183 if (!$installResult) 184 { 185 $this->parent->abort( 186 JText::sprintf( 187 'JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION', JText::_('JLIB_INSTALLER_' . strtoupper($this->route)), 188 basename($file) 189 ) 190 ); 191 return false; 192 } 193 else 194 { 195 $results[$i] = array( 196 'name' => $tmpInstaller->manifest->name, 197 'result' => $installResult 198 ); 199 } 200 $i++; 201 } 202 } 203 else 204 { 205 $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES', JText::_('JLIB_INSTALLER_' . strtoupper($this->route)))); 206 return false; 207 } 208 209 // Parse optional tags 210 $this->parent->parseLanguages($this->manifest->languages); 211 212 // Extension Registration 213 214 $row = JTable::getInstance('extension'); 215 $eid = $row->find(array('element' => strtolower($this->get('element')), 'type' => 'package')); 216 if ($eid) 217 { 218 $row->load($eid); 219 } 220 else 221 { 222 $row->name = $this->get('name'); 223 $row->type = 'package'; 224 $row->element = $this->get('element'); 225 // There is no folder for modules 226 $row->folder = ''; 227 $row->enabled = 1; 228 $row->protected = 0; 229 $row->access = 1; 230 $row->client_id = 0; 231 // custom data 232 $row->custom_data = ''; 233 $row->params = $this->parent->getParams(); 234 } 235 // Update the manifest cache for the entry 236 $row->manifest_cache = $this->parent->generateManifestCache(); 237 238 if (!$row->store()) 239 { 240 // Install failed, roll back changes 241 $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PACK_INSTALL_ROLLBACK', $row->getError())); 242 return false; 243 } 244 245 // Finalization and Cleanup Section 246 247 // Start Joomla! 1.6 248 ob_start(); 249 ob_implicit_flush(false); 250 251 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, $this->route)) 252 { 253 if ($this->parent->manifestClass->{$this->route}($this) === false) 254 { 255 // Install failed, rollback changes 256 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_INSTALL_CUSTOM_INSTALL_FAILURE')); 257 258 return false; 259 } 260 } 261 262 $msg .= ob_get_contents(); // append messages 263 ob_end_clean(); 264 265 // Lastly, we will copy the manifest file to its appropriate place. 266 $manifest = array(); 267 $manifest['src'] = $this->parent->getPath('manifest'); 268 $manifest['dest'] = JPATH_MANIFESTS . '/packages/' . basename($this->parent->getPath('manifest')); 269 270 if (!$this->parent->copyFiles(array($manifest), true)) 271 { 272 // Install failed, rollback changes 273 $this->parent->abort( 274 JText::sprintf('JLIB_INSTALLER_ABORT_PACK_INSTALL_COPY_SETUP', JText::_('JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES')) 275 ); 276 return false; 277 } 278 279 // If there is a manifest script, let's copy it. 280 if ($this->get('manifest_script')) 281 { 282 // First, we have to create a folder for the script if one isn't present 283 $created = false; 284 285 if (!file_exists($this->parent->getPath('extension_root'))) 286 { 287 JFolder::create($this->parent->getPath('extension_root')); 288 } 289 290 $path['src'] = $this->parent->getPath('source') . '/' . $this->get('manifest_script'); 291 $path['dest'] = $this->parent->getPath('extension_root') . '/' . $this->get('manifest_script'); 292 293 if (!file_exists($path['dest']) || $this->parent->getOverwrite()) 294 { 295 if (!$this->parent->copyFiles(array($path))) 296 { 297 // Install failed, rollback changes 298 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PACKAGE_INSTALL_MANIFEST')); 299 300 return false; 301 } 302 } 303 } 304 305 // And now we run the postflight 306 ob_start(); 307 ob_implicit_flush(false); 308 309 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'postflight')) 310 { 311 $this->parent->manifestClass->postflight($this->route, $this, $results); 312 } 313 314 $msg .= ob_get_contents(); // append messages 315 ob_end_clean(); 316 317 if ($msg != '') 318 { 319 $this->parent->set('extension_message', $msg); 320 } 321 return $row->extension_id; 322 } 323 324 /** 325 * Updates a package 326 * 327 * The only difference between an update and a full install 328 * is how we handle the database 329 * 330 * @return void 331 * 332 * @since 11.1 333 */ 334 public function update() 335 { 336 $this->route = 'update'; 337 $this->install(); 338 } 339 340 /** 341 * Custom uninstall method 342 * 343 * @param integer $id The id of the package to uninstall. 344 * 345 * @return boolean True on success 346 * 347 * @since 11.1 348 */ 349 public function uninstall($id) 350 { 351 // Initialise variables. 352 $row = null; 353 $retval = true; 354 355 $row = JTable::getInstance('extension'); 356 $row->load($id); 357 358 if ($row->protected) 359 { 360 JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_WARNCOREPACK')); 361 return false; 362 } 363 364 $manifestFile = JPATH_MANIFESTS . '/packages/' . $row->get('element') . '.xml'; 365 $manifest = new JPackageManifest($manifestFile); 366 367 // Set the package root path 368 $this->parent->setPath('extension_root', JPATH_MANIFESTS . '/packages/' . $manifest->packagename); 369 370 // Because packages may not have their own folders we cannot use the standard method of finding an installation manifest 371 if (!file_exists($manifestFile)) 372 { 373 // TODO: Fail? 374 JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_MISSINGMANIFEST')); 375 return false; 376 377 } 378 379 $xml = JFactory::getXML($manifestFile); 380 381 // If we cannot load the XML file return false 382 if (!$xml) 383 { 384 JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_LOAD_MANIFEST')); 385 return false; 386 } 387 388 /* 389 * Check for a valid XML root tag. 390 * @todo: Remove backwards compatibility in a future version 391 * Should be 'extension', but for backward compatibility we will accept 'install'. 392 */ 393 if ($xml->getName() != 'install' && $xml->getName() != 'extension') 394 { 395 JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_INVALID_MANIFEST')); 396 return false; 397 } 398 399 // If there is an manifest class file, let's load it 400 $this->scriptElement = $manifest->scriptfile; 401 $manifestScript = (string) $manifest->scriptfile; 402 403 if ($manifestScript) 404 { 405 $manifestScriptFile = $this->parent->getPath('extension_root') . '/' . $manifestScript; 406 407 if (is_file($manifestScriptFile)) 408 { 409 // Load the file 410 include_once $manifestScriptFile; 411 } 412 413 // Set the class name 414 $classname = $row->element . 'InstallerScript'; 415 416 if (class_exists($classname)) 417 { 418 // Create a new instance 419 $this->parent->manifestClass = new $classname($this); 420 // And set this so we can copy it later 421 $this->set('manifest_script', $manifestScript); 422 423 // Note: if we don't find the class, don't bother to copy the file 424 } 425 } 426 427 ob_start(); 428 ob_implicit_flush(false); 429 430 // Run uninstall if possible 431 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'uninstall')) 432 { 433 $this->parent->manifestClass->uninstall($this); 434 } 435 436 $msg = ob_get_contents(); 437 ob_end_clean(); 438 439 $error = false; 440 foreach ($manifest->filelist as $extension) 441 { 442 $tmpInstaller = new JInstaller; 443 $id = $this->_getExtensionID($extension->type, $extension->id, $extension->client, $extension->group); 444 $client = JApplicationHelper::getClientInfo($extension->client, true); 445 if ($id) 446 { 447 if (!$tmpInstaller->uninstall($extension->type, $id, $client->id)) 448 { 449 $error = true; 450 JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_NOT_PROPER', basename($extension->filename))); 451 } 452 } 453 else 454 { 455 JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_UNKNOWN_EXTENSION')); 456 } 457 } 458 459 // Remove any language files 460 $this->parent->removeFiles($xml->languages); 461 462 // clean up manifest file after we're done if there were no errors 463 if (!$error) 464 { 465 JFile::delete($manifestFile); 466 $folder = $this->parent->getPath('extension_root'); 467 if (JFolder::exists($folder)) 468 { 469 JFolder::delete($folder); 470 } 471 $row->delete(); 472 } 473 else 474 { 475 JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_MANIFEST_NOT_REMOVED')); 476 } 477 478 // Return the result up the line 479 return $retval; 480 } 481 482 /** 483 * Gets the extension id. 484 * 485 * @param string $type The extension type. 486 * @param string $id The name of the extension (the element field). 487 * @param integer $client The application id (0: Joomla CMS site; 1: Joomla CMS administrator). 488 * @param string $group The extension group (mainly for plugins). 489 * 490 * @return integer 491 * 492 * @since 11.1 493 */ 494 protected function _getExtensionID($type, $id, $client, $group) 495 { 496 $db = $this->parent->getDbo(); 497 $result = $id; 498 499 $query = $db->getQuery(true); 500 $query->select('extension_id'); 501 $query->from('#__extensions'); 502 $query->where('type = ' . $db->Quote($type)); 503 $query->where('element = ' . $db->Quote($id)); 504 505 switch ($type) 506 { 507 case 'plugin': 508 // Plugins have a folder but not a client 509 $query->where('folder = ' . $db->Quote($group)); 510 break; 511 512 case 'library': 513 case 'package': 514 case 'component': 515 // Components, packages and libraries don't have a folder or client. 516 // Included for completeness. 517 break; 518 519 case 'language': 520 case 'module': 521 case 'template': 522 // Languages, modules and templates have a client but not a folder 523 $client = JApplicationHelper::getClientInfo($client, true); 524 $query->where('client_id = ' . (int) $client->id); 525 break; 526 } 527 528 $db->setQuery($query); 529 $result = $db->loadResult(); 530 531 // Note: For templates, libraries and packages their unique name is their key. 532 // This means they come out the same way they came in. 533 return $result; 534 } 535 536 /** 537 * Refreshes the extension table cache 538 * 539 * @return boolean Result of operation, true if updated, false on failure 540 * 541 * @since 11.1 542 */ 543 public function refreshManifestCache() 544 { 545 // Need to find to find where the XML file is since we don't store this normally 546 $manifestPath = JPATH_MANIFESTS . '/packages/' . $this->parent->extension->element . '.xml'; 547 $this->parent->manifest = $this->parent->isManifest($manifestPath); 548 $this->parent->setPath('manifest', $manifestPath); 549 550 $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest')); 551 $this->parent->extension->manifest_cache = json_encode($manifest_details); 552 $this->parent->extension->name = $manifest_details['name']; 553 554 try 555 { 556 return $this->parent->extension->store(); 557 } 558 catch (JException $e) 559 { 560 JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_PACK_REFRESH_MANIFEST_CACHE')); 561 return false; 562 } 563 } 564 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Tue Apr 3 11:40:28 2012 | Cross-referenced by PHPXref 0.7.1 |