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/review.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;

require_once('base/base.php');

/**
 * FLEXIcontent Component Review Model
 *
 */
class FlexicontentModelReview extends FCModelAdmin
{
	/**
	 * Record name, (parent class property), this is used for: naming session data, XML file of class, etc
	 *
	 * @var string
	 */
	protected $name = 'review';

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

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

	/**
	 * Column names
	 */
	var $state_col   = 'state';
	var $name_col    = 'title';
	var $parent_col  = null;//'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 = null;

	/**
	 * 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 = null;

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

	/**
	 * Use language associations
	 *
	 * @var string
	 */
	var $associations_context = false;

	/**
	 * Various record specific properties
	 *
	 */

	// Voting - reviews fields per item type
	var $fields = array();

	// Voting - reviews field for item type 0 (No per type configuration)
	var $field  = null;

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

		$this->canManage = FlexicontentHelperPerm::getPerm()->CanReviews;
		$this->canCreate = FlexicontentHelperPerm::getPerm()->CanCreateReviews;

		// Load field's language files
		JFactory::getLanguage()->load('plg_flexicontent_fields_core', JPATH_ADMINISTRATOR, 'en-GB', true);
		JFactory::getLanguage()->load('plg_flexicontent_fields_core', JPATH_ADMINISTRATOR, null, true);
	}


	/**
	 * Legacy method to get the record
	 *
	 * @return	object
	 *
	 * @since	1.0
	 */
	public function getReview($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->content_id			= $this->getState('content_id');
		$record->type						= $this->getState('review_type');
		$record->email					= $this->getState('email');
		$record->title					= '';
		$record->text						= '';
		$record->state					= 0;
		$record->checked_out		= 0;
		$record->checked_out_time	= '';

		$this->_record = $record;

		return true;
	}


	/**
	 * Legacy method to store the record, use save() instead
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.2.0
	 */
	public function store($data)
	{
		return parent::store($data);
	}


	/**
	 * 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)
	{
		$data = $data && is_array($data) ? (object) $data : $data;

		/**
		 * Do not allow changing some properties
		 */

		$isNew    = empty($this->_record->id);
		$isLogged = (boolean) JFactory::getUser()->id;
		
		$readonlyFields = array();
		$hiddenFields   = array();
		
		// Only allow email to guests to admins
		if ((!$isNew || $isLogged) && !$this->canManage)
		{
			$readonlyFields[]= 'email';
			$hiddenFields[]  = 'email';
		}

		if (!$this->canManage)
		{
			$readonlyFields = array_merge($readonlyFields,
				array(
					'state', 'approved', 'verified', 'useful_yes', 'useful_no',
					'id', 'type', 'average_rating', 'custom_ratings', 'user_id',
					'submit_date', 'update_date',
				)
			);
			$hiddenFields   = array_merge($hiddenFields,
				array(
					'state', 'approved', 'verified', 'useful_yes', 'useful_no',
					'id', 'type', 'average_rating', 'custom_ratings', 'user_id',
					'submit_date', 'update_date',
					'content_id',  // Form submitted but hidden
				)
			);
		}

		foreach($readonlyFields as $fieldname)
		{
			$form->setFieldAttribute($fieldname, 'readonly', 'true');
			$form->setFieldAttribute($fieldname, 'filter', 'unset');
		}

		foreach($hiddenFields as $fieldname)
		{
			$form->setFieldAttribute($fieldname, 'hidden', 'true');
		}

		// 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)
	{
		// Alter the title & alias
		$table = $this->getTable();

		while ($table->load(array('title' => $title)))
		{
			$title = StringHelper::increment($title);
		}

		return array($title, null);
	}


	/**
	 * 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)
	{
		if ($user)
		{
			throw new Exception(__FUNCTION__ . '(): Error model does not support checking ACL of specific user', 500);
		}

		$record  = $record ?: $this->_record;
		$user    = $user ?: JFactory::getUser();
		$app     = JFactory::getApplication();

		$isOwner = $record && $record->user_id == $user->id;
		$isSite  = $app->isClient('site');

		// Get per field's per type configuration if possible
		$item  = (object) array('type_id' => empty($record->item_type_id) ? 0 : $record->item_type_id);
		$field = $this->getVotingReviewsField($item, $setAsDefault = true);

		$allow_submit_review_by = (int) $field->parameters->get('allow_submit_review_by', 0);

		if ($isSite && !$record->id)
		{
			switch ($allow_submit_review_by)
			{
				case 0:
					// No new submissions are allowed
					$app->enqueueMessage('New review submission has been disabled', 'warning');
					return false;

				case 1:
					// Anyone (guest or logged) is allowed to submit
					return true;

				case 2:
					// Only Logged users are allowed to submit
					if (!$user->id)
					{
						$app->enqueueMessage('Please login / register before you can submit a new review', 'warning');
						return false;
					}

					return true;

				case 3:
					$aid_arr = $user->getAuthorisedViewLevels();
					$acclvl = (int) $field->parameters->get('review_submit_access', 1);
					$has_acclvl = in_array($acclvl, $aid_arr);

					if (!$has_acclvl)
					{
						$app->enqueueMessage('You do not have access level to submit a new review', 'warning');
						return false;
					}

					return true;

				default:
					$app->enqueueMessage('Unhandled parameter value for "allow_submit_review_by parameter" ' . $allow_submit_review_by, 'warning');
					return false;
			}
		}

		return !$record || !$record->id
			? $this->canCreate
			: (($this->canCreate && $isOwner) || $this->canManage);
	}


	/**
	 * 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)
	{
		if ($user)
		{
			throw new Exception(__FUNCTION__ . '(): Error model does not support checking ACL of specific user', 500);
		}

		$record  = $record ?: $this->_record;
		$user    = $user ?: JFactory::getUser();

		return $this->canManage;
	}


	/**
	 * 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();

		return $this->canManage;
	}


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


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


	/**
	 * START OF MODEL SPECIFIC METHODS
	 */


	/**
	 * Method to do extra validation on the data posted by a reviewer
	 *
	 * @param   array     $data  The (already JForm validated) record data
	 *
	 * @return  boolean   true on success, false on failure
	 *
	 * @since   3.3
	 */
	public function reviewerValidation($data)
	{
		$user = JFactory::getUser();
		$db   = JFactory::getDbo();

		$review_id   = $data['id'];
		$content_id  = $data['content_id'];
		$review_type = $data['type'];

		$errors = array();

		// Validate title, decode entities, and strip HTML
		$data['title'] = flexicontent_html::dataFilter($data['title'], $maxlength=255, 'STRING', 0);

		// Validate email
		$data['email'] = $user->id ? $user->email : flexicontent_html::dataFilter($data['email'], $maxlength=255, 'EMAIL', 0);

		// Validate text, decode entities and strip HTML
		$data['text'] = flexicontent_html::dataFilter($data['text'], $maxlength=10000, 'STRING', 0);


		/**
		 * Check for validation failures on posted data
		 */

		if (!$content_id)
		{
			$this->setError('Content being reviewed not given (content_id is zero)');
			return false;
		}

		if (!$data['email'])
		{
			$this->setError('Email is invalid or empty');
			return false;
		}

		if (!$user->id)
		{
			$query = 'SELECT id FROM #__users WHERE email = ' . $db->Quote($email);
			$reviewer = $db->setQuery($query)->loadObject();

			if ($reviewer)
			{
				$this->setError('Please login');
				return false;
			}
		}

		if (!$text)
		{
			$this->setError('Text is invalid or empty');
			return false;
		}

		if ($review_type !== 'item')
		{
			$this->setError('review_type <> item is not yet supported');
			return false;
		}

		// Return the further validated data
		return $data;
	}


	/**
	 * Method to toggle approved flag of a review
	 *
	 * @param		array			$cid          Array of record ids to set to a new state
	 * @param		string    $approved     The new state
	 *
	 * @return	boolean	True on success
	 *
	 * @since	3.3.0
	 */
	public function approved($cid = array(), $value = 0, $cleanCache = true)
	{
		$cid = (array) $cid;
		$cid = ArrayHelper::toInteger($cid);
		$affected = 0;

		if (count($cid))
		{
			$user     = JFactory::getUser();
			$cid_list = implode(',', $cid);

			$query = $this->_db->getQuery(true)
				->update('#__' . $this->records_dbtbl)
				->set('approved = ' . (int) $value)
				->where('id IN (' . $cid_list . ')')
				->where('(checked_out = 0 OR checked_out = ' . (int) $user->get('id') . ')');

			$this->_db->setQuery($query)->execute();

			// Get affected records, non records may have been locked by another user
			$affected = $this->_db->getAffectedRows();

			if ($cleanCache)
			{
				$this->cleanCache(null, 0);
				$this->cleanCache(null, 1);
			}
		}

		return $affected;
	}

	/**
	 * Method to get the voting - reviews field
	 *
	 * @return	Object	The voting - reviews field
	 *
	 * @since	3.4
	 */
	public function getVotingReviewsField($item = null, $setAsDefault = false)
	{
		if (empty($this->fields[$item ? $item->type_id : 0]))
		{
			$db    = JFactory::getDbo();
			$query = 'SELECT * FROM #__flexicontent_fields WHERE field_type = ' . $db->Quote('voting');
			$field = $db->setQuery($query)->loadObject();

			// Load field's configuration together with type-specific field customization
			FlexicontentFields::loadFieldConfig($field, $item);

			$this->fields[$item ? $item->type_id : 0] = $field;

			if ($setAsDefault)
			{
				$this->fields[0] = $field;
			}
		}

		return $this->fields[$item ? $item->type_id : 0];
	}
}