name : Condition.php
<?php
/**
 * @package         Conditions
 * @version         25.7.12430
 * 
 * @author          Peter van Westen <[email protected]>
 * @link            https://regularlabs.com
 * @copyright       Copyright © 2025 Regular Labs All Rights Reserved
 * @license         GNU General Public License version 2 or later
 */

namespace RegularLabs\Component\Conditions\Administrator\Condition;

defined('_JEXEC') or die;

use Joomla\CMS\Factory as JFactory;
use Joomla\CMS\Menu\MenuItem as JMenuItem;
use RegularLabs\Component\Conditions\Administrator\Helper\Cache;
use RegularLabs\Library\Document as RL_Document;
use RegularLabs\Library\Input as RL_Input;
use RegularLabs\Library\Parameters as RL_Parameters;

/**
 * Class Condition
 *
 * @package RegularLabs\Library
 */
abstract class Condition
{
    static    $_request;
    public    $article;
    public    $category_id;
    public    $date;
    public    $db;
    public    $exclude;
    public    $module;
    public    $params;
    public    $request;
    public    $selection;
    protected $request_keys = [];

    public function __construct(
        object            $rule,
        object|false|null $article = null,
        object|false|null $module = null,
        object|false|null $request = null,
        ?int              $category_id = null
    )
    {
        self::setRequest($request);

        $this->db = JFactory::getDbo();

        $this->params      = $rule->params ?? (object) [];
        $this->selection   = $rule->params->selection ?? [];
        $this->exclude     = $rule->exclude ?? false;
        $this->article     = $article;
        $this->module      = $module;
        $this->category_id = $category_id;

        $this->prepareSelection();
    }

    public function beforePass(): void
    {
    }

    public function getMenuItemParams(int $id = 0): object
    {
        $cache = new Cache;

        if ($cache->exists())
        {
            return $cache->get();
        }

        $query = $this->db->getQuery(true)
            ->select('m.params')
            ->from('#__menu AS m')
            ->where('m.id = ' . (int) $id);
        $this->db->setQuery($query);
        $params = $this->db->loadResult();

        return $cache->set(RL_Parameters::getObjectFromRegistry($params));
    }

    public function getParentIds(
        int    $id = 0,
        string $table = 'menu',
        string $parent = 'parent_id',
        string $child = 'id'
    ): array
    {
        if ( ! $id)
        {
            return [];
        }

        $cache = new Cache;

        if ($cache->exists())
        {
            return $cache->get();
        }

        $parent_ids = [];

        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($parent_ids);
    }

    public function init(): void
    {
    }

    public function initRequest(&$request): void
    {
    }

    public function makeArray(
        array|string|null $array = '',
        string            $delimiter = ',',
        bool              $trim = false
    ): array
    {
        if (empty($array))
        {
            return [];
        }

        $cache = new Cache;

        if ($cache->exists())
        {
            return $cache->get();
        }

        $array = $this->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($array);
    }

    public function passByPageType(
        string $option,
        array  $selection = [],
        bool   $add_view = false,
        bool   $get_task = false,
        bool   $get_layout = true
    ): bool
    {
        if ($this->request->option != $option)
        {
            return false;
        }

        if ($get_task && $this->request->task && $this->request->task != $this->request->view && $this->request->task != 'default')
        {
            $pagetype = ($add_view ? $this->request->view . '_' : '') . $this->request->task;

            return $this->passSimple($pagetype, $selection);
        }

        if ($get_layout && $this->request->layout && $this->request->layout != $this->request->view && $this->request->layout != 'default')
        {
            $pagetype = ($add_view ? $this->request->view . '_' : '') . $this->request->layout;

            return $this->passSimple($pagetype, $selection);
        }

        return $this->passSimple($this->request->view, $selection);
    }

    public function passInRange(
        string|int|null   $value = '',
        array|string|null $selection = null
    ): bool
    {
        if (empty($value))
        {
            return false;
        }

        $selections = $this->makeArray($selection ?: $this->selection);

        $pass = false;

        foreach ($selections as $selection)
        {
            if (empty($selection))
            {
                continue;
            }

            if ( ! str_contains($selection, '-'))
            {
                if ((int) $value == (int) $selection)
                {
                    $pass = true;
                    break;
                }

                continue;
            }

            [$min, $max] = explode('-', $selection, 2);

            if ((int) $value >= (int) $min && (int) $value <= (int) $max)
            {
                $pass = true;
                break;
            }
        }

        return $pass;
    }

    public function passItemByType(bool &$pass, string $type = '', mixed $data = null): bool
    {
        $pass_type = ! empty($data) ? $this->{'pass' . $type}($data) : $this->{'pass' . $type}();

        if ($pass_type === null)
        {
            return true;
        }

        $pass = $pass_type;

        return $pass;
    }

