File: /home/oscasa/public_html/libraries/regularlabs/src/Conditions.php
<?php
/**
* @package Regular Labs Library
* @version 19.10.11711
*
* @author Peter van Westen <info@regularlabs.com>
* @link http://www.regularlabs.com
* @copyright Copyright © 2019 Regular Labs All Rights Reserved
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
*/
namespace RegularLabs\Library;
defined('_JEXEC') or die;
jimport('joomla.filesystem.file');
/**
* Class Conditions
* @package RegularLabs\Library
*/
class Conditions
{
static $installed_extensions = null;
static $params = null;
public static function pass($conditions, $matching_method = 'all', $article = null, $module = null)
{
if (empty($conditions))
{
return true;
}
$article_id = isset($article->id) ? $article->id : '';
$module_id = isset($module->id) ? $module->id : '';
$matching_method = in_array($matching_method, ['any', 'or']) ? 'any' : 'all';
$cache_id = 'pass_' . $article_id . '_' . $module_id . '_' . $matching_method . '_' . json_encode($conditions);
if (Cache::has($cache_id))
{
return Cache::get($cache_id);
}
$pass = (bool) ($matching_method == 'all');
foreach (self::getTypes() as $type)
{
// Break if not passed and matching method is ALL
// Or if passed and matching method is ANY
if (
( ! $pass && $matching_method == 'all')
|| ($pass && $matching_method == 'any')
)
{
break;
}
if ( ! isset($conditions[$type]))
{
continue;
}
$pass = self::passByType($conditions[$type], $type, $article, $module);
}
return Cache::set(
$cache_id,
$pass
);
}
public static function hasConditions($conditions)
{
if (empty($conditions))
{
return false;
}
foreach (self::getTypes() as $type)
{
if (isset($conditions[$type]) && isset($conditions[$type]->include_type) && $conditions[$type]->include_type)
{
return true;
}
}
return false;
}
public static function getConditionsFromParams(&$params)
{
$cache_id = 'getConditionsFromParams_' . json_encode($params);
if (Cache::has($cache_id))
{
return Cache::get($cache_id);
}
self::renameParamKeys($params);
$types = [];
foreach (self::getTypes() as $id => $type)
{
if (empty($params->conditions[$id]))
{
continue;
}
$types[$type] = (object) [
'include_type' => $params->conditions[$id],
'selection' => [],
'params' => (object) [],
];
if (isset($params->conditions[$id . '_selection']))
{
$types[$type]->selection = self::getSelection($params->conditions[$id . '_selection'], $type);
}
self::addParams($types[$type], $type, $id, $params);
}
return Cache::set(
$cache_id,
$types
);
}
public static function getConditionsFromTagAttributes(&$attributes, $only_types = [])
{
$conditions = [];
PluginTag::replaceKeyAliases($attributes, self::getTypeAliases(), true);
$types = self::getTypes($only_types);
if (empty($types))
{
return $conditions;
}
$type_params = [];
foreach ($attributes as $type_param => $value)
{
if (strpos($type_param, '_') === false)
{
continue;
}
list($type, $param) = explode('_', $type_param, 2);
$condition_type = self::getType($type, $only_types);
if ( ! $condition_type)
{
continue;
}
$type_params[$type_param] = $value;
unset($attributes->{$type_param});
}
foreach ($attributes as $type => $value)
{
if (empty($value))
{
continue;
}
$condition_type = self::getType($type, $only_types);
if ( ! $condition_type)
{
continue;
}
$value = html_entity_decode($value);
$params = self::getDefaultParamsByType($condition_type, $type);
$params->conditions = $type_params;
$reverse = false;
$selection = self::getSelectionFromTagAttribute($condition_type, $value, $params, $reverse);
$condition = (object) [
'include_type' => $reverse ? 2 : 1,
'selection' => $selection,
'params' => (object) [],
];
self::addParams($condition, $condition_type, $type, $params);
$conditions[$condition_type] = $condition;
}
return $conditions;
}
private static function initParametersByType(&$params, $type = '')
{
$params->class_name = str_replace('.', '', $type);
$params->include_type = self::getConditionState($params->include_type);
}
private static function passByType($condition, $type, $article = null, $module = null)
{
$article_id = isset($article->id) ? $article->id : '';
$module_id = isset($module->id) ? $module->id : '';
$cache_prefix = 'passByType_' . $type . '_' . $article_id . '_' . $module_id;
$cache_id = $cache_prefix . '_' . json_encode($condition);
if (Cache::has($cache_id))
{
return Cache::get($cache_id);
}
self::initParametersByType($condition, $type);
$cache_id = $cache_prefix . '_' . json_encode($condition);
if (Cache::has($cache_id))
{
return Cache::get($cache_id);
}
$pass = false;
switch ($condition->include_type)
{
case 'all':
$pass = true;
break;
case 'none':
$pass = false;
break;
default:
if ( ! file_exists(__DIR__ . '/Condition/' . $condition->class_name . '.php'))
{
break;
}
$className = '\\RegularLabs\\Library\\Condition\\' . $condition->class_name;
$class = new $className($condition, $article, $module);
$class->beforePass();
$pass = $class->pass();
break;
}
return Cache::set(
$cache_id,
$pass
);
}
private static function getConditionState($include_type)
{
switch ($include_type . '')
{
case 1:
case 'include':
return 'include';
case 2:
case 'exclude':
return 'exclude';
case 3:
case -1:
case 'none':
return 'none';
default:
return 'all';
}
}
private static function makeArray($array = '', $delimiter = ',', $trim = true)
{
if (empty($array))
{
return [];
}
$cache_id = 'makeArray_' . json_encode($array) . '_' . $delimiter . '_' . $trim;
if (Cache::has($cache_id))
{
return Cache::get($cache_id);
}
$array = self::mixedDataToArray($array, $delimiter);
if (empty($array))
{
return $array;
}
if ( ! $trim)
{
return $array;
}
foreach ($array as $k => $v)
{
if ( ! is_string($v))
{
continue;
}
$array[$k] = trim($v);
}
return Cache::set(
$cache_id,
$array
);
}
private static function mixedDataToArray($array = '', $delimiter = ',')
{
if ( ! is_array($array))
{
return explode($delimiter, $array);
}
if (empty($array))
{
return $array;
}
if (isset($array[0]) && is_array($array[0]))
{
return $array[0];
}
if (count($array) === 1 && strpos($array[0], $delimiter) !== false)
{
return explode($delimiter, $array[0]);
}
return $array;
}
private static function renameParamKeys(&$params)
{
$params->conditions = isset($params->conditions) ? $params->conditions : [];
foreach ($params as $key => $value)
{
if (strpos($key, 'condition_') === false && strpos($key, 'assignto_') === false)
{
continue;
}
$new_key = substr($key, strpos($key, '_') + 1);
$params->conditions[$new_key] = $value;
unset($params->{$key});
}
}
private static function getSelection($selection, $type = '')
{
if (in_array($type, self::getNotArrayTextAreaTypes()))
{
return $selection;
}
$delimiter = in_array($type, self::getTextAreaTypes()) ? "\n" : ',';
return self::makeArray($selection, $delimiter);
}
private static function getSelectionFromTagAttribute($type, $value, &$params, &$reverse)
{
if ($type == 'Date.Date')
{
$value = str_replace('from', '', $value);
$dates = explode(' - ', str_replace('to', ' - ', $value));
$params->ignore_time_zone = true;
if ( ! empty($dates[0]))
{
$params->publish_up = date('Y-m-d H:i:s', strtotime($dates[0]));
}
if ( ! empty($dates[1]))
{
$params->publish_down = date('Y-m-d H:i:s', strtotime($dates[1]));
}
return [];
}
if ($type == 'Date.Time')
{
$value = str_replace('from', '', $value);
$dates = explode(' - ', str_replace('to', ' - ', $value));
$params->publish_up = $dates[0];
$params->publish_down = isset($dates[1]) ? $dates[1] : $dates[0];
return [];
}
if (in_array($type, self::getTextAreaTypes()))
{
$value = Html::convertWysiwygToPlainText($value);
}
if (strpos($value, '!NOT!') === 0)
{
$reverse = true;
$value = substr($value, 5);
}
if ( ! in_array($type, self::getNotArrayTextAreaTypes()))
{
$value = str_replace('[[:COMMA:]]', ',', str_replace(',', '[[:SPLIT:]]', str_replace('\\,', '[[:COMMA:]]', $value)));
$value = explode('[[:SPLIT:]]', $value);
}
return $value;
}
private static function getDefaultParamsByType($condition_type, $type)
{
switch ($condition_type)
{
case 'Content.Category':
return (object) [
'assignto_' . $type . '_inc' => [
'inc_cats',
'inc_arts',
],
];
case 'Easyblog.Category':
case 'K2.Category':
case 'Zoo.Category':
case 'Hikashop.Category':
case 'Mijoshop.Category':
case 'Redshop.Category':
case 'Virtuemart.Category':
return (object) [
'assignto_' . $type . '_inc' => [
'inc_cats',
'inc_items',
],
];
default:
return (object) [];
}
}
private static function addParams(&$object, $type, $id, &$params)
{
$extra_params = [];
$array_params = [];
$includes = [];
switch ($type)
{
case 'Menu':
$extra_params = ['inc_children', 'inc_noitemid'];
break;
case 'Date.Date':
$extra_params = ['publish_up', 'publish_down', 'recurring', 'ignore_time_zone'];
break;
case 'Date.Season':
$extra_params = ['hemisphere'];
break;
case 'Date.Time':
$extra_params = ['publish_up', 'publish_down'];
break;
case 'User.Grouplevel':
$extra_params = ['inc_children'];
break;
case 'Url':
if (is_array($object->selection))
{
$object->selection = implode("\n", $object->selection);
}
if (isset($params->conditions['urls_selection_sef']))
{
$object->selection .= "\n" . $params->conditions['urls_selection_sef'];
}
$object->selection = trim(str_replace("\r", '', $object->selection));
$object->selection = explode("\n", $object->selection);
$object->params->regex = isset($params->conditions['urls_regex']) ? $params->conditions['urls_regex'] : false;
break;
case 'Agent.Browser':
if ( ! empty($params->conditions['mobile_selection']))
{
$object->selection = array_merge(self::makeArray($object->selection), self::makeArray($params->conditions['mobile_selection']));
}
if ( ! empty($params->conditions['searchbots_selection']))
{
$object->selection = array_merge($object->selection, self::makeArray($params->conditions['searchbots_selection']));
}
break;
case 'Tag':
$extra_params = ['inc_children'];
break;
case 'Content.Category':
$extra_params = ['inc_children'];
$includes = ['cats' => 'categories', 'arts' => 'articles', 'others'];
break;
case 'Easyblog.Category':
case 'K2.Category':
case 'Hikashop.Category':
case 'Mijoshop.Category':
case 'Redshop.Category':
case 'Virtuemart.Category':
$extra_params = ['inc_children'];
$includes = ['cats' => 'categories', 'items'];
break;
case 'Zoo.Category':
$extra_params = ['inc_children'];
$includes = ['apps', 'cats' => 'categories', 'items'];
break;
case 'Easyblog.Tag':
case 'Flexicontent.Tag':
case 'K2.Tag':
$includes = ['tags', 'items'];
break;
case 'Content.Article':
$extra_params = [
'featured',
'content_keywords', 'keywords' => 'meta_keywords',
'authors',
'date', 'date_comparison', 'date_type', 'date_date', 'date_from', 'date_to',
'fields',
];
break;
case 'K2.Item':
$extra_params = ['content_keywords', 'meta_keywords', 'authors'];
break;
case 'Easyblog.Item':
$extra_params = ['content_keywords', 'authors'];
break;
case 'Zoo.Item':
$extra_params = ['authors'];
break;
}
if (in_array($type, self::getMatchAllTypes()))
{
$extra_params[] = 'match_all';
if (count($object->selection) == 1 && strpos($object->selection[0], '+') !== false)
{
$object->selection = ArrayHelper::toArray($object->selection[0], '+');
$params->match_all = true;
}
}
if (empty($extra_params) && empty($array_params) && empty($includes))
{
return;
}
self::addParamsByType($object, $id, $params, $extra_params, $array_params, $includes);
}
private static function addParamsByType(&$object, $id, $params, $extra_params = [], $array_params = [], $includes = [])
{
foreach ($extra_params as $key => $param)
{
$key = is_numeric($key) ? $param : $key;
$object->params->{$param} = self::getTypeParamValue($id, $params, $key);
}
foreach ($array_params as $key => $param)
{
$key = is_numeric($key) ? $param : $key;
$object->params->{$param} = self::getTypeParamValue($id, $params, $key, true);
}
if (empty($includes))
{
return;
}
$incs = self::getTypeParamValue($id, $params, 'inc', true);
if (empty($incs) && ! empty($params->conditions[$id]) && ! isset($params->conditions[$id . '_inc']))
{
$incs = ['inc_items', 'inc_arts', 'inc_cats', 'inc_others', 'x'];
}
foreach ($includes as $key => $param)
{
$key = is_numeric($key) ? $param : $key;
$object->params->{'inc_' . $param} = in_array('inc_' . $key, $incs) ? 1 : 0;
}
unset($object->params->inc);
}
private static function getTypeParamValue($id, $params, $key, $is_array = false)
{
if (isset($params->conditions) && isset($params->conditions[$id . '_' . $key]))
{
return $params->conditions[$id . '_' . $key];
}
if (isset($params->{'assignto_' . $id . '_' . $key}))
{
return $params->{'assignto_' . $id . '_' . $key};
}
if (isset($params->{$key}))
{
return $params->{$key};
}
if ($is_array)
{
return [];
}
return '';
}
private static function getTypes($only_types = [])
{
$types = [
'menuitems' => 'Menu',
'homepage' => 'Homepage',
'date' => 'Date.Date',
'seasons' => 'Date.Season',
'months' => 'Date.Month',
'days' => 'Date.Day',
'time' => 'Date.Time',
'accesslevels' => 'User.Accesslevel',
'usergrouplevels' => 'User.Grouplevel',
'users' => 'User.User',
'languages' => 'Language',
'ips' => 'Ip',
'geocontinents' => 'Geo.Continent',
'geocountries' => 'Geo.Country',
'georegions' => 'Geo.Region',
'geopostalcodes' => 'Geo.Postalcode',
'templates' => 'Template',
'urls' => 'Url',
'devices' => 'Agent.Device',
'os' => 'Agent.Os',
'browsers' => 'Agent.Browser',
'components' => 'Component',
'tags' => 'Tag',
'contentpagetypes' => 'Content.Pagetype',
'cats' => 'Content.Category',
'articles' => 'Content.Article',
'easyblogpagetypes' => 'Easyblog.Pagetype',
'easyblogcats' => 'Easyblog.Category',
'easyblogtags' => 'Easyblog.Tag',
'easyblogitems' => 'Easyblog.Item',
'flexicontentpagetypes' => 'Flexicontent.Pagetype',
'flexicontenttags' => 'Flexicontent.Tag',
'flexicontenttypes' => 'Flexicontent.Type',
'form2contentprojects' => 'Form2content.Project',
'k2pagetypes' => 'K2.Pagetype',
'k2cats' => 'K2.Category',
'k2tags' => 'K2.Tag',
'k2items' => 'K2.Item',
'zoopagetypes' => 'Zoo.Pagetype',
'zoocats' => 'Zoo.Category',
'zooitems' => 'Zoo.Item',
'akeebasubspagetypes' => 'Akeebasubs.Pagetype',
'akeebasubslevels' => 'Akeebasubs.Level',
'hikashoppagetypes' => 'Hikashop.Pagetype',
'hikashopcats' => 'Hikashop.Category',
'hikashopproducts' => 'Hikashop.Product',
'mijoshoppagetypes' => 'Mijoshop.Pagetype',
'mijoshopcats' => 'Mijoshop.Category',
'mijoshopproducts' => 'Mijoshop.Product',
'redshoppagetypes' => 'Redshop.Pagetype',
'redshopcats' => 'Redshop.Category',
'redshopproducts' => 'Redshop.Product',
'virtuemartpagetypes' => 'Virtuemart.Pagetype',
'virtuemartcats' => 'Virtuemart.Category',
'virtuemartproducts' => 'Virtuemart.Product',
'cookieconfirm' => 'Cookieconfirm',
'php' => 'Php',
];
if (empty($only_types))
{
return $types;
}
return array_intersect_key($types, array_flip($only_types));
}
private static function getType(&$type, $only_types = [])
{
$types = self::getTypes($only_types);
if (isset($types[$type]))
{
return $types[$type];
}
// Make it plural
$type = rtrim($type, 's') . 's';
if (isset($types[$type]))
{
return $types[$type];
}
// Replace incorrect plural endings
$type = str_replace('ys', 'ies', $type);
if (isset($types[$type]))
{
return $types[$type];
}
return false;
}
private static function getTypeAliases()
{
return [
'matching_method' => ['method'],
'menuitems' => ['menu'],
'homepage' => ['home'],
'date' => ['daterange'],
'seasons' => [''],
'months' => [''],
'days' => [''],
'time' => [''],
'accesslevels' => ['access'],
'usergrouplevels' => ['usergroups', 'groups'],
'users' => [''],
'languages' => ['langs'],
'ips' => ['ipaddress', 'ipaddresses'],
'geocontinents' => ['continents'],
'geocountries' => ['countries'],
'georegions' => ['regions'],
'geopostalcodes' => ['postalcodes', 'postcodes'],
'templates' => [''],
'urls' => [''],
'devices' => [''],
'os' => [''],
'browsers' => [''],
'components' => [''],
'tags' => [''],
'contentpagetypes' => ['pagetypes'],
'cats' => ['categories', 'category'],
'articles' => [''],
'php' => [''],
];
}
private static function getTextAreaTypes()
{
return [
'Ip',
'Url',
'Php',
];
}
private static function getNotArrayTextAreaTypes()
{
return [
'Php',
];
}
public static function getMatchAllTypes()
{
return [
'User.Grouplevel',
'Tag',
];
}
}