Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
MetadataGenerator.php
Go to the documentation of this file.
1 <?php
7 
8 use Doctrine\Common\Collections\ArrayCollection;
9 use Epfremme\Swagger\Entity\Schemas\SchemaInterface;
10 use Epfremme\Swagger\Entity\Schemas\ObjectSchema;
11 use Epfremme\Swagger\Entity\Schemas\RefSchema;
12 use Epfremme\Swagger\Entity\Schemas\ArraySchema;
13 use Epfremme\Swagger\Factory\SwaggerFactory;
14 use Epfremme\Swagger\Entity\Swagger;
15 use Epfremme\Swagger\Entity\Operation;
16 use Epfremme\Swagger\Entity\Parameters\BodyParameter;
17 use Epfremme\Swagger\Entity\Parameters\AbstractTypedParameter;
18 use Mustache_Engine;
19 use Mustache_Loader_FilesystemLoader;
20 
22 {
23  const OUTPUT_DIR = '_operations';
24  const OUTPUT_DIR2 = '_definitions';
25  const INPUT_TXT_FILE = 'magento.json';
26  const AUTH = 'adminOauth';
27  const TEMPLATE_VAR_DEF_TYPE = 'create';
28 
29  const TEMPLATE_VAR_OP_NAME = 'operationName';
30  const TEMPLATE_VAR_OP_DATATYPE = 'operationDataType';
31  const TEMPLATE_VAR_OP_TYPE = 'operationType';
32  const TEMPLATE_VAR_OP_AUTH = 'auth';
33  const TEMPLATE_VAR_OP_URL = 'operationUrl';
34  const TEMPLATE_VAR_OP_METHOD = 'method';
35 
36  const TEMPLATE_VAR_OP_FIELD = 'fields';
37  const TEMPLATE_VAR_FIELD_NAME = 'fieldName';
38  const TEMPLATE_VAR_FIELD_TYPE = 'fieldType';
39  const TEMPLATE_VAR_FIELD_IS_REQUIRED = 'isRequired';
40 
41  const TEMPLATE_VAR_OP_PARAM = 'params';
42  const TEMPLATE_VAR_PARAM_NAME = 'paramName';
43  const TEMPLATE_VAR_PARAM_TYPE = 'paramType';
44 
45  const TEMPLATE_VAR_OP_ARRAY = 'arrays';
46  const TEMPLATE_VAR_ARRAY_KEY = 'arrayKey';
47  const TEMPLATE_VAR_ARRAY_IS_REQUIRED = 'isRequiredArray';
48  const TEMPLATE_VAR_VALUES = 'values';
49  const TEMPLATE_VAR_VALUE = 'value';
50 
51  const REF_REGEX = "~#/definitions/([\S]+)~";
52 
58  private $mustache_engine;
59 
65  private static $swagger;
66 
72  private $pathParams;
73 
79  private $params;
80 
86  private $fields;
87 
93  private $filepath;
94 
100  private static $methodMapping = [
101  'POST' => 'create',
102  'DELETE' => 'delete',
103  'PUT' => 'update',
104  'GET' => 'get',
105  ];
106 
110  public function __construct()
111  {
112  self::buildSwaggerSpec();
113  $this->initMustacheTemplates();
114  }
115 
122  public function generateMetadataFromSwagger()
123  {
124  $paths = self::$swagger->getPaths();
125 
126  foreach ($paths->getIterator() as $pathKey => $path) {
127  $operations = $path->getOperations();
128  foreach ($operations->getIterator() as $operationKey => $operation) {
129  $this->renderOperation($operation, $pathKey, $operationKey);
130  }
131  }
132 
133  $definitions = self::$swagger->getDefinitions();
134  foreach ($definitions->getIterator() as $defKey => $definition) {
135  $this->renderDefinition($defKey, $definition);
136  }
137  }
138 
147  private function renderOperation($operation, $path, $method)
148  {
149  $operationArray = [];
150  $this->pathParams = '';
151  $this->params = [];
152  $this->fields = [];
153  $operationMethod = strtoupper($method);
154  $operationDataType = ucfirst($operation->getOperationId());
155 
156  $operationArray[self::TEMPLATE_VAR_OP_NAME] = self::$methodMapping[$operationMethod] . $operationDataType;
157  $operationArray[self::TEMPLATE_VAR_OP_DATATYPE] = $operationDataType;
158  $operationArray[self::TEMPLATE_VAR_OP_METHOD] = $operationMethod;
159  $operationArray[self::TEMPLATE_VAR_OP_AUTH] = self::AUTH;
160  $operationArray[self::TEMPLATE_VAR_OP_TYPE] = self::$methodMapping[$operationMethod];
161  $operationArray[self::TEMPLATE_VAR_OP_URL] = $path;
162 
163  $params = $operation->getParameters();
164  if (!empty($params)) {
165  $this->parseParams($params, $path);
166  $operationArray[self::TEMPLATE_VAR_OP_FIELD] = $this->fields;
167  $operationArray[self::TEMPLATE_VAR_OP_PARAM] = $this->params;
168  }
169 
170  if (!empty($this->pathParams)) {
171  $operationArray[self::TEMPLATE_VAR_OP_URL] .= $this->pathParams;
172  }
173 
174  $this->generateMetaDataFile(
175  self::OUTPUT_DIR,
176  $operationDataType,
177  'operation',
178  $operationArray
179  );
180  }
181 
189  private function renderDefinition($defKey, $definition)
190  {
191  $operationArray = [];
192  $this->fields = [];
193 
194  $operationArray[self::TEMPLATE_VAR_OP_NAME] = $defKey;
195  $operationArray[self::TEMPLATE_VAR_OP_DATATYPE] = $defKey;
197 
198  if ($definition instanceof ObjectSchema) {
199  $properties = $definition->getProperties();
200  if (!empty($properties)) {
201  $dataField = [];
202  $dataArray = [];
203  foreach ($properties->getIterator() as $propertyKey => $property) {
204  if ($property instanceof ArraySchema) {
205  $dataArray[] = $this->parseSchema($property, $propertyKey, 1, 1);
206  } else {
207  $dataField[] = $this->parseSchema($property, $propertyKey, 0, 1);
208  }
209  }
210  if (!empty($dataField)) {
211  $operationArray[self::TEMPLATE_VAR_OP_FIELD] = $dataField;
212  }
213  if (!empty($dataArray)) {
214  foreach ($dataArray as $array) {
215  $operationArray[self::TEMPLATE_VAR_OP_ARRAY.'1'][] = $array[self::TEMPLATE_VAR_OP_ARRAY.'1'];
216  }
217  }
218  }
219  } elseif ($definition instanceof ArraySchema) {
220  $operationArray = array_merge($operationArray, $this->parseSchema($definition, $defKey, 1, 1));
221  }
222 
223  $this->generateMetaDataFile(
224  self::OUTPUT_DIR2,
225  $defKey,
226  'definition',
227  $operationArray
228  );
229  }
230 
240  private function parseSchema($schema, $name, $forArray, $depth)
241  {
242  $data = [];
243 
244  if ($schema instanceof RefSchema) {
245  $ref = $schema->getRef();
246  preg_match(self::REF_REGEX, $ref, $matches);
247  if (count($matches) == 2) {
248  if (!$forArray) {
250  $data[self::TEMPLATE_VAR_FIELD_TYPE] = $matches[1];
251  } else {
252  $data[self::TEMPLATE_VAR_VALUES][] = [self::TEMPLATE_VAR_VALUE => $matches[1]];
253  }
254  }
255  } elseif ($schema instanceof ArraySchema) {
256  $values = [];
257  $items = $schema->getItems();
258  $data[self::TEMPLATE_VAR_OP_ARRAY.$depth][self::TEMPLATE_VAR_ARRAY_KEY] = $name;
259  if ($items instanceof ArrayCollection) {
260  foreach ($items->getIterator() as $itemKey => $item) {
261  $values[] = $this->parseSchema($item, $itemKey, 1, $depth+1);
262  }
264  $data[self::TEMPLATE_VAR_OP_ARRAY.$depth] = $data;
265  } else {
266  $data[self::TEMPLATE_VAR_OP_ARRAY.$depth] = array_merge(
267  $data[self::TEMPLATE_VAR_OP_ARRAY.$depth],
268  $this->parseSchema($items, $name, 1, $depth+1)
269  );
270  }
271  } else {
272  if (method_exists($schema, 'getType')) {
273  if (!$forArray) {
276  } else {
277  $data[self::TEMPLATE_VAR_VALUES][] = [self::TEMPLATE_VAR_VALUE => $schema->getType()];
278  }
279  }
280  }
281  return $data;
282  }
283 
291  private function parseParams($params, $path)
292  {
293  foreach ($params->getIterator() as $paramKey => $param) {
294  if (empty($param)) {
295  continue;
296  }
297 
298  $paramIn = $param->getIn();
299  if ($paramIn == 'body') {
300  $this->setBodyParams($param);
301  } elseif ($paramIn == 'path') {
302  $this->setPathParams($param, $path);
303  } elseif ($paramIn == 'query') {
304  $this->setQueryParams($param);
305  }
306  }
307  }
308 
315  private function setBodyParams($param)
316  {
317  $this->fields = [];
318  $required = [];
319 
320  $paramSchema = $param->getSchema();
321  $paramSchemaRequired = $paramSchema->getRequired();
322  if (!empty($paramSchemaRequired)) {
323  foreach ($paramSchemaRequired as $i => $key) {
324  $required[] = $key;
325  }
326  }
327  $paramSchemaProperties = $paramSchema->getProperties();
328  foreach ($paramSchemaProperties->getIterator() as $paramPropertyKey => $paramSchemaProperty) {
329  $field = [];
330  $field[self::TEMPLATE_VAR_FIELD_NAME] = $paramPropertyKey;
331  $field[self::TEMPLATE_VAR_FIELD_TYPE] = $paramSchemaProperty->getType();
332  if ($field[self::TEMPLATE_VAR_FIELD_TYPE] == 'ref') {
333  preg_match(self::REF_REGEX, $paramSchemaProperty->getRef(), $matches);
334  if (count($matches) == 2) {
335  $field[self::TEMPLATE_VAR_FIELD_TYPE] = $matches[1];
336  }
337  }
338  if (in_array($paramPropertyKey, $required)) {
339  $field[self::TEMPLATE_VAR_FIELD_IS_REQUIRED] = 'true';
340  } else {
341  $field[self::TEMPLATE_VAR_FIELD_IS_REQUIRED] = 'false';
342  }
343  $this->fields[] = $field;
344  }
345  }
346 
354  private function setPathParams($param, $path)
355  {
356  $pathParamStr = '{' . $param->getName() . '}';
357  if (strpos($path, $pathParamStr) === false) {
358  $this->pathParams .= '/' . $pathParamStr;
359  }
360  }
361 
368  private function setQueryParams($param)
369  {
370  $query = [];
371  $query[self::TEMPLATE_VAR_PARAM_NAME] = $param->getName();
372  $query[self::TEMPLATE_VAR_PARAM_TYPE] = $param->getType();
373 
374  $this->params[] = $query;
375  }
376 
382  private static function buildSwaggerSpec()
383  {
384  $factory = new SwaggerFactory();
385  self::$swagger = $factory->build(self::INPUT_TXT_FILE);
386  }
387 
393  private function initMustacheTemplates()
394  {
395  $this->mustache_engine = new Mustache_Engine(
396  ['loader' => new Mustache_Loader_FilesystemLoader("views"),
397  'partials_loader' => new Mustache_Loader_FilesystemLoader(
398  "views" . DIRECTORY_SEPARATOR . "partials"
399  )]
400  );
401  }
402 
412  private function generateMetaDataFile($relativeDir, $fileName, $template, $data)
413  {
414  $this->filepath = $relativeDir . DIRECTORY_SEPARATOR . $fileName . "-meta.xml";
415  $result = $this->mustache_engine->render($template, $data);
416  $this->cleanAndCreateOutputDir();
418  $this->filepath,
419  $result
420  );
421  }
422 
428  private function cleanAndCreateOutputDir()
429  {
430  if (!file_exists(self::OUTPUT_DIR)) {
431  mkdir(self::OUTPUT_DIR);
432  }
433 
434  if (!file_exists(self::OUTPUT_DIR2)) {
435  mkdir(self::OUTPUT_DIR2);
436  }
437 
438  if (file_exists($this->filepath)) {
439  unlink($this->filepath);
440  }
441  }
442  /*
443  private static function debugData() {
444  $paramsExample = ['params' =>
445  [
446  'paramName' => 'name',
447  'paramType' => 'type'
448  ],
449  [
450  'paramName' => 'name',
451  'paramType' => 'type'
452  ],
453  [
454  'paramName' => 'name',
455  'paramType' => 'type'
456  ],
457  ];
458  $fieldsExample = ['fields' =>
459  [
460  'fieldName' => 'name',
461  'fieldType' => 'type',
462  'isRequired' => true,
463  ],
464  [
465  'fieldName' => 'name',
466  'fieldType' => 'type',
467  'isRequired' => true,
468  ],
469  [
470  'fieldName' => 'name',
471  'fieldType' => 'type',
472  'isRequired' => true,
473  ],
474  ];
475  $arraysExample = ['arrays1' =>
476  [
477  'arrayKey' => 'someKey',
478  'values' => [
479  'type1',
480  'type2',
481  ],
482  'arrays2' => [
483  'arrayKey' => 'otherKey',
484  'values' => [
485  'type3',
486  'type4',
487  ],
488  'arrays3' => [
489  'arrayKey' => 'anotherKey',
490  'values' => [
491  'type5',
492  'type6',
493  ],
494  ],
495  ],
496  ],
497  [
498  'arrayKey' => 'someKey',
499  'values' => [
500  [
501  'value' => 'type1',
502  ],
503  [
504  'value' => 'type2',
505  ],
506  ],
507  'arrays2' => [
508  'arrayKey' => 'otherKey',
509  'values' => [
510  [
511  'value' => 'type3',
512  ],
513  [
514  'value' => 'type4',
515  ],
516  ],
517  'arrays3' => [
518  'arrayKey' => 'anotherKey',
519  'values' => [
520  [
521  'value' => 'type5',
522  ],
523  [
524  'value' => 'type6',
525  ],
526  ],
527  ],
528  ],
529  ],
530  ];
531  }
532  */
533 }
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
$operations
Definition: bulk.php:55
$values
Definition: options.phtml:88
$fileName
Definition: translate.phtml:15
const INPUT_TXT_FILE
$method
Definition: info.phtml:13
mkdir($pathname, $mode=0777, $recursive=false, $context=null)
Definition: ioMock.php:25
$properties
Definition: categories.php:26
$paths
Definition: _bootstrap.php:83
$i
Definition: gallery.phtml:31
$template
Definition: export.php:12
$items
$required
Definition: wrapper.phtml:8
if(!isset($_GET['name'])) $name
Definition: log.php:14