Completed
Push — 1.1 ( d166b0...e7f438 )
by Patrick
11:31 queued 07:46
created

TreeStrategy::enable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
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\Extensions\ExtensibleClassMetadata;
9
use LaravelDoctrine\Fluent\Extensions\Extension;
10
use LaravelDoctrine\Fluent\Fluent;
11
12
abstract class TreeStrategy implements Buildable, Extension
13
{
14
    /**
15
     * @var string
16
     */
17
    protected $parent;
18
19
    /**
20
     * @var string
21
     */
22
    protected $level;
23
24
    /**
25
     * @var Fluent
26
     */
27
    protected $builder;
28
29
    /**
30
     * @param Fluent $builder
31
     */
32
    public function __construct(Fluent $builder)
33
    {
34
        $this->builder = $builder;
35
    }
36
37
    /**
38
     * Enable extension
39
     */
40
    public static function enable()
41
    {
42
        TreeLevel::enable();
43
        TreeSelfReference::enableParent();
44
    }
45
46
    /**
47
     * @param string        $field
48
     * @param string        $type
49
     * @param callable|null $callback
50
     *
51
     * @throws InvalidMappingException
52
     * @return $this
53
     */
54 View Code Duplication
    public function level($field = 'level', $type = 'integer', callable $callback = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
55
    {
56
        $this->validateNumericField($type, $field);
57
58
        $this->mapField($type, $field, $callback);
59
60
        $this->level = $field;
61
62
        return $this;
63
    }
64
65
    /**
66
     * @param string        $field
67
     * @param callable|null $callback
68
     *
69
     * @return $this
70
     */
71
    public function parent($field = 'parent', callable $callback = null)
72
    {
73
        $this->addSelfReferencingRelation($field, $callback);
74
75
        $this->parent = $field;
76
77
        return $this;
78
    }
79
80
    /**
81
     * {@inheritdoc}
82
     */
83
    public function build()
84
    {
85
        $this->defaults();
86
87
        $this->getClassMetadata()->mergeExtension($this->getExtensionName(), $this->getValues());
88
    }
89
90
    /**
91
     * Return the name of the actual extension.
92
     *
93
     * @return string
94
     */
95
    protected function getExtensionName()
96
    {
97
        return FluentDriver::EXTENSION_NAME;
98
    }
99
100
    /**
101
     * @param string        $type
102
     * @param string        $field
103
     * @param callable|null $callback
104
     * @param bool|false    $nullable
105
     */
106
    protected function mapField($type, $field, callable $callback = null, $nullable = false)
107
    {
108
        $this->builder->field($type, $field, $callback)->nullable($nullable);
109
    }
110
111
    /**
112
     * @param string $type
113
     * @param string $field
114
     *
115
     * @throws InvalidMappingException
116
     */
117
    protected function validateNumericField($type, $field)
118
    {
119
        if (!in_array($type, ['integer', 'bigint', 'smallint'])) {
120
            throw new InvalidMappingException("Invalid type [$type] for the [$field] field. Must be a (small, big) integer type.");
121
        }
122
    }
123
124
    /**
125
     * Returns the name of the mapped class.
126
     *
127
     * @return string
128
     */
129
    protected function myself()
130
    {
131
        return $this->getClassMetadata()->name;
132
    }
133
134
    /**
135
     * @param string        $field
136
     * @param callable|null $callback
137
     */
138
    protected function addSelfReferencingRelation($field, callable $callback = null)
139
    {
140
        $this->builder->belongsTo($this->myself(), $field, $callback)->nullable();
141
    }
142
143
    /**
144
     * @return ExtensibleClassMetadata
145
     */
146
    protected function getClassMetadata()
147
    {
148
        return $this->builder->getBuilder()->getClassMetadata();
149
    }
150
151
    /**
152
     * @return array
153
     */
154
    protected function getValues()
155
    {
156
        $values = [];
157
158
        if ($this->parent) {
159
            $values['parent'] = $this->parent;
160
        }
161
162
        if ($this->level) {
163
            $values['level'] = $this->level;
164
        }
165
166
        return $values;
167
    }
168
169
    /**
170
     * Check if a given key is already configured for this extension.
171
     *
172
     * @param string $key
173
     *
174
     * @return bool
175
     */
176
    protected function alreadyConfigured($key)
177
    {
178
        $config = $this->getClassMetadata()->getExtension($this->getExtensionName());
179
180
        return isset($config[$key]);
181
    }
182
183
    /**
184
     * Check if parent is missing from both configuration and the current tree strategy builder.
185
     *
186
     * @return bool
187
     */
188
    protected function isMissingParent()
189
    {
190
        return !$this->alreadyConfigured('parent') && !$this->parent;
191
    }
192
193
    /**
194
     * Set the default fields to fill if they were not configured.
195
     * All Tree strategies share one common required field: the parent reference.
196
     *
197
     * @return void
198
     */
199
    protected function defaults()
200
    {
201
        if ($this->isMissingParent()) {
202
            $this->parent();
203
        }
204
    }
205
}
206