예제 #1
0
 /**
  * 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);
     }
 }
 /**
  * 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;
 }
예제 #3
0
 /**
  * Content Search method
  * The sql must return the following fields that are used in a common display
  * routine: href, title, section, created, text, browsernav
  * @param string Target search string
  * @param string mathcing option, exact|any|all
  * @param string ordering option, newest|oldest|popular|alpha|category
  * @param mixed An array if restricted to areas, null if search all
  */
 function onContentSearch($text, $phrase = '', $ordering = '', $areas = null)
 {
     $db = JFactory::getDbo();
     $app = JFactory::getApplication();
     $user = JFactory::getUser();
     // Get language
     $cntLang = substr(JFactory::getLanguage()->getTag(), 0, 2);
     // Current Content language (Can be natively switched in J2.5)
     $urlLang = JRequest::getWord('lang', '');
     // Language from URL (Can be switched via Joomfish in J1.5)
     $lang = FLEXI_J16GE || empty($urlLang) ? $cntLang : $urlLang;
     // COMPONENT PARAMETERS
     $cparams = $app->isSite() ? $app->getParams('com_flexicontent') : JComponentHelper::getParams('com_flexicontent');
     if (!defined('FLEXI_SECTION')) {
         define('FLEXI_SECTION', $cparams->get('flexi_section'));
     }
     // define section
     $show_noauth = $cparams->get('show_noauth', 0);
     // items the user cannot see ...
     $searchText = $text;
     $AllAreas = array_keys($this->_getAreas());
     $AllTypes = array_keys($this->_getContentTypes());
     if (is_array($areas)) {
         // search in selected areas
         $searchAreas = array_intersect($areas, $AllAreas);
         $searchTypes = array_intersect($areas, $AllTypes);
         if (!$searchAreas && !$searchTypes) {
             return array();
         }
         if (!$searchAreas) {
             $searchAreas = $AllAreas;
         }
         if (!$searchTypes) {
             $searchTypes = $AllTypes;
         }
     } else {
         // search in all avaliable areas if no selected ones
         $searchAreas = $AllAreas;
         $searchTypes = $AllTypes;
     }
     foreach ($searchTypes as $id => $tipe) {
         $searchTypes[$id] = preg_replace('/\\D/', '', $tipe);
     }
     $types = implode(', ', $searchTypes);
     $filter_lang = $this->params->def('filter_lang', 1);
     $limit = $this->params->def('search_limit', 50);
     // Dates for publish up & down items
     $date = JFactory::getDate();
     $nowDate = $date->toSql();
     $nullDate = $db->getNullDate();
     $text = trim($text);
     if ($text == '') {
         return array();
     }
     $wheres = array();
     switch ($phrase) {
         case 'exact':
             $text = $db->escape($text, true);
             $text = $db->Quote('%' . $text . '%', false);
             $wheres2 = array();
             if (in_array('FlexisearchTitle', $searchAreas)) {
                 $wheres2[] = 'i.title LIKE ' . $text;
             }
             if (in_array('FlexisearchDesc', $searchAreas)) {
                 $wheres2[] = 'i.introtext LIKE ' . $text;
                 $wheres2[] = 'i.fulltext LIKE ' . $text;
             }
             if (in_array('FlexisearchMeta', $searchAreas)) {
                 $wheres2[] = 'i.metakey LIKE ' . $text;
                 $wheres2[] = 'i.metadesc LIKE ' . $text;
             }
             if (in_array('FlexisearchFields', $searchAreas)) {
                 $wheres2[] = "f.field_type IN ('text','textselect') AND f.issearch=1 AND fir.value LIKE " . $text;
             }
             if (in_array('FlexisearchTags', $searchAreas)) {
                 $wheres2[] = 't.name LIKE ' . $text;
             }
             if (count($wheres2)) {
                 $where = '(' . implode(') OR (', $wheres2) . ')';
             }
             break;
         case 'all':
         case 'any':
         default:
             $words = explode(' ', $text);
             $wheres = array();
             foreach ($words as $word) {
                 $word = $db->escape($word, true);
                 $word = $db->Quote('%' . $word . '%', false);
                 $wheres2 = array();
                 if (in_array('FlexisearchTitle', $searchAreas)) {
                     $wheres2[] = 'i.title LIKE ' . $word;
                 }
                 if (in_array('FlexisearchDesc', $searchAreas)) {
                     $wheres2[] = 'i.introtext LIKE ' . $word;
                     $wheres2[] = 'i.fulltext LIKE ' . $word;
                 }
                 if (in_array('FlexisearchMeta', $searchAreas)) {
                     $wheres2[] = 'i.metakey LIKE ' . $word;
                     $wheres2[] = 'i.metadesc LIKE ' . $word;
                 }
                 if (in_array('FlexisearchFields', $searchAreas)) {
                     $wheres2[] = "f.field_type IN ('text','textselect') AND f.issearch=1 AND fir.value LIKE " . $word;
                 }
                 if (in_array('FlexisearchTags', $searchAreas)) {
                     $wheres2[] = 't.name LIKE ' . $word;
                 }
                 if (count($wheres2)) {
                     $wheres[] = '(' . implode(') OR (', $wheres2) . ')';
                 }
             }
             if (count($wheres)) {
                 $where = '(' . implode($phrase == 'all' ? ') AND (' : ') OR (', $wheres) . ')';
             }
             break;
     }
     if (!@$where) {
         return array();
     }
     //if ( empty($where) ) $where = '1';
     switch ($ordering) {
         //case 'relevance': $order = ' ORDER BY score DESC, i.title ASC'; break;
         case 'oldest':
             $order = 'i.created ASC';
             break;
         case 'popular':
             $order = 'i.hits DESC';
             break;
         case 'alpha':
             $order = 'i.title ASC';
             break;
         case 'category':
             $order = 'c.title ASC, i.title ASC';
             break;
         case 'newest':
             $order = 'i.created DESC';
             break;
         default:
             $order = 'i.created DESC';
             break;
     }
     // ****************************************************************************************
     // Create JOIN clause and WHERE clause part for filtering by current (viewing) access level
     // ****************************************************************************************
     $joinaccess = '';
     $andaccess = '';
     $select_access = '';
     // Extra access columns for main category and content type (item access will be added as 'access')
     $select_access .= ',  c.access as category_access, ty.access as type_access';
     if (!$show_noauth) {
         // User not allowed to LIST unauthorized items
         $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 ( i.language LIKE ' . $db->Quote($lang . '%') . ' OR i.language="*" ) ';
         $andlang .= ' AND ( c.language LIKE ' . $db->Quote($lang . '%') . ' OR c.language="*" ) ';
     }
     // search articles
     $results = array();
     if ($limit > 0) {
         $query = $db->getQuery(true);
         $query->clear();
         $query->select('' . ' i.id as id,' . ' i.title AS title,' . ' i.language AS language,' . ' i.metakey AS metakey,' . ' i.metadesc AS metadesc,' . ' i.modified AS created,' . ' t.name AS tagname,' . ' fir.value as field,' . ' i.access, ie.type_id,' . ' CONCAT(i.introtext, i.fulltext) AS text,' . ' CONCAT_WS( " / ", ' . $db->Quote(JText::_('FLEXICONTENT')) . ', c.title, i.title ) AS section,' . ' CASE WHEN CHAR_LENGTH(i.alias) THEN CONCAT_WS(\':\', i.id, i.alias) ELSE i.id END AS slug,' . ' CASE WHEN CHAR_LENGTH(c.alias) THEN CONCAT_WS(\':\', c.id, c.alias) ELSE c.id END AS catslug,' . ' "2" AS browsernav' . $select_access);
         $query->from('#__content AS i ' . ' JOIN #__categories AS c ON i.catid = c.id' . ' JOIN #__flexicontent_items_ext AS ie ON i.id = ie.item_id' . ' JOIN #__flexicontent_types AS ty ON ie.type_id = ty.id' . ' LEFT JOIN #__flexicontent_fields_item_relations AS fir ON i.id = fir.item_id' . ' LEFT JOIN #__flexicontent_fields AS f ON fir.field_id = f.id' . ' LEFT JOIN #__flexicontent_tags_item_relations AS tir ON i.id = tir.itemid' . ' LEFT JOIN #__flexicontent_tags AS t ON tir.tid = t.id	' . $joinaccess);
         $query->where(' (' . $where . ') ' . ' AND ie.type_id IN(' . $types . ') ' . ' AND i.state IN (1, -5) AND c.published = 1 ' . ' AND (i.publish_up = ' . $db->Quote($nullDate) . ' OR i.publish_up <= ' . $db->Quote($nowDate) . ') ' . ' AND (i.publish_down = ' . $db->Quote($nullDate) . ' OR i.publish_down >= ' . $db->Quote($nowDate) . ') ' . $andaccess . $andlang);
         $query->group('i.id');
         $query->order($order);
         //echo "<pre style='white-space:normal!important;'>".$query."</pre>";
         $db->setQuery($query, 0, $limit);
         $list = $db->loadObjectList();
         if ($db->getErrorNum()) {
             echo $db->getErrorMsg();
         }
         if ($list) {
             $item_cats = FlexicontentFields::_getCategories($list);
             $typeData = flexicontent_db::getTypeData();
             foreach ($list as $key => $item) {
                 // echo $item->title." ".$item->tagname."<br/>"; // Before checking for noHTML
                 $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->catslug, $item->language));
                 } else {
                     $item->href = JRoute::_(FlexicontentHelperRoute::getItemRoute($item->slug, $item->catslug, 0, $item));
                 }
                 if (searchHelper::checkNoHTML($item, $searchText, array('title', 'metadesc', 'metakey', 'tagname', 'field', 'text'))) {
                     $results[$item->id] = $item;
                 }
             }
         }
     }
     return $results;
 }