Completed
Push — master ( 68da2d...d119ba )
by Gaetano
07:21
created

RepositoryExecutor::insureSingleEntity()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 15
Code Lines 8

Duplication

Lines 6
Ratio 40 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 6
loc 15
ccs 0
cts 0
cp 0
rs 9.2
c 0
b 0
f 0
cc 4
eloc 8
nc 4
nop 2
crap 20
1
<?php
2
3
namespace Kaliop\eZMigrationBundle\Core\Executor;
4
5
use eZ\Publish\API\Repository\Repository;
6
use Kaliop\eZMigrationBundle\API\Collection\AbstractCollection;
7
use Kaliop\eZMigrationBundle\API\ReferenceResolverBagInterface;
8
use Kaliop\eZMigrationBundle\API\Value\MigrationStep;
9
use Kaliop\eZMigrationBundle\Core\RepositoryUserSetterTrait;
10
11
/**
12
 * The core manager class that all migration action managers inherit from.
13
 */
14
abstract class RepositoryExecutor extends AbstractExecutor
15
{
16
    use RepositoryUserSetterTrait;
17
18
    /**
19
     * Constant defining the default language code (used if not specified by the migration or on the command line)
20
     */
21
    const DEFAULT_LANGUAGE_CODE = 'eng-GB';
22
23
    /**
24
     * The default Admin user Id, used when no Admin user is specified
25
     */
26
    const ADMIN_USER_ID = 14;
27
28
    /** Used if not specified by the migration */
29
    const USER_CONTENT_TYPE = 'user';
30
31
    /**
32
     * @var array $dsl The parsed DSL instruction array
33
     */
34
    //protected $dsl;
35
36
    /** @var array $context The context (configuration) for the execution of the current step */
37
    //protected $context;
38
39
    /**
40
     * The eZ Publish 5 API repository.
41
     *
42
     * @var \eZ\Publish\API\Repository\Repository
43
     */
44
    protected $repository;
45
46
    /** @var ReferenceResolverBagInterface $referenceResolver */
47
    protected $referenceResolver;
48
49
    // to redefine in subclasses if they don't support all methods, or if they support more...
50
    protected $supportedActions = array(
51
        'create', 'update', 'delete'
52
    );
53
54
    public function setRepository(Repository $repository)
55
    {
56
        $this->repository = $repository;
57
    }
58
59
    public function setReferenceResolver(ReferenceResolverBagInterface $referenceResolver)
60
    {
61
        $this->referenceResolver = $referenceResolver;
62
    }
63
64
    public function execute(MigrationStep $step)
65
    {
66
        // base checks
67
        parent::execute($step);
68
69
        if (!isset($step->dsl['mode'])) {
70
            throw new \Exception("Invalid step definition: missing 'mode'");
71
        }
72
73
        $action = $step->dsl['mode'];
74 20
75
        if (!in_array($action, $this->supportedActions)) {
76 20
            throw new \Exception("Invalid step definition: value '$action' is not allowed for 'mode'");
77 20
        }
78
79 20
        if (method_exists($this, $action)) {
80
81 20
            $previousUserId = $this->loginUser($this->getAdminUserIdentifierFromContext($step->context));
82 20
83
            try {
84 9
                $output = $this->$action($step);
85
            } catch (\Exception $e) {
86
                $this->loginUser($previousUserId);
87 9
                throw $e;
88
            }
89 9
90
            // reset the environment as much as possible as we had found it before the migration
91
            $this->loginUser($previousUserId);
92
93 9
            return $output;
94
        } else {
95 9
            throw new \Exception("Invalid step definition: value '$action' is not a method of " . get_class($this));
96
        }
97
    }
98
99 9
    /**
100 9
     * Method that each executor (subclass) has to implement.
101 9
     *
102 2
     * It is used to set references based on the DSL instructions executed in the current step, for later steps to reuse.
103 2
     *
104
     * @throws \InvalidArgumentException when trying to set a reference to an unsupported attribute.
105 9
     * @param $object
106
     * @return boolean
107 9
     */
108
    abstract protected function setReferences($object, $step);
109 9
110 9
    /**
111 2
     * @param MigrationStep $step
112 3
     * @return string
113
     */
114
    protected function getLanguageCode($step)
115
    {
116 8
        return isset($step->dsl['lang']) ? $step->dsl['lang'] : $this->getLanguageCodeFromContext($step->context);
117
    }
118 8
119
    /**
120
     * @param array $context
121
     * @return string
122
     */
123
    protected function getLanguageCodeFromContext($context)
124
    {
125
        return isset($context['defaultLanguageCode']) ? $context['defaultLanguageCode'] : self::DEFAULT_LANGUAGE_CODE;
126
    }
127
128
    /**
129
     * @param MigrationStep $step
130
     * @return string
131
     */
132
    protected function getUserContentType($step)
133
    {
134
        return isset($step->dsl['user_content_type']) ? $step->dsl['user_content_type'] : $this->getUserContentTypeFromContext($step->context);
135
    }
136
137
    protected function getUserContentTypeFromContext($context)
138
    {
139
        return isset($context['userContentType']) ? $context['userContentType'] : self::USER_CONTENT_TYPE;
140 9
    }
141
142 9
    /**
143
     * @param $context we have to return FALSE if that is set as adminUserLogin, whereas if NULL is set, we return the default admin
144 9
     * @return int|string|false
145 9
     */
146 9
    protected function getAdminUserIdentifierFromContext($context)
147
    {
148 9
        if (isset($context['adminUserLogin'])) {
149
            return $context['adminUserLogin'];
150
        }
151 2
152
        return self::ADMIN_USER_ID;
153 2
    }
154 2
155
    protected function setReferencesCommon($entity, $step)
156 7
    {
157
        // allow setting *some* refs even when we have 0 or N matches
158 7
        foreach ($step->dsl['references'] as $key => $reference) {
159
            switch($reference['attribute']) {
160
161
                case 'count':
162
                    $value = count($entity);
163
                    $overwrite = false;
164
                    if (isset($reference['overwrite'])) {
165
                        $overwrite = $reference['overwrite'];
166 6
                    }
167
                    $this->referenceResolver->addReference($reference['identifier'], $value, $overwrite);
168 6
                    unset($step->dsl['references'][$key]);
169
                    break;
170
171
                default:
172
                    // do nothing
173
            }
174
        }
175
    }
176
177
    protected function insureSingleEntity($entity, $step)
0 ignored issues
show
Unused Code introduced by
The parameter $step is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
178
    {
179
        if ($entity instanceof AbstractCollection) {
180 View Code Duplication
            if (count($entity) > 1) {
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...
181
                throw new \InvalidArgumentException($this->getSelfName() . ' does not support setting references for multiple ' . $this->getCollectionName($entity) . 's');
182
            }
183 View Code Duplication
            if (count($entity) == 0) {
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...
184
                throw new \InvalidArgumentException($this->getSelfName() . ' does not support setting references for no ' . $this->getCollectionName($entity). 's');
185
            }
186
187
            $entity = reset($entity);
188
        }
189
190
        return $entity;
191
    }
192
193
    protected function getSelfName()
194
    {
195
        $className = get_class($this);
196
        // CamelCase to Camel Case using negative look-behind in regexp
197
        return preg_replace('/(?<!^)[A-Z]/', ' $0', $className);
198
    }
199
200
    protected function getCollectionName($collection)
201
    {
202
        $className = str_replace('Collection', '', get_class($collection));
0 ignored issues
show
Unused Code introduced by
$className is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
203
        // CamelCase to snake case using negative look-behind in regexp
204
        return strtolower(preg_replace('/(?<!^)[A-Z]/', ' $0', $collection));
205
    }
206
207
    /**
208
     * Courtesy code to avoid reimplementing it in every subclass
209
     * @deprecated will be moved into the reference resolver classes
210
     */
211 View Code Duplication
    protected function resolveReferencesRecursively($match)
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...
212
    {
213
        if (is_array($match)) {
214
            foreach ($match as $condition => $values) {
215
                $match[$condition] = $this->resolveReferencesRecursively($values);
0 ignored issues
show
Deprecated Code introduced by
The method Kaliop\eZMigrationBundle...ReferencesRecursively() has been deprecated with message: will be moved into the reference resolver classes

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

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

Loading history...
216
            }
217
            return $match;
218
        } else {
219
            return $this->referenceResolver->resolveReference($match);
220
        }
221
    }
222
}
223