diff --git a/docs/03_Development/15_Frontend_Bundle/02_Best_Practices.md b/docs/03_Development/15_Frontend_Bundle/02_Best_Practices.md new file mode 100644 index 0000000000..b0170bf600 --- /dev/null +++ b/docs/03_Development/15_Frontend_Bundle/02_Best_Practices.md @@ -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. \ No newline at end of file diff --git a/docs/03_Development/15_Frontend_Bundle/index.md b/docs/03_Development/15_Frontend_Bundle/index.md index 0d95dc3ec0..874a54ff2d 100644 --- a/docs/03_Development/15_Frontend_Bundle/index.md +++ b/docs/03_Development/15_Frontend_Bundle/index.md @@ -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 -setName('coreshop:frontend:install') + ->setDescription('Install CoreShop Demo Frontend.') + ->setHelp( + <<%command.name% 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; + } +} diff --git a/src/CoreShop/Bundle/FrontendBundle/DependencyInjection/Configuration.php b/src/CoreShop/Bundle/FrontendBundle/DependencyInjection/Configuration.php index 9099be5469..b2d7b04986 100644 --- a/src/CoreShop/Bundle/FrontendBundle/DependencyInjection/Configuration.php +++ b/src/CoreShop/Bundle/FrontendBundle/DependencyInjection/Configuration.php @@ -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() ; diff --git a/src/CoreShop/Bundle/FrontendBundle/DependencyInjection/CoreShopFrontendExtension.php b/src/CoreShop/Bundle/FrontendBundle/DependencyInjection/CoreShopFrontendExtension.php index 42c2a5903a..bb5562a666 100644 --- a/src/CoreShop/Bundle/FrontendBundle/DependencyInjection/CoreShopFrontendExtension.php +++ b/src/CoreShop/Bundle/FrontendBundle/DependencyInjection/CoreShopFrontendExtension.php @@ -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']); diff --git a/src/CoreShop/Bundle/FrontendBundle/Installer/FrontendInstaller.php b/src/CoreShop/Bundle/FrontendBundle/Installer/FrontendInstaller.php new file mode 100644 index 0000000000..304d7c8f83 --- /dev/null +++ b/src/CoreShop/Bundle/FrontendBundle/Installer/FrontendInstaller.php @@ -0,0 +1,33 @@ +installers as $installer) { + $installer->installFrontend($frontendBundlePath, $rootPath, $templatePath); + } + } +} diff --git a/src/CoreShop/Bundle/FrontendBundle/Installer/FrontendInstallerInterface.php b/src/CoreShop/Bundle/FrontendBundle/Installer/FrontendInstallerInterface.php new file mode 100644 index 0000000000..bd0d1837b7 --- /dev/null +++ b/src/CoreShop/Bundle/FrontendBundle/Installer/FrontendInstallerInterface.php @@ -0,0 +1,24 @@ +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); + } +} diff --git a/src/CoreShop/Bundle/FrontendBundle/Installer/TemplatesInstaller.php b/src/CoreShop/Bundle/FrontendBundle/Installer/TemplatesInstaller.php new file mode 100644 index 0000000000..5e40bd70a3 --- /dev/null +++ b/src/CoreShop/Bundle/FrontendBundle/Installer/TemplatesInstaller.php @@ -0,0 +1,58 @@ +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); + } + } +} diff --git a/src/CoreShop/Bundle/FrontendBundle/Resources/config/services.yml b/src/CoreShop/Bundle/FrontendBundle/Resources/config/services.yml index 344fdc2960..eff116ca57 100755 --- a/src/CoreShop/Bundle/FrontendBundle/Resources/config/services.yml +++ b/src/CoreShop/Bundle/FrontendBundle/Resources/config/services.yml @@ -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: diff --git a/src/CoreShop/Bundle/FrontendBundle/Resources/config/services/frontend-installer.yaml b/src/CoreShop/Bundle/FrontendBundle/Resources/config/services/frontend-installer.yaml new file mode 100644 index 0000000000..69bdcefff3 --- /dev/null +++ b/src/CoreShop/Bundle/FrontendBundle/Resources/config/services/frontend-installer.yaml @@ -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 \ No newline at end of file diff --git a/src/CoreShop/Bundle/FrontendBundle/TemplateConfigurator/TemplateConfigurator.php b/src/CoreShop/Bundle/FrontendBundle/TemplateConfigurator/TemplateConfigurator.php index ea302f4ca2..dbba876474 100644 --- a/src/CoreShop/Bundle/FrontendBundle/TemplateConfigurator/TemplateConfigurator.php +++ b/src/CoreShop/Bundle/FrontendBundle/TemplateConfigurator/TemplateConfigurator.php @@ -21,13 +21,13 @@ class TemplateConfigurator implements TemplateConfiguratorInterface { public function __construct( - private string $bundleName, + private string $tempaltePrefix, private string $templateSuffix, ) { } public function findTemplate($templateName): string { - return sprintf('@%s/%s.%s', $this->bundleName, $templateName, $this->templateSuffix); + return sprintf('%s/%s.%s', $this->tempaltePrefix, $templateName, $this->templateSuffix); } }