Completed
Push — master ( 397eee...f113dc )
by Gaetano
22:13 queued 10:37
created

SectionManager::load()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 0
cts 6
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Kaliop\eZMigrationBundle\Core\Executor;
4
5
use eZ\Publish\API\Repository\Values\Content\Section;
6
use Kaliop\eZMigrationBundle\API\Collection\SectionCollection;
7
use Kaliop\eZMigrationBundle\API\MigrationGeneratorInterface;
8
use Kaliop\eZMigrationBundle\Core\Matcher\SectionMatcher;
9
10
/**
11
 * Handles section migrations.
12
 */
13
class SectionManager extends RepositoryExecutor implements MigrationGeneratorInterface
14
{
15
    protected $supportedStepTypes = array('section');
16
    protected $supportedActions = array('create', 'load', 'update', 'delete');
17
18
    /** @var SectionMatcher $sectionMatcher */
19
    protected $sectionMatcher;
20
21
    /**
22
     * @param SectionMatcher $sectionMatcher
23
     */
24
    public function __construct(SectionMatcher $sectionMatcher)
25
    {
26
        $this->sectionMatcher = $sectionMatcher;
27
    }
28
29
    /**
30
     * Handles the section create migration action
31
     */
32
    protected function create($step)
33
    {
34 View Code Duplication
        foreach (array('name', 'identifier') as $key) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
35
            if (!isset($step->dsl[$key])) {
36
                throw new \Exception("The '$key' key is missing in a section creation definition");
37
            }
38
        }
39
40
        $sectionService = $this->repository->getSectionService();
41
42
        $sectionCreateStruct = $sectionService->newSectionCreateStruct();
43
44
        $sectionIdentifier = $this->referenceResolver->resolveReference($step->dsl['identifier']);
45
        $sectionCreateStruct->identifier = $sectionIdentifier;
46
        $sectionCreateStruct->name = $this->referenceResolver->resolveReference($step->dsl['name']);
47
48
        $section = $sectionService->createSection($sectionCreateStruct);
49
50
        $this->setReferences($section, $step);
0 ignored issues
show
Documentation introduced by
$section is of type object<eZ\Publish\API\Re...Values\Content\Section>, but the function expects a object<Object>|object<Ka...ion\AbstractCollection>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
51
52
        return $section;
53
    }
54
55
    protected function load($step)
56
    {
57
        $sectionCollection = $this->matchSections('load', $step);
58
59
        $this->setReferences($sectionCollection, $step);
0 ignored issues
show
Bug introduced by
It seems like $sectionCollection defined by $this->matchSections('load', $step) on line 57 can be null; however, Kaliop\eZMigrationBundle...ecutor::setReferences() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
60
61
        return $sectionCollection;
62
    }
63
64
    /**
65
     * Handles the section update migration action
66
     */
67 View Code Duplication
    protected function update($step)
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...
68
    {
69
        $sectionCollection = $this->matchSections('update', $step);
70
71
        if (count($sectionCollection) > 1 && array_key_exists('references', $step->dsl)) {
72
            throw new \Exception("Can not execute Section update because multiple sections match, and a references section is specified in the dsl. References can be set when only 1 section matches");
73
        }
74
75
        $sectionService = $this->repository->getSectionService();
76
        foreach ($sectionCollection as $key => $section) {
0 ignored issues
show
Bug introduced by
The expression $sectionCollection of type object<Kaliop\eZMigratio...SectionCollection>|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
77
            $sectionUpdateStruct = $sectionService->newSectionUpdateStruct();
78
79
            if (isset($step->dsl['identifier'])) {
80
                $sectionUpdateStruct->identifier = $this->referenceResolver->resolveReference($step->dsl['identifier']);
81
            }
82
            if (isset($step->dsl['name'])) {
83
                $sectionUpdateStruct->name = $this->referenceResolver->resolveReference($step->dsl['name']);
84
            }
85
86
            $section = $sectionService->updateSection($section, $sectionUpdateStruct);
87
88
            $sectionCollection[$key] = $section;
89
        }
90
91
        $this->setReferences($sectionCollection, $step);
0 ignored issues
show
Bug introduced by
It seems like $sectionCollection defined by $this->matchSections('update', $step) on line 69 can be null; however, Kaliop\eZMigrationBundle...ecutor::setReferences() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
92
93
        return $sectionCollection;
94
    }
95
96
    /**
97
     * Handles the section delete migration action
98
     */
