Completed
Branch develop-3.0 (780dc9)
by Mohamed
03:14
created

ModelAbstract::fetcher()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
3
/*
4
 * This file is part of the Tinyissue package.
5
 *
6
 * (c) Mohamed Alsharaf <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Tinyissue\Model;
13
14
use Illuminate\Database\Eloquent\Model;
15
use Tinyissue\Repository\Repository;
16
use Tinyissue\Repository\RepositoryUpdater;
17
18
/**
19
 * Class ModelAbstract
20
 *
21
 * @method \Illuminate\Support\Collection get()
22
 * @method int count()
23
 * @method \Illuminate\Support\Collection pluck($name, $key)
24
 * @method static orderBy($column, $direction = 'asc')
25
 * @method static select($columns = ['*'])
26
 * @method static where($key, $operator, $value = null)
27
 * @method static dropdown($text = 'name', $value = 'id')
28
 * @method static find($id, $columns = ['*'])
29
 * @method static whereIn($column, $values, $boolean = 'and', $not = false)
30
 */
31
abstract class ModelAbstract extends Model
32
{
33
    /**
34
     * @var RepositoryUpdater
35
     */
36
    protected $updater;
37
38
    /**
39
     * @var Repository
40
     */
41
    protected $counter;
42
43
    /**
44
     * @var Repository
45
     */
46
    protected $fetcher;
47
48
    /**
49
     * Factory method to instantiate a repository class based on a type.
50
     *
51
     * @param string $type
52
     *
53
     * @return Repository|RepositoryUpdater
54
     */
55
    protected function factoryRepository($type)
56
    {
57
        if (is_null($this->$type)) {
58
            $class = $this->getRepositoryClassName($type);
59
            $this->$type = new $class($this);
60
61
            if (!$this->$type instanceof RepositoryUpdater && !$this->$type instanceof Repository) {
62
                throw new \DomainException(sprintf('Unable to find the repository class "%s"', $class));
63
            }
64
        }
65
66
        return $this->$type;
67
    }
68
69
    /**
70
     * @param string $type
71
     *
72
     * @return string
73
     */
74
    protected function getRepositoryClassName($type)
75
    {
76
        return str_replace(__NAMESPACE__, 'Tinyissue\\Repository', static::class) . '\\' . ucfirst($type);
77
    }
78
79
    /**
80
     * Get repository for updating / modifying data.
81
     *
82
     * @param User|null $user
83
     *
84
     * @return RepositoryUpdater
85
     */
86
    public function updater(User $user = null)
87
    {
88
        $this->factoryRepository('updater');
89
90
        $this->updater->setUser($user);
91
92
        return $this->updater;
93
    }
94
95
    /**
96
     * get repository class for counting records.
97
     *
98
     * @return Repository
99
     */
100
    public function counter()
101
    {
102
        $this->factoryRepository('counter');
103
104
        return $this->counter;
105
    }
106
107
    /**
108
     * Get repository class for fetching data.
109
     *
110
     * @return Repository
111
     */
112
    public function fetcher()
113
    {
114
        $this->factoryRepository('fetcher');
115
116
        return $this->fetcher;
117
    }
118
119
    /**
120
     * Attempt to proxy the method call to other related classes if possible.
121
     *
122
     * @param string $name
123
     * @param array  $arguments
124
     *
125
     * @return mixed
126
     */
127
    public function __call($name, $arguments)
128
    {
129
        $caller = false;
130
131
        if (strpos($name, 'count') === 0) {
132
            $caller = $this->counter();
133
        }
134
135
        if (strpos($name, 'get') === 0) {
136
            $caller = $this->fetcher();
137
        }
138
139
        if (!is_null($this->updater()) && method_exists($this->updater, $name)) {
140
            $caller = $this->updater();
141
        }
142
143
        if (false !== $caller && method_exists($caller, $name)) {
144
            return $caller->{$name}(...$arguments);
145
        }
146
147
        return parent::__call($name, $arguments);
148
    }
149
150
    /**
151
     * Return instance of the current class.
152
     *
153
     * @param array $attributes
154
     *
155
     * @return static
156
     */
157
    public static function instance(array $attributes = [])
158
    {
159
        $model = new static($attributes);
160
        $model->exists = false;
161
162
        return $model;
163
    }
164
165
    /**
166
     * Returns the aggregate value of a field.
167
     *
168
     * @param string $field
169
     *
170
     * @return int
171
     */
172
    protected function getCountAttribute($field)
173
    {
174
        // if relation is not loaded already, let's do it first
175
        if (!array_key_exists($field, $this->relations)) {
176
            $this->load($field);
177
        }
178
179
        $related = $this->getRelation($field);
180
181
        // then return the count directly
182
        return ($related) ? (int)$related->aggregate : 0;
183
    }
184
}
185