Completed
Push — extensions-support ( 972b2b...906276 )
by Guido
03:56
created

Tree::addDefaults()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 18
ccs 14
cts 14
cp 1
rs 8.8571
cc 5
eloc 9
nc 16
nop 0
crap 5
1
<?php
2
3
namespace LaravelDoctrine\Fluent\Extensions\Gedmo;
4
5
use Gedmo\Exception\InvalidMappingException;
6
use Gedmo\Tree\Mapping\Driver\Fluent as FluentDriver;
7
use LaravelDoctrine\Fluent\Buildable;
8
use LaravelDoctrine\Fluent\Builders\Builder;
9
use LaravelDoctrine\Fluent\Extensions\ExtensibleClassMetadata;
10
use LaravelDoctrine\Fluent\Extensions\Extension;
11
use LaravelDoctrine\Fluent\Fluent;
12
13
class Tree implements Buildable, Extension
14
{
15
    const MACRO_METHOD = 'tree';
16
17
    /**
18
     * List of tree strategies available
19
     *
20
     * @var array
21
     */
22
    private $strategies = [
23
        'nested',
24
        'closure',
25
        'materializedPath',
26
    ];
27
28
    /**
29
     * @var Fluent
30
     */
31
    private $builder;
32
33
    /**
34
     * @var ExtensibleClassMetadata
35
     */
36
    protected $classMetadata;
37
38
    /**
39
     * @var string
40
     */
41
    protected $strategy;
42
43
    /**
44
     * @var string
45
     */
46
    protected $left;
47
48
    /**
49
     * @var string
50
     */
51
    protected $right;
52
53
    /**
54
     * @var string
55
     */
56
    protected $level;
57
58
    /**
59
     * @var string
60
     */
61
    protected $root;
62
63
    /**
64
     * @var bool
65
     */
66
    protected $activateLocking = false;
67
68
    /**
69
     * @var int
70
     */
71
    protected $lockingTimeout = 3;
72
73
    /**
74
     * @var string
75
     */
76
    protected $closure;
77
78
    /**
79
     * @var bool
80
     */
81
    private $autoComplete = false;
82
83
    /**
84
     * @param Fluent $builder
85
     * @param string $strategy
86
     * @param bool   $autoComplete
87
     */
88 10
    public function __construct(Fluent $builder, $strategy = 'nested', $autoComplete = false)
89
    {
90 10
        $this->builder       = $builder;
91 10
        $this->classMetadata = $builder->getBuilder()->getClassMetadata();
92 10
        $this->strategy      = $strategy;
93 10
        $this->autoComplete  = $autoComplete;
94 10
    }
95
96
    /**
97
     * Enable extension
98
     */
99 83
    public static function enable()
100
    {
101
        $macro = function (Fluent $fluent, $strategy = 'nested', $callback = null, $autoComplete = false) {
102 3
            $tree = new static($fluent, $strategy, $autoComplete);
103
104 3
            if (is_callable($callback)) {
105 1
                call_user_func($callback, $tree);
106 1
            }
107
108 3
            return $tree;
109 83
        };
110
111 83
        Builder::macro(self::MACRO_METHOD, $macro);
112 83
        Builder::macro('nestedSet', function (Fluent $fluent, $callback = null) use ($macro) {
113 2
            return $macro($fluent, 'nested', $callback, true);
114 83
        });
115
116 83
        TreeLeft::enable();
117 83
        TreeRight::enable();
118 83
        TreeLevel::enable();
119 83
        TreeRoot::enable();
120 83
        TreeParent::enable();
121 83
        TreePath::enable();
122 83
        TreePathSource::enable();
123 83
        TreePathHash::enable();
124 83
        TreeLockTime::enable();
125 83
    }
126
127
    /**
128
     * @param string      $field
129
     * @param string      $type
130
     * @param string|null $column
131
     *
132
     * @return $this
133
     */
134 4
    public function root($field = 'root', $type = 'integer', $column = null)
135
    {
136 4
        $this->mapField($type, $field, $column, true);
137
138 4
        $this->root = $field;
139
140 4
        return $this;
141
    }
142
143
    /**
144
     * @param string      $field
145
     * @param string      $type
146
     * @param string|null $column
147
     *
148
     * @return $this
149
     */
150 4
    public function left($field = 'left', $type = 'integer', $column = null)
151
    {
152 4
        $this->mapField($type, $field, $column);
153
154 4
        $this->left = $field;
155
156 4
        return $this;
157
    }
158
159
    /**
160
     * @param string      $field
161
     * @param string      $type
162
     * @param string|null $column
163
     *
164
     * @return $this
165
     */
166 4
    public function right($field = 'right', $type = 'integer', $column = null)
167
    {
168 4
        $this->mapField($type, $field, $column);
169
170 4
        $this->right = $field;
171
172 4
        return $this;
173
    }
174
175
    /**
176
     * @param string      $field
177
     * @param string      $type
178
     * @param string|null $column
179
     *
180
     * @return $this
181
     */
182 4
    public function level($field = 'level', $type = 'integer', $column = null)
183
    {
184 4
        $this->mapField($type, $field, $column);
185
186 4
        $this->level = $field;
187
188 4
        return $this;
189
    }
190
191
    /**
192
     * Execute the build process
193
     */
194 7
    public function build()
195
    {
196 7
        if (!in_array($this->strategy, $this->strategies)) {
197 1
            throw new InvalidMappingException("Tree type: $this->strategy is not available.");
198
        }
199
200 6
        if ($this->autoComplete) {
201 3
            $this->addDefaults();
202 3
        }
203
204 6
        $this->classMetadata->appendExtension($this->getExtensionName(), [
205 6
            'root'             => $this->root,
206 6
            'level'            => $this->level,
207 6
            'right'            => $this->right,
208 6
            'left'             => $this->left,
209 6
            'strategy'         => $this->strategy,
210 6
            'activate_locking' => $this->activateLocking,
211 6
            'locking_timeout'  => $this->lockingTimeout,
212 6
            'closure'          => $this->closure,
213 6
        ]);
214 6
    }
215
216
    /**
217
     * Return the name of the actual extension.
218
     *
219
     * @return string
220
     */
221 6
    public function getExtensionName()
222
    {
223 6
        return FluentDriver::EXTENSION_NAME;
224
    }
225
226
    /**
227
     * @param bool $activateLocking
228
     *
229
     * @return Tree
230
     */
231 1
    public function activateLocking($activateLocking = true)
232
    {
233 1
        $this->activateLocking = $activateLocking;
234
235 1
        return $this;
236
    }
237
238
    /**
239
     * @param string $strategy
240
     *
241
     * @return Tree
242
     */
243 2
    public function strategy($strategy)
244
    {
245 2
        $this->strategy = $strategy;
246
247 2
        return $this;
248
    }
249
250
    /**
251
     * @param int $lockingTimeout
252
     *
253
     * @return Tree
254
     */
255 2
    public function lockingTimeout($lockingTimeout)
256
    {
257 2
        if ($lockingTimeout < 1) {
258 1
            throw new InvalidMappingException("Tree Locking Timeout must be at least of 1 second.");
259
        }
260
261 1
        $this->lockingTimeout = $lockingTimeout;
262
263 1
        return $this;
264
    }
265
266
    /**
267
     * @param string $closure
268
     *
269
     * @return Tree
270
     */
271 1
    public function closure($closure)
272
    {
273 1
        $this->closure = $closure;
274
275 1
        return $this;
276
    }
277
278
    /**
279
     * @param string $type
280
     * @param string $field
281
     * @param string $column
282
     * @param bool   $nullable
283
     */
284 4
    private function mapField($type, $field, $column = null, $nullable = false)
285
    {
286 4
        $field = $this->builder->field($type, $field)->nullable($nullable);
287
288 4
        if ($column) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $column of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
289
            $field->name($column);
290
        }
291 4
    }
292
293
    /**
294
     * Add default values to all required fields.
295
     *
296
     * @return void
297
     */
298 3
    private function addDefaults()
299
    {
300 3
        if (!$this->root) {
301 2
            $this->root('root');
302 2
        }
303
304 3
        if (!$this->level) {
305 3
            $this->level('level');
306 3
        }
307
308 3
        if (!$this->left) {
309 1
            $this->left('left');
310 1
        }
311
312 3
        if (!$this->right) {
313 1
            $this->right('right');
314 1
        }
315 3
    }
316
}
317