示例#1
0
 /**
  * count the rows
  *
  * @access public
  * @return void
  * @since 1.0
  */
 function countrows()
 {
     $start_microtime = microtime(true);
     // Check for request forgeries
     //JRequest::checkToken() or jexit( 'Invalid Token' );
     //$params = JComponentHelper::getParams( 'com_flexicontent' );
     @ob_end_clean();
     $indexer = JRequest::getVar('indexer', 'advanced');
     $rebuildmode = JRequest::getVar('rebuildmode', '');
     $session = JFactory::getSession();
     // Retrieve fields, that are assigned as (advanced/basic) searchable/filterable
     if ($rebuildmode == 'quick' && $indexer == 'advanced') {
         $nse_fields = FlexicontentFields::getSearchFields('id', $indexer, null, null, $_load_params = false, 0, $search_type = 'non-search');
         $nsp_fields = FlexicontentFields::getSearchFields('id', $indexer, null, null, $_load_params = false, 0, $search_type = 'dirty-nosupport');
         $session->set($indexer . '_nse_fields', $nse_fields, 'flexicontent');
         $session->set($indexer . '_nsp_fields', $nsp_fields, 'flexicontent');
         $fields = FlexicontentFields::getSearchFields('id', $indexer, null, null, $_load_params = true, 0, $search_type = 'dirty-search');
     } else {
         $fields = FlexicontentFields::getSearchFields('id', $indexer, null, null, $_load_params = true, 0, $search_type = 'all-search');
     }
     // Get the field ids of the searchable fields
     $fieldids = array_keys($fields);
     // Get ids of searchable and ids of item having values for these fields
     $itemsmodel = $this->getModel('items');
     // Get items model to call needed methods
     $itemids = $itemsmodel->getFieldsItems($fieldids);
     // Get the items ids that have value for any of the searchable fields
     // Set item ids into session to avoid recalculation ...
     $session->set($indexer . '_items_to_index', $itemids, 'flexicontent');
     // Set field information into session to avoid recalculation ...
     $session->set($indexer . '_fields', $fields, 'flexicontent');
     echo 'success';
     //echo count($fieldids)*count($itemids).'|';
     // WARNING: json_encode will output object if given an array with gaps in the indexing
     //echo '|'.json_encode($itemids);
     //echo '|'.json_encode($fieldids);
     echo '|' . count($itemids);
     echo '|' . count($fieldids);
     $elapsed_microseconds = round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10;
     $session->set($indexer . '_total_runtime', $elapsed_microseconds, 'flexicontent');
     exit;
 }
 /**
  * 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;
 }
 /**
  * Creates the page's display
  *
  * @since 1.0
  */
 function display($tpl = null)
 {
     //initialize variables
     $option = JRequest::getVar('option');
     $app = JFactory::getApplication();
     $document = JFactory::getDocument();
     $db = JFactory::getDBO();
     $menus = $app->getMenu();
     $menu = $menus->getActive();
     $uri = JFactory::getURI();
     $pathway = $app->getPathway();
     // Get view's Model
     $model = $this->getModel();
     $error = '';
     $rows = null;
     $total = 0;
     $form_id = $form_name = "searchForm";
     // Get parameters via model
     $params = $model->getParams();
     // Get various data from the model
     $areas = $this->get('areas');
     $state = $this->get('state');
     $searchword = $state->get('keyword');
     $searchphrase = $state->get('match');
     $searchordering = $state->get('ordering');
     // ***********************************************************
     // some parameter shortcuts common with advanced search plugin
     // ***********************************************************
     $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;
     // ********************************
     // Load needed JS libs & CSS styles
     // ********************************
     FLEXI_J30GE ? JHtml::_('behavior.framework', true) : JHTML::_('behavior.mootools');
     flexicontent_html::loadFramework('jQuery');
     flexicontent_html::loadFramework('flexi_tmpl_common');
     // Add css files to the document <head> section (also load CSS joomla template override)
     if (!$params->get('disablecss', '')) {
         $document->addStyleSheetVersion($this->baseurl . '/components/com_flexicontent/assets/css/flexicontent.css', FLEXI_VERSION);
         $document->addStyleSheetVersion($this->baseurl . '/components/com_flexicontent/assets/css/flexi_filters.css', FLEXI_VERSION);
         //$document->addCustomTag('<!--[if IE]><style type="text/css">.floattext {zoom:1;}</style><![endif]-->');
     }
     if (file_exists(JPATH_SITE . DS . 'templates' . DS . $app->getTemplate() . DS . 'css' . DS . 'flexicontent.css')) {
         $document->addStyleSheetVersion($this->baseurl . '/templates/' . $app->getTemplate() . '/css/flexicontent.css', FLEXI_VERSION);
     }
     // **********************************************************
     // Calculate a (browser window) page title and a page heading
     // **********************************************************
     // Verify menu item points to current FLEXIcontent object
     if ($menu) {
         $view_ok = 'search' == @$menu->query['view'];
         $menu_matches = $view_ok;
         //$menu_params = FLEXI_J16GE ? $menu->params : new JParameter($menu->params);  // Get active menu item parameters
     } else {
         $menu_matches = false;
     }
     // MENU ITEM matched, use its page heading (but use menu title if the former is not set)
     if ($menu_matches) {
         $default_heading = FLEXI_J16GE ? $menu->title : $menu->name;
         // Cross set (show_) page_heading / page_title for compatibility of J2.5+ with J1.5 template (and for J1.5 with J2.5 template)
         $params->def('page_heading', $params->get('page_title', $default_heading));
         $params->def('page_title', $params->get('page_heading', $default_heading));
         $params->def('show_page_heading', $params->get('show_page_title', 0));
         $params->def('show_page_title', $params->get('show_page_heading', 0));
     } else {
         // Clear some menu parameters
         //$params->set('pageclass_sfx',	'');  // CSS class SUFFIX is behavior, so do not clear it ?
         // Calculate default page heading (=called page title in J1.5), which in turn will be document title below !! ...
         // meta_params->get('page_title') is meant for <title> but let's use as ... default page heading
         $default_heading = JText::_('FLEXI_SEARCH');
         // Decide to show page heading (=J1.5 page title), this default to no
         $show_default_heading = 0;
         // Set both (show_) page_heading / page_title for compatibility of J2.5+ with J1.5 template (and for J1.5 with J2.5 template)
         $params->set('page_title', $default_heading);
         $params->set('page_heading', $default_heading);
         $params->set('show_page_heading', $show_default_heading);
         $params->set('show_page_title', $show_default_heading);
     }
     // Prevent showing the page heading if ... currently no reason
     if (0) {
         $params->set('show_page_heading', 0);
         $params->set('show_page_title', 0);
     }
     // ************************************************************
     // Create the document title, by from page title and other data
     // ************************************************************
     // Use the page heading as document title, (already calculated above via 'appropriate' logic ...)
     $doc_title = $params->get('page_title');
     // Check and prepend or append site name to page title
     if ($doc_title != $app->getCfg('sitename')) {
         if ($app->getCfg('sitename_pagetitles', 0) == 1) {
             $doc_title = JText::sprintf('JPAGETITLE', $app->getCfg('sitename'), $doc_title);
         } elseif ($app->getCfg('sitename_pagetitles', 0) == 2) {
             $doc_title = JText::sprintf('JPAGETITLE', $doc_title, $app->getCfg('sitename'));
         }
     }
     // Finally, set document title
     $document->setTitle($doc_title);
     // ************************
     // Set document's META tags
     // ************************
     // Workaround for Joomla not setting the default value for 'robots', so component must do it
     $app_params = $app->getParams();
     if ($_mp = $app_params->get('robots')) {
         $document->setMetadata('robots', $_mp);
     }
     // Overwrite with menu META data if menu matched
     if ($menu_matches) {
         if ($_mp = $menu->params->get('menu-meta_description')) {
             $document->setDescription($_mp);
         }
         if ($_mp = $menu->params->get('menu-meta_keywords')) {
             $document->setMetadata('keywords', $_mp);
         }
         if ($_mp = $menu->params->get('robots')) {
             $document->setMetadata('robots', $_mp);
         }
         if ($_mp = $menu->params->get('secure')) {
             $document->setMetadata('secure', $_mp);
         }
     }
     // ********************************************************************
     // 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();
         }
     }
     // ****************************************
     // Create Form Elements (the 'lists' array)
     // ****************************************
     $lists = array();
     // *** Selector of Content Types
     if ($canseltypes) {
         $types = array();
         if ($show_filters) {
             $types[] = JHTML::_('select.option', '', JText::_('FLEXI_PLEASE_SELECT'));
         }
         foreach ($typeData as $type) {
             $types[] = JHTML::_('select.option', $type->id, JText::_($type->name));
         }
         $multiple_param = $show_filters ? ' onchange="adminFormPrepare(this.form); this.form.submit();" ' : ' multiple="multiple" ';
         $attribs = $multiple_param . ' size="5" class="fc_field_filter use_select2_lib fc_label_internal fc_prompt_internal"';
         $attribs .= ' data-fc_label_text="' . flexicontent_html::escapeJsText(JText::_('FLEXI_CLICK_TO_LIST'), 's') . '"';
         $attribs .= ' data-fc_prompt_text="' . flexicontent_html::escapeJsText(JText::_('FLEXI_TYPE_TO_FILTER'), 's') . '"';
         $lists['contenttypes'] = JHTML::_('select.genericlist', $types, 'contenttypes[]', $attribs, 'value', 'text', empty($form_contenttypes) ? '' : $form_contenttypes, 'contenttypes');
         /*
         $checked = !count($form_contenttypes) || !strlen($form_contenttypes[0]);
         $checked_attr = $checked ? 'checked="checked"' : '';
         $checked_class = $checked ? 'fc_highlight' : '';
         
         $lists['contenttypes']  = '<ul class="fc_field_filter fc_checkradio_group">';
         $lists['contenttypes'] .= ' <li class="fc_checkradio_option fc_checkradio_special">';
         $lists['contenttypes'] .= '  <input href="javascript:;" onclick="fc_toggleClass(this, \'fc_highlight\', 1);" ';
         $lists['contenttypes'] .= '    id="_contenttypes_0" type="checkbox" name="contenttypes[0]" ';
         $lists['contenttypes'] .= '    value="" '.$checked_attr.' class="fc_checkradio" />';
         $lists['contenttypes'] .= '  <label class="'.$checked_class.'" for="_contenttypes_0">';
         $lists['contenttypes'] .= '   -'.JText::_('FLEXI_ALL').'-';
         $lists['contenttypes'] .= '  </label>';
         $lists['contenttypes'] .= ' </li>';
         foreach($typeData as $type) {
         	$checked = in_array($type->value, $form_contenttypes);
         	$checked_attr = $checked ? 'checked=checked' : '';
         	$checked_class = $checked ? ' fc_highlight' : '';
         	$lists['contenttypes'] .= ' <li class="fc_checkradio_option">';
         	$lists['contenttypes'] .= '  <input href="javascript:;" onclick="fc_toggleClass(this, \'fc_highlight\');" ';
         	$lists['contenttypes'] .= '    id="_contenttypes_'.$type->value.'" type="checkbox" name="contenttypes[]" ';
         	$lists['contenttypes'] .= '    value="'.$type->value.'" '.$checked_attr.' class="fc_checkradio" />';
         	$lists['contenttypes'] .= '  <label class="'.$checked_class.'" for="_contenttypes_'.$type->value.'">';
         	$lists['contenttypes'] .= '   '.JText::_($type->text);
         	$lists['contenttypes'] .= '  </label>';
         	$lists['contenttypes'] .= ' </li>';
         }
         $lists['contenttypes'] .= '</ul>';
         */
     }
     // *** Selector of Fields for text searching
     if ($txtmode == 2 && count($fields_text)) {
         // Get selected text fields in the Search Form
         $form_txtflds = JRequest::getVar('txtflds', array());
         if (!$form_txtflds || empty($form_txtflds)) {
             $form_txtflds = array();
             //array('__FC_ALL__'); //array_keys($fields_text);
         }
         $attribs = ' multiple="multiple" size="5" class="fc_field_filter use_select2_lib fc_label_internal fc_prompt_internal"';
         $attribs .= ' data-fc_label_text="' . flexicontent_html::escapeJsText(JText::_('FLEXI_CLICK_TO_LIST'), 's') . '"';
         $attribs .= ' data-fc_prompt_text="' . flexicontent_html::escapeJsText(JText::_('FLEXI_TYPE_TO_FILTER'), 's') . '"';
         $lists['txtflds'] = JHTML::_('select.genericlist', $fields_text, 'txtflds[]', $attribs, 'name', 'label', $form_txtflds, 'txtflds');
         /*
         $checked = !count($form_txtflds) || !strlen($form_txtflds[0]);
         $checked_attr = $checked ? 'checked="checked"' : '';
         $checked_class = $checked ? 'fc_highlight' : '';
         
         $lists['txtflds']  = '<ul class="fc_field_filter fc_checkradio_group">';
         $lists['txtflds'] .= ' <li class="fc_checkradio_option fc_checkradio_special">';
         $lists['txtflds'] .= '  <input href="javascript:;" onclick="fc_toggleClass(this, \'fc_highlight\', 1);" ';
         $lists['txtflds'] .= '    id="_txtflds_0" type="checkbox" name="txtflds[0]" value="" ';
         $lists['txtflds'] .= '    value="" '.$checked_attr.' class="fc_checkradio" />';
         $lists['txtflds'] .= '  <label class="'.$checked_class.'" for="_txtflds_0">';
         $lists['txtflds'] .= '   -'.JText::_('FLEXI_ALL').'-';
         $lists['txtflds'] .= '  </label>';
         $lists['txtflds'] .= ' </li>';
         foreach($fields_text as $field) {
         	$checked = in_array($field->name, $form_txtflds);
         	$checked_attr = $checked ? 'checked=checked' : '';
         	$checked_class = $checked ? ' fc_highlight' : '';
         	$lists['txtflds'] .= ' <li class="fc_checkradio_option">';
         	$lists['txtflds'] .= '  <input href="javascript:;" onclick="fc_toggleClass(this, \'fc_highlight\');" ';
         	$lists['txtflds'] .= '    id="_txtflds_'.$field->id.'" type="checkbox" name="txtflds[]" ';
         	$lists['txtflds'] .= '    value="'.$field->name.'" '.$checked_attr.' class="fc_checkradio" />';
         	$lists['txtflds'] .= '  <label class="class=""'.$checked_class.'" for="_txtflds_'.$field->id.'">';
         	$lists['txtflds'] .= '   '.JText::_($field->label);
         	$lists['txtflds'] .= '  </label>';
         	$lists['txtflds'] .= ' </li>';
         }
         $lists['txtflds'] .= '</ul>';
         */
     }
     // *** Selector of FLEXIcontent Results Ordering
     if ($orderby_override = $params->get('orderby_override', 1)) {
         $lists['orderby'] = flexicontent_html::ordery_selector($params, $form_id, $autosubmit = 0);
     }
     // *** Selector of Pagination Limit
     if ($limit_override = $params->get('limit_override', 1)) {
         $lists['limit'] = flexicontent_html::limit_selector($params, $form_id, $autosubmit = 0);
     }
     // *** Selector of non-FLEXIcontent Results Ordering
     if ($show_searchordering = $params->get('show_searchordering', 1)) {
         // built select lists
         $orders = array();
         $orders[] = JHTML::_('select.option', 'newest', JText::_('FLEXI_ADV_NEWEST_FIRST'));
         $orders[] = JHTML::_('select.option', 'oldest', JText::_('FLEXI_ADV_OLDEST_FIRST'));
         $orders[] = JHTML::_('select.option', 'popular', JText::_('FLEXI_ADV_MOST_POP'));
         $orders[] = JHTML::_('select.option', 'alpha', JText::_('FLEXI_ADV_ALPHA'));
         $orders[] = JHTML::_('select.option', 'category', JText::_('FLEXI_ADV_SEARCH_SEC_CAT'));
         $lists['ordering'] = JHTML::_('select.genericlist', $orders, 'o', 'class="fc_field_filter use_select2_lib"', 'value', 'text', $searchordering, 'ordering');
     }
     // *** Selector for usage of Search Text
     if ($show_searchphrase = $params->get('show_searchphrase', 1)) {
         $searchphrase_names = array('natural' => 'FLEXI_NATURAL_PHRASE', 'natural_expanded' => 'FLEXI_NATURAL_PHRASE_GUESS_RELEVANT', 'all' => 'FLEXI_ALL_WORDS', 'any' => 'FLEXI_ANY_WORDS', 'exact' => 'FLEXI_EXACT_PHRASE');
         $phrases = array();
         foreach ($searchphrase_names as $searchphrase_value => $searchphrase_name) {
             $_obj = new stdClass();
             $_obj->value = $searchphrase_value;
             $_obj->text = $searchphrase_name;
             $phrases[] = $_obj;
         }
         $lists['searchphrase'] = JHTML::_('select.genericlist', $phrases, 'p', 'class="fc_field_filter use_select2_lib"', 'value', 'text', $searchphrase, 'searchphrase', $_translate = true);
         /*$lists['searchphrase']  = '<ul class="fc_field_filter fc_checkradio_group">';
         		foreach ($searchphrase_names as $searchphrase_value => $searchphrase_name) {
         			$lists['searchphrase'] .= ' <li class="fc_checkradio_option fc_checkradio_special">';
         			$checked = $searchphrase_value == $searchphrase;
         			$checked_attr = $checked ? 'checked=checked' : '';
         			$checked_class = $checked ? 'fc_highlight' : '';
         			$lists['searchphrase'] .= '  <input href="javascript:;" onclick="fc_toggleClassGrp(this.parentNode, \'fc_highlight\');" id="searchphrase_'.$searchphrase_value.'" type="radio" name="p" value="'.$searchphrase_value.'" '.$checked_attr.' />';
         			$lists['searchphrase'] .= '  <label class="'.$checked_class.'" style="display:inline-block; white-space:nowrap;" for="searchphrase_'.$searchphrase_value.'">';
         			$lists['searchphrase'] .=     JText::_($searchphrase_name);
         			$lists['searchphrase'] .= '  </label>';
         			$lists['searchphrase'] .= ' </li>';
         		}
         		$lists['searchphrase']  .= '</ul>';*/
     }
     // *** Selector for filter combination
     /*if($show_filtersop = $params->get('show_filtersop', 1)) {
     			$default_filtersop = $params->get('default_filtersop', 'all');
     			$filtersop = JRequest::getVar('filtersop', $default_filtersop);
     			$filtersop_arr		= array();
     			$filtersop_arr[] = JHTML::_('select.option',  'all', JText::_( 'FLEXI_SEARCH_ALL' ) );
     			$filtersop_arr[] = JHTML::_('select.option',  'any', JText::_( 'FLEXI_SEARCH_ANY' ) );
     			$lists['filtersop']= JHTML::_('select.radiolist',  $filtersop_arr, 'filtersop', '', 'value', 'text', $filtersop );
     		}*/
     // *** Selector of Search Areas
     // If showing this is disabled, then FLEXIcontent (advanced) search model will not use all search areas,
     // but instead it will use just 'flexicontent' search area, that is the search area of FLEXIcontent (advanced) search plugin
     if ($params->get('show_searchareas', 0)) {
         // Get Content Types currently selected in the Search Form
         $form_areas = JRequest::getVar('areas', array());
         //if ( empty($form_areas) || !count($form_areas) )  $form_areas = array('flexicontent');
         $checked = empty($form_areas) || !count($form_areas);
         $checked_attr = $checked ? 'checked="checked"' : '';
         $checked_class = $checked ? 'fc_highlight' : '';
         // Create array of area options
         $options = array();
         foreach ($areas['search'] as $area => $label) {
             $_area = new stdClass();
             $_area->text = $label;
             $_area->value = $area;
             $options[] = $_area;
         }
         $attribs = ' multiple="multiple" size="5" class="fc_field_filter use_select2_lib fc_label_internal fc_prompt_internal"';
         $attribs .= ' data-fc_label_text="' . flexicontent_html::escapeJsText(JText::_('FLEXI_CLICK_TO_LIST'), 's') . '"';
         $attribs .= ' data-fc_prompt_text="' . flexicontent_html::escapeJsText(JText::_('FLEXI_TYPE_TO_FILTER'), 's') . '"';
         $lists['areas'] = JHTML::_('select.genericlist', $options, 'areas[]', $attribs, 'value', 'text', $form_areas, 'areas', $do_jtext = true);
         /*
         $lists['areas']  = '<ul class="fc_field_filter fc_checkradio_group">';
         $lists['areas'] .= ' <li class="fc_checkradio_option fc_checkradio_special">';
         $lists['areas'] .= '  <input href="javascript:;" onclick="fc_toggleClass(this, \'fc_highlight\', 1);" ';
         $lists['areas'] .= '    id="area_0" type="checkbox" name="area[0]" ';
         $lists['areas'] .= '    value="" '.$checked_attr.' class="fc_checkradio" />';
         $lists['areas'] .= '  <label class="'.$checked_class.'" for="_txtflds_0">';
         $lists['areas'] .= '   -'.JText::_('FLEXI_CONTENT_ONLY').'-';
         $lists['areas'] .= '  </label>';
         $lists['areas'] .= ' </li>';
         foreach($areas['search'] as $area_name => $area_label) {
         	$checked = in_array($area_name, $form_areas);
         	$checked_attr = $checked ? 'checked=checked' : '';
         	$checked_class = $checked ? ' fc_highlight' : '';
         	$lists['areas'] .= ' <li class="fc_checkradio_option">';
         	$lists['areas'] .= '  <input href="javascript:;" onclick="fc_toggleClass(this, \'fc_highlight\');" ';
         	$lists['areas'] .= '    id="area_'.$area_name.'" type="checkbox" name="areas[]" ';
         	$lists['areas'] .= '    value="'.$area_name.'" '.$checked_attr.' class="fc_checkradio" />';
         	$lists['areas'] .= '  <label class="'.$checked_class.'" for="area_'.$area_name.'">';
         	$lists['areas'] .= '  '.JText::_($area_label);
         	$lists['areas'] .= '  </label>';
         	$lists['areas'] .= ' </li>';
         }
         $lists['areas'] .= '</ul>';
         */
     }
     // log the search
     FLEXIadvsearchHelper::logSearch($searchword);
     //limit searchword
     $min_word_len = $app->getUserState($option . '.min_word_len', 0);
     $min = $min_word_len ? $min_word_len : $params->get('minchars', 3);
     $max = $params->get('maxchars', 200);
     if (FLEXIadvsearchHelper::limitSearchWord($searchword, $min, $max)) {
         $error = JText::sprintf('FLEXI_SEARCH_MESSAGE', $min, $max);
     }
     // sanitise searchword
     if (FLEXIadvsearchHelper::santiseSearchWord($searchword, $state->get('match'), $min)) {
         $error = JText::_('IGNOREKEYWORD');
     }
     if (!$searchword && count(JRequest::get('post'))) {
         //$error = JText::_( 'Enter a search keyword' );
     }
     // put the filtered results back into the model
     // for next release, the checks should be done in the model perhaps...
     $state->set('keyword', $searchword);
     $filter_word_like_any = $params->get('filter_word_like_any', 0);
     if (!$error) {
         require_once JPATH_SITE . DS . 'components' . DS . 'com_flexicontent' . DS . 'helpers' . DS . 'route.php';
         $results = $this->get('data');
         $total = $this->get('total');
         $pageNav = $this->get('pagination');
         // URL-encode filter values
         foreach ($_GET as $i => $v) {
             if (substr($i, 0, 6) === "filter") {
                 $_revert = array('%21' => '!', '%2A' => '*', '%27' => "'", '%28' => '(', '%29' => ')');
                 $v = str_replace('&', '__amp__', $v);
                 $v = strtr(rawurlencode($v), $_revert);
                 $pageNav->setAdditionalUrlParam($i, $v);
             }
         }
         if ($state->get('match') == 'exact') {
             $searchwords = array($searchword);
             //$needle = $searchword;
         } else {
             $searchwords = preg_split("/\\s+/u", $searchword);
             //print_r($searchwords);
         }
         // Create regular expressions, for highlighting the matched words
         $w_regexp_highlight = array();
         foreach ($searchwords as $n => $_word) {
             $w_regexp_highlight[$_word] = mb_strlen($_word, 'utf-8') <= 2 || $n + 1 < count($searchwords) ? '#\\b(' . preg_quote($_word, '#') . ')\\b#iu' : '#\\b(' . preg_quote($_word, '#') . ')#iu';
         }
         for ($i = 0; $i < count($results); $i++) {
             $result =& $results[$i];
             if (strlen($searchwords[0])) {
                 $parts = FLEXIadvsearchHelper::prepareSearchContent($result->text, $params->get('text_chars', 200), $searchwords);
                 //if( count($parts)>1 ) { echo "<pre>"; print_r($parts); exit;}
                 foreach ($parts as $word_found => $part) {
                     if (!$word_found) {
                         continue;
                     }
                     $searchRegex = $w_regexp_highlight[$word_found];
                     $parts[$word_found] = preg_replace($searchRegex, '_fc_highlight_start_\\0_fc_highlight_end_', $part);
                 }
                 $result->text = implode($parts, " <br/> ");
                 $replace_count_total = 0;
                 // This is for LIKE %word% search for languages without spaces
                 if ($filter_word_like_any) {
                     if (strlen($word_found) <= 2) {
                         continue;
                     }
                     // Do not highlight too small words, since we do not consider spaces
                     foreach ($searchwords as $_word) {
                         $searchRegex = '#(' . preg_quote($_word, '#') . '[^\\s]*)#iu';
                         $result->text = preg_replace($searchRegex, '_fc_highlight_start_\\0_fc_highlight_end_', $result->text, 1, $replace_count);
                         if ($replace_count) {
                             $replace_count_total++;
                         }
                     }
                 }
                 $result->text = str_replace('_fc_highlight_start_', '<span class="highlight">', $result->text);
                 $result->text = str_replace('_fc_highlight_end_', '</span>', $result->text);
                 // Add some message about matches
                 /*if ( $state->get('match')=='any' ) {
                 			$text_search_header = "<u><b>".JText::sprintf('Text Search matched at least %d %% (%d out of %d words)', $replace_count_total/count($searchwords) * 100, $replace_count_total, count($searchwords)).": </b></u><br/>";
                 		} else if ( $state->get('match')=='all' ) {
                 			$text_search_header = "<u><b>".JText::sprintf('Text Search (all %d words required)', count($searchwords)).": </b></u><br/>";
                 		} else if ( $state->get('match')=='exact' ) {
                 			$text_search_header = "<u><b>".JText::_('Text Search (exact phrase)').": </b></u><br/>";
                 		} else if ( $state->get('match')=='natural_expanded' ) {
                 			$text_search_header = "<u><b>".JText::_('Text Search (phrase, guessing related)').": </b></u><br/>";
                 		} else if ( $state->get('match')=='natural' ) {
                 			$text_search_header = "<u><b>".JText::_('Text Search (phrase)').": </b></u><br/>";
                 		}
                 		$result->text = $text_search_header . $result->text;*/
             } else {
                 $parts = FLEXIadvsearchHelper::prepareSearchContent($result->text, $params->get('text_chars', 200), array());
                 $result->text = implode($parts, " <br/> ");
             }
             /*if ( !empty($result->fields_text) ) {
             			$result->text .= "<br/><u><b>".JText::_('Attribute filters matched')." : </b></u>";
             			$result->fields_text = str_replace('[span=highlight]', '<span class="highlight">', $result->fields_text);
             			$result->fields_text = str_replace('[/span]', '</span>', $result->fields_text);
             			$result->fields_text = str_replace('[br /]', '<br />', $result->fields_text);
             			$result->text .= $result->fields_text;
             		}*/
             $result->text = str_replace('[[[', '<', $result->text);
             $result->text = str_replace(']]]', '>', $result->text);
             $result->created = $result->created ? JHTML::Date($result->created) : '';
             $result->count = $i + 1;
         }
     }
     $this->result = JText::sprintf('FLEXI_TOTALRESULTSFOUND', $total);
     // ******************************************************************
     // Create HTML of filters (-AFTER- getData of model have been called)
     // ******************************************************************
     foreach ($filters as $filter) {
         $filter->parameters->set('display_label_filter_s', 0);
         $filter->value = JRequest::getVar('filter_' . $filter->id, false);
         //$fieldsearch = $app->getUserStateFromRequest( 'flexicontent.search.'.'filter_'.$filter->id, 'filter_'.$filter->id, array(), 'array' );
         //echo "Field name: ".$filter->name; echo ":: ". 'filter_'.$filter->id ." :: value: "; print_r($filter->value); echo "<br/>\n";
         $field_filename = $filter->iscore ? 'core' : $filter->field_type;
         FLEXIUtilities::call_FC_Field_Func($field_filename, 'onAdvSearchDisplayFilter', array(&$filter, $filter->value, $form_id));
     }
     //echo "<pre>"; print_r($_GET); exit;
     // Create links
     $link = JRoute::_(FlexicontentHelperRoute::getSearchRoute(0, $menu_matches ? $menu->id : 0));
     //$print_link = JRoute::_('index.php?view=search&pop=1&tmpl=component&print=1');
     $curr_url = str_replace('&', '&amp;', $_SERVER['REQUEST_URI']);
     $print_link = $curr_url . (strstr($curr_url, '?') ? '&amp;' : '?') . 'pop=1&amp;tmpl=component&amp;print=1';
     $pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx'));
     $this->assignRef('action', $link);
     // $uri->toString()
     $this->assignRef('print_link', $print_link);
     $this->assignRef('contenttypes', $contenttypes);
     $this->assignRef('filters', $filters);
     $this->assignRef('results', $results);
     $this->assignRef('lists', $lists);
     $this->assignRef('params', $params);
     $this->assignRef('pageNav', $pageNav);
     $this->assignRef('pageclass_sfx', $pageclass_sfx);
     $this->assignRef('typeData', $typeData);
     $this->assign('ordering', $state->get('ordering'));
     $this->assign('searchword', $searchword);
     $this->assign('searchphrase', $state->get('match'));
     $this->assign('searchareas', $areas);
     $this->assign('total', $total);
     $this->assign('error', $error);
     $this->assignRef('document', $document);
     $this->assign('form_id', $form_id);
     $this->assign('form_name', $form_name);
     $print_logging_info = $params->get('print_logging_info');
     if ($print_logging_info) {
         global $fc_run_times;
         $start_microtime = microtime(true);
     }
     parent::display($tpl);
     if ($print_logging_info) {
         @($fc_run_times['template_render'] += round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10);
     }
 }
