AthensFramework/core

View on GitHub
src/filter/Filter.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php

namespace Athens\Core\Filter;

use Athens\Core\ORMWrapper\QueryWrapperInterface;
use Athens\Core\Row\RowInterface;
use Athens\Core\Visitor\VisitableTrait;
use Athens\Core\FilterStatement\FilterStatementInterface;
use Athens\Core\Writable\WritableTrait;

/**
 * Class Filter
 *
 * @package Athens\Core\Filter
 */
class Filter implements FilterInterface
{

    const TYPE_SEARCH = 'search';
    const TYPE_SORT = 'sort';
    const TYPE_SELECT = 'select';
    const TYPE_STATIC = 'static';
    const TYPE_PAGINATION = 'pagination';
    const TYPE_RELATION = 'relation';

    /** @var FilterStatementInterface[] */
    protected $statements = [];

    /** @var FilterStatementInterface[] */
    protected $queryStatements = [];

    /** @var array */
    protected $options = [];

    /** @var string */
    protected $feedback;

    /** @var boolean */
    protected $canQueryFilter;

    /**
     * @var FilterInterface The next filter in this chain
     */
    protected $nextFilter;

    use VisitableTrait;
    use WritableTrait;

    /**
     * @param string                     $id
     * @param string[]                   $classes
     * @param array                      $data
     * @param FilterStatementInterface[] $statements
     * @param FilterInterface|null       $nextFilter
     */
    public function __construct($id, array $classes, array $data, array $statements, FilterInterface $nextFilter = null)
    {

        if ($nextFilter === null) {
            $this->nextFilter = new DummyFilter();
        } else {
            $this->nextFilter = $nextFilter;
        }

        $this->id = $id;
        $this->statements = $statements;
        $this->classes = $classes;
        $this->data = $data;
    }

    /**
     * @return string[]
     */
    public function getFeedback()
    {
        return $this->feedback;
    }

    /**
     * @param FilterInterface $filter
     * @return FilterInterface
     */
    public function combine(FilterInterface $filter)
    {
        $this->nextFilter = $filter;
        return $this;
    }

    /**
     * @return FilterInterface
     */
    public function getNextFilter()
    {
        return $this->nextFilter;
    }

    /**
     * @return FilterStatementInterface[]
     */
    public function getStatements()
    {
        return $this->statements;
    }

    /**
     * @return FilterStatementInterface[]
     */
    protected function getRowStatements()
    {
        $queryStatements = $this->queryStatements;
        return array_filter(
            $this->statements,
            function ($statement) use ($queryStatements) {
                return array_search($statement, $queryStatements) === false;
            }
        );
    }

    /**
     * @param QueryWrapperInterface $query
     * @return QueryWrapperInterface
     */
    public function queryFilter(QueryWrapperInterface $query)
    {
        $query = $this->getNextFilter()->queryFilter($query);

        $this->canQueryFilter = true;

        if ($this->getNextFilter()->canQueryFilter === false) {
            $this->canQueryFilter = false;
        }

        foreach ($this->statements as $statement) {
            if ($statement->canApplyToQuery($query) === false) {
                $this->canQueryFilter = false;
            }

            if ($this->canQueryFilter === true) {
                $this->setOptionsByQuery($query);
                $this->setFeedbackByQuery($query);
                $query = $statement->applyToQuery($query);

                $this->queryStatements[] = $statement;
            }
        }
        return $query;
    }

    /**
     * @param QueryWrapperInterface $query
     * @return void
     */
    protected function setOptionsByQuery(QueryWrapperInterface $query)
    {
    }

    /**
     * @param QueryWrapperInterface $query
     * @return void
     */
    protected function setFeedbackByQuery(QueryWrapperInterface $query)
    {
    }

    /**
     * @param RowInterface[] $rows
     * @return void
     */
    protected function setOptionsByRows(array $rows)
    {
    }

    /**
     * @param RowInterface[] $rows
     * @return void
     */
    protected function setFeedbackByRows(array $rows)
    {
    }

    /**
     * @param RowInterface[] $rows
     * @return RowInterface[]
     */
    public function rowFilter(array $rows)
    {
        $this->setOptionsByRows($rows);
        $this->setFeedbackByRows($rows);

        $rows = $this->getNextFilter()->rowFilter($rows);
        foreach ($this->getRowStatements() as $statement) {
            $rows = $statement->applyToRows($rows);
        }

        return $rows;
    }

    /**
     * @return array
     */
    public function getOptions()
    {
        return $this->options;
    }
}