Skip to content

Commit

Permalink
Merge pull request #2739 from dpfaffenbauer/template-installer
Browse files Browse the repository at this point in the history
[Frontend] introduce template installer and better define best-practice
  • Loading branch information
dpfaffenbauer authored Oct 28, 2024
2 parents d9586dc + 2bcee62 commit 85e8e5a
Show file tree
Hide file tree
Showing 14 changed files with 355 additions and 45 deletions.
35 changes: 35 additions & 0 deletions docs/03_Development/15_Frontend_Bundle/02_Best_Practices.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Best Practices for Frontend in CoreShop

We learned a lot over the years and want to share our best practices with you. This guide will help you to get the most
out of CoreShop and to avoid common pitfalls.

## Server Side Rendering
If you do PHP Server Side Rendering with Twig, you should enable the Frontend Bundle in bundles.php:

```php
// config/bundles.php
return [
// ...
CoreShop\Bundle\FrontendBundle\CoreShopFrontendBundle::class => ['all' => true],
];
```

### Templates
Symfony allows to override Bundle templates by placing them in the `templates` directory. This is something we don't recommend!
We, at CoreShop, sometimes change Templates, add templates, or rename them. Sometimes on accident, sometimes on purpose.

To not run into any issues with CoreShop Demo Files to be loaded, we recommend to copy the Templates from the Demo Frontend.
There is also a new command for that:

```bash
php bin/console coreshop:frontend:install
```

This will copy all the templates from CoreShop into `coreshop` and it also replaces all the Bundle Prefixes. That way, you
can be sure that you are using the correct templates.

This command also creates a configuration to change the `TemplateConfigurator` to use your app template paths and not the
FrontendBundle paths.

## Headless
If you are going headless, you can simply not enable the Frontend Bundle and do whatever need for your Headless API.
40 changes: 1 addition & 39 deletions docs/03_Development/15_Frontend_Bundle/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,42 +20,4 @@ is meant as a Demo and not as a production-ready store.

## Best Practice

Best practice is not to use any Templates from the Demo Frontend, but to create your own Templates and use the
Controllers from the Demo Frontend.

## Copy Templates

To copy the Templates from the Demo Frontend, you can use the following command:

```bash
cp -R vendor/coreshop/core-shop/src/CoreShop/Bundle/FrontendBundle/Resources/views templates/coreshop
```

Overwrite the `TemplateConfiguratorInterface` by creating a new Service and decorate the original one:

```php
<?php
// src/CoreShop/TemplateConfigurator/TemplateConfigurator.php
declare(strict_types=1);

namespace App\CoreShop\TemplateConfigurator;

use CoreShop\Bundle\FrontendBundle\TemplateConfigurator\TemplateConfiguratorInterface;

class TemplateConfigurator implements TemplateConfiguratorInterface
{
public function findTemplate(string $templateName): string
{
return sprintf('coreshop/%s.twig', $templateName);
}
}
```

And configure the new Service:

```yaml
# config/services.yaml
services:
App\CoreShop\TemplateConfigurator\TemplateConfigurator:
decorates: 'CoreShop\Bundle\FrontendBundle\TemplateConfigurator\TemplateConfigurator'
```
We have a separate Guide how we recommend you use the Frontend Bundle: [Best Practices](02_Best_Practices.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

/*
* CoreShop
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - CoreShop Commercial License (CCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) CoreShop GmbH (https://www.coreshop.org)
* @license https://www.coreshop.org/license GPLv3 and CCL
*
*/

namespace CoreShop\Bundle\FrontendBundle\Command;

use CoreShop\Bundle\CoreBundle\Command\AbstractInstallCommand;
use CoreShop\Bundle\CoreBundle\Installer\Checker\CommandDirectoryChecker;
use CoreShop\Bundle\FrontendBundle\Installer\FrontendInstallerInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\HttpKernel\KernelInterface;

final class InstallFrontendCommand extends AbstractInstallCommand
{
public function __construct(
KernelInterface $kernel,
CommandDirectoryChecker $directoryChecker,
protected FrontendInstallerInterface $frontendInstaller,
) {
parent::__construct($kernel, $directoryChecker);
}

protected function configure(): void
{
$this
->setName('coreshop:frontend:install')
->setDescription('Install CoreShop Demo Frontend.')
->setHelp(
<<<EOT
The <info>%command.name%</info> command install CoreShop Frontend Controllers/Templates/Configs.
EOT
)
->addOption('templatePath', null, InputOption::VALUE_OPTIONAL, 'Path to the template directory', 'templates')
;
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$coreBundle = $this->kernel->getBundle('CoreShopFrontendBundle');
$frontendBundlePath = $coreBundle->getPath();

$rootPath = $this->kernel->getProjectDir();

$templatePath = $rootPath . '/' . $input->getOption('templatePath');

$this->frontendInstaller->installFrontend(
$frontendBundlePath,
$rootPath,
$templatePath
);

return 0;
}
}
2 changes: 2 additions & 0 deletions src/CoreShop/Bundle/FrontendBundle/CoreShopFrontendBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

use Composer\InstalledVersions;
use CoreShop\Bundle\CoreBundle\CoreShopCoreBundle;
use CoreShop\Bundle\FrontendBundle\DependencyInjection\CompilerPass\FrontendInstallerPass;
use CoreShop\Bundle\FrontendBundle\DependencyInjection\CompilerPass\RegisterFrontendControllerPass;
use Pimcore\Extension\Bundle\AbstractPimcoreBundle;
use Pimcore\HttpKernel\Bundle\DependentBundleInterface;
Expand All @@ -38,6 +39,7 @@ public function build(ContainerBuilder $container): void
parent::build($container);

$container->addCompilerPass(new RegisterFrontendControllerPass());
$container->addCompilerPass(new FrontendInstallerPass());
}