    public function passSimple(
        mixed             $values = '',
        string|array|null $selection = null,
        bool              $caseinsensitive = false
    )
    {
        $values = $this->makeArray($values);

        $selection = $selection ?: $this->selection;
        $selection = is_array($selection) ? $selection : [$selection];

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

        $pass = false;

        foreach ($values as $value)
        {
            if ($caseinsensitive)
            {
                if (in_array(strtolower($value), array_map('strtolower', $selection), true))
                {
                    $pass = true;
                    break;
                }

                continue;
            }

            if (in_array($value, $selection))
            {
                $pass = true;
                break;
            }
        }

        return $pass;
    }

    protected function prepareSelection(): void
    {
    }

    private function getActiveMenu(): object|false
    {
        $menu = JFactory::getApplication()->getMenu()->getActive();

        if (empty($menu->id))
        {
            return false;
        }

        return $this->getMenuById($menu->id);
    }

    private function getItemId(): int
    {
        $id = RL_Input::getInt('Itemid', 0);

        if ($id)
        {
            return $id;
        }

        $menu = $this->getActiveMenu();

        return $menu->id ?? 0;
    }

    private function getMenuById(int $id = 0): object|false
    {
        $menu = JFactory::getApplication()->getMenu()->getItem($id);

        if (empty($menu->id))
        {
            return false;
        }

        if ($menu->type == 'alias')
        {
            $params = $menu->getParams();

            return $this->getMenuById($params->get('aliasoptions'));
        }

        return $menu;
    }

    private function getRequest(): object
    {
        $return_early = ! is_null(self::$_request);

        $app = JFactory::getApplication();

        $id = RL_Input::getAsArray(
            'a_id',
            RL_Input::getAsArray('id', [0])
        );

        self::$_request = (object) [
            'idname' => 'id',
            'option' => RL_Input::getCmd('option'),
            'view'   => RL_Input::getCmd('view'),
            'task'   => RL_Input::getCmd('task'),
            'layout' => RL_Input::getString('layout'),
            'Itemid' => $this->getItemId(),
            'id'     => (int) $id[0],
        ];

        switch (self::$_request->option)
        {
            case 'com_categories':
                $extension              = RL_Input::getCmd('extension');
                self::$_request->option = $extension ?: 'com_content';
                self::$_request->view   = 'category';
                break;

            case 'com_breezingforms':
                if (self::$_request->view == 'article')
                {
                    self::$_request->option = 'com_content';
                }
                break;

            default:
                break;
        }

        $this->initRequest(self::$_request);

        if ( ! self::$_request->id)
        {
            $cid                = RL_Input::getAsArray('cid', [0]);
            self::$_request->id = (int) $cid[0];
        }

        if ($return_early)
        {
            return self::$_request;
        }

        // if no id is found, check if menuitem exists to get view and id
        if ( ! RL_Document::isClient('site')
            || (self::$_request->option && self::$_request->id)
        )
        {
            return self::$_request;
        }

        /* @var JMenuItem $menu_item */
        $menu_item = empty(self::$_request->Itemid)
            ? $app->getMenu('site')->getActive()
            : $app->getMenu('site')->getItem(self::$_request->Itemid);

        if ( ! $menu_item)
        {
            return self::$_request;
        }

        if ( ! self::$_request->option)
        {
            self::$_request->option = $menu_item->query['option'] ?? null;
        }

        self::$_request->view = $menu_item->query['view'] ?? null;
        self::$_request->task = $menu_item->query['task'] ?? null;

        if ( ! self::$_request->id)
        {
            self::$_request->id = $menu_item->query[self::$_request->idname] ?? $menu_item->getParams()->get(self::$_request->idname);
        }

        unset($menu_item);

        return self::$_request;
    }

    private function getRequestKeys(): array
    {
        return ['option', 'view', 'task', 'layout', 'id', 'Itemid', ...$this->request_keys];
    }

    private function mixedDataToArray(
        array|string $array = '',
        bool         $onlycommas = false
    ): array
    {
        if ( ! is_array($array))
        {
            $delimiter = ($onlycommas || ! str_contains($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 && str_contains($array[0], ','))
        {
            return explode(',', $array[0]);
        }

        return $array;
    }

    private function setRequest(object|false|null $request_overrides = null): void
    {
        $this->request = $this->getRequest();

        if (empty($request_overrides))
        {
            return;
        }

        foreach ($request_overrides as $key => $value)
        {
            $key = $key == 'cid' ? 'id' : $key;

            if ( ! in_array($key, $this->getRequestKeys()))
            {
                continue;
            }

            if ($key === 'id' && is_array($value))
            {
                $value = (int) $value[0];
            }

            $this->request->{$key} = $value;
        }
    }
}

© 2025 Cubjrnet7