PageRenderTime 26ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/joomla/installer/adapters/library.php

http://github.com/joomla/joomla-platform
PHP | 426 lines | 258 code | 46 blank | 122 comment | 27 complexity | 3fd04c070e49572d1c9fe2ee9babcb1d MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  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. defined('JPATH_PLATFORM') or die;
  10. jimport('joomla.installer.librarymanifest');
  11. jimport('joomla.base.adapterinstance');
  12. /**
  13. * Library installer
  14. *
  15. * @package Joomla.Platform
  16. * @subpackage Installer
  17. * @since 11.1
  18. */
  19. class JInstallerLibrary extends JAdapterInstance
  20. {
  21. /**
  22. * Custom loadLanguage method
  23. *
  24. * @param string $path The path where to find language files.
  25. *
  26. * @return void
  27. *
  28. * @since 11.1
  29. */
  30. public function loadLanguage($path = null)
  31. {
  32. $source = $this->parent->getPath('source');
  33. if (!$source)
  34. {
  35. $this->parent->setPath('source', JPATH_PLATFORM . '/' . $this->parent->extension->element);
  36. }
  37. $this->manifest = $this->parent->getManifest();
  38. $extension = 'lib_' . strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd'));
  39. $name = strtolower((string) $this->manifest->libraryname);
  40. $lang = JFactory::getLanguage();
  41. $source = $path ? $path : JPATH_PLATFORM . "/$name";
  42. $lang->load($extension . '.sys', $source, null, false, false)
  43. || $lang->load($extension . '.sys', JPATH_SITE, null, false, false)
  44. || $lang->load($extension . '.sys', $source, $lang->getDefault(), false, false)
  45. || $lang->load($extension . '.sys', JPATH_SITE, $lang->getDefault(), false, false);
  46. }
  47. /**
  48. * Custom install method
  49. *
  50. * @return boolean True on success
  51. *
  52. * @since 11.1
  53. */
  54. public function install()
  55. {
  56. // Get the extension manifest object
  57. $this->manifest = $this->parent->getManifest();
  58. // Manifest Document Setup Section
  59. // Set the extensions name
  60. $name = JFilterInput::getInstance()->clean((string) $this->manifest->name, 'string');
  61. $element = str_replace('.xml', '', basename($this->parent->getPath('manifest')));
  62. $this->set('name', $name);
  63. $this->set('element', $element);
  64. $db = $this->parent->getDbo();
  65. $query = $db->getQuery(true);
  66. $query->select($db->quoteName('extension_id'));
  67. $query->from($db->quoteName('#__extensions'));
  68. $query->where($db->quoteName('type') . ' = ' . $db->quote('library'));
  69. $query->where($db->quoteName('element') . ' = ' . $db->quote($element));
  70. $db->setQuery($query);
  71. $result = $db->loadResult();
  72. if ($result)
  73. {
  74. // Already installed, can we upgrade?
  75. if ($this->parent->isOverwrite() || $this->parent->isUpgrade())
  76. {
  77. // We can upgrade, so uninstall the old one
  78. $installer = new JInstaller; // we don't want to compromise this instance!
  79. $installer->uninstall('library', $result);
  80. }
  81. else
  82. {
  83. // Abort the install, no upgrade possible
  84. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_LIB_INSTALL_ALREADY_INSTALLED'));
  85. return false;
  86. }
  87. }
  88. // Get the libraries description
  89. $description = (string) $this->manifest->description;
  90. if ($description)
  91. {
  92. $this->parent->set('message', JText::_($description));
  93. }
  94. else
  95. {
  96. $this->parent->set('message', '');
  97. }
  98. // Set the installation path
  99. $group = (string) $this->manifest->libraryname;
  100. if (!$group)
  101. {
  102. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_LIB_INSTALL_NOFILE'));
  103. return false;
  104. }
  105. else
  106. {
  107. $this->parent->setPath('extension_root', JPATH_PLATFORM . '/' . implode(DIRECTORY_SEPARATOR, explode('/', $group)));
  108. }
  109. // Filesystem Processing Section
  110. // If the plugin directory does not exist, let's create it
  111. $created = false;
  112. if (!file_exists($this->parent->getPath('extension_root')))
  113. {
  114. if (!$created = JFolder::create($this->parent->getPath('extension_root')))
  115. {
  116. $this->parent->abort(
  117. JText::sprintf('JLIB_INSTALLER_ABORT_LIB_INSTALL_FAILED_TO_CREATE_DIRECTORY', $this->parent->getPath('extension_root'))
  118. );
  119. return false;
  120. }
  121. }
  122. /*
  123. * If we created the plugin directory and will want to remove it if we
  124. * have to roll back the installation, let's add it to the installation
  125. * step stack
  126. */
  127. if ($created)
  128. {
  129. $this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_root')));
  130. }
  131. // Copy all necessary files
  132. if ($this->parent->parseFiles($this->manifest->files, -1) === false)
  133. {
  134. // Install failed, roll back changes
  135. $this->parent->abort();
  136. return false;
  137. }
  138. // Parse optional tags
  139. $this->parent->parseLanguages($this->manifest->languages);
  140. $this->parent->parseMedia($this->manifest->media);
  141. // Extension Registration
  142. $row = JTable::getInstance('extension');
  143. $row->name = $this->get('name');
  144. $row->type = 'library';
  145. $row->element = $this->get('element');
  146. // There is no folder for modules
  147. $row->folder = '';
  148. $row->enabled = 1;
  149. $row->protected = 0;
  150. $row->access = 1;
  151. $row->client_id = 0;
  152. $row->params = $this->parent->getParams();
  153. // Custom data
  154. $row->custom_data = '';
  155. $row->manifest_cache = $this->parent->generateManifestCache();
  156. if (!$row->store())
  157. {
  158. // Install failed, roll back changes
  159. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_LIB_INSTALL_ROLLBACK', $db->stderr(true)));
  160. return false;
  161. }
  162. // Finalization and Cleanup Section
  163. // Lastly, we will copy the manifest file to its appropriate place.
  164. $manifest = array();
  165. $manifest['src'] = $this->parent->getPath('manifest');
  166. $manifest['dest'] = JPATH_MANIFESTS . '/libraries/' . basename($this->parent->getPath('manifest'));
  167. if (!$this->parent->copyFiles(array($manifest), true))
  168. {
  169. // Install failed, rollback changes
  170. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_LIB_INSTALL_COPY_SETUP'));
  171. return false;
  172. }
  173. return $row->get('extension_id');
  174. }
  175. /**
  176. * Custom update method
  177. *
  178. * @return boolean True on success
  179. *
  180. * @since 11.1
  181. */
  182. public function update()
  183. {
  184. // Since this is just files, an update removes old files
  185. // Get the extension manifest object
  186. $this->manifest = $this->parent->getManifest();
  187. // Manifest Document Setup Section
  188. // Set the extensions name
  189. $name = (string) $this->manifest->name;
  190. $name = JFilterInput::getInstance()->clean($name, 'string');
  191. $element = str_replace('.xml', '', basename($this->parent->getPath('manifest')));
  192. $this->set('name', $name);
  193. $this->set('element', $element);
  194. // We don't want to compromise this instance!
  195. $installer = new JInstaller;
  196. $db = $this->parent->getDbo();
  197. $query = $db->getQuery(true);
  198. $query->select($db->quoteName('extension_id'));
  199. $query->from($db->quoteName('#__extensions'));
  200. $query->where($db->quoteName('type') . ' = ' . $db->quote('library'));
  201. $query->where($db->quoteName('element') . ' = ' . $db->quote($element));
  202. $db->setQuery($query);
  203. $result = $db->loadResult();
  204. if ($result)
  205. {
  206. // Already installed, which would make sense
  207. $installer->uninstall('library', $result);
  208. }
  209. // Now create the new files
  210. return $this->install();
  211. }
  212. /**
  213. * Custom uninstall method
  214. *
  215. * @param string $id The id of the library to uninstall.
  216. *
  217. * @return boolean True on success
  218. *
  219. * @since 11.1
  220. */
  221. public function uninstall($id)
  222. {
  223. // Initialise variables.
  224. $retval = true;
  225. // First order of business will be to load the module object table from the database.
  226. // This should give us the necessary information to proceed.
  227. $row = JTable::getInstance('extension');
  228. if (!$row->load((int) $id) || !strlen($row->element))
  229. {
  230. JError::raiseWarning(100, JText::_('ERRORUNKOWNEXTENSION'));
  231. return false;
  232. }
  233. // Is the library we are trying to uninstall a core one?
  234. // Because that is not a good idea...
  235. if ($row->protected)
  236. {
  237. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_LIB_UNINSTALL_WARNCORELIBRARY'));
  238. return false;
  239. }
  240. $manifestFile = JPATH_MANIFESTS . '/libraries/' . $row->element . '.xml';
  241. // Because libraries may not have their own folders we cannot use the standard method of finding an installation manifest
  242. if (file_exists($manifestFile))
  243. {
  244. $manifest = new JLibraryManifest($manifestFile);
  245. // Set the plugin root path
  246. $this->parent->setPath('extension_root', JPATH_PLATFORM . '/' . $manifest->libraryname);
  247. $xml = JFactory::getXML($manifestFile);
  248. // If we cannot load the XML file return null
  249. if (!$xml)
  250. {
  251. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_LIB_UNINSTALL_LOAD_MANIFEST'));
  252. return false;
  253. }
  254. // Check for a valid XML root tag.
  255. if ($xml->getName() != 'extension')
  256. {
  257. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_LIB_UNINSTALL_INVALID_MANIFEST'));
  258. return false;
  259. }
  260. $this->parent->removeFiles($xml->files, -1);
  261. JFile::delete($manifestFile);
  262. }
  263. else
  264. {
  265. // Remove this row entry since its invalid
  266. $row->delete($row->extension_id);
  267. unset($row);
  268. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_LIB_UNINSTALL_INVALID_NOTFOUND_MANIFEST'));
  269. return false;
  270. }
  271. // TODO: Change this so it walked up the path backwards so we clobber multiple empties
  272. // If the folder is empty, let's delete it
  273. if (JFolder::exists($this->parent->getPath('extension_root')))
  274. {
  275. if (is_dir($this->parent->getPath('extension_root')))
  276. {
  277. $files = JFolder::files($this->parent->getPath('extension_root'));
  278. if (!count($files))
  279. {
  280. JFolder::delete($this->parent->getPath('extension_root'));
  281. }
  282. }
  283. }
  284. $this->parent->removeFiles($xml->media);
  285. $this->parent->removeFiles($xml->languages);
  286. $row->delete($row->extension_id);
  287. unset($row);
  288. return $retval;
  289. }
  290. /**
  291. * Custom discover method
  292. *
  293. * @return array JExtension list of extensions available
  294. *
  295. * @since 11.1
  296. */
  297. public function discover()
  298. {
  299. $results = array();
  300. $file_list = JFolder::files(JPATH_MANIFESTS . '/libraries', '\.xml$');
  301. foreach ($file_list as $file)
  302. {
  303. $manifest_details = JApplicationHelper::parseXMLInstallFile(JPATH_MANIFESTS . '/libraries/' . $file);
  304. $file = JFile::stripExt($file);
  305. $extension = JTable::getInstance('extension');
  306. $extension->set('type', 'library');
  307. $extension->set('client_id', 0);
  308. $extension->set('element', $file);
  309. $extension->set('name', $file);
  310. $extension->set('state', -1);
  311. $extension->set('manifest_cache', json_encode($manifest_details));
  312. $results[] = $extension;
  313. }
  314. return $results;
  315. }
  316. /**
  317. * Custom discover_install method
  318. *
  319. * @return boolean True on success
  320. *
  321. * @since 11.1
  322. */
  323. public function discover_install()
  324. {
  325. /* Libraries are a strange beast; they are actually references to files
  326. * There are two parts to a library which are disjunct in their locations
  327. * 1) The manifest file (stored in /JPATH_MANIFESTS/libraries)
  328. * 2) The actual files (stored in /JPATH_PLATFORM/libraryname)
  329. * Thus installation of a library is the process of dumping files
  330. * in two different places. As such it is impossible to perform
  331. * any operation beyond mere registration of a library under the presumption
  332. * that the files exist in the appropriate location so that come uninstall
  333. * time they can be adequately removed.
  334. */
  335. $manifestPath = JPATH_MANIFESTS . '/libraries/' . $this->parent->extension->element . '.xml';
  336. $this->parent->manifest = $this->parent->isManifest($manifestPath);
  337. $this->parent->setPath('manifest', $manifestPath);
  338. $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest'));
  339. $this->parent->extension->manifest_cache = json_encode($manifest_details);
  340. $this->parent->extension->state = 0;
  341. $this->parent->extension->name = $manifest_details['name'];
  342. $this->parent->extension->enabled = 1;
  343. $this->parent->extension->params = $this->parent->getParams();
  344. if ($this->parent->extension->store())
  345. {
  346. return true;
  347. }
  348. else
  349. {
  350. JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_LIB_DISCOVER_STORE_DETAILS'));
  351. return false;
  352. }
  353. }
  354. /**
  355. * Refreshes the extension table cache
  356. *
  357. * @return boolean Result of operation, true if updated, false on failure
  358. *
  359. * @since 11.1
  360. */
  361. public function refreshManifestCache()
  362. {
  363. // Need to find to find where the XML file is since we don't store this normally
  364. $manifestPath = JPATH_MANIFESTS . '/libraries/' . $this->parent->extension->element . '.xml';
  365. $this->parent->manifest = $this->parent->isManifest($manifestPath);
  366. $this->parent->setPath('manifest', $manifestPath);
  367. $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest'));
  368. $this->parent->extension->manifest_cache = json_encode($manifest_details);
  369. $this->parent->extension->name = $manifest_details['name'];
  370. try
  371. {
  372. return $this->parent->extension->store();
  373. }
  374. catch (JException $e)
  375. {
  376. JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_LIB_REFRESH_MANIFEST_CACHE'));
  377. return false;
  378. }
  379. }
  380. }