File Manager

Current Directory: /home/astoriaah/www/old15/administrator/components/com_sh404sef
Viewing File: /home/astoriaah/www/old15/administrator/components/com_sh404sef/installation.script.php
<?php /** * sh404SEF - SEO extension for Joomla! * * @author Yannick Gaultier * @copyright (c) Yannick Gaultier 2014 * @package sh404SEF * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL * @version 4.4.4.1791 * @date 2014-07-01 */ // Security check to ensure this file is being included by a parent file. defined('_JEXEC') or die; /** * Installation/Uninstallation script * */ class Com_Sh404sefInstallerScript { const MIN_JOOMLA_VERSION = '2.5.6'; const MAX_JOOMLA_VERSION = '4'; private $_siteId = ''; private $_preserveConfigFolder = ''; private $_errorPageCatId = 0; private $_shlibVersion = ''; private $_skipInstall = array(); public function install($parent) { } public function uninstall($parent) { // save configuration try { $this->_definePaths(); $sh404sef = ShlDbHelper::selectObject('#__extensions', 'params', array('type' => 'component', 'element' => 'com_sh404sef')); $saved = $this->_shWriteExtensionConfig('com_sh404sef', array('sh404sefConfig' => $sh404sef->params)); if (!$saved) { JFactory::getApplication()->enqueueMessage('Error saving sh404SEF configuration to disk, configuration may be lost upon reinstallation'); } } catch (Exception $e){ JFactory::getApplication()->enqueueMessage('Error saving sh404SEF configuration to disk, configuration may be lost upon reinstallation'); } $this->_doUninstall($parent); } public function update($parent) { } public function preflight($route, $installer) { if ($route == 'install' || $route == 'update') { // check Joomla! version if (version_compare(JVERSION, self::MIN_JOOMLA_VERSION, '<') || version_compare(JVERSION, self::MAX_JOOMLA_VERSION, 'ge')) { JFactory::getApplication() ->enqueueMessage( sprintf('sh404SEF requires Joomla! version between %s and %s (you are using %s). Aborting installation', self::MIN_JOOMLA_VERSION, self::MAX_JOOMLA_VERSION, JVERSION), 'error'); return false; } // make sure resource manager is available, we'll need it during plugins installs if (!class_exists('ShlSystem_Resourcemanager')) { require_once $installer->getParent()->getPath('source') . '/admin/plugins/system/shlib/shl_packages/system/resourcemanager.php'; } // check authorization to install for shared resources $newVersionFile = $installer->getParent()->getPath('source') . '/admin/plugins/system/shlib/shlib.xml'; $this->_shlibVersion = ShlSystem_Resourcemanager::getXmlFileVersion($newVersionFile); $installCheckResult = ShlSystem_Resourcemanager::canInstall('shlib', $this->_shlibVersion); if ($installCheckResult->canInstall == 'no') { JFactory::getApplication() ->enqueueMessage( 'Cannot install sh404SEF: not allowed to install shLib version ' . $this->_shlibVersion . ': ' . $installCheckResult->reason, 'error'); } if ($installCheckResult->canInstall == 'skip') { $this->_shlibVersion = ''; $this->_skipInstall[] = 'shlib'; JFactory::getApplication() ->enqueueMessage('shLib: skipping install of shLib version ' . $this->_shlibVersion . ': ' . $installCheckResult->reason); } $canInstall = $installCheckResult->canInstall != 'no'; return $canInstall; } } public function postflight($type, $parent) { $this->_doInstallUpdate($parent); // installed a shared resource? register it with version if (!in_array('shlib', $this->_skipInstall)) { ShlSystem_Resourcemanager::registerResource('shlib', $this->_shlibVersion); } // register that we are now using shLib ShlSystem_Resourcemanager::register(array('resource' => 'shlib', 'context' => 'com_sh404sef', 'min_version' => '0.2.0')); // make sure the update site is appropriate $this->_processUpdateSite($type, $parent); // clear caches, in case cache handling or remote config has been modified $caches = array('sh404sef_updates', 'sh404sef_rconfig', 'sh404sef_analytics_auth', 'sh404sef_analytics'); foreach ($caches as $cacheName) { $cache = JFactory::getCache($cacheName); $cache->clean(); } } /** * Make sure the update site is correct when switching from * one edition to another. * Specifically, wipe out update site when going from an * edition that does auto-update to one that does not * (ie community to full or lite) * * @param unknown $type * @param unknown $parent * @return boolean */ private function _processUpdateSite($type, $parent) { // figure out if there's an update server $manifest = $parent->get('manifest'); $updateservers = $manifest->updateservers; $children = array(); if ($updateservers) { $children = $updateservers->children(); } // figure out the extension id try { $extensionId = (int) ShlDbHelper::selectResult('#__extensions', array('extension_id'), array('type' => 'component', 'element' => 'com_sh404sef')); } catch (Exception $e) { $extensionId = 0; } // no update site. We must make sure we wipe out // any existing update site. We use Joomla code for that if (!empty($extensionId)) { JPluginHelper::importPlugin('extension'); $dispatcher = ShlSystem_factory::dispatcher(); // Fire the onExtensionAfterInstall $result = null; $dispatcher->trigger('onExtensionAfterUninstall', array('installer' => clone $parent, 'eid' => $extensionId, 'result' => $result)); } return true; } // Implementation of install/uninstall scripts private function _doInstallUpdate($parent) { $this->_definePaths(); $this->_includeLibs(); // V 1.2.4.q Copy existing config file from /media to current component. Used to recover configuration when upgrading // V 1.2.4.s check if old file exists before deleting stub config file $oldConfigFile = $this->_preserveConfigFolder . 'sh404_upgrade_conf_' . $this->_siteId . '.php'; if (JFile::exists($oldConfigFile)) { // update old config files from VALID_MOS check to _JEXEC $config = JFile::read($oldConfigFile); if ($config && strpos($config, 'VALID_MOS') !== false) { $config = str_replace('VALID_MOS', '_JEXEC', $config); JFile::write($oldConfigFile, $config); // write it back } // now get back old config if (JFile::exists(JPATH_ADMINISTRATOR . '/components/com_sh404sef/config/config.sef.php')) { JFile::delete(JPATH_ADMINISTRATOR . '/components/com_sh404sef/config/config.sef.php'); } JFile::copy($oldConfigFile, JPATH_ADMINISTRATOR . '/components/com_sh404sef/config/config.sef.php'); } // restore black/white lists $folder = $this->_preserveConfigFolder . 'sh404_upgrade_conf_security'; if (JFolder::exists($folder)) { $fileList = JFolder::files($folder); if (!empty($fileList)) { foreach ($fileList as $file) { if (JFile::exists(JPATH_ADMINISTRATOR . '/components/com_sh404sef/security/' . $file)) { JFile::delete(JPATH_ADMINISTRATOR . '/components/com_sh404sef/security/' . $file); } JFile::copy($this->_preserveConfigFolder . 'sh404_upgrade_conf_security/' . $file, JPATH_ADMINISTRATOR . '/components/com_sh404sef/security/' . $file); } } } // if upgrading rather than installing from scratch, or after an uninstall // we must not copy back saved configuration files and log files // as this would overwrite up to date current ones // note that above we restored main config file and // security data files becomes blank files come // with the extension, so they'll be deleted in any case // and we have to restore them $shouldRestore = $this->_shShouldRestore(); if ($shouldRestore) { // restore log files $folder = $this->_preserveConfigFolder . 'sh404_upgrade_conf_logs'; if (JFolder::exists($folder)) { JFolder::copy($folder, JPATH_ROOT . '/logs/sh404sef', $path = '', $force = true); } // restore customized default params $oldCustomConfigFile = $this->_preserveConfigFolder . 'sh404_upgrade_conf_' . $this->_siteId . '.custom.php'; if (is_readable($oldCustomConfigFile) && filesize($oldCustomConfigFile) > 1000) { // update old config files from VALID_MOS check to _JEXEC $config = JFile::read($oldCustomConfigFile); if ($config && strpos($config, 'VALID_MOS') !== false) { $config = str_replace('VALID_MOS', '_JEXEC', $config); JFile::write($oldCustomConfigFile, $config); // write it back } if (JFile::exists(JPATH_ADMINISTRATOR . '/components/com_sh404sef/custom.sef.php')) { JFile::delete(JPATH_ADMINISTRATOR . '/components/com_sh404sef/custom.sef.php'); } $result = JFile::copy($oldCustomConfigFile, JPATH_ADMINISTRATOR . '/components/com_sh404sef/custom.sef.php'); } // read saved config $extFile = $this->_preserveConfigFolder . 'sh404_upgrade_conf' . '/com_sh404sef_' . $this->_siteId . '.php'; // remove previous if any if (JFile::exists($extFile)) { include_once $extFile; if(!empty($sh404sefConfig)) { // write it back into sh404sef config field try { ShlDbHelper::update('#__extensions', array('params' => $sh404sefConfig), array('type' => 'component', 'element' => 'com_sh404sef')); } catch (Exception $e) { JFactory::getApplication() ->enqueuemessage('Database error while restoring saved configuration. Config may be lost: ' . $e->getMessage()); } } } } // install plugins if (defined('SHLIB_ROOT_PATH')) { // trick of the day: we must fetch an instance of the db using the db helper // before installing the newest version of shLib system plugin. This will // force a decorated db instance to be created and stored, using the shlib // db class version that matches that of the shlib db helper class // As there was interface changes betwen shLib 0.1.x and 0.2.x, this prevents // "method not existing" errors when installing a newer version over an old one // make sure resource manager is available, we'll need it during plugins installs $db = ShlDbHelper::getInstance(); $status = $this->_shInstallPluginGroup('system'); } else { $this->_shInstallPluginGroup('system'); // shLib is not installed yet, let's make it available to us if (!JFile::exists(JPATH_ROOT . '/plugins/system/shlib/shlib.php')) { JFactory::getApplication() ->enqueuemessage('shLib was not installed properly, cannot continue. Please try uninstalling and installing again'); return false; } require_once JPATH_ROOT . '/plugins/system/shlib/shlib.php'; $config = array('type' => 'system', 'name' => 'shlib', 'params' => ''); if (version_compare(JVERSION, '3', 'ge')) { $dispatcher = JEventDispatcher::getInstance(); } else { $dispatcher = JDispatcher::getInstance(); } $shLibPlugin = new plgSystemShlib($dispatcher, $config); $shLibPlugin->onAfterInitialise(); $status = true; } if (!$status) { JFactory::getApplication() ->enqueuemessage('There was an error installing one or more system plugins. Please try uninstalling and installing again'); return; } $status = $this->_shInstallPluginGroup('sh404sefcore'); if (!$status) { JFactory::getApplication() ->enqueuemessage('There was an error installing one or more sh404SEF core plugins. Please try uninstalling and installing again'); return; } $status = $this->_shInstallPluginGroup('installer'); if (!$status) { JFactory::getApplication() ->enqueuemessage('There was an error installing one or more sh404SEF installer plugins. Please try uninstalling and installing again'); return; } $status = $this->_shInstallPluginGroup('sh404sefextplugins'); if (!$status) { JFactory::getApplication() ->enqueuemessage('There was an error installing one or more sh404SEF extension plugins. Please try uninstalling and installing again'); return; } // install module $installer = $parent->getParent(); $source = $installer->getPath('source'); $extensionConfig = array('enabled' => 1, 'access' => 3); $moduleConfig = version_compare(JVERSION, '3.0', 'ge') ? array('position' => 'status', 'published' => 1) : array(); $status = $this->_shInstallModule('mod_sh404sef_cpicon', $source, $extensionConfig, $moduleConfig); // now we insert the 404 error page into the database // from version 1.5.5, the default content of 404 page has been largely modified // to make use of the similar urls plugin (and potentially others) // so we want to make sure people will have the new version of the 404 error page $this->_shUpdateErrorPage(); // apply various DB updates $this->_shUpdateDBStructure(); // make sur permissions record are set straight $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select('rules'); $query->from('#__assets'); $query->where($db->quoteName('name') . '=' . $db->quote('com_sh404sef')); $db->setQuery($query); $existingRules = $db->loadResult(); if (empty($existingRules) || $existingRules == '{}') { // write valid default value into assets record $defaultRule = '{"core.admin":[],"core.manage":[],"core.create":[],"core.delete":[],"core.edit":[],"core.edit.state":[],"core.edit.own":[]}'; $query->update($db->quoteName('#__assets'))->set($db->quoteName('rules') . '=' . $db->quote($defaultRule)) ->where($db->quoteName('name') . '=' . $db->quote('com_sh404sef')); $db->setQuery($query); $result = $db->query(); } // message // decide on help file language $languageCode = Sh404sefHelperLanguage::getFamily(); $basePath = JPATH_ROOT . '/administrator/components/com_sh404sef/language/%s.postinstall.php'; // fall back to english if language readme does not exist jimport('joomla.filesystem.file'); if (!JFile::exists(sprintf($basePath, $languageCode))) { $languageCode = 'en'; } include sprintf($basePath, $languageCode); } private function _getErrorPageCatId() { $this->_errorPageCatId = (int) ShlDbHelper::selectResult('#__categories', array('id'), array('parent_id' => 1, 'extension' => 'com_content', 'path' => 'sh404sef-custom-content', 'level' => 1)); // we have a category, all good if (!empty($this->_errorPageCatId)) { return $this->_errorPageCatId; } // no category for our content yet. Create it $basePath = JPATH_ADMINISTRATOR . '/components/com_categories'; require_once $basePath . '/models/category.php'; $config = array('table_path' => $basePath . '/tables'); $catmodel = new CategoriesModelCategory($config); $catData = array('id' => 0, 'parent_id' => 1, 'level' => 1, 'path' => 'sh404sef-custom-content', 'extension' => 'com_content', 'title' => 'sh404SEF custom content', 'alias' => 'sh404sef-custom-content', 'description' => 'Do not delete please!', 'published' => 1, 'language' => '*'); $status = $catmodel->save($catData); if (!$status) { throw new Sh404sefExceptionDefault('Unable to create sh404SEF content category!', 500); } // now get and store the id $this->_errorPageCatId = (int) ShlDbHelper::selectResult('#__categories', array('id'), array('parent_id' => 1, 'extension' => 'com_content', 'path' => 'sh404sef-custom-content', 'level' => 1)); if (empty($this->_errorPageCatId)) { throw new Sh404sefExceptionDefault( 'Unable to read sh404SEF content category! You might need to use the Rebuild button in Joomla! categories manager, as categories on your site may be broken. This often happens after migrating a Joomla! site to a newer version.', 500); } return $this->_errorPageCatId; } private function _changeErrorPageCategory($pageTitle = '__404__') { // try find this old category $catid = ShlDbHelper::selectResult('#__categories', array('id'), 'parent_id > 0 and extension = ? and path = ? and level = ?', array('com_content', 'uncategorised', 1)); if (empty($catid)) { return false; } // we have cat id, try to read article $ids = ShlDbHelper::selectAssoc('#__content', array('id'), array('catid' => $catid, 'title' => $pageTitle)); if (empty($ids)) { return false; } // we indeed have one or more such articles (possibly one per language: move them to new category) ShlDbHelper::updateIn('#__content', array('catid' => $this->_errorPageCatId), 'id', $ids); return true; } /** * Insert into the content database an uncategorized article * which serves as a basis for the 404 error page * Article title is __404__ * Prior to version 1.5.5, the article displayed for 404 errors * was titled 404. The new name ensures users who customized * will keep their old design in the db. They can either reselect it * from the control panel, or customize as well the new __404__ page * @return unknown_type */ private function _shUpdateErrorPage($pageTitle = '__404__') { // do we already have a __404__ article? try { $catid = $this->_getErrorPageCatId(); // we have cat id, try to read article $id = ShlDbHelper::selectResult('#__content', array('id'), array('catid' => $catid, 'title' => $pageTitle)); // if required page is already there, go away if (!empty($id)) { return; } // maybe there's already an error page in the 'uncategorised' category we were using prior to 3.4 // we can move it to the new category $updated = $this->_changeErrorPageCategory(); if ($updated) { return true; } // find about the default page content $lang = JFactory::getLanguage(); $lang->load('com_sh404sef'); // now we can insert the new page content into the db $status = $this->_insertContent($pageTitle, JText::_('COM_SH404SEF_DEF_404_MSG')); return $status; } catch (Exception $e) { $app = JFactory::getApplication(); $app->enqueueMessage('Error: ' . $e->getMessage()); return false; } } /** * Performs update to db stucture on existing setups */ private function _shUpdateDBStructure() { // get a db instance $db = JFactory::getDBO(); /* version 3.4: added OpenGraph data columns to meta data table CREATE TABLE IF NOT EXISTS `#__sh404sef_metas` ( `id` int(11) NOT NULL auto_increment, `newurl` varchar(255) NOT NULL default '', `metadesc` varchar(255) default '', `metakey` varchar(255) default '', `metatitle` varchar(255) default '', `metalang` varchar(30) default '', `metarobots` varchar(30) default '', `og_enable` tinyint(3) NOT NULL DEFAULT '0', `og_type` varchar(30) default '', `og_image` varchar(255) default '', `og_enable_description` tinyint(3) NOT NULL DEFAULT '0', `og_enable_site_name` tinyint(3) NOT NULL DEFAULT '0', `og_site_name` varchar(255) default '', `fb_admin_ids` varchar(255) default '', `og_enable_location` tinyint(3) NOT NULL DEFAULT '0', `og_latitude` varchar(30) default '', `og_longitude` varchar(30) default '', `og_street_address` varchar(255) default '', `og_locality` varchar(255) default '', `og_postal_code` varchar(30) default '', `og_region` varchar(255) default '', `og_country_name` varchar(255) default '', `og_enable_contact` tinyint(3) NOT NULL DEFAULT '0', `og_email` varchar(255) default '', `og_phone_number` varchar(255) default '', `og_fax_number` varchar(255) default '', `og_enable_fb_admin_ids` tinyint(3) NOT NULL DEFAULT '0', `canonical` varchar(255) default '', PRIMARY KEY (`id`), KEY `newurl` (`newurl`) ) DEFAULT CHARSET=utf8;*/ // when upgrading from older version, these values could be missing at the time of install defined('SH404SEF_OPTION_VALUE_NO') or define('SH404SEF_OPTION_VALUE_NO', 0); defined('SH404SEF_OPTION_VALUE_YES') or define('SH404SEF_OPTION_VALUE_YES', 1); defined('SH404SEF_OPTION_VALUE_USE_DEFAULT') or define('SH404SEF_OPTION_VALUE_USE_DEFAULT', 2); // get list of columns // platform 12.1 if (method_exists($db, 'getTableFields')) { $columns = $db->getTableFields('#__sh404sef_metas'); $columns = empty($columns['#__sh404sef_metas']) ? array() : $columns['#__sh404sef_metas']; } else { $columns = $db->getTableColumns('#__sh404sef_metas'); } // build required statements $subQueries = array(); if (empty($columns['canonical'])) { $subQueries[] = "add `canonical` varchar(255) default ''"; } if (empty($columns['og_enable'])) { $subQueries[] = "add `og_enable` tinyint(3) NOT NULL DEFAULT '" . SH404SEF_OPTION_VALUE_USE_DEFAULT . "'"; } if (empty($columns['og_type'])) { $subQueries[] = "add `og_type` varchar(30) default ''"; } if (empty($columns['og_image'])) { $subQueries[] = "add `og_image` varchar(255) default ''"; } if (empty($columns['og_enable_description'])) { $subQueries[] = "add `og_enable_description` tinyint(3) NOT NULL DEFAULT '" . SH404SEF_OPTION_VALUE_USE_DEFAULT . "'"; } if (empty($columns['og_enable_site_name'])) { $subQueries[] = "add `og_enable_site_name` tinyint(3) NOT NULL DEFAULT '" . SH404SEF_OPTION_VALUE_USE_DEFAULT . "'"; } if (empty($columns['og_site_name'])) { $subQueries[] = "add `og_site_name` varchar(255) default ''"; } if (empty($columns['fb_admin_ids'])) { $subQueries[] = "add `fb_admin_ids` varchar(255) default ''"; } if (empty($columns['og_enable_location'])) { $subQueries[] = "add `og_enable_location` tinyint(3) NOT NULL DEFAULT '" . SH404SEF_OPTION_VALUE_USE_DEFAULT . "'"; } if (empty($columns['og_latitude'])) { $subQueries[] = "add `og_latitude` varchar(30) default ''"; } if (empty($columns['og_longitude'])) { $subQueries[] = "add `og_longitude` varchar(30) default ''"; } if (empty($columns['og_street_address'])) { $subQueries[] = "add `og_street_address` varchar(255) default ''"; } if (empty($columns['og_locality'])) { $subQueries[] = "add `og_locality` varchar(255) default ''"; } if (empty($columns['og_postal_code'])) { $subQueries[] = "add `og_postal_code` varchar(30) default ''"; } if (empty($columns['og_region'])) { $subQueries[] = "add `og_region` varchar(255) default ''"; } if (empty($columns['og_country_name'])) { $subQueries[] = "add `og_country_name` varchar(255) default ''"; } if (empty($columns['og_enable_contact'])) { $subQueries[] = "add `og_enable_contact` tinyint(3) NOT NULL DEFAULT '" . SH404SEF_OPTION_VALUE_USE_DEFAULT . "'"; } if (empty($columns['og_email'])) { $subQueries[] = "add `og_email` varchar(255) default ''"; } if (empty($columns['og_phone_number'])) { $subQueries[] = "add `og_phone_number` varchar(255) default ''"; } if (empty($columns['og_fax_number'])) { $subQueries[] = "add `og_fax_number` varchar(255) default ''"; } if (empty($columns['og_enable_fb_admin_ids'])) { $subQueries[] = "add `og_enable_fb_admin_ids` tinyint(3) NOT NULL DEFAULT '" . SH404SEF_OPTION_VALUE_USE_DEFAULT . "'"; } // twitter cards if (empty($columns['twittercards_enable'])) { $subQueries[] = "add `twittercards_enable` tinyint(3) NOT NULL DEFAULT '" . SH404SEF_OPTION_VALUE_USE_DEFAULT . "'"; } if (empty($columns['twittercards_site_account'])) { $subQueries[] = "add `twittercards_site_account` varchar(100) default ''"; } if (empty($columns['twittercards_creator_account'])) { $subQueries[] = "add `twittercards_creator_account` varchar(100) default ''"; } // google authorship if (empty($columns['google_authorship_enable'])) { $subQueries[] = "add `google_authorship_enable` tinyint(3) NOT NULL DEFAULT '" . SH404SEF_OPTION_VALUE_USE_DEFAULT . "'"; } if (empty($columns['google_authorship_author_profile'])) { $subQueries[] = "add `google_authorship_author_profile` varchar(255) default ''"; } if (empty($columns['google_authorship_author_name'])) { $subQueries[] = "add `google_authorship_author_name` varchar(255) default ''"; } // google publisher if (empty($columns['google_publisher_enable'])) { $subQueries[] = "add `google_publisher_enable` tinyint(3) NOT NULL DEFAULT '" . SH404SEF_OPTION_VALUE_USE_DEFAULT . "'"; } if (empty($columns['google_publisher_url'])) { $subQueries[] = "add `google_publisher_url` varchar(255) default ''"; } // apply changes if (!empty($subQueries)) { // aggregate sub-queries $subQueries = implode(', ', $subQueries); // prepend query $query = 'alter table ' . $db->quoteName('#__sh404sef_metas') . ' ' . $subQueries; // run query try { $db->setQuery($query); $db->query(); $error = $db->getErrorNum(); if (!empty($error)) { throw new Exception($db->getErrorMsg()); } } catch (Exception $e) { $app = JFactory::getApplication(); $app ->enqueueMessage( 'Error while upgrading the database : ' . $e->getMessage() . '. Sh404SEF will probably not operate properly. Please uninstall it, then try again after checking your database server setup. Contact us in case this happens again.'); } } } private function _shInstallModule($module, $source, $extensionConfig, $moduleConfig) { $app = JFactory::getApplication(); $path = $source . '/admin/modules/' . $module; $installer = new JInstaller; $result = $installer->install($path); if ($result) { // if files moved to destination, setup module in Joomla database $shouldRestore = $this->_shShouldRestore(); if ($shouldRestore) { // read stored params from disk $this->_shGetExtensionSavedParams($module . '_extension', $extensionConfig); } // update elements in db, only if we need to restore past configuration try { if (!empty($extensionConfig)) { // load module details from extension table $moduleDetails = ShlDbHelper::selectAssoc('#__extensions', array('*'), array('type' => 'module', 'element' => $module)); // merge with saved details and write back to disk $details = array_merge($moduleDetails, $extensionConfig); ShlDbHelper::update('#__extensions', $details, array('extension_id' => (int) $moduleDetails['extension_id'])); } } catch (Exception $e) { $app->enqueueMessage('Error: ' . $e->getMessage()); } if ($shouldRestore) { // read stored params from disk $this->_shGetExtensionSavedParams($module . '_modules', $moduleConfig); } // update elements in db, if we need to restore past configuration try { $instanceDetails = ShlDbHelper::selectAssoc('#__modules', array('*'), array('module' => $module)); // merge with saved details and write back to disk $details = array_merge($instanceDetails, $moduleConfig); ShlDbHelper::update('#__modules', $details, array('id' => (int) $instanceDetails['id'])); } catch (Exception $e) { $app->enqueueMessage('Error: ' . $e->getMessage()); } // and finally we make sure there is a menu item associated with the module $details = array('menuid' => 0); if ($shouldRestore) { // read stored params from disk $this->_shGetExtensionSavedParams($module . '_modules_menu', $details); } $details = array_merge($details, array('moduleid' => (int) $instanceDetails['id'])); // insert or update elements in db, if we need to restore past configuration try { ShlDbHelper::insertUpdate('#__modules_menu', $details, array('moduleid' => (int) $instanceDetails['id'])); } catch (Exception $e) { $app->enqueueMessage('Error: ' . $e->getMessage()); } } else { $app->enqueueMessage('Error installing sh404sef module: ' . $module); } return $result; } /** * Install all sh404sef plugins available in a given * group * * @param string $group name of group * @return boolean, true if success */ private function _shInstallPluginGroup($group) { $app = JFactory::getApplication(); $sourcePath = JPATH_ADMINISTRATOR . '/components/com_sh404sef/plugins/' . $group; if (!JFolder::exists($sourcePath)) { $app->enqueueMessage('Trying to install empty plugin group: ' . $group); return true; } // if each plugin resides in its own subDir, we must iterate over all sub dirs $folderList = JFolder::folders($sourcePath); if (empty($folderList)) { $app->enqueueMessage('Trying to install empty plugin group, folder is empty: ' . $sourcePath); return true; } // process each plugin $errors = false; foreach ($folderList as $folder) { // install the plugin itself $status = $this->_shInstallPlugin($group, $folder, $sourcePath); // set flag if an error happened, but keep installing // other plugins $errors = $errors || !$status; // also display status if (!$status) { $app->enqueueMessage('Error installing sh404sef plugin from ' . $folder); } } // return true if no error at all return $errors == false; } /** * Insert in the db the previously retrieved parameters for a plugin * including publication information. Also move files as required * * @param string $basePath , the base path to get original files from */ /** * Insert in the db the previously retrieved parameters for a plugin * including publication information. Also move files as required * * @param string $pluginFolder * @param string $pluginElement * @param string $basePath */ private function _shInstallPlugin($pluginFolder, $pluginElement, $sourcePath) { if ($pluginFolder == 'system' && $pluginElement == 'shlib') { if (in_array('shlib', $this->_skipInstall)) { return true; } } $status = true; $app = JFactory::getApplication(); // in case of upgrade, don't touch settings by user try { $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select('extension_id')->from('#__extensions')->where($db->quoteName('type') . '=' . $db->quote('plugin')) ->where($db->quoteName('element') . '=' . $db->quote($pluginElement)) ->where($db->quoteName('folder') . '=' . $db->quote($pluginFolder)); $db->setQuery($query); $pluginId = $db->loadResult(); } catch (Exception $e) { $status = false; $app->enqueueMessage('Error reading pre-existing plugin record from db: ' . $pluginFolder . ' / ' . $pluginElement); return $status; } $overrides = empty($pluginId) ? array('ordering' => 10, 'enabled' => 1) : array(); // make sure main library is loaded first if (empty($pluginId) && $pluginElement == 'shlib') { $overrides['ordering'] = -100; } // use J! installer to fully install the plugin $installer = new JInstaller; $result = $installer->install($sourcePath . '/' . $pluginElement); if ($result) { $shouldRestore = $this->_shShouldRestore(); if ($shouldRestore) { // read stored params from disk $saved = array(); $this->_shGetExtensionSavedParams($pluginFolder . '.' . $pluginElement, $saved); unset($saved['extension_id']); $overrides = array_merge($overrides, $saved); } // overrides data in extension table, possibly overriding some columns from saved data if (!empty($overrides)) { try { $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select('extension_id')->from('#__extensions')->where($db->quoteName('type') . '=' . $db->quote('plugin')) ->where($db->quoteName('element') . '=' . $db->quote($pluginElement)) ->where($db->quoteName('folder') . '=' . $db->quote($pluginFolder)); $db->setQuery($query); $pluginId = $db->loadResult(); $error = $db->getErrorNum(); if (!empty($error)) { throw new Exception($db->getErrorMsg()); } if (!empty($pluginId)) { jimport('joomla.database.table.extension'); $extension = JTable::getInstance('Extension'); $extension->load($pluginId); $extension->bind($overrides); $status = $extension->store(); if (!$status) { $app->enqueueMessage('Error writing updated extension record: ' . $extension->getError() . ' for ' . $pluginFolder . ' / ' . $pluginElement); } } else { $app->enqueueMessage('Error updating plugin DB record: ' . $pluginFolder . ' / ' . $pluginElement); } } catch (Exception $e) { $status = false; $app->enqueueMessage('Error: ' . $e->getMessage()); } } } else { $app->enqueueMessage('Error installing sh404sef plugin: ' . $pluginFolder . ' / ' . $pluginElement); $status = false; } return $status; } /** * Retrieves stored params of a given extension (module or plugin) * (as saved upon uninstall) * * @param string $extName the module name, including mod_ if a module * @param array $shConfig an array holding the database columns of the extension * @param array $shPub, an array holding the publication information of the module (only for modules) * @return boolean, true if any stored parameters were found for this extension */ private function _shGetExtensionSavedParams($extName, &$shConfig, &$shPub = null, $useId = false) { static $fileList = array(); // prepare default return value $status = false; // read all file names in /media/sh404_upgrade_conf dir, for easier processing $baseFolder = $this->_preserveConfigFolder . 'sh404_upgrade_conf'; if (JFolder::exists($baseFolder) && (empty($fileList) || !isset($fileList[$extName]))) { $baseName = $extName . ($useId ? '_[0-9]{1,10}' : '') . '_' . $this->_siteId . '.php'; $fileList[$extName] = JFolder::files($baseFolder, $baseName); } // extract filename from list we've established previously $extFile = isset($fileList[$extName]) && $fileList[$extName] !== false ? array_shift($fileList[$extName]) : ''; if (empty($fileList[$extName])) { // prevent infinite loop $fileList[$extName] = false; } if (!empty($extFile) && JFile::exists($baseFolder . '/' . $extFile)) { $status = true; // operation was successful include($baseFolder . '/' . $extFile); } return $status; } /** * Decide whether backed up params should be restore (and * plugins reinstalled). * This should happen only when the extension is NOT already * installed. Most of times, as we are using updagre install * that should not happen and we jst overwrite * but if user uninstalled the extension, we must restore * data saved when he uninstalled * */ private function _shShouldRestore() { // IMPORTANT: the check is done once, and only once // as for later calls, the system plugin will have been installed // and thus the test will not be valid anymore static $restore = null; if (is_null($restore)) { // search for base xml file to decide if already installed $restore = !JFile::exists(JPATH_ROOT . '/plugins/system/sh404sef/sh404sef.xml'); } return $restore; } /** * Performs pre-uninstall backup of configuration * * @param object $parent */ private function _doUninstall($parent) { $this->_definePaths(); $this->_includeLibs(); // V 1.2.4.t before uninstalling modules, save their settings, if told to do so $sef_config_class = JPATH_ADMINISTRATOR . '/components/com_sh404sef/sh404sef.class.php'; // Make sure class was loaded. if (!class_exists('shSEFConfig')) { if (is_readable($sef_config_class)) { require_once($sef_config_class); } else { JError::RaiseError(500, JText::_('COM_SH404SEF_NOREAD') . "( $sef_config_class )<br />" . JText::_('COM_SH404SEF_CHK_PERMS')); } } $sefConfig = new shSEFConfig(); if (!$sefConfig->shKeepStandardURLOnUpgrade && !$sefConfig->shKeepCustomURLOnUpgrade) { $this->_shDeleteTable('sh404sef_urls'); $this->_shDeleteTable('sh404sef_aliases'); $this->_shDeleteTable('sh404sef_pageids'); } elseif (!$sefConfig->shKeepStandardURLOnUpgrade) { $this->_shDeleteAllSEFUrl('Standard'); } elseif (!$sefConfig->shKeepCustomURLOnUpgrade) { $this->_shDeleteAllSEFUrl('Custom'); $this->_shDeleteTable('sh404sef_aliases'); $this->_shDeleteTable('sh404sef_pageids'); } if (!$sefConfig->shKeepMetaDataOnUpgrade) { $this->_shDeleteTable('sh404sef_metas'); } // remove admin quick icon module $this->_shSaveDeleteModuleParams('mod_sh404sef_cpicon', $client = 1); // remove language switcher module // custom language switcher module disabled for now, not needed //$this->_shSaveDeleteModuleParams( 'mod_sh_languages', $client = 0); // remove system plugins $this->_shSaveDeletePluginParams('sh404sef', 'system'); $this->_shSaveDeletePluginParams('shmobile', 'system'); // remove installer plugin $this->_shSaveDeletePluginParams('sh404sef', 'installer'); // unregister from shLib, then possibly uninstall it if (JFile::exists(JPATH_ROOT . '/plugins/system/shlib/shl_packages/system/resourcemanager.php')) { require_once JPATH_ROOT . '/plugins/system/shlib/shl_packages/system/resourcemanager.php'; ShlSystem_Resourcemanager::unregister('shlib', 'com_sh404sef'); if (ShlSystem_Resourcemanager::canUninstall('shlib')) { $this->_shSaveDeletePluginParams('shlib', 'system'); } } // remove core plugins $this->_shSaveDeletePluginGroup('sh404sefcore'); $this->_shSaveDeletePluginGroup('sh404sefextplugins'); // delete analytics cached data, to force update // in case this part of sh404sef has changed $cache = JFactory::getCache('sh404sef_analytics'); $cache->clean(); // preserve configuration or not ? if (!$sefConfig->shKeepConfigOnUpgrade) { // main config file $fileName = $this->_preserveConfigFolder . 'sh404_upgrade_conf_' . $this->_siteId . '.php'; if (JFile::exists($fileName)) { JFile::delete($fileName); } // user custom config file $fileName = $this->_preserveConfigFolder . 'sh404_upgrade_conf_' . $this->_siteId . '.custom.php'; if (JFile::exists($fileName)) { JFile::delete($fileName); } // related extensions (plugins) config files folder if (JFolder::exists($this->_preserveConfigFolder . 'sh404_upgrade_conf')) { JFolder::delete($this->_preserveConfigFolder . 'sh404_upgrade_conf'); } // log files folder if (JFolder::exists($this->_preserveConfigFolder . 'sh404_upgrade_conf_logs')) { JFolder::delete($this->_preserveConfigFolder . 'sh404_upgrade_conf_logs'); } // security log files folder if (JFolder::exists($this->_preserveConfigFolder . 'sh404_upgrade_conf_security')) { JFolder::delete($this->_preserveConfigFolder . 'sh404_upgrade_conf_security'); } } else { // if we keep config if (JFolder::exists(JPATH_ROOT . '/logs/sh404sef')) { JFolder::copy(JPATH_ROOT . '/logs/sh404sef', $this->_preserveConfigFolder . 'sh404_upgrade_conf_logs', $path = '', $force = true); } if (JFolder::exists(JPATH_ADMINISTRATOR . '/components/com_sh404sef/security')) { JFolder::copy(JPATH_ADMINISTRATOR . '/components/com_sh404sef/security', $this->_preserveConfigFolder . 'sh404_upgrade_conf_security', $path = '', $force = true); } } // delete folder in /media // display results echo '<h3>sh404SEF has been succesfully uninstalled. </h3>'; echo '<br />'; if ($sefConfig->shKeepStandardURLOnUpgrade) { echo '- automatically generated SEF url have not been deleted (table #__sh404sef_urls)<br />'; } else { echo '- automatically generated SEF url have been deleted<br />'; } echo '<br />'; if ($sefConfig->shKeepCustomURLOnUpgrade) { echo '- custom SEF url, aliases and pageIds have not been deleted (tables #__sh404sef_urls, #__sh404sef_aliases and #__sh404sef_pageids)<br />'; } else { echo '- custom SEF url, aliases and pageIds have been deleted<br />'; } echo '<br />'; if ($sefConfig->shKeepMetaDataOnUpgrade) { echo '- Custom Title and META data have not been deleted (table #__sh404sef_metas)<br />'; } else { echo '- Custom Title and META data have been deleted<br />'; } echo '<br />'; } // V 1.2.4.t improved upgrading private function _shDeletetable($tableName) { $db = ShlDbHelper::getDb(); $query = 'drop table ' . $db->quoteName('#__' . $tableName); try { ShlDbHelper::query($query); } catch (Exception $e) { echo $e->getMessage() . '<br />'; } } private function _shDeleteAllSEFUrl($kind) { If ($kind == 'Custom') { $where = '`dateadd` > \'0000-00-00\' and `newurl` != \'\';'; } else { $where = '`dateadd` = \'0000-00-00\';'; } try { ShlDbHelper::delete('#__sh404sef_urls', $where); } catch (Exception $e) { echo $e->getMessage() . '<br />'; } } /** * * utility functions * */ /** * Writes an extension parameter to a disk file, located * in the /media directory * * @param string $extName the extension name * @param array $shConfig associative array of parameters of the extension, to be written to disk * @param array $pub, optional, only if module, an array of the menu item id where the module is published * @return boolean, true if no error */ private function _shWriteExtensionConfig($extName, $params) { if (empty($params)) { return; } // calculate target file name $extPath = $this->_preserveConfigFolder . 'sh404_upgrade_conf'; // if it does not exists, lets create it first if (!JFolder::exists($extPath)) { JFolder::create($extPath); } // make sure we have an index.html file in that folder $target = JPath::clean($extPath . '/' . 'index.html'); if (!JFile::exists($target)) { // copy one Joomla's index.html file to the backup directory $source = JPath::clean(JPATH_ROOT . '/plugins/index.html'); $success = JFile::copy($source, $target); } // now build full path file name to save config $extFile = $extPath . '/' . $extName . '_' . $this->_siteId . '.php'; // remove previous if any if (JFile::exists($extFile)) { JFile::delete($extFile); } // prepare data for writing $data = '<?php // Extension params save file for sh404sef // if (!defined(\'_JEXEC\')) die(\'Direct Access to this location is not allowed.\');'; $data .= "\n"; if (!empty($params)) { foreach ($params as $key => $value) { $data .= '$' . $key . ' = ' . var_export($value, true) . ';'; $data .= "\n"; } } // write to disk $success = JFile::write($extFile, $data); return $success !== false; } /** * Save parameters, then delete a module * Would not work on additional copies made by user * * @param string $moduleName, the module name, matching 'module' column in modules table * @param string $client (ie : site or administrator */ private function _shSaveDeleteModuleParams($moduleName, $client) { // read plugin param from db try { $result = ShlDbHelper::selectAssoc('#__extensions', array('*'), array('type' => 'module', 'element' => $moduleName, 'client_id' => $client)); if (empty($result)) { // invalid module name? return false; } // remove module db id unset($result['extension_id']); // write everything on disk $this->_shWriteExtensionConfig($moduleName . '_extension', array('shConfig' => $result)); // now remove plugin details from db ShlDbHelper::delete('#__extensions', array('type' => 'module', 'element' => $moduleName, 'client_id' => $client)); // do the same for the module instance, in #__module table $result = ShlDbHelper::selectAssoc('#__modules', array('*'), array('module' => $moduleName, 'client_id' => $client)); if (empty($result)) { // invalid module name? return false; } // save and remove module db id $moduleId = $result['id']; unset($result['id']); // write everything on disk $this->_shWriteExtensionConfig($moduleName . '_modules', array('shConfig' => $result)); // now remove plugin details from db ShlDbHelper::delete('#__modules', array('module' => $moduleName, 'client_id' => $client)); // remove module/menu affectation $result = ShlDbHelper::selectAssoc('#__modules_menu', array('*'), array('moduleid' => $moduleId)); // remove module db id unset($result['moduleid']); // write everything on disk $this->_shWriteExtensionConfig($moduleName . '_modules_menu', array('shConfig' => $result)); // now remove plugin details from db ShlDbHelper::delete('#__modules_menu', array('moduleid' => $moduleId)); } catch (Exception $e) { echo $e->getMessage() . '<br />'; } // delete the module files $path = JPATH_ROOT . '/' . ($client ? 'administrator' . '/' : '') . 'modules/' . $moduleName; if (JFolder::exists($path)) { JFolder::delete($path); } } /** * Save parameters, then delete a plugin * * @param string $pluginName, the plugin name, mathcing 'element' column in plugins table * @param string $folder, the plugin folder (ie : 'content', 'search', 'system',... */ private function _shSaveDeletePluginParams($pluginName, $folder, $folders = null) { try { $result = ShlDbHelper::selectAssoc('#__extensions', array('*'), array('type' => 'plugin', 'element' => $pluginName, 'folder' => $folder)); if (empty($result)) { // invalid plugin name? return false; } // remove plugin db id $pluginId = $result['extension_id']; unset($result['extension_id']); // write everything on disk $this->_shWriteExtensionConfig($pluginName, array('shConfig' => $result)); // now uninstall $installer = new JInstaller; $result = $installer->uninstall('plugin', $pluginId); // now remove plugin details from db //ShlDbHelper::delete( '#__extensions', array( 'type' => 'plugin', 'element' => $pluginName, 'folder' => $folder)); } catch (Exception $e) { } } /** * Save params, then delete plugin, for all plugins * in a given group * * @param $group the group to be deleted * @return none */ private function _shSaveDeletePluginGroup($group) { $unsafe = array('authentication', 'content', 'editors', 'editors-xtd', 'search', 'system', 'xmlrpc'); if (in_array($group, $unsafe)) { // safety net : we don't want to delete the whole system or content folder return false; } // read plugin param from db try { $pluginList = ShlDbHelper::selectAssocList('#__extensions', array('*'), array('type' => 'plugin', 'folder' => $group)); if (empty($pluginList)) { return true; } // for each plugin foreach ($pluginList as $plugin) { // remove plugin db id unset($plugin['id']); // write everything on disk $this->_shWriteExtensionConfig($plugin['folder'] . '.' . $plugin['element'], array('shConfig' => $plugin)); // now remove plugin details from db ShlDbHelper::delete('#__extensions', array('type' => 'plugin', 'element' => $plugin['element'], 'folder' => $plugin['folder'])); } } catch (Exception $e) { echo $e->getMessage() . '<br />'; } // now delete the files for the whole group if (JFolder::exists(JPATH_ROOT . '/plugins/' . $group)) { JFolder::delete(JPATH_ROOT . '/plugins/' . $group); } } /** * Insert an intro text into the content table * * @param strng $shIntroText * @return boolean, true if success */ function _insertContent($pageTitle, $shIntroText) { // result storage $status = false; jimport('joomla.database.table'); try { $catid = $this->_errorPageCatId; if (empty($catid)) { $this->setError(JText::_('COM_SH404SEF_CANNOT_SAVE_404_NO_UNCAT')); return; } $contentTable = JTable::getInstance('content'); $content = array('title' => $pageTitle, 'alias' => $pageTitle, 'title_alias' => $pageTitle, 'introtext' => $shIntroText, 'state' => 1, 'language' => '*', 'catid' => $catid, 'attribs' => '{"menu_image":"-1","show_title":"0","show_section":"0","show_category":"0","show_vote":"0","show_author":"0","show_create_date":"0","show_modify_date":"0","show_pdf_icon":"0","show_print_icon":"0","show_email_icon":"0","pageclass_sfx":""' /* ,'rules' => '{"core.delete":[],"core.edit":[],"core.edit.state":[]}'*/ ); $status = $contentTable->save($content); } catch (Exception $e) { } return $status; } private function _definePaths() { $this->_siteId = rtrim(str_replace('/administrator', '', JURI::base()), '/'); $this->_siteId = str_replace('/', '_', str_replace('http://', '', $this->_siteId)); $this->_preserveConfigFolder = JPATH_ROOT . '/media/sh404sef/'; } private function _includeLibs() { jimport('joomla.filesystem.file'); jimport('joomla.filesystem.folder'); jimport('joomla.filesystem.path'); jimport('joomla.html.parameter'); jimport('joomla.filter.filterinput'); jimport('joomla.utilities.string'); // we use require instead of require_once so that the NEW, just installed, version of the file is // reloaded. If any new define has been added in the new version, they will thus become available // This requires that defines in defines.php are protected again redifining the same constant require JPATH_ROOT . '/administrator/components/com_sh404sef/defines.php'; // if these files have been included already, we will use the old version of the file require_once JPATH_ROOT . '/administrator/components/com_sh404sef/exceptions/default.php'; require_once JPATH_ROOT . '/administrator/components/com_sh404sef/helpers/language.php'; } }