Вход Регистрация
Файл: gapps/vendor/prettus/l5-repository/src/Prettus/Repository/Eloquent/BaseRepository.php
Строк: 671
<?php
namespace PrettusRepositoryEloquent;

use 
Closure;
use 
Exception;
use 
IlluminateContainerContainer as Application;
use 
IlluminateContractsPaginationLengthAwarePaginator;
use 
IlluminateDatabaseEloquentBuilder;
use 
IlluminateDatabaseEloquentModel;
use 
IlluminateSupportCollection;
use 
PrettusRepositoryContractsCriteriaInterface;
use 
PrettusRepositoryContractsPresentable;
use 
PrettusRepositoryContractsPresentableInterface;
use 
PrettusRepositoryContractsPresenterInterface;
use 
PrettusRepositoryContractsRepositoryCriteriaInterface;
use 
PrettusRepositoryContractsRepositoryInterface;
use 
PrettusRepositoryEventsRepositoryEntityCreated;
use 
PrettusRepositoryEventsRepositoryEntityDeleted;
use 
PrettusRepositoryEventsRepositoryEntityUpdated;
use 
PrettusRepositoryExceptionsRepositoryException;
use 
PrettusValidatorContractsValidatorInterface;
use 
PrettusValidatorExceptionsValidatorException;

/**
 * Class BaseRepository
 * @package PrettusRepositoryEloquent
 */
