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/category.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\Component\Categories\Administrator\Helper\CategoriesHelper;

require_once('base/base.php');
require_once('base/traitnestable.php');

/**
 * FLEXIcontent Component Category Model
 *
 */
class FlexicontentModelCategory extends FCModelAdmin
{

	use FCModelTraitNestableRecord;

	/**
	 * Record name, (parent class property), this is used for: naming session data, XML file of class, etc
	 *
	 * @var string
	 */
	protected $name = 'category';

	/**
	 * Record database table
	 *
	 * @var string
	 */
	var $records_dbtbl = 'categories';

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

	/**
	 * Column names
	 */
	var $state_col   = 'published';
	var $name_col    = 'title';
	var $parent_col  = 'parent_id';

	/**
	 * Record primary key
	 *
	 * @var int
	 */
	var $_id = null;

	/**
	 * Record data
	 *
	 * @var object
	 */
	var $_record = null;

	/**
	 * Events context to use during model FORM events and diplay PREPARE events triggering
	 *
	 * @var object
	 */
	var $events_context = 'com_content.category';

	/**
	 * Record's type alias string
	 *
	 * @var        string
	 */
	var $type_alias = 'com_content.category';

	/**
	 * Flag to indicate adding new records with next available ordering (at the end),
	 * this is ignored if this record DB model does not have 'ordering'
	 *
	 * @var boolean
	 */
	var $useLastOrdering = false;

	/**
	 * Plugin group used to trigger events
	 *
	 * @var boolean
	 */
	var $plugins_group = 'content';

	/**
	 * Records real extension
	 *
	 * @var string
	 */
	var $extension_proxy = 'com_content';

	/**
	 * Context to use for registering (language) associations
	 *
	 * @var string
	 */
	var $associations_context = 'com_categories.item';


	/**
	 * Groups of Fields that can be partially present in the form
	 */
	var $mergeableGroups = array('params');

	/**
	 * Various record specific properties
	 *
	 */

	// Inherited parameters
	var $_inherited_params = null;

	/**
	 * List filters that are always applied
	 */
	var $hard_filters = array('a.extension' => FLEXI_CAT_EXTENSION);

	/**
	 * Constructor
	 *
	 * @since 3.3.0
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);
	}


	/**
	 * Legacy method to get the record
	 *
	 * @return	object
	 *
	 * @since	1.0
	 */
	public function getCategory($pk = null)
	{
		return parent::getRecord($pk);
	}


	/**
	 * Method to initialise the record data
	 *
	 * @param   object      $record    The record being initialized
	 * @param   boolean     $initOnly  If true then only a new record will be initialized without running the _afterLoad() method
	 *
	 * @return	boolean	True on success
	 *
	 * @since	1.5
	 */
	protected function _initRecord(&$record = null, $initOnly = false)
	{
		parent::_initRecord($record, $initOnly);

		// Set some new record specific properties, note most properties already have proper values
		// Either the DB default values (set by getTable() method) or the values set by _afterLoad() method
		$record->id							= 0;
		$record->parent_id			= 0;
		$record->title					= null;
		$record->name						= null;  //$this->getName() . ($this->_getLastId() + 1);
		$record->alias					= null;
		$record->description		= null;
		$record->extension			= FLEXI_CAT_EXTENSION;
		$record->image_position	= 'left';
		$record->published			= 1;
		$record->params					= null;
		$record->editor					= null;
		$record->ordering				= 0;
		$record->access					= 1;
		$record->count					= 0;
		$record->checked_out		= 0;
		$record->checked_out_time	= '';

		$this->_record = $record;

		return true;
	}


	/**
	 * Method to get a table object, load it if necessary.
	 *
	 * @param   string  $type    The table name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable  A JTable object
	 *
	 * @since   3.2.0
	 */
	public function getTable($type = 'Category', $prefix = null, $config = array())
	{
		$prefix = $prefix !== null
			? $prefix
			: (FLEXI_J40GE ? 'JTable' : 'CategoriesTable');

		if (!FLEXI_J40GE)
		{
			JTable::addIncludePath(JPATH_ADMINISTRATOR.DS.'components'.DS.'com_categories'.DS.'tables');
		}

		return parent::getTable($type, $prefix, $config);
	}


