diff --git a/plugins/search/content/content.php b/plugins/search/content/content.php index 23d4877d10aaf..4cc0a3f3460a6 100644 --- a/plugins/search/content/content.php +++ b/plugins/search/content/content.php @@ -48,11 +48,12 @@ public function onContentSearchAreas() */ public function onContentSearch($text, $phrase = '', $ordering = '', $areas = null) { - $db = JFactory::getDbo(); - $app = JFactory::getApplication(); - $user = JFactory::getUser(); - $groups = implode(',', $user->getAuthorisedViewLevels()); - $tag = JFactory::getLanguage()->getTag(); + $db = JFactory::getDbo(); + $serverType = $db->serverType; + $app = JFactory::getApplication(); + $user = JFactory::getUser(); + $groups = implode(',', $user->getAuthorisedViewLevels()); + $tag = JFactory::getLanguage()->getTag(); JLoader::register('ContentHelperRoute', JPATH_SITE . '/components/com_content/helpers/route.php'); JLoader::register('SearchHelper', JPATH_ADMINISTRATOR . '/components/com_search/helpers/search.php'); @@ -89,8 +90,43 @@ public function onContentSearch($text, $phrase = '', $ordering = '', $areas = nu $wheres2[] = 'a.fulltext LIKE ' . $text; $wheres2[] = 'a.metakey LIKE ' . $text; $wheres2[] = 'a.metadesc LIKE ' . $text; - $wheres2[] = 'fv.value LIKE ' . $text; - $where = '(' . implode(') OR (', $wheres2) . ')'; + + // Join over Fields. + $subQuery = $db->getQuery(true); + $subQuery->select("cfv.item_id") + ->from("#__fields_values AS cfv") + ->join('LEFT', '#__fields AS f ON f.id = cfv.field_id') + ->where('(f.context IS NULL OR f.context = ' . $db->q('com_content.article') . ')') + ->where('(f.state IS NULL OR f.state = 1)') + ->where('(f.access IS NULL OR f.access IN (' . $groups . '))') + ->where('cfv.value LIKE ' . $text); + + // Filter by language. + if ($app->isClient('site') && JLanguageMultilang::isEnabled()) + { + $subQuery->where('(f.language IS NULL OR f.language in (' . $db->quote($tag) . ',' . $db->quote('*') . '))'); + } + + if ($serverType == "mysql") + { + /* This generates a dependent sub-query so do no use in MySQL prior to version 6.0 ! + * $wheres2[] = 'a.id IN( '. (string) $subQuery.')'; + */ + + $db->setQuery($subQuery); + $fieldids = $db->loadColumn(); + + if (count($fieldids)) + { + $wheres2[] = 'a.id IN(' . implode(",", $fieldids) . ')'; + } + } + else + { + $wheres2[] = $subQuery->castAsChar('a.id') . ' IN( ' . (string) $subQuery . ')'; + } + + $where = '(' . implode(') OR (', $wheres2) . ')'; break; case 'all': @@ -98,6 +134,7 @@ public function onContentSearch($text, $phrase = '', $ordering = '', $areas = nu default: $words = explode(' ', $text); $wheres = array(); + $cfwhere = array(); foreach ($words as $word) { @@ -108,8 +145,79 @@ public function onContentSearch($text, $phrase = '', $ordering = '', $areas = nu $wheres2[] = 'LOWER(a.fulltext) LIKE LOWER(' . $word . ')'; $wheres2[] = 'LOWER(a.metakey) LIKE LOWER(' . $word . ')'; $wheres2[] = 'LOWER(a.metadesc) LIKE LOWER(' . $word . ')'; - $wheres2[] = 'LOWER(fv.value) LIKE LOWER(' . $word . ')'; - $wheres[] = implode(' OR ', $wheres2); + + if ($phrase === 'all') + { + // Join over Fields. + $subQuery = $db->getQuery(true); + $subQuery->select("cfv.item_id") + ->from("#__fields_values AS cfv") + ->join('LEFT', '#__fields AS f ON f.id = cfv.field_id') + ->where('(f.context IS NULL OR f.context = ' . $db->q('com_content.article') . ')') + ->where('(f.state IS NULL OR f.state = 1)') + ->where('(f.access IS NULL OR f.access IN (' . $groups . '))') + ->where('LOWER(cfv.value) LIKE LOWER(' . $word . ')'); + + // Filter by language. + if ($app->isClient('site') && JLanguageMultilang::isEnabled()) + { + $subQuery->where('(f.language IS NULL OR f.language in (' . $db->quote($tag) . ',' . $db->quote('*') . '))'); + } + + if ($serverType == "mysql") + { + $db->setQuery($subQuery); + $fieldids = $db->loadColumn(); + + if (count($fieldids)) + { + $wheres2[] = 'a.id IN(' . implode(",", $fieldids) . ')'; + } + } + else + { + $wheres2[] = $subQuery->castAsChar('a.id') . ' IN( ' . (string) $subQuery . ')'; + } + } + else + { + $cfwhere[] = 'LOWER(cfv.value) LIKE LOWER(' . $word . ')'; + } + $wheres[] = implode(' OR ', $wheres2); + } + + if ($phrase === 'any') + { + // Join over Fields. + $subQuery = $db->getQuery(true); + $subQuery->select("cfv.item_id") + ->from("#__fields_values AS cfv") + ->join('LEFT', '#__fields AS f ON f.id = cfv.field_id') + ->where('(f.context IS NULL OR f.context = ' . $db->q('com_content.article') . ')') + ->where('(f.state IS NULL OR f.state = 1)') + ->where('(f.access IS NULL OR f.access IN (' . $groups . '))') + ->where('(' . implode(($phrase === 'all' ? ') AND (' : ') OR ('), $cfwhere) . ')'); + + // Filter by language. + if ($app->isClient('site') && JLanguageMultilang::isEnabled()) + { + $subQuery->where('(f.language IS NULL OR f.language in (' . $db->quote($tag) . ',' . $db->quote('*') . '))'); + } + + if ($serverType == "mysql") + { + $db->setQuery($subQuery); + $fieldids = $db->loadColumn(); + + if (count($fieldids)) + { + $wheres[] = 'a.id IN(' . implode(",", $fieldids) . ')'; + } + } + else + { + $wheres[] = $subQuery->castAsChar('a.id') . ' IN( ' . (string) $subQuery . ')'; + } } $where = '(' . implode(($phrase === 'all' ? ') AND (' : ') OR ('), $wheres) . ')'; @@ -160,7 +268,7 @@ public function onContentSearch($text, $phrase = '', $ordering = '', $areas = nu $case_when1 = ' CASE WHEN '; $case_when1 .= $query->charLength('c.alias', '!=', '0'); $case_when1 .= ' THEN '; - $c_id = $query->castAsChar('c.id'); + $c_id = $query->castAsChar('c.id'); $case_when1 .= $query->concatenate(array($c_id, 'c.alias'), ':'); $case_when1 .= ' ELSE '; $case_when1 .= $c_id . ' END as catslug'; @@ -179,19 +287,11 @@ public function onContentSearch($text, $phrase = '', $ordering = '', $areas = nu ->group('a.id, a.title, a.metadesc, a.metakey, a.created, a.language, a.catid, a.introtext, a.fulltext, c.title, a.alias, c.alias, c.id') ->order($order); - // Join over Fields. - $query->join('LEFT', '#__fields_values AS fv ON fv.item_id = ' . $query->castAsChar('a.id')) - ->join('LEFT', '#__fields AS f ON f.id = fv.field_id') - ->where('(f.context IS NULL OR f.context = ' . $db->q('com_content.article') . ')') - ->where('(f.state IS NULL OR f.state = 1)') - ->where('(f.access IS NULL OR f.access IN (' . $groups . '))'); - // Filter by language. if ($app->isClient('site') && JLanguageMultilang::isEnabled()) { $query->where('a.language in (' . $db->quote($tag) . ',' . $db->quote('*') . ')') - ->where('c.language in (' . $db->quote($tag) . ',' . $db->quote('*') . ')') - ->where('(f.language IS NULL OR f.language in (' . $db->quote($tag) . ',' . $db->quote('*') . '))'); + ->where('c.language in (' . $db->quote($tag) . ',' . $db->quote('*') . ')'); } $db->setQuery($query, 0, $limit); @@ -242,9 +342,9 @@ public function onContentSearch($text, $phrase = '', $ordering = '', $areas = nu $query->select( 'a.title AS title, a.metadesc, a.metakey, a.created AS created, ' - . $query->concatenate(array('a.introtext', 'a.fulltext')) . ' AS text,' - . $case_when . ',' . $case_when1 . ', ' - . 'c.title AS section, \'2\' AS browsernav' + . $query->concatenate(array('a.introtext', 'a.fulltext')) . ' AS text,' + . $case_when . ',' . $case_when1 . ', ' + . 'c.title AS section, \'2\' AS browsernav' ); // .'CONCAT_WS("/", c.title) AS section, \'2\' AS browsernav' ); @@ -258,19 +358,13 @@ public function onContentSearch($text, $phrase = '', $ordering = '', $areas = nu ) ->order($order); - // Join over Fields. - $query->join('LEFT', '#__fields_values AS fv ON fv.item_id = ' . $query->castAsChar('a.id')) - ->join('LEFT', '#__fields AS f ON f.id = fv.field_id') - ->where('(f.context IS NULL OR f.context = ' . $db->q('com_content.article') . ')') - ->where('(f.state IS NULL OR f.state = 1)') - ->where('(f.access IS NULL OR f.access IN (' . $groups . '))'); + // Join over Fields is no longer neded // Filter by language. if ($app->isClient('site') && JLanguageMultilang::isEnabled()) { $query->where('a.language in (' . $db->quote($tag) . ',' . $db->quote('*') . ')') - ->where('c.language in (' . $db->quote($tag) . ',' . $db->quote('*') . ')') - ->where('(f.language IS NULL OR f.language in (' . $db->quote($tag) . ',' . $db->quote('*') . '))'); + ->where('c.language in (' . $db->quote($tag) . ',' . $db->quote('*') . ')'); } $db->setQuery($query, 0, $limit); @@ -296,7 +390,7 @@ public function onContentSearch($text, $phrase = '', $ordering = '', $areas = nu $date = JFactory::getDate($item->created); $created_month = $date->format('n'); - $created_year = $date->format('Y'); + $created_year = $date->format('Y'); $list3[$key]->href = JRoute::_('index.php?option=com_content&view=archive&year=' . $created_year . '&month=' . $created_month . $itemid); } @@ -315,6 +409,7 @@ public function onContentSearch($text, $phrase = '', $ordering = '', $areas = nu foreach ($row as $article) { + // Not efficient to get these ONE article at a TIME // Lookup field values so they can be checked, GROUP_CONCAT would work in above queries, but isn't supported by non-MySQL DBs. $query = $db->getQuery(true); $query->select('fv.value') @@ -334,7 +429,7 @@ public function onContentSearch($text, $phrase = '', $ordering = '', $areas = nu $results = array_merge($results, (array) $new_row); } } - return $results; } + }