jeyroik/extas-operations-jsonrpc-index

View on GitHub
src/components/operations/jsonrpc/Index.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php
namespace extas\components\operations\jsonrpc;

use extas\components\conditions\ConditionParameter;
use extas\components\expands\Expand;
use extas\components\api\jsonrpc\operations\OperationRunner;
use extas\interfaces\extensions\IExtensionJsonRpcIndex;
use extas\interfaces\IItem;
use extas\interfaces\jsonrpc\IRequest;
use extas\interfaces\operations\jsonrpc\IIndex;
use extas\interfaces\stages\IStageJsonRpcBeforeIndexResponse;
use extas\interfaces\stages\IStageJsonRpcBeforeSelect;

/**
 * Class Index
 *
 * @package extas\components\api\jsonrpc
 * @author jeyroik@gmail.com
 */
class Index extends OperationRunner implements IIndex
{
    /**
     * @return array
     */
    public function run(): array
    {
        /**
         * @var IExtensionJsonRpcIndex|IRequest $request
         */
        $request = $this->getJsonRpcRequest();
        $repository = $this->getOperation()->getItemRepository();
        $records = $repository->all(
            [],
            $request->getLimit(0),
            $request->getOffset(0),
            $this->convertIntoTableSort($request->getSort([$repository->getPk()]))
        );

        $items = $this->filter($request->getFilter(), $records);
        $items = $this->selectFields($items);
        $items = $this->expandItems($items);
        $items = $this->runStageBeforeIndexResponse($items);

        $asArray = [];

        foreach ($items as $item) {
            $asArray[] = $item->__toArray();
        }

        return [
            'items' => $asArray,
            'total' => count($asArray)
        ];
    }

    /**
     * @param array $items
     * @return array
     */
    protected function runStageBeforeIndexResponse(array $items): array
    {
        $stage = IStageJsonRpcBeforeIndexResponse::NAME;
        foreach ($this->getPluginsByStage($stage, $this->getHttpIO()) as $plugin) {
            /**
             * @var IStageJsonRpcBeforeIndexResponse $plugin
             */
            $items = $plugin($items);
        }

        $stage .= '.' . $this->getOperation()->getName();
        foreach ($this->getPluginsByStage($stage, $this->getHttpIO()) as $plugin) {
            /**
             * @var IStageJsonRpcBeforeIndexResponse $plugin
             */
            $items = $plugin($items);
        }

        return $items;
    }

    /**
     * @param array $sort
     * @return array
     */
    protected function convertIntoTableSort(array $sort): array
    {
        $keys = array_keys($sort);
        $firstKey = array_shift($keys);

        return [$firstKey, $sort[$firstKey]];
    }

    /**
     * @param $items
     * @return array
     */
    protected function expandItems($items): array
    {
        $expand = new Expand($this->getHttpIO());

        foreach ($items as $index => $item) {
            $items[$index] = $expand->expand($item);
        }

        return $items;
    }

    /**
     * @param IItem[] $items
     * @return IItem[]
     */
    protected function selectFields(array $items): array
    {
        /**
         * @var IExtensionJsonRpcIndex $request
         */
        $request = $this->getJsonRpcRequest();
        $select = $request->getSelect([]);

        if (empty($select)) {
            return $items;
        }

        foreach ($this->getPluginsByStage(IStageJsonRpcBeforeSelect::NAME, $this->getHttpIO()) as $plugin) {
            /**
             * @var IStageJsonRpcBeforeSelect $plugin
             */
            $select = $plugin($select, $items);
        }

        $valid = [];
        foreach ($items as $index => $item) {
            $this->selectItemFields($item, $select, $valid);
        }

        return $valid;
    }

    /**
     * @param IItem $item
     * @param array $select
     * @param array $items
     */
    protected function selectItemFields(IItem $item, array $select, array &$items): void
    {
        if ($item->has(...$select)) {
            $items[] = $item->__select($select);
        }
    }

    /**
     * @param array $filter
     * @param array $items
     *
     * @return array
     */
    protected function filter($filter, $items)
    {
        if (empty($filter)) {
            return $items;
        }

        $result = [];
        $conditions = [];

        foreach ($filter as $fieldName => $filterOptions) {
            $this->appendCondition($fieldName, $filterOptions, $conditions);
        }

        foreach ($items as $item) {
            $this->filterByConditions($item, $conditions, $result);
        }

        return $result;
    }

    /**
     * @param string $fieldName
     * @param array $filterOptions
     * @param array $conditions
     */
    protected function appendCondition(string $fieldName, array $filterOptions, array &$conditions): void
    {
        foreach ($filterOptions as $filterCompare => $filterValue) {
            $conditions[] = new ConditionParameter([
                ConditionParameter::FIELD__NAME => $fieldName,
                ConditionParameter::FIELD__CONDITION => str_replace('$', '', $filterCompare),
                ConditionParameter::FIELD__VALUE => $filterValue
            ]);
        }
    }

    /**
     * @param IItem $item
     * @param ConditionParameter[] $conditions
     * @param array $result
     */
    protected function filterByConditions(IItem $item, array $conditions, array &$result): void
    {
        $valid = true;
        foreach ($conditions as $condition) {
            if (!$condition->isConditionTrue($item[$condition->getName()] ?? null)) {
                $valid = false;
                break;
            }
        }

        $valid && ($result[] = $item);
    }

    /**
     * @return string
     */
    protected function getSubjectForExtension(): string
    {
        return 'extas.operation.jsonrpc.index';
    }
}