示例#4
0
    /**
     * Method to empty search indexes
     *
     * @access	public
     * @return	null
     * @since	1.0
     */
    function purge($del_fieldids = null)
    {
        $app = JFactory::getApplication();
        $db = JFactory::getDBO();
        // ******************************
        // Empty Common text-search index
        // ******************************
        if (empty($del_fieldids)) {
            $query = "TRUNCATE TABLE `#__flexicontent_advsearch_index`;";
        } else {
            $del_fieldids_list = implode(',', $del_fieldids);
            $query = "DELETE FROM #__flexicontent_advsearch_index WHERE field_id IN (" . $del_fieldids_list . ")";
        }
        $db->setQuery($query);
        $db->execute();
        // **********************
        // Empty per field TABLES
        // **********************
        $filterables = FlexicontentFields::getSearchFields('id', $indexer = 'advanced', null, null, $_load_params = true, 0, $search_type = 'filter');
        $filterables = array_keys($filterables);
        $filterables = array_flip($filterables);
        $tbl_prefix = $app->getCfg('dbprefix') . 'flexicontent_advsearch_index_field_';
        $query = "SELECT TABLE_NAME\n\t\t\tFROM INFORMATION_SCHEMA.TABLES\n\t\t\tWHERE TABLE_NAME LIKE '" . $tbl_prefix . "%'\n\t\t\t";
        $db->setQuery($query);
        $tbl_names = $db->loadColumn();
        foreach ($tbl_names as $tbl_name) {
            $_field_id = str_replace($tbl_prefix, '', $tbl_name);
            // Drop the table of no longer filterable field
            if (!isset($filterables[$_field_id])) {
                $db->setQuery('DROP TABLE IF EXISTS ' . $tbl_name);
            } else {
                if (empty($del_fieldids) || isset($del_fieldids[$_field_id])) {
                    //$db->setQuery( 'DROP TABLE IF EXISTS '.$tbl_name );
                    $db->setQuery('TRUNCATE TABLE ' . $tbl_name);
                }
            }
            $db->execute();
        }
        // VERIFY all search tables exist
        $tbl_names_flipped = array_flip($tbl_names);
        foreach ($filterables as $_field_id => $_ignored) {
            $tbl_name = $app->getCfg('dbprefix') . 'flexicontent_advsearch_index_field_' . $_field_id;
            $query = '
			CREATE TABLE IF NOT EXISTS `' . $tbl_name . '` (
			  `sid` int(11) NOT NULL auto_increment,
			  `field_id` int(11) NOT NULL,
			  `item_id` int(11) NOT NULL,
			  `extraid` int(11) NOT NULL,
			  `search_index` longtext NOT NULL,
			  `value_id` varchar(255) NULL,
			  PRIMARY KEY (`field_id`,`item_id`,`extraid`),
			  KEY `sid` (`sid`),
			  KEY `field_id` (`field_id`),
			  KEY `item_id` (`item_id`),
			  FULLTEXT `search_index` (`search_index`),
			  KEY `value_id` (`value_id`)
			) ENGINE=MyISAM CHARACTER SET `utf8` COLLATE `utf8_general_ci`
			';
            $db->setQuery($query);
            $db->execute();
        }
    }
    /**
     * Method to save field values of the item in field versioning DB table or in ..._fields_item_relations DB table 
     *
     * @access	public
     * @return	boolean	True on success
     * @since	1.0
     */
    function saveFields($isnew, &$item, &$data, &$files, &$old_item = null, &$core_data_via_events = null)
    {
        if (!$old_item) {
            $old_item =& $item;
        }
        $app = JFactory::getApplication();
        $user = JFactory::getUser();
        $dispatcher = JDispatcher::getInstance();
        $cparams = $this->_cparams;
        $use_versioning = $cparams->get('use_versioning', 1);
        $print_logging_info = $cparams->get('print_logging_info');
        $last_version = (int) FLEXIUtilities::getLastVersions($item->id, true);
        $mval_query = true;
        if ($print_logging_info) {
            global $fc_run_times;
        }
        if ($print_logging_info) {
            $start_microtime = microtime(true);
        }
        // ********************************
        // Checks for untranslatable fields
        // ********************************
        // CASE 1. Check if saving an item that translates an original content in site's default language
        // ... Decide whether to retrieve field values of untranslatable fields from the original content item
        $enable_translation_groups = flexicontent_db::useAssociations();
        //$cparams->get('enable_translation_groups');
        $site_default = substr(flexicontent_html::getSiteDefaultLang(), 0, 2);
        $is_content_default_lang = $site_default == substr($item->language, 0, 2);
        $get_untraslatable_values = $enable_translation_groups && !$is_content_default_lang;
        if ($enable_translation_groups) {
            $langAssocs = $this->getLangAssocs();
            //}
            //if ($enable_translation_groups /*&& $is_content_default_lang*/)
            //{
            // ... Get item ids of the associated items, so that we save into the untranslatable fields
            $_langAssocs = $langAssocs;
            unset($_langAssocs[$this->_id]);
            $assoc_item_ids = array_keys($_langAssocs);
        }
        if (empty($assoc_item_ids)) {
            $assoc_item_ids = array();
        }
        // ***************************************************************************************************************************
        // Get item's fields ... and their values (for untranslatable fields the field values from original content item are retrieved
        // ***************************************************************************************************************************
        $original_content_id = 0;
        if ($get_untraslatable_values) {
            foreach ($langAssocs as $content_id => $_assoc) {
                if ($site_default == substr($_assoc->language, 0, 2)) {
                    $original_content_id = $content_id;
                    break;
                }
            }
        }
        //JFactory::getApplication()->enqueueMessage(__FUNCTION__.'(): '.$original_content_id.' '.print_r($assoc_item_ids, true),'message');
        $fields = $this->getExtrafields($force = true, $original_content_id, $old_item);
        // ******************************************************************************************************************
        // Loop through Fields triggering onBeforeSaveField Event handlers, this was seperated from the rest of the process
        // to give chance to ALL fields to check their DATA and cancel item saving process before saving any new field values
        // ******************************************************************************************************************
        $searchindex = array();
        //$qindex = array();
        $core_data_via_events = array();
        // Extra validation for some core fields via onBeforeSaveField
        if ($fields) {
            $core_via_post = array('title' => 1, 'text' => 1);
            foreach ($fields as $field) {
                // Set vstate property into the field object to allow this to be changed be the before saving  field event handler
                $field->item_vstate = $data['vstate'];
                $is_editable = !$field->valueseditable || $user->authorise('flexicontent.editfieldvalues', 'com_flexicontent.field.' . $field->id);
                $maintain_dbval = false;
                // FORM HIDDEN FIELDS (FRONTEND/BACKEND) AND (ACL) UNEDITABLE FIELDS: maintain their DB value ...
                if ($app->isSite() && ($field->formhidden == 1 || $field->formhidden == 3 || $field->parameters->get('frontend_hidden')) || $app->isAdmin() && ($field->formhidden == 2 || $field->formhidden == 3 || $field->parameters->get('backend_hidden')) || !$is_editable) {
                    $postdata[$field->name] = $field->value;
                    $maintain_dbval = true;
                    // UNTRANSLATABLE (CUSTOM) FIELDS: maintain their DB value ...
                    /*} else if ( $get_untraslatable_values && $field->untranslatable ) {
                    		$postdata[$field->name] = $field->value;
                    		$maintain_dbval = true;*/
                } else {
                    if ($field->iscore) {
                        // (posted) CORE FIELDS: if not set maintain their DB value ...
                        if (isset($core_via_post[$field->name])) {
                            if (isset($data[$field->name])) {
                                $postdata[$field->name] = $data[$field->name];
                            } else {
                                $postdata[$field->name] = $field->value;
                                $maintain_dbval = true;
                            }
                            // (not posted) CORE FIELDS: get current value
                        } else {
                            // Get value from the updated item instead of old data
                            $postdata[$field->name] = $this->getCoreFieldValue($field, 0);
                        }
                        // OTHER CUSTOM FIELDS (not hidden and not untranslatable)
                    } else {
                        $postdata[$field->name] = @$data['custom'][$field->name];
                    }
                }
                // Unserialize values already serialized values, e.g. (a) if current values used are from DB or (b) are being imported from CSV file
                if (!is_array($postdata[$field->name])) {
                    $postdata[$field->name] = strlen($postdata[$field->name]) ? array($postdata[$field->name]) : array();
                }
                foreach ($postdata[$field->name] as $i => $postdata_val) {
                    if (@unserialize($postdata_val) !== false || $postdata_val === 'b:0;') {
                        $postdata[$field->name][$i] = unserialize($postdata_val);
                    }
                }
                // Trigger plugin Event 'onBeforeSaveField'
                if (!$field->iscore || isset($core_via_post[$field->name])) {
                    $field_type = $field->iscore ? 'core' : $field->field_type;
                    $result = FLEXIUtilities::call_FC_Field_Func($field_type, 'onBeforeSaveField', array(&$field, &$postdata[$field->name], &$files[$field->name], &$item));
                    if ($result === false) {
                        // Field requested to abort item saving
                        $this->setError(JText::sprintf('FLEXI_FIELD_VALUE_IS_INVALID', $field->label));
                        return 'abort';
                    }
                    // For CORE field get the modified data, which will be used for storing in DB (these will be re-bind later)
                    if (isset($core_via_post[$field->name])) {
                        $core_data_via_events[$field->name] = isset($postdata[$field->name][0]) ? $postdata[$field->name][0] : '';
                        // The validation may have skipped it !!
                    }
                } else {
                    // Currently other CORE fields, these are skipped we will not call onBeforeSaveField() on them, neither rebind them
                }
                //$qindex[$field->name] = NULL;
                //$result = FLEXIUtilities::call_FC_Field_Func($field_type, 'onBeforeSaveField', array( &$field, &$postdata[$field->name], &$files[$field->name], &$item, &$qindex[$field->name] ));
                //if ($result===false) { ... }
                // Get vstate property from the field object back to the data array ... in case it was modified, since some field may decide to prevent approval !
                $data['vstate'] = $field->item_vstate;
            }
            //echo "<pre>"; print_r($postdata); echo "</pre>"; exit;
        }
        if ($print_logging_info) {
            @($fc_run_times['fields_value_preparation'] = round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10);
        }
        // **********************
        // Empty per field TABLES
        // **********************
        $filterables = FlexicontentFields::getSearchFields('id', $indexer = 'advanced', null, null, $_load_params = true, 0, $search_type = 'filter');
        $filterables = array_keys($filterables);
        $filterables = array_flip($filterables);
        $tbl_prefix = $app->getCfg('dbprefix') . 'flexicontent_advsearch_index_field_';
        $query = "SELECT TABLE_NAME\n\t\t\tFROM INFORMATION_SCHEMA.TABLES\n\t\t\tWHERE TABLE_NAME LIKE '" . $tbl_prefix . "%'\n\t\t\t";
        $this->_db->setQuery($query);
        $tbl_names = $this->_db->loadColumn();
        foreach ($tbl_names as $tbl_name) {
            $_field_id = str_replace($tbl_prefix, '', $tbl_name);
            // Drop the table of no longer filterable field
            if (!isset($filterables[$_field_id])) {
                $this->_db->setQuery('DROP TABLE IF EXISTS ' . $tbl_name);
            } else {
                // Remove item's old advanced search index entries
                $query = "DELETE FROM " . $tbl_name . " WHERE item_id=" . $item->id;
                $this->_db->setQuery($query);
                $this->_db->query();
            }
        }
        // VERIFY all search tables exist
        $tbl_names_flipped = array_flip($tbl_names);
        foreach ($filterables as $_field_id => $_ignored) {
            $tbl_name = $app->getCfg('dbprefix') . 'flexicontent_advsearch_index_field_' . $_field_id;
            if (isset($tbl_names_flipped[$tbl_name])) {
                continue;
            }
            $query = '
			CREATE TABLE IF NOT EXISTS `' . $tbl_name . '` (
			  `sid` int(11) NOT NULL auto_increment,
			  `field_id` int(11) NOT NULL,
			  `item_id` int(11) NOT NULL,
			  `extraid` int(11) NOT NULL,
			  `search_index` longtext NOT NULL,
			  `value_id` varchar(255) NULL,
			  PRIMARY KEY (`field_id`,`item_id`,`extraid`),
			  KEY `sid` (`sid`),
			  KEY `field_id` (`field_id`),
			  KEY `item_id` (`item_id`),
			  FULLTEXT `search_index` (`search_index`),
			  KEY `value_id` (`value_id`)
			) ENGINE=MyISAM CHARACTER SET `utf8` COLLATE `utf8_general_ci`
			';
            $this->_db->setQuery($query);
            $this->_db->query();
        }
        // ****************************************************************************************************************************
        // Loop through Fields triggering onIndexAdvSearch, onIndexSearch Event handlers, this was seperated from the before save field
        //  event, so that we will update search indexes only if the above has not canceled saving OR has not canceled version approval
        // ****************************************************************************************************************************
        if ($print_logging_info) {
            $start_microtime = microtime(true);
        }
        $ai_query_vals = array();
        $ai_query_vals_f = array();
        if ($fields) {
            foreach ($fields as $field) {
                $field_type = $field->iscore ? 'core' : $field->field_type;
                if ($data['vstate'] == 2 || $isnew) {
                    // Trigger plugin Event 'onIndexAdvSearch' to update field-item pair records in advanced search index
                    FLEXIUtilities::call_FC_Field_Func($field_type, 'onIndexAdvSearch', array(&$field, &$postdata[$field->name], &$item));
                    if (isset($field->ai_query_vals)) {
                        foreach ($field->ai_query_vals as $query_val) {
                            $ai_query_vals[] = $query_val;
                        }
                        if (isset($filterables[$field->id])) {
                            // Current for advanced index only
                            foreach ($field->ai_query_vals as $query_val) {
                                $ai_query_vals_f[$field->id][] = $query_val;
                            }
                        }
                    }
                    //echo $field->name .":".implode(",", @$field->ai_query_vals ? $field->ai_query_vals : array() )."<br/>";
                    // Trigger plugin Event 'onIndexSearch' to update item 's (basic) search index record
                    FLEXIUtilities::call_FC_Field_Func($field_type, 'onIndexSearch', array(&$field, &$postdata[$field->name], &$item));
                    if (strlen(@$field->search[$item->id])) {
                        $searchindex[] = $field->search[$item->id];
                    }
                    //echo $field->name .":".@$field->search[$item->id]."<br/>";
                }
            }
        }
        // Remove item's old advanced search index entries
        $query = "DELETE FROM #__flexicontent_advsearch_index WHERE item_id=" . $item->id;
        $this->_db->setQuery($query);
        $this->_db->query();
        // Store item's advanced search index entries
        $queries = array();
        if (count($ai_query_vals)) {
            $queries[] = "INSERT INTO #__flexicontent_advsearch_index " . " (field_id,item_id,extraid,search_index,value_id) VALUES " . implode(",", $ai_query_vals);
            $this->_db->setQuery($query);
            $this->_db->query();
            if ($this->_db->getErrorNum()) {
                JFactory::getApplication()->enqueueMessage(__FUNCTION__ . '(): SQL QUERY ERROR:<br/>' . nl2br($this->_db->getErrorMsg()), 'error');
            }
        }
        foreach ($ai_query_vals_f as $_field_id => $_query_vals) {
            // Current for advanced index only
            $queries[] = "INSERT INTO #__flexicontent_advsearch_index_field_" . $_field_id . " (field_id,item_id,extraid,search_index,value_id) VALUES " . implode(",", $_query_vals);
        }
        foreach ($queries as $query) {
            $this->_db->setQuery($query);
            $this->_db->query();
        }
        // Assigned created basic search index into item object
        $search_prefix = $cparams->get('add_search_prefix') ? 'vvv' : '';
        // SEARCH WORD Prefix
        $item->search_index = implode(' | ', $searchindex);
        if ($search_prefix && $item->search_index) {
            $item->search_index = preg_replace('/(\\b[^\\s]+\\b)/', $search_prefix . '$0', trim($item->search_index));
        }
        // Check if vstate was set to 1 (no approve new version) while versioning is disabled
        if (!$use_versioning && $data['vstate'] != 2) {
            $data['vstate'] = 2;
            $app->enqueueMessage('vstate cannot be set to 1 (=no approve new version) when versioning is disabled', 'notice');
        }
        if ($print_logging_info) {
            @($fc_run_times['fields_value_indexing'] = round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10);
        }
        if ($print_logging_info) {
            $start_microtime = microtime(true);
        }
        // **************************************************************************
        // IF new version is approved, remove old version values from the field table
        // **************************************************************************
        if ($data['vstate'] == 2) {
            //echo "delete __flexicontent_fields_item_relations, item_id: " .$item->id;
            $query = 'DELETE FROM #__flexicontent_fields_item_relations WHERE item_id = ' . $item->id;
            $this->_db->setQuery($query);
            $this->_db->query();
            $query = 'DELETE FROM #__flexicontent_items_versions WHERE item_id=' . $item->id . ' AND version=' . ((int) $last_version + 1);
            $this->_db->setQuery($query);
            $this->_db->query();
            $untranslatable_fields = array();
            if ($fields) {
                foreach ($fields as $field) {
                    if ($field->iscore) {
                        continue;
                    }
                    if (count($assoc_item_ids) && $field->untranslatable) {
                        // Delete field values in all translating items, if current field is untranslatable and current item version is approved
                        // NOTE: item itself is not include in associated translations, no need to check for it and skip itit
                        if (!$mval_query) {
                            $query = 'DELETE FROM #__flexicontent_fields_item_relations WHERE item_id IN (' . implode(',', $assoc_item_ids) . ') AND field_id=' . $field->id;
                            $this->_db->setQuery($query);
                            $this->_db->query();
                        } else {
                            $untranslatable_fields[] = $field->id;
                        }
                    }
                }
            }
            if (count($untranslatable_fields)) {
                $query = 'DELETE FROM #__flexicontent_fields_item_relations WHERE item_id IN (' . implode(',', $assoc_item_ids) . ') AND field_id IN (' . implode(',', $untranslatable_fields) . ')';
                $this->_db->setQuery($query);
                $this->_db->query();
            }
        }
        // *******************************************
        // Loop through Fields saving the field values
        // *******************************************
        if ($fields) {
            // Do not save if versioning disabled or item has no type (version 0)
            $record_versioned_data = $use_versioning && $item->version;
            $ver_query_vals = array();
            $rel_query_vals = array();
            foreach ($fields as $field) {
                // -- Add the new values to the database
                $postvalues = $this->formatToArray($postdata[$field->name]);
                //$qindex_values = $qindex[$field->name];
                $i = 1;
                foreach ($postvalues as $postvalue) {
                    // Create field obj for DB insertion
                    $obj = new stdClass();
                    $obj->field_id = $field->id;
                    $obj->item_id = $item->id;
                    $obj->valueorder = $i;
                    $obj->suborder = 1;
                    $obj->version = (int) $last_version + 1;
                    $use_ingroup = $field->parameters->get('use_ingroup', 0);
                    // Serialize the properties of the value, normally this is redudant, since the field must have had serialized the parameters of each value already
                    if (!empty($field->use_suborder) && is_array($postvalue)) {
                        $obj->value = null;
                    } else {
                        $obj->value = is_array($postvalue) ? serialize($postvalue) : $postvalue;
                    }
                    //$obj->qindex01 = isset($qindex_values['qindex01']) ? $qindex_values['qindex01'] : NULL;
                    //$obj->qindex02 = isset($qindex_values['qindex02']) ? $qindex_values['qindex02'] : NULL;
                    //$obj->qindex03 = isset($qindex_values['qindex03']) ? $qindex_values['qindex03'] : NULL;
                    // -- a. Add versioning values, but do not version the 'hits' or 'state' or 'voting' fields
                    if ($record_versioned_data && $field->field_type != 'hits' && $field->field_type != 'state' && $field->field_type != 'voting') {
                        // Insert only if value non-empty
                        if (!empty($field->use_suborder) && is_array($postvalue)) {
                            $obj->suborder = 1;
                            foreach ($postvalue as $v) {
                                $obj->value = $v;
                                if (!$mval_query) {
                                    $this->_db->insertObject('#__flexicontent_items_versions', $obj);
                                } else {
                                    $ver_query_vals[] = "(" . $obj->field_id . "," . $obj->item_id . "," . $obj->valueorder . "," . $obj->suborder . "," . $obj->version . "," . $this->_db->Quote($obj->value) . ")";
                                }
                                $obj->suborder++;
                            }
                            unset($v);
                        } else {
                            if (isset($obj->value) && ($use_ingroup || strlen(trim($obj->value)))) {
                                if (!$mval_query) {
                                    $this->_db->insertObject('#__flexicontent_items_versions', $obj);
                                } else {
                                    $ver_query_vals[] = "(" . $obj->field_id . "," . $obj->item_id . "," . $obj->valueorder . "," . $obj->suborder . "," . $obj->version . "," . $this->_db->Quote($obj->value) . ")";
                                }
                            }
                        }
                    }
                    //echo $field->field_type." - ".$field->name." - ".strlen(trim($obj->value))." ".$field->iscore."<br/>";
                    // -- b. If item is new OR version is approved, AND field is not core (aka stored in the content table or in special table), then add field value to field values table
                    if (($isnew || $data['vstate'] == 2) && !$field->iscore) {
                        // UNSET version it it used only verion data table, and insert only if value non-empty
                        unset($obj->version);
                        if (!empty($field->use_suborder) && is_array($postvalue)) {
                            $obj->suborder = 1;
                            foreach ($postvalue as $v) {
                                $obj->value = $v;
                                if (!$mval_query) {
                                    $this->_db->insertObject('#__flexicontent_fields_item_relations', $obj);
                                } else {
                                    $rel_query_vals[] = "(" . $obj->field_id . "," . $obj->item_id . "," . $obj->valueorder . "," . $obj->suborder . "," . $this->_db->Quote($obj->value) . ")";
                                }
                                $obj->suborder++;
                            }
                            unset($v);
                        } else {
                            if (isset($obj->value) && ($use_ingroup || strlen(trim($obj->value)))) {
                                if (!$mval_query) {
                                    $this->_db->insertObject('#__flexicontent_fields_item_relations', $obj);
                                } else {
                                    $rel_query_vals[] = "(" . $obj->field_id . "," . $obj->item_id . "," . $obj->valueorder . "," . $obj->suborder . "," . $this->_db->Quote($obj->value) . ")";
                                }
                                // Save field value in all translating items, if current field is untranslatable
                                // NOTE: item itself is not include in associated translations, no need to check for it and skip it
                                if (count($assoc_item_ids) && $field->untranslatable) {
                                    foreach ($assoc_item_ids as $t_item_id) {
                                        //echo "setting Untranslatable value for item_id: ".$t_item_id ." field_id: ".$field->id."<br/>";
                                        $obj->item_id = $t_item_id;
                                        if (!$mval_query) {
                                            $this->_db->insertObject('#__flexicontent_fields_item_relations', $obj);
                                        } else {
                                            $rel_query_vals[] = "(" . $obj->field_id . "," . $obj->item_id . "," . $obj->valueorder . "," . $obj->suborder . "," . $this->_db->Quote($obj->value) . ")";
                                        }
                                    }
                                }
                            }
                        }
                    }
                    $i++;
                }
            }
            // *********************************************
            // Insert values in item fields versioning table
            // *********************************************
            if (count($ver_query_vals)) {
                $query = "INSERT INTO #__flexicontent_items_versions " . " (field_id,item_id,valueorder,suborder,version,value" . ") VALUES " . "\n" . implode(",\n", $ver_query_vals);
                $this->_db->setQuery($query);
                $this->_db->query();
                if ($this->_db->getErrorNum()) {
                    JFactory::getApplication()->enqueueMessage(__FUNCTION__ . '(): SQL QUERY ERROR:<br/>' . nl2br($this->_db->getErrorMsg()), 'error');
                }
            }
            // *******************************************
            // Insert values in item fields relation table
            // *******************************************
            if (count($rel_query_vals)) {
                $query = "INSERT INTO #__flexicontent_fields_item_relations " . " (field_id,item_id,valueorder,suborder,value" . ") VALUES " . "\n" . implode(",\n", $rel_query_vals);
                $this->_db->setQuery($query);
                $this->_db->query();
                if ($this->_db->getErrorNum()) {
                    JFactory::getApplication()->enqueueMessage(__FUNCTION__ . '(): SQL QUERY ERROR:<br/>' . nl2br($this->_db->getErrorMsg()), 'error');
                }
            }
            // **************************************************************
            // Save other versioned item data into the field versioning table
            // **************************************************************
            // a. Save a version of item properties that do not have a corresponding CORE Field
            if ($record_versioned_data) {
                $obj = new stdClass();
                $obj->field_id = -2;
                // ID of Fake Field used to contain item properties not having a corresponding CORE field
                $obj->item_id = $item->id;
                $obj->valueorder = 1;
                $obj->suborder = 1;
                $obj->version = (int) $last_version + 1;
                $item_data = array();
                $iproperties = array('alias', 'catid', 'metadesc', 'metakey', 'metadata', 'attribs', 'urls', 'images');
                foreach ($iproperties as $iproperty) {
                    $item_data[$iproperty] = $item->{$iproperty};
                }
                $obj->value = serialize($item_data);
                $this->_db->insertObject('#__flexicontent_items_versions', $obj);
            }
            // b. Finally save a version of the posted JoomFish translated data for J1.5, if such data are editted inside the item edit form
            /*if ( FLEXI_FISH && !empty($data['jfdata']) && $record_versioned_data )
            		{
            			$obj = new stdClass();
            			$obj->field_id 		= -1;  // ID of Fake Field used to contain the Joomfish translated item data
            			$obj->item_id 		= $item->id;
            			$obj->valueorder	= 1;
            			$obj->suborder    = 1;
            			$obj->version			= (int)$last_version+1;
            			
            			$item_lang = substr($item->language ,0,2);
            			$data['jfdata'][$item_lang]['title'] = $item->title;
            			$data['jfdata'][$item_lang]['alias'] = $item->alias;
            			$data['jfdata'][$item_lang]['text'] = $item->text;
            			$data['jfdata'][$item_lang]['metadesc'] = $item->metadesc;
            			$data['jfdata'][$item_lang]['metakey'] = $item->metakey;
            			$obj->value = serialize($data['jfdata']);
            			$this->_db->insertObject('#__flexicontent_items_versions', $obj);
            		}*/
        }
        if ($print_logging_info) {
            @($fc_run_times['fields_value_saving'] = round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10);
        }
        // ******************************
        // Trigger onAfterSaveField Event
        // ******************************
        if ($fields) {
            if ($print_logging_info) {
                $start_microtime = microtime(true);
            }
            foreach ($fields as $field) {
                $field_type = $field->iscore ? 'core' : $field->field_type;
                $result = FLEXIUtilities::call_FC_Field_Func($field_type, 'onAfterSaveField', array(&$field, &$postdata[$field->name], &$files[$field->name], &$item));
                // *** $result is ignored
            }
            if ($print_logging_info) {
                @($fc_run_times['onAfterSaveField_event'] = round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10);
            }
        }
        return true;
    }
 function index()
 {
     $start_microtime = microtime(true);
     $session = JFactory::getSession();
     $db = JFactory::getDBO();
     // Test indexing with limited memory
     //ini_set("memory_limit", "20M");
     @ob_end_clean();
     $search_prefix = JComponentHelper::getParams('com_flexicontent')->get('add_search_prefix') ? 'vvv' : '';
     // SEARCH WORD Prefix
     $indexer = JRequest::getVar('indexer', 'advanced');
     $rebuildmode = JRequest::getVar('rebuildmode', '');
     $items_per_call = JRequest::getVar('items_per_call', 20);
     // Number of item to index per HTTP request
     $itemcnt = JRequest::getVar('itemcnt', 0);
     // Counter of items indexed so far, this is given via HTTP request
     // TAKE CARE: this code depends on countrows() to set session variables
     // Retrieve fields, that are assigned as (advanced/basic) searchable/filterable
     if ($rebuildmode == 'quick' && $indexer == 'advanced') {
         $nse_fields = $session->get($indexer . '_nse_fields', array(), 'flexicontent');
         $nsp_fields = $session->get($indexer . '_nsp_fields', array(), 'flexicontent');
         $fields = $session->get($indexer . '_fields', array(), 'flexicontent');
         //echo 'fail|'; print_r(array_keys($fields)); exit;
         // Get the field ids of the fields removed from searching
         $del_fieldids = array_unique(array_merge(array_keys($nse_fields), array_keys($nsp_fields), array_keys($fields)));
     } else {
         $fields = $session->get($indexer . '_fields', array(), 'flexicontent');
         //echo 'fail|'; print_r(array_keys($fields)); exit;
     }
     // Get the field ids of the searchable fields
     $fieldids = array_keys($fields);
     // Get fields that will have atomic search tables, (current for advanced index only)
     if ($indexer == 'advanced') {
         $filterables = FlexicontentFields::getSearchFields('id', $indexer, null, null, $_load_params = false, 0, $search_type = 'filter');
         $filterables = array_keys($filterables);
         $filterables = array_flip($filterables);
     } else {
         $filterables = array();
     }
     // Get items ids that have value for any of the searchable fields, but use session to avoid recalculation
     $itemids = $session->get($indexer . '_items_to_index', array(), 'flexicontent');
     $_fields = array();
     foreach ($fields as $field_id => $field) {
         // Clone field to avoid problems
         $_fields[$field_id] = clone $field;
         // Create field parameters if not already created
         if (empty($_fields[$field_id]->parameters)) {
             $_fields[$field_id]->parameters = new JRegistry($_fields[$field_id]->attribs);
         }
     }
     $fields = $_fields;
     // Get query size limit
     $query = "SHOW VARIABLES LIKE 'max_allowed_packet'";
     $db->setQuery($query);
     $_dbvariable = $db->loadObject();
     $max_allowed_packet = flexicontent_upload::parseByteLimit(@$_dbvariable->Value);
     $max_allowed_packet = $max_allowed_packet ? $max_allowed_packet : 256 * 1024;
     $query_lim = (int) (3 * $max_allowed_packet / 4);
     //echo 'fail|'.$query_lim; exit;
     // Get script max
     $max_execution_time = ini_get("max_execution_time");
     //echo 'fail|'.$max_execution_time; exit;
     $query_count = 0;
     $max_items_per_query = 100;
     $max_items_per_query = $max_items_per_query > $items_per_call ? $items_per_call : $max_items_per_query;
     $cnt = $itemcnt;
     while ($cnt < count($itemids) && $cnt < $itemcnt + $items_per_call) {
         $query_itemids = array_slice($itemids, $cnt, $max_items_per_query);
         $cnt += $max_items_per_query;
         // Item is not needed, later and only if field uses item replacements then it will be loaded
         $item = null;
         // Items language is needed to do (if needed) special per language handling
         $lang_query = "SELECT id, language" . " FROM #__content AS i " . " WHERE id IN (" . implode(', ', $query_itemids) . ")";
         $db->setQuery($lang_query);
         $items_data = $db->loadObjectList('id');
         if ($indexer == 'basic') {
             $searchindex = array();
             // Add all query itemids to searchindex array so that it will be cleared even if zero fields are indexed
             foreach ($query_itemids as $query_itemid) {
                 $searchindex[$query_itemid] = array();
             }
         } else {
             // This will hold the SQL inserting new advanced search records for multiple item/values
             $ai_query_vals = array();
             $ai_query_vals_f = array();
             // Current for advanced index only
         }
         // For current item: Loop though all searchable fields according to their type
         foreach ($fieldids as $fieldid) {
             // Must SHALLOW clone because we will be setting some properties , e.g. 'ai_query_vals', that we do not
             $field = clone $fields[$fieldid];
             // Indicate multiple items per query
             $field->item_id = 0;
             $field->query_itemids = $query_itemids;
             $field->items_data = $items_data;
             // Includes item langyage, which may be used for special per language handling
             // Indicate that the indexing fuction should retrieve the values
             $values = null;
             // Add values to advanced search index
             $fieldname = $field->iscore ? 'core' : $field->field_type;
             if ($indexer == 'advanced') {
                 FLEXIUtilities::call_FC_Field_Func($fieldname, 'onIndexAdvSearch', array(&$field, &$values, &$item));
                 //print_r($field->ai_query_vals);
                 if (isset($field->ai_query_vals)) {
                     foreach ($field->ai_query_vals as $query_val) {
                         $ai_query_vals[] = $query_val;
                     }
                     if (isset($filterables[$field->id])) {
                         // Current for advanced index only
                         foreach ($field->ai_query_vals as $query_val) {
                             $ai_query_vals_f[$field->id][] = $query_val;
                         }
                     }
                 }
                 //else echo "Not set for : ". $field->name;
             } else {
                 if ($indexer == 'basic') {
                     FLEXIUtilities::call_FC_Field_Func($fieldname, 'onIndexSearch', array(&$field, &$values, &$item));
                     foreach ($query_itemids as $query_itemid) {
                         if (@$field->search[$query_itemid]) {
                             $searchindex[$query_itemid][] = $field->search[$query_itemid];
                         }
                     }
                 }
             }
         }
         // Create query that will update/insert data into the DB
         unset($queries);
         // make sure it is not set above
         $queries = array();
         if ($indexer == 'basic') {
             if (count($searchindex)) {
                 // check for zero search index records
                 $query_vals = '';
                 $query_ids = array();
                 // Start new query
                 foreach ($searchindex as $query_itemid => $search_text) {
                     if (strlen($query_vals) > $query_lim) {
                         $query = "UPDATE #__flexicontent_items_ext SET search_index = CASE item_id " . $query_vals . " END " . " WHERE item_id IN (" . implode(',', $query_ids) . ")";
                         $queries[] = $query;
                         $query_vals = '';
                         $query_ids = array();
                         // Start new query
                     }
                     $query_ids[] = $query_itemid;
                     $_search_text = implode(' | ', $search_text);
                     if ($search_prefix && $_search_text) {
                         $_search_text = preg_replace('/(\\b[^\\s,\\.]+\\b)/u', $search_prefix . '$0', trim($_search_text));
                     }
                     $query_vals .= " WHEN {$query_itemid} THEN " . $db->Quote($_search_text);
                 }
                 if (count($query_ids)) {
                     $query = "UPDATE #__flexicontent_items_ext SET search_index = CASE item_id " . $query_vals . " END " . " WHERE item_id IN (" . implode(',', $query_ids) . ")";
                     $queries[] = $query;
                 }
             }
         } else {
             if (count($ai_query_vals)) {
                 // check for zero search index records
                 $query_vals = '';
                 // Start new query
                 foreach ($ai_query_vals as &$query_value) {
                     $query_vals .= ($query_vals ? ',' : '') . $query_value;
                     if (strlen($query_vals) > $query_lim) {
                         $queries[] = "INSERT INTO #__flexicontent_advsearch_index " . " (field_id,item_id,extraid,search_index,value_id) VALUES " . $query_vals;
                         $query_vals = '';
                         // Start new query
                     }
                 }
                 unset($query_value);
                 if (strlen($query_vals)) {
                     $queries[] = "INSERT INTO #__flexicontent_advsearch_index " . " (field_id,item_id,extraid,search_index,value_id) VALUES " . $query_vals;
                 }
             }
             foreach ($ai_query_vals_f as $_field_id => $_query_vals) {
                 $query_vals = '';
                 // Start new query
                 foreach ($_query_vals as &$query_value) {
                     $query_vals .= ($query_vals ? ',' : '') . $query_value;
                     if (strlen($query_vals) > $query_lim) {
                         $queries[] = "INSERT INTO #__flexicontent_advsearch_index_field_" . $_field_id . " (field_id,item_id,extraid,search_index,value_id) VALUES " . $query_vals;
                         $query_vals = '';
                         // Start new query
                     }
                 }
                 if (strlen($query_vals)) {
                     $queries[] = "INSERT INTO #__flexicontent_advsearch_index_field_" . $_field_id . " (field_id,item_id,extraid,search_index,value_id) VALUES " . $query_vals;
                     $query_vals = '';
                     // Start new query
                 }
             }
         }
         foreach ($queries as $query) {
             $db->setQuery($query);
             try {
                 $db->execute();
             } catch (RuntimeException $e) {
                 echo "fail|" . $e->getMessage();
                 exit;
             }
         }
         $query_count += count($queries);
         $elapsed_microseconds = round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10;
         $elapsed_seconds = $elapsed_microseconds / 1000000.0;
         if ($elapsed_seconds > $max_execution_time / 3 || $elapsed_seconds > 5) {
             break;
         }
     }
     // Check if items have finished, otherwise continue with -next- group of item ids
     if ($cnt >= count($itemids)) {
         // Reset dirty SEARCH properties of published fields to be: normal ON/OFF
         $set_clause = ' SET' . ($indexer == 'basic' ? ' issearch = CASE issearch WHEN 2 THEN 1   WHEN -1 THEN 0   ELSE issearch   END' : ' isadvsearch = CASE isadvsearch WHEN 2 THEN 1   WHEN -1 THEN 0   ELSE isadvsearch   END,' . ' isadvfilter = CASE isadvfilter WHEN 2 THEN 1   WHEN -1 THEN 0   ELSE isadvfilter   END');
         $query = 'UPDATE #__flexicontent_fields' . $set_clause . " WHERE published=1";
         $db->setQuery($query);
         $db->execute();
         // Force SEARCH properties of unpublished fields to be: normal OFF
         if ($indexer == 'basic') {
             $query = 'UPDATE #__flexicontent_fields SET issearch = 0 WHERE published=0';
             $db->setQuery($query);
             $db->execute();
         } else {
             $query = 'UPDATE #__flexicontent_fields SET isadvsearch = 0, isadvfilter = 0  WHERE published=0';
             $db->setQuery($query);
             $db->execute();
         }
     }
     if (!count($fieldids)) {
         echo 'fail|Index was only cleaned-up, <br/>since no <b>fields</b> were marked as: ' . '<br> -- ' . ($indexer == 'basic' ? 'Text Searchable (CONTENT LISTS)' : 'Text Searchable OR filterable (SEARCH VIEW)');
         exit;
     }
     if (!count($itemids)) {
         echo 'fail|Index was only cleaned-up, <br/>since no <b>items</b> were found to have value for fields marked as: ' . '<br> -- ' . ($indexer == 'basic' ? 'Text Searchable (CONTENT LISTS)' : 'Text Searchable OR filterable (SEARCH VIEW)');
         exit;
     }
     $elapsed_microseconds = round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10;
     if ($session->has($indexer . '_total_runtime', 'flexicontent')) {
         $_total_runtime = $session->get($indexer . '_total_runtime', 0, 'flexicontent');
     } else {
         $_total_runtime = 0;
     }
     $_total_runtime += $elapsed_microseconds;
     $session->set($indexer . '_total_runtime', $_total_runtime, 'flexicontent');
     if ($session->has($indexer . '_total_queries', 'flexicontent')) {
         $_total_queries = $session->get($indexer . '_total_queries', 0, 'flexicontent');
     } else {
         $_total_queries = 0;
     }
     $_total_queries += $query_count;
     $session->set($indexer . '_total_queries', $_total_queries, 'flexicontent');
     echo sprintf($cnt . ' | Server execution time: %.2f secs ', $_total_runtime / 1000000) . ' | Total DB updates: ' . $_total_queries;
     exit;
 }