Completed
Push — master ( 97fb46...770b11 )
by Gaetano
15:34 queued 07:06
created

ObjectStateManager   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 276
Duplicated Lines 0 %

Test Coverage

Coverage 83.62%

Importance

Changes 0
Metric Value
eloc 123
dl 0
loc 276
ccs 97
cts 116
cp 0.8362
rs 9.36
c 0
b 0
f 0
wmc 38

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B generateMigration() 0 74 8
B update() 0 36 11
A load() 0 7 1
B create() 0 36 7
A getReferencesValues() 0 21 5
A matchObjectStates() 0 10 2
A listAllowedConditions() 0 3 1
A delete() 0 13 2
1
<?php
2
3
namespace Kaliop\eZMigrationBundle\Core\Executor;
4
5
use eZ\Publish\API\Repository\Values\ObjectState\ObjectState;
6
use Kaliop\eZMigrationBundle\Core\Matcher\ObjectStateGroupMatcher;
7
use Kaliop\eZMigrationBundle\Core\Matcher\ObjectStateMatcher;
8
use Kaliop\eZMigrationBundle\API\Collection\ObjectStateCollection;
9
use Kaliop\eZMigrationBundle\API\MigrationGeneratorInterface;
10
use Kaliop\eZMigrationBundle\API\EnumerableMatcherInterface;
11
12
/**
13
 * Handles object-state migrations.
14
 */
