1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* base abstract for import based commands where a bunch of file must be collected and |
4
|
|
|
* done something with them.. |
5
|
|
|
*/ |
6
|
|
|
|
7
|
|
|
namespace Graviton\ImportExport\Command; |
8
|
|
|
|
9
|
|
|
use Graviton\ImportExport\Exception\MissingTargetException; |
10
|
|
|
use Symfony\Component\Console\Command\Command; |
11
|
|
|
use Symfony\Component\Console\Helper\ProgressBar; |
12
|
|
|
use Symfony\Component\Console\Input\InputArgument; |
13
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
14
|
|
|
use Symfony\Component\Console\Input\InputOption; |
15
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
16
|
|
|
use Symfony\Component\Finder\Finder; |
17
|
|
|
use Symfony\Component\Finder\SplFileInfo; |
18
|
|
|
use Symfony\Component\Yaml\Exception\ParseException; |
19
|
|
|
use Webuni\FrontMatter\FrontMatter; |
20
|
|
|
use Webuni\FrontMatter\Document; |
21
|
|
|
use Symfony\Component\Yaml\Parser as YmlParser; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* @author List of contributors <https://github.com/libgraviton/import-export/graphs/contributors> |
25
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GNU Public License |
26
|
|
|
* @link http://swisscom.ch |
27
|
|
|
*/ |
28
|
|
|
class ValidationCommand extends Command |
29
|
|
|
{ |
30
|
|
|
/** |
31
|
|
|
* @var FrontMatter |
32
|
|
|
*/ |
33
|
|
|
private $frontMatter; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @var YmlParser |
37
|
|
|
*/ |
38
|
|
|
private $ymlParser; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* Error array for validation |
42
|
|
|
* @var array |
43
|
|
|
*/ |
44
|
|
|
private $validationErrors = []; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* @param FrontMatter $frontMatter frontmatter parser |
48
|
|
|
* @param YmlParser $parser yaml parser |
49
|
|
|
*/ |
50
|
|
|
public function __construct( |
51
|
|
|
FrontMatter $frontMatter, |
52
|
|
|
YmlParser $parser |
53
|
|
|
) { |
54
|
|
|
$this->frontMatter = $frontMatter; |
55
|
|
|
$this->ymlParser = $parser; |
56
|
|
|
parent::__construct(); |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Configures the current command. |
61
|
|
|
* |
62
|
|
|
* @return void |
63
|
|
|
*/ |
64
|
|
|
protected function configure() |
65
|
|
|
{ |
66
|
|
|
$this |
67
|
|
|
->setName('graviton:validate:import') |
68
|
|
|
->setDescription('Import files from a folder or file.') |
69
|
|
|
->addArgument( |
70
|
|
|
'file', |
71
|
|
|
InputArgument::REQUIRED + InputArgument::IS_ARRAY, |
72
|
|
|
'Directories or files to load' |
73
|
|
|
); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* Executes the current command. |
78
|
|
|
* |
79
|
|
|
* @param InputInterface $input User input on console |
80
|
|
|
* @param OutputInterface $output Output of the command |
81
|
|
|
* |
82
|
|
|
* @return integer |
83
|
|
|
*/ |
84
|
|
|
protected function execute(InputInterface $input, OutputInterface $output) |
85
|
|
|
{ |
86
|
|
|
$files = $input->getArgument('file'); |
87
|
|
|
$finder = new Finder(); |
88
|
|
|
$finder = $finder->files(); |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* @param SplFileInfo $file |
92
|
|
|
* @return bool |
93
|
|
|
*/ |
94
|
|
View Code Duplication |
$filter = function (SplFileInfo $file) { |
|
|
|
|
95
|
|
|
if (!in_array($file->getExtension(), ['yml','json']) || $file->isDir()) { |
96
|
|
|
return false; |
97
|
|
|
} |
98
|
|
|
return true; |
99
|
|
|
}; |
100
|
|
|
|
101
|
|
View Code Duplication |
foreach ($files as $file) { |
|
|
|
|
102
|
|
|
if (is_file($file)) { |
103
|
|
|
$finder->in(dirname($file))->name(basename($file)); |
104
|
|
|
} else { |
105
|
|
|
$finder->in($file); |
106
|
|
|
} |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
$finder->ignoreDotFiles(true)->filter($filter); |
110
|
|
|
|
111
|
|
|
$this->validateFiles($finder, $output); |
|
|
|
|
112
|
|
|
|
113
|
|
|
$output->writeln("\n".'<info>Finished</info>'); |
114
|
|
|
|
115
|
|
|
if (!empty($this->validationErrors)) { |
116
|
|
|
$output->writeln("\n".'<error>With: '.count($this->validationErrors).' Errors</error>'); |
117
|
|
|
foreach ($this->validationErrors as $file => $error) { |
118
|
|
|
$output->writeln('<comment>'.strstr($file, '/initialdata/').': '.$error.'</comment>'); |
119
|
|
|
} |
120
|
|
|
} else { |
121
|
|
|
$output->writeln("\n".'<info>You are awesome! No Errors detected.</info>'); |
122
|
|
|
} |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* Will check and validate initial file information |
127
|
|
|
* |
128
|
|
|
* @param Finder $finder File Finder by SF |
129
|
|
|
* @param OutputInterface $output Print to command line |
130
|
|
|
* @return void |
131
|
|
|
*/ |
132
|
|
|
private function validateFiles(Finder $finder, OutputInterface $output) |
133
|
|
|
{ |
134
|
|
|
$count = $finder->count(); |
135
|
|
|
$output->writeln("\n".'<info>Validation will be done for: '.$count.' files </info>'); |
136
|
|
|
|
137
|
|
|
$progress = new ProgressBar($output, $count); |
138
|
|
|
|
139
|
|
|
foreach ($finder->files() as $file) { |
140
|
|
|
$progress->advance(); |
141
|
|
|
$path = str_replace('//', '/', $file->getPathname()); |
142
|
|
|
|
143
|
|
|
// To check file core db import structure or for PUT |
144
|
|
|
$fileType = strpos($path, '/data/param/') !== false ? 'param' : 'core'; |
145
|
|
|
|
146
|
|
|
/** @var Document $doc */ |
147
|
|
|
$doc = $this->frontMatter->parse($file->getContents()); |
148
|
|
|
$docHeader = $doc->getData(); |
149
|
|
|
|
150
|
|
|
if ('core' == $fileType) { |
151
|
|
View Code Duplication |
if (!array_key_exists('collection', $docHeader) || empty($docHeader['collection'])) { |
|
|
|
|
152
|
|
|
$this->validationErrors[$path] = 'Core import, header "collection" is required'; |
153
|
|
|
continue; |
154
|
|
|
} |
155
|
|
View Code Duplication |
} else { |
|
|
|
|
156
|
|
|
if (!array_key_exists('target', $docHeader) || empty($docHeader['target'])) { |
157
|
|
|
$this->validationErrors[$path] = 'Param import, header "target" is required'; |
158
|
|
|
continue; |
159
|
|
|
} |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
$this->parseContent($doc->getContent(), $path, $file->getExtension()); |
163
|
|
|
} |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* parse contents of a file depending on type |
168
|
|
|
* |
169
|
|
|
* @param string $content contents part of file |
170
|
|
|
* @param string $path full path to file |
171
|
|
|
* @param string $extension File extension json or yml |
172
|
|
|
* |
173
|
|
|
* @return void |
174
|
|
|
*/ |
175
|
|
|
protected function parseContent($content, $path, $extension) |
176
|
|
|
{ |
177
|
|
|
switch ($extension) { |
178
|
|
|
case 'json': |
179
|
|
|
$data = json_decode($content); |
180
|
|
|
if (json_last_error() !== JSON_ERROR_NONE) { |
181
|
|
|
$this->validationErrors[$path] = json_last_error_msg(); |
182
|
|
|
} |
183
|
|
|
break; |
184
|
|
|
case 'yml': |
185
|
|
|
try { |
186
|
|
|
$data = $this->ymlParser->parse($content); |
187
|
|
|
} catch (ParseException $e) { |
188
|
|
|
$this->validationErrors[$path] = $e->getMessage(); |
189
|
|
|
} |
190
|
|
|
break; |
191
|
|
|
default: |
192
|
|
|
$this->validationErrors[$path] = 'UnknownFileTypeException'; |
193
|
|
|
}; |
194
|
|
|
|
195
|
|
|
if (empty($data) && !array_key_exists($path, $this->validationErrors)) { |
196
|
|
|
$this->validationErrors[$path] = 'Returned empty yml data'; |
197
|
|
|
} |
198
|
|
|
} |
199
|
|
|
} |
200
|
|
|
|
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.