PageRenderTime 26ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://gitlab.com/endomorphosis/greenrenaissancejoomla
PHP | 703 lines | 384 code | 80 blank | 239 comment | 79 complexity | d131d8c435715151eadc8d596982b1c4 MD5 | raw file
  1. <?php
  2. /**
  3. * @version $Id:component.php 6961 2007-03-15 16:06:53Z tcp $
  4. * @package Joomla.Framework
  5. * @subpackage Installer
  6. * @copyright Copyright (C) 2005 - 2008 Open Source Matters. All rights reserved.
  7. * @license GNU/GPL, see LICENSE.php
  8. * Joomla! is free software. This version may have been modified pursuant
  9. * to the GNU General Public License, and as distributed it includes or
  10. * is derivative of works licensed under the GNU General Public License or
  11. * other free or open source software licenses.
  12. * See COPYRIGHT.php for copyright notices and details.
  13. */
  14. // Check to ensure this file is within the rest of the framework
  15. defined('JPATH_BASE') or die();
  16. /**
  17. * Component installer
  18. *
  19. * @package Joomla.Framework
  20. * @subpackage Installer
  21. * @since 1.5
  22. */
  23. class JInstallerComponent extends JObject
  24. {
  25. /**
  26. * Constructor
  27. *
  28. * @access protected
  29. * @param object $parent Parent object [JInstaller instance]
  30. * @return void
  31. * @since 1.5
  32. */
  33. function __construct(&$parent)
  34. {
  35. $this->parent =& $parent;
  36. }
  37. /**
  38. * Custom install method for components
  39. *
  40. * @access public
  41. * @return boolean True on success
  42. * @since 1.5
  43. */
  44. function install()
  45. {
  46. // Get a database connector object
  47. $db =& $this->parent->getDBO();
  48. // Get the extension manifest object
  49. $manifest =& $this->parent->getManifest();
  50. $this->manifest =& $manifest->document;
  51. /**
  52. * ---------------------------------------------------------------------------------------------
  53. * Manifest Document Setup Section
  54. * ---------------------------------------------------------------------------------------------
  55. */
  56. // Set the extensions name
  57. $name =& $this->manifest->getElementByPath('name');
  58. $name = JFilterInput::clean($name->data(), 'cmd');
  59. $this->set('name', $name);
  60. // Get the component description
  61. $description = & $this->manifest->getElementByPath('description');
  62. if (is_a($description, 'JSimpleXMLElement')) {
  63. $this->parent->set('message', $description->data());
  64. } else {
  65. $this->parent->set('message', '' );
  66. }
  67. // Get some important manifest elements
  68. $this->adminElement =& $this->manifest->getElementByPath('administration');
  69. $this->installElement =& $this->manifest->getElementByPath('install');
  70. $this->uninstallElement =& $this->manifest->getElementByPath('uninstall');
  71. // Set the installation target paths
  72. $this->parent->setPath('extension_site', JPath::clean(JPATH_SITE.DS."components".DS.strtolower("com_".str_replace(" ", "", $this->get('name')))));
  73. $this->parent->setPath('extension_administrator', JPath::clean(JPATH_ADMINISTRATOR.DS."components".DS.strtolower("com_".str_replace(" ", "", $this->get('name')))));
  74. /**
  75. * ---------------------------------------------------------------------------------------------
  76. * Basic Checks Section
  77. * ---------------------------------------------------------------------------------------------
  78. */
  79. // Make sure that we have an admin element
  80. if ( ! is_a($this->adminElement, 'JSimpleXMLElement') )
  81. {
  82. JError::raiseWarning(1, JText::_('Component').' '.JText::_('Install').': '.JText::_('The XML file did not contain an administration element'));
  83. return false;
  84. }
  85. /**
  86. * ---------------------------------------------------------------------------------------------
  87. * Filesystem Processing Section
  88. * ---------------------------------------------------------------------------------------------
  89. */
  90. /*
  91. * If the component site or admin directory already exists, then we will assume that the component is already
  92. * installed or another component is using that directory.
  93. */
  94. if ((file_exists($this->parent->getPath('extension_site')) || file_exists($this->parent->getPath('extension_administrator'))) && !$this->parent->getOverwrite()) {
  95. JError::raiseWarning(1, JText::_('Component').' '.JText::_('Install').': '.JText::_('Another component is already using directory').': "'.$this->parent->getPath('extension_site').'"');
  96. return false;
  97. }
  98. // If the component directory does not exist, lets create it
  99. $created = false;
  100. if (!file_exists($this->parent->getPath('extension_site'))) {
  101. if (!$created = JFolder::create($this->parent->getPath('extension_site'))) {
  102. JError::raiseWarning(1, JText::_('Component').' '.JText::_('Install').': '.JText::_('Failed to create directory').': "'.$this->parent->getPath('extension_site').'"');
  103. return false;
  104. }
  105. }
  106. /*
  107. * Since we created the component directory and will want to remove it if we have to roll back
  108. * the installation, lets add it to the installation step stack
  109. */
  110. if ($created) {
  111. $this->parent->pushStep(array ('type' => 'folder', 'path' => $this->parent->getPath('extension_site')));
  112. }
  113. // If the component admin directory does not exist, lets create it
  114. $created = false;
  115. if (!file_exists($this->parent->getPath('extension_administrator'))) {
  116. if (!$created = JFolder::create($this->parent->getPath('extension_administrator'))) {
  117. JError::raiseWarning(1, JText::_('Component').' '.JText::_('Install').': '.JText::_('Failed to create directory').': "'.$this->parent->getPath('extension_administrator').'"');
  118. // Install failed, rollback any changes
  119. $this->parent->abort();
  120. return false;
  121. }
  122. }
  123. /*
  124. * Since we created the component admin directory and we will want to remove it if we have to roll
  125. * back the installation, lets add it to the installation step stack
  126. */
  127. if ($created) {
  128. $this->parent->pushStep(array ('type' => 'folder', 'path' => $this->parent->getPath('extension_administrator')));
  129. }
  130. // Find files to copy
  131. foreach ($this->manifest->children() as $child)
  132. {
  133. if (is_a($child, 'JSimpleXMLElement') && $child->name() == 'files') {
  134. if ($this->parent->parseFiles($child) === false) {
  135. // Install failed, rollback any changes
  136. $this->parent->abort();
  137. return false;
  138. }
  139. }
  140. }
  141. foreach ($this->adminElement->children() as $child)
  142. {
  143. if (is_a($child, 'JSimpleXMLElement') && $child->name() == 'files') {
  144. if ($this->parent->parseFiles($child, 1) === false) {
  145. // Install failed, rollback any changes
  146. $this->parent->abort();
  147. return false;
  148. }
  149. }
  150. }
  151. // Parse optional tags
  152. $this->parent->parseMedia($this->manifest->getElementByPath('media'));
  153. $this->parent->parseLanguages($this->manifest->getElementByPath('languages'));
  154. $this->parent->parseLanguages($this->manifest->getElementByPath('administration/languages'), 1);
  155. // Parse deprecated tags
  156. $this->parent->parseFiles($this->manifest->getElementByPath('images'));
  157. $this->parent->parseFiles($this->manifest->getElementByPath('administration/images'), 1);
  158. // If there is an install file, lets copy it.
  159. $installScriptElement =& $this->manifest->getElementByPath('installfile');
  160. if (is_a($installScriptElement, 'JSimpleXMLElement')) {
  161. // Make sure it hasn't already been copied (this would be an error in the xml install file)
  162. if (!file_exists($this->parent->getPath('extension_administrator').DS.$installScriptElement->data()))
  163. {
  164. $path['src'] = $this->parent->getPath('source').DS.$installScriptElement->data();
  165. $path['dest'] = $this->parent->getPath('extension_administrator').DS.$installScriptElement->data();
  166. if (!$this->parent->copyFiles(array ($path))) {
  167. // Install failed, rollback changes
  168. $this->parent->abort(JText::_('Component').' '.JText::_('Install').': '.JText::_('Could not copy PHP install file.'));
  169. return false;
  170. }
  171. }
  172. $this->set('install.script', $installScriptElement->data());
  173. }
  174. // If there is an uninstall file, lets copy it.
  175. $uninstallScriptElement =& $this->manifest->getElementByPath('uninstallfile');
  176. if (is_a($uninstallScriptElement, 'JSimpleXMLElement')) {
  177. // Make sure it hasn't already been copied (this would be an error in the xml install file)
  178. if (!file_exists($this->parent->getPath('extension_administrator').DS.$uninstallScriptElement->data()))
  179. {
  180. $path['src'] = $this->parent->getPath('source').DS.$uninstallScriptElement->data();
  181. $path['dest'] = $this->parent->getPath('extension_administrator').DS.$uninstallScriptElement->data();
  182. if (!$this->parent->copyFiles(array ($path))) {
  183. // Install failed, rollback changes
  184. $this->parent->abort(JText::_('Component').' '.JText::_('Install').': '.JText::_('Could not copy PHP uninstall file.'));
  185. return false;
  186. }
  187. }
  188. }
  189. /**
  190. * ---------------------------------------------------------------------------------------------
  191. * Database Processing Section
  192. * ---------------------------------------------------------------------------------------------
  193. */
  194. /*
  195. * Let's run the install queries for the component
  196. * If backward compatibility is required - run queries in xml file
  197. * If Joomla 1.5 compatible, with discreet sql files - execute appropriate
  198. * file for utf-8 support or non-utf-8 support
  199. */
  200. $result = $this->parent->parseQueries($this->manifest->getElementByPath('install/queries'));
  201. if ($result === false) {
  202. // Install failed, rollback changes
  203. $this->parent->abort(JText::_('Component').' '.JText::_('Install').': '.JText::_('SQL Error')." ".$db->stderr(true));
  204. return false;
  205. } elseif ($result === 0) {
  206. // no backward compatibility queries found - try for Joomla 1.5 type queries
  207. // second argument is the utf compatible version attribute
  208. $utfresult = $this->parent->parseSQLFiles($this->manifest->getElementByPath('install/sql'));
  209. if ($utfresult === false) {
  210. // Install failed, rollback changes
  211. $this->parent->abort(JText::_('Component').' '.JText::_('Install').': '.JText::_('SQLERRORORFILE')." ".$db->stderr(true));
  212. return false;
  213. }
  214. }
  215. // Time to build the admin menus
  216. $this->_buildAdminMenus();
  217. /**
  218. * ---------------------------------------------------------------------------------------------
  219. * Custom Installation Script Section
  220. * ---------------------------------------------------------------------------------------------
  221. */
  222. /*
  223. * If we have an install script, lets include it, execute the custom
  224. * install method, and append the return value from the custom install
  225. * method to the installation message.
  226. */
  227. if ($this->get('install.script')) {
  228. if (is_file($this->parent->getPath('extension_administrator').DS.$this->get('install.script'))) {
  229. ob_start();
  230. ob_implicit_flush(false);
  231. require_once ($this->parent->getPath('extension_administrator').DS.$this->get('install.script'));
  232. if (function_exists('com_install')) {
  233. if (com_install() === false) {
  234. $this->parent->abort(JText::_('Component').' '.JText::_('Install').': '.JText::_('Custom install routine failure'));
  235. return false;
  236. }
  237. }
  238. $msg = ob_get_contents();
  239. ob_end_clean();
  240. if ($msg != '') {
  241. $this->parent->set('extension.message', $msg);
  242. }
  243. }
  244. }
  245. /**
  246. * ---------------------------------------------------------------------------------------------
  247. * Finalization and Cleanup Section
  248. * ---------------------------------------------------------------------------------------------
  249. */
  250. // Lastly, we will copy the manifest file to its appropriate place.
  251. if (!$this->parent->copyManifest()) {
  252. // Install failed, rollback changes
  253. $this->parent->abort(JText::_('Component').' '.JText::_('Install').': '.JText::_('Could not copy setup file'));
  254. return false;
  255. }
  256. return true;
  257. }
  258. /**
  259. * Custom uninstall method for components
  260. *
  261. * @access public
  262. * @param int $cid The id of the component to uninstall
  263. * @param int $clientId The id of the client (unused)
  264. * @return mixed Return value for uninstall method in component uninstall file
  265. * @since 1.0
  266. */
  267. function uninstall($id, $clientId)
  268. {
  269. // Initialize variables
  270. $db =& $this->parent->getDBO();
  271. $row = null;
  272. $retval = true;
  273. // First order of business will be to load the component object table from the database.
  274. // This should give us the necessary information to proceed.
  275. $row = & JTable::getInstance('component');
  276. if ( !$row->load((int) $id) ) {
  277. JError::raiseWarning(100, JText::_('ERRORUNKOWNEXTENSION'));
  278. return false;
  279. }
  280. // Is the component we are trying to uninstall a core one?
  281. // Because that is not a good idea...
  282. if ($row->iscore) {
  283. JError::raiseWarning(100, JText::_('Component').' '.JText::_('Uninstall').': '.JText::sprintf('WARNCORECOMPONENT', $row->name)."<br />".JText::_('WARNCORECOMPONENT2'));
  284. return false;
  285. }
  286. // Get the admin and site paths for the component
  287. $this->parent->setPath('extension_administrator', JPath::clean(JPATH_ADMINISTRATOR.DS.'components'.DS.$row->option));
  288. $this->parent->setPath('extension_site', JPath::clean(JPATH_SITE.DS.'components'.DS.$row->option));
  289. /**
  290. * ---------------------------------------------------------------------------------------------
  291. * Manifest Document Setup Section
  292. * ---------------------------------------------------------------------------------------------
  293. */
  294. // Find and load the XML install file for the component
  295. $this->parent->setPath('source', $this->parent->getPath('extension_administrator'));
  296. // Get the package manifest objecct
  297. $manifest =& $this->parent->getManifest();
  298. if (!is_a($manifest, 'JSimpleXML')) {
  299. // Make sure we delete the folders if no manifest exists
  300. JFolder::delete($this->parent->getPath('extension_administrator'));
  301. JFolder::delete($this->parent->getPath('extension_site'));
  302. // Remove the menu
  303. $this->_removeAdminMenus($row);
  304. // Raise a warning
  305. JError::raiseWarning(100, JText::_('ERRORREMOVEMANUALLY'));
  306. // Return
  307. return false;
  308. }
  309. // Get the root node of the manifest document
  310. $this->manifest =& $manifest->document;
  311. /**
  312. * ---------------------------------------------------------------------------------------------
  313. * Custom Uninstallation Script Section
  314. * ---------------------------------------------------------------------------------------------
  315. */
  316. // Now lets load the uninstall file if there is one and execute the uninstall function if it exists.
  317. $uninstallfileElement =& $this->manifest->getElementByPath('uninstallfile');
  318. if (is_a($uninstallfileElement, 'JSimpleXMLElement')) {
  319. // Element exists, does the file exist?
  320. if (is_file($this->parent->getPath('extension_administrator').DS.$uninstallfileElement->data())) {
  321. ob_start();
  322. ob_implicit_flush(false);
  323. require_once ($this->parent->getPath('extension_administrator').DS.$uninstallfileElement->data());
  324. if (function_exists('com_uninstall')) {
  325. if (com_uninstall() === false) {
  326. JError::raiseWarning(100, JText::_('Component').' '.JText::_('Uninstall').': '.JText::_('Custom Uninstall script unsuccessful'));
  327. $retval = false;
  328. }
  329. }
  330. $msg = ob_get_contents();
  331. ob_end_clean();
  332. if ($msg != '') {
  333. $this->parent->set('extension.message', $msg);
  334. }
  335. }
  336. }
  337. /**
  338. * ---------------------------------------------------------------------------------------------
  339. * Database Processing Section
  340. * ---------------------------------------------------------------------------------------------
  341. */
  342. /*
  343. * Let's run the uninstall queries for the component
  344. * If backward compatibility is required - run queries in xml file
  345. * If Joomla 1.5 compatible, with discreet sql files - execute appropriate
  346. * file for utf-8 support or non-utf support
  347. */
  348. $result = $this->parent->parseQueries($this->manifest->getElementByPath('uninstall/queries'));
  349. if ($result === false) {
  350. // Install failed, rollback changes
  351. JError::raiseWarning(100, JText::_('Component').' '.JText::_('Uninstall').': '.JText::_('SQL Error')." ".$db->stderr(true));
  352. $retval = false;
  353. } elseif ($result === 0) {
  354. // no backward compatibility queries found - try for Joomla 1.5 type queries
  355. // second argument is the utf compatible version attribute
  356. $utfresult = $this->parent->parseSQLFiles($this->manifest->getElementByPath('uninstall/sql'));
  357. if ($utfresult === false) {
  358. // Install failed, rollback changes
  359. JError::raiseWarning(100, JText::_('Component').' '.JText::_('Uninstall').': '.JText::_('SQLERRORORFILE')." ".$db->stderr(true));
  360. $retval = false;
  361. }
  362. }
  363. $this->_removeAdminMenus($row);
  364. /**
  365. * ---------------------------------------------------------------------------------------------
  366. * Filesystem Processing Section
  367. * ---------------------------------------------------------------------------------------------
  368. */
  369. // Let's remove language files and media in the JROOT/images/ folder that are
  370. // associated with the component we are uninstalling
  371. $this->parent->removeFiles($this->manifest->getElementByPath('media'));
  372. $this->parent->removeFiles($this->manifest->getElementByPath('languages'));
  373. $this->parent->removeFiles($this->manifest->getElementByPath('administration/languages'), 1);
  374. // Now we need to delete the installation directories. This is the final step in uninstalling the component.
  375. if (trim($row->option)) {
  376. // Delete the component site directory
  377. if (is_dir($this->parent->getPath('extension_site'))) {
  378. if (!JFolder::delete($this->parent->getPath('extension_site'))) {
  379. JError::raiseWarning(100, JText::_('Component').' '.JText::_('Uninstall').': '.JText::_('Unable to remove the component site directory'));
  380. $retval = false;
  381. }
  382. }
  383. // Delete the component admin directory
  384. if (is_dir($this->parent->getPath('extension_administrator'))) {
  385. if (!JFolder::delete($this->parent->getPath('extension_administrator'))) {
  386. JError::raiseWarning(100, JText::_('Component').' '.JText::_('Uninstall').': '.JText::_('Unable to remove the component admin directory'));
  387. $retval = false;
  388. }
  389. }
  390. return $retval;
  391. } else {
  392. // No component option defined... cannot delete what we don't know about
  393. JError::raiseWarning(100, 'Component Uninstall: Option field empty, cannot remove files');
  394. return false;
  395. }
  396. }
  397. /**
  398. * Method to build menu database entries for a component
  399. *
  400. * @access private
  401. * @return boolean True if successful
  402. * @since 1.5
  403. */
  404. function _buildAdminMenus()
  405. {
  406. // Get database connector object
  407. $db =& $this->parent->getDBO();
  408. // Initialize variables
  409. $option = strtolower("com_".str_replace(" ", "", $this->get('name')));
  410. // If a component exists with this option in the table than we don't need to add menus
  411. $query = 'SELECT id' .
  412. ' FROM #__components' .
  413. ' WHERE `option` = '.$db->Quote($option);
  414. $db->setQuery($query);
  415. $exists = $db->loadResult();
  416. // Check if menu items exist
  417. if ($exists) {
  418. // Don't do anything if overwrite has not been enabled
  419. if ( ! $this->parent->getOverwrite() ) {
  420. return true;
  421. }
  422. // Remove existing menu items if overwrite has been enabled
  423. if ( $option ) {
  424. $sql = 'DELETE FROM #__components WHERE `option` = '.$db->Quote($option);
  425. $db->setQuery($sql);
  426. if (!$db->query()) {
  427. JError::raiseWarning(100, JText::_('Component').' '.JText::_('Install').': '.$db->stderr(true));
  428. }
  429. }
  430. }
  431. // Ok, now its time to handle the menus. Start with the component root menu, then handle submenus.
  432. $menuElement = & $this->adminElement->getElementByPath('menu');
  433. if (is_a($menuElement, 'JSimpleXMLElement')) {
  434. $db_name = $menuElement->data();
  435. $db_link = "option=".$option;
  436. $db_menuid = 0;
  437. $db_parent = 0;
  438. $db_admin_menu_link = "option=".$option;
  439. $db_admin_menu_alt = $menuElement->data();
  440. $db_option = $option;
  441. $db_ordering = 0;
  442. $db_admin_menu_img = ($menuElement->attributes('img')) ? $menuElement->attributes('img') : 'js/ThemeOffice/component.png';
  443. $db_iscore = 0;
  444. $db_params = $this->parent->getParams();
  445. $db_enabled = 1;
  446. $query = 'INSERT INTO #__components' .
  447. ' VALUES( "", '.$db->Quote($db_name).', '.$db->Quote($db_link).', '.(int) $db_menuid.',' .
  448. ' '.(int) $db_parent.', '.$db->Quote($db_admin_menu_link).', '.$db->Quote($db_admin_menu_alt).',' .
  449. ' '.$db->Quote($db_option).', '.(int) $db_ordering.', '.$db->Quote($db_admin_menu_img).',' .
  450. ' '.(int) $db_iscore.', '.$db->Quote($db_params).', '.(int) $db_enabled.' )';
  451. $db->setQuery($query);
  452. if (!$db->query()) {
  453. // Install failed, rollback changes
  454. $this->parent->abort(JText::_('Component').' '.JText::_('Install').': '.$db->stderr(true));
  455. return false;
  456. }
  457. $menuid = $db->insertid();
  458. /*
  459. * Since we have created a menu item, we add it to the installation step stack
  460. * so that if we have to rollback the changes we can undo it.
  461. */
  462. $this->parent->pushStep(array ('type' => 'menu', 'id' => $menuid));
  463. } else {
  464. /*
  465. * No menu element was specified so lets first see if we have an admin menu entry for this component
  466. * if we do.. then we obviously don't want to create one -- we'll just attach sub menus to that one.
  467. */
  468. $query = 'SELECT id' .
  469. ' FROM #__components' .
  470. ' WHERE `option` = '.$db->Quote($option) .
  471. ' AND parent = 0';
  472. $db->setQuery($query);
  473. $menuid = $db->loadResult();
  474. if (!$menuid) {
  475. // No menu entry, lets just enter a component entry to the table.
  476. $db_name = $this->get('name');
  477. $db_link = "";
  478. $db_menuid = 0;
  479. $db_parent = 0;
  480. $db_admin_menu_link = "";
  481. $db_admin_menu_alt = $this->get('name');
  482. $db_option = $option;
  483. $db_ordering = 0;
  484. $db_admin_menu_img = "";
  485. $db_iscore = 0;
  486. $db_params = $this->parent->getParams();
  487. $db_enabled = 1;
  488. $query = 'INSERT INTO #__components' .
  489. ' VALUES( "", '.$db->Quote($db_name).', '.$db->Quote($db_link).', '.(int) $db_menuid.',' .
  490. ' '.(int) $db_parent.', '.$db->Quote($db_admin_menu_link).', '.$db->Quote($db_admin_menu_alt).',' .
  491. ' '.$db->Quote($db_option).', '.(int) $db_ordering.', '.$db->Quote($db_admin_menu_img).',' .
  492. ' '.(int) $db_iscore.', '.$db->Quote($db_params).', '.(int) $db_enabled.' )';
  493. $db->setQuery($query);
  494. if (!$db->query()) {
  495. // Install failed, rollback changes
  496. $this->parent->abort(JText::_('Component').' '.JText::_('Install').': '.$db->stderr(true));
  497. return false;
  498. }
  499. $menuid = $db->insertid();
  500. /*
  501. * Since we have created a menu item, we add it to the installation step stack
  502. * so that if we have to rollback the changes we can undo it.
  503. */
  504. $this->parent->pushStep(array ('type' => 'menu', 'id' => $menuid));
  505. }
  506. }
  507. /*
  508. * Process SubMenus
  509. */
  510. // Initialize submenu ordering value
  511. $ordering = 0;
  512. $submenu = $this->adminElement->getElementByPath('submenu');
  513. if (!is_a($submenu, 'JSimpleXMLElement') || !count($submenu->children())) {
  514. return true;
  515. }
  516. foreach ($submenu->children() as $child)
  517. {
  518. if (is_a($child, 'JSimpleXMLElement') && $child->name() == 'menu') {
  519. $com =& JTable::getInstance('component');
  520. $com->name = $child->data();
  521. $com->link = '';
  522. $com->menuid = 0;
  523. $com->parent = $menuid;
  524. $com->iscore = 0;
  525. $com->admin_menu_alt = $child->data();
  526. $com->option = $option;
  527. $com->ordering = $ordering ++;
  528. // Set the sub menu link
  529. if ($child->attributes("link")) {
  530. $com->admin_menu_link = str_replace('&amp;', '&', $child->attributes("link"));
  531. } else {
  532. $request = array();
  533. if ($child->attributes('act')) {
  534. $request[] = 'act='.$child->attributes('act');
  535. }
  536. if ($child->attributes('task')) {
  537. $request[] = 'task='.$child->attributes('task');
  538. }
  539. if ($child->attributes('controller')) {
  540. $request[] = 'controller='.$child->attributes('controller');
  541. }
  542. if ($child->attributes('view')) {
  543. $request[] = 'view='.$child->attributes('view');
  544. }
  545. if ($child->attributes('layout')) {
  546. $request[] = 'layout='.$child->attributes('layout');
  547. }
  548. if ($child->attributes('sub')) {
  549. $request[] = 'sub='.$child->attributes('sub');
  550. }
  551. $qstring = (count($request)) ? '&'.implode('&',$request) : '';
  552. $com->admin_menu_link = "option=".$option.$qstring;
  553. }
  554. // Set the sub menu image
  555. if ($child->attributes("img")) {
  556. $com->admin_menu_img = $child->attributes("img");
  557. } else {
  558. $com->admin_menu_img = "js/ThemeOffice/component.png";
  559. }
  560. // Store the submenu
  561. if (!$com->store()) {
  562. // Install failed, rollback changes
  563. $this->parent->abort(JText::_('Component').' '.JText::_('Install').': '.JText::_('SQL Error')." ".$db->stderr(true));
  564. return false;
  565. }
  566. /*
  567. * Since we have created a menu item, we add it to the installation step stack
  568. * so that if we have to rollback the changes we can undo it.
  569. */
  570. $this->parent->pushStep(array ('type' => 'menu', 'id' => $com->id));
  571. }
  572. }
  573. }
  574. /**
  575. * Method to remove admin menu references to a component
  576. *
  577. * @access private
  578. * @param object $component Component table object
  579. * @return boolean True if successful
  580. * @since 1.5
  581. */
  582. function _removeAdminMenus(&$row)
  583. {
  584. // Get database connector object
  585. $db =& $this->parent->getDBO();
  586. $retval = true;
  587. // Delete the submenu items
  588. $sql = 'DELETE ' .
  589. ' FROM #__components ' .
  590. 'WHERE parent = '.(int)$row->id;
  591. $db->setQuery($sql);
  592. if (!$db->query()) {
  593. JError::raiseWarning(100, JText::_('Component').' '.JText::_('Uninstall').': '.$db->stderr(true));
  594. $retval = false;
  595. }
  596. // Next, we will delete the component object
  597. if (!$row->delete($row->id)) {
  598. JError::raiseWarning(100, JText::_('Component').' '.JText::_('Uninstall').': '.JText::_('Unable to delete the component from the database'));
  599. $retval = false;
  600. }
  601. return $retval;
  602. }
  603. /**
  604. * Custom rollback method
  605. * - Roll back the component menu item
  606. *
  607. * @access public
  608. * @param array $arg Installation step to rollback
  609. * @return boolean True on success
  610. * @since 1.5
  611. */
  612. function _rollback_menu($arg)
  613. {
  614. // Get database connector object
  615. $db =& $this->parent->getDBO;
  616. // Remove the entry from the #__components table
  617. $query = 'DELETE ' .
  618. ' FROM `#__components` ' .
  619. ' WHERE id='.(int)$arg['id'];
  620. $db->setQuery($query);
  621. return ($db->query() !== false);
  622. }
  623. }