%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /var/www/html/news/vendor/czim/laravel-repository/src/
Upload File :
Create Path :
Current File : /var/www/html/news/vendor/czim/laravel-repository/src/ExtendedPostProcessingRepository.php

<?php
namespace Czim\Repository;

use Czim\Repository\Contracts\PostProcessingRepositoryInterface;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Czim\Repository\Contracts\PostProcessorInterface;
use Czim\Repository\PostProcessors\ApplyExtraHiddenAndVisibleAttributes;
use Closure;
use Illuminate\Container\Container as App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Pagination\AbstractPaginator;
use Illuminate\Support\Collection;
use InvalidArgumentException;
use ReflectionClass;

/**
 * Class ExtendedPostProcessingRepository
 *
 * Extends the ExtendedRepository with PostProcessing functionality,
 * including convenience methods for hiding/unhiding Model properties.
 */
abstract class ExtendedPostProcessingRepository extends ExtendedRepository implements PostProcessingRepositoryInterface
{
    /**
     * @var array
     */
    protected $extraHidden = [];

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

    /**
     * The postprocessors to apply to the returned results for the repository
     * (only all() and find(), and similar calls)
     *
     * @var Collection
     */
    protected $postProcessors;



    /**
     * @param App  $app
     * @param Collection $collection
     */
    public function __construct(App $app, Collection $collection)
    {
        parent::__construct($app, $collection);

        $this->restoreDefaultPostProcessors();
    }


    /**
     * Returns the default list of postprocessors to apply to models
     * before returning the result to anything using the repository.
     *
     * Each entry is combination of a key (the classname of the postprocessor)
     * and a value (set of parameters, or Closure that generates parameters).
     *
     * The idea is that on each call, the postprocessors are instantiated,
     * and the parameters (if any) set for them, so any updates on the
     * repository are reflected by the processors.
     *
     * @return Collection
     */
    public function defaultPostProcessors()
    {
        return new Collection([
            ApplyExtraHiddenAndVisibleAttributes::class => function () {
                return [$this->extraHidden, $this->extraUnhidden];
            },
        ]);
    }


    // -------------------------------------------------------------------------
    //      PostProcessors
    // -------------------------------------------------------------------------

    /**
     * Restores prostprocessors to default collection
     *
     * @return $this
     */
    public function restoreDefaultPostProcessors()
    {
        $this->postProcessors = $this->defaultPostProcessors();

        return $this;
    }

    /**
     * Pushes a postProcessor to apply to all models retrieved
     *
     * @param string        $class
     * @param array|Closure $parameters
     * @return $this
     */
    public function pushPostProcessor($class, $parameters = null)
    {
        $this->postProcessors->put($class, $parameters);

        return $this;
    }

    /**
     * Removes postProcessor
     *
     * @param $class
     * @return $this
     */
    public function removePostProcessor($class)
    {
        $this->postProcessors->forget($class);

        return $this;
    }

    /**
     * Runs the result for retrieval calls to the repository
     * through postprocessing.
     *
     * @param Collection|Model|null $result the result of the query, ready for postprocessing
     * @return Model|Collection|null
     */
    public function postProcess($result)
    {
        // determine whether there is anything to process
        if (    is_null($result)
            ||  is_a($result, Collection::class) && $result->isEmpty()
        ) {
            return $result;
        }

        // check if there is anything to do process it through
        if ($this->postProcessors->isEmpty()) return $result;


        // for each Model, instantiate and apply the processors
        if (is_a($result, Collection::class)) {

            $result->transform(function ($model) {
                return $this->applyPostProcessorsToModel($model);
            });

        } elseif (is_a($result, AbstractPaginator::class)) {
            // result is paginate() result
            // do not apply postprocessing for now (how would we even do it?)
            return $result;

        } else {
            // result is a model
            $result = $this->applyPostProcessorsToModel($result);
        }

        return $result;
    }

    /**
     * Applies the currently active postprocessors to a model
     *
     * @param Model $model
     * @return Model
     */
    protected function applyPostProcessorsToModel(Model $model)
    {
        foreach ($this->postProcessors as $processorClass => $parameters) {

            // if a processor class was added as a value instead of a key, it
            // does not have parameters
            if (is_numeric($processorClass)) {
                $processorClass = $parameters;
                $parameters     = null;
            }

            $processor = $this->makePostProcessor($processorClass, $parameters);

            $model = $processor->process($model);
        }

        return $model;
    }

    /**
     * @param string $processor
     * @param mixed  $parameters flexible parameter input can be string, array or closure that generates either
     * @return PostProcessorInterface
     */
    protected function makePostProcessor($processor, $parameters = null)
    {
        // no parameters? simple make
        if (is_null($parameters)) {

            $parameters = [];

        } elseif (is_callable($parameters)) {

            $parameters = $parameters();
        }

        if ( ! is_array($parameters)) {

            $parameters = [ $parameters ];
        }


        /** @var PostProcessorInterface $instance */
        if ( ! empty($parameters)) {

            $reflectionClass = new ReflectionClass($processor);

            $instance = $reflectionClass->newInstanceArgs($parameters);

        } else {

            $instance = app($processor);
        }

        return $instance;
    }


    // -------------------------------------------------------------------------
    //      Attribute hiding
    // -------------------------------------------------------------------------