	/**
	 * Method rebuild the entire nested set tree.
	 *
	 * @return  boolean  False on failure or error, true otherwise.
	 *
	 * @since   3.2.0
	 */
	public function rebuild()
	{
		// Get an instance of the table object.
		$table = $this->getTable();

		if (!$table->rebuild())
		{
			$this->setError($table->getError());

			return false;
		}

		// Clear the cache
		$this->cleanCache(null, 0);
		$this->cleanCache(null, 1);

		return true;
	}


	/**
	 * Method to load inherited parameters
	 *
	 * @access	private
	 * @return	void
	 * @since	1.5
	 */
	public function getInheritedParams($force=false)
	{
		if ($this->_inherited_params !== null && !$force)
		{
			return $this->_inherited_params;
		}

		$id = (int) $this->_id;

		$app = JFactory::getApplication();

		// a. Clone component parameters ... we will use these as parameters base for merging
		$compParams = clone(JComponentHelper::getComponent('com_flexicontent')->params);

		// b. Retrieve category parameters and create parameter object
		if ($id)
		{
			$query = $this->_db->getQuery(true)
				->select('params')
				->from('#__categories')
				->where('id = ' . (int) $id);
			$catParams = $this->_db->setQuery($query)->loadResult();
			$catParams = new JRegistry($catParams);
		}
		else
		{
			$catParams = new JRegistry();
		}


		// c. Retrieve inherited parameter and create parameter objects
		global $globalcats;
		$heritage_stack = array();
		$inheritcid = $catParams->get('inheritcid', '');
		$inheritcid_comp = $compParams->get('inheritcid', -1);
		$inherit_parent = $inheritcid==='-1' || ($inheritcid==='' && $inheritcid_comp);

		// CASE A: inheriting from parent category tree
		if ($id && $inherit_parent && !empty($globalcats[$id]->ancestorsonly))
		{
			$query = $this->_db->getQuery(true)
				->select('title, id, params')
				->from('#__categories')
				->where('id IN ( ' . $globalcats[$id]->ancestorsonly . ')')
				->order('level DESC');
				//>order('FIELD(id, ' . $globalcats[$id]->ancestorsonly . ' DESC)';
			$catdata = $this->_db->setQuery($query)->loadObjectList('id');

			if (!empty($catdata))
			{
				foreach ($catdata as $parentcat)
				{
					$parentcat->params = new JRegistry($parentcat->params);
					array_push($heritage_stack, $parentcat);
					$inheritcid = $parentcat->params->get('inheritcid', '');
					$inherit_parent = $inheritcid==='-1' || ($inheritcid==='' && $inheritcid_comp);

					// Stop inheriting from further parent categories
					if (!$inherit_parent)
					{
						break;
					}
				}
			}
		}

		// CASE B: inheriting from specific category
		elseif ($id && $inheritcid > 0 && !empty($globalcats[$inheritcid]))
		{
			$query = $this->_db->getQuery(true)
				->select('title, params')
				->from('#__categories')
				->where('id = ' . (int) $inheritcid);
			$catdata = $this->_db->setQuery($query)->loadObject();

			if ($catdata)
			{
				$catdata->params = new JRegistry($catdata->params);
				array_push($heritage_stack, $catdata);
			}
		}


		/**
		 * Start merging of parameters, OVERRIDE ORDER: layout(template-manager)/component/ancestors-cats/category
		 */

		// -1. layout parameters will be placed on top at end of this code ...

		// 0. Start from component parameters
		$params = new JRegistry();
		$params->merge($compParams);

		// 1. Merge category's inherited parameters (e.g. ancestor categories or specific category)
		while (!empty($heritage_stack))
		{
			$catdata = array_pop($heritage_stack);
			if ($catdata->params->get('orderbycustomfieldid') === '0')
			{
				$catdata->params->set('orderbycustomfieldid', '');
			}
			$params->merge($catdata->params);
		}

		// 2. Merge category parameters
		/**
		 * CURRENT CATEGORY PARAMETERS MUST BE SKIPED ! we only want the inherited parameters
		 */
		/*
		if ($catParams->get('orderbycustomfieldid') === '0')
		{
			$catParams->set('orderbycustomfieldid', '');
		}
		$params->merge($catParams);
		*/

		// 3. Retrieve and merge Global Layout's parameters (placing these at TOP allows proper heritage)
		$layoutParams = flexicontent_tmpl::getLayoutparams('category', $params->get('clayout'), '', $force);
		$layoutParams = new JRegistry($layoutParams);

		$this->_inherited_params = clone($layoutParams);
		$this->_inherited_params->merge($params);

		return $this->_inherited_params;
	}


