PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/libraries/joomla/installer/adapters/component.php

https://bitbucket.org/ankursaxena_2/joomla-platform
PHP | 1729 lines | 958 code | 309 blank | 462 comment | 217 complexity | e12790d6ce9746e5a308277c0caabc48 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * @package Joomla.Platform
  4. * @subpackage Installer
  5. *
  6. * @copyright Copyright (C) 2005 - 2011 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. * Component installer
  13. *
  14. * @package Joomla.Platform
  15. * @subpackage Installer
  16. * @since 11.1
  17. */
  18. class JInstallerComponent extends JAdapterInstance
  19. {
  20. protected $manifest = null;
  21. protected $name = null;
  22. protected $element = null;
  23. protected $oldAdminFiles = null;
  24. protected $oldFiles = null;
  25. protected $manifest_script = null;
  26. protected $install_script = null;
  27. /**
  28. * Custom loadLanguage method
  29. *
  30. * @param string $path the path where to find language files
  31. *
  32. * @return void
  33. * @since 11.1
  34. */
  35. public function loadLanguage($path=null)
  36. {
  37. $source = $this->parent->getPath('source');
  38. if (!$source) {
  39. $this->parent->setPath('source', ($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE).'/components/'.$this->parent->extension->element);
  40. }
  41. $this->manifest = $this->parent->getManifest();
  42. $name = strtolower(JFilterInput::getInstance()->clean((string)$this->manifest->name, 'cmd'));
  43. if (substr($name, 0, 4)=="com_") {
  44. $extension = $name;
  45. }
  46. else {
  47. $extension = "com_$name";
  48. }
  49. $lang = JFactory::getLanguage();
  50. $source = $path ? $path : ($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE).'/components/'.$extension;
  51. if ($this->manifest->administration->files) {
  52. $element = $this->manifest->administration->files;
  53. }
  54. else if ($this->manifest->files) {
  55. $element = $this->manifest->files;
  56. }
  57. else {
  58. $element = null;
  59. }
  60. if ($element) {
  61. $folder = (string)$element->attributes()->folder;
  62. if ($folder && file_exists("$path/$folder")) {
  63. $source = "$path/$folder";
  64. }
  65. }
  66. $lang->load($extension.'.sys', $source, null, false, false)
  67. || $lang->load($extension.'.sys', JPATH_ADMINISTRATOR, null, false, false)
  68. || $lang->load($extension.'.sys', $source, $lang->getDefault(), false, false)
  69. || $lang->load($extension.'.sys', JPATH_ADMINISTRATOR, $lang->getDefault(), false, false);
  70. }
  71. /**
  72. * Custom install method for components
  73. *
  74. * @return boolean True on success
  75. * @since 11.1
  76. */
  77. public function install()
  78. {
  79. // Get a database connector object
  80. $db = $this->parent->getDbo();
  81. // Get the extension manifest object
  82. $this->manifest = $this->parent->getManifest();
  83. // Manifest Document Setup Section
  84. // Set the extensions name
  85. $name = strtolower(JFilterInput::getInstance()->clean((string)$this->manifest->name, 'cmd'));
  86. if (substr($name, 0, 4)=="com_") {
  87. $element = $name;
  88. }
  89. else {
  90. $element = "com_$name";
  91. }
  92. $this->set('name', $name);
  93. $this->set('element', $element);
  94. // Get the component description
  95. $this->parent->set('message', JText::_((string)$this->manifest->description));
  96. // Set the installation target paths
  97. $this->parent->setPath('extension_site', JPath::clean(JPATH_SITE.DS.'components'.DS.$this->get('element')));
  98. $this->parent->setPath('extension_administrator', JPath::clean(JPATH_ADMINISTRATOR.DS.'components'.DS.$this->get('element')));
  99. $this->parent->setPath('extension_root', $this->parent->getPath('extension_administrator')); // copy this as its used as a common base
  100. // Basic Checks Section
  101. // Make sure that we have an admin element
  102. if (!$this->manifest->administration) {
  103. JError::raiseWarning(1, JText::_('JLIB_INSTALLER_ERROR_COMP_INSTALL_ADMIN_ELEMENT'));
  104. return false;
  105. }
  106. // Filesystem Processing Section
  107. // If the component site or admin directory already exists, then we will assume that the component is already
  108. // installed or another component is using that directory.
  109. if (file_exists($this->parent->getPath('extension_site')) || file_exists($this->parent->getPath('extension_administrator'))) {
  110. // Look for an update function or update tag
  111. $updateElement = $this->manifest->update;
  112. // Upgrade manually set
  113. // Update function available
  114. // Update tag detected
  115. if ($this->parent->getUpgrade() || ($this->parent->manifestClass && method_exists($this->parent->manifestClass,'update')) || $updateElement) {
  116. return $this->update(); // transfer control to the update function
  117. }
  118. else if (!$this->parent->getOverwrite()) {
  119. // Overwrite is set
  120. // We didn't have overwrite set, find an update function or find an update tag so lets call it safe
  121. if (file_exists($this->parent->getPath('extension_site'))) {
  122. // If the site exists say so
  123. JError::raiseWarning(1, JText::sprintf('JLIB_INSTALLER_ERROR_COMP_INSTALL_DIR_SITE', $this->parent->getPath('extension_site')));
  124. }
  125. else {
  126. // If the admin exists say so
  127. JError::raiseWarning(1, JText::sprintf('JLIB_INSTALLER_ERROR_COMP_INSTALL_DIR_ADMIN', $this->parent->getPath('extension_administrator')));
  128. }
  129. return false;
  130. }
  131. }
  132. // Installer Trigger Loading
  133. // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet)
  134. $manifestScript = (string)$this->manifest->scriptfile;
  135. if ($manifestScript) {
  136. $manifestScriptFile = $this->parent->getPath('source').DS.$manifestScript;
  137. if (is_file($manifestScriptFile)) {
  138. // Load the file
  139. include_once $manifestScriptFile;
  140. }
  141. // Set the class name
  142. $classname = $this->get('element').'InstallerScript';
  143. if (class_exists($classname)) {
  144. // Create a new instance
  145. $this->parent->manifestClass = new $classname($this);
  146. // And set this so we can copy it later
  147. $this->set('manifest_script', $manifestScript);
  148. // Note: if we don't find the class, don't bother to copy the file
  149. }
  150. }
  151. // Run preflight if possible (since we know we're not an update)
  152. ob_start();
  153. ob_implicit_flush(false);
  154. if ($this->parent->manifestClass && method_exists($this->parent->manifestClass,'preflight')) {
  155. if ($this->parent->manifestClass->preflight('install', $this) === false) {
  156. // Install failed, rollback changes
  157. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE'));
  158. return false;
  159. }
  160. }
  161. // Create msg object; first use here
  162. $msg = ob_get_contents();
  163. ob_end_clean();
  164. // If the component directory does not exist, let's create it
  165. $created = false;
  166. if (!file_exists($this->parent->getPath('extension_site'))) {
  167. if (!$created = JFolder::create($this->parent->getPath('extension_site'))) {
  168. JError::raiseWarning(1, JText::sprintf('JLIB_INSTALLER_ERROR_COMP_INSTALL_FAILED_TO_CREATE_DIRECTORY_SITE', $this->parent->getPath('extension_site')));
  169. return false;
  170. }
  171. }
  172. // Since we created the component directory and will want to remove it if we have to roll back
  173. // the installation, let's add it to the installation step stack
  174. if ($created) {
  175. $this->parent->pushStep(array ('type' => 'folder', 'path' => $this->parent->getPath('extension_site')));
  176. }
  177. // If the component admin directory does not exist, let's create it
  178. $created = false;
  179. if (!file_exists($this->parent->getPath('extension_administrator'))) {
  180. if (!$created = JFolder::create($this->parent->getPath('extension_administrator'))) {
  181. JError::raiseWarning(1, JText::sprintf('JLIB_INSTALLER_ERROR_COMP_INSTALL_FAILED_TO_CREATE_DIRECTORY_ADMIN', $this->parent->getPath('extension_administrator')));
  182. // Install failed, rollback any changes
  183. $this->parent->abort();
  184. return false;
  185. }
  186. }
  187. /*
  188. * Since we created the component admin directory and we will want to remove it if we have to roll
  189. * back the installation, lets add it to the installation step stack
  190. */
  191. if ($created) {
  192. $this->parent->pushStep(array ('type' => 'folder', 'path' => $this->parent->getPath('extension_administrator')));
  193. }
  194. // Copy site files
  195. if ($this->manifest->files) {
  196. if ($this->parent->parseFiles($this->manifest->files) === false) {
  197. // Install failed, rollback any changes
  198. $this->parent->abort();
  199. return false;
  200. }
  201. }
  202. // Copy admin files
  203. if ($this->manifest->administration->files) {
  204. if ($this->parent->parseFiles($this->manifest->administration->files, 1) === false) {
  205. // Install failed, rollback any changes
  206. $this->parent->abort();
  207. return false;
  208. }
  209. }
  210. // Parse optional tags
  211. $this->parent->parseMedia($this->manifest->media);
  212. $this->parent->parseLanguages($this->manifest->languages);
  213. $this->parent->parseLanguages($this->manifest->administration->languages, 1);
  214. // Deprecated install, remove after 1.6
  215. // If there is an install file, lets copy it.
  216. $installFile = (string)$this->manifest->installfile;
  217. if ($installFile) {
  218. // Make sure it hasn't already been copied (this would be an error in the xml install file)
  219. if (!file_exists($this->parent->getPath('extension_administrator').DS.$installFile) || $this->parent->getOverwrite()) {
  220. $path['src'] = $this->parent->getPath('source').DS.$installFile;
  221. $path['dest'] = $this->parent->getPath('extension_administrator').DS.$installFile;
  222. if (!$this->parent->copyFiles(array ($path))) {
  223. // Install failed, rollback changes
  224. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_PHP_INSTALL'));
  225. return false;
  226. }
  227. }
  228. $this->set('install_script', $installFile);
  229. }
  230. // Deprecated uninstall, remove after 1.6
  231. // If there is an uninstall file, lets copy it.
  232. $uninstallFile = (string)$this->manifest->uninstallfile;
  233. if ($uninstallFile) {
  234. // Make sure it hasn't already been copied (this would be an error in the xml install file)
  235. if (!file_exists($this->parent->getPath('extension_administrator').DS.$uninstallFile) || $this->parent->getOverwrite()) {
  236. $path['src'] = $this->parent->getPath('source').DS.$uninstallFile;
  237. $path['dest'] = $this->parent->getPath('extension_administrator').DS.$uninstallFile;
  238. if (!$this->parent->copyFiles(array ($path))) {
  239. // Install failed, rollback changes
  240. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_PHP_UNINSTALL'));
  241. return false;
  242. }
  243. }
  244. }
  245. // If there is a manifest script, lets copy it.
  246. if ($this->get('manifest_script')) {
  247. $path['src'] = $this->parent->getPath('source').DS.$this->get('manifest_script');
  248. $path['dest'] = $this->parent->getPath('extension_administrator').DS.$this->get('manifest_script');
  249. if (!file_exists($path['dest']) || $this->parent->getOverwrite()) {
  250. if (!$this->parent->copyFiles(array ($path))) {
  251. // Install failed, rollback changes
  252. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_MANIFEST'));
  253. return false;
  254. }
  255. }
  256. }
  257. /**
  258. * ---------------------------------------------------------------------------------------------
  259. * Database Processing Section
  260. * ---------------------------------------------------------------------------------------------
  261. */
  262. /*
  263. * Let's run the install queries for the component
  264. * If Joomla 1.5 compatible, with discreet sql files - execute appropriate
  265. * file for utf-8 support or non-utf-8 support
  266. */
  267. // try for Joomla 1.5 type queries
  268. // second argument is the utf compatible version attribute
  269. if (isset($this->manifest->install->sql)) {
  270. $utfresult = $this->parent->parseSQLFiles($this->manifest->install->sql);
  271. if ($utfresult === false) {
  272. // Install failed, rollback changes
  273. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_SQL_ERROR', $db->stderr(true)));
  274. return false;
  275. }
  276. }
  277. /**
  278. * ---------------------------------------------------------------------------------------------
  279. * Custom Installation Script Section
  280. * ---------------------------------------------------------------------------------------------
  281. */
  282. /*
  283. * If we have an install script, lets include it, execute the custom
  284. * install method, and append the return value from the custom install
  285. * method to the installation message.
  286. */
  287. // start legacy support
  288. if ($this->get('install_script')) {
  289. if (is_file($this->parent->getPath('extension_administrator').DS.$this->get('install_script')) || $this->parent->getOverwrite()) {
  290. $notdef = false;
  291. $ranwell = false;
  292. ob_start();
  293. ob_implicit_flush(false);
  294. require_once $this->parent->getPath('extension_administrator').DS.$this->get('install_script');
  295. if (function_exists('com_install')) {
  296. if (com_install() === false) {
  297. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE'));
  298. return false;
  299. }
  300. }
  301. $msg .= ob_get_contents(); // append messages
  302. ob_end_clean();
  303. }
  304. }
  305. // end legacy support
  306. // Start Joomla! 1.6
  307. ob_start();
  308. ob_implicit_flush(false);
  309. if ($this->parent->manifestClass && method_exists($this->parent->manifestClass,'install')) {
  310. if ($this->parent->manifestClass->install($this) === false) {
  311. // Install failed, rollback changes
  312. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE'));
  313. return false;
  314. }
  315. }
  316. $msg .= ob_get_contents(); // append messages
  317. ob_end_clean();
  318. /**
  319. * ---------------------------------------------------------------------------------------------
  320. * Finalization and Cleanup Section
  321. * ---------------------------------------------------------------------------------------------
  322. */
  323. // Add an entry to the extension table with a whole heap of defaults
  324. $row = JTable::getInstance('extension');
  325. $row->set('name', $this->get('name'));
  326. $row->set('type', 'component');
  327. $row->set('element', $this->get('element'));
  328. $row->set('folder', ''); // There is no folder for components
  329. $row->set('enabled', 1);
  330. $row->set('protected', 0);
  331. $row->set('access', 0);
  332. $row->set('client_id', 1);
  333. $row->set('params', $this->parent->getParams());
  334. $row->set('manifest_cache', $this->parent->generateManifestCache());
  335. if (!$row->store()) {
  336. // Install failed, roll back changes
  337. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', $db->stderr(true)));
  338. return false;
  339. }
  340. $eid = $db->insertid();
  341. // Clobber any possible pending updates
  342. $update = JTable::getInstance('update');
  343. $uid = $update->find(
  344. array(
  345. 'element' => $this->get('element'),
  346. 'type' => 'component',
  347. 'client_id' => '',
  348. 'folder' => ''
  349. )
  350. );
  351. if ($uid) {
  352. $update->delete($uid);
  353. }
  354. // We will copy the manifest file to its appropriate place.
  355. if (!$this->parent->copyManifest()) {
  356. // Install failed, rollback changes
  357. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_COPY_SETUP'));
  358. return false;
  359. }
  360. // Time to build the admin menus
  361. if (!$this->_buildAdminMenus($row->extension_id)) {
  362. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ABORT_COMP_BUILDADMINMENUS_FAILED'));
  363. //$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', $db->stderr(true)));
  364. //return false;
  365. }
  366. // Set the schema version to be the latest update version
  367. if ($this->manifest->update) {
  368. $this->parent->setSchemaVersion($this->manifest->update->schemas, $eid);
  369. }
  370. // Register the component container just under root in the assets table.
  371. $asset = JTable::getInstance('Asset');
  372. $asset->name = $row->element;
  373. $asset->parent_id = 1;
  374. $asset->rules = '{}';
  375. $asset->title = $row->name;
  376. $asset->setLocation(1, 'last-child');
  377. if (!$asset->store()) {
  378. // Install failed, roll back changes
  379. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', $db->stderr(true)));
  380. return false;
  381. }
  382. // And now we run the postflight
  383. ob_start();
  384. ob_implicit_flush(false);
  385. if ($this->parent->manifestClass && method_exists($this->parent->manifestClass,'postflight')) {
  386. $this->parent->manifestClass->postflight('install', $this);
  387. }
  388. $msg .= ob_get_contents(); // append messages
  389. ob_end_clean();
  390. if ($msg != '') {
  391. $this->parent->set('extension_message', $msg);
  392. }
  393. return $row->extension_id;
  394. }
  395. /**
  396. * Custom update method for components
  397. *
  398. * @return boolean True on success
  399. * @since 11.1
  400. */
  401. public function update()
  402. {
  403. // Get a database connector object
  404. $db = $this->parent->getDbo();
  405. // set the overwrite setting
  406. $this->parent->setOverwrite(true);
  407. // Get the extension manifest object
  408. $this->manifest = $this->parent->getManifest();
  409. /**
  410. * ---------------------------------------------------------------------------------------------
  411. * Manifest Document Setup Section
  412. * ---------------------------------------------------------------------------------------------
  413. */
  414. // Set the extensions name
  415. $name = strtolower(JFilterInput::getInstance()->clean((string)$this->manifest->name, 'cmd'));
  416. if (substr($name, 0, 4)=="com_") {
  417. $element = $name;
  418. }
  419. else {
  420. $element = "com_$name";
  421. }
  422. $this->set('name', $name);
  423. $this->set('element', $element);
  424. // Get the component description
  425. $description = (string) $this->manifest->description;
  426. if ($description) {
  427. $this->parent->set('message', JText::_($description));
  428. } else {
  429. $this->parent->set('message', '');
  430. }
  431. // Set the installation target paths
  432. $this->parent->setPath('extension_site', JPath::clean(JPATH_SITE.DS."components".DS.$this->get('element')));
  433. $this->parent->setPath('extension_administrator', JPath::clean(JPATH_ADMINISTRATOR.DS."components".DS.$this->get('element')));
  434. $this->parent->setPath('extension_root', $this->parent->getPath('extension_administrator')); // copy this as its used as a common base
  435. /**
  436. * Hunt for the original XML file
  437. */
  438. $old_manifest = null;
  439. $tmpInstaller = new JInstaller(); // create a new installer because findManifest sets stuff
  440. // look in the administrator first
  441. $tmpInstaller->setPath('source', $this->parent->getPath('extension_administrator'));
  442. if (!$tmpInstaller->findManifest()) {
  443. // then the site
  444. $tmpInstaller->setPath('source', $this->parent->getPath('extension_site'));
  445. if ($tmpInstaller->findManifest()) {
  446. $old_manifest = $tmpInstaller->getManifest();
  447. }
  448. }
  449. else {
  450. $old_manifest = $tmpInstaller->getManifest();
  451. }
  452. // should do this above perhaps?
  453. if ($old_manifest) {
  454. $this->oldAdminFiles = $old_manifest->administration->files;
  455. $this->oldFiles = $old_manifest->files;
  456. }
  457. else {
  458. $this->oldAdminFiles = null;
  459. $this->oldFiles = null;
  460. }
  461. /**
  462. * ---------------------------------------------------------------------------------------------
  463. * Basic Checks Section
  464. * ---------------------------------------------------------------------------------------------
  465. */
  466. // Make sure that we have an admin element
  467. if (!$this->manifest->administration) {
  468. JError::raiseWarning(1, JText::_('JLIB_INSTALLER_ABORT_COMP_UPDATE_ADMIN_ELEMENT'));
  469. return false;
  470. }
  471. /**
  472. * ---------------------------------------------------------------------------------------------
  473. * Installer Trigger Loading
  474. * ---------------------------------------------------------------------------------------------
  475. */
  476. // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet)
  477. $manifestScript = (string)$this->manifest->scriptfile;
  478. if ($manifestScript) {
  479. $manifestScriptFile = $this->parent->getPath('source').DS.$manifestScript;
  480. if (is_file($manifestScriptFile)) {
  481. // load the file
  482. include_once $manifestScriptFile;
  483. }
  484. // Set the class name
  485. $classname = $element.'InstallerScript';
  486. if (class_exists($classname)) {
  487. // create a new instance
  488. $this->parent->manifestClass = new $classname($this);
  489. // and set this so we can copy it later
  490. $this->set('manifest_script', $manifestScript);
  491. // Note: if we don't find the class, don't bother to copy the file
  492. }
  493. }
  494. // run preflight if possible (since we know we're not an update)
  495. ob_start();
  496. ob_implicit_flush(false);
  497. if ($this->parent->manifestClass && method_exists($this->parent->manifestClass,'preflight')) {
  498. if ($this->parent->manifestClass->preflight('update', $this) === false) {
  499. // Install failed, rollback changes
  500. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE'));
  501. return false;
  502. }
  503. }
  504. $msg = ob_get_contents(); // create msg object; first use here
  505. ob_end_clean();
  506. /**
  507. * ---------------------------------------------------------------------------------------------
  508. * Filesystem Processing Section
  509. * ---------------------------------------------------------------------------------------------
  510. */
  511. // If the component directory does not exist, lets create it
  512. $created = false;
  513. if (!file_exists($this->parent->getPath('extension_site'))) {
  514. if (!$created = JFolder::create($this->parent->getPath('extension_site'))) {
  515. JError::raiseWarning(1, JText::sprintf('JLIB_INSTALLER_ERROR_COMP_UPDATE_FAILED_TO_CREATE_DIRECTORY_SITE', $this->parent->getPath('extension_site')));
  516. return false;
  517. }
  518. }
  519. /*
  520. * Since we created the component directory and will want to remove it if we have to roll back
  521. * the installation, lets add it to the installation step stack
  522. */
  523. if ($created) {
  524. $this->parent->pushStep(array ('type' => 'folder', 'path' => $this->parent->getPath('extension_site')));
  525. }
  526. // If the component admin directory does not exist, lets create it
  527. $created = false;
  528. if (!file_exists($this->parent->getPath('extension_administrator'))) {
  529. if (!$created = JFolder::create($this->parent->getPath('extension_administrator'))) {
  530. JError::raiseWarning(1, JText::sprintf('JLIB_INSTALLER_ERROR_COMP_UPDATE_FAILED_TO_CREATE_DIRECTORY_ADMIN', $this->parent->getPath('extension_administrator')));
  531. // Install failed, rollback any changes
  532. $this->parent->abort();
  533. return false;
  534. }
  535. }
  536. /*
  537. * Since we created the component admin directory and we will want to remove it if we have to roll
  538. * back the installation, lets add it to the installation step stack
  539. */
  540. if ($created) {
  541. $this->parent->pushStep(array ('type' => 'folder', 'path' => $this->parent->getPath('extension_administrator')));
  542. }
  543. // Find files to copy
  544. if ($this->manifest->files) {
  545. if ($this->parent->parseFiles($this->manifest->files, 0, $this->oldFiles) === false) {
  546. // Install failed, rollback any changes
  547. $this->parent->abort();
  548. return false;
  549. }
  550. }
  551. if ($this->manifest->administration->files) {
  552. if ($this->parent->parseFiles($this->manifest->administration->files, 1, $this->oldAdminFiles) === false) {
  553. // Install failed, rollback any changes
  554. $this->parent->abort();
  555. return false;
  556. }
  557. }
  558. // Parse optional tags
  559. $this->parent->parseMedia($this->manifest->media);
  560. $this->parent->parseLanguages($this->manifest->languages);
  561. $this->parent->parseLanguages($this->manifest->administration->languages, 1);
  562. // Deprecated install, remove after 1.6
  563. // If there is an install file, lets copy it.
  564. $installFile = (string)$this->manifest->installfile;
  565. if ($installFile) {
  566. // Make sure it hasn't already been copied (this would be an error in the xml install file)
  567. if (!file_exists($this->parent->getPath('extension_administrator').DS.$installFile) || $this->parent->getOverwrite()) {
  568. $path['src'] = $this->parent->getPath('source').DS.$installFile;
  569. $path['dest'] = $this->parent->getPath('extension_administrator').DS.$installFile;
  570. if (!$this->parent->copyFiles(array ($path))) {
  571. // Install failed, rollback changes
  572. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_UPDATE_PHP_INSTALL'));
  573. return false;
  574. }
  575. }
  576. $this->set('install_script', $installFile);
  577. }
  578. // Deprecated uninstall, remove after 1.6
  579. // If there is an uninstall file, lets copy it.
  580. $uninstallFile = (string)$this->manifest->uninstallfile;
  581. if ($uninstallFile) {
  582. // Make sure it hasn't already been copied (this would be an error in the xml install file)
  583. if (!file_exists($this->parent->getPath('extension_administrator').DS.$uninstallFile) || $this->parent->getOverwrite()) {
  584. $path['src'] = $this->parent->getPath('source').DS.$uninstallFile;
  585. $path['dest'] = $this->parent->getPath('extension_administrator').DS.$uninstallFile;
  586. if (!$this->parent->copyFiles(array ($path))) {
  587. // Install failed, rollback changes
  588. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_UPDATE_PHP_UNINSTALL'));
  589. return false;
  590. }
  591. }
  592. }
  593. // If there is a manifest script, lets copy it.
  594. if ($this->get('manifest_script')) {
  595. $path['src'] = $this->parent->getPath('source').DS.$this->get('manifest_script');
  596. $path['dest'] = $this->parent->getPath('extension_administrator').DS.$this->get('manifest_script');
  597. if (!file_exists($path['dest']) || $this->parent->getOverwrite()) {
  598. if (!$this->parent->copyFiles(array ($path))) {
  599. // Install failed, rollback changes
  600. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_UPDATE_MANIFEST'));
  601. return false;
  602. }
  603. }
  604. }
  605. /**
  606. * ---------------------------------------------------------------------------------------------
  607. * Database Processing Section
  608. * ---------------------------------------------------------------------------------------------
  609. */
  610. /*
  611. * Let's run the update queries for the component
  612. */
  613. $row = JTable::getInstance('extension');
  614. $eid = $row->find(
  615. array(
  616. 'element' => strtolower($this->get('element')),
  617. 'type' =>'component'
  618. )
  619. );
  620. if ($this->manifest->update) {
  621. $result = $this->parent->parseSchemaUpdates($this->manifest->update->schemas, $eid);
  622. if ($result === false) {
  623. // Install failed, rollback changes
  624. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_UPDATE_SQL_ERROR', $db->stderr(true)));
  625. return false;
  626. }
  627. }
  628. // Time to build the admin menus
  629. if (!$this->_buildAdminMenus($eid)) {
  630. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ABORT_COMP_BUILDADMINMENUS_FAILED'));
  631. //$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', $db->stderr(true)));
  632. //return false;
  633. }
  634. /**
  635. * ---------------------------------------------------------------------------------------------
  636. * Custom Installation Script Section
  637. * ---------------------------------------------------------------------------------------------
  638. */
  639. /*
  640. * If we have an install script, lets include it, execute the custom
  641. * install method, and append the return value from the custom install
  642. * method to the installation message.
  643. */
  644. // start legacy support
  645. if ($this->get('install_script')) {
  646. if (is_file($this->parent->getPath('extension_administrator').DS.$this->get('install_script')) || $this->parent->getOverwrite()) {
  647. $notdef = false;
  648. $ranwell = false;
  649. ob_start();
  650. ob_implicit_flush(false);
  651. require_once $this->parent->getPath('extension_administrator').DS.$this->get('install_script');
  652. if (function_exists('com_install')) {
  653. if (com_install() === false) {
  654. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE'));
  655. return false;
  656. }
  657. }
  658. $msg .= ob_get_contents(); // append messages
  659. ob_end_clean();
  660. }
  661. }
  662. /*
  663. * If we have an update script, lets include it, execute the custom
  664. * update method, and append the return value from the custom update
  665. * method to the installation message.
  666. */
  667. // Start Joomla! 1.6
  668. ob_start();
  669. ob_implicit_flush(false);
  670. if ($this->parent->manifestClass && method_exists($this->parent->manifestClass,'update')) {
  671. if ($this->parent->manifestClass->update($this) === false) {
  672. // Install failed, rollback changes
  673. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE'));
  674. return false;
  675. }
  676. }
  677. $msg .= ob_get_contents(); // append messages
  678. ob_end_clean();
  679. /**
  680. * ---------------------------------------------------------------------------------------------
  681. * Finalization and Cleanup Section
  682. * ---------------------------------------------------------------------------------------------
  683. */
  684. // Clobber any possible pending updates
  685. $update = JTable::getInstance('update');
  686. $uid = $update->find(
  687. array(
  688. 'element' => $this->get('element'),
  689. 'type' => 'component',
  690. 'client_id' => '',
  691. 'folder' => ''
  692. )
  693. );
  694. if ($uid) {
  695. $update->delete($uid);
  696. }
  697. // Update an entry to the extension table
  698. if ($eid) {
  699. $row->load($eid);
  700. } else {
  701. // set the defaults
  702. $row->folder = ''; // There is no folder for components
  703. $row->enabled = 1;
  704. $row->protected = 0;
  705. $row->access = 1;
  706. $row->client_id = 1;
  707. $row->params = $this->parent->getParams();
  708. }
  709. $row->name = $this->get('name');
  710. $row->type = 'component';
  711. $row->element = $this->get('element');
  712. $row->manifest_cache = $this->parent->generateManifestCache();
  713. if (!$row->store()) {
  714. // Install failed, roll back changes
  715. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_UPDATE_ROLLBACK', $db->stderr(true)));
  716. return false;
  717. }
  718. // We will copy the manifest file to its appropriate place.
  719. if (!$this->parent->copyManifest()) {
  720. // Install failed, rollback changes
  721. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_UPDATE_COPY_SETUP'));
  722. return false;
  723. }
  724. // And now we run the postflight
  725. ob_start();
  726. ob_implicit_flush(false);
  727. if ($this->parent->manifestClass && method_exists($this->parent->manifestClass,'postflight')) {
  728. $this->parent->manifestClass->postflight('update', $this);
  729. }
  730. $msg .= ob_get_contents(); // append messages
  731. ob_end_clean();
  732. if ($msg != '') {
  733. $this->parent->set('extension_message', $msg);
  734. }
  735. return $row->extension_id;
  736. }
  737. /**
  738. * Custom uninstall method for components
  739. *
  740. * @param int $id The unique extension id of the component to uninstall
  741. *
  742. * @return mixed Return value for uninstall method in component uninstall file
  743. * @since 1.0
  744. */
  745. public function uninstall($id)
  746. {
  747. // Initialise variables.
  748. $db = $this->parent->getDbo();
  749. $row = null;
  750. $retval = true;
  751. // First order of business will be to load the component object table from the database.
  752. // This should give us the necessary information to proceed.
  753. $row = JTable::getInstance('extension');
  754. if (!$row->load((int) $id)) {
  755. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_ERRORUNKOWNEXTENSION'));
  756. return false;
  757. }
  758. // Is the component we are trying to uninstall a core one?
  759. // Because that is not a good idea...
  760. if ($row->protected) {
  761. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_WARNCORECOMPONENT'));
  762. return false;
  763. }
  764. // Get the admin and site paths for the component
  765. $this->parent->setPath('extension_administrator', JPath::clean(JPATH_ADMINISTRATOR.DS.'components'.DS.$row->element));
  766. $this->parent->setPath('extension_site', JPath::clean(JPATH_SITE.DS.'components'.DS.$row->element));
  767. $this->parent->setPath('extension_root', $this->parent->getPath('extension_administrator')); // copy this as its used as a common base
  768. /**
  769. * ---------------------------------------------------------------------------------------------
  770. * Manifest Document Setup Section
  771. * ---------------------------------------------------------------------------------------------
  772. */
  773. // Find and load the XML install file for the component
  774. $this->parent->setPath('source', $this->parent->getPath('extension_administrator'));
  775. // Get the package manifest object
  776. // We do findManifest to avoid problem when uninstalling a list of extension: getManifest cache its manifest file
  777. $this->parent->findManifest();
  778. $this->manifest = $this->parent->getManifest();
  779. if (!$this->manifest) {
  780. // Make sure we delete the folders if no manifest exists
  781. JFolder::delete($this->parent->getPath('extension_administrator'));
  782. JFolder::delete($this->parent->getPath('extension_site'));
  783. // Remove the menu
  784. $this->_removeAdminMenus($row);
  785. // Raise a warning
  786. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_ERRORREMOVEMANUALLY'));
  787. // Return
  788. return false;
  789. }
  790. // Set the extensions name
  791. $name = strtolower(JFilterInput::getInstance()->clean((string)$this->manifest->name, 'cmd'));
  792. if (substr($name, 0, 4)=="com_") {
  793. $element = $name;
  794. }
  795. else {
  796. $element = "com_$name";
  797. }
  798. $this->set('name', $name);
  799. $this->set('element', $element);
  800. // Attempt to load the admin language file; might have uninstall strings
  801. $this->loadLanguage(JPATH_ADMINISTRATOR.'/components/'.$element);
  802. /**
  803. * ---------------------------------------------------------------------------------------------
  804. * Installer Trigger Loading and Uninstall
  805. * ---------------------------------------------------------------------------------------------
  806. */
  807. // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet)
  808. $scriptFile = (string)$this->manifest->scriptfile;
  809. if ($scriptFile) {
  810. $manifestScriptFile = $this->parent->getPath('source').DS.$scriptFile;
  811. if (is_file($manifestScriptFile)) {
  812. // load the file
  813. include_once $manifestScriptFile;
  814. }
  815. // Set the class name
  816. $classname = $row->element.'InstallerScript';
  817. if (class_exists($classname)) {
  818. // create a new instance
  819. $this->parent->manifestClass = new $classname($this);
  820. // and set this so we can copy it later
  821. $this->set('manifest_script', $scriptFile);
  822. // Note: if we don't find the class, don't bother to copy the file
  823. }
  824. }
  825. ob_start();
  826. ob_implicit_flush(false);
  827. // run uninstall if possible
  828. if ($this->parent->manifestClass && method_exists($this->parent->manifestClass,'uninstall')) {
  829. $this->parent->manifestClass->uninstall($this);
  830. }
  831. $msg = ob_get_contents();
  832. ob_end_clean();
  833. /**
  834. * ---------------------------------------------------------------------------------------------
  835. * Custom Uninstallation Script Section; Legacy 1.5 Support
  836. * ---------------------------------------------------------------------------------------------
  837. */
  838. // Now lets load the uninstall file if there is one and execute the uninstall function if it exists.
  839. $uninstallFile = (string)$this->manifest->uninstallfile;
  840. if ($uninstallFile) {
  841. // Element exists, does the file exist?
  842. if (is_file($this->parent->getPath('extension_administrator').DS.$uninstallFile)) {
  843. ob_start();
  844. ob_implicit_flush(false);
  845. require_once $this->parent->getPath('extension_administrator').DS.$uninstallFile;
  846. if (function_exists('com_uninstall')) {
  847. if (com_uninstall() === false) {
  848. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_CUSTOM'));
  849. $retval = false;
  850. }
  851. }
  852. $msg .= ob_get_contents(); // append this in case there was something else
  853. ob_end_clean();
  854. }
  855. }
  856. if ($msg != '') {
  857. $this->parent->set('extension_message', $msg);
  858. }
  859. /**
  860. * ---------------------------------------------------------------------------------------------
  861. * Database Processing Section
  862. * ---------------------------------------------------------------------------------------------
  863. */
  864. /*
  865. * Let's run the uninstall queries for the component
  866. * If Joomla 1.5 compatible, with discreet sql files - execute appropriate
  867. * file for utf-8 support or non-utf support
  868. */
  869. // try for Joomla 1.5 type queries
  870. // second argument is the utf compatible version attribute
  871. if (isset($this->manifest->uninstall->sql)) {
  872. $utfresult = $this->parent->parseSQLFiles($this->manifest->uninstall->sql);
  873. if ($utfresult === false) {
  874. // Install failed, rollback changes
  875. JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_SQL_ERROR', $db->stderr(true)));
  876. $retval = false;
  877. }
  878. }
  879. $this->_removeAdminMenus($row);
  880. /**
  881. * ---------------------------------------------------------------------------------------------
  882. * Filesystem Processing Section
  883. * ---------------------------------------------------------------------------------------------
  884. */
  885. // Let's remove language files and media in the JROOT/images/ folder that are
  886. // associated with the component we are uninstalling
  887. $this->parent->removeFiles($this->manifest->media);
  888. $this->parent->removeFiles($this->manifest->languages);
  889. $this->parent->removeFiles($this->manifest->administration->languages, 1);
  890. // Remove the schema version
  891. $query = $db->getQuery(true);
  892. $query->delete()->from('#__schemas')->where('extension_id = '. $id);
  893. $db->setQuery($query);
  894. $db->query();
  895. // Remove the component container in the assets table.
  896. $asset = JTable::getInstance('Asset');
  897. if ($asset->loadByName($element)) {
  898. $asset->delete();
  899. }
  900. // Clobber any possible pending updates
  901. $update = JTable::getInstance('update');
  902. $uid = $update->find(
  903. array(
  904. 'element' => $row->element,
  905. 'type' => 'component',
  906. 'client_id' => '',
  907. 'folder' => ''
  908. )
  909. );
  910. if ($uid) {
  911. $update->delete($uid);
  912. }
  913. // Now we need to delete the installation directories. This is the final step in uninstalling the component.
  914. if (trim($row->element)) {
  915. // Delete the component site directory
  916. if (is_dir($this->parent->getPath('extension_site'))) {
  917. if (!JFolder::delete($this->parent->getPath('extension_site'))) {
  918. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_FAILED_REMOVE_DIRECTORY_SITE'));
  919. $retval = false;
  920. }
  921. }
  922. // Delete the component admin directory
  923. if (is_dir($this->parent->getPath('extension_administrator'))) {
  924. if (!JFolder::delete($this->parent->getPath('extension_administrator'))) {
  925. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_FAILED_REMOVE_DIRECTORY_ADMIN'));
  926. $retval = false;
  927. }
  928. }
  929. // Now we will no longer need the extension object, so lets delete it and free up memory
  930. $row->delete($row->extension_id);
  931. unset ($row);
  932. return $retval;
  933. }
  934. else {
  935. // No component option defined... cannot delete what we don't know about
  936. JError::raiseWarning(100, 'JLIB_INSTALLER_ERROR_COMP_UNINSTALL_NO_OPTION');
  937. return false;
  938. }
  939. }
  940. /**
  941. * Method to build menu database entries for a component
  942. *
  943. * @return boolean True if successful
  944. * @since 11.1
  945. */
  946. protected function _buildAdminMenus()
  947. {
  948. // Initialise variables.
  949. $db = $this->parent->getDbo();
  950. $table = JTable::getInstance('menu');
  951. $option = $this->get('element');
  952. // If a component exists with this option in the table then we don't need to add menus
  953. $query = $db->getQuery(true);
  954. $query->select('m.id, e.extension_id');
  955. $query->from('#__menu AS m');
  956. $query->leftJoin('#__extensions AS e ON m.component_id = e.extension_id');
  957. $query->where('m.parent_id = 1');
  958. $query->where("m.client_id = 1");
  959. $query->where('e.element = '.$db->quote($option));
  960. $db->setQuery($query);
  961. $componentrow = $db->loadObject();
  962. // Check if menu items exist
  963. if ($componentrow) {
  964. // Don't do anything if overwrite has not been enabled
  965. if (! $this->parent->getOverwrite()) {
  966. return true;
  967. }
  968. // Remove existing menu items if overwrite has been enabled
  969. if ($option) {
  970. $this->_removeAdminMenus($componentrow);// If something goes wrong, theres no way to rollback TODO: Search for better solution
  971. }
  972. $component_id = $componentrow->extension_id;
  973. }
  974. else {
  975. // Lets Find the extension id
  976. $query->clear();
  977. $query->select('e.extension_id');
  978. $query->from('#__extensions AS e');
  979. $query->where('e.element = '.$db->quote($option));
  980. $db->setQuery($query);
  981. $component_id = $db->loadResult(); // TODO Find Some better way to discover the component_id
  982. }
  983. // Ok, now its time to handle the menus. Start with the component root menu, then handle submenus.
  984. $menuElement = $this->manifest->administration->menu;
  985. if ($menuElement) {
  986. $data = array();
  987. $data['menutype'] = 'main';
  988. $data['client_id'] = 1;
  989. $data['title'] = (string)$menuElement;
  990. $data['alias'] = (string)$menuElement;
  991. $data['link'] = 'index.php?option='.$option;
  992. $data['type'] = 'component';
  993. $data['published'] = 0;
  994. $data['parent_id'] = 1;
  995. $data['component_id'] = $component_id;
  996. $data['img'] = ((string)$menuElement->attributes()->img) ? (string)$menuElement->attributes()->img : 'class:component';
  997. $data['home'] = 0;
  998. if (!$table->setLocation(1, 'last-child') || !$table->bind($data) || !$table->check() || !$table->store()) {
  999. // Install failed, rollback changes
  1000. return false;
  1001. }
  1002. /*
  1003. * Since we have created a menu item, we add it to the installation step stack
  1004. * so that if we have to rollback the changes we can undo it.
  1005. */
  1006. $this->parent->pushStep(array ('type' => 'menu'));
  1007. }
  1008. // No menu element was specified, Let's make a generic menu item
  1009. else {
  1010. $data = array();
  1011. $data['menutype'] = 'main';
  1012. $data['client_id'] = 1;
  1013. $data['title'] = $option;
  1014. $data['alias'] = $option;
  1015. $data['link'] = 'index.php?option='.$option;
  1016. $data['type'] = 'component';
  1017. $data['published'] = 0;
  1018. $data['parent_id'] = 1;
  1019. $data['component_id'] = $component_id;
  1020. $data['img'] = 'class:component';
  1021. $data['home'] = 0;
  1022. if (!$table->setLocation(1, 'last-child') || !$table->bind($data) || !$table->check() || !$table->store()) {
  1023. // Install failed, rollback changes
  1024. return false;
  1025. }
  1026. /*
  1027. * Since we have created a menu item, we add it to the installation step stack
  1028. * so that if we have to rollback the changes we can undo it.
  1029. */
  1030. $this->parent->pushStep(array ('type' => 'menu'));
  1031. }
  1032. $parent_id = $table->id;;
  1033. /*
  1034. * Process SubMenus
  1035. */
  1036. if (!$this->manifest->administration->submenu) {
  1037. return true;
  1038. }
  1039. $parent_id = $table->id;;
  1040. foreach ($this->manifest->administration->submenu->menu as $child) {
  1041. $data = array();
  1042. $data['menutype'] = 'main';
  1043. $data['client_id'] = 1;
  1044. $data['title'] = (string)$child;
  1045. $data['alias'] = (string)$child;
  1046. $data['type'] = 'component';
  1047. $data['published'] = 0;
  1048. $data['parent_id'] = $parent_id;
  1049. $data['component_id'] = $component_id;
  1050. $data['img'] = ((string)$child->attributes()->img) ? (string)$child->attributes()->img : 'class:component';
  1051. $data['home'] = 0;
  1052. // Set the sub menu link
  1053. if ((string)$child->attributes()->link) {
  1054. $data['link'] = 'index.php?'.$child->attributes()->link;
  1055. }
  1056. else {
  1057. $request = array();
  1058. if ((string)$child->attributes()->act) {
  1059. $request[] = 'act='.$child->attributes()->act;
  1060. }
  1061. if ((string)$child->attributes()->task) {
  1062. $request[] = 'task='.$child->attributes()->task;
  1063. }
  1064. if ((string)$child->attributes()->controller) {
  1065. $request[] = 'controller='.$child->attributes()->controller;
  1066. }
  1067. if ((string)$child->attributes()->view) {
  1068. $request[] = 'view='.$child->attributes()->view;
  1069. }
  1070. if ((string)$child->attributes()->layout) {
  1071. $request[] = 'layout='.$child->attributes()->layout;
  1072. }
  1073. if ((string)$child->attributes()->sub) {
  1074. $request[] = 'sub='.$child->attributes()->sub;
  1075. }
  1076. $qstring = (count($request)) ? '&'.implode('&',$request) : '';
  1077. $data['link'] = 'index.php?option='.$option.$qstring;
  1078. }
  1079. $table = JTable::getInstance('menu');
  1080. if (!$table->setLocation($parent_id, 'last-child') || !$table->bind($data) || !$table->check() || !$table->store()) {
  1081. // Install failed, rollback changes
  1082. return false;
  1083. }
  1084. /*
  1085. * Since we have created a menu item, we add it to the installation step stack
  1086. * so that if we have to rollback the changes we can undo it.
  1087. */
  1088. $this->parent->pushStep(array ('type' => 'menu'));
  1089. }
  1090. return true;
  1091. }
  1092. /**
  1093. * Method to remove admin menu references to a component
  1094. *
  1095. * @param object $component Component table object
  1096. *
  1097. * @return boolean True if successful
  1098. * @since 11.1
  1099. */
  1100. protected function _removeAdminMenus(&$row)
  1101. {
  1102. // Initialise Variables
  1103. $db = $this->parent->getDbo();
  1104. $table = JTable::getInstance('menu');
  1105. $id = $row->extension_id;
  1106. // Get the ids of the menu items
  1107. $query = $db->getQuery(true);
  1108. $query->select('id');
  1109. $query->from('#__menu');
  1110. $query->where('`client_id` = 1');
  1111. $query->where('`component_id` = '.(int) $id);
  1112. $db->setQuery($query);
  1113. $ids = $db->loadResultArray();
  1114. // Check for error
  1115. if ($error = $db->getErrorMsg() || empty($ids)){
  1116. JError::raiseWarning('', JText::_('JLIB_INSTALLER_ERROR_COMP_REMOVING_ADMIN_MENUS_FAILED'));
  1117. if ($error && $error != 1) {
  1118. JError::raiseWarning(100, $error);
  1119. }
  1120. return false;
  1121. }
  1122. else {
  1123. // Iterate the items to delete each one.
  1124. foreach($ids as $menuid){
  1125. if (!$table->delete((int) $menuid)) {
  1126. $this->setError($table->getError());
  1127. return false;
  1128. }
  1129. }
  1130. // Rebuild the whole tree
  1131. $table->rebuild();
  1132. }
  1133. return true;
  1134. }
  1135. /**
  1136. * Custom rollback method
  1137. * - Roll back the component menu item
  1138. *
  1139. * @param array $arg Installation step to rollback
  1140. *
  1141. * @return boolean True on success
  1142. * @since 11.1
  1143. */
  1144. protected function _rollback_menu()
  1145. {
  1146. return true;
  1147. }
  1148. /**
  1149. * Discover unregistered extensions.
  1150. *
  1151. * @return array A list of extensions.
  1152. * @since 11.1
  1153. */
  1154. public function discover()
  1155. {
  1156. $results = array();
  1157. $site_components = JFolder::folders(JPATH_SITE.DS.'components');
  1158. $admin_components = JFolder::folders(JPATH_ADMINISTRATOR.DS.'components');
  1159. foreach ($site_components as $component) {
  1160. if (file_exists(JPATH_SITE.DS.'components'.DS.$component.DS.str_replace('com_','', $component).'.xml')) {
  1161. $manifest_details = JApplicationHelper::parseXMLInstallFile(JPATH_SITE.DS.'components'.DS.$component.DS.str_replace('com_','', $component).'.xml');
  1162. $extension = JTable::getInstance('extension');
  1163. $extension->set('type', 'component');
  1164. $extension->set('client_id', 0);
  1165. $extension->set('element', $component);
  1166. $extension->set('name', $component);
  1167. $extension->set('state', -1);
  1168. $extension->set('manifest_cache', json_encode($manifest_details));
  1169. $results[] = $extension;
  1170. }
  1171. }
  1172. foreach ($admin_components as $component) {
  1173. if (file_exists(JPATH_ADMINISTRATOR.DS.'components'.DS.$component.DS.str_replace('com_','', $component).'.xml')) {
  1174. $manifest_details = JApplicationHelper::parseXMLInstallFile(JPATH_ADMINISTRATOR.DS.'components'.DS.$component.DS.str_replace('com_','', $component).'.xml');
  1175. $extension = JTable::getInstance('extension');
  1176. $extension->set('type', 'component');
  1177. $extension->set('client_id', 1);
  1178. $extension->set('element', $component);
  1179. $extension->set('name', $component);
  1180. $extension->set('state', -1);
  1181. $extension->set('manifest_cache', json_encode($manifest_details));
  1182. $results[] = $extension;
  1183. }
  1184. }
  1185. return $results;
  1186. }
  1187. /**
  1188. * Install unregistered extensions that have been discovered.
  1189. *
  1190. * @return mixed
  1191. * @since 11.1
  1192. */
  1193. public function discover_install()
  1194. {
  1195. // Need to find to find where the XML file is since we don't store this normally
  1196. $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id);
  1197. $short_element = str_replace('com_', '', $this->parent->extension->element);
  1198. $manifestPath = $client->path.DS.'components'. DS.$this->parent->extension->element.DS.$short_element.'.xml';
  1199. $this->parent->manifest = $this->parent->isManifest($manifestPath);
  1200. $this->parent->setPath('manifest', $manifestPath);
  1201. $this->parent->setPath('source', $client->path.DS.'components'. DS.$this->parent->extension->element);
  1202. $this->parent->setPath('extension_root', $this->parent->getPath('source'));
  1203. $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest'));
  1204. $this->parent->extension->manifest_cache = json_encode($manifest_details);
  1205. $this->parent->extension->state = 0;
  1206. $this->parent->extension->name = $manifest_details['name'];
  1207. $this->parent->extension->enabled = 1;
  1208. $this->parent->extension->params = $this->parent->getParams();
  1209. try {
  1210. $this->parent->extension->store();
  1211. }
  1212. catch (JException $e) {
  1213. JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_COMP_DISCOVER_STORE_DETAILS'));
  1214. return false;
  1215. }
  1216. // now we need to run any SQL it has, languages, media or menu stuff
  1217. // Get a database connector object
  1218. $db = $this->parent->getDbo();
  1219. // Get the extension manifest object
  1220. $this->manifest = $this->parent->getManifest();
  1221. /**
  1222. * ---------------------------------------------------------------------------------------------
  1223. * Manifest Document Setup Section
  1224. * ---------------------------------------------------------------------------------------------
  1225. */
  1226. // Set the extensions name
  1227. $name = strtolower(JFilterInput::getInstance()->clean((string)$this->manifest->name, 'cmd'));
  1228. if (substr($name, 0, 4)=="com_") {
  1229. $element = $name;
  1230. }
  1231. else {
  1232. $element = "com_$name";
  1233. }
  1234. $this->set('name', $name);
  1235. $this->set('element', $element);
  1236. // Get the component description
  1237. $description = (string)$this->manifest->description;
  1238. if ($description) {
  1239. $this->parent->set('message', JText::_((string)$description));
  1240. }
  1241. else {
  1242. $this->parent->set('message', '');
  1243. }
  1244. // Set the installation target paths
  1245. $this->parent->setPath('extension_site', JPath::clean(JPATH_SITE.DS."components".DS.$this->get('element')));
  1246. $this->parent->setPath('extension_administrator', JPath::clean(JPATH_ADMINISTRATOR.DS."components".DS.$this->get('element')));
  1247. $this->parent->setPath('extension_root', $this->parent->getPath('extension_administrator')); // copy this as its used as a common base
  1248. /**
  1249. * ---------------------------------------------------------------------------------------------
  1250. * Basic Checks Section
  1251. * ---------------------------------------------------------------------------------------------
  1252. */
  1253. // Make sure that we …

Large files files are truncated, but you can click here to view the full file