<commit_before><?php

namespace SebastianBerc\Repositories;

use Illuminate\Container\Container;
use Illuminate\Contracts\Container\Container as Application;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model as Eloquent;
use Illuminate\Pagination\LengthAwarePaginator;
use SebastianBerc\Repositories\Contracts\RepositoryInterface;
use SebastianBerc\Repositories\Contracts\ShouldCache;
use SebastianBerc\Repositories\Contracts\TransformerInterface;
use SebastianBerc\Repositories\Exceptions\InvalidRepositoryModel;
use SebastianBerc\Repositories\Exceptions\InvalidTransformer;
use SebastianBerc\Repositories\Mediators\RepositoryMediator;
use SebastianBerc\Repositories\Traits\Filterable;
use SebastianBerc\Repositories\Traits\Sortable;

/**
 * Class Repositories
 *
 * @author    <NAME> <<EMAIL>>
 * @copyright Copyright (c) <NAME>
 * @package   SebastianBerc\Repositories
 */
abstract class Repository implements RepositoryInterface
{
    use Filterable, Sortable;

    /**
     * Contains Laravel Application instance.
     *
     * @var Application
     */
    protected $app;

    /**
     * Contains Eloquent model instance.
     *
     * @var Eloquent
     */
    public $model;

    /**
     * Contains relations to eager load.
     *
     * @var array
     */
    public $with = [];

    /**
     * Contains time of caching.
     *
     * @var int
     */
    public $lifetime;

    /**
     * Contains transformer instance.
     *
     * @var string
     */
    public $transformer;

    /**
     * Contains repository mediator instance.
     *
     * @var RepositoryMediator
     */
    public $mediator;

    /**
     * Create a new RepositoryInterface instance.
     *
     * @param Application $app
     */
    public function __construct(Application $app)
    {
        $this->app      = $app;
        $this->mediator = new RepositoryMediator($app, $this);
    }

    /**
     * Create a new RepositoryInterface instance.
     *
     * @return static
     */
    public static function instance()
    {
        return new static(function_exists('app') ? app() : Container::getInstance());
    }

    /**
     * Call an action on mediator.
     *
     * @param array $parameters
     *
     * @return mixed
     */
    public function mediator(array $parameters)
    {
        $caller = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]["function"];

        if ($this->shouldBeCached()) {
            return $this->mediator->cache($caller, $parameters);
        }

        return $this->mediator->database($caller, $parameters);
    }

    /**
     * Add criteria to next query in repository.
     *
     * @param Criteria $criteria
     *
     * @return $this
     */
    public function citeria(Criteria $criteria)
    {
        $this->mediator->criteria()->addCriteria($criteria);

        return $this;
    }

    /**
     * Return fully qualified model class name.
     *
     * @return string
     */
    abstract public function takeModel();

    /**
     * Return instance of Eloquent model.
     *
     * @return \Illuminate\Database\Eloquent\Model
     */
    public function makeModel()
    {
        if (!($this->model = $this->app->make($this->takeModel())) instanceof Eloquent) {
            throw new InvalidRepositoryModel(get_class($this->model), Eloquent::class);
        }

        return $this->model;
    }

    /**
     * Return instance of query builder for Eloquent model.
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function makeQuery()
    {
        $query = $this->makeModel()->query();

        if ($this->mediator->hasCriteria()) {
            $query = $this->mediator->criteria()->executeOn($this->makeModel()->query());
        }

        return empty($this->with) ? $query : $query->with($this->with);
    }

    /**
     * Adds relation to eager loads.
     *
     * @param string|string[] $relation
     *
     * @return static
     */
    public function with($relation)
    {
        if (func_num_args() == 1) {
            $this->with = array_merge($this->with, is_array($relation) ? $relation : [$relation]);
        } else {
            $this->with = array_merge($this->with, func_get_args());
        }

        return $this;
    }

    /**
     * Sets transformer to current repository instance.
     *
     * @param string $transformer
     *
     * @return static
     */
    public function setTransformer($transformer)
    {
        if (!(new \ReflectionClass($transformer))->implementsInterface(TransformerInterface::class)) {
            throw new InvalidTransformer();
        }

        $this->transformer = $transformer;

        return $this;
    }

    /**
     * Get all of the models from the database.
     *
     * @param string[] $columns<commit_msg>Rename typo in method name from citeria to criteria.<commit_after><?php

namespace SebastianBerc\Repositories;

use Illuminate\Container\Container;
use Illuminate\Contracts\Container\Container as Application;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model as Eloquent;
use Illuminate\Pagination\LengthAwarePaginator;
use SebastianBerc\Repositories\Contracts\RepositoryInterface;
use SebastianBerc\Repositories\Contracts\ShouldCache;
use SebastianBerc\Repositories\Contracts\TransformerInterface;
use SebastianBerc\Repositories\Exceptions\InvalidRepositoryModel;
use SebastianBerc\Repositories\Exceptions\InvalidTransformer;
use SebastianBerc\Repositories\Mediators\RepositoryMediator;
use SebastianBerc\Repositories\Traits\Filterable;
use SebastianBerc\Repositories\Traits\Sortable;

/**
 * Class Repositories
 *
 * @author    <NAME> <<EMAIL>>
 * @copyright Copyright (c) <NAME>
 * @package   SebastianBerc\Repositories
 */