abstract class BaseRepository implements RepositoryInterfaceRepositoryCriteriaInterface
{

    
/**
     * @var Application
     */
    
protected $app;

    
/**
     * @var Model
     */
    
protected $model;

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

    
/**
     * @var PresenterInterface
     */
    
protected $presenter;

    
/**
     * @var ValidatorInterface
     */
    
protected $validator;

    
/**
     * Validation Rules
     *
     * @var array
     */
    
protected $rules null;

    
/**
     * Collection of Criteria
     *
     * @var Collection
     */
    
protected $criteria;

    
/**
     * @var bool
     */
    
protected $skipCriteria false;

    
/**
     * @var bool
     */
    
protected $skipPresenter false;

    
/**
     * @var Closure
     */
    
protected $scopeQuery null;

    
/**
     * @param Application $app
     */
    
public function __construct(Application $app)
    {
        
$this->app $app;
        
$this->criteria = new Collection();
        
$this->makeModel();
        
$this->makePresenter();
        
$this->makeValidator();
        
$this->boot();
    }

    
/**
     *
     */
    
public function boot()
    {

    }

    
/**
     * @throws RepositoryException
     */
    
public function resetModel()
    {
        
$this->makeModel();
    }

    
/**
     * Specify Model class name
     *
     * @return string
     */
    
abstract public function model();

    
/**
     * Specify Presenter class name
     *
     * @return string
     */
    
public function presenter()
    {
        return 
null;
    }

    
/**
     * Specify Validator class name of PrettusValidatorContractsValidatorInterface
     *
     * @return null
     * @throws Exception
     */
    
public function validator()
    {

        if (isset(
$this->rules) && !is_null($this->rules) && is_array($this->rules) && !empty($this->rules)) {
            if (
class_exists('PrettusValidatorLaravelValidator')) {
                
$validator app('PrettusValidatorLaravelValidator');
                if (
$validator instanceof ValidatorInterface) {
                    
$validator->setRules($this->rules);

                    return 
$validator;
                }
            } else {
                throw new 
Exception(trans('repository::packages.prettus_laravel_validation_required'));
            }
        }

        return 
null;
    }

    
/**
     * Set Presenter
     *
     * @param $presenter
     *
     * @return $this
     */
    
public function setPresenter($presenter)
    {
        
$this->makePresenter($presenter);

        return 
$this;
    }

    
/**
     * @return Model
     * @throws RepositoryException
     */
    
public function makeModel()
    {
        
$model $this->app->make($this->model());

        if (!
$model instanceof Model) {
            throw new 
RepositoryException("Class {$this->model()} must be an instance of Illuminate\Database\Eloquent\Model");
        }

        return 
$this->model $model;
    }

    
/**
     * @param null $presenter
     *
     * @return PresenterInterface
     * @throws RepositoryException
     */
    
public function makePresenter($presenter null)
    {
        
$presenter = !is_null($presenter) ? $presenter $this->presenter();

        if (!
is_null($presenter)) {
            
$this->presenter is_string($presenter) ? $this->app->make($presenter) : $presenter;

            if (!
$this->presenter instanceof PresenterInterface) {
                throw new 
RepositoryException("Class {$presenter} must be an instance of Prettus\Repository\Contracts\PresenterInterface");
            }

            return 
$this->presenter;
        }

        return 
null;
    }

    
/**
     * @param null $validator
     *
     * @return null|ValidatorInterface
     * @throws RepositoryException
     */
    
public function makeValidator($validator null)
    {
        
$validator = !is_null($validator) ? $validator $this->validator();

        if (!
is_null($validator)) {
            
$this->validator is_string($validator) ? $this->app->make($validator) : $validator;

            if (!
$this->validator instanceof ValidatorInterface) {
                throw new 
RepositoryException("Class {$validator} must be an instance of Prettus\Validator\Contracts\ValidatorInterface");
            }

            return 
$this->validator;
        }

        return 
null;
    }

    
/**
     * Get Searchable Fields
     *
     * @return array
     */
    
public function getFieldsSearchable()
    {
        return 
$this->fieldSearchable;
    }

    
/**
     * Query Scope
     *
     * @param Closure $scope
     *
     * @return $this
     */
    
public function scopeQuery(Closure $scope)
    {
        
$this->scopeQuery $scope;

        return 
$this;
    }

    
/**
     * Retrieve data array for populate field select
     *
     * @param string $column
     * @param string|null $key
     *
     * @return IlluminateSupportCollection|array
     */
    
public function lists($column$key null)
    {
        
$this->applyCriteria();

        return 
$this->model->lists($column$key);
    }

    
/**
     * Retrieve data array for populate field select
     * Compatible with Laravel 5.3
     * @param string $column
     * @param string|null $key
     *
     * @return IlluminateSupportCollection|array
     */
    
public function pluck($column$key null)
    {
        
$this->applyCriteria();

        return 
$this->model->pluck($column$key);
    }

    
/**
     * Sync relations
     *
     * @param $id
     * @param $relation
     * @param $attributes
     * @param bool $detaching
     * @return mixed
     */
    
public function sync($id$relation$attributes$detaching true)
    {
        return 
$this->find($id)->{$relation}()->sync($attributes$detaching);
    }

    
/**
     * SyncWithoutDetaching
     *
     * @param $id
     * @param $relation
     * @param $attributes
     * @return mixed
     */
    
public function syncWithoutDetaching($id$relation$attributes)
    {
        return 
$this->sync($id$relation$attributesfalse);
    }

    
/**
     * Retrieve all data of repository
     *
     * @param array $columns
     *
     * @return mixed
     */
    
public function all($columns = ['*'])
    {
        
$this->applyCriteria();
        
$this->applyScope();

        if (
$this->model instanceof Builder) {
            
$results $this->model->get($columns);
        } else {
            
$results $this->model->all($columns);
        }

        
$this->resetModel();
        
$this->resetScope();

        return 
$this->parserResult($results);
    }


    
/**
     * Retrieve first data of repository
     *
     * @param array $columns
     *
     * @return mixed
     */
    
public function first($columns = ['*'])
    {
        
$this->applyCriteria();
        
$this->applyScope();

        
$results $this->model->first($columns);

        
$this->resetModel();

        return 
$this->parserResult($results);
    }

    
/**
     * Retrieve first data of repository, or return new Entity
     *
     * @param array $attributes
     *
     * @return mixed
     */
    
public function firstOrNew(array $attributes = [])
    {
        
$this->applyCriteria();
        
$this->applyScope();

        
$temporarySkipPresenter $this->skipPresenter;
        
$this->skipPresenter(true);

        
$model $this->model->firstOrNew($attributes);
        
$this->skipPresenter($temporarySkipPresenter);

        
$this->resetModel();

        return 
$this->parserResult($model);
    }

    
/**
     * Retrieve first data of repository, or create new Entity
     *
     * @param array $attributes
     *
     * @return mixed
     */
    
public function firstOrCreate(array $attributes = [])
    {
        
$this->applyCriteria();
        
$this->applyScope();

        
$temporarySkipPresenter $this->skipPresenter;
        
$this->skipPresenter(true);

        
$model $this->model->firstOrCreate($attributes);
        
$this->skipPresenter($temporarySkipPresenter);

        
$this->resetModel();

        return 
$this->parserResult($model);
    }

    
/**
     * Retrieve all data of repository, paginated
     *
     * @param null $limit
     * @param array $columns
     * @param string $method
     *
     * @return mixed
     */
    
public function paginate($limit null$columns = ['*'], $method "paginate")
    {
        
$this->applyCriteria();
        
$this->applyScope();
        
$limit is_null($limit) ? config('repository.pagination.limit'15) : $limit;
        
$results $this->model->{$method}($limit$columns);
        
$results->appends(app('request')->query());
        
$this->resetModel();

        return 
$this->parserResult($results);
    }

    
/**
     * Retrieve all data of repository, simple paginated
     *
     * @param null $limit
     * @param array $columns
     *
     * @return mixed
     */
    
public function simplePaginate($limit null$columns = ['*'])
    {
        return 
$this->paginate($limit$columns"simplePaginate");
    }

    
/**
     * Find data by id
     *
     * @param       $id
     * @param array $columns
     *
     * @return mixed
     */
    
public function find($id$columns = ['*'])
    {
        
$this->applyCriteria();
        
$this->applyScope();
        
$model $this->model->findOrFail($id$columns);
        
$this->resetModel();

        return 
$this->parserResult($model);
    }

    
/**
     * Find data by field and value
     *
     * @param       $field
     * @param       $value
     * @param array $columns
     *
     * @return mixed
     */
    
public function findByField($field$value null$columns = ['*'])
    {
        
$this->applyCriteria();
        
$this->applyScope();
        
$model $this->model->where($field'='$value)->get($columns);
        
$this->resetModel();

        return 
$this->parserResult($model);
    }

    
/**
     * Find data by multiple fields
     *
     * @param array $where
     * @param array $columns
     *
     * @return mixed
     */
    
public function findWhere(array $where$columns = ['*'])
    {
        
$this->applyCriteria();
        
$this->applyScope();

        
$this->applyConditions($where);

        
$model $this->model->get($columns);
        
$this->resetModel();

        return 
$this->parserResult($model);
    }

    
/**
     * Find data by multiple values in one field
     *
     * @param       $field
     * @param array $values
     * @param array $columns
     *
     * @return mixed
     */
    
public function findWhereIn($field, array $values$columns = ['*'])
    {
        
$this->applyCriteria();
        
$this->applyScope();
        
$model $this->model->whereIn($field$values)->get($columns);
        
$this->resetModel();

        return 
$this->parserResult($model);
    }

    
/**
     * Find data by excluding multiple values in one field
     *
     * @param       $field
     * @param array $values
     * @param array $columns
     *
     * @return mixed
     */
    
public function findWhereNotIn($field, array $values$columns = ['*'])
    {
        
$this->applyCriteria();
        
$this->applyScope();
        
$model $this->model->whereNotIn($field$values)->get($columns);
        
$this->resetModel();

        return 
$this->parserResult($model);
    }

    
/**
     * Save a new entity in repository
     *
     * @throws ValidatorException
     *
     * @param array $attributes
     *
     * @return mixed
     */
    
public function create(array $attributes)
    {
        if (!
is_null($this->validator)) {
            
// we should pass data that has been casts by the model
            // to make sure data type are same because validator may need to use
            // this data to compare with data that fetch from database.
            
$attributes $this->model->newInstance()->forceFill($attributes)->makeVisible($this->model->getHidden())->toArray();

            
$this->validator->with($attributes)->passesOrFail(ValidatorInterface::RULE_CREATE);
        }

        
$model $this->model->newInstance($attributes);
        
$model->save();
        
$this->resetModel();

        
event(new RepositoryEntityCreated($this$model));

        return 
$this->parserResult($model);
    }

    
/**
     * Update a entity in repository by id
     *
     * @throws ValidatorException
     *
     * @param array $attributes
     * @param       $id
     *
     * @return mixed
     */
    
public function update(array $attributes$id)
    {
        
$this->applyScope();

        if (!
is_null($this->validator)) {
            
// we should pass data that has been casts by the model
            // to make sure data type are same because validator may need to use
            // this data to compare with data that fetch from database.
            
$attributes $this->model->newInstance()->forceFill($attributes)->makeVisible($this->model->getHidden())->toArray();

            
$this->validator->with($attributes)->setId($id)->passesOrFail(ValidatorInterface::RULE_UPDATE);
        }

        
$temporarySkipPresenter $this->skipPresenter;

        
$this->skipPresenter(true);

        
$model $this->model->findOrFail($id);
        
$model->fill($attributes);
        
$model->save();

        
$this->skipPresenter($temporarySkipPresenter);
        
$this->resetModel();

        
event(new RepositoryEntityUpdated($this$model));

        return 
$this->parserResult($model);
    }

    
/**
     * Update or Create an entity in repository
     *
     * @throws ValidatorException
     *
     * @param array $attributes
     * @param array $values
     *
     * @return mixed
     */
    
public function updateOrCreate(array $attributes, array $values = [])
    {
        
$this->applyScope();

        if (!
is_null($this->validator)) {
            
$this->validator->with($attributes)->passesOrFail(ValidatorInterface::RULE_UPDATE);
        }

        
$temporarySkipPresenter $this->skipPresenter;

        
$this->skipPresenter(true);

        
$model $this->model->updateOrCreate($attributes$values);

        
$this->skipPresenter($temporarySkipPresenter);
        
$this->resetModel();

        
event(new RepositoryEntityUpdated($this$model));

        return 
$this->parserResult($model);
    }

    
/**
     * Delete a entity in repository by id
     *
     * @param $id
     *
     * @return int
     */
    
public function delete($id)
    {
        
$this->applyScope();

        
$temporarySkipPresenter $this->skipPresenter;
        
$this->skipPresenter(true);

        
$model $this->find($id);
        
$originalModel = clone $model;

        
$this->skipPresenter($temporarySkipPresenter);
        
$this->resetModel();

        
$deleted $model->delete();

        
event(new RepositoryEntityDeleted($this$originalModel));

        return 
$deleted;
    }

    
/**
     * Delete multiple entities by given criteria.
     *
     * @param array $where
     *
     * @return int
     */
    
public function deleteWhere(array $where)
    {
        
$this->applyScope();

        
$temporarySkipPresenter $this->skipPresenter;
        
$this->skipPresenter(true);

        
$this->applyConditions($where);

        
$deleted $this->model->delete();

        
event(new RepositoryEntityDeleted($this$this->model->getModel()));

        
$this->skipPresenter($temporarySkipPresenter);
        
$this->resetModel();

        return 
$deleted;
    }

    
/**
     * Check if entity has relation
     *
     * @param string $relation
     *
     * @return $this
     */
    
public function has($relation)
    {
        
$this->model $this->model->has($relation);

        return 
$this;
    }

    
/**
     * Load relations
     *
     * @param array|string $relations
     *
     * @return $this
     */
    
public function with($relations)
    {
        
$this->model $this->model->with($relations);

        return 
$this;
    }

    
/**
     * Add subselect queries to count the relations.
     *
     * @param  mixed $relations
     * @return $this
     */
    
public function withCount($relations)
    {
        
$this->model $this->model->withCount($relations);
        return 
$this;
    }

    
/**
     * Load relation with closure
     *
     * @param string $relation
     * @param closure $closure
     *
     * @return $this
     */
    
public function whereHas($relation$closure)
    {
        
$this->model $this->model->whereHas($relation$closure);

        return 
$this;
    }

    
/**
     * Set hidden fields
     *
     * @param array $fields
     *
     * @return $this
     */
    
public function hidden(array $fields)
    {
        
$this->model->setHidden($fields);

        return 
$this;
    }

