Completed
Pull Request — 2.6 (#3147)
by
unknown
10:56 queued 06:16
created

Index::isFullfilledBy()   C

Complexity

Conditions 12
Paths 14

Size

Total Lines 45
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 45
ccs 18
cts 18
cp 1
rs 5.1612
c 0
b 0
f 0
cc 12
eloc 18
nc 14
nop 1
crap 12

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\DBAL\Schema;
21
22
use Doctrine\DBAL\Platforms\AbstractPlatform;
23
24
class Index extends AbstractAsset implements Constraint
25
{
26
    /**
27
     * Asset identifier instances of the column names the index is associated with.
28
     * array($columnName => Identifier)
29
     *
30
     * @var Identifier[]
31
     */
32
    protected $_columns = array();
33
34
    /**
35
     * @var boolean
36
     */
37
    protected $_isUnique = false;
38
39
    /**
40
     * @var boolean
41
     */
42
    protected $_isPrimary = false;
43
44
    /**
45
     * Platform specific flags for indexes.
46
     * array($flagName => true)
47
     *
48
     * @var array
49
     */
50
    protected $_flags = array();
51
52
    /**
53
     * Platform specific options
54
     *
55
     * @todo $_flags should eventually be refactored into options
56
     *
57
     * @var array
58
     */
59
    private $options = array();
60
61
    /**
62
     * @param string   $indexName
63
     * @param string[] $columns
64
     * @param boolean  $isUnique
65
     * @param boolean  $isPrimary
66
     * @param string[] $flags
67
     * @param array    $options
68
     */
69 621
    public function __construct($indexName, array $columns, $isUnique = false, $isPrimary = false, array $flags = array(), array $options = array())
70
    {
71 621
        $isUnique = $isUnique || $isPrimary;
72
73 621
        $this->_setName($indexName);
74 621
        $this->_isUnique = $isUnique;
75 621
        $this->_isPrimary = $isPrimary;
76 621
        $this->options = $options;
77
78 621
        foreach ($columns as $column) {
79 600
            $this->_addColumn($column);
80
        }
81 621
        foreach ($flags as $flag) {
82 18
            $this->addFlag($flag);
83
        }
84 621
    }
85
86
    /**
87
     * @param string $column
88
     *
89
     * @return void
90
     *
91
     * @throws \InvalidArgumentException
92
     */
93 600
    protected function _addColumn($column)
94
    {
95 600
        if (is_string($column)) {
96 600
            $this->_columns[$column] = new Identifier($column);
97
        } else {
98
            throw new \InvalidArgumentException("Expecting a string as Index Column");
99
        }
100 600
    }
101
102
    /**
103
     * {@inheritdoc}
104
     */
105 306
    public function getColumns()
106
    {
107 306
        return array_keys($this->_columns);
108
    }
109
110
    /**
111
     * {@inheritdoc}
112
     */
113 379 View Code Duplication
    public function getQuotedColumns(AbstractPlatform $platform)
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...
114
    {
115 379
        $columns = array();
116
117 379
        foreach ($this->_columns as $column) {
118 371
            $columns[] = $column->getQuotedName($platform);
119
        }
120
121 379
        return $columns;
122
    }
123
124
    /**
125
     * @return string[]
126
     */
127 1
    public function getUnquotedColumns()
128
    {
129 1
        return array_map(array($this, 'trimQuotes'), $this->getColumns());
130
    }
131
132
    /**
133
     * Is the index neither unique nor primary key?
134
     *
135
     * @return boolean
136
     */
137 1
    public function isSimpleIndex()
138
    {
139 1
        return !$this->_isPrimary && !$this->_isUnique;
140
    }
141
142
    /**
143
     * @return boolean
144
     */
145 276
    public function isUnique()
146
    {
147 276
        return $this->_isUnique;
148
    }
149
150
    /**
151
     * @return boolean
152
     */
153 576
    public function isPrimary()
154
    {
155 576
        return $this->_isPrimary;
156
    }
157
158
    /**
159
     * @param string  $columnName
160
     * @param integer $pos
161
     *
162
     * @return boolean
163
     */
164 1
    public function hasColumnAtPosition($columnName, $pos = 0)
165
    {
166 1
        $columnName   = $this->trimQuotes(strtolower($columnName));
167 1
        $indexColumns = array_map('strtolower', $this->getUnquotedColumns());
168
169 1
        return array_search($columnName, $indexColumns) === $pos;
170
    }
171
172
    /**
173
     * Checks if this index exactly spans the given column names in the correct order.
174
     *
175
     * @param array $columnNames
176
     *
177
     * @return boolean
178
     */
179 120
    public function spansColumns(array $columnNames)
180
    {
181 120
        $columns         = $this->getColumns();
182 120
        $numberOfColumns = count($columns);
183 120
        $sameColumns     = true;
184
185 120
        for ($i = 0; $i < $numberOfColumns; $i++) {
186 120
            if ( ! isset($columnNames[$i]) || $this->trimQuotes(strtolower($columns[$i])) !== $this->trimQuotes(strtolower($columnNames[$i]))) {
187 52
                $sameColumns = false;
188
            }
189
        }
190
191 120
        return $sameColumns;
192
    }
193
194
    /**
195
     * Checks if the other index already fulfills all the indexing and constraint needs of the current one.
196
     *
197
     * @param Index $other
198
     *
199
     * @return boolean
200
     */
201 120
    public function isFullfilledBy(Index $other)
202
    {
203
        // allow the other index to be longer or equally large.
204 120
        if (count($other->getColumns()) < count($this->getColumns())) {
205 15
            return false;
206
        }
207
208 118
        if (count($other->getColumns()) != count($this->getColumns())) {
209
            // A special case where an index won't be fullffiled by a longer one:
210
            //    PRIMARY KEY(foo, bar)
211
            //    UNIQUE(foo)
212 9
            if ( ! $this->isPrimary() && $this->isUnique() && $other->isPrimary()) {
213 1
                return false;
214
            }
215
        }
216
217
        // Check if columns are the same, and even in the same order
218 117
        $sameColumns = $this->spansColumns($other->getColumns());
219
220 117
        if ($sameColumns) {
221 86
            if ( ! $this->samePartialIndex($other)) {
222 1
                return false;
223
            }
224
225 86
            if ( ! $this->isUnique() && ! $this->isPrimary()) {
226
                // this is a special case: If the current key is neither primary or unique, any unique or
227
                // primary key will always have the same effect for the index and there cannot be any constraint
228
                // overlaps. This means a primary or unique index can always fulfill the requirements of just an
229
                // index that has no constraints.
230 60
                return true;
231
            }
232
233 26
            if ($other->isPrimary() != $this->isPrimary()) {
234 3
                return false;
235
            }
236
237 24
            if ($other->isUnique() != $this->isUnique()) {
238 1
                return false;
239
            }
240
241 24
            return true;
242
        }
243
244 52
        return false;
245
    }
246
247
    /**
248
     * Detects if the other index is a non-unique, non primary index that can be overwritten by this one.
249
     *
250
     * @param Index $other
251
     *
252
     * @return boolean
253
     */
254 1
    public function overrules(Index $other)
255
    {
256 1
        if ($other->isPrimary()) {
257
            return false;
258 1
        } elseif ($this->isSimpleIndex() && $other->isUnique()) {
259
            return false;
260
        }
261
262 1
        if ($this->spansColumns($other->getColumns()) && ($this->isPrimary() || $this->isUnique()) && $this->samePartialIndex($other)) {
263 1
            return true;
264
        }
265
266 1
        return false;
267
    }
268
269
    /**
270
     * Returns platform specific flags for indexes.
271
     *
272
     * @return string[]
273
     */
274 12
    public function getFlags()
275
    {
276 12
        return array_keys($this->_flags);
277
    }
278
279
    /**
280
     * Adds Flag for an index that translates to platform specific handling.
281
     *
282
     * @example $index->addFlag('CLUSTERED')
283
     *
284
     * @param string $flag
285
     *
286
     * @return Index
287
     */
288 33
    public function addFlag($flag)
289
    {
290 33
        $this->_flags[strtolower($flag)] = true;
291
292 33
        return $this;
293
    }
294
295
    /**
296
     * Does this index have a specific flag?
297
     *
298
     * @param string $flag
299
     *
300
     * @return boolean
301
     */
302 147
    public function hasFlag($flag)
303
    {
304 147
        return isset($this->_flags[strtolower($flag)]);
305
    }
306
307
    /**
308
     * Removes a flag.
309
     *
310
     * @param string $flag
311
     *
312
     * @return void
313
     */
314 1
    public function removeFlag($flag)
315
    {
316 1
        unset($this->_flags[strtolower($flag)]);
317 1
    }
318
319
    /**
320
     * @param string $name
321
     *
322
     * @return boolean
323
     */
324 120
    public function hasOption($name)
325
    {
326 120
        return isset($this->options[strtolower($name)]);
327
    }
328
329
    /**
330
     * @param string $name
331
     *
332
     * @return mixed
333
     */
334 7
    public function getOption($name)
335
    {
336 7
        return $this->options[strtolower($name)];
337
    }
338
339
    /**
340
     * @return array
341
     */
342 12
    public function getOptions()
343
    {
344 12
        return $this->options;
345
    }
346
347
    /**
348
     * Return whether the two indexes have the same partial index
349
     * @param \Doctrine\DBAL\Schema\Index $other
350
     *
351
     * @return boolean
352
     */
353 87
    private function samePartialIndex(Index $other)
354
    {
355 87
        if ($this->hasOption('where') && $other->hasOption('where') && $this->getOption('where') == $other->getOption('where')) {
356 2
            return true;
357
        }
358
359 87
        if ( ! $this->hasOption('where') && ! $other->hasOption('where')) {
360 85
            return true;
361
        }
362
363 2
        return false;
364
    }
365
366
}
367