PageRenderTime 46ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/libraries/joomla/installer/adapters/plugin.php

http://github.com/joomla/joomla-platform
PHP | 874 lines | 544 code | 97 blank | 233 comment | 86 complexity | 347c3907eaeb246de7301e8064b0ebc4 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.base.adapterinstance');
  11. /**
  12. * Plugin installer
  13. *
  14. * @package Joomla.Platform
  15. * @subpackage Installer
  16. * @since 11.1
  17. */
  18. class JInstallerPlugin extends JAdapterInstance
  19. {
  20. /**
  21. * Install function routing
  22. *
  23. * @var string
  24. * @since 11.1
  25. * */
  26. protected $route = 'install';
  27. /**
  28. * The installation manifest XML object
  29. *
  30. * @var
  31. * @since 11.1
  32. * */
  33. protected $manifest = null;
  34. /**
  35. *
  36. *
  37. * @var
  38. * @since 11.1
  39. * */
  40. protected $manifest_script = null;
  41. /**
  42. *
  43. *
  44. * @var
  45. * @since 11.1
  46. * */
  47. protected $name = null;
  48. /**
  49. *
  50. *
  51. * @var
  52. * @since 11.1
  53. * */
  54. protected $scriptElement = null;
  55. /**
  56. * @var
  57. * @since 11.1
  58. */
  59. protected $oldFiles = null;
  60. /**
  61. * Custom loadLanguage method
  62. *
  63. * @param string $path The path where to find language files.
  64. *
  65. * @return void
  66. *
  67. * @since 11.1
  68. */
  69. public function loadLanguage($path = null)
  70. {
  71. $source = $this->parent->getPath('source');
  72. if (!$source)
  73. {
  74. $this->parent->setPath('source', JPATH_PLUGINS . '/' . $this->parent->extension->folder . '/' . $this->parent->extension->element);
  75. }
  76. $this->manifest = $this->parent->getManifest();
  77. $element = $this->manifest->files;
  78. if ($element)
  79. {
  80. $group = strtolower((string) $this->manifest->attributes()->group);
  81. $name = '';
  82. if (count($element->children()))
  83. {
  84. foreach ($element->children() as $file)
  85. {
  86. if ((string) $file->attributes()->plugin)
  87. {
  88. $name = strtolower((string) $file->attributes()->plugin);
  89. break;
  90. }
  91. }
  92. }
  93. if ($name)
  94. {
  95. $extension = "plg_${group}_${name}";
  96. $lang = JFactory::getLanguage();
  97. $source = $path ? $path : JPATH_PLUGINS . "/$group/$name";
  98. $folder = (string) $element->attributes()->folder;
  99. if ($folder && file_exists("$path/$folder"))
  100. {
  101. $source = "$path/$folder";
  102. }
  103. $lang->load($extension . '.sys', $source, null, false, false)
  104. || $lang->load($extension . '.sys', JPATH_ADMINISTRATOR, null, false, false)
  105. || $lang->load($extension . '.sys', $source, $lang->getDefault(), false, false)
  106. || $lang->load($extension . '.sys', JPATH_ADMINISTRATOR, $lang->getDefault(), false, false);
  107. }
  108. }
  109. }
  110. /**
  111. * Custom install method
  112. *
  113. * @return boolean True on success
  114. *
  115. * @since 11.1
  116. */
  117. public function install()
  118. {
  119. // Get a database connector object
  120. $db = $this->parent->getDbo();
  121. // Get the extension manifest object
  122. $this->manifest = $this->parent->getManifest();
  123. $xml = $this->manifest;
  124. // Manifest Document Setup Section
  125. // Set the extension name
  126. $name = (string) $xml->name;
  127. $name = JFilterInput::getInstance()->clean($name, 'string');
  128. $this->set('name', $name);
  129. // Get the plugin description
  130. $description = (string) $xml->description;
  131. if ($description)
  132. {
  133. $this->parent->set('message', JText::_($description));
  134. }
  135. else
  136. {
  137. $this->parent->set('message', '');
  138. }
  139. /*
  140. * Backward Compatibility
  141. * @todo Deprecate in future version
  142. */
  143. $type = (string) $xml->attributes()->type;
  144. // Set the installation path
  145. if (count($xml->files->children()))
  146. {
  147. foreach ($xml->files->children() as $file)
  148. {
  149. if ((string) $file->attributes()->$type)
  150. {
  151. $element = (string) $file->attributes()->$type;
  152. break;
  153. }
  154. }
  155. }
  156. $group = (string) $xml->attributes()->group;
  157. if (!empty($element) && !empty($group))
  158. {
  159. $this->parent->setPath('extension_root', JPATH_PLUGINS . '/' . $group . '/' . $element);
  160. }
  161. else
  162. {
  163. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_NO_FILE', JText::_('JLIB_INSTALLER_' . $this->route)));
  164. return false;
  165. }
  166. // Check if we should enable overwrite settings
  167. // Check to see if a plugin by the same name is already installed.
  168. $query = $db->getQuery(true);
  169. $query->select($query->qn('extension_id'))->from($query->qn('#__extensions'));
  170. $query->where($query->qn('folder') . ' = ' . $query->q($group));
  171. $query->where($query->qn('element') . ' = ' . $query->q($element));
  172. $db->setQuery($query);
  173. try
  174. {
  175. $db->Query();
  176. }
  177. catch (JException $e)
  178. {
  179. // Install failed, roll back changes
  180. $this->parent
  181. ->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_ROLLBACK', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true)));
  182. return false;
  183. }
  184. $id = $db->loadResult();
  185. // If it's on the fs...
  186. if (file_exists($this->parent->getPath('extension_root')) && (!$this->parent->isOverwrite() || $this->parent->isUpgrade()))
  187. {
  188. $updateElement = $xml->update;
  189. /*
  190. * Upgrade manually set or
  191. * Update function available or
  192. * Update tag detected
  193. */
  194. if ($this->parent->isUpgrade() || ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'update'))
  195. || $updateElement)
  196. {
  197. // Force this one
  198. $this->parent->setOverwrite(true);
  199. $this->parent->setUpgrade(true);
  200. if ($id)
  201. {
  202. // If there is a matching extension mark this as an update; semantics really
  203. $this->route = 'update';
  204. }
  205. }
  206. elseif (!$this->parent->isOverwrite())
  207. {
  208. // Overwrite is set
  209. // We didn't have overwrite set, find an update function or find an update tag so lets call it safe
  210. $this->parent
  211. ->abort(
  212. JText::sprintf(
  213. 'JLIB_INSTALLER_ABORT_PLG_INSTALL_DIRECTORY', JText::_('JLIB_INSTALLER_' . $this->route),
  214. $this->parent->getPath('extension_root')
  215. )
  216. );
  217. return false;
  218. }
  219. }
  220. // Installer Trigger Loading
  221. // If there is an manifest class file, let's load it; we'll copy it later (don't have destination yet).
  222. if ((string) $xml->scriptfile)
  223. {
  224. $manifestScript = (string) $xml->scriptfile;
  225. $manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript;
  226. if (is_file($manifestScriptFile))
  227. {
  228. // Load the file
  229. include_once $manifestScriptFile;
  230. }
  231. // If a dash is present in the group name, remove it
  232. $groupClass = str_replace('-', '', $group);
  233. // Set the class name
  234. $classname = 'plg' . $groupClass . $element . 'InstallerScript';
  235. if (class_exists($classname))
  236. {
  237. // Create a new instance
  238. $this->parent->manifestClass = new $classname($this);
  239. // And set this so we can copy it later
  240. $this->set('manifest_script', $manifestScript);
  241. // Note: if we don't find the class, don't bother to copy the file
  242. }
  243. }
  244. // Run preflight if possible (since we know we're not an update)
  245. ob_start();
  246. ob_implicit_flush(false);
  247. if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight'))
  248. {
  249. if ($this->parent->manifestClass->preflight($this->route, $this) === false)
  250. {
  251. // Install failed, rollback changes
  252. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PLG_INSTALL_CUSTOM_INSTALL_FAILURE'));
  253. return false;
  254. }
  255. }
  256. // Create msg object; first use here
  257. $msg = ob_get_contents();
  258. ob_end_clean();
  259. // Filesystem Processing Section
  260. // If the plugin directory does not exist, lets create it
  261. $created = false;
  262. if (!file_exists($this->parent->getPath('extension_root')))
  263. {
  264. if (!$created = JFolder::create($this->parent->getPath('extension_root')))
  265. {
  266. $this->parent
  267. ->abort(
  268. JText::sprintf(
  269. 'JLIB_INSTALLER_ABORT_PLG_INSTALL_CREATE_DIRECTORY', JText::_('JLIB_INSTALLER_' . $this->route),
  270. $this->parent->getPath('extension_root')
  271. )
  272. );
  273. return false;
  274. }
  275. }
  276. // If we're updating at this point when there is always going to be an extension_root find the old XML files
  277. if ($this->route == 'update')
  278. {
  279. // Hunt for the original XML file
  280. $old_manifest = null;
  281. // Create a new installer because findManifest sets stuff; side effects!
  282. $tmpInstaller = new JInstaller;
  283. // Look in the extension root
  284. $tmpInstaller->setPath('source', $this->parent->getPath('extension_root'));
  285. if ($tmpInstaller->findManifest())
  286. {
  287. $old_manifest = $tmpInstaller->getManifest();
  288. $this->oldFiles = $old_manifest->files;
  289. }
  290. }
  291. /*
  292. * If we created the plugin directory and will want to remove it if we
  293. * have to roll back the installation, let's add it to the installation
  294. * step stack
  295. */
  296. if ($created)
  297. {
  298. $this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_root')));
  299. }
  300. // Copy all necessary files
  301. if ($this->parent->parseFiles($xml->files, -1, $this->oldFiles) === false)
  302. {
  303. // Install failed, roll back changes
  304. $this->parent->abort();
  305. return false;
  306. }
  307. // Parse optional tags -- media and language files for plugins go in admin app
  308. $this->parent->parseMedia($xml->media, 1);
  309. $this->parent->parseLanguages($xml->languages, 1);
  310. // If there is a manifest script, lets copy it.
  311. if ($this->get('manifest_script'))
  312. {
  313. $path['src'] = $this->parent->getPath('source') . '/' . $this->get('manifest_script');
  314. $path['dest'] = $this->parent->getPath('extension_root') . '/' . $this->get('manifest_script');
  315. if (!file_exists($path['dest']))
  316. {
  317. if (!$this->parent->copyFiles(array($path)))
  318. {
  319. // Install failed, rollback changes
  320. $this->parent
  321. ->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_MANIFEST', JText::_('JLIB_INSTALLER_' . $this->route)));
  322. return false;
  323. }
  324. }
  325. }
  326. // Database Processing Section
  327. $row = JTable::getInstance('extension');
  328. // Was there a plugin with the same name already installed?
  329. if ($id)
  330. {
  331. if (!$this->parent->isOverwrite())
  332. {
  333. // Install failed, roll back changes
  334. $this->parent
  335. ->abort(
  336. JText::sprintf(
  337. 'JLIB_INSTALLER_ABORT_PLG_INSTALL_ALLREADY_EXISTS', JText::_('JLIB_INSTALLER_' . $this->route),
  338. $this->get('name')
  339. )
  340. );
  341. return false;
  342. }
  343. $row->load($id);
  344. $row->name = $this->get('name');
  345. $row->manifest_cache = $this->parent->generateManifestCache();
  346. // Update the manifest cache and name
  347. $row->store();
  348. }
  349. else
  350. {
  351. // Store in the extensions table (1.6)
  352. $row->name = $this->get('name');
  353. $row->type = 'plugin';
  354. $row->ordering = 0;
  355. $row->element = $element;
  356. $row->folder = $group;
  357. $row->enabled = 0;
  358. $row->protected = 0;
  359. $row->access = 1;
  360. $row->client_id = 0;
  361. $row->params = $this->parent->getParams();
  362. // Custom data
  363. $row->custom_data = '';
  364. // System data
  365. $row->system_data = '';
  366. $row->manifest_cache = $this->parent->generateManifestCache();
  367. // Editor plugins are published by default
  368. if ($group == 'editors')
  369. {
  370. $row->enabled = 1;
  371. }
  372. if (!$row->store())
  373. {
  374. // Install failed, roll back changes
  375. $this->parent
  376. ->abort(
  377. JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_ROLLBACK', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true))
  378. );
  379. return false;
  380. }
  381. // Since we have created a plugin item, we add it to the installation step stack
  382. // so that if we have to rollback the changes we can undo it.
  383. $this->parent->pushStep(array('type' => 'extension', 'id' => $row->extension_id));
  384. $id = $row->extension_id;
  385. }
  386. /*
  387. * Let's run the queries for the module
  388. * If Joomla 1.5 compatible, with discreet sql files - execute appropriate
  389. * file for utf-8 support or non-utf-8 support
  390. */
  391. // Try for Joomla 1.5 type queries
  392. // Second argument is the utf compatible version attribute
  393. if (strtolower($this->route) == 'install')
  394. {
  395. $utfresult = $this->parent->parseSQLFiles($this->manifest->install->sql);
  396. if ($utfresult === false)
  397. {
  398. // Install failed, rollback changes
  399. $this->parent
  400. ->abort(
  401. JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_SQL_ERROR', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true))
  402. );
  403. return false;
  404. }
  405. // Set the schema version to be the latest update version
  406. if ($this->manifest->update)
  407. {
  408. $this->parent->setSchemaVersion($this->manifest->update->schemas, $row->extension_id);
  409. }
  410. }
  411. elseif (strtolower($this->route) == 'update')
  412. {
  413. if ($this->manifest->update)
  414. {
  415. $result = $this->parent->parseSchemaUpdates($this->manifest->update->schemas, $row->extension_id);
  416. if ($result === false)
  417. {
  418. // Install failed, rollback changes
  419. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_UPDATE_SQL_ERROR', $db->stderr(true)));
  420. return false;
  421. }
  422. }
  423. }
  424. // Start Joomla! 1.6
  425. ob_start();
  426. ob_implicit_flush(false);
  427. if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, $this->route))
  428. {
  429. if ($this->parent->manifestClass->{$this->route}($this) === false)
  430. {
  431. // Install failed, rollback changes
  432. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PLG_INSTALL_CUSTOM_INSTALL_FAILURE'));
  433. return false;
  434. }
  435. }
  436. // Append messages
  437. $msg .= ob_get_contents();
  438. ob_end_clean();
  439. // Finalization and Cleanup Section
  440. // Lastly, we will copy the manifest file to its appropriate place.
  441. if (!$this->parent->copyManifest(-1))
  442. {
  443. // Install failed, rollback changes
  444. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_COPY_SETUP', JText::_('JLIB_INSTALLER_' . $this->route)));
  445. return false;
  446. }
  447. // And now we run the postflight
  448. ob_start();
  449. ob_implicit_flush(false);
  450. if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'postflight'))
  451. {
  452. $this->parent->manifestClass->postflight($this->route, $this);
  453. }
  454. // Append messages
  455. $msg .= ob_get_contents();
  456. ob_end_clean();
  457. if ($msg != '')
  458. {
  459. $this->parent->set('extension_message', $msg);
  460. }
  461. return $id;
  462. }
  463. /**
  464. * Custom update method
  465. *
  466. * @return boolean True on success
  467. *
  468. * @since 11.1
  469. */
  470. public function update()
  471. {
  472. // Set the overwrite setting
  473. $this->parent->setOverwrite(true);
  474. $this->parent->setUpgrade(true);
  475. // Set the route for the install
  476. $this->route = 'update';
  477. // Go to install which handles updates properly
  478. return $this->install();
  479. }
  480. /**
  481. * Custom uninstall method
  482. *
  483. * @param integer $id The id of the plugin to uninstall
  484. *
  485. * @return boolean True on success
  486. *
  487. * @since 11.1
  488. */
  489. public function uninstall($id)
  490. {
  491. $this->route = 'uninstall';
  492. // Initialise variables.
  493. $row = null;
  494. $retval = true;
  495. $db = $this->parent->getDbo();
  496. // First order of business will be to load the plugin object table from the database.
  497. // This should give us the necessary information to proceed.
  498. $row = JTable::getInstance('extension');
  499. if (!$row->load((int) $id))
  500. {
  501. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PLG_UNINSTALL_ERRORUNKOWNEXTENSION'));
  502. return false;
  503. }
  504. // Is the plugin we are trying to uninstall a core one?
  505. // Because that is not a good idea...
  506. if ($row->protected)
  507. {
  508. JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_PLG_UNINSTALL_WARNCOREPLUGIN', $row->name));
  509. return false;
  510. }
  511. // Get the plugin folder so we can properly build the plugin path
  512. if (trim($row->folder) == '')
  513. {
  514. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PLG_UNINSTALL_FOLDER_FIELD_EMPTY'));
  515. return false;
  516. }
  517. // Set the plugin root path
  518. $this->parent->setPath('extension_root', JPATH_PLUGINS . '/' . $row->folder . '/' . $row->element);
  519. $this->parent->findManifest();
  520. $manifestFile = $this->parent->getManifest();
  521. if (!file_exists($manifestFile))
  522. {
  523. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PLG_UNINSTALL_INVALID_NOTFOUND_MANIFEST'));
  524. return false;
  525. }
  526. $xml = JFactory::getXML($manifestFile);
  527. $this->manifest = $xml;
  528. // If we cannot load the XML file return null
  529. if (!$xml)
  530. {
  531. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PLG_UNINSTALL_LOAD_MANIFEST'));
  532. return false;
  533. }
  534. /*
  535. * Check for a valid XML root tag.
  536. */
  537. if ($xml->getName() != 'extension')
  538. {
  539. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PLG_UNINSTALL_INVALID_MANIFEST'));
  540. return false;
  541. }
  542. // Attempt to load the language file; might have uninstall strings
  543. $this->parent->setPath('source', JPATH_PLUGINS . '/' . $row->folder . '/' . $row->element);
  544. $this->loadLanguage(JPATH_PLUGINS . '/' . $row->folder . '/' . $row->element);
  545. // Installer Trigger Loading
  546. // If there is an manifest class file, let's load it; we'll copy it later (don't have dest yet)
  547. $manifestScript = (string) $xml->scriptfile;
  548. if ($manifestScript)
  549. {
  550. $manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript;
  551. if (is_file($manifestScriptFile))
  552. {
  553. // Load the file
  554. include_once $manifestScriptFile;
  555. }
  556. // If a dash is present in the folder, remove it
  557. $folderClass = str_replace('-', '', $row->folder);
  558. // Set the class name
  559. $classname = 'plg' . $folderClass . $row->element . 'InstallerScript';
  560. if (class_exists($classname))
  561. {
  562. // Create a new instance
  563. $this->parent->manifestClass = new $classname($this);
  564. // And set this so we can copy it later
  565. $this->set('manifest_script', $manifestScript);
  566. // Note: if we don't find the class, don't bother to copy the file
  567. }
  568. }
  569. // Run preflight if possible (since we know we're not an update)
  570. ob_start();
  571. ob_implicit_flush(false);
  572. if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight'))
  573. {
  574. if ($this->parent->manifestClass->preflight($this->route, $this) === false)
  575. {
  576. // Install failed, rollback changes
  577. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PLG_INSTALL_CUSTOM_INSTALL_FAILURE'));
  578. return false;
  579. }
  580. }
  581. // Create msg object; first use here
  582. $msg = ob_get_contents();
  583. ob_end_clean();
  584. /*
  585. * Let's run the queries for the module
  586. * If Joomla 1.5 compatible, with discreet sql files - execute appropriate
  587. * file for utf-8 support or non-utf-8 support
  588. */
  589. // Try for Joomla 1.5 type queries
  590. // Second argument is the utf compatible version attribute
  591. $utfresult = $this->parent->parseSQLFiles($xml->{strtolower($this->route)}->sql);
  592. if ($utfresult === false)
  593. {
  594. // Install failed, rollback changes
  595. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_UNINSTALL_SQL_ERROR', $db->stderr(true)));
  596. return false;
  597. }
  598. // Start Joomla! 1.6
  599. ob_start();
  600. ob_implicit_flush(false);
  601. if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'uninstall'))
  602. {
  603. $this->parent->manifestClass->uninstall($this);
  604. }
  605. // Append messages
  606. $msg = ob_get_contents();
  607. ob_end_clean();
  608. // Remove the plugin files
  609. $this->parent->removeFiles($xml->images, -1);
  610. $this->parent->removeFiles($xml->files, -1);
  611. JFile::delete($manifestFile);
  612. // Remove all media and languages as well
  613. $this->parent->removeFiles($xml->media);
  614. $this->parent->removeFiles($xml->languages, 1);
  615. // Remove the schema version
  616. $query = $db->getQuery(true);
  617. $query->delete()->from('#__schemas')->where('extension_id = ' . $row->extension_id);
  618. $db->setQuery($query);
  619. $db->Query();
  620. // Now we will no longer need the plugin object, so let's delete it
  621. $row->delete($row->extension_id);
  622. unset($row);
  623. // If the folder is empty, let's delete it
  624. $files = JFolder::files($this->parent->getPath('extension_root'));
  625. JFolder::delete($this->parent->getPath('extension_root'));
  626. if ($msg)
  627. {
  628. $this->parent->set('extension_message', $msg);
  629. }
  630. return $retval;
  631. }
  632. /**
  633. * Custom discover method
  634. *
  635. * @return array JExtension) list of extensions available
  636. *
  637. * @since 11.1
  638. */
  639. public function discover()
  640. {
  641. $results = array();
  642. $folder_list = JFolder::folders(JPATH_SITE . '/plugins');
  643. foreach ($folder_list as $folder)
  644. {
  645. $file_list = JFolder::files(JPATH_SITE . '/plugins/' . $folder, '\.xml$');
  646. foreach ($file_list as $file)
  647. {
  648. $manifest_details = JApplicationHelper::parseXMLInstallFile(JPATH_SITE . '/plugins/' . $folder . '/' . $file);
  649. $file = JFile::stripExt($file);
  650. // Ignore example plugins
  651. if ($file == 'example')
  652. {
  653. continue;
  654. }
  655. $extension = JTable::getInstance('extension');
  656. $extension->set('type', 'plugin');
  657. $extension->set('client_id', 0);
  658. $extension->set('element', $file);
  659. $extension->set('folder', $folder);
  660. $extension->set('name', $file);
  661. $extension->set('state', -1);
  662. $extension->set('manifest_cache', json_encode($manifest_details));
  663. $results[] = $extension;
  664. }
  665. $folder_list = JFolder::folders(JPATH_SITE . '/plugins/' . $folder);
  666. foreach ($folder_list as $plugin_folder)
  667. {
  668. $file_list = JFolder::files(JPATH_SITE . '/plugins/' . $folder . '/' . $plugin_folder, '\.xml$');
  669. foreach ($file_list as $file)
  670. {
  671. $manifest_details = JApplicationHelper::parseXMLInstallFile(
  672. JPATH_SITE . '/plugins/' . $folder . '/' . $plugin_folder . '/' . $file
  673. );
  674. $file = JFile::stripExt($file);
  675. if ($file == 'example')
  676. {
  677. continue;
  678. }
  679. // Ignore example plugins
  680. $extension = JTable::getInstance('extension');
  681. $extension->set('type', 'plugin');
  682. $extension->set('client_id', 0);
  683. $extension->set('element', $file);
  684. $extension->set('folder', $folder);
  685. $extension->set('name', $file);
  686. $extension->set('state', -1);
  687. $extension->set('manifest_cache', json_encode($manifest_details));
  688. $results[] = $extension;
  689. }
  690. }
  691. }
  692. return $results;
  693. }
  694. /**
  695. * Custom discover_install method.
  696. *
  697. * @return mixed
  698. *
  699. * @since 11.1
  700. */
  701. public function discover_install()
  702. {
  703. /*
  704. * Plugins use the extensions table as their primary store
  705. * Similar to modules and templates, rather easy
  706. * If it's not in the extensions table we just add it
  707. */
  708. $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id);
  709. if (is_dir($client->path . '/plugins/' . $this->parent->extension->folder . '/' . $this->parent->extension->element))
  710. {
  711. $manifestPath = $client->path . '/plugins/' . $this->parent->extension->folder . '/' . $this->parent->extension->element . '/'
  712. . $this->parent->extension->element . '.xml';
  713. }
  714. else
  715. {
  716. $manifestPath = $client->path . '/plugins/' . $this->parent->extension->folder . '/' . $this->parent->extension->element . '.xml';
  717. }
  718. $this->parent->manifest = $this->parent->isManifest($manifestPath);
  719. $description = (string) $this->parent->manifest->description;
  720. if ($description)
  721. {
  722. $this->parent->set('message', JText::_($description));
  723. }
  724. else
  725. {
  726. $this->parent->set('message', '');
  727. }
  728. $this->parent->setPath('manifest', $manifestPath);
  729. $manifest_details = JApplicationHelper::parseXMLInstallFile($manifestPath);
  730. $this->parent->extension->manifest_cache = json_encode($manifest_details);
  731. $this->parent->extension->state = 0;
  732. $this->parent->extension->name = $manifest_details['name'];
  733. $this->parent->extension->enabled = ('editors' == $this->parent->extension->folder) ? 1 : 0;
  734. $this->parent->extension->params = $this->parent->getParams();
  735. if ($this->parent->extension->store())
  736. {
  737. return $this->parent->extension->get('extension_id');
  738. }
  739. else
  740. {
  741. JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_PLG_DISCOVER_STORE_DETAILS'));
  742. return false;
  743. }
  744. }
  745. /**
  746. * Refreshes the extension table cache.
  747. *
  748. * @return boolean Result of operation, true if updated, false on failure.
  749. *
  750. * @since 11.1
  751. */
  752. public function refreshManifestCache()
  753. {
  754. /*
  755. * Plugins use the extensions table as their primary store
  756. * Similar to modules and templates, rather easy
  757. * If it's not in the extensions table we just add it
  758. */
  759. $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id);
  760. $manifestPath = $client->path . '/plugins/' . $this->parent->extension->folder . '/' . $this->parent->extension->element . '/'
  761. . $this->parent->extension->element . '.xml';
  762. $this->parent->manifest = $this->parent->isManifest($manifestPath);
  763. $this->parent->setPath('manifest', $manifestPath);
  764. $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest'));
  765. $this->parent->extension->manifest_cache = json_encode($manifest_details);
  766. $this->parent->extension->name = $manifest_details['name'];
  767. if ($this->parent->extension->store())
  768. {
  769. return true;
  770. }
  771. else
  772. {
  773. JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_PLG_REFRESH_MANIFEST_CACHE'));
  774. return false;
  775. }
  776. }
  777. }