/** * Method to bind fields to an items object * * @access private * @return object * @since 1.5 */ static function &getFields(&$_items, $view = FLEXI_ITEMVIEW, $params = null, $aid = false, $use_tmpl = true) { static $expired_cleaned = false; if (!$_items) { return $_items; } if (!is_array($_items)) { $items = array(&$_items); } else { $items =& $_items; } $user = JFactory::getUser(); $cparams = JComponentHelper::getParams('com_flexicontent'); $print_logging_info = $cparams->get('print_logging_info'); if ($print_logging_info) { global $fc_run_times; $start_microtime = microtime(true); } // Calculate access for current user if it was not given or if given access is invalid if (FLEXI_J16GE) { $aid = is_array($aid) ? $aid : JAccess::getAuthorisedViewLevels($user->id); } else { $aid = $aid !== false ? (int) $aid : (int) $user->get('aid'); } // Apply cache to public (unlogged) users only /*$apply_cache = !$user->id && FLEXI_CACHE; if ($apply_cache) { $itemcache = JFactory::getCache('com_flexicontent_items'); // Get Joomla Cache of '...items' Caching Group $itemcache->setCaching(1); // Force cache ON $itemcache->setLifeTime(FLEXI_CACHE_TIME); // Set expire time (default is 1 hour) $filtercache = JFactory::getCache('com_flexicontent_filters'); // Get Joomla Cache of '...filters' Caching Group $filtercache->setCaching(1); // Force cache ON $filtercache->setLifeTime(FLEXI_CACHE_TIME); // Set expire time (default is 1 hour) // Auto-clean expired item & filters cache, only done here once if (FLEXI_GC && !$expired_cleaned) { $itemcache->gc(); $filtercache->gc(); $expired_cleaned = true; } // ... now retrieved CACHED ... code removed ... }*/ // @TODO : move to the constructor // This is optimized regarding the use of SINGLE QUERY to retrieve the core item data $vars['tags'] = FlexicontentFields::_getTags($items); $vars['cats'] = FlexicontentFields::_getCategories($items); $vars['favourites'] = FlexicontentFields::_getFavourites($items); $vars['favoured'] = FlexicontentFields::_getFavoured($items); $vars['authors'] = FlexicontentFields::_getAuthors($items); $vars['modifiers'] = FlexicontentFields::_getModifiers($items); $vars['typenames'] = FlexicontentFields::_getTypenames($items); $vars['votes'] = FlexicontentFields::_getVotes($items); $vars['custom'] = FlexicontentFields::_getCustomValues($items); FlexicontentFields::getItemFields($items, $vars, $view, $aid); if ($print_logging_info) { @($fc_run_times['field_values_params'] += round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10); } $_rendered = array(); if ($params) { $always_create_fields_display = $cparams->get('always_create_fields_display', 0); $flexiview = JRequest::getVar('view'); // CHECK if 'always_create_fields_display' enabled and create the display for all item's fields // *** This should be normally set to ZERO (never), to avoid a serious performance penalty !!! // 0: never, 1: always, 2: only in item view, 3: never unless in a template position, this effects function: renderPositions() if ($always_create_fields_display == 1 || $always_create_fields_display == 2 && $flexiview == FLEXI_ITEMVIEW && $view == FLEXI_ITEMVIEW) { $field_names = array(); foreach ($items as $i => $item) { if ($items[$i]->fields) { foreach ($items[$i]->fields as $field) { $values = isset($items[$i]->fieldvalues[$field->id]) ? $items[$i]->fieldvalues[$field->id] : array(); $field = FlexicontentFields::renderField($items[$i], $field, $values, $method = 'display', $view); $field_names[$field->name] = 1; } } } foreach ($field_names as $field_name => $_ignore) { $_rendered['ALL'][$field_name] = 1; } } // Render field positions $items = FlexicontentFields::renderPositions($items, $view, $params, $use_tmpl, $_rendered); } return $items; }
/** * Content Search method * The sql must return the following fields that are used in a common display * routine: href, title, section, created, text, browsernav * @param string Target search string * @param string mathcing option, exact|any|all * @param string ordering option, newest|oldest|popular|alpha|category * @param mixed An array if restricted to areas, null if search all */ function onContentSearch($text, $phrase = '', $ordering = '', $areas = null) { $db = JFactory::getDbo(); $app = JFactory::getApplication(); $user = JFactory::getUser(); // Get language $cntLang = substr(JFactory::getLanguage()->getTag(), 0, 2); // Current Content language (Can be natively switched in J2.5) $urlLang = JRequest::getWord('lang', ''); // Language from URL (Can be switched via Joomfish in J1.5) $lang = FLEXI_J16GE || empty($urlLang) ? $cntLang : $urlLang; // COMPONENT PARAMETERS $cparams = $app->isSite() ? $app->getParams('com_flexicontent') : JComponentHelper::getParams('com_flexicontent'); if (!defined('FLEXI_SECTION')) { define('FLEXI_SECTION', $cparams->get('flexi_section')); } // define section $show_noauth = $cparams->get('show_noauth', 0); // items the user cannot see ... $searchText = $text; $AllAreas = array_keys($this->_getAreas()); $AllTypes = array_keys($this->_getContentTypes()); if (is_array($areas)) { // search in selected areas $searchAreas = array_intersect($areas, $AllAreas); $searchTypes = array_intersect($areas, $AllTypes); if (!$searchAreas && !$searchTypes) { return array(); } if (!$searchAreas) { $searchAreas = $AllAreas; } if (!$searchTypes) { $searchTypes = $AllTypes; } } else { // search in all avaliable areas if no selected ones $searchAreas = $AllAreas; $searchTypes = $AllTypes; } foreach ($searchTypes as $id => $tipe) { $searchTypes[$id] = preg_replace('/\\D/', '', $tipe); } $types = implode(', ', $searchTypes); $filter_lang = $this->params->def('filter_lang', 1); $limit = $this->params->def('search_limit', 50); // Dates for publish up & down items $date = JFactory::getDate(); $nowDate = FLEXI_J16GE ? $date->toSql() : $date->toMySQL(); $nullDate = $db->getNullDate(); $text = trim($text); if ($text == '') { return array(); } $wheres = array(); switch ($phrase) { case 'exact': $text = FLEXI_J16GE ? $db->escape($text, true) : $db->getEscaped($text, true); $text = $db->Quote('%' . $text . '%', false); $wheres2 = array(); if (in_array('FlexisearchTitle', $searchAreas)) { $wheres2[] = 'i.title LIKE ' . $text; } if (in_array('FlexisearchDesc', $searchAreas)) { $wheres2[] = 'i.introtext LIKE ' . $text; $wheres2[] = 'i.fulltext LIKE ' . $text; } if (in_array('FlexisearchMeta', $searchAreas)) { $wheres2[] = 'i.metakey LIKE ' . $text; $wheres2[] = 'i.metadesc LIKE ' . $text; } if (in_array('FlexisearchFields', $searchAreas)) { $wheres2[] = "f.field_type IN ('text','textselect') AND f.issearch=1 AND fir.value LIKE " . $text; } if (in_array('FlexisearchTags', $searchAreas)) { $wheres2[] = 't.name LIKE ' . $text; } if (count($wheres2)) { $where = '(' . implode(') OR (', $wheres2) . ')'; } break; case 'all': case 'any': default: $words = explode(' ', $text); $wheres = array(); foreach ($words as $word) { $word = FLEXI_J16GE ? $db->escape($word, true) : $db->getEscaped($word, true); $word = $db->Quote('%' . $word . '%', false); $wheres2 = array(); if (in_array('FlexisearchTitle', $searchAreas)) { $wheres2[] = 'i.title LIKE ' . $word; } if (in_array('FlexisearchDesc', $searchAreas)) { $wheres2[] = 'i.introtext LIKE ' . $word; $wheres2[] = 'i.fulltext LIKE ' . $word; } if (in_array('FlexisearchMeta', $searchAreas)) { $wheres2[] = 'i.metakey LIKE ' . $word; $wheres2[] = 'i.metadesc LIKE ' . $word; } if (in_array('FlexisearchFields', $searchAreas)) { $wheres2[] = "f.field_type IN ('text','textselect') AND f.issearch=1 AND fir.value LIKE " . $word; } if (in_array('FlexisearchTags', $searchAreas)) { $wheres2[] = 't.name LIKE ' . $word; } if (count($wheres2)) { $wheres[] = '(' . implode(') OR (', $wheres2) . ')'; } } if (count($wheres)) { $where = '(' . implode($phrase == 'all' ? ') AND (' : ') OR (', $wheres) . ')'; } break; } if (!@$where) { return array(); } //if ( empty($where) ) $where = '1'; switch ($ordering) { //case 'relevance': $order = ' ORDER BY score DESC, i.title ASC'; break; case 'oldest': $order = 'i.created ASC'; break; case 'popular': $order = 'i.hits DESC'; break; case 'alpha': $order = 'i.title ASC'; break; case 'category': $order = 'c.title ASC, i.title ASC'; break; case 'newest': $order = 'i.created DESC'; break; default: $order = 'i.created DESC'; break; } // **************************************************************************************** // Create JOIN clause and WHERE clause part for filtering by current (viewing) access level // **************************************************************************************** $joinaccess = ''; $andaccess = ''; $select_access = ''; // Extra access columns for main category and content type (item access will be added as 'access') $select_access .= ', c.access as category_access, ty.access as type_access'; if (!$show_noauth) { // User not allowed to LIST unauthorized items if (FLEXI_J16GE) { $aid_arr = JAccess::getAuthorisedViewLevels($user->id); $aid_list = implode(",", $aid_arr); $andaccess .= ' AND ty.access IN (0,' . $aid_list . ')'; $andaccess .= ' AND c.access IN (0,' . $aid_list . ')'; $andaccess .= ' AND i.access IN (0,' . $aid_list . ')'; } else { $aid = (int) $user->get('aid'); if (FLEXI_ACCESS) { $joinaccess .= ' LEFT JOIN #__flexiaccess_acl AS gt ON ty.id = gt.axo AND gt.aco = "read" AND gt.axosection = "type"'; $joinaccess .= ' LEFT JOIN #__flexiaccess_acl AS gc ON c.id = gc.axo AND gc.aco = "read" AND gc.axosection = "category"'; $joinaccess .= ' LEFT JOIN #__flexiaccess_acl AS gi ON i.id = gi.axo AND gi.aco = "read" AND gi.axosection = "item"'; $andaccess .= ' AND (gt.aro IN ( ' . $user->gmid . ' ) OR ty.access <= ' . $aid . ')'; $andaccess .= ' AND (gc.aro IN ( ' . $user->gmid . ' ) OR c.access <= ' . $aid . ')'; $andaccess .= ' AND (gi.aro IN ( ' . $user->gmid . ' ) OR i.access <= ' . $aid . ')'; } else { $andaccess .= ' AND ty.access <= ' . $aid; $andaccess .= ' AND c.access <= ' . $aid; $andaccess .= ' AND i.access <= ' . $aid; } } $select_access .= ', 1 AS has_access'; } else { // Access Flags for: content type, main category, item if (FLEXI_J16GE) { $aid_arr = JAccess::getAuthorisedViewLevels($user->id); $aid_list = implode(",", $aid_arr); $select_access .= ', ' . ' CASE WHEN ' . ' ty.access IN (' . $aid_list . ') AND ' . ' c.access IN (' . $aid_list . ') AND ' . ' i.access IN (' . $aid_list . ') ' . ' THEN 1 ELSE 0 END AS has_access'; } else { $aid = (int) $user->get('aid'); if (FLEXI_ACCESS) { $joinaccess .= ' LEFT JOIN #__flexiaccess_acl AS gt ON ty.id = gt.axo AND gt.aco = "read" AND gt.axosection = "type"'; $joinaccess .= ' LEFT JOIN #__flexiaccess_acl AS gc ON c.id = gc.axo AND gc.aco = "read" AND gc.axosection = "category"'; $joinaccess .= ' LEFT JOIN #__flexiaccess_acl AS gi ON i.id = gi.axo AND gi.aco = "read" AND gi.axosection = "item"'; $select_access .= ', ' . ' CASE WHEN ' . ' (gt.aro IN ( ' . $user->gmid . ' ) OR ty.access <= ' . (int) $aid . ') AND ' . ' (gc.aro IN ( ' . $user->gmid . ' ) OR c.access <= ' . (int) $aid . ') AND ' . ' (gi.aro IN ( ' . $user->gmid . ' ) OR i.access <= ' . (int) $aid . ') ' . ' THEN 1 ELSE 0 END AS has_access'; } else { $select_access .= ', ' . ' CASE WHEN ' . ' (ty.access <= ' . (int) $aid . ') AND ' . ' ( c.access <= ' . (int) $aid . ') AND ' . ' ( i.access <= ' . (int) $aid . ') ' . ' THEN 1 ELSE 0 END AS has_access'; } } } // ********************************************************************************************************************************************************** // Create WHERE clause part for filtering by current active language, and current selected contend types ( !! although this is possible via a filter too ...) // ********************************************************************************************************************************************************** $andlang = ''; if ($app->isSite() && (FLEXI_FISH || FLEXI_J16GE && $app->getLanguageFilter()) && $filter_lang) { $andlang .= ' AND ( i.language LIKE ' . $db->Quote($lang . '%') . ' OR i.language="*" ) '; $andlang .= ' AND ( c.language LIKE ' . $db->Quote($lang . '%') . ' OR c.language="*" ) '; } // search articles $results = array(); if ($limit > 0) { $query = $db->getQuery(true); $query->clear(); $query->select('' . ' i.id as id,' . ' i.title AS title,' . ' i.language AS language,' . ' i.metakey AS metakey,' . ' i.metadesc AS metadesc,' . ' i.modified AS created,' . ' t.name AS tagname,' . ' fir.value as field,' . ' i.access, ie.type_id,' . ' CONCAT(i.introtext, i.fulltext) AS text,' . ' CONCAT_WS( " / ", ' . $db->Quote(JText::_('FLEXICONTENT')) . ', c.title, i.title ) AS section,' . ' CASE WHEN CHAR_LENGTH(i.alias) THEN CONCAT_WS(\':\', i.id, i.alias) ELSE i.id END AS slug,' . ' CASE WHEN CHAR_LENGTH(c.alias) THEN CONCAT_WS(\':\', c.id, c.alias) ELSE c.id END AS catslug,' . ' "2" AS browsernav' . $select_access); $query->from('#__content AS i ' . ' JOIN #__categories AS c ON i.catid = c.id' . ' JOIN #__flexicontent_items_ext AS ie ON i.id = ie.item_id' . ' JOIN #__flexicontent_types AS ty ON ie.type_id = ty.id' . ' LEFT JOIN #__flexicontent_fields_item_relations AS fir ON i.id = fir.item_id' . ' LEFT JOIN #__flexicontent_fields AS f ON fir.field_id = f.id' . ' LEFT JOIN #__flexicontent_tags_item_relations AS tir ON i.id = tir.itemid' . ' LEFT JOIN #__flexicontent_tags AS t ON tir.tid = t.id ' . $joinaccess); $query->where(' (' . $where . ') ' . ' AND ie.type_id IN(' . $types . ') ' . ' AND i.state IN (1, -5) AND c.published = 1 ' . ' AND (i.publish_up = ' . $db->Quote($nullDate) . ' OR i.publish_up <= ' . $db->Quote($nowDate) . ') ' . ' AND (i.publish_down = ' . $db->Quote($nullDate) . ' OR i.publish_down >= ' . $db->Quote($nowDate) . ') ' . $andaccess . $andlang); $query->group('i.id'); $query->order($order); //echo "<pre style='white-space:normal!important;'>".$query."</pre>"; $db->setQuery($query, 0, $limit); $list = $db->loadObjectList(); if ($db->getErrorNum()) { echo $db->getErrorMsg(); } if ($list) { $item_cats = FlexicontentFields::_getCategories($list); foreach ($list as $key => $item) { // echo $item->title." ".$item->tagname."<br/>"; // Before checking for noHTML if (FLEXI_J16GE || $item->sectionid == FLEXI_SECTION) { $item->categories = isset($item_cats[$item->id]) ? $item_cats[$item->id] : array(); // in case of item categories missing $item->href = JRoute::_(FlexicontentHelperRoute::getItemRoute($item->slug, $item->catslug, 0, $item)); } else { $item->href = JRoute::_(ContentHelperRoute::getArticleRoute($item->slug, $item->catslug, $item->sectionid)); } if (searchHelper::checkNoHTML($item, $searchText, array('title', 'metadesc', 'metakey', 'tagname', 'field', 'text'))) { $results[$item->id] = $item; } } } } return $results; }
/** * Search method * * The sql must return the following fields that are used in a common display routine: * * href, title, section, created, text, browsernav * * @param string Target search string * @param string matching option, natural|natural_expanded|exact|any|all * @param string ordering option, newest|oldest|popular|alpha|category * @param mixed An array if restricted to areas, null if search all */ function onContentSearch($text, $phrase = '', $ordering = '', $areas = null) { $app = JFactory::getApplication(); $view = JRequest::getCMD('view'); $app->setUserState('fc_view_total_' . $view, 0); $app->setUserState('fc_view_limit_max_' . $view, 0); // Check if not requested search areas, inside this search areas of this plugin if (is_array($areas) && !array_intersect($areas, array_keys($this->onContentSearchAreas()))) { return array(); } // Initialize some variables $db = JFactory::getDBO(); $user = JFactory::getUser(); $menu = $app->getMenu()->getActive(); // Get the COMPONENT only parameters and merge current menu item parameters $params = clone JComponentHelper::getParams('com_flexicontent'); if ($menu) { $params->merge($menu->params); } // some parameter shortcuts for SQL query $show_noauth = $params->get('show_noauth', 0); $orderby_override = $params->get('orderby_override', 1); // Compatibility text search (LIKE %word%) for language without spaces $filter_word_like_any = $params->get('filter_word_like_any', 0); // ************************************************ // some parameter shortcuts common with search view // ************************************************ $canseltypes = $params->get('canseltypes', 1); $txtmode = $params->get('txtmode', 0); // 0: BASIC Index, 1: ADVANCED Index without search fields user selection, 2: ADVANCED Index with search fields user selection // Get if text searching according to specific (single) content type $show_txtfields = $params->get('show_txtfields', 1); //0:hide, 1:according to content, 2:use custom configuration $show_txtfields = $txtmode ? 0 : $show_txtfields; // disable this flag if using BASIC index for text search // Get if filtering according to specific (single) content type $show_filters = $params->get('show_filters', 1); //0:hide, 1:according to content, 2:use custom configuration // Force single type selection and showing the content type selector $type_based_search = $show_filters == 1 || $show_txtfields == 1; $canseltypes = $type_based_search ? 1 : $canseltypes; // ******************************************************************** // Get Content Types allowed for user selection in the Search Form // Also retrieve their configuration, plus the currently selected types // ******************************************************************** // Get them from configuration $contenttypes = $params->get('contenttypes', array()); // Sanitize them $contenttypes = !is_array($contenttypes) ? array($contenttypes) : $contenttypes; $contenttypes = array_unique(array_map('intval', $contenttypes)); // Make sure these are integers since we will be using them UNQUOTED // Force hidden content type selection if only 1 content type was initially configured $canseltypes = count($contenttypes) == 1 ? 0 : $canseltypes; // Type data and configuration (parameters), if no content types specified then all will be retrieved $typeData = flexicontent_db::getTypeData(implode(",", $contenttypes)); $contenttypes = array(); foreach ($typeData as $tdata) { $contenttypes[] = $tdata->id; } // Get Content Types to use either those currently selected in the Search Form, or those hard-configured in the search menu item if ($canseltypes) { $form_contenttypes = JRequest::getVar('contenttypes', array()); // Sanitize them $form_contenttypes = !is_array($form_contenttypes) ? array($form_contenttypes) : $form_contenttypes; $form_contenttypes = array_unique(array_map('intval', $form_contenttypes)); // Make sure these are integers since we will be using them UNQUOTED $_contenttypes = array_intersect($contenttypes, $form_contenttypes); if (!empty($_contenttypes)) { $contenttypes = $_contenttypes; } // catch empty case: no content types were given or not-allowed content types were passed } // Check for zero content type (can occur during sanitizing content ids to integers) if (!empty($contenttypes)) { foreach ($contenttypes as $i => $v) { if (!strlen($contenttypes[$i])) { unset($contenttypes[$i]); } } } // Type based seach, get a single content type (first one, if more than 1 were given ...) if ($type_based_search && !empty($contenttypes)) { $single_contenttype = reset($contenttypes); $contenttypes = array($single_contenttype); } else { $single_contenttype = false; } // ************************************* // Text Search Fields of the search form // ************************************* if (!$txtmode) { $txtflds = array(); $fields_text = array(); } else { $txtflds = ''; if ($show_txtfields) { if ($show_txtfields == 1) { $txtflds = $single_contenttype ? $typeData[$single_contenttype]->params->get('searchable', '') : ''; } else { $txtflds = $params->get('txtflds', ''); } } // Sanitize them $txtflds = preg_replace("/[\"'\\\\]/u", "", $txtflds); $txtflds = array_unique(preg_split("/\\s*,\\s*/u", $txtflds)); if (!strlen($txtflds[0])) { unset($txtflds[0]); } // Create a comma list of them $txtflds_list = count($txtflds) ? "'" . implode("','", $txtflds) . "'" : ''; // Retrieve field properties/parameters, verifying the support to be used as Text Search Fields // This will return all supported fields if field limiting list is empty $fields_text = FlexicontentFields::getSearchFields($key = 'id', $indexer = 'advanced', $txtflds_list, $contenttypes, $load_params = true, 0, 'search'); if (empty($fields_text)) { // all entries of field limiting list were invalid , get ALL if (!empty($contenttypes)) { $fields_text = FlexicontentFields::getSearchFields($key = 'id', $indexer = 'advanced', null, $contenttypes, $load_params = true, 0, 'search'); } else { $fields_text = array(); } } } // ******************************** // Filter Fields of the search form // ******************************** // Get them from type configuration or from search menu item $filtflds = ''; if ($show_filters) { if ($show_filters == 1) { $filtflds = $single_contenttype ? $typeData[$single_contenttype]->params->get('filters', '') : ''; } else { $filtflds = $params->get('filtflds', ''); } } // Sanitize them $filtflds = preg_replace("/[\"'\\\\]/u", "", $filtflds); $filtflds = array_unique(preg_split("/\\s*,\\s*/u", $filtflds)); if (!strlen($filtflds[0])) { unset($filtflds[0]); } // Create a comma list of them $filtflds_list = count($filtflds) ? "'" . implode("','", $filtflds) . "'" : ''; // Retrieve field properties/parameters, verifying the support to be used as Filter Fields // This will return all supported fields if field limiting list is empty if (count($filtflds)) { $filters_tmp = FlexicontentFields::getSearchFields($key = 'name', $indexer = 'advanced', $filtflds_list, $contenttypes, $load_params = true, 0, 'filter'); // Use custom order $filters = array(); if ($canseltypes && $show_filters) { foreach ($filtflds as $field_name) { if (empty($filters_tmp[$field_name])) { continue; } $filter_id = $filters_tmp[$field_name]->id; $filters[$filter_id] = $filters_tmp[$field_name]; } } else { foreach ($filters_tmp as $filter) { $filters[$filter->id] = $filter; // index by filter_id in this case too (for consistency, although we do not use the array index ?) } } unset($filters_tmp); } // If configured filters were not found/invalid for the current content type(s) // then retrieve all fields marked as filterable for the give content type(s) this is useful to list per content type filters automatically, even when not set or misconfigured if (empty($filters)) { if (!empty($contenttypes)) { $filters = FlexicontentFields::getSearchFields($key = 'id', $indexer = 'advanced', null, $contenttypes, $load_params = true, 0, 'filter'); } else { $filters = array(); } } // ********************** // Load Plugin parameters // ********************** $plugin = JPluginHelper::getPlugin('search', 'flexiadvsearch'); $pluginParams = new JRegistry($plugin->params); // Shortcuts for plugin parameters $search_limit = $params->get('search_limit', $pluginParams->get('search_limit', 20)); // Limits the returned results of this seach plugin $filter_lang = $params->get('filter_lang', $pluginParams->get('filter_lang', 1)); // Language filtering enabled $search_archived = $params->get('search_archived', $pluginParams->get('search_archived', 1)); // Include archive items into the search $browsernav = $params->get('browsernav', $pluginParams->get('browsernav', 2)); // Open search in window (for value 1) // *************************************************************************************************************** // Varous other variable USED in the SQL query like (a) current frontend language and (b) -this- plugin specific ordering, (c) null / now dates, (d) etc // *************************************************************************************************************** // Get current frontend language (fronted user selected) $lang = flexicontent_html::getUserCurrentLang(); // NULL and CURRENT dates, // NOTE: the current date needs to use built-in MYSQL function, otherwise filter caching can not work because the CURRENT DATETIME is continuously different !!! //$now = JFactory::getDate()->toSql(); $_nowDate = 'UTC_TIMESTAMP()'; //$db->Quote($now); $nullDate = $db->getNullDate(); // Section name $searchFlexicontent = JText::_('FLEXICONTENT'); // REMOVED / COMMENTED OUT this feature: // Require any OR all Filters ... this can be user selectable //$show_filtersop = $params->get('show_filtersop', 1); //$default_filtersop = $params->get('default_filtersop', 'all'); //$FILTERSOP = !$show_filtersop ? $default_filtersop : JRequest::getVar('filtersop', $default_filtersop); // **************************************** // Create WHERE clause part for Text Search // **************************************** $si_tbl = !$txtmode ? 'flexicontent_items_ext' : 'flexicontent_advsearch_index'; $search_prefix = JComponentHelper::getParams('com_flexicontent')->get('add_search_prefix') ? 'vvv' : ''; // SEARCH WORD Prefix $text = preg_replace('/(\\b[^\\s,\\.]+\\b)/u', $search_prefix . '$0', trim($text)); if (strlen($text)) { $ts = !$txtmode ? 'ie' : 'ts'; $escaped_text = $db->escape($text, true); $quoted_text = $db->Quote($escaped_text, false); switch ($phrase) { case 'natural': if ($filter_word_like_any) { $_text_match = ' LOWER (' . $ts . '.search_index) LIKE ' . $db->Quote('%' . $escaped_text . '%', false); } else { $_text_match = ' MATCH (' . $ts . '.search_index) AGAINST (' . $quoted_text . ') '; } break; case 'natural_expanded': $_text_match = ' MATCH (' . $ts . '.search_index) AGAINST (' . $quoted_text . ' WITH QUERY EXPANSION) '; break; case 'exact': $words = preg_split('/\\s\\s*/u', $text); $stopwords = array(); $shortwords = array(); if (!$search_prefix) { $words = flexicontent_db::removeInvalidWords($words, $stopwords, $shortwords, $si_tbl, 'search_index', $isprefix = 0); } if (empty($words)) { // All words are stop-words or too short, we could try to execute a query that only contains a LIKE %...% , but it would be too slow JRequest::setVar('ignoredwords', implode(' ', $stopwords)); JRequest::setVar('shortwords', implode(' ', $shortwords)); $_text_match = ' 0=1 '; } else { // speed optimization ... 2-level searching: first require ALL words, then require exact text $newtext = '+' . implode(' +', $words); $quoted_text = $db->escape($newtext, true); $quoted_text = $db->Quote($quoted_text, false); $exact_text = $db->Quote('%' . $escaped_text . '%', false); $_text_match = ' MATCH (' . $ts . '.search_index) AGAINST (' . $quoted_text . ' IN BOOLEAN MODE) AND ' . $ts . '.search_index LIKE ' . $exact_text; } break; case 'all': $words = preg_split('/\\s\\s*/u', $text); $stopwords = array(); $shortwords = array(); if (!$search_prefix) { $words = flexicontent_db::removeInvalidWords($words, $stopwords, $shortwords, $si_tbl, 'search_index', $isprefix = 1); } JRequest::setVar('ignoredwords', implode(' ', $stopwords)); JRequest::setVar('shortwords', implode(' ', $shortwords)); $newtext = '+' . implode('* +', $words) . '*'; $quoted_text = $db->escape($newtext, true); $quoted_text = $db->Quote($quoted_text, false); $_text_match = ' MATCH (' . $ts . '.search_index) AGAINST (' . $quoted_text . ' IN BOOLEAN MODE) '; break; case 'any': default: if ($filter_word_like_any) { $_text_match = ' LOWER (' . $ts . '.search_index) LIKE ' . $db->Quote('%' . $escaped_text . '%', false); } else { $words = preg_split('/\\s\\s*/u', $text); $stopwords = array(); $shortwords = array(); if (!$search_prefix) { $words = flexicontent_db::removeInvalidWords($words, $stopwords, $shortwords, $si_tbl, 'search_index', $isprefix = 1); } JRequest::setVar('ignoredwords', implode(' ', $stopwords)); JRequest::setVar('shortwords', implode(' ', $shortwords)); $newtext = implode('* ', $words) . '*'; $quoted_text = $db->escape($newtext, true); $quoted_text = $db->Quote($quoted_text, false); $_text_match = ' MATCH (' . $ts . '.search_index) AGAINST (' . $quoted_text . ' IN BOOLEAN MODE) '; } break; } // Construct TEXT SEARCH limitation SUB-QUERY (contained in a AND-WHERE clause) $text_where = ' AND ' . $_text_match; } else { $text_where = ''; } // ******************* // Create ORDER clause // ******************* // FLEXIcontent search view, use FLEXIcontent ordering $orderby_join = ''; $orderby_col = ''; if (JRequest::getVar('option') == 'com_flexicontent') { $order = ''; $orderby = flexicontent_db::buildItemOrderBy($params, $order, $_request_var = 'orderby', $_config_param = 'orderby', $_item_tbl_alias = 'i', $_relcat_tbl_alias = 'rel', $_default_order = '', $_default_order_dir = '', $sfx = '', $support_2nd_lvl = false); // Create JOIN for ordering items by a custom field (Level 1) if ('field' == $order[1]) { $orderbycustomfieldid = (int) $params->get('orderbycustomfieldid', 0); $orderby_join .= ' LEFT JOIN #__flexicontent_fields_item_relations AS f ON f.item_id = i.id AND f.field_id=' . $orderbycustomfieldid; } // Create JOIN for ordering items by a custom field (Level 2) if ('field' == $order[2]) { $orderbycustomfieldid_2nd = (int) $params->get('orderbycustomfieldid' . '_2nd', 0); $orderby_join .= ' LEFT JOIN #__flexicontent_fields_item_relations AS f2 ON f2.item_id = i.id AND f2.field_id=' . $orderbycustomfieldid_2nd; } // Create JOIN for ordering items by author's name if (in_array('author', $order) || in_array('rauthor', $order)) { $orderby_col = ''; $orderby_join .= ' LEFT JOIN #__users AS u ON u.id = i.created_by'; } // Create JOIN for ordering items by a most commented if (in_array('commented', $order)) { $orderby_col = ', count(com.object_id) AS comments_total'; $orderby_join .= ' LEFT JOIN #__jcomments AS com ON com.object_id = i.id'; } // Create JOIN for ordering items by a most rated if (in_array('rated', $order)) { $orderby_col = ', (cr.rating_sum / cr.rating_count) * 20 AS votes'; $orderby_join .= ' LEFT JOIN #__content_rating AS cr ON cr.content_id = i.id'; } // Create JOIN for ordering items by their ordering attribute (in item's main category) if (in_array('order', $order)) { $orderby_join .= ' LEFT JOIN #__flexicontent_cats_item_relations AS rel ON rel.itemid = i.id AND rel.catid = i.catid'; } } else { switch ($ordering) { //case 'relevance': $orderby = ' ORDER BY score DESC, i.title ASC'; break; case 'oldest': $orderby = 'i.created ASC'; break; case 'popular': $orderby = 'i.hits DESC'; break; case 'alpha': $orderby = 'i.title ASC'; break; case 'category': $orderby = 'c.title ASC, i.title ASC'; break; case 'newest': $orderby = 'i.created DESC'; break; default: $orderby = 'i.created DESC'; break; } $orderby = ' ORDER BY ' . $orderby; } // **************************************************************************************** // Create JOIN clause and WHERE clause part for filtering by current (viewing) access level // **************************************************************************************** $joinaccess = ''; $andaccess = ''; $select_access = ''; // Extra access columns for main category and content type (item access will be added as 'access') $select_access .= ', c.access as category_access, ty.access as type_access'; if (!$show_noauth) { // User not allowed to LIST unauthorized items $aid_arr = JAccess::getAuthorisedViewLevels($user->id); $aid_list = implode(",", $aid_arr); $andaccess .= ' AND ty.access IN (0,' . $aid_list . ')'; $andaccess .= ' AND c.access IN (0,' . $aid_list . ')'; $andaccess .= ' AND i.access IN (0,' . $aid_list . ')'; $select_access .= ', 1 AS has_access'; } else { // Access Flags for: content type, main category, item $aid_arr = JAccess::getAuthorisedViewLevels($user->id); $aid_list = implode(",", $aid_arr); $select_access .= ', ' . ' CASE WHEN ' . ' ty.access IN (' . $aid_list . ') AND ' . ' c.access IN (' . $aid_list . ') AND ' . ' i.access IN (' . $aid_list . ') ' . ' THEN 1 ELSE 0 END AS has_access'; } // ********************************************************************************************************************************************************** // Create WHERE clause part for filtering by current active language, and current selected contend types ( !! although this is possible via a filter too ...) // ********************************************************************************************************************************************************** $andlang = ''; if ($app->isSite() && (FLEXI_FISH || FLEXI_J16GE && $app->getLanguageFilter()) && $filter_lang) { $andlang .= ' AND ( ie.language LIKE ' . $db->Quote($lang . '%') . (FLEXI_J16GE ? ' OR ie.language="*" ' : '') . ' ) '; } // Filter by currently selected content types $andcontenttypes = count($contenttypes) ? ' AND ie.type_id IN (' . implode(",", $contenttypes) . ') ' : ''; // *********************************************************************** // Create the AND-WHERE clause parts for the currentl active Field Filters // *********************************************************************** $return_sql = 2; $filters_where = array(); foreach ($filters as $field) { // Get value of current filter, and SKIP it if value is EMPTY $filtervalue = JRequest::getVar('filter_' . $field->id, ''); $empty_filtervalue_array = is_array($filtervalue) && !strlen(trim(implode('', $filtervalue))); $empty_filtervalue_string = !is_array($filtervalue) && !strlen(trim($filtervalue)); if ($empty_filtervalue_array || $empty_filtervalue_string) { continue; } // Call field filtering of advanced search to find items matching the field filter (an SQL SUB-QUERY is returned) $field_filename = $field->iscore ? 'core' : $field->field_type; $filtered = FLEXIUtilities::call_FC_Field_Func($field_filename, 'getFilteredSearch', array(&$field, &$filtervalue, &$return_sql)); // An empty return value means no matching values were found $filtered = empty($filtered) ? ' AND 0 ' : $filtered; // A string mean a subquery was returned, while an array means that item ids we returned $filters_where[$field->id] = is_array($filtered) ? ' AND i.id IN (' . implode(',', $filtered) . ')' : $filtered; /*if ($filters_where[$field->id]) { echo "\n<br/>Filter:". $field->name ." : "; print_r($filtervalue); echo "<br>".$filters_where[$field->id]."<br/>"; }*/ } //echo "\n<br/><br/>Filters Active: ". count($filters_where)."<br/>"; //echo "<pre>"; print_r($filters_where); //exit; // ****************************************************** // Create Filters JOIN clauses and AND-WHERE clause parts // ****************************************************** // JOIN clause - USED - to limit returned 'text' to the text of TEXT-SEARCHABLE only fields ... (NOT shared with filters) if (!$txtmode) { $onBasic_textsearch = $text_where; $onAdvanced_textsearch = ''; $join_textsearch = ''; $join_textfields = ''; } else { $onBasic_textsearch = ''; $onAdvanced_textsearch = $text_where; $join_textsearch = ' JOIN #__flexicontent_advsearch_index as ts ON ts.item_id = i.id ' . (count($fields_text) ? 'AND ts.field_id IN (' . implode(',', array_keys($fields_text)) . ')' : ''); $join_textfields = ' JOIN #__flexicontent_fields as f ON f.id=ts.field_id'; } // JOIN clauses ... (shared with filters) $join_clauses = '' . ' JOIN #__categories AS c ON c.id = i.catid' . ' JOIN #__flexicontent_items_ext AS ie ON ie.item_id = i.id' . ' JOIN #__flexicontent_types AS ty ON ie.type_id = ty.id'; $join_clauses_with_text = '' . ' JOIN #__categories AS c ON c.id = i.catid' . ' JOIN #__flexicontent_items_ext AS ie ON ie.item_id = i.id' . $onBasic_textsearch . ' JOIN #__flexicontent_types AS ty ON ie.type_id = ty.id' . ($text_where ? $join_textsearch . $onAdvanced_textsearch . $join_textfields : ''); // AND-WHERE sub-clauses ... (shared with filters) $where_conf = ' WHERE 1 ' . ' AND i.state IN (1,-5' . ($search_archived ? ',' . (FLEXI_J16GE ? 2 : -1) : '') . ') ' . ' AND c.published = 1 ' . ' AND ( i.publish_up = ' . $db->Quote($nullDate) . ' OR i.publish_up <= ' . $_nowDate . ' )' . ' AND ( i.publish_down = ' . $db->Quote($nullDate) . ' OR i.publish_down >= ' . $_nowDate . ' )' . $andaccess . $andlang . $andcontenttypes; // AND-WHERE sub-clauses for text search ... (shared with filters) $and_where_filters = count($filters_where) ? implode(" ", $filters_where) : ''; // ************************************************ // Set variables used by filters creation mechanism // ************************************************ global $fc_searchview; $fc_searchview['join_clauses'] = $join_clauses; $fc_searchview['join_clauses_with_text'] = $join_clauses_with_text; $fc_searchview['where_conf_only'] = $where_conf; // WHERE of the view (mainly configuration dependent) $fc_searchview['filters_where'] = $filters_where; // WHERE of the filters $fc_searchview['search'] = $text_where; // WHERE for text search $fc_searchview['params'] = $params; // view's parameters // ***************************************************************************************************** // Execute search query. NOTE this is skipped it if (a) no text-search and no (b) no filters are active // ***************************************************************************************************** // Do not check for 'contentypes' this are based on configuration and not on form submitted data, // considering contenttypes or other configuration based parameters, will return all items on initial search view display ! if (!count($filters_where) && !strlen($text)) { return array(); } $print_logging_info = $params->get('print_logging_info'); if ($print_logging_info) { global $fc_run_times; $start_microtime = microtime(true); } // ***************************************** // Overcome possible group concat limitation // ***************************************** $query = "SET SESSION group_concat_max_len = 9999999"; $db->setQuery($query); $db->execute(); // ************* // Get the items // ************* $query = 'SELECT SQL_CALC_FOUND_ROWS i.id' . $orderby_col . ' FROM #__content AS i' . $join_clauses_with_text . $orderby_join . $joinaccess . $where_conf . $and_where_filters . ' GROUP BY i.id ' . $orderby; //echo "Adv search plugin main SQL query: ".nl2br($query)."<br/><br/>"; // NOTE: The plugin will return a PRECONFIGURED limited number of results, the SEARCH VIEW to do the pagination, splicing (appropriately) the data returned by all search plugins try { // Get items, we use direct query because some extensions break the SQL_CALC_FOUND_ROWS, so let's bypass them (at this point it is OK) // *** Usage of FOUND_ROWS() will fail when (e.g.) Joom!Fish or Falang are installed, in this case we will be forced to re-execute the query ... // PLUS, we don't need Joom!Fish or Falang layer at --this-- STEP which may slow down the query considerably in large sites $query_limited = $query . ' LIMIT ' . $search_limit . ' OFFSET 0'; $rows = flexicontent_db::directQuery($query_limited); $item_ids = array(); foreach ($rows as $row) { $item_ids[] = $row->id; } // Get current items total for pagination $db->setQuery("SELECT FOUND_ROWS()"); $fc_searchview['view_total'] = $db->loadResult(); $app->setUserState('fc_view_total_' . $view, $fc_searchview['view_total']); } catch (Exception $e) { // Get items via normal joomla SQL layer $db->setQuery(str_replace('SQL_CALC_FOUND_ROWS', '', $query), 0, $search_limit); $item_ids = $db->loadColumn(0); } if (!count($item_ids)) { return array(); } // No items found // ***************** // Get the item data // ***************** $query_data = 'SELECT i.id, i.title AS title, i.created, i.id AS fc_item_id, i.access, ie.type_id, i.language' . (!$txtmode ? ', ie.search_index AS text' : ', GROUP_CONCAT(ts.search_index ORDER BY f.ordering ASC SEPARATOR \' \') AS text') . ', CASE WHEN CHAR_LENGTH(i.alias) THEN CONCAT_WS(\':\', i.id, i.alias) ELSE i.id END as slug' . ', CASE WHEN CHAR_LENGTH(c.alias) THEN CONCAT_WS(\':\', c.id, c.alias) ELSE c.id END as categoryslug' . ', CONCAT_WS( " / ", ' . $db->Quote($searchFlexicontent) . ', c.title, i.title ) AS section' . $select_access . ' FROM #__content AS i' . $join_clauses . $join_textsearch . $join_textfields . ' WHERE i.id IN (' . implode(',', $item_ids) . ') ' . ' GROUP BY i.id ' . ' ORDER BY FIELD(i.id, ' . implode(',', $item_ids) . ')'; //echo nl2br($query)."<br/><br/>"; $db->setQuery($query_data); $list = $db->loadObjectList(); if ($db->getErrorNum()) { echo $db->getErrorMsg(); } if ($print_logging_info) { @($fc_run_times['search_query_runtime'] += round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10); } // ************************************* // Create item links and other variables // ************************************* //echo "<pre>"; print_r($list); echo "</pre>"; if ($list) { if (count($list) >= $search_limit) { $app->setUserState('fc_view_limit_max_' . $view, $search_limit); } $item_cats = FlexicontentFields::_getCategories($list); foreach ($list as $key => $item) { $item->text = preg_replace('/\\b' . $search_prefix . '/', '', $item->text); $item->categories = isset($item_cats[$item->id]) ? $item_cats[$item->id] : array(); // in case of item categories missing // If joomla article view is allowed allowed and then search view may optional create Joomla article links if ($typeData[$item->type_id]->params->get('allow_jview', 0) && $typeData[$item->type_id]->params->get('search_jlinks', 1)) { $item->href = JRoute::_(ContentHelperRoute::getArticleRoute($item->slug, $item->categoryslug, $item->language)); } else { $item->href = JRoute::_(FlexicontentHelperRoute::getItemRoute($item->slug, $item->categoryslug, 0, $item)); } $item->browsernav = $browsernav; } } return $list; }
/** * Method to fetch the fields from an item object * * @access private * @return object * @since 1.5 */ static function &getItemFields(&$items, &$vars = null, $view = FLEXI_ITEMVIEW, $aid = false) { if (empty($items)) { return; } static $type_fields = array(); $dispatcher = JDispatcher::getInstance(); $db = JFactory::getDBO(); $user = JFactory::getUser(); // This is optimized regarding the use of SINGLE QUERY to retrieve the core item data if ($vars == null) { $vars['tags'] = FlexicontentFields::_getTags($items, $view); $vars['cats'] = FlexicontentFields::_getCategories($items, $view); $vars['favourites'] = FlexicontentFields::_getFavourites($items, $view); $vars['favoured'] = FlexicontentFields::_getFavoured($items, $view); $vars['authors'] = FlexicontentFields::_getAuthors($items, $view); $vars['modifiers'] = FlexicontentFields::_getModifiers($items, $view); $vars['typenames'] = FlexicontentFields::_getTypenames($items, $view); $vars['votes'] = FlexicontentFields::_getVotes($items, $view); $vars['custom'] = FlexicontentFields::_getCustomValues($items, $view); } foreach ($items as $i => $item) { if (!FLEXI_J16GE && $item->sectionid != FLEXI_SECTION) { continue; } $item_id = $item->id; $cats = isset($vars['cats'][$item_id]) ? $vars['cats'][$item_id] : array(); $tags = isset($vars['tags'][$item_id]) ? $vars['tags'][$item_id] : array(); $favourites = isset($vars['favourites'][$item_id]) ? $vars['favourites'][$item_id]->favs : 0; $favoured = isset($vars['favoured'][$item_id]) ? $vars['favoured'][$item_id]->fav : 0; $author = isset($vars['authors'][$item_id]) ? $vars['authors'][$item_id] : ''; $modifier = isset($vars['modifiers'][$item_id]) ? $vars['modifiers'][$item_id] : ''; $typename = isset($vars['typenames'][$item_id]) ? $vars['typenames'][$item_id] : ''; $vote = isset($vars['votes'][$item_id]) ? $vars['votes'][$item_id] : ''; $custom = isset($vars['custom'][$item_id]) ? $vars['custom'][$item_id] : array(); // ONCE per Content Item Type if (!isset($type_fields[$item->type_id])) { // Field's has_access flag $aid_arr = is_array($aid) ? $aid : JAccess::getAuthorisedViewLevels($user->id); $aid_list = implode(",", $aid_arr); $select_access = ', CASE WHEN fi.access IN (0,' . $aid_list . ') THEN 1 ELSE 0 END AS has_access'; $query = 'SELECT fi.*' . $select_access . ' FROM #__flexicontent_fields AS fi' . ' JOIN #__flexicontent_fields_type_relations AS ftrel ON ftrel.field_id = fi.id AND ftrel.type_id = ' . $item->type_id . ' WHERE fi.published = 1' . ' GROUP BY fi.id' . ' ORDER BY ftrel.ordering, fi.ordering, fi.name'; $db->setQuery($query); $type_fields[$item->type_id] = $db->loadObjectList('name'); //echo "<pre>"; print_r( array_keys($type_fields[$item->type_id]) ); exit; } $item->fields = array(); if ($type_fields[$item->type_id]) { foreach ($type_fields[$item->type_id] as $field_name => $field_data) { $item->fields[$field_name] = clone $field_data; } } $item->fields = $item->fields ? $item->fields : array(); if (!isset($item->parameters)) { $item->parameters = new JRegistry($item->attribs); } $item->params = $item->parameters; $item->text = $item->introtext . chr(13) . chr(13) . $item->fulltext; $item->tags = $tags; $item->cats = $cats; $item->favs = $favourites; $item->fav = $favoured; $item->creator = @$author->alias ? $author->alias : (@$author->name ? $author->name : ''); $item->author =& $item->creator; // An alias ... of creator $item->modifier = @$modifier->name ? $modifier->name : $item->creator; // If never modified, set modifier to be the creator $item->modified = $item->modified != $db->getNulldate() ? $item->modified : $item->created; // If never modified, set modification date to be the creation date $item->cmail = @$author->email ? $author->email : ''; $item->cuname = @$author->username ? $author->username : ''; $item->mmail = @$modifier->email ? $modifier->email : $item->cmail; $item->muname = @$modifier->muname ? $modifier->muname : $item->cuname; $item->typename = @$typename->name ? $typename->name : JText::_('Article'); $item->vote = @$vote ? $vote : ''; // some aliases to much CORE field names $item->categories =& $item->cats; $item->favourites =& $item->favs; $item->document_type =& $item->typename; $item->voting =& $item->vote; // custom field values $item->fieldvalues = $custom; } return $items; }