PageRenderTime 56ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

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

https://github.com/reechalee/joomla1.6
PHP | 1743 lines | 958 code | 304 blank | 481 comment | 217 complexity | 545c9ecb1a87a5ae114d9debbd14661c MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause, JSON

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

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

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