Your IP : 216.73.216.43


Current Path : /home/cbequiperp/www/administrator/components/com_flexicontent/models/
Upload File :
Current File : /home/cbequiperp/www/administrator/components/com_flexicontent/models/search.php

<?php
/**
 * @package         FLEXIcontent
 * @version         3.3
 *
 * @author          Emmanuel Danan, Georgios Papadakis, Yannick Berges, others, see contributor page
 * @link            https://flexicontent.org
 * @copyright       Copyright © 2018, FLEXIcontent team, All Rights Reserved
 * @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
 */

defined('_JEXEC') or die('Restricted access');

use Joomla\String\StringHelper;
use Joomla\Utilities\ArrayHelper;
use Joomla\CMS\Table\Table;

require_once('base/baselist.php');

/**
 * FLEXIcontent Component Search Model
 *
 */
class FLEXIcontentModelSearch extends FCModelAdminList
{
	/**
	 * Record database table
	 *
	 * @var string
	 */
	var $records_dbtbl  = null;

	/**
	 * Record jtable name
	 *
	 * @var string
	 */
	var $records_jtable = null;

	/**
	 * Column names
	 */
	var $state_col      = null;
	var $name_col       = null;
	var $parent_col     = null;
	var $created_by_col = null;

	/**
	 * Search and ordering columns
	 */
	var $search_cols = array(
	);
	var $default_order     = 'a.title';
	var $default_order_dir = 'ASC';

	/**
	 * List filters that are always applied
	 */
	var $hard_filters = array();

	/**
	 * Record rows
	 *
	 * @var array
	 */
	var $_data = null;

	/**
	 * Rows total
	 *
	 * @var integer
	 */
	var $_total = null;

	/**
	 * Pagination object
	 *
	 * @var object
	 */
	var $_pagination = null;

	/**
	 * Search areas
	 *
	 * @var array
	 */
	var $_areas = null;

	/**
	 * Constructor
	 *
	 * @since 3.3.0
	 */
	public function __construct($config = array())
	{
		$app    = JFactory::getApplication();
		$jinput = $app->input;
		$option = $jinput->getCmd('option', '');
		$view   = $jinput->getCmd('view', '');
		$layout = $jinput->getString('layout', 'default');
		$fcform = $jinput->getInt('fcform', 0);

		// Make session index more specific ... (if needed by this model)
		//$this->view_id = $view . '_' . $layout;

		// Call parent after setting ... $this->view_id
		parent::__construct($config);

		$p = $this->ovid;


		/**
		 * View's Filters
		 * Inherited filters : filter_state, search
		 */

		// Various filters
		$filter_type      = $fcform ? $jinput->get('filter_type', 0, 'int') : $app->getUserStateFromRequest($p . 'filter_type',  'filter_type',   0, 'int' );
		$filter_itemlang  = $fcform ? $jinput->get('filter_itemlang', '', 'cmd') : $app->getUserStateFromRequest($p . 'filter_itemlang', 'filter_itemlang', '', 'cmd');
		$filter_fieldtype = $fcform ? $jinput->get('filter_fieldtype', '', 'cmd') : $app->getUserStateFromRequest($p . 'filter_fieldtype', 'filter_fieldtype', '', 'cmd');
		$search_itemtitle = $fcform ? $jinput->get('search_itemtitle', '', 'string') : $app->getUserStateFromRequest($p . 'search_itemtitle', 'search_itemtitle', '', 'string' );
		$search_itemid    = $fcform ? $jinput->get('search_itemid', 0, 'int') : $app->getUserStateFromRequest( $p.'search_itemid',    'search_itemid',     0, 'int' );

		$this->setState('filter_type', $filter_type);
		$this->setState('filter_itemlang', $filter_itemlang);
		$this->setState('filter_fieldtype', $filter_fieldtype);
		$this->setState('search_itemtitle', $search_itemtitle);
		$this->setState('search_itemid', $search_itemid);

		$app->setUserState($p.'filter_type', $filter_type);
		$app->setUserState($p.'filter_itemlang', $filter_itemlang);
		$app->setUserState($p.'filter_fieldtype', $filter_fieldtype);
		$app->setUserState($p.'search_itemtitle', $search_itemtitle);
		$app->setUserState($p.'search_itemid', $search_itemid);


		// Type of search index being listed
		$indexer = $app->getUserStateFromRequest( $p.'indexer', 'indexer', '', 'cmd' );
		if ($indexer)
		{
			$filter_indextype = $indexer;
			$app->setUserState('indexer', '');
		}
		else
		{
			$filter_indextype = $fcform ? $jinput->get('filter_indextype',  'advanced', 'cmd')  :  $app->getUserStateFromRequest( $p.'filter_indextype', 'filter_indextype', 'advanced', 'cmd' );
		}
		$this->setState('filter_indextype', $filter_indextype);
		$app->setUserState($p.'filter_indextype', $filter_indextype);
		$isADV = $filter_indextype=='advanced';



		/**
		 * Override default ordering code
		 */

		$default_order     = $this->cparams->get('search_manager_order', 'a.title');  // Parameter does not exist
		$default_order_dir = $this->cparams->get('search_manager_order_dir', 'ASC');  // Parameter does not exist

		$filter_order      = $fcform ? $jinput->get('filter_order',     $default_order,      'cmd')  :  $app->getUserStateFromRequest( $p.'filter_order',     'filter_order',     $default_order,      'cmd' );
		$filter_order_Dir  = $fcform ? $jinput->get('filter_order_Dir', $default_order_dir, 'word')  :  $app->getUserStateFromRequest( $p.'filter_order_Dir', 'filter_order_Dir', $default_order_dir, 'word' );

		if (!$filter_order)
		{
			$filter_order = $default_order;
		}

		if (!$filter_order_Dir)
		{
			$filter_order_Dir = $default_order_dir;
		}

		// Clear invalid order when search if switch search is 
		if (!$isADV && !in_array($this->getState('filter_order'), array('a.id', 'a.title', 'ext.search_index')))
		{
			$this->setState('filter_order', 'a.title');
			$app->setUserState($p.'filter_order', 'a.title');
		}
	}


