Passed
Push — master ( 6c8cca...faca34 )
by Gaetano
05:35
created

ReferenceExecutor::set()   B

Complexity

Conditions 11
Paths 16

Size

Total Lines 38
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 11.968

Importance

Changes 0
Metric Value
cc 11
eloc 20
c 0
b 0
f 0
nc 16
nop 2
dl 0
loc 38
ccs 16
cts 20
cp 0.8
crap 11.968
rs 7.3166

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\eZMigrationBundle\Core\Executor;
4
5
use Kaliop\eZMigrationBundle\API\EnumerableReferenceResolverInterface;
6
use Kaliop\eZMigrationBundle\API\Exception\InvalidStepDefinitionException;
7
use Kaliop\eZMigrationBundle\API\ReferenceResolverBagInterface;
8
use Kaliop\eZMigrationBundle\API\Value\MigrationStep;
9
use Symfony\Component\Console\Output\OutputInterface;
10
use Symfony\Component\DependencyInjection\ContainerInterface;
11
use Symfony\Component\VarDumper\Cloner\VarCloner;
12
use Symfony\Component\VarDumper\Dumper\CliDumper;
13
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
14
use Symfony\Component\Yaml\Yaml;
15
16
class ReferenceExecutor extends AbstractExecutor
17
{
18
    use IgnorableStepExecutorTrait;
0 ignored issues
show
Bug introduced by
The trait Kaliop\eZMigrationBundle...orableStepExecutorTrait requires the property $dsl which is not provided by Kaliop\eZMigrationBundle...cutor\ReferenceExecutor.
Loading history...
19
20
    protected $supportedStepTypes = array('reference');
21
    protected $supportedActions = array('set', 'load', 'save', 'dump');
22
23
    protected $container;
24 96
    /** @var ReferenceResolverBagInterface $referenceResolver */
25
    protected $referenceResolver;
26 96
27 96
    public function __construct(ContainerInterface $container, ReferenceResolverBagInterface $referenceResolver)
28 96
    {
29
        $this->container = $container;
30
        $this->referenceResolver = $referenceResolver;
31
    }
32
33
    /**
34
     * @param MigrationStep $step
35 18
     * @return mixed
36
     * @throws \Exception
37 18
     */
38
    public function execute(MigrationStep $step)
39 18
    {
40
        parent::execute($step);
41
42
        if (!isset($step->dsl['mode'])) {
43 18
            throw new InvalidStepDefinitionException("Invalid step definition: missing 'mode'");
44
        }
45 18
46
        $action = $step->dsl['mode'];
47
48
        if (!in_array($action, $this->supportedActions)) {
49 18
            throw new InvalidStepDefinitionException("Invalid step definition: value '$action' is not allowed for 'mode'");
50
        }
51 18
52
        $this->skipStepIfNeeded($step);
53
54 18
        return $this->$action($step->dsl, $step->context);
55
    }
56 18
57
    protected function set($dsl, $context)
58
    {
59 18
        if (!isset($dsl['identifier'])) {
60
            throw new InvalidStepDefinitionException("Invalid step definition: miss 'identifier' for setting reference");
61
        }
62
        if (!isset($dsl['value'])) {
63 18
            throw new InvalidStepDefinitionException("Invalid step definition: miss 'value' for setting reference");
64
        }
65 18
66
        if (!isset($dsl['resolve_references']) || $dsl['resolve_references']) {
67 1
            // this makes sense since we started supporting embedded refs...
68
            $value = $this->referenceResolver->resolveReference($dsl['value']);
69
        } else {
70 18
            $value = $dsl['value'];
71 18
        }
72
73 18
        if (0 === strpos($value, '%env(') && ')%' === substr($value, -2) && '%env()%' !== $value) {
74
            /// @todo find out how to use Sf components to resolve this value instead of doing it by ourselves...
75
            $env = substr($value, 5, -2);
76 1
            // we use getenv because $_ENV gets cleaned up (by whom?)
77
            $val = getenv($env);
78 1
            if ($val === false) {
79
                throw new \Exception("Env var $env seems not to be defined");
80
            }
81 1
            $value = $val;
82 1
        } else {
83
            /// @todo add support for eZ dynamic parameters too
84 1
85
            if (preg_match('/.*%.+%.*$/', $value)) {
86 1
                // we use the same parameter resolving rule as symfony, even though this means abusing the ContainerInterface
87 1
                $value = $this->container->getParameterBag()->resolveString($value);
0 ignored issues
show
Bug introduced by
The method getParameterBag() does not exist on Symfony\Component\Depend...tion\ContainerInterface. Did you maybe mean getParameter()? ( Ignorable by Annotation )

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

87
                $value = $this->container->/** @scrutinizer ignore-call */ getParameterBag()->resolveString($value);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
88
            }
89
        }
90 1
91
        $overwrite = isset($dsl['overwrite']) ? $overwrite = $dsl['overwrite'] : false;
0 ignored issues
show
Unused Code introduced by
The assignment to $overwrite is dead and can be removed.
Loading history...
92
        $this->referenceResolver->addReference($dsl['identifier'], $value, $overwrite);
93 1
94
        return $value;
95 1
    }
96
97 1
    protected function load($dsl, $context)
98
    {
99
        if (!isset($dsl['file'])) {
100 1
            throw new InvalidStepDefinitionException("Invalid step definition: miss 'file' for loading references");
101
        }
102 1
        $fileName = $this->referenceResolver->resolveReference($dsl['file']);
103 1
        $fileName = str_replace('{ENV}', $this->container->get('kernel')->getEnvironment(), $fileName);
104
105
        $overwrite = isset($dsl['overwrite']) ? $overwrite = $dsl['overwrite'] : false;
0 ignored issues
show
Unused Code introduced by
The assignment to $overwrite is dead and can be removed.
Loading history...
106
107
        if (!is_file($fileName) && is_file(dirname($context['path']) . '/references/' . $fileName)) {
108 1
            $fileName = dirname($context['path']) . '/references/' . $fileName;
109
        }
110
111
        if (!is_file($fileName)) {
112 1
            throw new InvalidStepDefinitionException("Invalid step definition: invalid file '$fileName' for loading references");
113 1
        }
114
        $data = file_get_contents($fileName);
115
116
        $ext = pathinfo($fileName, PATHINFO_EXTENSION);
117 1
        switch ($ext) {
118 1
            case 'json':
119
                $data = json_decode($data, true);
120
                break;
121
            case 'yml':
122 1
            case 'yaml':
123
                $data = Yaml::parse($data);
124
                break;
125
            default:
126
                throw new InvalidStepDefinitionException("Invalid step definition: unsupported file extension '$ext' for loading references from");
127
        }
128 1
129
        if (!is_array($data)) {
130 1
            throw new \Exception("Invalid step definition: file does not contain an array of key/value pairs");
131
        }
132
133 1
        foreach ($data as $refName => $value) {
134 1
            if (preg_match('/%.+%$/', $value)) {
135
                $value = $this->container->getParameter(trim($value, '%'));
136 1
            }
137
138 1
            if (!$this->referenceResolver->addReference($refName, $value, $overwrite)) {
139
                throw new \Exception("Failed adding to Reference Resolver the reference: $refName");
140
            }
141
        }
142 1
143
        return $data;
144
    }
145
146 1
    /**
147
     * @todo find a smart way to allow saving the references file next to the current migration
148 1
     */
149
    protected function save($dsl, $context)
150 1
    {
151
        if (!isset($dsl['file'])) {
152
            throw new InvalidStepDefinitionException("Invalid step definition: miss 'file' for saving references");
153 1
        }
154
        $fileName = $this->referenceResolver->resolveReference($dsl['file']);
155 1
        $fileName = str_replace('{ENV}', $this->container->get('kernel')->getEnvironment(), $fileName);
156 1
157
        $overwrite = isset($dsl['overwrite']) ? $overwrite = $dsl['overwrite'] : false;
0 ignored issues
show
Unused Code introduced by
The assignment to $overwrite is dead and can be removed.
Loading history...
158
159
        if (is_file($fileName) && !$overwrite) {
160
            throw new \Exception("Invalid step definition: file '$fileName' for saving references already exists");
161 1
        }
162
163 1
        if (! $this->referenceResolver instanceof EnumerableReferenceResolverInterface) {
164
            throw new \Exception("Can not save references as resolver is not enumerable");
165
        }
166 10
167
        $data = $this->referenceResolver->listReferences();
168 10
169
        $ext = pathinfo($fileName, PATHINFO_EXTENSION);
170
        switch ($ext) {
171 10
            case 'json':
172
                $data = json_encode($data, JSON_PRETTY_PRINT);
173
                break;
174 10
            case 'yml':
175 1
            case 'yaml':
176
            /// @todo use Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE option if it is supported
177 10
                $data = Yaml::dump($data);
178
                break;
179 10
            default:
180 10
                throw new InvalidStepDefinitionException("Invalid step definition: unsupported file extension '$ext' for saving references to");
181
        }
182 10
183
        file_put_contents($fileName, $data);
184
185
        return $data;
186
    }
187
188
    protected function dump($dsl, $context)
189
    {
190
        if (!isset($dsl['identifier'])) {
191
            throw new InvalidStepDefinitionException("Invalid step definition: miss 'identifier' for dumping reference");
192
        }
193
        if (!$this->referenceResolver->isReference($dsl['identifier'])) {
194
            throw new \Exception("Invalid step definition: identifier '{$dsl['identifier']}' is not a reference");
195
        }
196
        if (isset($context['output']) && $context['output'] instanceof OutputInterface && $context['output']->isQuiet()) {
197
            return $this->referenceResolver->resolveReference($dsl['identifier']);
198
        }
199
200
        if (isset($dsl['label'])) {
201
            $label = $dsl['label'];
202
        } else {
203
            $label = $this->dumpVar($dsl['identifier']);
204
        }
205
        $value = $this->dumpVar($this->referenceResolver->resolveReference($dsl['identifier']));
206
207
        if (isset($context['output']) && $context['output'] instanceof OutputInterface) {
208
            $context['output']->write($label . $value, false, OutputInterface::OUTPUT_RAW|OutputInterface::VERBOSITY_NORMAL);
209
        } else {
210
            echo $label . $value;
211
        }
212
213
        return $value;
214
    }
215
216
    /**
217
     * Similar to VarDumper::dump(), but returns the output
218
     * @param mixed $var
219
     * @return string
220
     * @throws \ErrorException
221
     */
222
    protected function dumpVar($var)
223
    {
224
        $cloner = new VarCloner();
225
        $dumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliDumper() : new HtmlDumper();
226
        $output = '';
227
228
        $dumper->dump(
229
            $cloner->cloneVar($var),
230
            function ($line, $depth) use (&$output) {
231
                // A negative depth means "end of dump"
232
                if ($depth >= 0) {
233
                    // Adds a two spaces indentation to the line
234
                    /// @todo should we use NBSP for html dumping?
235
                    $output .= str_repeat('  ', $depth) . $line . "\n";
236
                }
237
            }
238
        );
239
240
        return $output;
241
    }
242
}
243