Your IP : 216.73.216.240


Current Path : /home/juvelize/saulnois/tmp/install_695d2cf0b4957/src/Model/Back/
Upload File :
Current File : /home/juvelize/saulnois/tmp/install_695d2cf0b4957/src/Model/Back/TfModelList.php

<?php
/*
* @package		Tech Fry Library
* @license		https://www.gnu.org/licenses/gpl-3.0.en.html
*/

namespace TechFry\Library\Model\Back;

\defined('_JEXEC') or die;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Associations;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\CMS\MVC\Model\ListModel;
use Joomla\Database\ParameterType;
use Joomla\CMS\Date\Date;
use Joomla\Utilities\ArrayHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;
use TechFry\Library\TDb;
use TechFry\Library\Model\TfModelTrait;

class TfModelList extends ListModel
{
    // ListModel: getActiveFilters(), getFilterForm(), getItems(), getPagination(), getTotal()
    
    use TfModelTrait, TfFilterTrait;
    
    public $select_fields = [];
    
  	public $left_joins = [];
  	public $inner_joins = [];
    public $where = [];
    
    public $orderCol = 'a.id';
    public $orderDirn = 'DESC';
    
    public $search = 'a.title'; // Default search field
  	public $search_fields = []; // key - operator, value - table.database_column
    
    public $filters = []; // key - name in filter form, value - table.database_column
    public $datefilters = [];
    
    public $sorting_fields = [];
    
    public $sortings = [];
    
    public $is_ml = false;
    
    public function __construct($config = [], ?MVCFactoryInterface $factory = null)
    {
        if ($this->table_name)
		{
		    $db = new TDb($this->table_name);
            $this->table_columns = $db->get_table_columns();
		}
		
        // Set default filters - published, access, note
		$this->set_filters();

        // Set default fields for sorting - id, title, published, created, modified, hits, ordering, access, note
		$this->set_sorting_fields();
      
        // Set default fields for search term - id, description, note
      	$this->set_search_fields();
      	
      	$config['filter_fields'] = $this->sorting_fields;
        
        if (Associations::isEnabled())
		{
			$config['filter_fields'][] = 'association';
		}
      
        parent::__construct($config, $factory);
        
        $this->app = Factory::getApplication();
        
        $this->input = $this->app->input;
        
        $this->option = $this->input->get('option');

        $this->cparams = ComponentHelper::getParams($this->option);

        $this->today = Factory::getDate();
        $this->date_sql = $this->today->toSql();
		$this->date_unix = $this->today->toUnix();
		$this->date_lc3 = $this->today->format(Text::_('DATE_FORMAT_LC3'));

        $this->juser = $this->app->getIdentity();
        $this->user_levels = $this->juser->getAuthorisedViewLevels();

        $this->url = Uri::getInstance()->toString();

		$this->post = $this->input->post->getArray();

		$this->get = $this->input->get->getArray();
        
        $this->set_sortings_array();
    }
    
    public function getFilterForm($data = [], $loadData = true)
    {
        $form = parent::getFilterForm($data, $loadData);
        
        // Search
        $element = '<field name="search" type="text" inputmode="search" label="COM_TF_FILTER_SEARCH_LABEL" hint="JSEARCH_FILTER" />';
        $form = $this->add_field($form, $element, 'default', 'filter');
        
        // Filters
        foreach ($this->filters as $k => $v)
        {
            switch ($k)
            {
                case 'published' :
                    $element = $this->filter_published_field();
		            $form = $this->add_field($form, $element, 'default', 'filter');
		            break;
		            
		        case 'access' :
		            $element = $this->filter_access_field();
                    $form = $this->add_field($form, $element, 'default', 'filter');
                    break;
                    
                case 'note' :
                    $element = $this->filter_note_field($this->table_name);
                    $form = $this->add_field($form, $element, 'default', 'filter');
                    break;
                    
                case 'language' :
                    $element = $this->filter_language_field();
			        $form = $this->add_field($form, $element, 'default', 'filter');
			        break;
            }
        }
        
        // Ordering field
        $element = $this->filter_ordering_field($this->orderCol);
        $form = $this->add_field($form, $element, 'default', 'list');
        
        $ordering = $form->getField('fullordering', 'list');
        foreach ($this->sortings as $k => $v)
        {
            $ordering->addOption($k, array('value' => $v));
        }
        
        // Limit field
        $element = $this->filter_limit_field();
        $form = $this->add_field($form, $element, 'default', 'list');
        
        $data = $this->loadFormData();

        $form->bind($data);
        
        return $form;
    }
    
