<commit_before><?php
/**
 * @author <NAME>
 */

namespace Msantang\QueryFilters;


use Msantang\QueryFilters\Contracts\FilterInterface;
use Msantang\QueryFilters\Contracts\ParameterFilterInterface;

/**
 * Class Filter
 * @package Msantang\QueryFilters
 */
class Filter implements FilterInterface
{
    /**
     * @var array
     */
    protected static $macros = [];
    /**
     * @var array|null
     */
    protected $filters = [];

    /**
     * @param null $filters
     */
    public function __construct($filters = null)
    {
        if($filters) {
            $this->filters = $filters;
        }
    }

    /**
     * Add a new filter
     *
     * @param $name
     * @param $callback
     */
    public static function macro($name, $callback)
    {
        static::$macros[$name] = $callback;
    }

    /**
     * @param \Illuminate\Database\Eloquent\Builder|Contracts\Model $query
     * @param FilterInput $input
     */
    public function apply($query, $input)
    {
        $this->explodeFilters();

        $data = $input->getMappedData();

        foreach ($data as $param => $value) {
            $this->applyParameterFilter($param, $value, $query);
        }
    }

    /**
     * Apply the filters to a parameter
     *
     * @param $param
     * @param $value
     * @param $query
     */
    protected function applyParameterFilter($param, $value, $query)
    {
        foreach($this->filters[$param] as $k => $filters) {

            // if there is no value skip it
            if (!array_key_exists($k, $value)) continue;

            $v = $value[$k];

            $class = ucfirst($filters[0]);
            $opt   = @$filters[1];

            $filter = $this->getParameterFilter($class);

            $p = $this->joined($param);

            // is joined?
            if (is_array($p)) {

                $param = array_pop($p);

                $f = function($q) use($filter, $param, $v, $opt) {
                    $filter($q, $v, $param, $opt);
                };

                while (count($p) > 1) {
                    $rel = array_pop($p);

                    $f = function($q) use($rel, $f, $filter, $param, $v, $opt) {
                        $q->whereHas($rel, $f);
                    };
                }

                $rel = array_pop($p);

                $query->whereHas($rel, $f);

            } else {<commit_msg>add support for relations<commit_after><?php
/**
 * @author <NAME>
 */

namespace Msantang\QueryFilters;


use Msantang\QueryFilters\Contracts\FilterInterface;

/**
 * Class Filter
 * @package Msantang\QueryFilters
 */
class Filter implements FilterInterface
{
    /**
     * @var array
     */
    protected static $macros = [];
    /**
     * @var array|null
     */
    protected $filters = [];

    /**
     * @param null $filters
     */
    public function __construct($filters = null)
    {
        if($filters) {
            $this->filters = $filters;
        }
    }

    /**
     * Add a new filter
     *
     * @param $name
     * @param $callback
     */
    public static function macro($name, $callback)
    {
        static::$macros[$name] = $callback;
    }

    /**
     * @param \Illuminate\Database\Eloquent\Builder|Contracts\Model $query
     * @param FilterInput $input
     */
    public function apply($query, $input)
    {
        $this->explodeFilters();

        $data = $input->getMappedData();

        foreach ($data as $param => $value) {
            $this->applyParameterFilter($param, $value, $query);
        }
    }

    /**
     * Apply the filters to a parameter
     *
     * @param $param
     * @param $value
     * @param $query
     */
    protected function applyParameterFilter($param, $value, $query)
    {
        foreach($this->filters[$param] as $k => $filters) {

            // if there is no value skip it
            if (!array_key_exists($k, $value)) continue;

            $v = $value[$k];

            $class = ucfirst($filters[0]);
            $opt   = @$filters[1];

            $filter = $this->getParameterFilter($class);

            if (!is_callable($filter)) throw new \Exception('ParameterFilter is not callable');

            $p = $this->joined($param);

            // is joined?
            if (is_array($p)) {

                $param = array_pop($p);

                $f = function($q) use($filter, $param, $v, $opt) {
                    $filter($q, $v, $param, $opt);
                };

                while (count($p) > 1) {
                    $rel = array_pop($p);

                    $f = function($q) use($rel, $f, $filter, $param, $v, $opt) {
                        $q->whereHas($rel, $f);
                    };
                }

                $rel = array_pop($p);

                $query->whereHas($rel, $f);

            } else {
{'fraction_non_alphanumeric': 0.15339602925809823, 'fraction_numerical': 0.0012539184952978057, 'mean_word_length': 1.6311159978009895, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3814722', 'n_tokens_mistral': 1454, 'n_tokens_neox': 1401, 'n_words': 309}