PageRenderTime 61ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/pasamio/jhttprequest
PHP | 1741 lines | 958 code | 304 blank | 479 comment | 217 complexity | e40c9a9273ea01ad0f5f44f9525da811 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.1

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

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

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