Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copy extension services and routes into Bolt #1634

Merged
merged 11 commits into from
Jul 18, 2020
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,12 @@
"prefer-stable": true,
"scripts": {
"post-install-cmd": [
"php bin/console extensions:configure --with-config",
"@auto-scripts",
"php bin/console bolt:info"
],
"post-update-cmd": [
"php bin/console extensions:configure",
"@auto-scripts",
"php bin/console bolt:info"
],
Expand Down
18 changes: 18 additions & 0 deletions config/packages/bolt.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# This file is auto-generated by Bolt. Do not modify.

services:
_defaults:
autowire: true
autoconfigure: true
AcmeCorp\ReferenceExtension\:
resource: '../../vendor/acmecorp/reference-extension/src/*'
exclude: '../../vendor/acmecorp/reference-extension/src/{Entity,Exception}'
BobdenOtter\ConfigurationNotices\:
resource: '../../vendor/bobdenotter/configuration-notices/src/*'
exclude: '../../vendor/bobdenotter/configuration-notices/src/{Entity,Exception}'
BobdenOtter\WeatherWidget\:
resource: '../../vendor/bobdenotter/weatherwidget/src/*'
exclude: '../../vendor/bobdenotter/weatherwidget/src/{Entity,Exception}'
Bolt\NewsWidget\:
resource: '../../vendor/bolt/newswidget/src/*'
exclude: '../../vendor/bolt/newswidget/src/{Entity,Exception}'
18 changes: 0 additions & 18 deletions config/services_bolt.yaml

This file was deleted.

140 changes: 140 additions & 0 deletions src/Command/ExtensionsConfigureCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<?php

declare(strict_types=1);

namespace Bolt\Command;

use Bolt\Common\Str;
use Bolt\Extension\ExtensionRegistry;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Webmozart\PathUtil\Path;

class ExtensionsConfigureCommand extends Command
{
protected static $defaultName = 'extensions:configure';

/** @var ExtensionRegistry */
private $extensionRegistry;

/** @var mixed */
private $projectDir;

public function __construct(ExtensionRegistry $extensionRegistry, ContainerInterface $container)
{
$this->extensionRegistry = $extensionRegistry;
$this->projectDir = $container->getParameter('kernel.project_dir');

parent::__construct();
}

protected function configure(): void
{
$this
->setDescription('Copy the config/config.yaml, config/services.yaml and config/routes.yaml files from extensions.')
->addOption('with-config', null, InputOption::VALUE_NONE, 'If set, Bolt will copy the default extension config.yaml file');
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$extensions = $this->extensionRegistry->getExtensions();

$this->copyExtensionRoutesAndServices($extensions);

if ($input->getOption('with-config')) {
$this->copyExtensionConfig($extensions);
}

return 0;
}

public function copyExtensionConfig(array $packages): void
{
// @todo: Combine this with Bolt\Extension\ConfigTrait.php
foreach ($packages as $package) {
$path = $this->getPackagePath($package);

$configPath = $this->getRelativePath($path) . '/config/config.yaml';
if (file_exists($configPath)) {
[$namespace, $name] = explode('\\', mb_strtolower($this->getNamespace($package)));
$destination = $this->getExtensionConfigPath($namespace, $name);
file_put_contents($destination, file_get_contents($configPath));
}
}
}

public function copyExtensionRoutesAndServices(array $packages): void
{
$oldExtensionsRoutes = glob($this->getExtensionRoutesPath());
$oldExtensionsServices = glob($this->getExtensionServicesPath());

foreach ($packages as $package) {
$path = $this->getPackagePath($package);

$extensionRoutesPath = $this->getRelativePath($path) . '/config/routes.yaml';
if (file_exists($extensionRoutesPath)) {
$destination = $this->getExtensionRoutesPath($path);
$oldExtensionsRoutes = array_diff($oldExtensionsRoutes, [$destination]);
file_put_contents($destination, file_get_contents($extensionRoutesPath));
}

$extensionServicesPath = $this->getRelativePath($path) . '/../config.services.yaml';
if (file_exists($extensionServicesPath)) {
$destination = $this->getExtensionServicesPath($path);
$oldExtensionsServices = array_diff($oldExtensionsServices, [$destination]);
file_put_contents($destination, file_get_contents($extensionRoutesPath));
}
}

// Remove routes.yaml files for old (uninstalled) extensions
array_map('unlink', $oldExtensionsRoutes);

// Remove services.yaml files for old (uninstalled) extensions
array_map('unlink', $oldExtensionsServices);
}

private function getRelativePath(string $path): string
{
return Path::makeRelative($path, $this->projectDir);
}

/**
* Helper function that returns the path of the extension routes.yaml file
* inside Bolt.
*/
private function getExtensionRoutesPath(string $path = '*'): string
{
return $this->projectDir . '/config/routes/extension_' . Str::splitLast($path, '/') . '.yaml';
}

/**
* Helper function that returns the path of the extension services.yaml file
* inside Bolt.
*/
private function getExtensionServicesPath(string $path = '*'): string
{
return $this->projectDir . '/config/packages/services_extension_' . Str::splitLast($path, '/') . '.yaml';
}

private function getExtensionConfigPath(string $namespace, string $name): string
{
return $this->projectDir . '/config/extensions/' . $namespace . '-' . $name . '.yaml';
}

private function getPackagePath($package): string
{
$reflection = new \ReflectionClass($package);

return dirname(dirname($reflection->getFilename()));
}

private function getNamespace($package): string
{
$reflection = new \ReflectionClass($package);

return $reflection->getNamespaceName();
}
}
96 changes: 0 additions & 96 deletions src/Extension/ExtensionCompilerPass.php

This file was deleted.

11 changes: 0 additions & 11 deletions src/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use Bolt\Configuration\Parser\ContentTypesParser;
use Bolt\Configuration\Parser\TaxonomyParser;
use Bolt\Extension\ExtensionCompilerPass;
use Bolt\Extension\ExtensionInterface;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\FileLocator;
Expand Down Expand Up @@ -44,9 +43,6 @@ public function build(ContainerBuilder $container): void
$container
->registerForAutoconfiguration(ExtensionInterface::class)
->addTag(ExtensionInterface::CONTAINER_TAG);

// Process all our implementors through our CompilerPass
$container->addCompilerPass(new ExtensionCompilerPass());
}

protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void
Expand All @@ -64,13 +60,6 @@ protected function configureContainer(ContainerBuilder $container, LoaderInterfa
$this->setBoltParameters($container, $confDir);
$this->setContentTypeRequirements($container);
$this->setTaxonomyRequirements($container);

try {
$loader->load($confDir . '/{services}_bolt' . self::CONFIG_EXTS, 'glob');
} catch (\Throwable $e) {
// Ignore errors. The file will be updated on next `cache:clear` or whenever
// the container gets refreshed
}
}

protected function configureRoutes(RouteCollectionBuilder $routes): void
Expand Down