	/**
	 * Method to get the parameters of another category
	 *
	 * @access	public
	 * @params	int			id of the category
	 * @return	string		ini string of params
	 * @since	1.5
	 */
	public function getParams($id)
	{
		$query = $this->_db->getQuery(true)
			->select('params')
			->from('#__categories')
			->where('id = ' . (int) $id);

		return $this->_db->setQuery($query)->loadResult();
	}


	/**
	 * Method to copy category parameters
	 *
	 * @param 	int 	$id of target
	 * @param 	string 	$params to copy
	 * @return 	boolean	true on success
	 *
	 * @since 1.5
	 */
	public function copyParams($id, $params)
	{
		$query 	= 'UPDATE #__categories'
			. ' SET params = ' . $this->_db->Quote($params)
			. ' WHERE id = ' . (int)$id
			;
		$this->_db->setQuery($query);
		$this->_db->execute();

		return true;
	}


	/**
	 * Method to get the row form.
	 *
	 * @param   array    $data      An optional array of data for the form to interogate.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  mixed  A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		$this->setState($this->getName().'.extension', 'com_content');
		$extension = $this->getState($this->getName().'.extension');

		$jinput = JFactory::getApplication()->input;

		// A workaround to get the extension and other data into the model for save requests.
		if (empty($extension) && isset($data['extension']))
		{
			$extension = $data['extension'];
			$parts = explode('.', $extension);

			$this->setState($this->getName().'.extension', $extension);
			$this->setState($this->getName().'.component', $parts[0]);
			$this->setState($this->getName().'.section', @$parts[1]);
		}
		$this->setState($this->getName().'.language', isset($data['language']) ? $data['language'] : null);

		// Get the form.
		$form = parent::getForm($data, $loadData);

		if (empty($form))
		{
			return false;
		}

		// Modify the form based on Edit State access controls.
		if (empty($data['extension']))
		{
			$data['extension'] = $extension;
		}

		// Force asset from request
		$categoryId = $jinput->get('id');
		$assetKey   = $categoryId ? $this->extension_proxy . '.category.' . $categoryId : $this->extension_proxy;

		if (!JFactory::getUser()->authorise('core.edit.state', $assetKey))
		{
			// Disable fields for display.
			$form->setFieldAttribute('ordering', 'disabled', 'true');
			$form->setFieldAttribute('published', 'disabled', 'true');

			// Disable fields while saving.
			// The controller has already verified this is a record you can edit.
			$form->setFieldAttribute('ordering', 'filter', 'unset');
			$form->setFieldAttribute('published', 'filter', 'unset');
		}

		return $form;
	}


	/**
	 * Method to get a record.
	 *
	 * @param	integer  $pk An optional id of the object to get, otherwise the id from the model state is used.
	 *
	 * @return	mixed 	Record data object on success, false on failure.
	 *
	 * @since	1.6
	 */
	public function getItem($pk = null)
	{
		$pk = $pk ? (int) $pk : $this->_id;
		$pk = $pk ? $pk : (int) $this->getState($this->getName().'.id');

		static $items = array();
		if ( $pk && isset($items[$pk]) ) return $items[$pk];

		// Instatiate the JTable
		$item = parent::getItem($pk);

		if ( $item )
		{
			// Prime required properties.
			if (empty($item->id))
			{
				$item->parent_id	= $this->getState($this->getName().'.parent_id');
				$item->extension	= $this->getState($this->getName().'.extension');
			}

			// Convert the metadata field to an array.
			$registry = new JRegistry($item->metadata);
			$item->metadata = $registry->toArray();

			// Convert the created and modified dates to local user time for display in the form.
			jimport('joomla.utilities.date');

			$site_zone = JFactory::getApplication()->getCfg('offset');
			$user_zone = JFactory::getUser()->getParam('timezone', $site_zone);
			$tz_string = $user_zone;
			$tz = new DateTimeZone( $tz_string );

			if (intval($item->created_time))
			{
				$date = new JDate($item->created_time);
				$date->setTimezone($tz);
				$item->created_time = $date->toSql(true);
			}
			else
			{
				$item->created_time = null;
			}

			if (intval($item->modified_time))
			{
				$date = new JDate($item->modified_time);
				$date->setTimezone($tz);
				$item->modified_time = $date->toSql(true);
			}
			else
			{
				$item->modified_time = null;
			}

			$this->_record = $item;

			$useAssocs = $this->useAssociations();
			if ($useAssocs)
			{
				if ($item->id != null)
				{
					$item->associations = FLEXI_J40GE
						? CategoriesHelper::getAssociations($item->id, $item->extension)
						: \CategoriesHelper::getAssociations($item->id, $item->extension);
					$item->associations = ArrayHelper::toInteger($item->associations);
				}
				else
				{
					$item->associations = array();
				}
			}
		}

		if ($pk) $items[$pk] = $item;
		return $item;
	}


