Passed
Pull Request — master (#195)
by
unknown
09:41 queued 02:26
created

ParserGenerator::setFileData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 4
rs 10
1
<?php
2
namespace EWW\Dpf\Services;
3
4
/*
5
 * This file is part of the TYPO3 CMS project.
6
 *
7
 * It is free software; you can redistribute it and/or modify it under
8
 * the terms of the GNU General Public License, either version 2
9
 * of the License, or any later version.
10
 *
11
 * For the full copyright and license information, please read the
12
 * LICENSE.txt file that was distributed with this source code.
13
 *
14
 * The TYPO3 project - inspiring people to share!
15
 */
16
17
use EWW\Dpf\Configuration\ClientConfigurationManager;
18
use EWW\Dpf\Domain\Repository\DocumentTypeRepository;
19
use EWW\Dpf\Helper\XSLTransformator;
0 ignored issues
show
Bug introduced by
The type EWW\Dpf\Helper\XSLTransformator was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
20
use TYPO3\CMS\Extbase\Object\ObjectManager;
21
use EWW\Dpf\Services\Transformer\DocumentTransformer;
22
23
/**
24
 * ParserGenerator
25
 */
26
class ParserGenerator
27
{
28
    /**
29
     * clientConfigurationManager
30
     *
31
     * @var \EWW\Dpf\Configuration\ClientConfigurationManager
32
     * @inject
33
     */
34
    protected $clientConfigurationManager;
35
36
    /**
37
     * documentTypeRepository
38
     *
39
     * @var \EWW\Dpf\Domain\Repository\DocumentTypeRepository
40
     */
41
    protected $documentTypeRepository = null;
42
43
    /**
44
     * formData
45
     *
46
     * @var array
47
     */
48
    protected $formData = array();
49
50
    /**
51
     * files from form
52
     * @var array
53
     */
54
    protected $files = array();
55
56
    /**
57
     * metsData
58
     *
59
     * @var  DOMDocument
0 ignored issues
show
Bug introduced by
The type EWW\Dpf\Services\DOMDocument was not found. Did you mean DOMDocument? If so, make sure to prefix the type with \.
Loading history...
60
     */
61
    protected $metsData = '';
62
63
    /**
64
     * xml data
65
     * @var DOMDocument
66
     */
67
    protected $xmlData = '';
68
69
    /**
70
     * xml header
71
     * @var string
72
     */
73
    protected $xmlHeader = '';
74
75
    /**
76
     * xPathXMLGenerator
77
     * @var object
78
     */
79
    protected $parser = null;
80
81
    /**
82
     * ref id counter
83
     */
84
    protected $counter = 0;
85
86
    /**
87
     * namespaces as string
88
     * @var string
89
     */
90
    protected $namespaceString = '';
91
92
93
    /**
94
     * Constructor
95
     */
96
    public function __construct()
97
    {
98
        $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ObjectManager::class);
99
        $this->clientConfigurationManager = $objectManager->get(ClientConfigurationManager::class);
100
101
        $this->documentTypeRepository = $objectManager->get(DocumentTypeRepository::class);
102
103
        $namespaceConfiguration = explode(";",$this->clientConfigurationManager->getNamespaces());
104
105
106
        foreach ($namespaceConfiguration as $key => $value) {
107
            $namespace = explode("=", $value);
108
            $this->namespaceString .= ' xmlns:' . $namespace[0] . '="' . $namespace[1] . '"';
109
        }
110
111
        $this->xmlHeader = '<data' . $this->namespaceString . '></data>';
112
113
        $this->xmlData =  new \DOMDocument();
0 ignored issues
show
Documentation Bug introduced by
It seems like new DOMDocument() of type DOMDocument is incompatible with the declared type EWW\Dpf\Services\DOMDocument of property $xmlData.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
114
        $this->xmlData->loadXML($this->xmlHeader);
115
116
        // Parser
117
        include_once 'XPathXMLGenerator.php';
118
119
        $this->parser = new XPathXMLGenerator();
120
    }
121
122
    /**
123
     * returns the mods xml string
124
     * @return string mods xml
125
     */
126
    public function getXMLData()
127
    {
128
        $xml = $this->xmlData->saveXML();
129
        $xml = preg_replace("/eww=\"\d-\d-\d\"/", '${1}${2}${3}', $xml);
130
131
        return $xml;
132
    }
133
134
    public function transformInputXML($xml)
135
    {
136
        $XSLTransformator = new XSLTransformator();
137
        return $XSLTransformator->transformInputXML($xml);
138
    }
139
140
    /**
141
     * @param $document
142
     * @return string The transformed xml
143
     */
144
    public function getTransformedOutputXML($document)
145
    {
146
        $XSLTransformator = new XSLTransformator();
147
        return $XSLTransformator->getTransformedOutputXML($document);
148
    }
149
150
151
    /**
152
     * build mods from form array
153
     * @param array $array structured form data array
154
     */
155
    public function buildXmlFromForm($array)
156
    {
157
        $this->xmlData = $this->xmlData;
158
        // Build xml mods from form fields
159
        // loop each group
160
        foreach ($array['metadata'] as $key => $group) {
161
            //groups
162
            $mapping = $group['mapping'];
163
164
            $values     = $group['values'];
165
            $attributes = $group['attributes'];
166
167
            $attributeXPath     = '';
168
            $extensionAttribute = '';
169
            foreach ($attributes as $attribute) {
170
                if (!$attribute["modsExtension"]) {
171
                    $attributeXPath .= '[' . $attribute['mapping'] . '="' . $attribute['value'] . '"]';
172
                } else {
173
                    $extensionAttribute .= '[' . $attribute['mapping'] . '="' . $attribute['value'] . '"]';
174
                }
175
176
            }
177
178
            // mods extension
179
            if ($group['modsExtensionMapping']) {
180
                $counter = sprintf("%'03d", $this->counter);
181
                $attributeXPath .= '[@ID="QUCOSA_' . $counter . '"]';
182
            }
183
184
            $existsExtensionFlag = false;
185
            $i                   = 0;
186
            // loop each object
187
            if (!empty($values)) {
188
                foreach ($values as $value) {
189
190
                    if ($value['modsExtension']) {
191
                        $existsExtensionFlag = true;
192
                        // mods extension
193
                        $counter            = sprintf("%'03d", $this->counter);
194
                        $referenceAttribute = $extensionAttribute . '[@' . $group['modsExtensionReference'] . '="QUCOSA_' . $counter . '"]';
195
196
                        $path = $group['modsExtensionMapping'] . $referenceAttribute . '%/' . $value['mapping'];
197
198
                        $xml = $this->customXPath($path, false, $value['value']);
0 ignored issues
show
Unused Code introduced by
The assignment to $xml is dead and can be removed.
Loading history...
Bug introduced by
$path of type string is incompatible with the type EWW\Dpf\Services\xpath expected by parameter $xPath of EWW\Dpf\Services\ParserGenerator::customXPath(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

198
                        $xml = $this->customXPath(/** @scrutinizer ignore-type */ $path, false, $value['value']);
Loading history...
199
                    } else {
200
                        $path = $mapping . $attributeXPath . '%/' . $value['mapping'];
201
202
                        if ($i == 0) {
203
                            $newGroupFlag = true;
204
                        } else {
205
                            $newGroupFlag = false;
206
                        }
207
208
                    $this->customXPath($path, $newGroupFlag, $value['value']);
209
                    $i++;
210
211
                    }
212
213
                }
214
            } else {
215
                if (!empty($attributeXPath)) {
216
                    $path = $mapping . $attributeXPath;
217
                    $this->customXPath($path, true, '', true);
218
                }
219
            }
220
            if (!$existsExtensionFlag && $group['modsExtensionMapping']) {
221
                $xPath = $group['modsExtensionMapping'] . $extensionAttribute . '[@' . $group['modsExtensionReference'] . '="QUCOSA_' . $counter . '"]';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $counter does not seem to be defined for all execution paths leading up to this point.
Loading history...
222
                $xml   = $this->customXPath($xPath, true, '', true);
223
            }
224
            if ($group['modsExtensionMapping']) {
225
                $this->counter++;
226
            }
227
        }
228
229
        $this->files = $array['files'];
230
    }
231
232
    /**
233
     * get xml from xpath
234
     * @param  xpath $xPath xPath expression
235
     * @return xml
0 ignored issues
show
Bug introduced by
The type EWW\Dpf\Services\xml was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
236
     */
237
    public function parseXPath($xPath)
238
    {
239
240
        $this->parser->generateXmlFromXPath($xPath);
241
        $xml = $this->parser->getXML();
242
243
        return $xml;
244
    }
245
246
    public function parseXPathWrapped($xPath)
247
    {
248
        $this->parser->generateXmlFromXPath($xPath);
249
        $xml = $this->parser->getXML();
250
251
        $xml = '<data' . $this->namespaceString . '>' . $xml . '</data>';
252
253
        return $xml;
254
    }
255
256
    /**
257
     * Customized xPath parser
258
     * @param  xpath  $xPath xpath expression
259
     * @param  string $value form value
260
     * @return xml    created xml
261
     */
262
    public function customXPath($xPath, $newGroupFlag = false, $value = '', $attributeOnly = false)
263
    {
264
        if (!$attributeOnly) {
265
            // Explode xPath
266
            $newPath = explode('%', $xPath);
267
268
            $praedicateFlag = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $praedicateFlag is dead and can be removed.
Loading history...
269
            $explodedXPath  = explode('[', $newPath[0]);
270
            if (count($explodedXPath) > 1) {
271
                // praedicate is given
272
                if (substr($explodedXPath[1], 0, 1) == "@") {
273
                    // attribute
274
                    $path = $newPath[0];
275
                } else {
276
                    // path
277
                    $path = $explodedXPath[0];
278
                }
279
280
                $praedicateFlag = true;
281
            } else {
282
                $path = $newPath[0];
283
            }
284
285
            if (!empty($value)) {
286
                $newPath[1] = $newPath[1] . '="' . $value . '"';
287
            }
288
289
            $modsDataXPath = \EWW\Dpf\Helper\XPath::create($this->xmlData);
290
291
            if (!$newGroupFlag && $modsDataXPath->query('/data/' . $newPath[0])->length > 0) {
292
                // first xpath path exist
293
294
                // build xml from second xpath part
295
                $xml = $this->parseXPath($newPath[1]);
296
297
                // check if xpath [] are nested
298
                $search = '/(\/\w*:\w*)\[(.*)\]/';
299
                preg_match($search, $newPath[1], $match);
300
                preg_match($search, $match[2], $secondMatch);
301
                // first part nested xpath
302
                if ($match[2] && $secondMatch[2]) {
303
                    $nested = $match[2];
304
305
                    $nestedXml = $this->parseXPath($nested);
306
307
                    // object xpath without nested element []
308
                    $newPath[1] = str_replace('['.$match[2].']', '', $newPath[1]);
309
310
                    $xml = $this->parseXPath($newPath[1]);
311
312
                }
313
314
                $docXML = new \DOMDocument();
315
                $docXML->loadXML($xml);
316
317
                $domXPath = \EWW\Dpf\Helper\XPath::create($this->xmlData);
318
319
                // second part nested xpath
320
                if ($match[2] && $secondMatch[2]) {
321
                    // import node from nested
322
                    $docXMLNested = new \DOMDocument();
323
                    $docXMLNested->loadXML($nestedXml);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $nestedXml does not seem to be defined for all execution paths leading up to this point.
Loading history...
324
325
                    $xPath = \EWW\Dpf\Helper\XPath::create($docXML);
326
327
                    $nodeList = $xPath->query($match[1]);
328
                    $node = $nodeList->item(0);
329
330
                    $importNode = $docXML->importNode($docXMLNested->getElementsByTagName("mods")->item(0)->firstChild, true);
0 ignored issues
show
Bug introduced by
It seems like $docXMLNested->getElemen...')->item(0)->firstChild can also be of type null; however, parameter $node of DOMDocument::importNode() does only seem to accept DOMNode, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

330
                    $importNode = $docXML->importNode(/** @scrutinizer ignore-type */ $docXMLNested->getElementsByTagName("mods")->item(0)->firstChild, true);
Loading history...
331
332
                    $node->appendChild($importNode);
333
                }
334
335
                $domNode = $domXPath->query('/data/' . $path);
336
                $node = $docXML->documentElement;
337
338
                $nodeAppendModsData = $this->xmlData->importNode($node, true);
339
                $domNode->item($domNode->length - 1)->appendChild($nodeAppendModsData);
340
            } else {
341
                // first xpath doesn't exist
342
                // parse first xpath part
343
                $xml1 = $this->parseXPathWrapped($newPath[0]);
344
345
                $doc1 = new \DOMDocument();
346
                $doc1->loadXML($xml1);
347
348
                $domXPath = \EWW\Dpf\Helper\XPath::create($doc1);
349
350
                $domNode = $domXPath->query('//' . $path);
351
352
                // parse second xpath part
353
                $xml2 = $this->parseXPathWrapped($path . $newPath[1]);
354
355
                // check if xpath [] are nested
356
                $search = '/(\/\w*:?\w*)\[(.*)\]/';
357
                preg_match($search, $newPath[1], $match);
358
                preg_match($search, $match[2], $secondMatch);
359
360
                // first part nested xpath
361
                if ($match[2] && $secondMatch[2]) {
362
                    $nested = $match[2];
363
364
                    $nestedXml = $this->parseXPathWrapped($nested);
365
366
                    // object xpath without nested element []
367
                    $newPath[1] = str_replace('['.$match[2].']', '', $newPath[1]);
368
369
                    $xml2 = $this->parseXPathWrapped($path . $newPath[1]);
370
                }
371
372
                $doc2 = new \DOMDocument();
373
                $doc2->loadXML($xml2);
374
375
                $domXPath2 = \EWW\Dpf\Helper\XPath::create($doc2);
376
377
                  // second part nested xpath
378
                if ($match[2] && $secondMatch[2]) {
379
                    // import node from nested
380
                    $docXMLNested = new \DOMDocument();
381
                    $docXMLNested->loadXML($nestedXml);
382
383
                    $xPath = \EWW\Dpf\Helper\XPath::create($doc2);
384
                    $nodeList = $xPath->query('//' . $path . $match[1]);
385
                    $node = $nodeList->item(0);
386
387
                    $importNode = $doc2->importNode($docXMLNested->documentElement, true);
388
389
                    $node->appendChild($importNode);
390
                }
391
                $domNode2 = $domXPath2->query('//' . $path)->item(0)->childNodes->item(0);
392
393
                // merge xml nodes
394
                $nodeToBeAppended = $doc1->importNode($domNode2, true);
395
                $domNode->item(0)->appendChild($nodeToBeAppended);
396
397
                // add to modsData (merge not required)
398
                // get mods tag
399
                foreach ($this->xmlData->childNodes as $childNode) {
400
                    // Skip comments inside the xml.
401
                    if ($childNode instanceof \DOMElement) {
402
                        $firstChild = $childNode;
403
                        break;
404
                    }
405
                }
406
                //$firstChild = $this->xmlData->childNodes->item(0);
407
                $firstItem = $doc1->documentElement->firstChild;
408
                $nodeAppendModsData = $this->xmlData->importNode($firstItem, true);
409
                $firstChild->appendChild($nodeAppendModsData);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $firstChild does not seem to be defined for all execution paths leading up to this point.
Loading history...
410
411
                return $doc1->saveXML();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $doc1->saveXML() returns the type string which is incompatible with the documented return type EWW\Dpf\Services\xml.
Loading history...
412
            }
413
        } else {
414
            // attribute only
415
            $xml = $this->parseXPath($xPath);
416
417
            $docXML = new \DOMDocument();
418
            $docXML->loadXML($xml);
419
420
            $domXPath = \EWW\Dpf\Helper\XPath::create($this->xmlData);
421
            $domNode  = $domXPath->query('/data');
422
423
            $node = $docXML->documentElement;
424
425
            $nodeAppendModsData = $this->xmlData->importNode($node, true);
426
            $domNode->item($domNode->length - 1)->appendChild($nodeAppendModsData);
427
428
            return $docXML->saveXML();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $docXML->saveXML() returns the type string which is incompatible with the documented return type EWW\Dpf\Services\xml.
Loading history...
429
        }
430
431
        return $this->xmlData->saveXML();
432
    }
433
434
    public function setXML($value = '') {
435
        $domDocument = new \DOMDocument();
436
        if (is_null(@$domDocument->loadXML($value))) {
437
            throw new \Exception("Couldn't load MODS data");
438
        }
439
        $this->xmlData = $domDocument;
0 ignored issues
show
Documentation Bug introduced by
It seems like $domDocument of type DOMDocument is incompatible with the declared type EWW\Dpf\Services\DOMDocument of property $xmlData.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
440
    }
441
442
    /**
443
     * sets the file data and generates file xml
444
     * @param string $value
445
     */
446
    public function setFileData($value = '')
447
    {
448
        $this->files = $value;
0 ignored issues
show
Documentation Bug introduced by
It seems like $value of type string is incompatible with the declared type array of property $files.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
449
        $this->generateFileXML();
450
    }
451
452
    /**
453
     * generates the internal xml format for files
454
     */
455
    public function generateFileXML() {
456
457
        $fileXpathConfiguration = $this->clientConfigurationManager->getFileXpath();
458
459
        foreach ($this->files as $key => $fileGrp) {
460
            foreach ($fileGrp as $file) {
461
462
                $this->customXPath($fileXpathConfiguration . '/href', true, $file["path"]);
0 ignored issues
show
Bug introduced by
$fileXpathConfiguration . '/href' of type string is incompatible with the type EWW\Dpf\Services\xpath expected by parameter $xPath of EWW\Dpf\Services\ParserGenerator::customXPath(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

462
                $this->customXPath(/** @scrutinizer ignore-type */ $fileXpathConfiguration . '/href', true, $file["path"]);
Loading history...
463
                $this->customXPath($fileXpathConfiguration . '%mimetype', false, $file["type"]);
464
                $this->customXPath($fileXpathConfiguration . '%title', false, $file["title"]);
465
                $this->customXPath($fileXpathConfiguration . '%download', false, $file["download"]);
466
                $this->customXPath($fileXpathConfiguration . '%archive', false, $file["archive"]);
467
                $this->customXPath($fileXpathConfiguration . '%use', false, $file["use"]);
468
                $this->customXPath($fileXpathConfiguration . '%id', false, $file["id"]);
469
                $this->customXPath($fileXpathConfiguration . '%hasFLocat', false, $file["hasFLocat"]);
470
471
            }
472
        }
473
    }
474
475
}
476