PageRenderTime 49ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/joomla/libraries/joomla/installer/adapters/module.php

https://github.com/reechalee/joomla1.6
PHP | 831 lines | 480 code | 125 blank | 226 comment | 77 complexity | c27075b2b27c42053c4e4280f7323347 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause, JSON
  1. <?php
  2. /**
  3. * @version $Id: module.php 20819 2011-02-21 21:53:18Z dextercowley $
  4. * @copyright Copyright (C) 2005 - 2011 Open Source Matters, Inc. All rights reserved.
  5. * @license GNU General Public License version 2 or later; see LICENSE.txt
  6. */
  7. // No direct access
  8. defined('JPATH_BASE') or die;
  9. jimport('joomla.base.adapterinstance');
  10. /**
  11. * Module installer
  12. *
  13. * @package Joomla.Framework
  14. * @subpackage Installer
  15. * @since 1.5
  16. */
  17. class JInstallerModule extends JAdapterInstance
  18. {
  19. /**
  20. * @var string install function routing
  21. */
  22. protected $route = 'Install';
  23. protected $manifest = null;
  24. protected $manifest_script = null;
  25. protected $name = null;
  26. protected $element = null;
  27. protected $scriptElement = null;
  28. /**
  29. * Custom loadLanguage method
  30. *
  31. * @param string $path the path where to find language files
  32. *
  33. * @since 1.6
  34. */
  35. public function loadLanguage($path=null)
  36. {
  37. $source = $this->parent->getPath('source');
  38. if (!$source) {
  39. $this->parent->setPath('source', ($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/modules/'.$this->parent->extension->element);
  40. }
  41. $this->manifest = $this->parent->getManifest();
  42. if ($this->manifest->files) {
  43. $element = $this->manifest->files;
  44. $extension = '';
  45. if (count($element->children())) {
  46. foreach ($element->children() as $file)
  47. {
  48. if ((string)$file->attributes()->module) {
  49. $extension = strtolower((string)$file->attributes()->module);
  50. break;
  51. }
  52. }
  53. }
  54. if ($extension) {
  55. $lang = JFactory::getLanguage();
  56. $source = $path ? $path : ($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/modules/'.$extension ;
  57. $folder = (string)$element->attributes()->folder;
  58. if ($folder && file_exists("$path/$folder")) {
  59. $source = "$path/$folder";
  60. }
  61. $client = (string)$this->manifest->attributes()->client;
  62. $lang->load($extension . '.sys', $source, null, false, false)
  63. || $lang->load($extension . '.sys', constant('JPATH_' . strtoupper($client)), null, false, false)
  64. || $lang->load($extension . '.sys', $source, $lang->getDefault(), false, false)
  65. || $lang->load($extension . '.sys', constant('JPATH_' . strtoupper($client)), $lang->getDefault(), false, false);
  66. }
  67. }
  68. }
  69. /**
  70. * Custom install method
  71. *
  72. * @return boolean True on success
  73. *
  74. * @since 1.5
  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 = (string)$this->manifest->name;
  89. $name = JFilterInput::getInstance()->clean($name, 'string');
  90. $this->set('name', $name);
  91. // Get the component description
  92. $description = (string)$this->manifest->description;
  93. if ($description) {
  94. $this->parent->set('message', JText::_($description));
  95. }
  96. else {
  97. $this->parent->set('message', '');
  98. }
  99. /**
  100. * ---------------------------------------------------------------------------------------------
  101. * Target Application Section
  102. * ---------------------------------------------------------------------------------------------
  103. */
  104. // Get the target application
  105. if ($cname = (string)$this->manifest->attributes()->client) {
  106. // Attempt to map the client to a base path
  107. jimport('joomla.application.helper');
  108. $client = JApplicationHelper::getClientInfo($cname, true);
  109. if ($client === false) {
  110. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_UNKNOWN_CLIENT', JText::_('JLIB_INSTALLER_'.$this->route), $client->name));
  111. return false;
  112. }
  113. $basePath = $client->path;
  114. $clientId = $client->id;
  115. }
  116. else {
  117. // No client attribute was found so we assume the site as the client
  118. $cname = 'site';
  119. $basePath = JPATH_SITE;
  120. $clientId = 0;
  121. }
  122. // Set the installation path
  123. $element = '';
  124. if (count($this->manifest->files->children())) {
  125. foreach ($this->manifest->files->children() as $file)
  126. {
  127. if ((string)$file->attributes()->module) {
  128. $element = (string)$file->attributes()->module;
  129. $this->set('element',$element);
  130. break;
  131. }
  132. }
  133. }
  134. if (!empty ($element)) {
  135. $this->parent->setPath('extension_root', $basePath.DS.'modules'.DS.$element);
  136. }
  137. else {
  138. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_INSTALL_NOFILE', JText::_('JLIB_INSTALLER_'.$this->route)));
  139. return false;
  140. }
  141. // Check to see if a module by the same name is already installed
  142. // If it is, then update the table because if the files aren't there
  143. // we can assume that it was (badly) uninstalled
  144. // If it isn't, add an entry to extensions
  145. $query = 'SELECT `extension_id`' .
  146. ' FROM `#__extensions` ' .
  147. ' WHERE element = '.$db->Quote($element) .
  148. ' AND client_id = '.(int)$clientId;
  149. $db->setQuery($query);
  150. try
  151. {
  152. $db->Query();
  153. }
  154. catch(JException $e)
  155. {
  156. // Install failed, roll back changes
  157. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_ROLLBACK', JText::_('JLIB_INSTALLER_'.$this->route), $db->stderr(true)));
  158. return false;
  159. }
  160. $id = $db->loadResult();
  161. /*
  162. * If the module directory already exists, then we will assume that the
  163. * module is already installed or another module is using that
  164. * directory.
  165. * Check that this is either an issue where its not overwriting or it is
  166. * set to upgrade anyway
  167. */
  168. if (file_exists($this->parent->getPath('extension_root')) && (!$this->parent->getOverwrite() || $this->parent->getUpgrade())) {
  169. // look for an update function or update tag
  170. $updateElement = $this->manifest->update;
  171. // upgrade manually set
  172. // update function available
  173. // update tag detected
  174. if ($this->parent->getUpgrade() || ($this->parent->manifestClass && method_exists($this->parent->manifestClass,'update')) || is_a($updateElement, 'JXMLElement')) {
  175. // force these one
  176. $this->parent->setOverwrite(true);
  177. $this->parent->setUpgrade(true);
  178. if ($id) { // if there is a matching extension mark this as an update; semantics really
  179. $this->route = 'Update';
  180. }
  181. }
  182. else if (!$this->parent->getOverwrite()) {
  183. // overwrite is set
  184. // we didn't have overwrite set, find an udpate function or find an update tag so lets call it safe
  185. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_INSTALL_DIRECTORY', JText::_('JLIB_INSTALLER_'.$this->route), $this->parent->getPath('extension_root')));
  186. return false;
  187. }
  188. }
  189. /**
  190. * ---------------------------------------------------------------------------------------------
  191. * Installer Trigger Loading
  192. * ---------------------------------------------------------------------------------------------
  193. */
  194. // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet)
  195. $this->scriptElement = $this->manifest->scriptfile;
  196. $manifestScript = (string)$this->manifest->scriptfile;
  197. if ($manifestScript) {
  198. $manifestScriptFile = $this->parent->getPath('source').DS.$manifestScript;
  199. if (is_file($manifestScriptFile)) {
  200. // load the file
  201. include_once $manifestScriptFile;
  202. }
  203. // Set the class name
  204. $classname = $element.'InstallerScript';
  205. if (class_exists($classname)) {
  206. // create a new instance
  207. $this->parent->manifestClass = new $classname($this);
  208. // and set this so we can copy it later
  209. $this->set('manifest_script', $manifestScript);
  210. // Note: if we don't find the class, don't bother to copy the file
  211. }
  212. }
  213. // run preflight if possible (since we know we're not an update)
  214. ob_start();
  215. ob_implicit_flush(false);
  216. if ($this->parent->manifestClass && method_exists($this->parent->manifestClass,'preflight')) {
  217. if ($this->parent->manifestClass->preflight($this->route, $this) === false) {
  218. // Install failed, rollback changes
  219. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_MOD_INSTALL_CUSTOM_INSTALL_FAILURE'));
  220. return false;
  221. }
  222. }
  223. $msg = ob_get_contents(); // create msg object; first use here
  224. ob_end_clean();
  225. /**
  226. * ---------------------------------------------------------------------------------------------
  227. * Filesystem Processing Section
  228. * ---------------------------------------------------------------------------------------------
  229. */
  230. // If the module directory does not exist, lets create it
  231. $created = false;
  232. if (!file_exists($this->parent->getPath('extension_root'))) {
  233. if (!$created = JFolder::create($this->parent->getPath('extension_root'))) {
  234. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_INSTALL_CREATE_DIRECTORY', JText::_('JLIB_INSTALLER_'.$this->route), $this->parent->getPath('extension_root')));
  235. return false;
  236. }
  237. }
  238. /*
  239. * Since we created the module directory and will want to remove it if
  240. * we have to roll back the installation, lets add it to the
  241. * installation step stack
  242. */
  243. if ($created) {
  244. $this->parent->pushStep(array ('type' => 'folder', 'path' => $this->parent->getPath('extension_root')));
  245. }
  246. // Copy all necessary files
  247. if ($this->parent->parseFiles($this->manifest->files, -1) === false) {
  248. // Install failed, roll back changes
  249. $this->parent->abort();
  250. return false;
  251. }
  252. // Parse optional tags
  253. $this->parent->parseMedia($this->manifest->media, $clientId);
  254. $this->parent->parseLanguages($this->manifest->languages, $clientId);
  255. // Parse deprecated tags
  256. $this->parent->parseFiles($this->manifest->images, -1);
  257. /**
  258. * ---------------------------------------------------------------------------------------------
  259. * Database Processing Section
  260. * ---------------------------------------------------------------------------------------------
  261. */
  262. $row = JTable::getInstance('extension');
  263. // Was there a module already installed with the same name?
  264. if ($id) {
  265. // load the entry and update the manifest_cache
  266. $row->load($id);
  267. $row->name = $this->get('name'); // update name
  268. $row->manifest_cache = $this->parent->generateManifestCache(); // update manifest
  269. if (!$row->store()) {
  270. // Install failed, roll back changes
  271. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_ROLLBACK', JText::_('JLIB_INSTALLER_'.$this->route), $db->stderr(true)));
  272. return false;
  273. }
  274. }
  275. else {
  276. $row->set('name', $this->get('name'));
  277. $row->set('type', 'module');
  278. $row->set('element', $this->get('element'));
  279. $row->set('folder', ''); // There is no folder for modules
  280. $row->set('enabled', 1);
  281. $row->set('protected', 0);
  282. $row->set('access', $clientId == 1 ? 2 : 0);
  283. $row->set('client_id', $clientId);
  284. $row->set('params', $this->parent->getParams());
  285. $row->set('custom_data', ''); // custom data
  286. $row->set('manifest_cache', $this->parent->generateManifestCache());
  287. if (!$row->store()) {
  288. // Install failed, roll back changes
  289. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_ROLLBACK', JText::_('JLIB_INSTALLER_'.$this->route), $db->stderr(true)));
  290. return false;
  291. }
  292. // set the insert id
  293. $row->extension_id = $db->insertid();
  294. // Since we have created a module item, we add it to the installation step stack
  295. // so that if we have to rollback the changes we can undo it.
  296. $this->parent->pushStep(array ('type' => 'extension', 'extension_id' => $row->extension_id));
  297. // Create unpublished module in jos_modules
  298. $module = JTable::getInstance('module');
  299. $module->set('title', $this->get('name'));
  300. $module->set('module', $this->get('element'));
  301. $module->set('access', '1');
  302. $module->set('showtitle', '1');
  303. $module->set('client_id', $clientId);
  304. $module->set('language', '*');
  305. $module->store();
  306. }
  307. /*
  308. * Let's run the queries for the module
  309. * If Joomla 1.5 compatible, with discreet sql files - execute appropriate
  310. * file for utf-8 support or non-utf-8 support
  311. */
  312. // try for Joomla 1.5 type queries
  313. // second argument is the utf compatible version attribute
  314. if (strtolower($this->route) == 'install') {
  315. $utfresult = $this->parent->parseSQLFiles($this->manifest->install->sql);
  316. if ($utfresult === false) {
  317. // Install failed, rollback changes
  318. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_INSTALL_SQL_ERROR', JText::_('JLIB_INSTALLER_'.$this->route), $db->stderr(true)));
  319. return false;
  320. }
  321. // Set the schema version to be the latest update version
  322. if ($this->manifest->update) {
  323. $this->parent->setSchemaVersion($this->manifest->update->schemas, $row->extension_id);
  324. }
  325. }
  326. else if (strtolower($this->route) == 'update') {
  327. if ($this->manifest->update) {
  328. $result = $this->parent->parseSchemaUpdates($this->manifest->update->schemas, $row->extension_id);
  329. if ($result === false) {
  330. // Install failed, rollback changes
  331. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_UPDATE_SQL_ERROR', $db->stderr(true)));
  332. return false;
  333. }
  334. }
  335. }
  336. // Start Joomla! 1.6
  337. ob_start();
  338. ob_implicit_flush(false);
  339. if ($this->parent->manifestClass && method_exists($this->parent->manifestClass,$this->route)) {
  340. if ($this->parent->manifestClass->{$this->route}($this) === false) {
  341. // Install failed, rollback changes
  342. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_MOD_INSTALL_CUSTOM_INSTALL_FAILURE'));
  343. return false;
  344. }
  345. }
  346. $msg .= ob_get_contents(); // append messages
  347. ob_end_clean();
  348. /**
  349. * ---------------------------------------------------------------------------------------------
  350. * Finalization and Cleanup Section
  351. * ---------------------------------------------------------------------------------------------
  352. */
  353. // Lastly, we will copy the manifest file to its appropriate place.
  354. if (!$this->parent->copyManifest(-1)) {
  355. // Install failed, rollback changes
  356. $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_MOD_INSTALL_COPY_SETUP'));
  357. return false;
  358. }
  359. // And now we run the postflight
  360. ob_start();
  361. ob_implicit_flush(false);
  362. if ($this->parent->manifestClass && method_exists($this->parent->manifestClass,'postflight')) {
  363. $this->parent->manifestClass->postflight($this->route, $this);
  364. }
  365. $msg .= ob_get_contents(); // append messages
  366. ob_end_clean();
  367. if ($msg != '') {
  368. $this->parent->set('extension_message', $msg);
  369. }
  370. return $row->get('extension_id');
  371. }
  372. /**
  373. * Custom update method
  374. * This is really a shell for the install system
  375. *
  376. * @return boolean True on success
  377. * @since 1.6
  378. */
  379. function update()
  380. {
  381. // set the overwrite setting
  382. $this->parent->setOverwrite(true);
  383. $this->parent->setUpgrade(true);
  384. // set the route for the install
  385. $this->route = 'Update';
  386. // go to install which handles updates properly
  387. return $this->install();
  388. }
  389. /**
  390. * Custom discover method
  391. *
  392. * @return array(JExtension) list of extensions available
  393. * @since 1.6
  394. */
  395. public function discover()
  396. {
  397. $results = Array();
  398. $site_list = JFolder::folders(JPATH_SITE.DS.'modules');
  399. $admin_list = JFolder::folders(JPATH_ADMINISTRATOR.DS.'modules');
  400. $site_info = JApplicationHelper::getClientInfo('site', true);
  401. $admin_info = JApplicationHelper::getClientInfo('administrator', true);
  402. foreach ($site_list as $module) {
  403. $manifest_details = JApplicationHelper::parseXMLInstallFile(JPATH_SITE."/modules/$module/$module.xml");
  404. $extension = JTable::getInstance('extension');
  405. $extension->set('type', 'module');
  406. $extension->set('client_id', $site_info->id);
  407. $extension->set('element', $module);
  408. $extension->set('name', $module);
  409. $extension->set('state', -1);
  410. $extension->set('manifest_cache', json_encode($manifest_details));
  411. $results[] = clone $extension;
  412. }
  413. foreach ($admin_list as $module) {
  414. $manifest_details = JApplicationHelper::parseXMLInstallFile(JPATH_ADMINISTRATOR."/modules/$module/$module.xml");
  415. $extension = JTable::getInstance('extension');
  416. $extension->set('type', 'module');
  417. $extension->set('client_id', $admin_info->id);
  418. $extension->set('element', $module);
  419. $extension->set('name', $module);
  420. $extension->set('state', -1);
  421. $extension->set('manifest_cache', json_encode($manifest_details));
  422. $results[] = clone $extension;
  423. }
  424. return $results;
  425. }
  426. /**
  427. * Custom discover_install method
  428. *
  429. * @param int $id The id of the extension to install (from #__discoveredextensions)
  430. *
  431. * @return void
  432. * @since 1.6
  433. */
  434. function discover_install()
  435. {
  436. // Modules are like templates, and are one of the easiest
  437. // If its not in the extensions table we just add it
  438. $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id);
  439. $manifestPath = $client->path . DS . 'modules'. DS . $this->parent->extension->element . DS . $this->parent->extension->element . '.xml';
  440. $this->parent->manifest = $this->parent->isManifest($manifestPath);
  441. $description = (string)$this->parent->manifest->description;
  442. if ($description) {
  443. $this->parent->set('message', JText::_($description));
  444. }
  445. else {
  446. $this->parent->set('message', '');
  447. }
  448. $this->parent->setPath('manifest', $manifestPath);
  449. $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest'));
  450. // TODO: Re-evaluate this; should we run installation triggers? postflight perhaps?
  451. $this->parent->extension->manifest_cache = json_encode($manifest_details);
  452. $this->parent->extension->state = 0;
  453. $this->parent->extension->name = $manifest_details['name'];
  454. $this->parent->extension->enabled = 1;
  455. $this->parent->extension->params = $this->parent->getParams();
  456. if ($this->parent->extension->store()) {
  457. return $this->parent->extension->get('extension_id');
  458. }
  459. else {
  460. JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_MOD_DISCOVER_STORE_DETAILS'));
  461. return false;
  462. }
  463. }
  464. /**
  465. * Refreshes the extension table cache
  466. * @return boolean result of operation, true if updated, false on failure
  467. * @since 1.6
  468. */
  469. public function refreshManifestCache()
  470. {
  471. $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id);
  472. $manifestPath = $client->path . DS . 'modules'. DS . $this->parent->extension->element . DS . $this->parent->extension->element . '.xml';
  473. $this->parent->manifest = $this->parent->isManifest($manifestPath);
  474. $this->parent->setPath('manifest', $manifestPath);
  475. $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest'));
  476. $this->parent->extension->manifest_cache = json_encode($manifest_details);
  477. $this->parent->extension->name = $manifest_details['name'];
  478. if ($this->parent->extension->store()) {
  479. return true;
  480. }
  481. else {
  482. JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_MOD_REFRESH_MANIFEST_CACHE'));
  483. return false;
  484. }
  485. }
  486. /**
  487. * Custom uninstall method
  488. *
  489. * @param int $id The id of the module to uninstall
  490. *
  491. * @return boolean True on success
  492. * @since 1.5
  493. */
  494. public function uninstall($id)
  495. {
  496. // Initialise variables.
  497. $row = null;
  498. $retval = true;
  499. $db = $this->parent->getDbo();
  500. // First order of business will be to load the module object table from the database.
  501. // This should give us the necessary information to proceed.
  502. $row = JTable::getInstance('extension');
  503. if (!$row->load((int) $id) || !strlen($row->element)) {
  504. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_ERRORUNKOWNEXTENSION'));
  505. return false;
  506. }
  507. // Is the module we are trying to uninstall a core one?
  508. // Because that is not a good idea...
  509. if ($row->protected) {
  510. JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_WARNCOREMODULE', $row->name));
  511. return false;
  512. }
  513. // Get the extension root path
  514. jimport('joomla.application.helper');
  515. $element = $row->element;
  516. $client = JApplicationHelper::getClientInfo($row->client_id);
  517. if ($client === false) {
  518. $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_UNKNOWN_CLIENT', $row->client_id));
  519. return false;
  520. }
  521. $this->parent->setPath('extension_root', $client->path.DS.'modules'.DS.$element);
  522. $this->parent->setPath('source', $this->parent->getPath('extension_root'));
  523. // Get the package manifest objecct
  524. // We do findManifest to avoid problem when uninstalling a list of extension: getManifest cache its manifest file
  525. $this->parent->findManifest();
  526. $this->manifest = $this->parent->getManifest();
  527. // Attempt to load the language file; might have uninstall strings
  528. $this->loadLanguage(($row->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/modules/'.$element);
  529. // If there is an manifest class file, lets load it
  530. $this->scriptElement = $this->manifest->scriptfile;
  531. $manifestScript = (string)$this->manifest->scriptfile;
  532. if ($manifestScript) {
  533. $manifestScriptFile = $this->parent->getPath('extension_root').DS.$manifestScript;
  534. if (is_file($manifestScriptFile)) {
  535. // load the file
  536. include_once $manifestScriptFile;
  537. }
  538. // Set the class name
  539. $classname = $element.'InstallerScript';
  540. if (class_exists($classname)) {
  541. // create a new instance
  542. $this->parent->manifestClass = new $classname($this);
  543. // and set this so we can copy it later
  544. $this->set('manifest_script', $manifestScript);
  545. // Note: if we don't find the class, don't bother to copy the file
  546. }
  547. }
  548. ob_start();
  549. ob_implicit_flush(false);
  550. // run uninstall if possible
  551. if ($this->parent->manifestClass && method_exists($this->parent->manifestClass,'uninstall')) {
  552. $this->parent->manifestClass->uninstall($this);
  553. }
  554. $msg = ob_get_contents();
  555. ob_end_clean();
  556. if (!($this->manifest instanceof JXMLElement)) {
  557. // Make sure we delete the folders
  558. JFolder::delete($this->parent->getPath('extension_root'));
  559. JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_INVALID_NOTFOUND_MANIFEST'));
  560. return false;
  561. }
  562. /*
  563. * Let's run the uninstall queries for the component
  564. * If Joomla 1.5 compatible, with discreet sql files - execute appropriate
  565. * file for utf-8 support or non-utf support
  566. */
  567. // try for Joomla 1.5 type queries
  568. // second argument is the utf compatible version attribute
  569. $utfresult = $this->parent->parseSQLFiles($this->manifest->uninstall->sql);
  570. if ($utfresult === false) {
  571. // Install failed, rollback changes
  572. JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_SQL_ERROR', $db->stderr(true)));
  573. $retval = false;
  574. }
  575. // Remove the schema version
  576. $query = $db->getQuery(true);
  577. $query->delete()->from('#__schemas')->where('extension_id = '. $row->extension_id);
  578. $db->setQuery($query);
  579. $db->Query();
  580. // Remove other files
  581. $this->parent->removeFiles($this->manifest->media);
  582. $this->parent->removeFiles($this->manifest->languages, $row->client_id);
  583. // Lets delete all the module copies for the type we are uninstalling
  584. $query = 'SELECT `id`' .
  585. ' FROM `#__modules`' .
  586. ' WHERE module = '.$db->Quote($row->element) .
  587. ' AND client_id = '.(int)$row->client_id;
  588. $db->setQuery($query);
  589. try
  590. {
  591. $modules = $db->loadResultArray();
  592. }
  593. catch(JException $e)
  594. {
  595. $modules = array();
  596. }
  597. // Do we have any module copies?
  598. if (count($modules))
  599. {
  600. // Ensure the list is sane
  601. JArrayHelper::toInteger($modules);
  602. $modID = implode(',', $modules);
  603. // Wipe out any items assigned to menus
  604. $query = 'DELETE' .
  605. ' FROM #__modules_menu' .
  606. ' WHERE moduleid IN ('.$modID.')';
  607. $db->setQuery($query);
  608. try
  609. {
  610. $db->query();
  611. }
  612. catch(JException $e)
  613. {
  614. JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_EXCEPTION', $db->stderr(true)));
  615. $retval = false;
  616. }
  617. // Wipe out any instances in the modules table
  618. $query = 'DELETE' .
  619. ' FROM #__modules' .
  620. ' WHERE id IN ('.$modID.')';
  621. $db->setQuery($query);
  622. try
  623. {
  624. $db->query();
  625. }
  626. catch (JException $e)
  627. {
  628. JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_EXCEPTION', $db->stderr(true)));
  629. $retval = false;
  630. }
  631. }
  632. // Now we will no longer need the module object, so lets delete it and free up memory
  633. $row->delete($row->extension_id);
  634. $query = 'DELETE FROM `#__modules` WHERE module = '.$db->Quote($row->element) . ' AND client_id = ' . $row->client_id;
  635. $db->setQuery($query);
  636. try
  637. {
  638. $db->Query(); // clean up any other ones that might exist as well
  639. }
  640. catch(JException $e)
  641. {
  642. //Ignore the error...
  643. }
  644. unset ($row);
  645. // Remove the installation folder
  646. if (!JFolder::delete($this->parent->getPath('extension_root'))) {
  647. // JFolder should raise an error
  648. $retval = false;
  649. }
  650. return $retval;
  651. }
  652. /**
  653. * Custom rollback method
  654. * - Roll back the menu item
  655. *
  656. * @param array $arg Installation step to rollback
  657. *
  658. * @return boolean True on success
  659. * @since 1.5
  660. */
  661. public function _rollback_menu($arg)
  662. {
  663. // Get database connector object
  664. $db = $this->parent->getDbo();
  665. // Remove the entry from the #__modules_menu table
  666. $query = 'DELETE' .
  667. ' FROM `#__modules_menu`' .
  668. ' WHERE moduleid='.(int)$arg['id'];
  669. $db->setQuery($query);
  670. try
  671. {
  672. return $db->query();
  673. }
  674. catch(JException $e)
  675. {
  676. return false;
  677. }
  678. }
  679. /**
  680. * Custom rollback method
  681. * - Roll back the module item
  682. *
  683. * @param array $arg Installation step to rollback
  684. *
  685. * @return boolean True on success
  686. * @since 1.5
  687. */
  688. public function _rollback_module($arg)
  689. {
  690. // Get database connector object
  691. $db = $this->parent->getDbo();
  692. // Remove the entry from the #__modules table
  693. $query = 'DELETE' .
  694. ' FROM `#__modules`' .
  695. ' WHERE id='.(int)$arg['id'];
  696. $db->setQuery($query);
  697. try
  698. {
  699. return $db->query();
  700. }
  701. catch(JException $e)
  702. {
  703. return false;
  704. }
  705. }
  706. }