Passed
Push — master ( d55943...2c5004 )
by Gaetano
06:36
created

ReferenceExecutor::save()   B

Complexity

Conditions 9
Paths 13

Size

Total Lines 37
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 10.6426

Importance

Changes 0
Metric Value
cc 9
eloc 23
nc 13
nop 2
dl 0
loc 37
ccs 16
cts 22
cp 0.7272
crap 10.6426
rs 8.0555
c 0
b 0
f 0
1
<?php
2
3
4
namespace Kaliop\eZMigrationBundle\Core\Executor;
5
6
use Kaliop\eZMigrationBundle\API\Exception\InvalidStepDefinitionException;
7
use Symfony\Component\Console\Output\OutputInterface;
8
use Symfony\Component\DependencyInjection\ContainerInterface;
9
use Symfony\Component\Yaml\Yaml;
10
use Symfony\Component\VarDumper\VarDumper;
11
use Kaliop\eZMigrationBundle\API\Value\MigrationStep;
12
use Kaliop\eZMigrationBundle\API\ReferenceResolverBagInterface;
13
use Kaliop\eZMigrationBundle\API\EnumerableReferenceResolverInterface;
14
15
class ReferenceExecutor extends AbstractExecutor
16
{
17
    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...
18
19
    protected $supportedStepTypes = array('reference');
20
    protected $supportedActions = array('set', 'load', 'save', 'dump');
21
22
    protected $container;
23
    /** @var ReferenceResolverBagInterface $referenceResolver */
24 96
    protected $referenceResolver;
25
26 96
    public function __construct(ContainerInterface $container, ReferenceResolverBagInterface $referenceResolver)
27 96
    {
28 96
        $this->container = $container;
29
        $this->referenceResolver = $referenceResolver;
30
    }
31
32
    /**
33
     * @param MigrationStep $step
34
     * @return mixed
35 18
     * @throws \Exception
36
     */
37 18
    public function execute(MigrationStep $step)
38
    {
39 18
        parent::execute($step);
40
41
        if (!isset($step->dsl['mode'])) {
42
            throw new InvalidStepDefinitionException("Invalid step definition: missing 'mode'");
43 18
        }
44
45 18
        $action = $step->dsl['mode'];
46
47
        if (!in_array($action, $this->supportedActions)) {
48
            throw new InvalidStepDefinitionException("Invalid step definition: value '$action' is not allowed for 'mode'");
49 18
        }
50
51 18
        $this->skipStepIfNeeded($step);
52
53
        return $this->$action($step->dsl, $step->context);
54 18
    }
55
56 18
    protected function set($dsl, $context)
57
    {
58
        if (!isset($dsl['identifier'])) {
59 18
            throw new InvalidStepDefinitionException("Invalid step definition: miss 'identifier' for setting reference");
60
        }
61
        if (!isset($dsl['value'])) {
62
            throw new InvalidStepDefinitionException("Invalid step definition: miss 'value' for setting reference");
63 18
        }
64
65 18
        // this makes sense since we started supporting embedded refs...
66
        $value = $this->referenceResolver->resolveReference($dsl['value']);
67 1
68
        if (0 === strpos($value, '%env(') && ')%' === substr($value, -2) && '%env()%' !== $value) {
69
            /// @todo find out how to use Sf components to resolve this value instead of doing it by ourselves...
70 18
            $env = substr($value, 5, -2);
71 18
            // we use getenv because $_ENV gets cleaned up (by whom?)
72
            $val = getenv($env);
73 18
            if ($val === false) {
74
                throw new \Exception("Env var $env seems not to be defined");
75
            }
76 1
            $value = $val;
77
        } else {
78 1
            /// @todo add support for eZ dynamic parameters too
79
80
            if (preg_match('/.*%.+%.*$/', $value)) {
81 1
                // we use the same parameter resolving rule as symfony, even though this means abusing the ContainerInterface
82 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

82
                $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...
83
            }
84 1
        }
85
86 1
        $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...
87 1
        $this->referenceResolver->addReference($dsl['identifier'], $value, $overwrite);
88
89
        return $value;
90 1
    }
91
92
    protected function load($dsl, $context)
93 1
    {
94
        if (!isset($dsl['file'])) {
95 1
            throw new InvalidStepDefinitionException("Invalid step definition: miss 'file' for loading references");
96
        }
97 1
        $fileName = $this->referenceResolver->resolveReference($dsl['file']);
98
        $fileName = str_replace('{ENV}', $this->container->get('kernel')->getEnvironment(), $fileName);
99
100 1
        $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...
101
102 1
        if (!is_file($fileName) && is_file(dirname($context['path']) . '/references/' . $fileName)) {
103 1
            $fileName = dirname($context['path']) . '/references/' . $fileName;
104
        }
105
106
        if (!is_file($fileName)) {
107
            throw new InvalidStepDefinitionException("Invalid step definition: invalid file '$fileName' for loading references");
108 1
        }
109
        $data = file_get_contents($fileName);
110
111
        $ext = pathinfo($fileName, PATHINFO_EXTENSION);
112 1
        switch ($ext) {
113 1
            case 'json':
114
                $data = json_decode($data, true);
115
                break;
116
            case 'yml':
117 1
            case 'yaml':
118 1
                $data = Yaml::parse($data);
119
                break;
120
            default:
121
                throw new InvalidStepDefinitionException("Invalid step definition: unsupported file extension '$ext' for loading references from");
122 1
        }
123
124
        if (!is_array($data)) {
125
            throw new \Exception("Invalid step definition: file does not contain an array of key/value pairs");
126
        }
127
128 1
        foreach ($data as $refName => $value) {
129
            if (preg_match('/%.+%$/', $value)) {
130 1
                $value = $this->container->getParameter(trim($value, '%'));
131
            }
132
133 1
            if (!$this->referenceResolver->addReference($refName, $value, $overwrite)) {
134 1
                throw new \Exception("Failed adding to Reference Resolver the reference: $refName");
135
            }
136 1
        }
137
138 1
        return $data;
139
    }
140
141
    /**
142 1
     * @todo find a smart way to allow saving the references file next to the current migration
143
     */
144
    protected function save($dsl, $context)
145
    {
146 1
        if (!isset($dsl['file'])) {
147
            throw new InvalidStepDefinitionException("Invalid step definition: miss 'file' for saving references");
148 1
        }
149
        $fileName = $this->referenceResolver->resolveReference($dsl['file']);
150 1
        $fileName = str_replace('{ENV}', $this->container->get('kernel')->getEnvironment(), $fileName);
151
152
        $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...
153 1
154
        if (is_file($fileName) && !$overwrite) {
155 1
            throw new \Exception("Invalid step definition: file '$fileName' for saving references already exists");
156 1
        }
157
158
        if (! $this->referenceResolver instanceof EnumerableReferenceResolverInterface) {
159
            throw new \Exception("Can not save references as resolver is not enumerable");
160
        }
161 1
162
        $data = $this->referenceResolver->listReferences();
163 1
164
        $ext = pathinfo($fileName, PATHINFO_EXTENSION);
165
        switch ($ext) {
166 10
            case 'json':
167
                $data = json_encode($data, JSON_PRETTY_PRINT);
168 10
                break;
169
            case 'yml':
170
            case 'yaml':
171 10
            /// @todo use Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE option if it is supported
172
                $data = Yaml::dump($data);
173
                break;
174 10
            default:
175 1
                throw new InvalidStepDefinitionException("Invalid step definition: unsupported file extension '$ext' for saving references to");
176
        }
177 10
178
        file_put_contents($fileName, $data);
179 10
180 10
        return $data;
181
    }
182 10
183
    protected function dump($dsl, $context)
184
    {
185
        if (!isset($dsl['identifier'])) {
186
            throw new InvalidStepDefinitionException("Invalid step definition: miss 'identifier' for dumping reference");
187
        }
188
        if (!$this->referenceResolver->isReference($dsl['identifier'])) {
189
            throw new \Exception("Invalid step definition: identifier '{$dsl['identifier']}' is not a reference");
190
        }
191
        /// @todo improve handling of the case $context['output'] is set - atm it does not seem to work with unit tests...
192
        if (isset($context['output']) && $context['output'] instanceof OutputInterface) {
193
            if ($context['output']->isQuiet()) {
194
                return $this->referenceResolver->resolveReference($dsl['identifier']);
195
            }
196
            ob_start();
197
        }
198
        if (isset($dsl['label'])) {
199
            echo $dsl['label'];
200
        } else {
201
            VarDumper::dump($dsl['identifier']);
202
        }
203
        $value = $this->referenceResolver->resolveReference($dsl['identifier']);
204
        VarDumper::dump($value);
205
        if (isset($context['output']) && $context['output'] instanceof OutputInterface) {
206
            $context['output']->write(ob_get_contents(), false, OutputInterface::OUTPUT_RAW|OutputInterface::VERBOSITY_NORMAL);
207
            ob_end_clean();
208
        }
209
        return $value;
210
    }
211
}
212