	/**
	 * Method to preprocess the form.
	 *
	 * @param   JForm   $form   A JForm object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $plugins_group  The name of the plugin group to import and trigger
	 *
	 * @return  void
	 *
	 * @see     JFormField
	 * @since   1.6
	 * @throws  Exception if there is an error in the form event.
	 */
	protected function preprocessForm(JForm $form, $data, $plugins_group = null)
	{
		jimport('joomla.filesystem.path');

		$lang = JFactory::getLanguage();
		$component = $this->getState($this->getName().'.component', '');
		$section   = $this->getState($this->getName().'.section', '');
		$extension = JFactory::getApplication()->input->get('extension', null);

		// Get the component form if it exists
		$name = 'category' . ($section ? ('.' . $section) : '');

		// Try to find the component helper.
		$eName = str_replace('com_', '', $component);
		$path = JPath::clean(JPATH_ADMINISTRATOR . "/components/$component/helpers/category.php");

		if (file_exists($path))
		{
			$cName = ucfirst($eName) . ucfirst($section) . 'HelperCategory';

			JLoader::register($cName, $path);

			if (class_exists($cName) && is_callable(array($cName, 'onPrepareForm')))
			{
				$lang->load($component, JPATH_BASE, null, false, false)
					|| $lang->load($component, JPATH_BASE . '/components/' . $component, null, false, false)
					|| $lang->load($component, JPATH_BASE, $lang->getDefault(), false, false)
					|| $lang->load($component, JPATH_BASE . '/components/' . $component, $lang->getDefault(), false, false);
				call_user_func_array(array($cName, 'onPrepareForm'), array(&$form));

				// Check for an error.
				if ($form instanceof Exception)
				{
					$this->setError($form->getMessage());

					return false;
				}
			}
		}

		// Set the access control rules field component value.
		$form->setFieldAttribute('rules', 'component', $component);
		$form->setFieldAttribute('rules', 'section', $name);

		// Association category items
		if ($this->useAssociations())
		{
			$languages = JLanguageHelper::getContentLanguages(false, true, null, 'ordering', 'asc');
			$data_language = !empty($data->language) ? $data->language : $this->getState($this->getName().'.language');

			if (count($languages) > 1)
			{
				$addform = new SimpleXMLElement('<form />');
				$fields = $addform->addChild('fields');
				$fields->addAttribute('name', 'associations');
				$fieldset = $fields->addChild('fieldset');
				$fieldset->addAttribute('name', 'item_associations');
				$fieldset->addAttribute('description', 'COM_CATEGORIES_ITEM_ASSOCIATIONS_FIELDSET_DESC');

				foreach ($languages as $language)
				{
					if ($language->lang_code == $data_language) continue;
					$field = $fieldset->addChild('field');
					$field->addAttribute('name', $language->lang_code);
					$field->addAttribute('type', 'fccategory');
					$field->addAttribute('language', $language->lang_code);
					$field->addAttribute('label', $language->title);
					$field->addAttribute('class', 'label');
					$field->addAttribute('translate_label', 'false');
					$field->addAttribute('extension', $extension);
					$field->addAttribute('edit', 'true');
					$field->addAttribute('clear', 'true');
					$field->addAttribute('filter', 'INT');  // also enforced later, but better to have it here too
				}

				$form->load($addform, false);
			}
		}

		// Trigger the default form events.
		$plugins_group = $plugins_group ?: $this->plugins_group;
		parent::preprocessForm($form, $data, $plugins_group);
	}


