1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file is part of the m1\vars library |
5
|
|
|
* |
6
|
|
|
* Copyright (c) Miles Croxford <[email protected]> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
* |
11
|
|
|
* @package m1/vars |
12
|
|
|
* @version 1.1.0 |
13
|
|
|
* @author Miles Croxford <[email protected]> |
14
|
|
|
* @copyright Copyright (c) Miles Croxford <[email protected]> |
15
|
|
|
* @license http://github.com/m1/vars/blob/master/LICENSE |
16
|
|
|
* @link http://github.com/m1/vars/blob/master/README.MD Documentation |
17
|
|
|
*/ |
18
|
|
|
|
19
|
|
|
namespace M1\Vars\Resource; |
20
|
|
|
|
21
|
|
|
use M1\Vars\Traits\FileTrait; |
22
|
|
|
use M1\Vars\Traits\ResourceFlagsTrait; |
23
|
|
|
use Symfony\Component\Filesystem\Filesystem; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* File Resource enables interaction with files as resources |
27
|
|
|
* |
28
|
|
|
* @since 0.1.0 |
29
|
|
|
*/ |
30
|
|
|
class FileResource extends AbstractResource |
31
|
|
|
{ |
32
|
|
|
/** |
33
|
|
|
* Basic file interaction logic |
34
|
|
|
*/ |
35
|
|
|
use FileTrait; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Enables the resource flags logic |
39
|
|
|
*/ |
40
|
|
|
use ResourceFlagsTrait; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* The filename of the loaded file |
44
|
|
|
* |
45
|
|
|
* @var string |
46
|
|
|
*/ |
47
|
|
|
private $filename; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* The parent ResourceProvider |
51
|
|
|
* |
52
|
|
|
* @var \M1\Vars\Resource\ResourceProvider |
53
|
|
|
*/ |
54
|
|
|
private $provider; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* The raw content from the passed file |
58
|
|
|
* |
59
|
|
|
* @var mixed |
60
|
|
|
*/ |
61
|
|
|
private $raw_content = array(); |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* The VariableProvider |
65
|
|
|
* |
66
|
|
|
* @var \M1\Vars\Variables\VariableProvider |
67
|
|
|
*/ |
68
|
|
|
private $variables; |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* The file resource constructor to get and parse the content from files |
72
|
|
|
* |
73
|
|
|
* @param \M1\Vars\Resource\ResourceProvider $provider The parent ResourceProvider |
74
|
|
|
* @param string $file The passed file |
75
|
|
|
*/ |
76
|
75 |
|
public function __construct(ResourceProvider $provider, $file) |
77
|
|
|
{ |
78
|
75 |
|
$this->provider = $provider; |
79
|
75 |
|
$this->vars = $provider->vars; |
80
|
75 |
|
$this->variables = $this->vars->variables; |
81
|
|
|
|
82
|
75 |
|
$this->makePaths($file); |
83
|
75 |
|
$this->validate(); |
84
|
|
|
|
85
|
75 |
|
$store_prefix = $this->variables->vstore->getPrefix(); |
86
|
|
|
|
87
|
75 |
|
$content = $this->loadContent($this->file); |
88
|
67 |
|
$this->raw_content = $content; |
89
|
|
|
|
90
|
67 |
|
if ($content) { |
91
|
63 |
|
$this->content = $this->searchForResources($content, $store_prefix); |
92
|
|
|
} |
93
|
64 |
|
} |
94
|
|
|
|
95
|
|
|
/** |
96
|
|
|
* Make the paths used for the filename variable |
97
|
|
|
* |
98
|
|
|
* @param string $file The passed file |
99
|
|
|
*/ |
100
|
75 |
|
private function makePaths($file) |
101
|
|
|
{ |
102
|
75 |
|
$file = realpath($file); |
103
|
|
|
|
104
|
75 |
|
$base_path = $this->provider->vars->getPath(); |
105
|
|
|
|
106
|
75 |
|
$filesystem = new Filesystem(); |
107
|
75 |
|
$abs_path = $filesystem->makePathRelative( |
108
|
75 |
|
$file, |
109
|
75 |
|
$base_path |
110
|
|
|
); |
111
|
|
|
|
112
|
75 |
|
$this->file = $file; |
113
|
75 |
|
$this->filename = rtrim($abs_path, "/"); |
114
|
75 |
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Search for imports in the files and does the replacement variables |
118
|
|
|
* |
119
|
|
|
* @param mixed $content The file content received from the loader |
120
|
|
|
* @param string $prefix The array prefix for the entity |
121
|
|
|
* |
122
|
|
|
* @return array Returns the parsed content |
123
|
|
|
*/ |
124
|
63 |
|
private function searchForResources($content = array(), $prefix = '') |
125
|
|
|
{ |
126
|
63 |
|
$returned_content = array(); |
127
|
|
|
|
128
|
63 |
|
foreach ($content as $ck => $cv) { |
129
|
63 |
|
$this->variables->vstore->setCurrentPrefix($prefix); |
130
|
63 |
|
$returned_content = $this->parseContent($ck, $cv, $returned_content, $prefix); |
131
|
|
|
} |
132
|
|
|
|
133
|
60 |
|
return $returned_content; |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Parses the contents inside the content array |
138
|
|
|
* |
139
|
|
|
* @param mixed $key The key of the content array |
140
|
|
|
* @param mixed $value The value of the key |
141
|
|
|
* @param array $returned_content The modified content array to return |
142
|
|
|
* @param string $prefix The array prefix for the entity |
143
|
|
|
* |
144
|
|
|
* @return array Returns the modified content array |
145
|
|
|
*/ |
146
|
63 |
|
private function parseContent($key, $value, $returned_content, $prefix) |
147
|
|
|
{ |
148
|
63 |
|
if ($key === 'imports' && !is_null($value) && !empty($value)) { |
149
|
53 |
|
$imported_resource = $this->useImports($value); |
150
|
|
|
|
151
|
51 |
|
if ($imported_resource) { |
|
|
|
|
152
|
51 |
|
$returned_content = array_replace_recursive($returned_content, $imported_resource); |
153
|
|
|
} |
154
|
58 |
|
} elseif (is_array($value)) { |
155
|
15 |
|
$returned_content[$key] = $this->searchForResources( |
156
|
15 |
|
$value, |
157
|
15 |
|
$this->variables->vstore->createPrefixName($prefix, $key) |
158
|
|
|
); |
159
|
|
|
} else { |
160
|
58 |
|
$value = $this->parseText($value); |
161
|
57 |
|
$this->variables->vstore->set($prefix.$key, $value); |
162
|
57 |
|
$returned_content[$key] = $value; |
163
|
|
|
} |
164
|
|
|
|
165
|
60 |
|
return $returned_content; |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* Parses the text for option and environment replacements and replaces the text |
170
|
|
|
* |
171
|
|
|
* @param string $text The text to be parsed |
172
|
|
|
* |
173
|
|
|
* @return string|null The parsed string |
174
|
|
|
*/ |
175
|
63 |
|
private function parseText($text) |
176
|
|
|
{ |
177
|
63 |
|
if (is_string($text)) { |
178
|
63 |
|
return $this->variables->parse($text); |
179
|
|
|
} |
180
|
|
|
|
181
|
10 |
|
return $text; |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* Use the import arrays to import resources |
186
|
|
|
* |
187
|
|
|
* @param mixed $imports The resources wanting to be imported |
188
|
|
|
* |
189
|
|
|
* @return array The parsed imported resources |
190
|
|
|
*/ |
191
|
53 |
|
private function useImports($imports) |
192
|
|
|
{ |
193
|
53 |
|
$imported_resources = array(); |
194
|
|
|
|
195
|
53 |
|
if ((is_array($imports) && $this->isAssoc($imports)) || is_string($imports)) { |
196
|
47 |
|
$imports = array($imports); |
197
|
|
|
} |
198
|
|
|
|
199
|
53 |
|
foreach ($imports as $import) { |
|
|
|
|
200
|
53 |
|
$imported_resources = $this->processImport($this->parseText($import), $imported_resources); |
201
|
|
|
} |
202
|
|
|
|
203
|
51 |
|
return $imported_resources; |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* Processes the import and gets individual import if set and passes them off to import2Resources() |
208
|
|
|
* |
209
|
|
|
* @param mixed $import The import to be processed |
210
|
|
|
* @param array $imported_resources The array of imported resources |
211
|
|
|
* |
212
|
|
|
* @return array The parsed imported resources |
213
|
|
|
*/ |
214
|
53 |
|
private function processImport($import, array $imported_resources) |
215
|
|
|
{ |
216
|
53 |
|
if (is_array($import) && array_key_exists('resource', $import) && is_array($import['resource'])) { |
217
|
1 |
|
foreach ($import['resource'] as $resource) { |
218
|
|
|
$temp = array( |
219
|
1 |
|
'resource' => $resource, |
220
|
1 |
|
'relative' => $this->checkBooleanValue('relative', $import), |
221
|
1 |
|
'recursive' => $this->checkBooleanValue('recursive', $import), |
222
|
|
|
); |
223
|
|
|
|
224
|
1 |
|
$imported_resources = $this->import2Resource($temp, $imported_resources); |
225
|
|
|
} |
226
|
|
|
} else { |
227
|
53 |
|
$imported_resources = $this->import2Resource($import, $imported_resources); |
228
|
|
|
} |
229
|
|
|
|
230
|
51 |
|
return $imported_resources; |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
/** |
234
|
|
|
* Creates the resource from the import then imports it |
235
|
|
|
* |
236
|
|
|
* @param array|string $import The string|array to be converted to a resource |
237
|
|
|
* @param array $imported_resources The array of imported resources |
238
|
|
|
* |
239
|
|
|
* @return array The imported resources |
240
|
|
|
*/ |
241
|
53 |
|
private function import2Resource($import, array $imported_resources) |
242
|
|
|
{ |
243
|
53 |
|
$resource = $this->createResource($import); |
244
|
|
|
|
245
|
51 |
|
if ($resource) { |
246
|
51 |
|
$imported_resources = $this->importResource($resource, $imported_resources); |
247
|
|
|
} |
248
|
|
|
|
249
|
51 |
|
return $imported_resources; |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* Creates resource from the import |
254
|
|
|
* |
255
|
|
|
* @param array|string $import The import to create a resource from |
256
|
|
|
* |
257
|
|
|
* @return \M1\Vars\Resource\ResourceProvider The resource of the import |
258
|
|
|
*/ |
259
|
53 |
|
private function createResource($import) |
260
|
|
|
{ |
261
|
53 |
|
if (is_array($import) && array_key_exists('resource', $import)) { |
262
|
10 |
|
$import_resource = $import; |
263
|
10 |
|
$import_resource['relative'] = $this->checkBooleanValue('relative', $import_resource); |
264
|
10 |
|
$import_resource['recursive'] = $this->checkBooleanValue('recursive', $import_resource); |
265
|
44 |
|
} elseif (is_string($import)) { |
266
|
44 |
|
$import_resource = array('resource' => $import, 'relative' => true, 'recursive' => true); |
267
|
|
|
} |
268
|
|
|
|
269
|
53 |
|
$import_resource = new ResourceProvider( |
270
|
53 |
|
$this->provider->vars, |
271
|
53 |
|
$this->createImportName($import_resource['resource']), |
|
|
|
|
272
|
53 |
|
$import_resource['relative'], |
|
|
|
|
273
|
53 |
|
$import_resource['recursive'] |
|
|
|
|
274
|
|
|
); |
275
|
|
|
|
276
|
51 |
|
return $import_resource; |
277
|
|
|
} |
278
|
|
|
|
279
|
|
|
/** |
280
|
|
|
* Creates the correctly formatted resource name with paths |
281
|
|
|
* |
282
|
|
|
* @param string $resource The resource to create the import name for |
283
|
|
|
* |
284
|
|
|
* @return string The parsed resource |
285
|
|
|
*/ |
286
|
53 |
|
private function createImportName($resource) |
287
|
|
|
{ |
288
|
53 |
|
$resource = $this->explodeResourceIfElse($resource); |
289
|
53 |
|
$resource_pieces = array(); |
290
|
|
|
|
291
|
53 |
|
foreach ($resource as $r) { |
292
|
53 |
|
$parsed_r = $this->trimFlags($r); |
293
|
53 |
|
$parsed_r = sprintf('%s/%s', dirname($this->file), $parsed_r); |
294
|
53 |
|
$parsed_r = $this->replicateFlags($parsed_r, $r); |
295
|
|
|
|
296
|
53 |
|
$resource_pieces[] = $parsed_r; |
297
|
|
|
} |
298
|
|
|
|
299
|
53 |
|
return $this->implodeResourceIfElse($resource_pieces); |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
/** |
303
|
|
|
* Import resource into the imported resources and merge contents |
304
|
|
|
* |
305
|
|
|
* @param ResourceProvider $provider The new imported resource |
306
|
|
|
* @param array $imported_resources The imported resources |
307
|
|
|
* |
308
|
|
|
* @return array The modified imported resources |
309
|
|
|
*/ |
310
|
51 |
|
private function importResource(ResourceProvider $provider, $imported_resources) |
311
|
|
|
{ |
312
|
51 |
|
$content = $provider->getContent(); |
313
|
51 |
|
$parent_content = $provider->getParentContent(); |
314
|
|
|
|
315
|
51 |
|
if (!empty($content)) { |
316
|
48 |
|
$imported_resources = array_replace_recursive($imported_resources, $content); |
317
|
|
|
} |
318
|
|
|
|
319
|
51 |
|
if (!empty($parent_content)) { |
320
|
7 |
|
$this->provider->addParentContent($parent_content); |
321
|
|
|
} |
322
|
|
|
|
323
|
51 |
|
return $imported_resources; |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
/** |
327
|
|
|
* Returns whether the passed array is associative |
328
|
|
|
* |
329
|
|
|
* @param array $array The passed array |
330
|
|
|
* |
331
|
|
|
* @return bool Is the passed array associative |
332
|
|
|
*/ |
333
|
11 |
|
private function isAssoc(array $array) |
334
|
|
|
{ |
335
|
11 |
|
return array_keys($array) !== range(0, count($array) - 1); |
336
|
|
|
} |
337
|
|
|
|
338
|
|
|
/** |
339
|
|
|
* Checks if the passed boolean value is true or false |
340
|
|
|
* |
341
|
|
|
* @param string $value The value to check |
342
|
|
|
* @param mixed $import The passed import |
343
|
|
|
* |
344
|
|
|
* @return bool Returns the value of the boolean |
345
|
|
|
*/ |
346
|
10 |
|
public function checkBooleanValue($value, $import) |
347
|
|
|
{ |
348
|
10 |
|
$default = false; |
349
|
|
|
|
350
|
10 |
|
if ($value === 'relative') { |
351
|
10 |
|
$default = true; |
352
|
|
|
} |
353
|
|
|
|
354
|
10 |
|
$value = (isset($import[$value])) ? $import[$value] : $default; |
355
|
|
|
|
356
|
10 |
|
return $this->getBooleanValue($value); |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
/** |
360
|
|
|
* Gets the boolean value from the string |
361
|
|
|
* |
362
|
|
|
* @param string $value The value to check |
363
|
|
|
* |
364
|
|
|
* @return bool Returns the value of the boolean |
365
|
|
|
*/ |
366
|
10 |
|
private function getBooleanValue($value) |
367
|
|
|
{ |
368
|
10 |
|
$value = strtolower($value); |
369
|
|
|
|
370
|
10 |
|
if (!$value || $value === "false" || $value === "no") { |
371
|
10 |
|
return false; |
372
|
|
|
} |
373
|
|
|
|
374
|
9 |
|
return true; |
375
|
|
|
} |
376
|
|
|
|
377
|
|
|
/** |
378
|
|
|
* Returns the filename of the resource |
379
|
|
|
* |
380
|
|
|
* @return string The filename |
381
|
|
|
*/ |
382
|
3 |
|
public function getFilename() |
383
|
|
|
{ |
384
|
3 |
|
return $this->filename; |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
/** |
388
|
|
|
* Returns the raw content of the resource |
389
|
|
|
* |
390
|
|
|
* @return array|mixed The raw content |
391
|
|
|
*/ |
392
|
1 |
|
public function getRawContent() |
393
|
|
|
{ |
394
|
1 |
|
return $this->raw_content; |
395
|
|
|
} |
396
|
|
|
} |
397
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.