15
class ObjectStateManager extends RepositoryExecutor implements MigrationGeneratorInterface, EnumerableMatcherInterface
16
{
17
    /**
18
     * @var array
19
     */
20
    protected $supportedStepTypes = array('object_state');
21
    protected $supportedActions = array('create', 'load', 'update', 'delete');
22
23
    /**
24
     * @var ObjectStateMatcher
25
     */
26
    protected $objectStateMatcher;
27
28
    /**
29
     * @var ObjectStateGroupMatcher
30
     */
31
    protected $objectStateGroupMatcher;
32
33
    /**
34
     * @param ObjectStateMatcher      $objectStateMatcher
35
     * @param ObjectStateGroupMatcher $objectStateGroupMatcher
36
     */
37 96
    public function __construct(ObjectStateMatcher $objectStateMatcher, ObjectStateGroupMatcher $objectStateGroupMatcher)
38
    {
39 96
        $this->objectStateMatcher = $objectStateMatcher;
40 96
        $this->objectStateGroupMatcher = $objectStateGroupMatcher;
41 96
    }
42
43
    /**
44
     * Handles the create step of object state migrations.
45
     *
46
     * @throws \Exception
47
     */
48 1
    protected function create($step)
49
    {
50 1
        foreach (array('object_state_group', 'names', 'identifier') as $key) {
51 1
            if (!isset($step->dsl[$key])) {
52 1
                throw new \Exception("The '$key' key is missing in a object state creation definition");
53
            }
54
        }
55
56 1
        if (!count($step->dsl['names'])) {
57
            throw new \Exception('No object state names have been defined. Need to specify at least one to create the state.');
58
        }
59
60 1
        $objectStateService = $this->repository->getObjectStateService();
61
62 1
        $objectStateGroupId = $step->dsl['object_state_group'];
63 1
        $objectStateGroupId = $this->referenceResolver->resolveReference($objectStateGroupId);
64 1
        $objectStateGroup = $this->objectStateGroupMatcher->matchOneByKey($objectStateGroupId);
65
66 1
        $objectStateIdentifier = $this->referenceResolver->resolveReference($step->dsl['identifier']);
67 1
        $objectStateCreateStruct = $objectStateService->newObjectStateCreateStruct($objectStateIdentifier);
68 1
        $objectStateCreateStruct->defaultLanguageCode = $this->getLanguageCode($step); // was: self::DEFAULT_LANGUAGE_CODE;
69
70 1
        foreach ($step->dsl['names'] as $languageCode => $name) {
71 1
            $objectStateCreateStruct->names[$languageCode] = $name;
72
        }
73 1
        if (isset($step->dsl['descriptions'])) {
74 1
            foreach ($step->dsl['descriptions'] as $languageCode => $description) {
75 1
                $objectStateCreateStruct->descriptions[$languageCode] = $description;
76
            }
77
        }
78
79 1
        $objectState = $objectStateService->createObjectState($objectStateGroup, $objectStateCreateStruct);
80
81 1
        $this->setReferences($objectState, $step);
82
83 1
        return $objectState;
84
    }
85
86
    protected function load($step)
87
    {
88
        $stateCollection = $this->matchObjectStates('load', $step);
89
90
        $this->setReferences($stateCollection, $step);
91
92
        return $stateCollection;
93
    }
94
95
    /**
96
     * Handles the update step of object state migrations.
97
     *
98
     * @throws \Exception
99
     */
100 1
    protected function update($step)
101
    {
102 1
        $stateCollection = $this->matchObjectStates('update', $step);
103
104 1
        if (count($stateCollection) > 1 && array_key_exists('references', $step->dsl)) {
105
            throw new \Exception("Can not execute Object State update because multiple states match, and a references section is specified in the dsl. References can be set when only 1 state matches");
106
        }
107
108 1
        if (count($stateCollection) > 1 && isset($step->dsl['identifier'])) {
109
            throw new \Exception("Can not execute Object State update because multiple states match, and an identifier is specified in the dsl.");
110
        }
111
112 1
        $objectStateService = $this->repository->getObjectStateService();
113
114 1
        foreach ($stateCollection as $state) {
115 1
            $objectStateUpdateStruct = $objectStateService->newObjectStateUpdateStruct();
116
117 1
            if (isset($step->dsl['identifier'])) {
118 1
                $objectStateUpdateStruct->identifier = $this->referenceResolver->resolveReference($step->dsl['identifier']);
119
            }
120 1
            if (isset($step->dsl['names'])) {
121
                foreach ($step->dsl['names'] as $name) {
122
                    $objectStateUpdateStruct->names[$name['languageCode']] = $name['name'];
123
                }
124
            }
125 1
            if (isset($step->dsl['descriptions'])) {
126
                foreach ($step->dsl['descriptions'] as $languageCode => $description) {
127
                    $objectStateUpdateStruct->descriptions[$languageCode] = $description;
128
                }
129
            }
130 1
            $state = $objectStateService->updateObjectState($state, $objectStateUpdateStruct);
131
132 1
            $this->setReferences($state, $step);
133
        }
134
135 1
        return $stateCollection;
136
    }
137
138
    /**
139
     * Handles the deletion step of object state migrations.
140
     */
141 1
    protected function delete($step)
142
    {
143 1
        $stateCollection = $this->matchObjectStates('delete', $step);
144
145 1
        $this->setReferences($stateCollection, $step);
146
147 1
        $objectStateService = $this->repository->getObjectStateService();
148
149 1
        foreach ($stateCollection as $state) {
150 1
            $objectStateService->deleteObjectState($state);
151
        }
152
153 1
        return $stateCollection;
154
    }
155
156
    /**
157
     * @param string $action
158
     * @return ObjectStateCollection
159
     * @throws \Exception
160
     */
161 1
    protected function matchObjectStates($action, $step)
162
    {
163 1
        if (!isset($step->dsl['match'])) {
164
            throw new \Exception("A match condition is required to $action an object state");
165
        }
166
167
        // convert the references passed in the match
168 1
        $match = $this->resolveReferencesRecursively($step->dsl['match']);
169
170 1
        return $this->objectStateMatcher->match($match);
171
    }
172
173
    /**
174
     * @param ObjectState $objectState
175
     * @param array $references the definitions of the references to set
176
     * @throws \InvalidArgumentException When trying to assign a reference to an unsupported attribute
177
     * @return array key: the reference names, values: the reference values
178
     */
179 1
    protected function getReferencesValues($objectState, array $references, $step)
180
    {
181 1
        $refs = array();
182
183 1
        foreach ($references as $reference) {
184 1
            switch ($reference['attribute']) {
185 1
                case 'object_state_id':
186 1
                case 'id':
187 1
                    $value = $objectState->id;
188 1
                    break;
189
                case 'priority':
190
                    $value = $objectState->priority;
191
                    break;
192
                default:
193
                    throw new \InvalidArgumentException('Object State Manager does not support setting references for attribute ' . $reference['attribute']);
194
            }
195
196 1
            $refs[$reference['identifier']] = $value;
197
        }
198
199 1
        return $refs;
200
    }
201
202
    /**
203
     * @param array $matchCondition
204
     * @param string $mode
205
     * @param array $context
206
     * @throws \Exception
207
     * @return array
208
     */
209 3
    public function generateMigration(array $matchCondition, $mode, array $context = array())
210
    {
211 3
        $previousUserId = $this->loginUser($this->getAdminUserIdentifierFromContext($context));
212 3
        $objectStateCollection = $this->objectStateMatcher->match($matchCondition);
213 3
        $data = array();
214
215
        /** @var \eZ\Publish\API\Repository\Values\ObjectState\ObjectState $objectState */
216 3
        foreach ($objectStateCollection as $objectState) {
217
218
            $groupData = array(
219 3
                'type' => reset($this->supportedStepTypes),
220 3
                'mode' => $mode,
221
            );
222
223
            switch ($mode) {
224 3
                case 'create':
225 1
                    $groupData = array_merge(
226 1
                        $groupData,
227
                        array(
228 1
                            'object_state_group' => $objectState->getObjectStateGroup()->identifier,
229 1
                            'identifier' => $objectState->identifier,
230
                        )
231
                    );
232 1
                    break;
233 2
                case 'update':
234 1
                    $groupData = array_merge(
235 1
                        $groupData,
236
                        array(
237
                            'match' => array(
238
                                ObjectStateMatcher::MATCH_OBJECTSTATE_IDENTIFIER =>
239 1
                                    $objectState->getObjectStateGroup()->identifier . '/' . $objectState->identifier
240
                            ),
241 1
                            'identifier' => $objectState->identifier,
242
                        )
243
                    );
244 1
                    break;
245 1
                case 'delete':
246 1
                    $groupData = array_merge(
247 1
                        $groupData,
248
                        array(
249
                            'match' => array(
250
                                ObjectStateMatcher::MATCH_OBJECTSTATE_IDENTIFIER =>
251 1
                                    $objectState->getObjectStateGroup()->identifier . '/' . $objectState->identifier
252
                            )
253
                        )
254
                    );
255 1
                    break;
256
                default:
257
                    throw new \Exception("Executor 'object_state_group' doesn't support mode '$mode'");
258
            }
259
260 3
            if ($mode != 'delete') {
261 2
                $names = array();
262 2
                $descriptions = array();
263 2
                foreach($objectState->languageCodes as $languageCode) {
264 2
                    $names[$languageCode] =  $objectState->getName($languageCode);
265
                }
266 2
                foreach($objectState->languageCodes as $languageCode) {
267 2
                    $descriptions[$languageCode] =  $objectState->getDescription($languageCode);
268
                }
269 2
                $groupData = array_merge(
270 2
                    $groupData,
271
                    array(
272 2
                        'names' => $names,
273 2
                        'descriptions' => $descriptions,
274
                    )
275
                );
276
            }
277
278 3
            $data[] = $groupData;
279
        }
280
281 3
        $this->loginUser($previousUserId);
282 3
        return $data;
283
    }
284
285
    /**
286
     * @return string[]
287
     */
288
    public function listAllowedConditions()
289
    {
290
        return $this->objectStateMatcher->listAllowedConditions();
291
    }
292
}
293