  	// Build an SQL query to load the list data
    protected function getListQuery()
    {
        $char = 'a';
        if (empty($this->select_fields))
        {
            $this->select_fields = array('a.*');
        }
        
      	$db = $this->getDatabase();
        
        $query = $db->getQuery(true);
      	
        $user = $this->getCurrentUser();
        
        $query->select($this->select_fields)
            ->from($db->quoteName('#__' . $this->table_name, $char));

      	if (!empty($this->left_joins))
        {
        	foreach ($this->left_joins as $join)
            {
                $char++;
                $query->join('LEFT', $db->quoteName('#__' . $join['table'], $char), $db->quoteName($join['on1']) . ' = ' . $db->quoteName($join['on2']));
            }  
        }
      
      	if (!empty($this->inner_joins))
        {
        	foreach ($this->inner_joins as $join)
            {
                $char++;
                $query->join('INNER', $db->quoteName('#__' . $join['table'], $char), $db->quoteName($join['on1']) . ' = ' . $db->quoteName($join['on2']));
            }  
        }

        // Add the list ordering clause
        $orderCol = $this->state->get('list.ordering', $this->orderCol);
        $orderDirn = $this->state->get('list.direction', $this->orderDirn);
        
        $query->order($db->escape($orderCol) . ' ' . $db->escape($orderDirn));

        // Join over users
        if (\array_key_exists('created_by', $this->table_columns))
        {
            $query->select(array($db->quoteName('ua.name', 'author_name'), $db->quoteName('ua.email', 'author_email')));
            $query->join('LEFT', $db->quoteName('#__users', 'ua'), $db->quoteName('ua.id') . ' = ' . $db->quoteName('a.created_by'));
        }

        // Join over access
        if (\array_key_exists('access', $this->table_columns))
        {
            $query->select(array($db->quoteName('ag.title', 'access_level')));
            $query->join('LEFT', $db->quoteName('#__viewlevels', 'ag'), $db->quoteName('ag.id') . ' = ' . $db->quoteName('a.access'));
        }

        // Join over languages
        if (Associations::isEnabled() && $this->is_ml)
        {
            $query->select(array($db->quoteName('l.title', 'language_title'), $db->quoteName('l.image', 'language_image')));
            $query->join('LEFT', $db->quoteName('#__languages', 'l'), $db->quoteName('l.lang_code') . ' = ' . $db->quoteName('a.language'));
        }
        
        // Join over associations
		if (Associations::isEnabled() && $this->is_ml)
		{
			$subQuery = $db->getQuery(true)
				->select('COUNT(' . $db->quoteName('asso1.id') . ') > 1')
				->from($db->quoteName('#__associations', 'asso1'))
				->join('INNER', $db->quoteName('#__associations', 'asso2'), $db->quoteName('asso1.key') . ' = ' . $db->quoteName('asso2.key'))
				->where(array($db->quoteName('asso1.id') . ' = ' . $db->quoteName('a.id'), $db->quoteName('asso1.context') . ' = ' . $db->quote('com_tfcontent.item'))
			);

			$query->select('(' . $subQuery . ') AS ' . $db->quoteName('association'));
		}

        // Where Conditions
        foreach ($this->where as $condition)
        {
            if (\is_array($condition))
            {
                $query->Where($db->quoteName($condition[0]) . ' ' . $condition[1] . ' ' . $db->quote($condition[2]));
            }
            else
            {
                $query->Where($condition);
            }
        }
        
      	// Add filters
      	$filters = $this->filters;
      	
        // Filter by search
        $search = $this->getState('filter.search');
        if (!empty($search))
        {
          	$default_search = true;
          	foreach ($this->search_fields as $search_field => $db_field)
            {
            	if (stripos($search, $search_field . ':') === 0)
            	{
                	$search = substr($search, strlen($search_field) + 1);
                  	if ($search_field == 'id')
                    {
                    	$query->where($db->quoteName($db_field) . ' = :search')
                    	    ->bind(':search', $search, ParameterType::INTEGER);
                    }
                	else
                    {
                    	$search = '%' . str_replace(' ', '%', trim($search)) . '%';
              			$query->where($db->quoteName($db_field) . ' LIKE :search')
                            ->bind(':search', $search);
                    }
                  	
                  	$default_search = false;
                  	break;
            	}
            }
          	if ($default_search)
            {
              	$search = '%' . str_replace(' ', '%', trim($search)) . '%';
              	$query->where($db->quoteName($this->search) . ' LIKE :search')
                    	->bind(':search', $search);
            }
        }
        
        // Filter by access level
		if (array_key_exists('access', $filters))
		{
		    $access = $this->getState('filter.access');
		    if (is_numeric($access))
		    {
		        $access = (int) $access;
              	$query->where($db->quoteName('a.access') . ' = :access')
				    ->bind(':access', $access, ParameterType::INTEGER);
		    }
		    elseif (\is_array($access))
		    {
    			$access = ArrayHelper::toInteger($access);
    			$query->whereIn($db->quoteName('a.access'), $access);
		    }
          	unset($filters['access']);
		}
		
		// Filter by published state
		if (array_key_exists('published', $filters))
		{
		    $published = (string) $this->getState('filter.published');
    		if ($published !== '*')
    		{	
              	if (is_numeric($published))
    		    {
                  	$state = (int) $published;
                  	$query->where($db->quoteName('a.published') . ' = :published')
                      	->bind(':published', $state, ParameterType::INTEGER);
    		    }
    		    else
    		    {
    		        $query->whereIn($db->quoteName('a.published'), array(0, 1));
    		    }
    		}
          	unset($filters['published']);
		}
		
        // Other Filters
        foreach ($filters as $k => $v)
        {
          	$value = $this->getState('filter.' . $k);
          	if ($value != '')
          	{
            	if (\is_array($value))
            	{
              		// To Do: Array may contain integers or strings
                  	$value = ArrayHelper::toInteger($value);
              		$query->whereIn($db->quoteName($v), $value);
            	}
           		else
            	{
              		$query->where($db->quoteName($v) . ' = ' . $db->quote($value));
            	}
            }
        }

        // Date Range Filters
        foreach ($this->datefilters as $k => $v)
        {
            $range = $this->getState('filter.' . $k);
            if ($range)
            {
                $dates = $this->build_date_range($range);
                if ($dates['start'])
                {
                    $query->where($db->quoteName($v) . ' > ' . $db->quote($dates['start']));
                }
                if ($dates['end']) // Assume start to be today
                {
                    $query->where($db->quoteName($v) . ' < ' . $db->quote($dates['end']));
                }
                if ($dates['start'] === false && $dates['end'] === false)
                {
                    $query->where($db->quoteName($v) . ' IS NULL');
                }
            }
        }
      	
      	if (Factory::getConfig()->get('debug'))
        {
        	$this->get_message($query->dump(), 'info');
        }

        return $query;
    }
    
