Ellrion
9/22/2014 - 10:37 AM

Laravel 4 Model GlobalScope

Laravel 4 Model GlobalScope

<?php

trait ActivityStatusTrait
{
    public static function bootActivityStatusTrait()
    {
        static::addGlobalScope(new ActivityStatusScope);
    }

    /**
     * Set active status fore inactive model instance.
     *
     * @return bool|null
     */
    public function activate()
    {
        if ($this->fireModelEvent('activating') === false) {
            return false;
        }

        $this->{$this->getStatusColumn()} = ActivityStatusScope::ACTIVE;

        $result = $this->save();

        $this->fireModelEvent('activated', false);

        return $result;
    }

    /**
     * Set inactive status fore active model instance.
     *
     * @return bool|null
     */
    public function deactivate()
    {
        if ($this->fireModelEvent('deactivating') === false) {
            return false;
        }

        $this->{$this->getStatusColumn()} = ActivityStatusScope::INACTIVE;

        $result = $this->save();

        $this->fireModelEvent('deactivated', false);

        return $result;
    }

    /**
     * Determine if the model instance has been inactive.
     *
     * @return bool
     */
    public function isInactive()
    {
        return (int)$this->{$this->getStatusColumn()} !== (int)ActivityStatusScope::ACTIVE;
    }

    /**
     * Get a new query builder that includes inactive items.
     *
     * @return \Illuminate\Database\Eloquent\Builder|static
     */
    public static function withInactive()
    {
        return (new static)->newQueryWithoutScope(new ActivityStatusScope);
    }

    /**
     * Get a new query builder that only includes inactive items.
     *
     * @return \Illuminate\Database\Eloquent\Builder|static
     */
    public static function onlyInactive()
    {
        $instance = new static;

        $column = $instance->getQualifiedStatusColumn();

        return $instance->newQueryWithoutScope(new ActivityStatusScope())
            ->where($column, '!=', ActivityStatusScope::ACTIVE);
    }

    /**
     * Register a activating model event with the dispatcher.
     *
     * @param  \Closure|string  $callback
     * @return void
     */
    public static function activating($callback)
    {
        static::registerModelEvent('activating', $callback);
    }

    /**
     * Register a activated model event with the dispatcher.
     *
     * @param  \Closure|string  $callback
     * @return void
     */
    public static function activated($callback)
    {
        static::registerModelEvent('activated', $callback);
    }

    /**
     * Register a deactivating model event with the dispatcher.
     *
     * @param  \Closure|string  $callback
     * @return void
     */
    public static function deactivating($callback)
    {
        static::registerModelEvent('deactivating', $callback);
    }

    /**
     * Register a deactivated model event with the dispatcher.
     *
     * @param  \Closure|string  $callback
     * @return void
     */
    public static function deactivated($callback)
    {
        static::registerModelEvent('deactivated', $callback);
    }

    /**
     * Get the name of the "status" column.
     *
     * @return string
     */
    public function getStatusColumn()
    {
        return defined('static::STATUS_FIELD') ? static::STATUS_FIELD : ActivityStatusScope::STATUS_FIELD;
    }

    /**
     * Get the fully qualified "status" column.
     *
     * @return string
     */
    public function getQualifiedStatusColumn()
    {
        return $this->getTable().'.'.$this->getStatusColumn();
    }

} 
<?php

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\ScopeInterface;

class ActivityStatusScope
implements ScopeInterface
{
    const STATUS_FIELD = 'status';
    const ACTIVE = 1;
    const INACTIVE = 0;

    /**
     * All of the extensions to be added to the builder.
     *
     * @var array
     */
    protected $extensions = ['Deactivate', 'Activate', 'WithInactive', 'OnlyInactive'];

    /**
     * Apply the scope to a given Eloquent query builder.
     *
     * @param  Builder $builder
     * @return void
     */
    public function apply(Builder $builder)
    {
        $model = $builder->getModel();
        $builder->where($this->getQualifiedStatusColumn($model), self::ACTIVE);
        $this->extend($builder);
    }

    /**
     * Remove the scope from the given Eloquent query builder.
     *
     * @param  Builder $builder
     * @return void
     */
    public function remove(Builder $builder)
    {
        $model = $builder->getModel();
        $column = $this->getQualifiedStatusColumn($model);

        $query = $builder->getQuery();
        $bindings = $query->getBindings();
        foreach ((array) $query->wheres as $key => $where) {
            if ('basic' === strtolower($where['type']) && $column === $where['column'] && '=' === $where['operator']) {
                if ( $bindings[$key] == $where['value'] ) {
                    unset($bindings[$key]);
                }
                unset($query->wheres[$key]);

                $query->wheres = array_values($query->wheres);
            }
        }
        $query->wheres = array_values($query->wheres);
        $query->setBindings(array_values($bindings));
    }

    /**
     * Extend the query builder with the needed functions.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @return void
     */
    public function extend(Builder $builder)
    {
        foreach ($this->extensions as $extension) {
            $this->{"add{$extension}"}($builder);
        }
    }

    protected function addDeactivate(Builder $builder)
    {
        $builder->macro('deactivate', function(Builder $builder) {
                return $builder->update([$this->getStatusColumn($builder->getModel()) => self::INACTIVE]);
            });
    }

    protected function addActivate(Builder $builder)
    {
        $builder->macro('activate', function(Builder $builder) {
                $builder->withInactive();

                return $builder->update([$this->getStatusColumn($builder->getModel()) => self::ACTIVE]);
            });
    }

    protected function addWithInactive(Builder $builder)
    {
        $builder->macro('withInactive', function(Builder $builder) {
                $this->remove($builder);

                return $builder;
            });
    }

    protected function addOnlyInactive(Builder $builder)
    {
        $builder->macro('onlyInactive', function(Builder $builder) {
                $this->remove($builder);

                $builder->getQuery()->where(
                    $this->getStatusColumn($builder->getModel())
                    , '!='
                    , self::ACTIVE
                );

                return $builder;

            });
    }

    protected function getQualifiedStatusColumn(\Illuminate\Database\Eloquent\Model $model)
    {
        return method_exists($model, 'getQualifiedStatusColumn')
            ? $model->getQualifiedStatusColumn()
            : $model->getTable().'.'.$this->getStatusColumn($model);
    }

    protected function getStatusColumn(\Illuminate\Database\Eloquent\Model $model)
    {
        return method_exists($model, 'getStatusColumn')
            ? $model->getStatusColumn()
            : self::STATUS_FIELD;
    }

}