Files
conservatorio-tomadini/plugins/system/nrframework/NRFramework/Conditions/Condition.php
2024-12-31 11:07:09 +01:00

455 lines
9.5 KiB
PHP

<?php
/**
* @author Tassos Marinos <info@tassos.gr>
* @link https://www.tassos.gr
* @copyright Copyright © 2024 Tassos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
namespace NRFramework\Conditions;
defined('_JEXEC') or die;
use Joomla\Registry\Registry;
use Joomla\String\StringHelper;
use Joomla\CMS\Language\Text;
/**
* Assignment Class
*/
class Condition
{
/**
* Application Object
*
* @var object
*/
protected $app;
/**
* Document Object
*
* @var object
*/
protected $doc;
/**
* Date Object
*
* @var object
*/
protected $date;
/**
* Database Object
*
* @var object
*/
protected $db;
/**
* User Object
*
* @var object
*/
protected $user;
/**
* Assignment Selection
*
* @var mixed
*/
protected $selection;
/**
* Assignment Parameters
*
* @var mixed
*/
protected $params;
/**
* Assignment State (Include|Exclude)
*
* @var string
*/
public $assignment;
/**
* Options
*
* @var object
*/
public $options;
/**
* Framework factory object
*
* @var object
*/
public $factory;
/**
* The default operator that will be used to compare haystack with needle.
*
* @var string
*/
protected $operator;
/**
* Class constructor
*
* @param array $options The rule options. Expected properties: selection, value, params
* @param object $factory The framework's factory class.
*/
public function __construct($options = null, $factory = null)
{
$this->factory = is_null($factory) ? new \NRFramework\Factory() : $factory;
// Set General Joomla Objects
$this->db = $this->factory->getDbo();
$this->app = $this->factory->getApplication();
$this->doc = $this->factory->getDocument();
$this->user = $this->factory->getUser();
$this->options = new Registry($options);
$this->setParams($this->options->get('params'));
$this->setOperator($this->options->get('operator', 'includesSome'));
// For performance reasons we might move this inside the pass() method
$this->setSelection($this->options->get('selection', ''));
}
/**
* Set the rule's user selected value
*
* @param mixed $selection
* @return object
*/
public function setSelection($selection)
{
$this->selection = $selection;
if (method_exists($this, 'prepareSelection'))
{
$this->selection = $this->prepareSelection();
}
return $this;
}
/**
* Undocumented function
*
* @return void
*/
public function getSelection()
{
return $this->selection;
}
/**
* Set the operator that will be used for the comparison
*
* @param string $operator
* @return object
*/
public function setOperator($operator)
{
$this->operator = $operator;
return $this;
}
/**
* Set the rule's parameters
*
* @param array $params
*/
public function setParams($params)
{
$this->params = new Registry($params);
}
public function getParams()
{
return $this->params;
}
/**
* Checks the validitity of two values based on the given operator.
*
* Consider converting this method as a Trait.
*
* @param mixed $value
* @param mixed $selection
* @param string $operator
* @param array $options ignoreCase: true,false
*
* @return bool
*/
public function passByOperator($value = null, $selection = null, $operator = null, $options = null)
{
$value = is_null($value) ? $this->value() : $value;
if (!is_null($selection))
{
$this->setSelection($selection);
}
$selection = $this->getSelection();
$options = new Registry($options);
$ignoreCase = $options->get('ignoreCase', true);
if (is_object($value))
{
$value = (array) $value;
}
if (is_object($selection))
{
$selection = (array) $selection;
}
if ($ignoreCase)
{
if (is_string($value))
{
$value = strtolower($value);
}
if (is_string($selection))
{
$selection = strtolower($selection);
}
if (is_array($value))
{
$value = array_map('strtolower', $value);
}
if (is_array($selection))
{
$selection = array_map(function($str)
{
return is_null($str) ? '' : strtolower($str);
}, $selection);
}
}
$operator = (is_null($operator) OR empty($operator)) ? $this->operator : $operator;
$pass = false;
switch ($operator)
{
case 'exists':
$pass = !is_null($value);
break;
// Determines whether haystack is empty. Accepts: array, string
case 'empty':
if (is_array($value))
{
$pass = empty($value);
}
if (is_string($value))
{
$pass = $value == '' || trim($value) == '';
}
if (is_bool($value))
{
$pass = !$value;
}
break;
case 'equals':
if (is_array($selection) || is_array($value))
{
$pass = $this->passByOperator($value, $selection, 'includesSome', $options);
}
else
{
$pass = $value == $selection;
}
break;
case 'contains':
if (is_string($value) && is_string($selection))
{
$pass = strlen($selection) > 0 && strpos($value, $selection) !== false;
}
break;
// Determine whether haystack is less than needle.
case 'less_than':
case 'lowerthan':
case 'lt':
$pass = $value < $selection;
break;
// Determine whether haystack is less than or equal to needle.
case 'less_than_or_equal_to':
case 'lowerthanequal':
case 'lte':
$pass = $value <= $selection;
break;
// Determine whether haystack is greater than needle.
case 'greater_than':
case 'greaterthan':
case 'gt':
$pass = $value > $selection;
break;
// Determine whether haystack is greater than or equal to needle.
case 'greater_than_or_equal_to':
case 'greterthanequal':
case 'gte':
$pass = $value >= $selection;
break;
// Determine whether haystack contains all elements in needle.
case 'includesAll':
case 'containsall':
$pass = count(array_intersect((array) $selection, (array) $value)) == count((array) $selection);
break;
// Determine whether haystack contains at least one element from needle.
case 'includesSome':
case 'containsany':
$pass = !empty(array_intersect((array) $value, (array) $selection));
break;
// Determine whether haystack contains at least one element from needle. Accepts; string, array.
case 'includes':
if (is_string($value) && $value != '' && is_string($selection) && $selection != '')
{
if (StringHelper::strpos($value, $selection) !== false)
{
$pass = true;
}
}
if (is_array($value) || is_array($selection))
{
$pass = $this->passByOperator($value, $selection, 'includesSome', $options);
}
break;
// Determine whether haystack starts with needle. Accepts: string
case 'starts_with':
$pass = StringHelper::substr($value, 0, StringHelper::strlen($selection)) === $selection;
break;
// Determine whether haystack ends with needle. Accepts: string
case 'ends_with':
$pass = StringHelper::substr($value, -StringHelper::strlen($selection)) === $selection;
break;
// Determine whether value is in given range
case 'range':
$value1 = isset($selection['value1']) ? (float) $selection['value1'] : false;
$value2 = isset($selection['value2']) ? (float) $selection['value2'] : false;
$pass = $value1 && $value2 ? (($value >= $value1) && ($value <= $value2)) : false;
break;
// Determine whether haystack equals to needle. Accepts any object.
default:
$pass = $value == $selection;
}
return $pass;
}
/**
* Base assignment check
*
* @return bool
*/
public function pass()
{
return $this->passByOperator();
}
/**
* Returns all parent rows
*
* This method doesn't belong here. Move it to Functions.php.
*
* @param integer $id Row primary key
* @param string $table Table name
* @param string $parent Parent column name
* @param string $child Child column name
*
* @return array Array with IDs
*/
public function getParentIds($id = 0, $table = 'menu', $parent = 'parent_id', $child = 'id')
{
if (!$id)
{
return [];
}
$cache = $this->factory->getCache();
$hash = md5('getParentIds_' . $id . '_' . $table . '_' . $parent . '_' . $child);
if ($cache->has($hash))
{
return $cache->get($hash);
}
$parent_ids = array();
while ($id)
{
$query = $this->db->getQuery(true)
->select('t.' . $parent)
->from('#__' . $table . ' as t')
->where('t.' . $child . ' = ' . (int) $id);
$this->db->setQuery($query);
$id = $this->db->loadResult();
// Break if no parent is found or parent already found before for some reason
if (!$id || in_array($id, $parent_ids))
{
break;
}
$parent_ids[] = $id;
}
return $cache->set($hash, $parent_ids);
}
/**
* A one-line text that describes the current value detected by the rule. Eg: The current time is %s.
*
* @return string
*/
public function getValueHint()
{
$value = $this->value();
// If the rule returns an array, use the 1st one.
$value = is_array($value) ? $value[0] : $value;
return Text::sprintf('NR_DISPLAY_CONDITIONS_HINT_' . strtoupper($this->getName()), ucfirst(strtolower($value)));
}
/**
* Return the rule name
*
* @return string
*/
protected function getName()
{
$classParts = explode('\\', get_called_class());
return array_pop($classParts);
}
}