	function getData()
	{
		if (!empty($this->_data)) return $this->_data;

		$cparams = JComponentHelper::getParams('com_flexicontent');
		$print_logging_info = $cparams->get('print_logging_info');
		if ( $print_logging_info )  global $fc_run_times;


		// 1, get filtered, limited, ordered items
		$query = $this->_buildQuery();

		if ( $print_logging_info )  $start_microtime = microtime(true);
		$this->_db->setQuery($query, $this->getState('limitstart'), $this->getState('limit'));
		$rows = $this->_db->loadObjectList();
		if ( $print_logging_info ) @$fc_run_times['execute_main_query'] += round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10;


		// 2, get current items total for pagination
		$this->_db->setQuery("SELECT FOUND_ROWS()");
		$this->_total = $this->_db->loadResult();

		$filter_indextype = $this->getState('filter_indextype');
		$isADV = $filter_indextype=='advanced';


		// 3, get item ids
		$query_ids = array();
		foreach ($rows as $row) {
			$query_ids[] = $isADV ? $row->sid : $row->item_id;
		}


		// 4, get item data
		if (count($query_ids)) $query = $this->_buildQuery($query_ids);
		if ( $print_logging_info )  $start_microtime = microtime(true);
		$_data = array();
		if (count($query_ids)) {
			$this->_db->setQuery($query);
			$_data = $this->_db->loadObjectList($isADV ? 'sid' : 'item_id');
		}
		if ( $print_logging_info ) @$fc_run_times['execute_sec_queries'] += round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10;


		// 5, reorder items and get cat ids
		$this->_data = array();
		foreach($query_ids as $query_id) {
			$this->_data[] = $_data[$query_id];
		}


		return $this->_data;
	}


	/**
	 * Method to get the number of relevant search index records
	 *
	 * @access	public
	 * @return	mixed	False on failure, integer on success.
	 * @since	1.0
	 */
	public function getCount() {
		// Lets load the Items if it doesn't already exist
		if ( $this->_total === null ) {
			$query = $this->_buildQuery();
			$this->_total = $this->_getListCount($query);
		}
		return $this->_total;
	}


