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

393 lines
12 KiB
PHP

<?php
/**
* @author Tassos.gr <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\CMS\Layout\LayoutHelper;
use NRFramework\Conditions\ConditionsHelper;
use NRFramework\Extension;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Form\Form;
class ConditionBuilder
{
public static function pass($rules)
{
$rules = self::prepareRules($rules);
if (empty($rules))
{
return true;
}
return ConditionsHelper::getInstance()->passSets($rules);
}
/**
* Prepare rules object to run checks
*
* @return void
*/
public static function prepareRules($rules = [])
{
if (!is_array($rules))
{
return [];
}
$rules_ = [];
foreach ($rules as $key => $group)
{
if (isset($group['enabled']) AND !(bool) $group['enabled'])
{
continue;
}
// A group without rules, doesn't make sense.
if (!isset($group['rules']) OR (isset($group['rules']) AND empty($group['rules'])))
{
continue;
}
$validRules = [];
foreach ($group['rules'] as $rule)
{
// Make sure rule has a name.
if (!isset($rule['name']) OR (isset($rule['name']) AND empty($rule['name'])))
{
continue;
}
// Rule is invalid if both value and params properties are empty
if (!isset($rule['value']) && !isset($rule['params']))
{
continue;
}
// Skip disabled rules
if (isset($rule['enabled']) && !(bool) $rule['enabled'])
{
continue;
}
// We don't need this property.
unset($rule['enabled']);
// Prepare rule value if necessary
if (isset($rule['value']))
{
$rule['value'] = self::prepareTFRepeaterValue($rule['value']);
}
// Verify operator
if (!isset($rule['operator']) OR (isset($rule['operator']) && empty($rule['operator'])))
{
$rule['operator'] = isset($rule['params']['operator']) ? $rule['params']['operator'] : '';
}
$validRules[] = $rule;
}
if (count($validRules) > 0)
{
$group['rules'] = $validRules;
if (!isset($group['matching_method']) OR (isset($group['matching_method']) AND empty($group['matching_method'])))
{
$group['matching_method'] = 'all';
}
unset($group['enabled']);
$rules_[] = $group;
}
}
return $rules_;
}
/**
* Parse the value of the TF Repeater Input field.
*
* @param array $selection
*
* @return mixed
*/
public static function prepareTFRepeaterValue($selection)
{
// Only proceed when we have an array of arrays selection.
if (!is_array($selection))
{
return $selection;
}
$first = array_values($selection)[0];
if (!is_array($first))
{
return $selection;
}
if (!isset($first['value']))
{
return $selection;
}
$new_selection = [];
foreach ($selection as $value)
{
/**
* We expect a `value` key for TFInputRepeater fields or a key,value pair
* for plain arrays.
*/
if (!isset($value['value']))
{
/**
* If no value exists, it means that the passed $assignment->selection is a key,value pair array so we use the value
* as our returned selection.
*
* This happens when we pass a key,value pair array as $assignment->selection when we expect a TFInputRepeater value
* so we need to take this into consideration.
*/
$new_selection[] = $value;
continue;
}
// value must not be empty
if (is_scalar($value['value']) && empty(trim($value['value'])))
{
continue;
}
$new_selection[] = count($value) === 1 ? $value['value'] : $value;
}
return $new_selection;
}
/**
* Returns the TGeoIP plugin modal.
*
* @return string
*/
public static function getGeoModal()
{
// Do not proceed if the database is up-to-date
if (!\NRFramework\Extension::geoPluginNeedsUpdate())
{
return;
}
HTMLHelper::_('bootstrap.modal');
$modalName = 'tf-geodbchecker-modal';
// The TGeoIP Plugin URL
$url = Uri::base(true) . '/index.php?option=com_plugins&view=plugin&tmpl=component&layout=modal&extension_id=' . \NRFramework\Functions::getExtensionID('tgeoip', 'system');
$options = [
'title' => Text::_('NR_EDIT'),
'url' => $url,
'height' => '400px',
'backdrop' => 'static',
'bodyHeight' => '70',
'modalWidth' => '70',
'footer' => '<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" data-dismiss="modal" aria-hidden="true">'
. Text::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>
<button type="button" class="btn btn-success" aria-hidden="true"
onclick="jQuery(\'#' . $modalName . ' iframe\').contents().find(\'#applyBtn\').click();">'
. Text::_('JAPPLY') . '</button>',
];
return HTMLHelper::_('bootstrap.renderModal', $modalName, $options);
}
/**
* Prepares the given rules list.
*
* @param array $list
*
* @return array
*/
public static function prepareXmlRulesList($list)
{
if (is_array($list))
{
$list = implode(',', array_map('trim', $list));
}
else if (is_string($list))
{
$list = str_replace(' ', '', $list);
}
return $list;
}
/**
* Adds a new condition item or group.
*
* @param string $controlGroup The name of the input used to store the data.
* @param string $groupKey The group index ID.
* @param string $conditionKey The added condition item index ID.
* @param array $condition The condition name we are adding.
* @param string $include_rules The list of included conditions that override the available conditions.
* @param string $exclude_rules The list of excluded conditions that override the available conditions.
* @param bool $exclude_rules_pro Whether the excluded rules should appear as Pro missing features.
*
* @return string
*/
public static function add($controlGroup, $groupKey, $conditionKey, $condition = null, $include_rules = [], $exclude_rules = [], $exclude_rules_pro = false)
{
$controlGroup_ = $controlGroup . "[$groupKey][rules][$conditionKey]"; // @Todo - rename input namespace to 'conditions'
$form = self::getForm('conditionbuilder/base.xml', $controlGroup_, $condition);
$form->setFieldAttribute('name', 'include_rules', is_array($include_rules) ? implode(',', $include_rules) : $include_rules);
$form->setFieldAttribute('name', 'exclude_rules', is_array($exclude_rules) ? implode(',', $exclude_rules) : $exclude_rules);
$form->setFieldAttribute('name', 'exclude_rules_pro', $exclude_rules_pro);
$options = [
'name' => $controlGroup_,
'enabled' => !isset($condition['enabled']) ? true : (string) $condition['enabled'] == '1',
'toolbar' => $form,
'groupKey' => $groupKey,
'conditionKey' => $conditionKey,
'options' => ''
];
if (isset($condition['name']))
{
$optionsHTML = self::renderOptions($condition['name'], $controlGroup_, $condition);
$options['condition_name'] = $condition['name'];
$options['options'] = $optionsHTML;
}
return self::getLayout('conditionbuilder_row', $options);
}
/**
* Render condition item settings.
*
* @param string $name The name of the condition item.
* @param string $controlGroup The name of the input used to store the data.
* @param object $formData The data that will be bound to the form.
*
* @return string
*/
public static function renderOptions($name, $controlGroup = null, $formData = null)
{
if (!$form = self::getForm('conditions/' . strtolower(str_replace('\\', '/', $name)) . '.xml', $controlGroup, $formData))
{
return;
}
$form->setFieldAttribute('note', 'ruleName', $name);
return $form->renderFieldset('general');
}
/**
* Handles loading condition builder given a payload.
*
* @param array $payload
*
* @return string
*/
public static function initLoad($payload = [])
{
if (!$payload)
{
return;
}
if (!isset($payload['data']) &&
!isset($payload['name']))
{
return;
}
if (!$data = json_decode($payload['data']))
{
return;
}
// transform object to assosiative array
$data = json_decode(json_encode($data), true);
// html of condition builder
$html = '';
$include_rules = isset($payload['include_rules']) ? $payload['include_rules'] : [];
$exclude_rules = isset($payload['exclude_rules']) ? $payload['exclude_rules'] : [];
$exclude_rules_pro = isset($payload['exclude_rules_pro']) ? $payload['exclude_rules_pro'] : false;
foreach ($data as $groupKey => $groupConditions)
{
$payload = [
'name' => $payload['name'],
'groupKey' => $groupKey,
'groupConditions' => $groupConditions,
'include_rules' => $include_rules,
'exclude_rules' => $exclude_rules,
'exclude_rules_pro' => $exclude_rules_pro
];
$html .= self::getLayout('conditionbuilder_group', $payload);
}
return $html;
}
/**
* Render a layout given its name and payload.
*
* @param string $name
* @param array $payload
*
* @return string
*/
public static function getLayout($name, $payload)
{
return LayoutHelper::render($name, $payload, JPATH_PLUGINS . '/system/nrframework/layouts');
}
/**
* Returns the form by binding given data.
*
* @param string $name
* @param string $controlGroup
* @param array $data
*
* @return object
*/
private static function getForm($name, $controlGroup, $data = null)
{
if (!file_exists(JPATH_PLUGINS . '/system/nrframework/xml/' . $name))
{
return;
}
$form = new Form('cb', ['control' => $controlGroup]);
$form->addFieldPath(JPATH_PLUGINS . '/system/nrframework/fields');
$form->loadFile(JPATH_PLUGINS . '/system/nrframework/xml/' . $name);
if (!is_null($data))
{
$form->bind($data);
}
return $form;
}
}