[ Index ]

PHP Cross Reference of Joomla 2.5.4 DE

title

Body

[close]

/libraries/joomla/installer/adapters/ -> package.php (source)

   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  }


Generated: Tue Apr 3 11:40:28 2012 Cross-referenced by PHPXref 0.7.1