Completed
Branch master (e35419)
by Gaetano
06:40
created

FileExecutor::exists()   A

Complexity

Conditions 6
Paths 3

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 6.0106

Importance

Changes 0
Metric Value
cc 6
eloc 14
nc 3
nop 2
dl 0
loc 24
ccs 14
cts 15
cp 0.9333
crap 6.0106
rs 9.2222
c 0
b 0
f 0
1
<?php
2
3
namespace Kaliop\eZMigrationBundle\Core\Executor;
4
5
use Kaliop\eZMigrationBundle\API\Value\MigrationStep;
6
use Kaliop\eZMigrationBundle\API\EmbeddedReferenceResolverBagInterface;
7
8
class FileExecutor extends AbstractExecutor
9
{
10
    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...e\Executor\FileExecutor.
Loading history...
11
12
    protected $supportedStepTypes = array('file');
13
    protected $supportedActions = array('load', 'save', 'copy', 'move', 'delete', 'append', 'prepend', 'exists');
14
15
    /** @var EmbeddedReferenceResolverBagInterface $referenceResolver */
16
    protected $referenceResolver;
17
18
    /**
19
     * @param EmbeddedReferenceResolverBagInterface $referenceResolver
20
     */
21 80
    public function __construct(EmbeddedReferenceResolverBagInterface $referenceResolver)
22
    {
23 80
        $this->referenceResolver = $referenceResolver;
24 80
    }
25
26
    /**
27
     * @param MigrationStep $step
28
     * @return mixed
29
     * @throws \Exception
30
     */
31 2
    public function execute(MigrationStep $step)
32
    {
33 2
        parent::execute($step);
34
35 2
        if (!isset($step->dsl['mode'])) {
36
            throw new \Exception("Invalid step definition: missing 'mode'");
37
        }
38
39 2
        $action = $step->dsl['mode'];
40
41 2
        if (!in_array($action, $this->supportedActions)) {
42
            throw new \Exception("Invalid step definition: value '$action' is not allowed for 'mode'");
43
        }
44
45 2
        $this->skipStepIfNeeded($step);
46
47 2
        return $this->$action($step->dsl, $step->context);
48
    }
49
50
    /**
51
     * @param array $dsl
52
     * @param array $context
53
     * @return string
54
     * @throws \Exception
55
     */
56 2
    protected function load($dsl, $context)
57
    {
58 2
        if (!isset($dsl['file'])) {
59
            throw new \Exception("Can not load file: name missing");
60
        }
61 2
        $fileName = $this->referenceResolver->resolveReference($dsl['file']);
62 2
        if (!file_exists($fileName)) {
63
            throw new \Exception("Can not load '$fileName': file missing");
64
        }
65
66 2
        $this->setReferences($fileName, $dsl);
67
68 2
        return file_get_contents($fileName);
69
    }
70
71
    /**
72
     * @param array $dsl
73
     * @param array $context
74
     * @return string
75
     * @throws \Exception
76
     */
77 1
    protected function exists($dsl, $context)
78
    {
79 1
        if (!isset($dsl['file'])) {
80
            throw new \Exception("Can not check for existence of file: name missing");
81
        }
82 1
        $fileName = $this->referenceResolver->resolveReference($dsl['file']);
83
84 1
        $exists = file_exists($fileName);
85
86 1
        if (array_key_exists('references', $dsl)) {
87 1
            foreach ($dsl['references'] as $reference) {
88 1
                switch ($reference['attribute']) {
89 1
                    case 'exists':
90 1
                        $overwrite = false;
91 1
                        if (isset($reference['overwrite'])) {
92 1
                            $overwrite = $reference['overwrite'];
93
                        }
94 1
                        $this->referenceResolver->addReference($reference['identifier'], $exists, $overwrite);
95 1
                        break;
96
                }
97
            }
98
        }
99
100 1
        return $exists;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $exists returns the type boolean which is incompatible with the documented return type string.
Loading history...
101
    }
102
103
    /**
104
     * @param array $dsl
105
     * @param array $context
106
     * @return int
107
     * @throws \Exception
108
     */
109 1
    protected function save($dsl, $context)
110
    {
111 1
        if (!isset($dsl['file']) || (!isset($dsl['body']) && !isset($dsl['template']))) {
112
            throw new \Exception("Can not save file: name or body or template missing");
113
        }
114
115 1
        if (isset($dsl['body']) && is_string($dsl['body'])) {
116 1
            $contents = $this->resolveReferencesInText($dsl['body']);
117 1
        } elseif (isset($dsl['template']) && is_string($dsl['template'])) {
118 1
            $path = $this->referenceResolver->resolveReference($dsl['template']);
119
            // we use the same logic as for the image/file fields in content: look up file 1st relative to the migration
120 1
            $template = dirname($context['path']) . '/templates/' . $path;
121 1
            if (!is_file($template)) {
122
                $template = $path;
123
            }
124 1
            $contents = $this->resolveReferencesInText(file_get_contents($template));
125
        } else {
126
            throw new \Exception("Can not save file: either body or template tag must be a string");
127
        }
128
129 1
        $fileName = $this->referenceResolver->resolveReference($dsl['file']);
130
131 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...
132 1
        if (!$overwrite && file_exists($fileName)) {
133
            throw new \Exception("Can not save file '$fileName: file already exists");
134
        }
135
136 1
        $return = file_put_contents($fileName, $contents);
137
138 1
        $this->setReferences($fileName, $dsl);
139
140 1
        return $return;
141
    }
142
143
    /**
144
     * @param array $dsl
145
     * @param array $context
146
     * @return int
147
     * @throws \Exception
148
     */
149 1
    protected function append($dsl, $context)
150
    {
151 1
        if (!isset($dsl['file']) || (!isset($dsl['body']) && !isset($dsl['template']))) {
152
            throw new \Exception("Can not append to file: name or body or template missing");
153
        }
154
155 1
        if (isset($dsl['body']) && is_string($dsl['body'])) {
156 1
            $contents = $this->resolveReferencesInText($dsl['body']);
157
        } elseif (isset($dsl['template']) && is_string($dsl['template'])) {
158
            $path = $this->referenceResolver->resolveReference($dsl['template']);
159
            // we use the same logic as for the image/file fields in content: look up file 1st relative to the migration
160
            $template = dirname($context['path']) . '/templates/' . $path;
161
            if (!is_file($template)) {
162
                $template = $path;
163
            }
164
            $contents = $this->resolveReferencesInText(file_get_contents($template));
165
        } else {
166
            throw new \Exception("Can not append to file: either body or template tag must be a string");
167
        }
168
169 1
        $fileName = $this->referenceResolver->resolveReference($dsl['file']);
170
171 1
        $return = file_put_contents($fileName, $contents, FILE_APPEND);
172
173 1
        $this->setReferences($fileName, $dsl);
174
175 1
        return $return;
176
    }
177
178
    /**
179
     * @param array $dsl
180
     * @param array $context
181
     * @return int
182
     * @throws \Exception
183
     */
184
    protected function prepend($dsl, $context)
185
    {
186
        if (!isset($dsl['file']) || (!isset($dsl['body']) && !isset($dsl['template']))) {
187
            throw new \Exception("Can not prepend to file: name or body or template missing");
188
        }
189
190
        if (isset($dsl['body']) && is_string($dsl['body'])) {
191
            $contents = $this->resolveReferencesInText($dsl['body']);
192
        } elseif (isset($dsl['template']) && is_string($dsl['template'])) {
193
            $path = $this->referenceResolver->resolveReference($dsl['template']);
194
            // we use the same logic as for the image/file fields in content: look up file 1st relative to the migration
195
            $template = dirname($context['path']) . '/templates/' . $path;
196
            if (!is_file($template)) {
197
                $template = $path;
198
            }
199
            $contents = $this->resolveReferencesInText(file_get_contents($template));
200
        } else {
201
            throw new \Exception("Can not append to file: either body or template tag must be a string");
202
        }
203
204
        $fileName = $this->referenceResolver->resolveReference($dsl['file']);
205
206
        if (file_exists($fileName)) {
207
            $contents .= file_get_contents($fileName);
208
        }
209
210
        $return = file_put_contents($fileName, $contents);
211
212
        $this->setReferences($fileName, $dsl);
213
214
        return $return;
215
    }
216
217
    /**
218
     * @param array $dsl
219
     * @param array $context
220
     * @return true
221
     * @throws \Exception
222
     */
223 1
    protected function copy($dsl, $context)
224
    {
225 1
        if (!isset($dsl['from']) || !isset($dsl['to'])) {
226
            throw new \Exception("Can not copy file: from or to missing");
227
        }
228
229 1
        $fileName = $this->referenceResolver->resolveReference($dsl['from']);
230 1
        if (!file_exists($fileName)) {
231
            throw new \Exception("Can not copy file '$fileName': file missing");
232
        }
233
234 1
        $this->setReferences($fileName, $dsl);
235
236 1
        $to = $this->referenceResolver->resolveReference($dsl['to']);
237 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...
238 1
        if (!$overwrite && file_exists($to)) {
239
            throw new \Exception("Can not copy file to '$to: file already exists");
240
        }
241
242 1
        if (!copy($fileName, $to)) {
243
            throw new \Exception("Can not copy file '$fileName' to '$to': operation failed");
244
        }
245
246 1
        return true;
247
    }
248
249
    /**
250
     * @param array $dsl
251
     * @param array $context
252
     * @return true
253
     * @throws \Exception
254
     */
255 1
    protected function move($dsl, $context)
256
    {
257 1
        if (!isset($dsl['from']) || !isset($dsl['to'])) {
258
            throw new \Exception("Can not move file: from or to missing");
259
        }
260
261 1
        $fileName = $this->referenceResolver->resolveReference($dsl['from']);
262 1
        if (!file_exists($fileName)) {
263
            throw new \Exception("Can not move file '$fileName': file missing");
264
        }
265
266 1
        $this->setReferences($fileName, $dsl);
267
268 1
        $to = $this->referenceResolver->resolveReference($dsl['to']);
269 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...
270 1
        if (!$overwrite && file_exists($to)) {
271
            throw new \Exception("Can not move to '$to': file already exists");
272
        }
273
274 1
        if (!rename($fileName, $to)) {
275
            throw new \Exception("Can not move file '$fileName': operation failed");
276
        }
277
278 1
        return true;
279
    }
280
281
    /**
282
     * @param array $dsl
283
     * @param array $context
284
     * @return true
285
     * @throws \Exception
286
     */
287 1
    protected function delete($dsl, $context)
288
    {
289 1
        if (!isset($dsl['file'])) {
290
            throw new \Exception("Can not delete file: name missing");
291
        }
292
293 1
        $fileName = $this->referenceResolver->resolveReference($dsl['file']);
294 1
        if (!file_exists($fileName)) {
295
            throw new \Exception("Can not move delete '$fileName': file missing");
296
        }
297
298 1
        $this->setReferences($fileName, $dsl);
299
300 1
        if (!unlink($fileName)) {
301
            throw new \Exception("Can not delete file '$fileName': operation failed");
302
        }
303
304 1
        return true;
305
    }
306
307 2
    protected function setReferences($fileName, $dsl)
308
    {
309 2
        if (!array_key_exists('references', $dsl)) {
310 1
            return false;
311
        }
312
313 2
        clearstatcache(true, $fileName);
314 2
        $stats = stat($fileName);
315
316 2
        if (!$stats) {
317
            throw new \Exception("Can not set references for file '$fileName': stat failed");
318
        }
319
320 2
        foreach ($dsl['references'] as $reference) {
321 2
            switch ($reference['attribute']) {
322 2
                case 'body':
323 2
                    $value = file_get_contents($fileName);
324 2
                    break;
325 1
                case 'size':
326 1
                    $value = $stats[7];
327 1
                    break;
328 1
                case 'uid':
329
                    $value = $stats[4];
330
                    break;
331 1
                case 'gid':
332
                    $value = $stats[5];
333
                    break;
334 1
                case 'atime':
335 1
                    $value = $stats[8];
336 1
                    break;
337 1
                case 'mtime':
338
                    $value = $stats[9];
339
                    break;
340 1
                case 'ctime':
341 1
                    $value = $stats[10];
342 1
                    break;
343
                default:
344
                    throw new \InvalidArgumentException('File executor does not support setting references for attribute ' . $reference['attribute']);
345
            }
346
347 2
            $overwrite = false;
348 2
            if (isset($reference['overwrite'])) {
349 1
                $overwrite = $reference['overwrite'];
350
            }
351 2
            $this->referenceResolver->addReference($reference['identifier'], $value, $overwrite);
352
        }
353
354 2
        return true;
355
    }
356
357
    /**
358
     * Replaces any references inside a string
359
     *
360
     * @param string $text
361
     * @return string
362
     * @throws \Exception
363
     */
364 1
    protected function resolveReferencesInText($text)
365
    {
366 1
        return $this->referenceResolver->ResolveEmbeddedReferences($text);
367
    }
368
}
369