99
    protected function delete($step)
100
    {
101
        $sectionCollection = $this->matchSections('delete', $step);
102
103
        $this->setReferences($sectionCollection, $step);
0 ignored issues
show
Bug introduced by
It seems like $sectionCollection defined by $this->matchSections('delete', $step) on line 101 can be null; however, Kaliop\eZMigrationBundle...ecutor::setReferences() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
104
105
        $sectionService = $this->repository->getSectionService();
106
107
        foreach ($sectionCollection as $section) {
0 ignored issues
show
Bug introduced by
The expression $sectionCollection of type object<Kaliop\eZMigratio...SectionCollection>|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
108
            $sectionService->deleteSection($section);
109
        }
110
111
        return $sectionCollection;
112
    }
113
114
    /**
115
     * @param string $action
116
     * @return SectionCollection
117
     * @throws \Exception
118
     */
119 View Code Duplication
    protected function matchSections($action, $step)
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...
120
    {
121
        if (!isset($step->dsl['match'])) {
122
            throw new \Exception("A match condition is required to $action a section");
123
        }
124
125
        // convert the references passed in the match
126
        $match = $this->resolveReferencesRecursively($step->dsl['match']);
127
128
        return $this->sectionMatcher->match($match);
129
    }
130
131
    /**
132
     * @param Section $section
133
     * @param array $references the definitions of the references to set
134
     * @throws \InvalidArgumentException When trying to assign a reference to an unsupported attribute
135
     * @return array key: the reference names, values: the reference values
136
     */
137 View Code Duplication
    protected function getReferencesValues($section, array $references, $step)
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...
138
    {
139
        $refs = array();
140
141
        foreach ($references as $reference) {
142
            switch ($reference['attribute']) {
143
                case 'section_id':
144
                case 'id':
145
                    $value = $section->id;
146
                    break;
147
                case 'section_identifier':
148
                case 'identifier':
149
                    $value = $section->identifier;
150
                    break;
151
                case 'section_name':
152
                case 'name':
153
                    $value = $section->name;
154
                    break;
155
                default:
156
                    throw new \InvalidArgumentException('Section Manager does not support setting references for attribute ' . $reference['attribute']);
157
            }
158
159
            $refs[$reference['identifier']] = $value;
160
        }
161
162
        return $refs;
163
    }
164
165
    /**
166
     * @param array $matchCondition
167
     * @param string $mode
168
     * @param array $context
169
     * @throws \Exception
170
     * @return array
171
     */
172 View Code Duplication
    public function generateMigration(array $matchCondition, $mode, array $context = array())
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...
173
    {
174
        $previousUserId = $this->loginUser($this->getAdminUserIdentifierFromContext($context));
175
        $sectionCollection = $this->sectionMatcher->match($matchCondition);
176
        $data = array();
177
178
        /** @var \eZ\Publish\API\Repository\Values\Content\Section $section */
179
        foreach ($sectionCollection as $section) {
0 ignored issues
show
Bug introduced by
The expression $sectionCollection of type object<Kaliop\eZMigratio...SectionCollection>|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
180
181
            $sectionData = array(
182
                'type' => reset($this->supportedStepTypes),
183
                'mode' => $mode,
184
            );
185
186
            switch ($mode) {
187
                case 'create':
188
                    $sectionData = array_merge(
189
                        $sectionData,
190
                        array(
191
                            'identifier' => $section->identifier,
192
                            'name' => $section->name,
193
                        )
194
                    );
195
                    break;
196
                case 'update':
197
                    $sectionData = array_merge(
198
                        $sectionData,
199
                        array(
200
                            'match' => array(
201
                                SectionMatcher::MATCH_SECTION_ID => $section->id
202
                            ),
203
                            'identifier' => $section->identifier,
204
                            'name' => $section->name,
205
                        )
206
                    );
207
                    break;
208
                case 'delete':
209
                    $sectionData = array_merge(
210
                        $sectionData,
211
                        array(
212
                            'match' => array(
213
                                SectionMatcher::MATCH_SECTION_ID => $section->id
214
                            )
215
                        )
216
                    );
217
                    break;
218
                default:
219
                    throw new \Exception("Executor 'section' doesn't support mode '$mode'");
220
            }
221
222
            $data[] = $sectionData;
223
        }
224
225
        $this->loginUser($previousUserId);
226
        return $data;
227
    }
228
}
229