	/**
	 * Method to build the query for the retrieval of search index records
	 *
	 * @access private
	 * @return string
	 * @since 1.0
	 */
	function _buildQuery($query_ids = false)
	{
		if (!$query_ids)
		{
			$where		= $this->_buildWhere();
			$orderby	= $this->_buildOrderBy();

			$filter_order     = $this->getState('filter_order');

			$filter_itemlang = $this->getState('filter_itemlang');
			$filter_fieldtype = $this->getState('filter_fieldtype');
			$filter_state = $this->getState('filter_state');
			$filter_type  = $this->getState('filter_type');

			$search_itemtitle = $this->getState('search_itemtitle');
			$search_itemid    = $this->getState('search_itemid');
		}

		$filter_indextype = $this->getState('filter_indextype');
		$isADV = $filter_indextype=='advanced';

		$query = !$query_ids
			? 'SELECT SQL_CALC_FOUND_ROWS ' . ($isADV ? 'ai.sid' : 'ext.item_id')
			: ($isADV
				? 'SELECT f.label, f.name, f.field_type, ai.*, a.title, a.id, a.language, 0 AS checked_out '
				: 'SELECT ext.*, a.title, a.id, a.language, 0 AS checked_out '
			);
		$query .= $isADV ? ' FROM #__flexicontent_advsearch_index as ai' : ' FROM #__flexicontent_items_ext as ext';

		if ($query_ids)
		{
			$query .= ''
				.' JOIN #__flexicontent_items_tmp as a ON ' .($isADV ? 'ai' : 'ext'). '.item_id=a.id'
				.(!$isADV ? '' : ''
					.' JOIN #__flexicontent_items_ext as ext ON ext.item_id=a.id'
					.' JOIN #__flexicontent_fields_type_relations as rel ON rel.field_id=ai.field_id AND rel.type_id=ext.type_id'
					.' JOIN #__flexicontent_fields as f ON ai.field_id=f.id'
				)
				;
		}
		else
		{
			if ($isADV && (in_array($filter_order, array('f.label','f.name','f.field_type')) || $filter_fieldtype))
			{
				$query .= ''
					.' JOIN #__flexicontent_items_tmp as a ON ai.item_id=a.id'
					.' JOIN #__flexicontent_items_ext as ext ON ext.item_id=a.id'
					.' JOIN #__flexicontent_fields_type_relations as rel ON rel.field_id=ai.field_id AND rel.type_id=ext.type_id'
					.' JOIN #__flexicontent_fields as f ON ai.field_id=f.id'
					;
			}
			else
			{
				if ($filter_order == 'a.id' || $filter_order == 'a.title' || $filter_state || $filter_type || $filter_itemlang || $search_itemtitle || $search_itemid)
					$query .= ' JOIN #__flexicontent_items_tmp as a ON ' .($isADV ? 'ai' : 'ext'). '.item_id=a.id';
				if ($isADV && $filter_type)
					$query .= ' JOIN #__flexicontent_items_ext as ext ON ext.item_id=a.id';
			}
		}

		$query .= !$query_ids ?
			$where.$orderby :
			($isADV ?
				' WHERE ai.sid IN ('. implode(',', $query_ids) .')' :
				' WHERE ext.item_id IN ('. implode(',', $query_ids) .')'
			);

		return $query;
	}


	/**
	 * Method to build the orderby clause of the query for the search index
	 *
	 * @access private
	 * @return string
	 * @since 1.0
	 */
	function _buildOrderBy()
	{
		$filter_order     = $this->getState('filter_order');
		$filter_order_Dir = $this->getState('filter_order_Dir');

		$orderby = $filter_order.' '.$filter_order_Dir;
		$orderby = ' ORDER BY '.$orderby;

		return $orderby;
	}


