Completed
Pull Request — master (#1753)
by
unknown
05:23
created

ActionSplitter::__invoke()   B

Complexity

Conditions 7
Paths 1

Size

Total Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 45
rs 8.2666
c 0
b 0
f 0
cc 7
nc 1
nop 1
1
<?php
2
3
/**
4
 * MIT License
5
 * For full license information, please view the LICENSE file that was distributed with this source code.
6
 */
7
8
namespace Phinx\Db\Plan\Solver;
9
10
use Phinx\Db\Plan\AlterTable;
11
12
/**
13
 * A Plan takes an Intent and transforms it into a sequence of
14
 * instructions that can be correctly executed by an AdapterInterface.
15
 *
16
 * The main focus of Plan is to arrange the actions in the most efficient
17
 * way possible for the database.
18
 */
19
class ActionSplitter
20
{
21
    /**
22
     * The fully qualified class name of the Action class to match for conflicts
23
     *
24
     * @var string
25
     */
26
    protected $conflictClass;
27
28
    /**
29
     * The fully qualified class name of the Action class to match for conflicts, which
30
     * is the dual of $conflictClass. For example `AddColumn` and `DropColumn` are duals.
31
     *
32
     * @var string
33
     */
34
    protected $conflictClassDual;
35
36
    /**
37
     * A callback used to signal the actual presence of a conflict, that will be used to
38
     * partition the AlterTable into non-conflicting parts.
39
     *
40
     * The callback receives as first argument amn instance of $conflictClass and as second
41
     * argument an instance of $conflictClassDual
42
     *
43
     * @var callable
44
     */
45
    protected $conflictFilter;
46
47
    /**
48
     * Comstructor
49
     *
50
     * @param string $conflictClass The fully qualified class name of the Action class to match for conflicts
51
     * @param string $conflictClassDual The fully qualified class name of the Action class to match for conflicts,
52
     * which is the dual of $conflictClass. For example `AddColumn` and `DropColumn` are duals.
53
     * @param callable $conflictFilter The collection of actions to inspect
54
     */
55
    public function __construct($conflictClass, $conflictClassDual, callable $conflictFilter)
56
    {
57
        $this->conflictClass = $conflictClass;
58
        $this->conflictClassDual = $conflictClassDual;
59
        $this->conflictFilter = $conflictFilter;
60
    }
61
62
    /**
63
     * Returs a sequence of AlterTable instructions that are non conflicting
64
     * based on the constructor parameters.
65
     *
66
     * @param \Phinx\Db\Plan\AlterTable $alter The collection of actions to inspect
67
     *
68
     * @return \Phinx\Db\Plan\AlterTable[] A list of AlterTable that can be executed without
69
     * this type of conflict
70
     */
71
    public function split(AlterTable $alter)
72
    {
73
        $conflictActions = array_filter($alter->getActions(), function ($action) {
74
            return $action instanceof $this->conflictClass;
75
        });
76
77
        $originalAlter = new AlterTable($alter->getTable());
78
        $newAlter = new AlterTable($alter->getTable());
79
80
        $actions = array_map(function ($action) use ($conflictActions) {
81
            if (!$action instanceof $this->conflictClassDual) {
82
                return [$action, null];
83
            }
84
85
            $found = false;
86
            $matches = $this->conflictFilter;
87
            foreach ($conflictActions as $ca) {
88
                if ($matches($ca, $action)) {
89
                    $found = true;
90
                    break;
91
                }
92
            }
93
94
            if ($found) {
95
                return [null, $action];
96
            }
97
98
            return [$action, null];
99
        }, $alter->getActions());
100
101
        foreach ($actions as $pair) {
102
            list($original, $new) = $pair;
103
            if ($original) {
104
                $originalAlter->addAction($original);
105
            }
106
            if ($new) {
107
                $newAlter->addAction($new);
108
            }
109
        }
110
111
        return [$originalAlter, $newAlter];
112
    }
113
}
114