    protected function populateState($ordering = null, $direction = null)
	{
        // Called automatially on the first call to the getState() method (called by getItems())
        // The getState() is defined in StateBehaviorTrait used by BaseModel
        
        // list.direction, list.ordering, list.limit, list.start
        // filter.search, filter.published, filter.note, etc.

        $app = Factory::getApplication();
        
		// Adjust the context to support modal layouts.
		if ($layout = $app->input->get('layout'))
		{
			$this->context .= '.' . $layout;
		}

		// Adjust the context to support forced languages.
		$forcedLanguage = $app->input->get('forcedLanguage', '', 'CMD');
		if ($forcedLanguage)
		{
			$this->context .= '.' . $forcedLanguage;
		}
        
		parent::populateState($ordering, $direction);
        
		// If there is a forced language, then define that filter for the query where clause
		if (!empty($forcedLanguage))
		{
			$this->setState('filter.language', $forcedLanguage);
		}
	}
    
    // Count total items in $table where $column is $value
    public function count_items($table, $column, $value)
    {
        $db = Factory::getDbo();
		$query = $db->getQuery(true);
		
		$query->select('COUNT(*)')
		    ->from($db->quoteName('#__' . $table))
		    ->where($db->quoteName($column) . ' = ' . $db->quote($value));
		    
	    $db->setQuery($query);
	    
        $total = $db->loadResult();
        
        return $total;
    }
    
    // Add field to fieldset in the form
    public function add_field($form, $element, $fieldset = 'default', $group = null, $replace = true)
    {
        $xml = new \SimpleXMLElement($element);
        
      	if ($form)
        {
        	$form->setField($xml, $group, $fieldset, $replace);  
        }
        
        return $form;
    }
    
