From c684036a49f9994d7dfcd4c65bbf66acb34538d8 Mon Sep 17 00:00:00 2001 From: andrepereiradasilva Date: Thu, 21 Jan 2016 23:38:06 +0000 Subject: [PATCH] Remove duplicate multilang database queries. Fixes #8914 --- .../com_categories/helpers/categories.php | 35 +---- .../com_languages/helpers/multilangstatus.php | 29 ++--- .../views/multilangstatus/view.html.php | 4 +- .../components/com_menus/helpers/menus.php | 28 +--- libraries/cms/language/associations.php | 120 ++++++++++-------- libraries/cms/language/multilang.php | 61 +++++++++ modules/mod_languages/helper.php | 3 +- .../system/languagefilter/languagefilter.php | 9 +- 8 files changed, 149 insertions(+), 140 deletions(-) diff --git a/administrator/components/com_categories/helpers/categories.php b/administrator/components/com_categories/helpers/categories.php index 348918073f9f4..fd6f28774cd9b 100644 --- a/administrator/components/com_categories/helpers/categories.php +++ b/administrator/components/com_categories/helpers/categories.php @@ -99,40 +99,11 @@ public static function getActions($extension, $categoryId = 0) */ public static function getAssociations($pk, $extension = 'com_content') { + $langAssociations = JLanguageAssociations::getAssociations($extension, '#__categories', 'com_categories.item', $pk, 'id', 'alias', ''); $associations = array(); - $db = JFactory::getDbo(); - $query = $db->getQuery(true) - ->from('#__categories as c') - ->join('INNER', '#__associations as a ON a.id = c.id AND a.context=' . $db->quote('com_categories.item')) - ->join('INNER', '#__associations as a2 ON a.key = a2.key') - ->join('INNER', '#__categories as c2 ON a2.id = c2.id AND c2.extension = ' . $db->quote($extension)) - ->where('c.id =' . (int) $pk) - ->where('c.extension = ' . $db->quote($extension)); - $select = array( - 'c2.language', - $query->concatenate(array('c2.id', 'c2.alias'), ':') . ' AS id' - ); - $query->select($select); - $db->setQuery($query); - - try - { - $contentitems = $db->loadObjectList('language'); - } - catch (RuntimeException $exception) + foreach ($langAssociations as $langAssociation) { - JError::raiseWarning(500, $exception->getMessage()); - - return array(); - } - - foreach ($contentitems as $tag => $item) - { - // Do not return itself as result - if ((int) $item->id != $pk) - { - $associations[$tag] = $item->id; - } + $associations[$langAssociation->language] = $langAssociation->id; } return $associations; diff --git a/administrator/components/com_languages/helpers/multilangstatus.php b/administrator/components/com_languages/helpers/multilangstatus.php index 042e02ddaca10..9509cbbc47e00 100644 --- a/administrator/components/com_languages/helpers/multilangstatus.php +++ b/administrator/components/com_languages/helpers/multilangstatus.php @@ -78,41 +78,28 @@ public static function getContentlangs() * Method to return a list of published site languages. * * @return array of language extension objects. + * + * @deprecated 4.0 Use JLanguageMultilang::getSiteLangs() instead. */ public static function getSitelangs() { - // Check for published Site Languages. - $db = JFactory::getDbo(); - $query = $db->getQuery(true) - ->select('a.element AS element') - ->from('#__extensions AS a') - ->where('a.type = ' . $db->quote('language')) - ->where('a.client_id = 0') - ->where('a.enabled = 1'); - $db->setQuery($query); + JLog::add(__METHOD__ . ' is deprecated, use JLanguageMultilang::getSiteLangs() instead.', JLog::WARNING, 'deprecated'); - return $db->loadObjectList('element'); + return JLanguageMultilang::getSiteLangs(); } /** * Method to return a list of language home page menu items. * * @return array of menu objects. + * + * @deprecated 4.0 Use JLanguageMultilang::getSiteHomePages() instead. */ public static function getHomepages() { - // Check for Home pages languages. - $db = JFactory::getDbo(); - $query = $db->getQuery(true) - ->select('language') - ->select('id') - ->from($db->quoteName('#__menu')) - ->where('home = 1') - ->where('published = 1') - ->where('client_id = 0'); - $db->setQuery($query); + JLog::add(__METHOD__ . ' is deprecated, use JLanguageMultilang::getSiteHomePages() instead.', JLog::WARNING, 'deprecated'); - return $db->loadObjectList('language'); + return JLanguageMultilang::getSiteHomePages(); } /** diff --git a/administrator/components/com_languages/views/multilangstatus/view.html.php b/administrator/components/com_languages/views/multilangstatus/view.html.php index 0993e144963b5..7062e2131b144 100644 --- a/administrator/components/com_languages/views/multilangstatus/view.html.php +++ b/administrator/components/com_languages/views/multilangstatus/view.html.php @@ -32,9 +32,9 @@ public function display($tpl = null) $this->switchers = MultilangstatusHelper::getLangswitchers(); $this->listUsersError = MultilangstatusHelper::getContacts(); $this->contentlangs = MultilangstatusHelper::getContentlangs(); - $this->site_langs = MultilangstatusHelper::getSitelangs(); + $this->site_langs = JLanguageMultilang::getSiteLangs(); $this->statuses = MultilangstatusHelper::getStatus(); - $this->homepages = MultilangstatusHelper::getHomepages(); + $this->homepages = JLanguageMultilang::getSiteHomePages(); parent::display($tpl); } diff --git a/administrator/components/com_menus/helpers/menus.php b/administrator/components/com_menus/helpers/menus.php index 8169a3bcd76dd..2782796e78c31 100644 --- a/administrator/components/com_menus/helpers/menus.php +++ b/administrator/components/com_menus/helpers/menus.php @@ -316,33 +316,11 @@ public static function getMenuLinks($menuType = null, $parentId = 0, $mode = 0, */ public static function getAssociations($pk) { + $langAssociations = JLanguageAssociations::getAssociations('com_menus', '#__menu', 'com_menus.item', $pk, 'id', '', ''); $associations = array(); - $db = JFactory::getDbo(); - $query = $db->getQuery(true) - ->from('#__menu as m') - ->join('INNER', '#__associations as a ON a.id=m.id AND a.context=' . $db->quote('com_menus.item')) - ->join('INNER', '#__associations as a2 ON a.key=a2.key') - ->join('INNER', '#__menu as m2 ON a2.id=m2.id') - ->where('m.id=' . (int) $pk) - ->select('m2.language, m2.id'); - $db->setQuery($query); - - try + foreach ($langAssociations as $langAssociation) { - $menuitems = $db->loadObjectList('language'); - } - catch (RuntimeException $e) - { - throw new Exception($e->getMessage(), 500); - } - - foreach ($menuitems as $tag => $item) - { - // Do not return itself as result - if ((int) $item->id != $pk) - { - $associations[$tag] = $item->id; - } + $associations[$langAssociation->language] = $langAssociation->id; } return $associations; diff --git a/libraries/cms/language/associations.php b/libraries/cms/language/associations.php index 65624b0d0c976..6b8f77c41b9fc 100644 --- a/libraries/cms/language/associations.php +++ b/libraries/cms/language/associations.php @@ -37,74 +37,88 @@ class JLanguageAssociations */ public static function getAssociations($extension, $tablename, $context, $id, $pk = 'id', $aliasField = 'alias', $catField = 'catid') { - $associations = array(); - $db = JFactory::getDbo(); - $query = $db->getQuery(true) - ->select($db->quoteName('c2.language')) - ->from($db->quoteName($tablename, 'c')) - ->join('INNER', $db->quoteName('#__associations', 'a') . ' ON a.id = c.' . $db->quoteName($pk) . ' AND a.context=' . $db->quote($context)) - ->join('INNER', $db->quoteName('#__associations', 'a2') . ' ON a.key = a2.key') - ->join('INNER', $db->quoteName($tablename, 'c2') . ' ON a2.id = c2.' . $db->quoteName($pk)); - - // Use alias field ? - if (!empty($aliasField)) - { - $query->select( - $query->concatenate( - array( - $db->quoteName('c2.' . $pk), - $db->quoteName('c2.' . $aliasField) - ), - ':' - ) . ' AS ' . $db->quoteName($pk) - ); - } - else - { - $query->select($db->quoteName('c2.' . $pk)); - } + // To avoid doing duplicate database queries. + static $multilanguageAssociations = array(); - // Use catid field ? - if (!empty($catField)) + // Multilanguage association array key. If the key is already in the array we don't need to run the query again, just return it. + $queryKey = implode('|', func_get_args()); + if (!isset($multilanguageAssociations[$queryKey])) { - $query->join( - 'INNER', - $db->quoteName('#__categories', 'ca') . ' ON ' . $db->quoteName('c2.' . $catField) . ' = ca.id AND ca.extension = ' . $db->quote($extension) - ) - ->select( + $multilanguageAssociations[$queryKey] = array(); + + $db = JFactory::getDbo(); + $categoriesExtraSql = (($tablename === '#__categories') ? ' AND c2.extension = ' . $db->quote($extension) : ''); + $query = $db->getQuery(true) + ->select($db->quoteName('c2.language')) + ->from($db->quoteName($tablename, 'c')) + ->join('INNER', $db->quoteName('#__associations', 'a') . ' ON a.id = c.' . $db->quoteName($pk) . ' AND a.context=' . $db->quote($context)) + ->join('INNER', $db->quoteName('#__associations', 'a2') . ' ON a.key = a2.key') + ->join('INNER', $db->quoteName($tablename, 'c2') . ' ON a2.id = c2.' . $db->quoteName($pk) . $categoriesExtraSql); + + // Use alias field ? + if (!empty($aliasField)) + { + $query->select( $query->concatenate( - array('ca.id', 'ca.alias'), + array( + $db->quoteName('c2.' . $pk), + $db->quoteName('c2.' . $aliasField) + ), ':' - ) . ' AS ' . $db->quoteName($catField) + ) . ' AS ' . $db->quoteName($pk) ); - } + } + else + { + $query->select($db->quoteName('c2.' . $pk)); + } - $query->where('c.' . $pk . ' = ' . (int) $id); + // Use catid field ? + if (!empty($catField)) + { + $query->join( + 'INNER', + $db->quoteName('#__categories', 'ca') . ' ON ' . $db->quoteName('c2.' . $catField) . ' = ca.id AND ca.extension = ' . $db->quote($extension) + ) + ->select( + $query->concatenate( + array('ca.id', 'ca.alias'), + ':' + ) . ' AS ' . $db->quoteName($catField) + ); + } - $db->setQuery($query); + $query->where('c.' . $pk . ' = ' . (int) $id); + if ($tablename === '#__categories') + { + $query->where('c.extension = ' . $db->quote($extension)); + } - try - { - $items = $db->loadObjectList('language'); - } - catch (RuntimeException $e) - { - throw new Exception($e->getMessage(), 500, $e); - } + $db->setQuery($query); - if ($items) - { - foreach ($items as $tag => $item) + try + { + $items = $db->loadObjectList('language'); + } + catch (RuntimeException $e) + { + throw new Exception($e->getMessage(), 500, $e); + } + + if ($items) { - // Do not return itself as result - if ((int) $item->{$pk} != $id) + foreach ($items as $tag => $item) { - $associations[$tag] = $item; + // Do not return itself as result + if ((int) $item->{$pk} != $id) + { + $multilanguageAssociations[$queryKey][$tag] = $item; + } } } } - return $associations; + return $multilanguageAssociations[$queryKey]; } /** diff --git a/libraries/cms/language/multilang.php b/libraries/cms/language/multilang.php index ca279254e9e27..3a02377f1b231 100644 --- a/libraries/cms/language/multilang.php +++ b/libraries/cms/language/multilang.php @@ -62,4 +62,65 @@ public static function isEnabled() return $enabled; } + + /** + * Method to return a list of published site languages. + * + * @return array of language extension objects. + * + * @since 3.6 + */ + public static function getSiteLangs() + { + // To avoid doing duplicate database queries. + static $multilangSiteLangs = null; + + if (!isset($multilangSiteLangs)) + { + // Check for published Site Languages. + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select('element') + ->from('#__extensions') + ->where('type = ' . $db->quote('language')) + ->where('client_id = 0') + ->where('enabled = 1'); + $db->setQuery($query); + + $multilangSiteLangs = $db->loadObjectList('element'); + } + + return $multilangSiteLangs; + } + + /** + * Method to return a list of language home page menu items. + * + * @return array of menu objects. + * + * @since 3.6 + */ + public static function getSiteHomePages() + { + // To avoid doing duplicate database queries. + static $multilangSiteHomePages = null; + + if (!isset($multilangSiteHomePages)) + { + // Check for Home pages languages. + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select('language') + ->select('id') + ->from($db->quoteName('#__menu')) + ->where('home = 1') + ->where('published = 1') + ->where('client_id = 0'); + $db->setQuery($query); + + $multilangSiteHomePages = $db->loadObjectList('language'); + } + + return $multilangSiteHomePages; + } } diff --git a/modules/mod_languages/helper.php b/modules/mod_languages/helper.php index fec63f472317c..140574d52ecff 100644 --- a/modules/mod_languages/helper.php +++ b/modules/mod_languages/helper.php @@ -10,7 +10,6 @@ defined('_JEXEC') or die; JLoader::register('MenusHelper', JPATH_ADMINISTRATOR . '/components/com_menus/helpers/menus.php'); -JLoader::register('MultilangstatusHelper', JPATH_ADMINISTRATOR . '/components/com_languages/helpers/multilangstatus.php'); /** * Helper for mod_languages @@ -74,7 +73,7 @@ public static function getList(&$params) } $levels = $user->getAuthorisedViewLevels(); - $sitelangs = MultilangstatusHelper::getSitelangs(); + $sitelangs = JLanguageMultilang::getSiteLangs(); $multilang = JLanguageMultilang::isEnabled(); // Filter allowed languages diff --git a/plugins/system/languagefilter/languagefilter.php b/plugins/system/languagefilter/languagefilter.php index ed2185a0066eb..ac52e897a73d1 100644 --- a/plugins/system/languagefilter/languagefilter.php +++ b/plugins/system/languagefilter/languagefilter.php @@ -12,7 +12,6 @@ use Joomla\Registry\Registry; JLoader::register('MenusHelper', JPATH_ADMINISTRATOR . '/components/com_menus/helpers/menus.php'); -JLoader::register('MultilangstatusHelper', JPATH_ADMINISTRATOR . '/components/com_languages/helpers/multilangstatus.php'); /** * Joomla! Language Filter Plugin. @@ -70,7 +69,7 @@ public function __construct(&$subject, $config) // @todo: In Joomla 2.5.4 and earlier access wasn't set. Non modified Content Languages got 0 as access value // we also check if frontend language exists and is enabled if (($language->access && !in_array($language->access, $levels)) - || (!array_key_exists($language->lang_code, MultilangstatusHelper::getSitelangs()))) + || (!array_key_exists($language->lang_code, JLanguageMultilang::getSiteLangs()))) { unset($this->lang_codes[$language->lang_code]); unset($this->sefs[$language->sef]); @@ -544,7 +543,7 @@ public function onUserLogin($user, $options = array()) // The language has been deleted/disabled or the related content language does not exist/has been unpublished // or the related home page does not exist/has been unpublished if (!array_key_exists($lang_code, $this->lang_codes) - || !array_key_exists($lang_code, MultilangstatusHelper::getHomepages()) + || !array_key_exists($lang_code, JLanguageMultilang::getSiteHomePages()) || !JFolder::exists(JPATH_SITE . '/language/' . $lang_code)) { $lang_code = $this->current_lang; @@ -608,7 +607,7 @@ public function onAfterDispatch() if ($this->app->isSite() && $this->params->get('alternate_meta') && $doc->getType() == 'html') { $languages = $this->lang_codes; - $homes = MultilangstatusHelper::getHomepages(); + $homes = JLanguageMultilang::getSiteHomePages(); $menu = $this->app->getMenu(); $active = $menu->getActive(); $levels = JFactory::getUser()->getAuthorisedViewLevels(); @@ -648,7 +647,7 @@ public function onAfterDispatch() switch (true) { // Language without frontend UI || Language without specific home menu || Language without authorized access level - case (!array_key_exists($i, MultilangstatusHelper::getSitelangs())): + case (!array_key_exists($i, JLanguageMultilang::getSiteLangs())): case (!isset($homes[$i])): case (isset($language->access) && $language->access && !in_array($language->access, $levels)): unset($languages[$i]);