Skip to content

Commit 69ca77e

Browse files
ENGCOM-6554: Add Visual Code catalog generator magento#26296
- Merge Pull Request magento#26296 from manuelcanepa/magento2:vscode-catalog - Merged commits: 1. 0c4cb77 2. 155e8a9 3. 10c0bc6 4. c540a59 5. 984d6b9 6. d9685bb 7. f948b1f 8. 8ffe789 9. 08061d9 10. 779c9ae
2 parents 5ad40fa + 779c9ae commit 69ca77e

File tree

6 files changed

+503
-0
lines changed

6 files changed

+503
-0
lines changed
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare (strict_types = 1);
7+
8+
namespace Magento\Developer\Model\XmlCatalog\Format;
9+
10+
use Magento\Framework\DomDocument\DomDocumentFactory;
11+
use Magento\Framework\Exception\FileSystemException;
12+
use Magento\Framework\Filesystem\Directory\ReadFactory;
13+
use Magento\Framework\Filesystem\Directory\ReadInterface;
14+
use Magento\Framework\Filesystem\DriverPool;
15+
use Magento\Framework\Filesystem\File\WriteFactory;
16+
17+
/**
18+
* Class VsCode generates URN catalog for VsCode
19+
*/
20+
class VsCode implements FormatInterface
21+
{
22+
private const PROJECT_PATH_IDENTIFIER = '..';
23+
public const XMLNS = 'urn:oasis:names:tc:entity:xmlns:xml:catalog';
24+
public const FILE_MODE_READ = 'r';
25+
public const FILE_MODE_WRITE = 'w';
26+
27+
/**
28+
* @var ReadInterface
29+
*/
30+
private $currentDirRead;
31+
32+
/**
33+
* @var WriteFactory
34+
*/
35+
private $fileWriteFactory;
36+
37+
/**
38+
* @var DomDocumentFactory
39+
*/
40+
private $domDocumentFactory;
41+
42+
/**
43+
* @param ReadFactory $readFactory
44+
* @param WriteFactory $fileWriteFactory
45+
* @param DomDocumentFactory $domDocumentFactory
46+
*/
47+
public function __construct(
48+
ReadFactory $readFactory,
49+
WriteFactory $fileWriteFactory,
50+
DomDocumentFactory $domDocumentFactory
51+
) {
52+
$this->currentDirRead = $readFactory->create(getcwd());
53+
$this->fileWriteFactory = $fileWriteFactory;
54+
$this->domDocumentFactory = $domDocumentFactory;
55+
}
56+
57+
/**
58+
* Generate Catalog of URNs for the VsCode
59+
*
60+
* @param string[] $dictionary
61+
* @param string $configFile relative path to the VsCode catalog.xml
62+
* @return void
63+
*/
64+
public function generateCatalog(array $dictionary, $configFile): void
65+
{
66+
$catalogNode = null;
67+
68+
try {
69+
$file = $this->fileWriteFactory->create($configFile, DriverPool::FILE, self::FILE_MODE_READ);
70+
$dom = $this->domDocumentFactory->create();
71+
$fileContent = $file->readAll();
72+
if (!empty($fileContent)) {
73+
$dom->loadXML($fileContent);
74+
} else {
75+
$this->initEmptyFile($dom);
76+
}
77+
$catalogNode = $dom->getElementsByTagName('catalog')->item(0);
78+
79+
if ($catalogNode == null) {
80+
$dom = $this->domDocumentFactory->create();
81+
$catalogNode = $this->initEmptyFile($dom);
82+
}
83+
$file->close();
84+
} catch (FileSystemException $f) {
85+
//create file if does not exists
86+
$dom = $this->domDocumentFactory->create();
87+
$catalogNode = $this->initEmptyFile($dom);
88+
}
89+
90+
$xpath = new \DOMXPath($dom);
91+
$xpath->registerNamespace('xmlns', self::XMLNS);
92+
93+
foreach ($dictionary as $urn => $xsdPath) {
94+
// Find an existing urn
95+
$existingNode = $xpath->query("/xmlns:catalog/xmlns:system[@systemId='" . $urn . "']")->item(0);
96+
$node = $existingNode ?? $dom->createElement('system');
97+
$node->setAttribute('systemId', $urn);
98+
$node->setAttribute('uri', $this->getFileLocationInProject($xsdPath));
99+
$catalogNode->appendChild($node);
100+
}
101+
$dom->formatOutput = true;
102+
$dom->preserveWhiteSpace = false;
103+
104+
// Reload to keep pretty format
105+
$dom->loadXML($dom->saveXML());
106+
107+
$file = $this->fileWriteFactory->create($configFile, DriverPool::FILE, self::FILE_MODE_WRITE);
108+
$file->write($dom->saveXML());
109+
$file->close();
110+
}
111+
112+
/**
113+
* Setup basic empty dom elements
114+
*
115+
* @param \DOMDocument $dom
116+
* @return \DOMElement
117+
*/
118+
private function initEmptyFile(\DOMDocument $dom): \DOMElement
119+
{
120+
$copyrigthComment = $dom->createComment('
121+
/**
122+
* Copyright © Magento, Inc. All rights reserved.
123+
* See COPYING.txt for license details.
124+
*/
125+
');
126+
$dom->appendChild($copyrigthComment);
127+
128+
$catalogNode = $dom->createElement('catalog');
129+
$catalogNode->setAttribute('xmlns', self::XMLNS);
130+
$dom->appendChild($catalogNode);
131+
132+
return $catalogNode;
133+
}
134+
135+
/**
136+
* Resolve xsdpath to xml project path
137+
*
138+
* @param string $xsdPath
139+
* @return string
140+
*/
141+
private function getFileLocationInProject(string $xsdPath): string
142+
{
143+
return self::PROJECT_PATH_IDENTIFIER . DIRECTORY_SEPARATOR . $this->currentDirRead->getRelativePath($xsdPath);
144+
}
145+
}

app/code/Magento/Developer/Test/Unit/Console/Command/XmlCatalogGenerateCommandTest.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,58 @@ public function testExecuteBadType()
6666
$commandTester->execute([XmlCatalogGenerateCommand::IDE_FILE_PATH_ARGUMENT => 'test']);
6767
$this->assertEquals('', $commandTester->getDisplay());
6868
}
69+
70+
public function testExecuteVsCodeFormat()
71+
{
72+
$fixtureXmlFile = __DIR__ . '/_files/test.xml';
73+
74+
$filesMock = $this->createPartialMock(\Magento\Framework\App\Utility\Files::class, ['getXmlCatalogFiles']);
75+
$filesMock->expects($this->at(0))
76+
->method('getXmlCatalogFiles')
77+
->will($this->returnValue([[$fixtureXmlFile]]));
78+
$filesMock->expects($this->at(1))
79+
->method('getXmlCatalogFiles')
80+
->will($this->returnValue([]));
81+
$urnResolverMock = $this->createMock(\Magento\Framework\Config\Dom\UrnResolver::class);
82+
$urnResolverMock->expects($this->once())
83+
->method('getRealPath')
84+
->with($this->equalTo('urn:magento:framework:Module/etc/module.xsd'))
85+
->will($this->returnValue($fixtureXmlFile));
86+
87+
$vscodeFormatMock = $this->createMock(\Magento\Developer\Model\XmlCatalog\Format\VsCode::class);
88+
$vscodeFormatMock->expects($this->once())
89+
->method('generateCatalog')
90+
->with(
91+
$this->equalTo(['urn:magento:framework:Module/etc/module.xsd' => $fixtureXmlFile]),
92+
$this->equalTo('test')
93+
)->will($this->returnValue(null));
94+
95+
$formats = ['vscode' => $vscodeFormatMock];
96+
$readFactory = $this->createMock(\Magento\Framework\Filesystem\Directory\ReadFactory::class);
97+
$readDirMock = $this->createMock(\Magento\Framework\Filesystem\Directory\ReadInterface::class);
98+
99+
$content = file_get_contents($fixtureXmlFile);
100+
101+
$readDirMock->expects($this->once())
102+
->method('readFile')
103+
->with($this->equalTo('test.xml'))
104+
->will($this->returnValue($content));
105+
$readFactory->expects($this->once())
106+
->method('create')
107+
->will($this->returnValue($readDirMock));
108+
109+
$this->command = new XmlCatalogGenerateCommand(
110+
$filesMock,
111+
$urnResolverMock,
112+
$readFactory,
113+
$formats
114+
);
115+
116+
$commandTester = new CommandTester($this->command);
117+
$commandTester->execute([
118+
'--' . XmlCatalogGenerateCommand::IDE_OPTION => 'vscode',
119+
XmlCatalogGenerateCommand::IDE_FILE_PATH_ARGUMENT => 'test',
120+
]);
121+
$this->assertEquals('', $commandTester->getDisplay());
122+
}
69123
}

0 commit comments

Comments
 (0)