Passed
Pull Request — master (#1928)
by Corey
03:52 queued 01:10
created

ActionSplitter::__invoke()   A

Complexity

Conditions 6
Paths 8

Size

Total Lines 32
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 32
c 0
b 0
f 0
rs 9.0111
cc 6
nc 8
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 __invoke(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
        foreach ($alter->getActions() as $action) {
81
            if (!$action instanceof $this->conflictClassDual) {
82
                $originalAlter->addAction($action);
83
                continue;
84
            }
85
86
            $found = false;
87
            $matches = $this->conflictFilter;
88
            foreach ($conflictActions as $ca) {
89
                if ($matches($ca, $action)) {
90
                    $found = true;
91
                    break;
92
                }
93
            }
94
95
            if ($found) {
96
                $newAlter->addAction($action);
97
            } else {
98
                $originalAlter->addAction($action);
99
            }
100
        }
101
102
        return [$originalAlter, $newAlter];
103
    }
104
}
105