Skip to content

Commit

Permalink
[Frontend] introduce template installer and new best-practice
Browse files Browse the repository at this point in the history
  • Loading branch information
dpfaffenbauer committed Oct 25, 2024
1 parent d9586dc commit 6ff8c4a
Show file tree
Hide file tree
Showing 12 changed files with 308 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;
}
}
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
33 changes: 33 additions & 0 deletions src/CoreShop/Bundle/FrontendBundle/Installer/FrontendInstaller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?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;

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

public function installFrontend(string $frontendBundlePath, string $rootPath, string $templatePath): void
{
foreach ($this->installers 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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?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;

class TemplatesInstaller implements FrontendInstallerInterface
{
public function installFrontend(string $frontendBundlePath, string $rootPath, string $templatePath): void
{
$finder = new Finder();
$finder
->in($frontendBundlePath . '/Resources/views')
->name('*.twig');

$twigFiles = $finder->files();

$fs = new Filesystem();

if (!$fs->exists($templatePath . '/coreshop')) {
$fs->mkdir($templatePath . '/coreshop');
}

foreach ($twigFiles as $twigFile) {
$newFileName = $templatePath. '/coreshop/' . $twigFile->getRelativePathname();

if ($fs->exists($newFileName)) {
continue;
}

$twigContent = file_get_contents($twigFile->getRealPath());
$twigContent = str_replace(
array('@CoreShopFrontend/', 'bundles/coreshopfrontend/'),
array('', 'coreshop/'),
$twigContent
);

$fs->dumpFile($newFileName, $twigContent);
}
}
}
12 changes: 10 additions & 2 deletions src/CoreShop/Bundle/FrontendBundle/Resources/config/services.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
imports:
- { resource: ../../../TestBundle/Resources/config/twig.yml }
- { resource: services/frontend-installer.yaml }

services:
CoreShop\Bundle\FrontendBundle\Command\InstallFrontendCommand:
parent: CoreShop\Bundle\CoreBundle\Command\InstallResourcesCommand
arguments:
$frontendInstaller: '@CoreShop\Bundle\FrontendBundle\Installer\FrontendInstallerInterface'
tags:
- { name: console.command, command: coreshop:frontend:install }

coreshop.frontend.controller.abstract:
class: CoreShop\Bundle\FrontendBundle\Controller\FrontendController
abstract: true
calls:
- [setContainer, ['@service_container']]
- [setTemplateConfigurator, ['@CoreShop\Bundle\FrontendBundle\TemplateConfigurator\TemplateConfiguratorInterface']]

CoreShop\Bundle\FrontendBundle\TemplateConfigurator\TemplateConfiguratorInterface: '@CoreShop\Bundle\FrontendBundle\TemplateConfigurator\TemplateConfigurator'
CoreShop\Bundle\FrontendBundle\TemplateConfigurator\TemplateConfigurator:
public: true
arguments:
- '%coreshop.frontend.view_bundle%'
- '%coreshop.frontend.view_prefix%'
- '%coreshop.frontend.view_suffix%'

CoreShop\Bundle\FrontendBundle\Twig\LocaleSwitcherExtension:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
services:

CoreShop\Bundle\FrontendBundle\Installer\TemplatesInstaller:
tags:
- { name: coreshop.frontend.installer }

CoreShop\Bundle\FrontendBundle\Installer\TemplateConfiguratorInstaller:
tags:
- { name: coreshop.frontend.installer }

CoreShop\Bundle\FrontendBundle\Installer\FrontendInstallerInterface: '@CoreShop\Bundle\FrontendBundle\Installer\FrontendInstaller'
CoreShop\Bundle\FrontendBundle\Installer\FrontendInstaller:
arguments:
- !tagged_iterator coreshop.frontend.installer

Check failure on line 14 in src/CoreShop/Bundle/FrontendBundle/Resources/config/services/frontend-installer.yaml

View workflow job for this annotation

GitHub Actions / ~11.1.0, PHP 8.1, Deps highest, JMS ^4.0

Tags support is not enabled. Enable the "Yaml::PARSE_CUSTOM_TAGS" flag to use "!tagged_iterator" at line 14 (near "!tagged_iterator coreshop.frontend.installer").

Check failure on line 14 in src/CoreShop/Bundle/FrontendBundle/Resources/config/services/frontend-installer.yaml

View workflow job for this annotation

GitHub Actions / ~11.1.0, PHP 8.1, Deps highest, JMS ^5.0

Tags support is not enabled. Enable the "Yaml::PARSE_CUSTOM_TAGS" flag to use "!tagged_iterator" at line 14 (near "!tagged_iterator coreshop.frontend.installer").

Check failure on line 14 in src/CoreShop/Bundle/FrontendBundle/Resources/config/services/frontend-installer.yaml

View workflow job for this annotation

GitHub Actions / ~11.2.0, PHP 8.1, Deps highest, JMS ^5.0

Tags support is not enabled. Enable the "Yaml::PARSE_CUSTOM_TAGS" flag to use "!tagged_iterator" at line 14 (near "!tagged_iterator coreshop.frontend.installer").

Check failure on line 14 in src/CoreShop/Bundle/FrontendBundle/Resources/config/services/frontend-installer.yaml

View workflow job for this annotation

GitHub Actions / ~11.1.0, PHP 8.2, Deps highest, JMS ^4.0

Tags support is not enabled. Enable the "Yaml::PARSE_CUSTOM_TAGS" flag to use "!tagged_iterator" at line 14 (near "!tagged_iterator coreshop.frontend.installer").

Check failure on line 14 in src/CoreShop/Bundle/FrontendBundle/Resources/config/services/frontend-installer.yaml

View workflow job for this annotation

GitHub Actions / ~11.1.0, PHP 8.2, Deps highest, JMS ^5.0

Tags support is not enabled. Enable the "Yaml::PARSE_CUSTOM_TAGS" flag to use "!tagged_iterator" at line 14 (near "!tagged_iterator coreshop.frontend.installer").

Check failure on line 14 in src/CoreShop/Bundle/FrontendBundle/Resources/config/services/frontend-installer.yaml

View workflow job for this annotation

GitHub Actions / ~11.2.0, PHP 8.2, Deps highest, JMS ^4.0

Tags support is not enabled. Enable the "Yaml::PARSE_CUSTOM_TAGS" flag to use "!tagged_iterator" at line 14 (near "!tagged_iterator coreshop.frontend.installer").

Check failure on line 14 in src/CoreShop/Bundle/FrontendBundle/Resources/config/services/frontend-installer.yaml

View workflow job for this annotation

GitHub Actions / ~11.2.0, PHP 8.2, Deps highest, JMS ^5.0

Tags support is not enabled. Enable the "Yaml::PARSE_CUSTOM_TAGS" flag to use "!tagged_iterator" at line 14 (near "!tagged_iterator coreshop.frontend.installer").
Loading

0 comments on commit 6ff8c4a

Please sign in to comment.