Skip to content

Commit 5e0dc67

Browse files
committed
feat(index): add load index action
1 parent 06db5c7 commit 5e0dc67

File tree

8 files changed

+168
-1
lines changed

8 files changed

+168
-1
lines changed

src/Action/LoadIndexAction.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace NuonicPluginInstaller\Action;
6+
7+
use League\Flysystem\FilesystemOperator;
8+
use NuonicPluginInstaller\Config\ConfigValue;
9+
use NuonicPluginInstaller\Config\PluginConfigService;
10+
use NuonicPluginInstaller\Exception\IndexLoadFailedException;
11+
use NuonicPluginInstaller\Service\IndexFileService;
12+
use Shopware\Core\System\SystemConfig\Exception\InvalidSettingValueException;
13+
use Symfony\Contracts\HttpClient\HttpClientInterface;
14+
15+
class LoadIndexAction
16+
{
17+
private const FALLBACK_PACKAGE_SOURCE = 'https://raw.githubusercontent.com/nuonic-digital/plugin-data/refs/heads/dev/shopware_extensions_v1.json';
18+
19+
public function __construct(
20+
private PluginConfigService $config,
21+
private HttpClientInterface $httpClient,
22+
private FilesystemOperator $filesystem,
23+
) {
24+
}
25+
26+
public function execute(): void
27+
{
28+
try {
29+
$url = $this->config->getString(ConfigValue::PACKAGE_SOURCE);
30+
} catch (InvalidSettingValueException $e) {
31+
$url = null;
32+
}
33+
if (is_null($url) || '' === trim($url)) {
34+
$url = self::FALLBACK_PACKAGE_SOURCE;
35+
}
36+
37+
$response = $this->httpClient->request('GET', $url);
38+
39+
if (200 !== $response->getStatusCode()) {
40+
throw new IndexLoadFailedException();
41+
}
42+
43+
44+
$this->filesystem->writeStream(IndexFileService::FILE_NAME, $this->httpClient->stream($response));
45+
}
46+
}

src/Config/ConfigValue.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace NuonicPluginInstaller\Config;
6+
7+
final readonly class ConfigValue
8+
{
9+
public const PACKAGE_SOURCE = 'packageSource';
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace NuonicPluginInstaller\Exception;
6+
7+
class IndexLoadFailedException extends \RuntimeException
8+
{
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace NuonicPluginInstaller\Exception;
6+
7+
class MalformedIndexException extends \RuntimeException
8+
{
9+
}

src/Resources/config/config.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,16 @@
44
<card>
55
<title>Basic configuration</title>
66
<title lang="de-DE">Grundeinstellungen</title>
7+
8+
<input-field type="text">
9+
<name>packageSource</name>
10+
<label>Package source URL</label>
11+
<label lang="de-DE">URL der Paketquelle</label>
12+
<placeholder>https://raw.githubusercontent.com/....</placeholder>
13+
<defaultValue>https://raw.githubusercontent.com/nuonic-digital/plugin-data/refs/heads/dev/shopware_extensions_v1.json</defaultValue>
14+
<required>true</required>
15+
<helpText>The plugin will load it's package index from the given package source url</helpText>
16+
<helpText lang="de-DE">Das Plugin wird seinen Paketindex von der angegebenen Paketquelle laden</helpText>
17+
</input-field>
718
</card>
819
</config>

src/Resources/config/services.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,15 @@
1515
<service id="NuonicPluginInstaller\Core\Framework\Plugin\AvailableOpensourcePlugin\Aggregate\AvailableOpensourcePluginTranslation\AvailableOpensourcePluginTranslationDefinition">
1616
<tag name="shopware.entity.definition" entity="nuonic_available_opensource_plugin_translation" />
1717
</service>
18+
19+
<service id="NuonicPluginInstaller\Action\LoadIndexAction">
20+
<argument type="service" id="NuonicPluginInstaller\Config\PluginConfigService" />
21+
<argument type="service" id="http_client" />
22+
<argument type="service" id="nuonic_plugin_installer.filesystem.private" />
23+
</service>
24+
25+
<service id="NuonicPluginInstaller\Service\IndexFileServiceInterface" class="NuonicPluginInstaller\Service\IndexFileService">
26+
<argument type="service" id="nuonic_plugin_installer.filesystem.private" />
27+
</service>
1828
</services>
1929
</container>

src/Service/IndexFileService.php

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace NuonicPluginInstaller\Service;
6+
7+
use League\Flysystem\FilesystemException;
8+
use League\Flysystem\FilesystemOperator;
9+
use NuonicPluginInstaller\Exception\MalformedIndexException;
10+
use NuonicPluginInstaller\Struct\PackageIndexEntry;
11+
12+
class IndexFileService implements IndexFileServiceInterface
13+
{
14+
public const FILE_NAME = 'shopware-extension-index.json';
15+
16+
/** @var array<string, PackageIndexEntry> */
17+
private array $packageInformation = [];
18+
19+
public function __construct(
20+
private readonly FilesystemOperator $filesystem,
21+
) {
22+
}
23+
24+
public function getPackageInformation(string $packageName): ?PackageIndexEntry
25+
{
26+
if (!isset($this->packageInformation[$packageName])) {
27+
$this->loadPluginInformationFromFile();
28+
}
29+
30+
return $this->packageInformation[$packageName];
31+
}
32+
33+
public function listPackages(): array
34+
{
35+
if (empty($this->packageInformation)) {
36+
$this->loadPluginInformationFromFile();
37+
}
38+
39+
return $this->packageInformation;
40+
}
41+
42+
/**
43+
* @return void
44+
* @throws MalformedIndexException
45+
*/
46+
private function loadPluginInformationFromFile(): void
47+
{
48+
try {
49+
$jsonData = $this->filesystem->read(self::FILE_NAME);
50+
$data = json_decode($jsonData, true, 512, JSON_THROW_ON_ERROR);
51+
} catch (FilesystemException $e) {
52+
// if the file does not exist, do not build an index
53+
return;
54+
} catch (\JsonException $e) {
55+
throw new MalformedIndexException(sprintf('JSON decoding failed: %s', $e->getMessage()), $e->getCode(), $e);
56+
}
57+
58+
foreach ($data as $package => $packageInfo) {
59+
if (!isset($packageInfo['repositoryUrl'], $packageInfo['ref'])) {
60+
throw new MalformedIndexException(sprintf('Package information is missing required fields for package: %s', $package));
61+
}
62+
63+
$this->packageInformation[$package] = new PackageIndexEntry(
64+
repositoryUrl: $packageInfo['repositoryUrl'],
65+
ref: $packageInfo['ref'],
66+
);
67+
}
68+
}
69+
}

src/Service/IndexFileServiceInterface.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@
44

55
namespace NuonicPluginInstaller\Service;
66

7+
use NuonicPluginInstaller\Exception\MalformedIndexException;
78
use NuonicPluginInstaller\Struct\PackageIndexEntry;
89

910
interface IndexFileServiceInterface
1011
{
11-
public function getPackageInformation(string $packageName): PackageIndexEntry;
12+
/** @throws MalformedIndexException */
13+
public function getPackageInformation(string $packageName): ?PackageIndexEntry;
1214

1315
/**
1416
* @return PackageIndexEntry[]
17+
* @throws MalformedIndexException
1518
*/
1619
public function listPackages(): array;
1720
}

0 commit comments

Comments
 (0)