    /**
     * Unhide an otherwise hidden attribute (in $hidden array)
     *
     * Note that these count on only the model's 'hidden' array to be set,
     * if a model whitelists with visible, it won't work as expected
     *
     * @param  string $attribute name of the attribute to unhide
     * @return $this
     */
    public function unhideAttribute($attribute)
    {
        if ( ! in_array($attribute, $this->extraUnhidden)) {

            $this->extraUnhidden[] = $attribute;
        }

        return $this;
    }

    /**
     * @param array|Arrayable $attributes
     * @return $this
     */
    public function unhideAttributes($attributes)
    {
        if ( ! empty($attributes)) {

            foreach ($attributes as $attribute) {

                $this->unhideAttribute($attribute);
            }
        }

        return $this;
    }

    /**
     * Hide an otherwise visible attribute (in $hidden array)
     *
     * Note that these count on only the model's 'hidden' array to be set,
     * if a model whitelists with visible, it won't work as expected
     *
     * @param  string $attribute name of the attribute to hide
     * @return $this
     */
    public function hideAttribute($attribute)
    {
        if (($key = array_search($attribute, $this->extraUnhidden)) !== false) {

            unset($this->extraUnhidden[ $key ]);

        } else {

            if ( ! in_array($attribute, $this->extraHidden)) {
                $this->extraHidden[] = $attribute;
            }
        }

        return $this;
    }

    /**
     * @param array|Arrayable $attributes
     * @return $this
     */
    public function hideAttributes($attributes)
    {
        if ( ! empty($attributes)) {

            foreach ($attributes as $attribute) {

                $this->hideAttribute($attribute);
            }
        }

        return $this;
    }

    /**
     * Resets any hidden or unhidden attribute changes
     */
    public function resetHiddenAttributes()
    {
        $this->extraHidden   = [];
        $this->extraUnhidden = [];
    }


    // -------------------------------------------------------------------------
    //      Overrides for applying postprocessing
    // -------------------------------------------------------------------------

    /**
     * Override
     *
     * @param array $columns
     * @return Model|null
     */
    public function first($columns = ['*'])
    {
        return $this->postProcess( parent::first($columns) );
    }

    /**
     * Override
     *
     * @param array $columns
     * @return Model
     * @throws ModelNotFoundException
     */
    public function firstOrFail($columns = ['*'])
    {
        return $this->postProcess( parent::firstOrFail($columns) );
    }

    /**
     * Override
     *
     * @param array $columns
     * @return mixed
     */
    public function all($columns = ['*'])
    {
        return $this->postProcess( parent::all($columns) );
    }

    /**
     * @param int $perPage
     * @param array $columns
     * @param string $pageName
     * @param null $page
     * @return LengthAwarePaginator|null
     */
    public function paginate($perPage = 1, $columns = ['*'], $pageName = 'page', $page = null)
    {
        return $this->postProcess( parent::paginate($perPage, $columns, $pageName, $page) );
    }

    /**
     * @param  mixed       $id
     * @param  array       $columns
     * @param  string|null $attribute
     * @return Model|null
     */
    public function find($id, $columns = ['*'], $attribute = null)
    {
        return $this->postProcess( parent::find($id, $columns, $attribute) );
    }

    /**
     * Override
     *
     * @param       $id
     * @param array $columns
     * @return Model
     * @throws ModelNotFoundException
     */
    public function findOrFail($id, $columns = ['*'])
    {
        return $this->postProcess( parent::findOrFail($id, $columns) );
    }

    /**
     * Override
     *
     * @param       $attribute
     * @param       $value
     * @param array $columns
     * @return Model|Null
     */
    public function findBy($attribute, $value, $columns = ['*'])
    {
        return $this->postProcess( parent::findBy($attribute, $value, $columns) );
    }
    /**
     * Override
     *
     * @param       $attribute
     * @param       $value
     * @param array $columns
     * @return mixed
     */
    public function findAllBy($attribute, $value, $columns = ['*'])
    {
        return $this->postProcess( parent::findAllBy($attribute, $value, $columns) );
    }
    /**
     * Override
     *
     * @param array $where
     * @param array $columns
     * @param bool  $or
     *
     * @return \Illuminate\Database\Eloquent\Collection|null
     */
    public function findWhere($where, $columns = ['*'], $or = false)
    {
        return $this->postProcess( parent::findWhere($where, $columns, $or) );
    }


    /**
     * Applies callback to query for easier elaborate custom queries
     * on all() calls.
     *
     * @param Closure $callback must return query/builder compatible
     * @param array   $columns
     * @return Collection
     * @throws InvalidArgumentException
     */
    public function allCallback(Closure $callback, $columns = ['*'])
    {
        return $this->postProcess( parent::allCallback($callback, $columns) );
    }

    /**
     * Applies callback to query for easier elaborate custom queries
     * on find (actually: ->first()) calls.
     *
     * @param Closure $callback must return query/builder compatible
     * @param array   $columns
     * @return Collection
     * @throws InvalidArgumentException
     */
    public function findCallback(Closure $callback, $columns = ['*'])
    {
        return $this->postProcess( parent::findCallback($callback, $columns) );
    }

}

Zerion Mini Shell 1.0