    public function 
orderBy($column$direction 'asc')
    {
        
$this->model $this->model->orderBy($column$direction);

        return 
$this;
    }

    
/**
     * Set visible fields
     *
     * @param array $fields
     *
     * @return $this
     */
    
public function visible(array $fields)
    {
        
$this->model->setVisible($fields);

        return 
$this;
    }

    
/**
     * Push Criteria for filter the query
     *
     * @param $criteria
     *
     * @return $this
     * @throws PrettusRepositoryExceptionsRepositoryException
     */
    
public function pushCriteria($criteria)
    {
        if (
is_string($criteria)) {
            
$criteria = new $criteria;
        }
        if (!
$criteria instanceof CriteriaInterface) {
            throw new 
RepositoryException("Class " get_class($criteria) . " must be an instance of Prettus\Repository\Contracts\CriteriaInterface");
        }
        
$this->criteria->push($criteria);

        return 
$this;
    }

    
/**
     * Pop Criteria
     *
     * @param $criteria
     *
     * @return $this
     */
    
public function popCriteria($criteria)
    {
        
$this->criteria $this->criteria->reject(function ($item) use ($criteria) {
            if (
is_object($item) && is_string($criteria)) {
                return 
get_class($item) === $criteria;
            }

            if (
is_string($item) && is_object($criteria)) {
                return 
$item === get_class($criteria);
            }

            return 
get_class($item) === get_class($criteria);
        });

        return 
$this;
    }

    
/**
     * Get Collection of Criteria
     *
     * @return Collection
     */
    
public function getCriteria()
    {
        return 
$this->criteria;
    }

    
/**
     * Find data by Criteria
     *
     * @param CriteriaInterface $criteria
     *
     * @return mixed
     */
    
public function getByCriteria(CriteriaInterface $criteria)
    {
        
$this->model $criteria->apply($this->model$this);
        
$results $this->model->get();
        
$this->resetModel();

        return 
$this->parserResult($results);
    }

    
/**
     * Skip Criteria
     *
     * @param bool $status
     *
     * @return $this
     */
    
public function skipCriteria($status true)
    {
        
$this->skipCriteria $status;

        return 
$this;
    }

    
/**
     * Reset all Criterias
     *
     * @return $this
     */
    
public function resetCriteria()
    {
        
$this->criteria = new Collection();

        return 
$this;
    }

    
/**
     * Reset Query Scope
     *
     * @return $this
     */
    
public function resetScope()
    {
        
$this->scopeQuery null;

        return 
$this;
    }

    
/**
     * Apply scope in current Query
     *
     * @return $this
     */
    
protected function applyScope()
    {
        if (isset(
$this->scopeQuery) && is_callable($this->scopeQuery)) {
            
$callback $this->scopeQuery;
            
$this->model $callback($this->model);
        }

        return 
$this;
    }

    
/**
     * Apply criteria in current Query
     *
     * @return $this
     */
    
protected function applyCriteria()
    {

        if (
$this->skipCriteria === true) {
            return 
$this;
        }

        
$criteria $this->getCriteria();

        if (
$criteria) {
            foreach (
$criteria as $c) {
                if (
$c instanceof CriteriaInterface) {
                    
$this->model $c->apply($this->model$this);
                }
            }
        }

        return 
$this;
    }

    
/**
     * Applies the given where conditions to the model.
     *
     * @param array $where
     * @return void
     */
    
protected function applyConditions(array $where)
    {
        foreach (
$where as $field => $value) {
            if (
is_array($value)) {
                list(
$field$condition$val) = $value;
                
$this->model $this->model->where($field$condition$val);
            } else {
                
$this->model $this->model->where($field'='$value);
            }
        }
    }

    
/**
     * Skip Presenter Wrapper
     *
     * @param bool $status
     *
     * @return $this
     */
    
public function skipPresenter($status true)
    {
        
$this->skipPresenter $status;

        return 
$this;
    }

    
/**
     * Wrapper result data
     *
     * @param mixed $result
     *
     * @return mixed
     */
    
public function parserResult($result)
    {
        if (
$this->presenter instanceof PresenterInterface) {

            if (
$result instanceof Collection || $result instanceof LengthAwarePaginator) {
                
$result->each(function ($model) {
                    if (
$model instanceof Presentable) {
                        
$model->setPresenter($this->presenter);
                    }

                    return 
$model;
                });
            } elseif (
$result instanceof Presentable) {
                
$result $result->setPresenter($this->presenter);
            }

            if (!
$this->skipPresenter) {
                return 
$this->presenter->present($result);
            }
        }

        return 
$result;
    }
}
Онлайн: 1
Реклама