	/**
	 * Method to change the title & alias.
	 *
	 * @param   integer  $parent_id  If applicable, the id of the parent (e.g. assigned category)
	 * @param   string   $alias      The alias / name.
	 * @param   string   $title      The title / label.
	 *
	 * @return  array    Contains the modified title and alias / name.
	 *
	 * @since   1.7
	 */
	protected function generateNewTitle($parent_id, $alias, $title)
	{
		return parent::generateNewTitle($parent_id, $alias, $title);
	}


	/**
	 * Method to check if the user can edit the record
	 *
	 * @return	boolean	True on success
	 *
	 * @since	3.2.0
	 */
	public function canEdit($record = null, $user = null)
	{
		$record  = $record ?: $this->_record;
		$user    = $user ?: JFactory::getUser();
		$asset   = $record && !$record->id ? $this->type_alias . '.' . $record->id : $this->option;
		$isOwner = $record && $user->id && $record->created_user_id == $user->id;

		$canDo    = $user->authorise('core.edit', $asset);
		$canDoOwn	= $user->authorise('core.edit.own', $asset) && $isOwner;

		return $canDo || $canDoOwn;
	}


	/**
	 * Method to check if the user can edit record 's state
	 *
	 * @return	boolean	True on success
	 *
	 * @since	3.2.0
	 */
	public function canEditState($record = null, $user = null)
	{
		$record  = $record ?: $this->_record;
		$user    = $user ?: JFactory::getUser();
		$asset   = $record && !$record->id ? $this->type_alias . '.' . $record->id : $this->option;
		$isOwner = $record && $user->id && $record->created_user_id == $user->id;

		$canDo    = $user->authorise('core.edit.state', $asset);
		$canDoOwn	= $user->authorise('core.edit.state.own', $asset) && $isOwner;

		return $canDo || $canDoOwn;
	}


	/**
	 * Method to check if the user can delete the record
	 *
	 * @return	boolean	True on success
	 *
	 * @since	3.2.0
	 */
	public function canDelete($record = null)
	{
		$record  = $record ?: $this->_record;
		$user    = JFactory::getUser();
		$asset   = $record && !$record->id ? $this->type_alias . '.' . $record->id : $this->option;
		$isOwner = $record && $user->id && $record->created_user_id == $user->id;

		$canDo    = $user->authorise('core.delete', $asset);
		$canDoOwn	= $user->authorise('core.delete.own', $asset) && $isOwner;

		return $canDo || $canDoOwn;
	}


	/**
	 * Method to do some record / data preprocessing before call JTable::bind()
	 *
	 * Note. Typically called inside this MODEL 's store()
	 *
	 * @param   object     $record   The record object
	 * @param   array      $data     The new data array
	 *
	 * @since	3.2.0
	 */
	protected function _prepareBind($record, & $data)
	{
		// Merge template fieldset this should include at least 'clayout' and optionally 'clayout_mobile' parameters
		if( !empty($data['templates']) )
		{
			$data['params'] = array_merge($data['params'], $data['templates']);
			unset($data['templates']);
		}

		// Merge other special parameters, e.g. 'inheritcid'
		if( !empty($data['special']) )
		{
			$data['params'] = array_merge($data['params'], $data['special']);
			unset($data['special']);
		}

		// Get RAW layout field values, validation will follow ...
		$raw_data = JFactory::getApplication()->input->post->get('jform', array(), 'array');
		$data['params']['layouts'] = !empty($raw_data['layouts']) ? $raw_data['layouts'] : null;


		// ***
		// *** Special handling of some FIELDSETs: e.g. 'attribs/params' and optionally for other fieldsets too, like: 'metadata'
		// *** By doing partial merging of these arrays we support having only a sub-set of them inside the form
		// *** we will use mergeAttributes() instead of bind(), thus fields that are not set will maintain their current DB values,
		// ***
		$mergeProperties = $this->mergeableGroups;
		$mergeOptions = array(
			'params_fset'  => 'params',
			'layout_type'  => 'category',
			'model_names'  => array($this->option => $this->getName(), 'com_categories' => 'category'),
			'cssprep_save' => false,
		);
		$this->mergeAttributes($record, $data, $mergeProperties, $mergeOptions);

		// Unset the above handled FIELDSETs from $data, since we selectively merged them above into the RECORD,
		// thus they will not overwrite the respective RECORD's properties during call of JTable::bind()
		foreach($mergeProperties as $prop)
		{
			unset($data[$prop]);
		}

		// Optionally copy parameters from another category
		$copycid = (int) $data['copycid'];

		if ($copycid)
		{
			unset($data['params']);
			$record->params = $this->getParams($copycid);
		}

		// Call parent class bind preparation
		parent::_prepareBind($record, $data);
	}


