Completed
Pull Request — master (#15)
by
unknown
07:26
created

NamespacesAwareComparator::compareNamespaces()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 18
ccs 13
cts 13
cp 1
rs 8.8571
cc 5
eloc 10
nc 9
nop 2
crap 5
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 Baleen\Migrations\Delta\Comparator;
21
22
use Baleen\Migrations\Exception\InvalidArgumentException;
23
use Baleen\Migrations\Exception\Version\ComparatorException;
24
use Baleen\Migrations\Migration\Options\Direction;
25
use Baleen\Migrations\Delta\DeltaInterface;
26
27
/**
28
 * Takes the version's namespace into account when sorting
29
 *
30
 * @author Gabriel Somoza <[email protected]>
31
 */
32
final class NamespacesAwareComparator extends AbstractComparator
33
{
34
    /** @var array */
35
    private $namespaces;
36
37
    /** @var ComparatorInterface */
38
    private $fallbackComparator;
39
40
    /**
41
     * NamespacesAwareComparator constructor.
42
     *
43
     * @param ComparatorInterface $fallbackComparator
44
     * @param array $namespaces Namespaces with keys ordered by priority (highest priority first)
45
     *
46
     * @throws ComparatorException
47
     */
48 14
    public function __construct(ComparatorInterface $fallbackComparator, array $namespaces)
49
    {
50 14
        $this->fallbackComparator = $fallbackComparator;
51 14
        $this->setNamespaces($namespaces);
52 13
    }
53
54
    /**
55
     * @param array $namespaces
56
     * @throws ComparatorException
57
     */
58 14
    private function setNamespaces($namespaces)
59
    {
60 14
        if (empty($namespaces)) {
61 1
            throw new ComparatorException('Expected at least one namespace for this comparator.');
62
        }
63
        // normalize namespaces
64 13
        foreach ($namespaces as &$namespace) {
65 13
            $namespace = trim($namespace, '\\') . '\\';
66 13
        }
67 13
        krsort($namespaces); // we search from highest to lowest priority
68 13
        $this->namespaces = $namespaces;
69 13
    }
70
71
    /**
72
     * {@inheritdoc}
73
     *
74
     * Given the following $namespaces passed in the constructor:
75
     *   - Taz (lowest priority)
76
     *   - Bar
77
     *   - Foo (highest priority)
78
     *
79
     * Will produce the following results based on the migration's FQCN:
80
     *   - (Foo\v200012, Bar\v201612) => -1
81
     *   - (Taz\v201612, Foo\v200012) => 1
82
     *   - (FooBar\v201612, Taz\v200012) => 1
83
     *   - (Taz\v201612, Taz\v201601) => delegate to fallback
84
     *   - (FooBar\v201612, FooBar\v200012) => delegate to fallback
85
     *
86
     * @param DeltaInterface $version1
87
     * @param DeltaInterface $version2
88
     *
89
     * @return int
90
     *
91
     * @throws InvalidArgumentException
92
     */
93 12
    public function compare(DeltaInterface $version1, DeltaInterface $version2)
94
    {
95 12
        $class1 = $version1->getMigrationClassName();
96 12
        $class2 = $version2->getMigrationClassName();
97
98 12
        if ($class1 === $class2) {
99
            // exit early in this case
100 2
            return 0;
101
        }
102
103 10
        $res = $this->compareNamespaces($class1, $class2);
104
105
        // null = could not determine order | zero = both orders are equal
106 10
        if (empty($res)) {
107
            // delegate sorting to the fallback comparator
108 2
            $res = call_user_func($this->fallbackComparator, $version1, $version2);
109 2
        }
110 10
        return $res;
111
    }
112
113
    /**
114
     * Compare using namespaces
115
     *
116
     * @param $class1
117
     * @param $class2
118
     * @return int|null
119
     */
120 10
    private function compareNamespaces($class1, $class2)
121
    {
122 10
        $res = null;
123
        // loop from highest namespace priority to lowest
124 10
        foreach ($this->namespaces as $namespace) {
125 10
            if (strpos($class1, $namespace) === 0) {
126 6
                $res = 1;
127 6
            }
128 10
            if (strpos($class2, $namespace) === 0) {
129
                // subtract 1 from $res, setting it to either -1 or 0
130 2
                $res = (int) $res - 1;
131 2
            }
132 10
            if (null !== $res) {
133 8
                break; // exit as soon as we found a sort order
134
            }
135 10
        }
136 10
        return $res;
137
    }
138
}
139