	/**
	 * Method to build the where clause of the query for the fields
	 *
	 * @access private
	 * @return string
	 * @since 1.0
	 */
	function _buildWhere()
	{
		static $where;

		if (isset($where))
		{
			return $where;
		}

		$filter_state	= $this->getState('filter_state');
		$filter_type	= $this->getState('filter_type');
		$filter_itemlang  = $this->getState('filter_itemlang');
		$filter_fieldtype = $this->getState('filter_fieldtype');
		$search_itemtitle	= $this->getState('search_itemtitle');
		$search_itemid		= $this->getState('search_itemid');

		$filter_indextype = $this->getState('filter_indextype');
		$isADV = $filter_indextype=='advanced';

		$search  = $this->getState('search');
		$search  = StringHelper::trim(StringHelper::strtolower($search));

		$where = array();

		if ($isADV && $filter_fieldtype)
		{
			if ($filter_fieldtype === 'C' )
			{
				$where[] = 'f.iscore = 1';
			}
			elseif ($filter_fieldtype === 'NC')
			{
				$where[] = 'f.iscore = 0';
			}
			else
			{
				$where[] = 'f.field_type = ' . $this->_db->quote($filter_fieldtype);
			}
		}

		if ($filter_itemlang)
		{
			$where[] = 'a.language = ' . $this->_db->quote($filter_itemlang);
		}

		if ($filter_state)
		{
			if ($filter_state === 'ALL_P')
			{
				$where[] = 'a.state IN (1, -5)';
			}
			elseif ($filter_state === 'ALL_U')
			{
				$where[] = 'a.state NOT IN (1, -5)';
			}
		}

		if ($filter_type)
		{
			$where[] = 'ext.type_id = ' . (int) $filter_type;
		}

		if ($search)
		{
			$escaped_search = str_replace(' ', '%', $this->_db->escape(trim($search), true));
			$search_quoted  = $this->_db->Quote('%' . $escaped_search . '%', false);

			$where[] = ' LOWER(' . ($isADV ? 'ai' : 'ext') . '.search_index) LIKE ' . $search_quoted;
		}

		if ($search_itemtitle)
		{
			$search_itemtitle_escaped = $this->_db->escape($search_itemtitle, true);
			$where[] = ' LOWER(a.title) LIKE ' . $this->_db->Quote('%' . $search_itemtitle_escaped . '%', false);
		}

		if ($search_itemid)
		{
			$where[] = ' a.id= ' . (int) $search_itemid;
		}

		$where = count($where) ? implode(' AND ', $where) : '';
		$where = trim($where) ? ' WHERE ' . $where : '';

		return $where;
	}


	/**
	 * Method to get types list
	 *
	 * @return array
	 * @since 1.5
	 */
	function getTypeslist ( $type_ids=false, $check_perms = false, $published=true )
	{
		return flexicontent_html::getTypesList( $type_ids, $check_perms, $published);
	}


	/**
	 * START OF MODEL LEGACY METHODS
	 */


	/**
	 * Method to empty search indexes
	 *
	 * @return	null
	 *
	 * @since	3.0
	 */
	public function purge($del_fieldids = null)
	{
		$app      = JFactory::getApplication();
		$dbprefix = $app->getCfg('dbprefix');
		$dbname   = $app->getCfg('db');

		/**
		 * 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. ")";
		}

		$this->_db->setQuery($query)->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 = $dbprefix . 'flexicontent_advsearch_index_field_';
		$query = 'SELECT TABLE_NAME
			FROM INFORMATION_SCHEMA.TABLES
			WHERE TABLE_SCHEMA = ' . $this->_db->Quote($dbname)
				. ' AND TABLE_NAME LIKE ' . $this->_db->Quote($tbl_prefix . '%');
		$tbl_names = $this->_db->setQuery($query)->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);
			}

			// Truncate (or drop/recreate) tables of fields that are still filterable. Any dropped but needed tables will be recreated below
			elseif (empty($del_fieldids) || isset($del_fieldids[$_field_id]))
			{
				$this->_db->setQuery('TRUNCATE TABLE ' . $tbl_name);
			}

			$this->_db->execute();
		}

		// VERIFY all search tables exist
		$tbl_names_flipped = array_flip($tbl_names);

		foreach ($filterables as $_field_id => $_ignored)
		{
			$tbl_name = $dbprefix . 'flexicontent_advsearch_index_field_'.$_field_id;
			$query = '
			CREATE TABLE IF NOT EXISTS ' . $this->_db->quoteName($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)->execute();
		}
	}
}