abstract class Repository implements RepositoryInterface
{
    use Filterable, Sortable;

    /**
     * Contains Laravel Application instance.
     *
     * @var Application
     */
    protected $app;

    /**
     * Contains Eloquent model instance.
     *
     * @var Eloquent
     */
    public $model;

    /**
     * Contains relations to eager load.
     *
     * @var array
     */
    public $with = [];

    /**
     * Contains time of caching.
     *
     * @var int
     */
    public $lifetime;

    /**
     * Contains transformer instance.
     *
     * @var string
     */
    public $transformer;

    /**
     * Contains repository mediator instance.
     *
     * @var RepositoryMediator
     */
    public $mediator;

    /**
     * Create a new RepositoryInterface instance.
     *
     * @param Application $app
     */
    public function __construct(Application $app)
    {
        $this->app      = $app;
        $this->mediator = new RepositoryMediator($app, $this);
    }

    /**
     * Create a new RepositoryInterface instance.
     *
     * @return static
     */
    public static function instance()
    {
        return new static(function_exists('app') ? app() : Container::getInstance());
    }

    /**
     * Call an action on mediator.
     *
     * @param array $parameters
     *
     * @return mixed
     */
    public function mediator(array $parameters)
    {
        $caller = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]["function"];

        if ($this->shouldBeCached()) {
            return $this->mediator->cache($caller, $parameters);
        }

        return $this->mediator->database($caller, $parameters);
    }

    /**
     * Add criteria to next query in repository.
     *
     * @param Criteria $criteria
     *
     * @return $this
     */
    public function criteria(Criteria $criteria)
    {
        $this->mediator->criteria()->addCriteria($criteria);

        return $this;
    }

    /**
     * Return fully qualified model class name.
     *
     * @return string
     */
    abstract public function takeModel();

    /**
     * Return instance of Eloquent model.
     *
     * @return Eloquent
     * @throws InvalidRepositoryModel
     */
    public function makeModel()
    {
        if (!($this->model = $this->app->make($this->takeModel())) instanceof Eloquent) {
            throw new InvalidRepositoryModel(get_class($this->model), Eloquent::class);
        }

        return $this->model;
    }

    /**
     * Return instance of query builder for Eloquent model.
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function makeQuery()
    {
        $query = $this->makeModel()->query();

        if ($this->mediator->hasCriteria()) {
            $query = $this->mediator->criteria()->executeOn($this->makeModel()->query());
        }

        return empty($this->with) ? $query : $query->with($this->with);
    }

    /**
     * Adds relation to eager loads.
     *
     * @param string|string[] $relation
     *
     * @return static
     */
    public function with($relation)
    {
        if (func_num_args() == 1) {
            $this->with = array_merge($this->with, is_array($relation) ? $relation : [$relation]);
        } else {
            $this->with = array_merge($this->with, func_get_args());
        }

        return $this;
    }

    /**
     * Sets transformer to current repository instance.
     *
     * @param string $transformer
     *
     * @return static
     * @throws InvalidTransformer
     */
    public function setTransformer($transformer)
    {
        if (!(new \ReflectionClass($transformer))->implementsInterface(TransformerInterface::class)) {
            throw new InvalidTransformer();
        }

        $this->transformer = $transformer;

        return $this;
    }

    /**
     * Get all of the models from the database.
     *
     * @param string[] $columns
{'fraction_non_alphanumeric': 0.12260734609415416, 'fraction_numerical': 0.0006207966890843249, 'mean_word_length': 2.3726448011165386, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 79, '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': '5587306', 'n_tokens_mistral': 2818, 'n_tokens_neox': 2764, 'n_words': 603}