	/**
	 * Method to do some work after record has been stored
	 *
	 * Note. Typically called inside this MODEL 's store()
	 *
	 * @param   object     $record   The record object
	 * @param   array      $data     The new data array
	 *
	 * @since	3.2.0
	 */
	protected function _afterStore($record, & $data)
	{
		parent::_afterStore($record, $data);

		// Rebuild the path for the category:
		if (!$record->rebuildPath($record->id))
		{
			$this->setError($record->getError());
			return false;
		}

		// Rebuild the paths of the category's children:
		if (!$record->rebuild($record->id, $record->lft, $record->level, $record->path))
		{
			$this->setError($record->getError());
			return false;
		}

		// Restore extension property of the category to 'com_content'
		if ($record->id)
		{
			$query 	= 'UPDATE #__categories'
				. ' SET extension = "com_content" '
				. ' WHERE id = ' . (int)$record->id
				;
		}
	}


	/**
	 * Method to do some work after record has been loaded via JTable::load()
	 *
	 * Note. Typically called inside this MODEL 's store()
	 *
	 * @param	object   $record   The record object
	 *
	 * @since	3.2.0
	 */
	protected function _afterLoad($record)
	{
		parent::_afterLoad($record);
	}


	/**
	 * Custom clean the cache
	 *
	 * @param   string   $group      Clean cache only in the given group
	 * @param   integer  $client_id  Site Cache (0) / Admin Cache (1)
	 *
	 * @return  void
	 *
	 * @since   3.2.0
	 */
	protected function cleanCache($group = NULL, $client_id = 0)
	{
		if ($group)
		{
			parent::cleanCache($group, $client_id);
		}

		// An empty '$group' will clean '$this->option' which is the Component VIEW Cache, we will do a little more ...
		else
		{
			/**
			 * Note: null should be the same as $this->option ...
			 * Maybe add option not clean Component's VIEW cache it will be too aggressive ...
			 */
			if (1)
			{
				parent::cleanCache(null, $client_id);
				parent::cleanCache('com_content', $client_id);
			}

			parent::cleanCache('mod_articles_archive', $client_id);
			parent::cleanCache('mod_articles_categories', $client_id);
			parent::cleanCache('mod_articles_category', $client_id);
			parent::cleanCache('mod_articles_latest', $client_id);
			parent::cleanCache('mod_articles_news', $client_id);
			parent::cleanCache('mod_articles_popular', $client_id);

			parent::cleanCache('com_flexicontent_cats', $client_id);

			// Indicate to our system plugin that its category cache needs to be cleaned
			JFactory::getSession()->set('clear_cats_cache', 1, 'flexicontent');
		}
	}


	/**
	 * START OF MODEL SPECIFIC METHODS
	 */



	/**
	 * Method to get parameters of parent categories
	 *
	 * @param   integer  $pk  The category id
	 * @return	string   An array of JSON strings
	 *
	 * @since	3.3.0
	 */
	public function getParentParams($pk)
	{
		if (empty($pk))
		{
			return array();
		}

		global $globalcats;

		$query = 'SELECT id, params'
			. ' FROM #__categories'
			. ' WHERE id IN (' . $globalcats[$pk]->ancestors . ')'
			. ' ORDER BY level ASC'
		;
		return $this->_db->setQuery($query)->loadObjectList('id');
	}
}