Passed
Push — main ( 4b1d5b...63f1e2 )
by Gaetano
08:10
created

WorkflowServiceInner::executeMigration()   B

Complexity

Conditions 11
Paths 10

Size

Total Lines 32
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 16
nc 10
nop 7
dl 0
loc 32
rs 7.3166
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Kaliop\eZWorkflowEngineBundle\Core;
4
5
use Kaliop\eZMigrationBundle\API\Value\MigrationDefinition;
6
use Kaliop\eZMigrationBundle\API\Value\Migration;
7
use Kaliop\eZMigrationBundle\API\EnumerableReferenceResolverInterface;
8
use Kaliop\eZMigrationBundle\Core\MigrationService;
9
use Kaliop\eZMigrationBundle\Core\ReferenceResolver\PrefixBasedResolverInterface;
10
use Kaliop\eZWorkflowEngineBundle\API\Value\WorkflowDefinition;
11
12
class WorkflowServiceInner extends MigrationService implements PrefixBasedResolverInterface, EnumerableReferenceResolverInterface
13
{
14
    protected $eventPrefix = 'ez_workflow.';
15
    protected $eventEntity = 'workflow';
16
    protected $referenceRegexp = '/^workflow:/';
17
    protected $currentWorkflowName;
18
19
    public function addMigration(MigrationDefinition $migrationDefinition)
20
    {
21
        throw new \Exception("Unsupported operation: direct adding of workflows");
22
    }
23
24
    public function skipMigration(MigrationDefinition $migrationDefinition)
25
    {
26
        throw new \Exception("Unsupported operation: tagging of workflows as skipped");
27
    }
28
29
    /**
30
     * Reimplemented to make sure we always return a WorkflowDefinition
31
     * @param MigrationDefinition $migrationDefinition this should be a WorkflowDefinition really
32
     * @return WorkflowDefinition
33
     * @throws \Exception
34
     */
35
    public function parseMigrationDefinition(MigrationDefinition $migrationDefinition)
36
    {
37
        foreach ($this->DefinitionParsers as $definitionParser) {
38
            if ($definitionParser->supports($migrationDefinition->name)) {
39
                // parse the source file
40
                $migrationDefinition = $definitionParser->parseMigrationDefinition($migrationDefinition);
41
42
                // and make sure we know how to handle all steps
43
                foreach ($migrationDefinition->steps as $step) {
44
                    if (!isset($this->executors[$step->type])) {
45
                        return new WorkflowDefinition(
46
                            $migrationDefinition->name,
47
                            $migrationDefinition->path,
48
                            $migrationDefinition->rawDefinition,
49
                            MigrationDefinition::STATUS_INVALID,
50
                            array(),
51
                            "Can not handle workflow step of type '{$step->type}'",
52
                            isset($migrationDefinition->signalName) ? $migrationDefinition->signalName : null,
53
                            isset($migrationDefinition->runAs) ? $migrationDefinition->runAs : false,
54
                            isset($migrationDefinition->useTransaction) ? $migrationDefinition->useTransaction : false,
55
                            isset($migrationDefinition->avoidRecursion) ? $migrationDefinition->avoidRecursion : false
56
                        );
57
                    }
58
                }
59
60
                return $migrationDefinition;
61
            }
62
        }
63
64
        throw new \Exception("No parser available to parse workflow definition '{$migrationDefinition->name}'");
65
    }
66
67
    /**
68
     * Reimplemented to add more parameters to be stored in the context
69
     *
70
     * @param MigrationDefinition $migrationDefinition
71
     * @param array $migrationContext Supported array keys are: adminUserLogin, defaultLanguageCode, userContentType,
72
     *                                userGroupContentType useTransaction, workflow
73
     *                                was: bool $useTransaction when set to false, no repo transaction will be used to wrap the migration
74
     * @param string $defaultLanguageCode Deprecated - use $migrationContext['defaultLanguageCode']
75
     * @param string|int|false|null $adminLogin Deprecated - use $migrationContext['adminLogin']; when false, current user is used; when null, hardcoded admin account
76
     * @param bool $force Deprecated - use $migrationContext['forceExecution']; when true, execute a migration if it was already in status DONE or SKIPPED (would throw by default)
77
     * @param bool|null $forceSigchildEnabled Deprecated
78
     * @param null|array $workflowParameters Deprecated - use $migrationContext['workflow']
79
     * @throws \Exception
80
     *
81
     * @todo treating a null and false $adminLogin values differently is prone to hard-to-track errors.
82
     *       Shall we use instead -1 to indicate the desire to not-login-as-admin-user-at-all ?
83
     */
84
    public function executeMigration(MigrationDefinition $migrationDefinition, $migrationContext = true,
85
        $defaultLanguageCode = null, $adminLogin = null, $force = false, $forceSigchildEnabled = null, $workflowParameters = null)
86
    {
87
        if ($migrationDefinition->status == MigrationDefinition::STATUS_TO_PARSE) {
88
            $migrationDefinition = $this->parseMigrationDefinition($migrationDefinition);
89
        }
90
91
        if ($migrationDefinition->status == MigrationDefinition::STATUS_INVALID) {
92
            /// @todo !important name of entity should be gotten dynamically (migration vs. workflow)
93
            throw new \Exception("Can not execute migration '{$migrationDefinition->name}': {$migrationDefinition->parsingError}");
94
        }
95
96
        // BC: handling of legacy method call signature
97
        if (!is_array($migrationContext)) {
98
            $useTransaction = $migrationContext;
99
            $migrationContext = $this->migrationContextFromParameters($defaultLanguageCode, $adminLogin, $forceSigchildEnabled, $workflowParameters);
0 ignored issues
show
Bug introduced by
It seems like $defaultLanguageCode can also be of type string; however, parameter $defaultLanguageCode of Kaliop\eZWorkflowEngineB...ContextFromParameters() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

99
            $migrationContext = $this->migrationContextFromParameters(/** @scrutinizer ignore-type */ $defaultLanguageCode, $adminLogin, $forceSigchildEnabled, $workflowParameters);
Loading history...
Bug introduced by
It seems like $adminLogin can also be of type false and integer and string; however, parameter $adminLogin of Kaliop\eZWorkflowEngineB...ContextFromParameters() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

99
            $migrationContext = $this->migrationContextFromParameters($defaultLanguageCode, /** @scrutinizer ignore-type */ $adminLogin, $forceSigchildEnabled, $workflowParameters);
Loading history...
Deprecated Code introduced by
The function Kaliop\eZWorkflowEngineB...ContextFromParameters() has been deprecated: kept for BC ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

99
            $migrationContext = /** @scrutinizer ignore-deprecated */ $this->migrationContextFromParameters($defaultLanguageCode, $adminLogin, $forceSigchildEnabled, $workflowParameters);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
100
        } else {
101
            if ($defaultLanguageCode !== null || $adminLogin !== null || $force !== false || $forceSigchildEnabled !== null
102
                || $workflowParameters !== null
103
            ) {
104
                throw new \Exception("Invalid call to executeMigration: argument types mismatch");
105
            }
106
            $useTransaction = array_key_exists('useTransaction', $migrationContext) ? $migrationContext['useTransaction'] : true;
107
            $migrationContext['workflow'] = $this->workflowMigrationContextFromParameters(
108
                array_key_exists('workflow', $migrationContext) ? $migrationContext['workflow'] : null
109
            );
110
        }
111
112
        // set migration as begun - has to be in own db transaction
113
        $migration = $this->storageHandler->startMigration($migrationDefinition, $force);
114
115
        $this->executeMigrationInner($migration, $migrationDefinition, $migrationContext, 0, $useTransaction, $adminLogin);
116
    }
117
118
    /**
119
     * Reimplemented to store the name of the current executing workflow
120
     * @param Migration $migration
121
     * @param MigrationDefinition $migrationDefinition
122
     * @param array $migrationContext
123
     * @param int $stepOffset
124
     * @param bool $useTransaction Deprecated - replaced by $migrationContext['useTransaction']. When set to false, no repo transaction will be used to wrap the migration
125
     * @param string|int|false|null $adminLogin Deprecated - $migrationContext['adminLogin']. Used only for committing db transaction if needed. If false or null, hardcoded admin is used
126
     * @throws \Exception
127
     */
128
    protected function executeMigrationInner(Migration $migration, MigrationDefinition $migrationDefinition,
129
        $migrationContext, $stepOffset = 0, $useTransaction = true, $adminLogin = null)
130
    {
131
        $previousWorkflowName = $this->currentWorkflowName;
132
        $this->currentWorkflowName = $migration->name;
133
        try {
134
            parent::executeMigrationInner($migration, $migrationDefinition, $migrationContext, $stepOffset,
135
                $useTransaction, $adminLogin);
136
            $this->currentWorkflowName = $previousWorkflowName;
137
        } catch (\Exception $e) {
138
            $this->currentWorkflowName = $previousWorkflowName;
139
            throw $e;
140
        }
141
    }
142
143
    /**
144
     * Reimplemented to store in the context the current user at start of workflow
145
     *
146
     * @param null $defaultLanguageCode
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $defaultLanguageCode is correct as it would always require null to be passed?
Loading history...
147
     * @param null $adminLogin
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $adminLogin is correct as it would always require null to be passed?
Loading history...
148
     * @param array $workflowParameters
149
     * @return array
150
     * @deprecated kept for BC
151
     */
152
    protected function migrationContextFromParameters($defaultLanguageCode = null, $adminLogin = null, $forceSigchildEnabled = null, $workflowParameters = null)
153
    {
154
        $properties = parent::migrationContextFromParameters($defaultLanguageCode, $adminLogin, $forceSigchildEnabled);
0 ignored issues
show
Deprecated Code introduced by
The function Kaliop\eZMigrationBundle...ContextFromParameters() has been deprecated: kept for BC ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

154
        $properties = /** @scrutinizer ignore-deprecated */ parent::migrationContextFromParameters($defaultLanguageCode, $adminLogin, $forceSigchildEnabled);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
155
156
        $properties['workflow'] = $this->workflowMigrationContextFromParameters($workflowParameters);
157
158
        return $properties;
159
    }
160
161
    protected function workflowMigrationContextFromParameters($workflowParameters = null)
162
    {
163
        if (!is_array($workflowParameters)) {
164
            /// @todo log warning
165
            $workflowParameters = array();
166
        }
167
168
        $workflowParameters = array_merge(
169
            $workflowParameters,
170
            array(
171
                'original_user' => $this->repository->getCurrentUser()->login,
172
                'start_time' => time()
173
            )
174
        );
175
176
        return $workflowParameters;
177
    }
178
179
    /**
180
     * When restoring the context of the original workflow, we will be running as anon, whereas the original
181
     * workflow might have been started either as an admin or as then-current user. We need special handling for the
182
     * latter case
183
     *
184
     * @param string $migrationName
185
     * @param array $context
186
     */
187
    public function restoreContext($migrationName, array $context)
188
    {
189
        if (array_key_exists('adminUserLogin', $context['context']) && $context['context']['adminUserLogin'] === false) {
190
            if (isset($context['context']['workflow']['original_user'])) {
191
                $context['context']['adminUserLogin'] = $context['context']['workflow']['original_user'];
192
            }
193
        }
194
195
        parent::restoreContext($migrationName, $context);
196
    }
197
198
    ### reference resolver interface
199
200
    public function getRegexp()
201
    {
202
        return $this->referenceRegexp;
203
    }
204
205
    public function isReference($stringIdentifier)
206
    {
207
        if (!is_string($stringIdentifier)) {
208
            return false;
209
        }
210
211
        return (bool)preg_match($this->referenceRegexp, $stringIdentifier);
212
    }
213
214
    /**
215
     * @param string $stringIdentifier
216
     * @return mixed
217
     * @throws \Exception if the given Identifier is not a reference
218
     */
219
    public function getReferenceValue($stringIdentifier)
220
    {
221
        $context = $this->getCurrentContext($this->currentWorkflowName);
222
        if (!is_array($context) || !isset($context['context']['workflow']) || !is_array($context['context']['workflow'])) {
0 ignored issues
show
introduced by
The condition is_array($context) is always true.
Loading history...
223
            throw new \Exception('Can not resolve reference to a workflow parameter as workflow context is missing');
224
        }
225
226
        $identifier = preg_replace($this->referenceRegexp, '', $stringIdentifier);
227
228
        if (!array_key_exists($identifier, $context['context']['workflow'])) {
229
            throw new \Exception("No workflow reference set with identifier '$identifier'");
230
        }
231
232
        return $context['context']['workflow'][$identifier];
233
    }
234
235
    /**
236
     * @param string $stringIdentifier
237
     * @return mixed $stringIdentifier if not a reference, otherwise the reference vale
238
     * @throws \Exception if the given Identifier is not a reference
239
     */
240
    public function resolveReference($stringIdentifier)
241
    {
242
        if ($this->isReference($stringIdentifier)) {
243
            return $this->getReferenceValue($stringIdentifier);
244
        }
245
        return $stringIdentifier;
246
    }
247
248
    public function listReferences()
249
    {
250
        $context = $this->getCurrentContext($this->currentWorkflowName);
251
        if (!is_array($context) || !isset($context['context']['workflow']) || !is_array($context['context']['workflow'])) {
0 ignored issues
show
introduced by
The condition is_array($context) is always true.
Loading history...
252
            throw new \Exception('Can not resolve reference to a workflow parameter as workflow context is missing');
253
        }
254
255
        return $context['context']['workflow'];
256
    }
257
}
258