    public function set_sortings_array()
    {
        foreach ($this->sorting_fields as $field)
        {
            switch ($field)
            {
                case 'a.title' :
                    $this->sortings['JGLOBAL_TITLE_ASC'] = 'a.title ASC';
                    $this->sortings['JGLOBAL_TITLE_DESC'] = 'a.title DESC';
                    break;
                
                case 'a.published' :
                    $this->sortings['JSTATUS_ASC'] = 'a.published ASC';
                    $this->sortings['JSTATUS_DESC'] = 'a.published DESC';
                    break;
                    
                case 'a.id' :
                    $this->sortings['JGRID_HEADING_ID_ASC'] = 'a.id ASC';
                    $this->sortings['JGRID_HEADING_ID_DESC'] = 'a.id DESC';
                    break;

                case 'a.created' :
                    $this->sortings['COM_TF_ORDERING_CREATED_ASC'] = 'a.created ASC';
                    $this->sortings['COM_TF_ORDERING_CREATED_DESC'] = 'a.created DESC';
                    break;
                    
                case 'a.modified' :
                    $this->sortings['COM_TF_ORDERING_MODIFIED_ASC'] = 'a.modified ASC';
                    $this->sortings['COM_TF_ORDERING_MODIFIED_DESC'] = 'a.modified DESC';
                    break;
                    
                case 'a.hits' :
                    $this->sortings['JGLOBAL_HITS_ASC'] = 'a.hits ASC';
                    $this->sortings['JGLOBAL_HITS_DESC'] = 'a.hits DESC';
                    break;
                    
                case 'a.ordering' :
                    $this->sortings['JGRID_HEADING_ORDERING_ASC'] = 'a.ordering ASC';
                    $this->sortings['JGRID_HEADING_ORDERING_DESC'] = 'a.ordering DESC';
                    break;
                    
                case 'a.access' :
                    $this->sortings['JGRID_HEADING_ACCESS_ASC'] = 'a.access ASC';
                    $this->sortings['JGRID_HEADING_ACCESS_DESC'] = 'a.access DESC';
                    break;
                    
                case 'a.note' :
                    $this->sortings['COM_TF_ORDERING_NOTE_ASC'] = 'a.note ASC';
                    $this->sortings['COM_TF_ORDERING_NOTE_DESC'] = 'a.note DESC';
                    break;
                    
                case 'a.language' :
                    $this->sortings['JGRID_HEADING_LANGUAGE_ASC'] = 'a.language ASC';
                    $this->sortings['JGRID_HEADING_LANGUAGE_DESC'] = 'a.language DESC';
                    break;
                    
                default :
                    $field_lang = (strpos($field, '.') == true) ? substr($field, 2) : $field;
                    $this->sortings[strtoupper($this->option) . '_ORDERING_' . strtoupper($field_lang) . '_ASC'] = $field . ' ASC';
                    $this->sortings[strtoupper($this->option) . '_ORDERING_' . strtoupper($field_lang) . '_DESC'] = $field . ' DESC';
            }
        }
    }
    
    public function set_filters()
    {
        $defaults = array('published', 'access', 'note');
        
        // Key is the name of field in filter form; Value is column in db query
        foreach ($defaults as $default)
        {
            if (array_key_exists($default, $this->table_columns))
            {
                $this->filters[$default] = 'a.' . $default;
            }
        }
    }
    
    public function set_sorting_fields()
    {
        $defaults = array('id', 'title', 'published', 'created', 'modified', 'hits', 'ordering', 'access', 'note');
      	
        foreach ($defaults as $default)
        {
            if (array_key_exists($default, $this->table_columns))
            {
                $this->sorting_fields[] = 'a.' . $default;
            }
        }
    }
  
  	public function set_search_fields()
    {
        $defaults = array('id', 'description', 'note');
      	
        foreach ($defaults as $default)
        {
            if (array_key_exists($default, $this->table_columns))
            {
                $this->search_fields[$default] = 'a.' . $default;
            }
        }
    }

    private function build_date_range($range)
    {
        $start = new Date;
        $end = new Date;

        switch ($range) 
        {
            case 'past_week':
                $start->modify('-7 day');
                break;

            case 'past_1month':
                $start->modify('-1 month');
                break;

            case 'past_3month':
                $start->modify('-3 month');
                break;

            case 'past_6month':
                $start->modify('-6 month');
                break;

            case 'past_year':
                $start->modify('-1 year');
                break;

            case 'post_year':
                $start = false;
                $end->modify('-1 year');
                break;

            case 'next_week':
                $end->modify('+7 day');
                break;

            case 'next_1month':
                $end->modify('+1 month');
                break;

            case 'next_3month':
                $end->modify('+3 month');
                break;

            case 'next_6month':
                $end->modify('+6 month');
                break;

            case 'next_year':
                $end->modify('+1 year');
                break;

            case 'post_future_year':
                $end = false;
                $start->modify('+1 year');
                break;

            case 'today':
                // Ranges that need to align with local 'days' need special treatment.
                $app = Factory::getApplication();
                $offset = $app->get('offset');

                // Reset the start time to be the beginning of today, local time.
                $start = new Date('now', $offset);
                $start->setTime(0, 0, 0);

                // Now change the timezone back to UTC.
                $tz = new \DateTimeZone('GMT');
                $start->setTimezone($tz);
                $end = false;
                break;
            
            case 'never':
                $end = false;
                $start = false;
                break;
        }

        return ['end' => $end, 'start' => $start];
    }
}