/** * Action to execute queries from sample data file * * @return void */ public function installDataAction() { try { // Create a backup of Joomla database $this->_backupDatabase(); // Initialize variables $config = JFactory::getConfig(); $tmpPath = $config->get('tmp_path'); $xmlFiles = glob("{$tmpPath}/{$this->template['name']}_sampledata/*.xml"); if (empty($xmlFiles)) { throw new Exception(JText::_('JSN_TPLFW_ERROR_CANNOT_EXTRACT_SAMPLE_DATA_PACKAGE')); } // Load XML document $xml = simplexml_load_file(current($xmlFiles)); $version = (string) $xml['version']; $joomla_ver = (string) $xml['joomla-version']; // Compare versions $templateVersion = JSNTplHelper::getTemplateVersion($this->template['name']); $joomlaVersion = new JVersion(); if (version_compare($templateVersion, $version, '<')) { throw new Exception(JText::sprintf('JSN_TPLFW_ERROR_SAMPLE_DATA_OUT_OF_DATED', $templateVersion), 99); } if (!empty($joomla_ver) and version_compare($joomlaVersion->getShortVersion(), $joomla_ver, '<')) { throw new Exception(JText::sprintf('JSN_TPLFW_ERROR_JOOMLA_OUT_OF_DATE', $joomlaVersion->getShortVersion()), 99); } $thirdComponents = array(); $thirdComponentErrors = array(); // Looping to each extension type=component to get information and dependencies foreach ($xml->xpath('//extension[@author="3rd_party"]') as $component) { if (isset($component['author']) && $component['author'] == '3rd_party') { $attrs = (array) $component->attributes(); $attrs = $attrs['@attributes']; $componentType = (string) $attrs['type']; $namePrefix = array('component' => 'com_', 'module' => 'mod_'); $componentName = isset($namePrefix[(string) $attrs['type']]) ? $namePrefix[$componentType] . $attrs['name'] : (string) $attrs['name']; $state = $this->_getExtensionState($componentName, (string) $attrs['version'], true); $thirdComponents[] = array('id' => $attrs['name'], 'state' => $state, 'full_name' => (string) $attrs['full_name'], 'version' => (string) $attrs['version'], 'type' => $componentType); } } if (count($thirdComponents)) { foreach ($thirdComponents as $thirdComponent) { if ($thirdComponent['state'] == 'install') { $thirdComponentErrors[] = JText::sprintf('JSN_TPLFW_ERROR_THIRD_EXTENSION_NOT_INSTALLED', strtoupper($thirdComponent['full_name']) . ' ' . $thirdComponent['type'], $thirdComponent['version']); } elseif ($thirdComponent['state'] == 'update') { $thirdComponentErrors[] = JText::sprintf('JSN_TPLFW_ERROR_THIRD_EXTENSION_NEED_TO_INSTALLED', strtoupper($thirdComponent['full_name']) . ' ' . $thirdComponent['type'], $thirdComponent['version']); } elseif ($thirdComponent['state'] == 'unsupported') { $thirdComponentErrors[] = JText::sprintf('JSN_TPLFW_ERROR_THIRD_EXTENSION_NOT_SUPPORTED', strtoupper($thirdComponent['full_name']) . ' ' . $thirdComponent['type'], $thirdComponent['version']); } else { //do nothing } } } if (count($thirdComponentErrors)) { $strThirdComponentError = '<ul>'; foreach ($thirdComponentErrors as $thirdComponentError) { $strThirdComponentError .= '<li>' . $thirdComponentError . '</li>'; } $strThirdComponentError .= '</ul>'; throw new Exception(JText::sprintf('JSN_TPLFW_ERROR_THIRD_EXTENSION', $strThirdComponentError), 99); } // Temporary backup data $this->_backupThirdPartyModules(); $this->_backupThirdPartyAdminModules(); $this->_backupThirdPartyMenus(); // Start transaction before manipulate database $this->dbo->transactionStart(); // Delete admin modules $this->_deleteThirdPartyAdminModules(); // Disable execution timeout if (!JSNTplHelper::isDisabledFunction('set_time_limit')) { set_time_limit(0); } $attentions = array(); // Loop each extension to execute queries foreach ($xml->xpath('//extension') as $extension) { if (isset($extension['author']) && $extension['author'] == 'joomlashine') { $extensionType = (string) $extension['type']; $namePrefix = array('component' => 'com_', 'module' => 'mod_'); $extensionName = isset($namePrefix[(string) $extension['type']]) ? $namePrefix[$extensionType] . $extension['name'] : (string) $extension['name']; // Check if JoomlaShine extension is installed $canInstall = JSNTplHelper::isInstalledExtension($extensionName); if ($canInstall == false and $extensionType == 'component') { // Add to attention list when extension is not installed $attentions[] = array('id' => (string) $extension['name'], 'name' => (string) $extension['description'], 'url' => (string) $extension['producturl']); } } else { $canInstall = true; $extensionName = 'com_' . (string) $extension['name']; } if ($canInstall === true) { // Get sample data queries if ($queries = $extension->xpath("task[@name=\"dbinstall\"]/parameters/parameter") and @count($queries)) { // Execute sample data queries foreach ($queries as $query) { // Find remote assets then download to local system if (preg_match_all('#(http://demo.joomlashine.com/[^\\s\\t\\r\\n]+/media/joomlashine/)[^\\s\\t\\r\\n]+\\.(js|css|bmp|gif|ico|jpg|png|svg|ttf|otf|eot|woff)#', $query, $matches, PREG_SET_ORDER)) { foreach ($matches as $match) { $keepAsIs = false; if (!isset($this->mediaFolder)) { // Detect a writable folder to store demo assets foreach (array('media', 'cache', 'tmp') as $folder) { $folder = JPATH_ROOT . "/{$folder}"; if (is_dir($folder) and is_writable($folder) and JFolder::create("{$folder}/joomlashine")) { $this->mediaFolder = "{$folder}/joomlashine"; break; } } } if (isset($this->mediaFolder)) { // Generate path to store demo asset $mediaFile = str_replace($match[1], "{$this->mediaFolder}/", $match[0]); // Download demo asset only once if (!is_file($mediaFile)) { try { JSNTplHttpRequest::get($match[0], $mediaFile); } catch (Exception $e) { $keepAsIs = true; } } // Alter sample data query if (!$keepAsIs) { $query = str_replace($match[0], str_replace(JPATH_ROOT . '/', '', $mediaFile), $query); } } } } // Execute query $this->dbo->setQuery((string) $query); if (!$this->dbo->{$this->queryMethod}()) { throw new Exception($this->dbo->getErrorMsg()); } } } } } // Restore backed up data $this->_restoreThirdPartyData(); $this->_rebuildMenus(); // Disable default template $q = $this->dbo->getQuery(true); $q->update('#__template_styles'); $q->set('home = 0'); $q->where('client_id = 0'); $q->where('home = 1'); $this->dbo->setQuery($q); if (!$this->dbo->{$this->queryMethod}()) { throw new Exception($this->dbo->getErrorMsg()); } // Set installed template the default one $q = $this->dbo->getQuery(true); $q->update('#__template_styles'); $q->set('home = 1'); $q->where('id = ' . (int) $this->request->getInt('styleId')); $this->dbo->setQuery($q); if (!$this->dbo->{$this->queryMethod}()) { throw new Exception($this->dbo->getErrorMsg()); } // Commit database change $this->dbo->transactionCommit(); // Clean up temporary data JInstallerHelper::cleanupInstall("{$tmpPath}/{$this->template['name']}_sampledata.zip", "{$tmpPath}/{$this->template['name']}_sampledata"); // Clean up assets table for extension that is not installed if (count($attentions)) { foreach ($attentions as $attention) { $this->_cleanExtensionAssets('com_' . $attention['id']); } } // Set final response $this->setResponse(array('attention' => $attentions)); } catch (Exception $e) { throw $e; } }
/** * Clean up junk data related to the missing component. * * @param string $name The component name. * @param array $modules Additional modules to be removed. * @param array $plugins Additional plugins to be removed. * * @return void */ private function _cleanJunkData($name, $modules = null, $plugins = null) { // Only clean-up junk data if component is really missing. if (!JSNTplHelper::isInstalledExtension($name)) { // Get all menu items associated with the missing component. $q = $this->dbo->getQuery(true); $q->select('id')->from('#__menu')->where("type = 'component'"); $q->where("link LIKE '%option=" . $name . "%'"); $this->dbo->setQuery($q); $items = $this->dbo->loadColumn(); if (count($items)) { // Get all modules associated with all menu items of the missing component. $q = $this->dbo->getQuery(true); $q->select('moduleid')->from('#__modules_menu')->where('menuid IN (' . implode(', ', $items) . ')'); $this->dbo->setQuery($q); $mods = $this->dbo->loadColumn(); // Clean up menu table. $q = $this->dbo->getQuery(true); $q->delete('#__menu')->where('id IN (' . implode(', ', $items) . ')'); $this->dbo->setQuery($q); if (!$this->dbo->{$this->queryMethod}()) { throw new Exception($this->dbo->getErrorMsg()); } // Clean up menu item alias also. $q = $this->dbo->getQuery(true); $q->delete('#__menu')->where("type = 'alias'")->where('(params LIKE \'%"aliasoptions":"' . implode('"%\' OR params LIKE \'%"aliasoptions":"', $items) . '"%\')'); $this->dbo->setQuery($q); if (!$this->dbo->{$this->queryMethod}()) { throw new Exception($this->dbo->getErrorMsg()); } // Clean up module menu mapping table. $q = $this->dbo->getQuery(true); $q->delete('#__modules_menu')->where('menuid IN (' . implode(', ', $items) . ')'); $this->dbo->setQuery($q); if (!$this->dbo->{$this->queryMethod}()) { throw new Exception($this->dbo->getErrorMsg()); } } if (isset($mods) && count($mods)) { // Make sure queried modules does not associate with menu items of other component. $q = $this->dbo->getQuery(true); $q->select('moduleid')->from('#__modules_menu')->where('moduleid IN (' . implode(', ', $mods) . ')'); $this->dbo->setQuery($q); if ($items = $this->dbo->loadColumn()) { $mods = array_diff($mods, $items); } // Clean up modules table. if (count($mods)) { $q = $this->dbo->getQuery(true); $q->delete('#__modules')->where('id IN (' . implode(', ', $mods) . ')'); $this->dbo->setQuery($q); if (!$this->dbo->{$this->queryMethod}()) { throw new Exception($this->dbo->getErrorMsg()); } } } // Clean up modules associated with the missing component but not associated with its menu items. $q = $this->dbo->getQuery(true); $q->delete('#__modules')->where("params LIKE '%\"moduleclass_sfx\":\"%jsn-demo-module-for-{$name}\"%'"); $this->dbo->setQuery($q); if (!$this->dbo->{$this->queryMethod}()) { throw new Exception($this->dbo->getErrorMsg()); } // Clean up assets table. $q = $this->dbo->getQuery(true); $q->delete('#__assets')->where('name = ' . $q->quote($name)); $this->dbo->setQuery($q); if (!$this->dbo->{$this->queryMethod}()) { throw new Exception($this->dbo->getErrorMsg()); } // Clean up extensions table. $q = $this->dbo->getQuery(true); $q->delete('#__extensions')->where('element = ' . $q->quote($name)); $this->dbo->setQuery($q); if (!$this->dbo->{$this->queryMethod}()) { throw new Exception($this->dbo->getErrorMsg()); } } // Clean up additional modules if specified. if ($modules && @count($modules)) { foreach ($modules as $module) { // Only clean-up junk data if module is really missing. if (!@is_dir(JPATH_ROOT . '/modules/' . (string) $module)) { // Clean up modules table. $q = $this->dbo->getQuery(true); $q->delete('#__modules')->where('module = ' . $q->quote((string) $module)); $this->dbo->setQuery($q); if (!$this->dbo->{$this->queryMethod}()) { throw new Exception($this->dbo->getErrorMsg()); } // Clean up extensions table. $q = $this->dbo->getQuery(true); $q->delete('#__extensions')->where("type = 'module'"); $q->where('element = ' . $q->quote((string) $module)); $this->dbo->setQuery($q); if (!$this->dbo->{$this->queryMethod}()) { throw new Exception($this->dbo->getErrorMsg()); } } } } // Clean up additional plugins if specified. if ($plugins && @count($plugins)) { foreach ($plugins as $plugin) { // Only clean-up junk data if plugin is really missing. if (!@is_dir(JPATH_ROOT . '/plugins/' . (string) $plugin['group'] . '/' . (string) $plugin)) { // Clean up extensions table. $q = $this->dbo->getQuery(true); $q->delete('#__extensions')->where("type = 'plugin'"); $q->where('folder = ' . $q->quote((string) $plugin['group'])); $q->where('element = ' . $q->quote((string) $plugin)); $this->dbo->setQuery($q); if (!$this->dbo->{$this->queryMethod}()) { throw new Exception($this->dbo->getErrorMsg()); } } } } }