public function getNiceName(): string
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

/*
* CoreShop
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - CoreShop Commercial License (CCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) CoreShop GmbH (https://www.coreshop.org)
* @license https://www.coreshop.org/license GPLv3 and CCL
*
*/

namespace CoreShop\Bundle\FrontendBundle\DependencyInjection\CompilerPass;

use CoreShop\Component\Registry\RegisterSimpleRegistryTypePass;

final class FrontendInstallerPass extends RegisterSimpleRegistryTypePass
{
public const FRONTEND_INSTALLER_TAG = 'coreshop.frontend.installer';

public function __construct()
{
parent::__construct(
'coreshop.registry.frontend.installers',
'coreshop.frontend.installers',
self::FRONTEND_INSTALLER_TAG,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ public function getConfigTreeBuilder(): TreeBuilder
$rootNode
->children()
->scalarNode('view_suffix')->defaultValue('twig')->end()
->scalarNode('view_bundle')->defaultValue('CoreShopFrontend')->end()
->scalarNode('view_bundle')->setDeprecated('coreshop_frontend', '4.1', 'Use view_prefix instead')->defaultValue('@CoreShopFrontend')->end()
->scalarNode('view_prefix')->defaultValue('@CoreShopFrontend')->end()
->end()
;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,15 @@ public function load(array $configs, ContainerBuilder $container): void
}
}

$container->setParameter('coreshop.frontend.view_bundle', $configs['view_bundle']);
$container->setParameter('coreshop.frontend.view_suffix', $configs['view_suffix']);

if (isset($configs['view_prefix'])) {
$container->setParameter('coreshop.frontend.view_prefix', $configs['view_prefix']);
}
else {
$container->setParameter('coreshop.frontend.view_prefix', '@' . $configs['view_bundle']);
}

$container->setParameter('coreshop.frontend.category.valid_sort_options', $configs['category']['valid_sort_options']);
$container->setParameter('coreshop.frontend.category.default_sort_name', $configs['category']['default_sort_name']);
$container->setParameter('coreshop.frontend.category.default_sort_direction', $configs['category']['default_sort_direction']);
Expand Down
36 changes: 36 additions & 0 deletions src/CoreShop/Bundle/FrontendBundle/Installer/FrontendInstaller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

/*
* CoreShop
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - CoreShop Commercial License (CCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) CoreShop GmbH (https://www.coreshop.org)
* @license https://www.coreshop.org/license GPLv3 and CCL
*
*/

namespace CoreShop\Bundle\FrontendBundle\Installer;

use CoreShop\Component\Registry\ServiceRegistryInterface;

class FrontendInstaller implements FrontendInstallerInterface
{
public function __construct(private readonly ServiceRegistryInterface $installers)
{
}

public function installFrontend(string $frontendBundlePath, string $rootPath, string $templatePath): void
{
/** @var FrontendInstallerInterface $installer */
foreach ($this->installers->all() as $installer) {
$installer->installFrontend($frontendBundlePath, $rootPath, $templatePath);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

/*
* CoreShop
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - CoreShop Commercial License (CCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) CoreShop GmbH (https://www.coreshop.org)
* @license https://www.coreshop.org/license GPLv3 and CCL
*
*/

namespace CoreShop\Bundle\FrontendBundle\Installer;

interface FrontendInstallerInterface
{
public function installFrontend(string $frontendBundlePath, string $rootPath, string $templatePath): void;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

/*
* CoreShop
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - CoreShop Commercial License (CCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) CoreShop GmbH (https://www.coreshop.org)
* @license https://www.coreshop.org/license GPLv3 and CCL
*
*/

namespace CoreShop\Bundle\FrontendBundle\Installer;

use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Yaml\Yaml;

class TemplateConfiguratorInstaller implements FrontendInstallerInterface
{
public function installFrontend(string $frontendBundlePath, string $rootPath, string $templatePath): void
{
$configFile = $rootPath . '/config/packages/coreshop_frontend.yaml';

$configContent = <<<CONFIG
core_shop_frontend:
view_prefix: 'coreshop'
CONFIG;
$fs = new Filesystem();
if (!file_exists($configFile)) {
$fs->dumpFile($configFile, $configContent);
return;
}

$configContent = file_get_contents($configFile);

$content = Yaml::parse($configContent);

if (!isset($content['core_shop_frontend']['view_prefix'])) {
$content['core_shop_frontend']['view_prefix'] = 'coreshop';
}

$configContent = Yaml::dump($content, 4, 2);
$fs->dumpFile($configFile, $configContent);
}
}
Loading

0 comments on commit 85e8e5a

Please sign in to comment.