Test Failed
Push — master ( 894c40...e5d2d2 )
by Julien
11:34
created

EagerLoad::getParametersFromArguments()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 10
c 0
b 0
f 0
nc 4
nop 1
dl 0
loc 19
rs 9.9332
1
<?php
2
3
/**
4
 * This file is part of the Zemit Framework.
5
 *
6
 * (c) Zemit Team <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE.txt
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Zemit\Mvc\Model;
13
14
use Phalcon\Mvc\Model\ResultsetInterface;
15
use Phalcon\Mvc\ModelInterface;
16
use Zemit\Mvc\Model\EagerLoading\Loader;
17
18
trait EagerLoad
19
{
20
    abstract public static function find($parameters = null): ResultsetInterface;
21
    
22
    abstract public static function findFirst($parameters = null): ?ModelInterface;
23
    
24
    /**
25
     * <code>
26
     * <?php
27
     *
28
     * $limit  = 100;
29
     * $offset = max(0, $this->request->getQuery('page', 'int') - 1) * $limit;
30
     *
31
     * $manufacturers = Manufacturer::with('Robots.Parts', [
32
     *     'limit' => [$limit, $offset]
33
     * ]);
34
     *
35
     * foreach ($manufacturers as $manufacturer) {
36
     *     foreach ($manufacturer->robots as $robot) {
37
     *         foreach ($robot->parts as $part) { ... }
38
     *     }
39
     * }
40
     *
41
     * </code>
42
     *
43
     * @param mixed ...$arguments
44
     */
45
    public static function findWith(array ...$arguments)
46
    {
47
        $parameters = self::getParametersFromArguments($arguments);
48
        $list = static::find($parameters);
49
        if ($list->count()) {
50
            return Loader::fromResultset($list, ...$arguments);
51
        }
52
        
53
        return $list;
54
    }
55
    
56
    /**
57
     * Same as EagerLoadingTrait::findWith() for a single record
58
     *
59
     * @param mixed ...$arguments
60
     * @return false|\Phalcon\Mvc\ModelInterface
61
     */
62
    public static function findFirstWith(array ...$arguments)
63
    {
64
        $parameters = self::getParametersFromArguments($arguments);
65
        $entity = static::findFirst($parameters);
66
        if ($entity) {
67
            return Loader::fromModel($entity, ...$arguments);
68
        }
69
        
70
        return $entity;
71
    }
72
    
73
    /**
74
     * @deprecated
75
     * Alias of findWith
76
     */
77
    public static function with(array ...$arguments)
78
    {
79
        return self::findWith(...$arguments);
80
    }
81
    
82
    /**
83
     * @deprecated
84
     * Alias of findWith
85
     */
86
    public static function firstWith(array ...$arguments)
87
    {
88
        return self::findWith(...$arguments);
89
    }
90
    
91
    /**
92
     * Call magic method to make the with works in an implicit way
93
     * @todo change it to behavior missingMethods()
94
     */
95
    public static function __callStatic(string $method, array $arguments = [])
96
    {
97
        // Single - FindFirstBy...
98
        if (strpos($method, 'findFirstWithBy') === 0 || strpos($method, 'firstWithBy') === 0) {
99
            
100
            $forwardMethod = str_replace(['findFirstWithBy', 'firstWithBy'], 'findFirstBy', $method);
101
            return self::findFirstWithBy($forwardMethod, $arguments);
102
        }
103
        
104
        // List - FindWithBy...
105
        elseif (strpos($method, 'findWithBy') === 0 || strpos($method, 'withBy') === 0) {
106
    
107
            $forwardMethod = str_replace(['findWithBy', 'withBy'], 'findBy', $method);
108
            return self::findWithBy($forwardMethod, $arguments);
109
        }
110
    
111
        return parent::$method(...$arguments);
112
    }
113
    
114
    /**
115
     * Call native Phalcon FindFirstBy function then eager load relationships from the model
116
     */
117
    private static function findFirstWithBy(string $forwardMethod, array $arguments): ModelInterface
118
    {
119
        $parameters = self::getParametersFromArguments($arguments);
120
        $entity = parent::$forwardMethod($parameters);
121
    
122
        if ($entity) {
123
            assert($entity instanceof ModelInterface);
124
            return Loader::fromModel($entity, ...$arguments);
125
        }
126
    
127
        return $entity;
128
    }
129
    
130
    /**
131
     * Call native Phalcon findBy function then eager load relationships from the resultset
132
     */
133
    private static function findWithBy(string $forwardMethod, array $arguments): ?array
134
    {
135
        $parameters = self::getParametersFromArguments($arguments);
136
        $list = parent::$forwardMethod($parameters);
137
        assert($list instanceof ResultsetInterface);
138
    
139
        if ($list->count()) {
140
            return Loader::fromResultset($list, ...$arguments);
141
        }
142
    
143
        return iterator_to_array($list);
144
    }
145
    
146
    /**
147
     * <code>
148
     *
149
     * $manufacturer = Manufacturer::findFirstById(51);
150
     *
151
     * $manufacturer->load('Robots.Parts');
152
     *
153
     * foreach ($manufacturer->robots as $robot) {
154
     *    foreach ($robot->parts as $part) { ... }
155
     * }
156
     *
157
     * </code>
158
     *
159
     * @param mixed ...$arguments
160
     * @return \Phalcon\Mvc\ModelInterface
161
     */
162
    public function load(array ...$arguments)
163
    {
164
        assert($this instanceof ModelInterface);
165
        return Loader::fromModel($this, ...$arguments);
166
    }
167
    
168
    /**
169
     * Get the query parameters from a list of arguments
170
     * @return mixed
171
     */
172
    public static function getParametersFromArguments(array &$arguments)
173
    {
174
        $parameters = null;
175
        
176
        if (!empty($arguments)) {
177
            $numArgs = count($arguments);
178
            $lastArg = $numArgs - 1;
179
            
180
            if ($numArgs >= 2) {
181
                $parameters = $arguments[$lastArg];
182
                unset($arguments[$lastArg]);
183
                
184
                if (isset($parameters['columns'])) {
185
                    throw new \LogicException('Results from database must be full models, do not use `columns` key');
186
                }
187
            }
188
        }
189
        
190
        return $parameters;
191
    }
192
}
193