diff --git a/.gitignore b/.gitignore
index 095f17e..e8fe863 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
/Tests/Application/var/*
/vendor/
+.env.local
+.env.*.local
/composer.phar
/composer.lock
.php_cs.cache
diff --git a/.travis.yml b/.travis.yml
index 6663f7c..074f299 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,7 +9,7 @@ cache:
matrix:
include:
- - php: 7.2
+ - php: 7.3
env:
- COMPOSER_FLAGS="--prefer-lowest --prefer-stable --prefer-dist --no-interaction"
- php: 7.4
diff --git a/DependencyInjection/CompilerPass/ImageFormatCompilerPass.php b/DependencyInjection/CompilerPass/ImageFormatCompilerPass.php
index 67cbeca..63fa245 100644
--- a/DependencyInjection/CompilerPass/ImageFormatCompilerPass.php
+++ b/DependencyInjection/CompilerPass/ImageFormatCompilerPass.php
@@ -11,8 +11,8 @@
namespace Sulu\Bundle\ThemeBundle\DependencyInjection\CompilerPass;
-use Liip\ThemeBundle\ActiveTheme;
use Sulu\Bundle\MediaBundle\DependencyInjection\AbstractImageFormatCompilerPass;
+use Sylius\Bundle\ThemeBundle\Repository\ThemeRepositoryInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
/**
@@ -25,14 +25,13 @@ class ImageFormatCompilerPass extends AbstractImageFormatCompilerPass
*/
protected function getFiles(ContainerBuilder $container)
{
- $files = [];
-
- /** @var ActiveTheme $activeTheme */
- $activeTheme = $container->get('liip_theme.active_theme');
+ /** @var ThemeRepositoryInterface $themeRepository */
+ $themeRepository = $container->get('sylius.repository.theme');
$bundles = $container->getParameter('kernel.bundles');
$configPath = 'config/image-formats.xml';
- foreach ($activeTheme->getThemes() as $theme) {
+ $files = [];
+ foreach ($themeRepository->findAll() as $theme) {
foreach ($bundles as $bundleName => $bundle) {
$bundleReflection = new \ReflectionClass($bundle);
$fileName = $bundleReflection->getFileName();
@@ -44,7 +43,7 @@ protected function getFiles(ContainerBuilder $container)
$path = sprintf(
'%s/Resources/themes/%s/%s',
dirname($fileName),
- $theme,
+ $theme->getName(),
$configPath
);
diff --git a/DependencyInjection/CompilerPass/WebspaceStructureProviderCompilerPass.php b/DependencyInjection/CompilerPass/WebspaceStructureProviderCompilerPass.php
deleted file mode 100644
index 55eac93..0000000
--- a/DependencyInjection/CompilerPass/WebspaceStructureProviderCompilerPass.php
+++ /dev/null
@@ -1,35 +0,0 @@
-hasDefinition('sulu.content.webspace_structure_provider')) {
- return;
- }
-
- $definition = $container->getDefinition('sulu.content.webspace_structure_provider');
- $definition->setClass(WebspaceStructureProvider::class);
- $definition->addArgument(new Reference('sulu_core.webspace.webspace_manager'));
- $definition->addArgument(new Reference('liip_theme.active_theme'));
- }
-}
diff --git a/EventListener/SetThemeEventListener.php b/EventListener/SetThemeEventListener.php
index 5bb8ab6..ae06cad 100644
--- a/EventListener/SetThemeEventListener.php
+++ b/EventListener/SetThemeEventListener.php
@@ -11,9 +11,10 @@
namespace Sulu\Bundle\ThemeBundle\EventListener;
-use Liip\ThemeBundle\ActiveTheme;
use Sulu\Bundle\PreviewBundle\Preview\Events\PreRenderEvent;
-use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Sylius\Bundle\ThemeBundle\Context\SettableThemeContext;
+use Sylius\Bundle\ThemeBundle\Repository\ThemeRepositoryInterface;
+use Symfony\Component\HttpKernel\Event\RequestEvent;
/**
* Listener which applies the configured theme.
@@ -21,19 +22,25 @@
class SetThemeEventListener
{
/**
- * @var ActiveTheme
+ * @var ThemeRepositoryInterface
*/
- private $activeTheme;
+ private $themeRepository;
- public function __construct(ActiveTheme $activeTheme)
+ /**
+ * @var SettableThemeContext
+ */
+ private $themeContext;
+
+ public function __construct(ThemeRepositoryInterface $themeRepository, SettableThemeContext $themeContext)
{
- $this->activeTheme = $activeTheme;
+ $this->themeRepository = $themeRepository;
+ $this->themeContext = $themeContext;
}
/**
* Set the active theme if there is a portal.
*/
- public function setActiveThemeOnRequest(GetResponseEvent $event): void
+ public function setActiveThemeOnRequest(RequestEvent $event): void
{
if (null === ($attributes = $event->getRequest()->get('_sulu'))
|| null === ($webspace = $attributes->getAttribute('webspace'))
@@ -42,7 +49,10 @@ public function setActiveThemeOnRequest(GetResponseEvent $event): void
return;
}
- $this->activeTheme->setName($theme);
+ $theme = $this->themeRepository->findOneByName($theme);
+ if (null !== $theme) {
+ $this->themeContext->setTheme($theme);
+ }
}
/**
@@ -50,6 +60,9 @@ public function setActiveThemeOnRequest(GetResponseEvent $event): void
*/
public function setActiveThemeOnPreviewPreRender(PreRenderEvent $event): void
{
- $this->activeTheme->setName($event->getAttribute('webspace')->getTheme());
+ $theme = $this->themeRepository->findOneByName($event->getAttribute('webspace')->getTheme());
+ if (null !== $theme) {
+ $this->themeContext->setTheme($theme);
+ }
}
}
diff --git a/README.md b/README.md
index 66d9be8..2d39b6d 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,152 @@
-# SuluThemeBundle
+
SuluThemeBundle
-[![Build Status](https://travis-ci.org/sulu/SuluThemeBundle.svg?branch=develop)](https://travis-ci.org/sulu/SuluThemeBundle)
+
+
+
+
+
-This package enables a basic theming for sulu. It uses liip/theme-bundle to extend the discovery feature of twig.
+
+
+
+
+
+
+
+
+
+
+
+
+
+The **SuluThemeBundle** provides the functionality to add multiple themes for different look and feel using multiple
+webspaces in the [Sulu](https://sulu.io/) content management system.
+
+To achieve this, the bundle uses the [SyliusThemeBundle](https://github.com/Sylius/SyliusThemeBundle) to render different
+twig templates and asset files. Each webspace can have it's own theme.
+
+## 🚀 Installation and Usage
+
+### Install the bundle
+
+Execute the following [composer](https://getcomposer.org/) command to add the bundle to the dependencies of your
+project:
+
+```bash
+composer require sulu/theme-bundle
+```
+
+### Enable the bundle
+
+Enable the bundle by adding it to the list of registered bundles in the `config/bundles.php` file of your project:
+
+```php
+return [
+ /* ... */
+ Sulu\Bundle\ThemeBundle\SuluThemeBundle::class => ['all' => true],
+];
+```
+
+
+### Configure the SyliusThemeBundle
+
+In order to use the bundle you have to add at least the following default configuration:
+
+```yaml
+# ./config/packages/sylius_theme.yaml
+
+sylius_theme:
+ sources:
+ filesystem: ~
+```
+
+By default, the bundle seeks for the themes in the `%kernel.project_dir%/themes` directory and looks for a
+theme configuration file named `composer.json`. This can be changed via the yaml configuration:
+
+```yaml
+sylius_theme:
+ sources:
+ filesystem:
+ filename: theme.json
+```
+
+For more detailed information about the configuration sources go to the [SyliusThemeBundle documentation](https://github.com/Sylius/SyliusThemeBundle/blob/master/docs/configuration_sources.md).
+
+### Configure your themes
+
+Every theme must have its own configuration file in form of a `theme.json`.
+Go to the [Theme Configuration Reference](https://github.com/Sylius/SyliusThemeBundle/blob/master/docs/theme_configuration_reference.md)
+for the detailed documentation about the configuration options.
+
+The minimal configuration for a theme would be the following:
+
+```json
+// ./themes//theme.json
+
+{
+ "name": "vendor/"
+}
+```
+
+It is important, that the `name` matches the naming convention of composer (`vendor/name`).
+
+### Create a theme
+First you have to create the directory `themes` inside your project.
+To create a theme you have to create a new directory in the themes folder with the name of the new theme.
+In the newly created directory you have to add the theme configuration file `theme.json`.
+See [Configure your themes](#configure-your-themes). Additonally you have to create the `templates` directory next to
+the `theme.json`. Afterwards you have to fill this folder with all the used templates and assets for this theme.
+
+This results in the following project structure:
+
+```
+ProjectName
+├── composer.json
+├── assets
+├── bin
+├── config
+├── templates
+├── themes
+│ ├──
+│ │ ├── templates
+│ │ │ └── base.html.twig
+│ │ └── theme.json
+│ └──
+│ ├── templates
+│ │ └── base.html.twig
+│ └── theme.json
+├── ...
+└── ...
+```
+
+### Add one of your themes to a webspace
+
+Each webspace can use a different theme. A theme can be enabled for a specific webspace by adding the theme name
+`vendor/theme-name` to your webspace:
+
+```xml
+
+
+ example.com
+ example
+ ...
+ vendor/theme-name
+ ...
+
+```
+
+## ❤️ Support and Contributions
+
+The Sulu content management system is a **community-driven open source project** backed by various partner companies.
+We are committed to a fully transparent development process and **highly appreciate any contributions**.
+
+In case you have questions, we are happy to welcome you in our official [Slack channel](https://sulu.io/services-and-support).
+If you found a bug or miss a specific feature, feel free to **file a new issue** with a respective title and description
+on the the [sulu/SuluThemeBundle](https://github.com/sulu/SuluThemeBundle) repository.
+
+
+## 📘 License
+
+The Sulu content management system is released under the under terms of the [MIT License](LICENSE).
diff --git a/Resources/config/admin.xml b/Resources/config/admin.xml
index 07e7fef..ed3827a 100644
--- a/Resources/config/admin.xml
+++ b/Resources/config/admin.xml
@@ -5,7 +5,8 @@
-
+
+
diff --git a/Resources/config/website.xml b/Resources/config/website.xml
index 8b59130..c5aab40 100644
--- a/Resources/config/website.xml
+++ b/Resources/config/website.xml
@@ -2,11 +2,11 @@
-
-
+
+
diff --git a/StructureProvider/WebspaceStructureProvider.php b/StructureProvider/WebspaceStructureProvider.php
deleted file mode 100644
index bc7b686..0000000
--- a/StructureProvider/WebspaceStructureProvider.php
+++ /dev/null
@@ -1,83 +0,0 @@
-webspaceManager = $webspaceManager;
- $this->activeTheme = $activeTheme;
- }
-
- /**
- * {@inheritdoc}
- *
- * @return StructureInterface[]
- */
- protected function loadStructures($webspaceKey): array
- {
- $before = $this->activeTheme->getName();
- $webspace = $this->webspaceManager->findWebspaceByKey($webspaceKey);
-
- if (!$webspace) {
- return [];
- }
-
- if (null !== $webspace->getTheme()) {
- $this->activeTheme->setName($webspace->getTheme());
- }
-
- $structures = [];
- $keys = [];
- /** @var PageBridge $page */
- foreach ($this->structureManager->getStructures() as $page) {
- $template = sprintf('%s.html.twig', $page->getView());
- if ($this->templateExists($template)) {
- $keys[] = $page->getKey();
- $structures[] = $page;
- }
- }
- $this->activeTheme->setName($before);
- $this->cache->save($webspaceKey, $keys);
-
- return $structures;
- }
-}
diff --git a/SuluThemeBundle.php b/SuluThemeBundle.php
index fa7d173..06a2727 100644
--- a/SuluThemeBundle.php
+++ b/SuluThemeBundle.php
@@ -12,7 +12,6 @@
namespace Sulu\Bundle\ThemeBundle;
use Sulu\Bundle\ThemeBundle\DependencyInjection\CompilerPass\ImageFormatCompilerPass;
-use Sulu\Bundle\ThemeBundle\DependencyInjection\CompilerPass\WebspaceStructureProviderCompilerPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
@@ -21,8 +20,6 @@ class SuluThemeBundle extends Bundle
public function build(ContainerBuilder $container): void
{
parent::build($container);
-
- $container->addCompilerPass(new WebspaceStructureProviderCompilerPass());
$container->addCompilerPass(new ImageFormatCompilerPass());
}
}
diff --git a/Tests/Application/Kernel.php b/Tests/Application/Kernel.php
index 2e02eba..c1c0db2 100644
--- a/Tests/Application/Kernel.php
+++ b/Tests/Application/Kernel.php
@@ -11,9 +11,9 @@
namespace Sulu\Bundle\ThemeBundle\Tests\Application;
-use Liip\ThemeBundle\LiipThemeBundle;
use Sulu\Bundle\TestBundle\Kernel\SuluTestKernel;
use Sulu\Bundle\ThemeBundle\SuluThemeBundle;
+use Sylius\Bundle\ThemeBundle\SyliusThemeBundle;
use Symfony\Component\Config\Loader\LoaderInterface;
class Kernel extends SuluTestKernel
@@ -34,7 +34,7 @@ public function registerBundles()
return array_merge(
parent::registerBundles(),
[
- new LiipThemeBundle(),
+ new SyliusThemeBundle(),
new SuluThemeBundle(),
]
);
diff --git a/Tests/Application/config/sylius_theme.yaml b/Tests/Application/config/sylius_theme.yaml
new file mode 100644
index 0000000..4d34199
--- /dev/null
+++ b/Tests/Application/config/sylius_theme.yaml
@@ -0,0 +1,3 @@
+sylius_theme:
+ sources:
+ test: ~
diff --git a/Tests/Unit/EventListener/SetThemeEventListenerTest.php b/Tests/Unit/EventListener/SetThemeEventListenerTest.php
index c1d38f6..b7b5f5c 100644
--- a/Tests/Unit/EventListener/SetThemeEventListenerTest.php
+++ b/Tests/Unit/EventListener/SetThemeEventListenerTest.php
@@ -11,32 +11,29 @@
namespace Sulu\Bundle\ThemeBundle\Tests\Unit\EventListener;
-use Liip\ThemeBundle\ActiveTheme;
use PHPUnit\Framework\TestCase;
use Prophecy\Prophecy\ObjectProphecy;
use Sulu\Bundle\PreviewBundle\Preview\Events\PreRenderEvent;
use Sulu\Bundle\ThemeBundle\EventListener\SetThemeEventListener;
use Sulu\Component\Webspace\Analyzer\Attributes\RequestAttributes;
use Sulu\Component\Webspace\Webspace;
+use Sylius\Bundle\ThemeBundle\Context\SettableThemeContext;
+use Sylius\Bundle\ThemeBundle\Model\ThemeInterface;
+use Sylius\Bundle\ThemeBundle\Repository\ThemeRepositoryInterface;
use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\Event\RequestEvent;
class SetThemeEventListenerTest extends TestCase
{
/**
- * @var ObjectProphecy|ActiveTheme
+ * @var ThemeRepositoryInterface|ObjectProphecy
*/
- private $activeTheme;
+ private $themeRepository;
/**
- * @var string
+ * @var SettableThemeContext
*/
- private $theme = 'test';
-
- /**
- * @var ObjectProphecy|Webspace
- */
- private $webspace;
+ private $themeContext;
/**
* @var SetThemeEventListener
@@ -45,84 +42,135 @@ class SetThemeEventListenerTest extends TestCase
public function setUp(): void
{
- $this->activeTheme = $this->prophesize(ActiveTheme::class);
- $this->webspace = $this->prophesize(Webspace::class);
- $this->webspace->getTheme()->willReturn($this->theme);
+ $this->themeRepository = $this->prophesize(ThemeRepositoryInterface::class);
+ $this->themeContext = new SettableThemeContext();
- $this->listener = new SetThemeEventListener($this->activeTheme->reveal());
+ $this->listener = new SetThemeEventListener($this->themeRepository->reveal(), $this->themeContext);
}
public function testEventListener(): void
{
+ /** @var Webspace|ObjectProphecy webspace */
+ $webspace = $this->prophesize(Webspace::class);
+ $webspace->getTheme()->willReturn('theme/name');
+
+ /** @var ThemeInterface|ObjectProphecy $theme */
+ $theme = $this->prophesize(ThemeInterface::class);
+
+ /** @var Request|ObjectProphecy $request */
$request = $this->prophesize(Request::class);
+ /** @var RequestAttributes|ObjectProphecy $attributes */
$attributes = $this->prophesize(RequestAttributes::class);
- $attributes->getAttribute('webspace')->willReturn($this->webspace->reveal());
+ $attributes->getAttribute('webspace')->willReturn($webspace->reveal());
$request->get('_sulu')->willReturn($attributes->reveal());
- $event = $this->prophesize(GetResponseEvent::class);
+ /** @var RequestEvent|ObjectProphecy $event */
+ $event = $this->prophesize(RequestEvent::class);
$event->getRequest()->willReturn($request->reveal());
$event->isMasterRequest()->willReturn(true);
- $this->activeTheme->setName($this->theme)->shouldBeCalled();
+ $this->themeRepository->findOneByName('theme/name')
+ ->shouldBeCalled()
+ ->willReturn($theme->reveal());
$this->listener->setActiveThemeOnRequest($event->reveal());
+
+ $this->assertSame($theme->reveal(), $this->themeContext->getTheme());
}
public function testEventListenerNotMaster(): void
{
+ /** @var Webspace|ObjectProphecy webspace */
+ $webspace = $this->prophesize(Webspace::class);
+ $webspace->getTheme()->willReturn('theme/name');
+
+ /** @var ThemeInterface|ObjectProphecy $theme */
+ $theme = $this->prophesize(ThemeInterface::class);
+
+ /** @var Request|ObjectProphecy $request */
$request = $this->prophesize(Request::class);
+ /** @var RequestAttributes|ObjectProphecy $attributes */
$attributes = $this->prophesize(RequestAttributes::class);
- $attributes->getAttribute('webspace')->willReturn($this->webspace->reveal());
+ $attributes->getAttribute('webspace')->willReturn($webspace->reveal());
$request->get('_sulu')->willReturn($attributes->reveal());
- $event = $this->prophesize(GetResponseEvent::class);
+ /** @var RequestEvent|ObjectProphecy $event */
+ $event = $this->prophesize(RequestEvent::class);
$event->getRequest()->willReturn($request->reveal());
$event->isMasterRequest()->willReturn(false);
- $this->activeTheme->setName($this->theme)->shouldBeCalled();
+ $this->themeRepository->findOneByName('theme/name')
+ ->shouldBeCalled()
+ ->willReturn($theme->reveal());
$this->listener->setActiveThemeOnRequest($event->reveal());
+
+ $this->assertSame($theme->reveal(), $this->themeContext->getTheme());
}
public function testEventListenerNoWebspace(): void
{
+ /** @var Request|ObjectProphecy $request */
$request = $this->prophesize(Request::class);
+ /** @var RequestAttributes|ObjectProphecy $attributes */
$attributes = $this->prophesize(RequestAttributes::class);
$attributes->getAttribute('webspace')->willReturn(null);
$request->get('_sulu')->willReturn($attributes->reveal());
- $event = $this->prophesize(GetResponseEvent::class);
+ /** @var RequestEvent|ObjectProphecy $event */
+ $event = $this->prophesize(RequestEvent::class);
$event->getRequest()->willReturn($request->reveal());
$event->isMasterRequest()->willReturn(true);
- $this->activeTheme->setName($this->theme)->shouldNotBeCalled();
+ $this->themeRepository->findOneByName('theme/name')
+ ->shouldNotBeCalled();
$this->listener->setActiveThemeOnRequest($event->reveal());
+
+ $this->assertNull($this->themeContext->getTheme());
}
public function testEventListenerNoAttributes(): void
{
+ /** @var Request|ObjectProphecy $request */
$request = $this->prophesize(Request::class);
+ /* @var RequestAttributes|ObjectProphecy $attributes */
$request->get('_sulu')->willReturn(null);
- $event = $this->prophesize(GetResponseEvent::class);
+ /** @var RequestEvent|ObjectProphecy $event */
+ $event = $this->prophesize(RequestEvent::class);
$event->getRequest()->willReturn($request->reveal());
$event->isMasterRequest()->willReturn(true);
- $this->activeTheme->setName($this->theme)->shouldNotBeCalled();
+ $this->themeRepository->findOneByName('theme/name')
+ ->shouldNotBeCalled();
$this->listener->setActiveThemeOnRequest($event->reveal());
+
+ $this->assertNull($this->themeContext->getTheme());
}
public function testEventListenerOnPreview(): void
{
+ /** @var ThemeInterface|ObjectProphecy $theme */
+ $theme = $this->prophesize(ThemeInterface::class);
+
+ /** @var Webspace|ObjectProphecy webspace */
+ $webspace = $this->prophesize(Webspace::class);
+ $webspace->getTheme()->willReturn('theme/name');
+
+ /** @var RequestAttributes|ObjectProphecy $attributes */
$attributes = $this->prophesize(RequestAttributes::class);
- $attributes->getAttribute('webspace', null)->willReturn($this->webspace->reveal());
+ $attributes->getAttribute('webspace', null)->willReturn($webspace->reveal());
- $this->activeTheme->setName($this->theme)->shouldBeCalled();
+ $this->themeRepository->findOneByName('theme/name')
+ ->shouldBeCalled()
+ ->willReturn($theme->reveal());
$this->listener->setActiveThemeOnPreviewPreRender(
new PreRenderEvent($attributes->reveal())
);
+
+ $this->assertSame($theme->reveal(), $this->themeContext->getTheme());
}
}
diff --git a/Tests/Unit/StructureProvider/WebspaceStructureProviderTest.php b/Tests/Unit/StructureProvider/WebspaceStructureProviderTest.php
deleted file mode 100644
index 832cbc7..0000000
--- a/Tests/Unit/StructureProvider/WebspaceStructureProviderTest.php
+++ /dev/null
@@ -1,124 +0,0 @@
-generateStructure('t1', 'MyBundle:default:t1'),
- $this->generateStructure('t2', 'MyBundle:default:t2'),
- $this->generateStructure('t3', 'MyBundle:default:t3'),
- ];
-
- $theme = 'test';
-
- $webspace = $this->prophesize('Sulu\Component\Webspace\Webspace');
- $webspace->getTheme()->willReturn($theme);
-
- $twigLoader = $this->prophesize('\Twig_ExistsLoaderInterface');
- $twigLoader->exists('MyBundle:default:t1.html.twig')->willReturn(false);
- $twigLoader->exists('MyBundle:default:t2.html.twig')->willReturn(true)->shouldBeCalled();
- $twigLoader->exists('MyBundle:default:t3.html.twig')->willReturn(false);
-
- $twig = $this->prophesize('\Twig_Environment');
- $twig->getLoader()->willReturn($twigLoader->reveal());
-
- $structureManager = $this->prophesize('Sulu\Component\Content\Compat\StructureManagerInterface');
- $structureManager->getStructures()->willReturn($structures);
-
- $webspaceManager = $this->prophesize('Sulu\Component\Webspace\Manager\WebspaceManagerInterface');
- $webspaceManager->findWebspaceByKey('sulu_io')->willReturn($webspace->reveal());
-
- $activeTheme = $this->prophesize('Liip\ThemeBundle\ActiveTheme');
- $activeTheme->getName()->willReturn('before');
- $activeTheme->setName('test')->shouldBeCalled();
- $activeTheme->setName('before')->shouldBeCalled();
-
- $structureProvider = new WebspaceStructureProvider(
- $twig->reveal(),
- $structureManager->reveal(),
- $cache,
- $webspaceManager->reveal(),
- $activeTheme->reveal()
- );
-
- $result = $structureProvider->getStructures('sulu_io');
-
- $this->assertCount(1, $result);
- $this->assertEquals($structures[1], $result[0]);
-
- $this->assertTrue($cache->contains('sulu_io'));
- $this->assertEquals(['t2'], $cache->fetch('sulu_io'));
- }
-
- public function testGetStructuresCached(): void
- {
- $cache = new ArrayCache();
- $cache->save('sulu_io', ['t1', 't3']);
-
- $structures = [
- $this->generateStructure('t1', 'MyBundle:default:t1'),
- $this->generateStructure('t2', 'MyBundle:default:t2'),
- $this->generateStructure('t3', 'MyBundle:default:t3'),
- ];
-
- $twig = $this->prophesize('\Twig_Environment');
- $twig->getLoader()->shouldNotBeCalled();
-
- $structureManager = $this->prophesize('Sulu\Component\Content\Compat\StructureManagerInterface');
- $structureManager->getStructures()->shouldNotBeCalled();
- $structureManager->getStructure('t1')->willReturn($structures[0]);
- $structureManager->getStructure('t2')->shouldNotBeCalled();
- $structureManager->getStructure('t3')->willReturn($structures[2]);
-
- $webspaceManager = $this->prophesize('Sulu\Component\Webspace\Manager\WebspaceManagerInterface');
- $webspaceManager->findWebspaceByKey('sulu_io')->shouldNotBeCalled();
-
- $activeTheme = $this->prophesize('Liip\ThemeBundle\ActiveTheme');
- $activeTheme->getName()->shouldNotBeCalled();
- $activeTheme->setName('test')->shouldNotBeCalled();
- $activeTheme->setName('before')->shouldNotBeCalled();
-
- $structureProvider = new WebspaceStructureProvider(
- $twig->reveal(),
- $structureManager->reveal(),
- $cache,
- $webspaceManager->reveal(),
- $activeTheme->reveal()
- );
-
- $result = $structureProvider->getStructures('sulu_io');
-
- $this->assertCount(2, $result);
- $this->assertEquals($structures[0]->getKey(), $result[0]->getKey());
- $this->assertEquals($structures[2]->getKey(), $result[1]->getKey());
- }
-
- private function generateStructure(string $key, string $view): StructureInterface
- {
- $mock = $this->prophesize('Sulu\Component\Content\Compat\Structure\PageBridge');
-
- $mock->getKey()->willReturn($key);
- $mock->getView()->willReturn($view);
-
- return $mock->reveal();
- }
-}
diff --git a/UPGRADE.md b/UPGRADE.md
new file mode 100644
index 0000000..0487b85
--- /dev/null
+++ b/UPGRADE.md
@@ -0,0 +1,111 @@
+# Upgrade
+
+## 3.0
+
+### Switch from LiipThemeBundle to SyliusThemeBundle
+
+To achieve Symfony 5 compatibility the ThemingBundle has to be changed from [LiipThemeBundle](https://github.com/liip/LiipThemeBundle) to [SyliusThemeBundle](https://github.com/Sylius/SyliusThemeBundle).
+
+#### Remove the old theme bundle and install the SyliusThemeBundle:
+
+```bash
+# Remove old theme-bundle
+composer remove liip/theme-bundle --no-update
+
+# Install new theme-bundle
+composer require sylius/theme-bundle:"^2.0" --no-update
+composer require sulu/theme-bundle:"^3.0"
+```
+
+#### Remove old configuration
+
+The old `liip_theme.yaml` configuration needs to be removed:
+
+```diff
+- liip_theme:
+- themes: ['project', 'awesome']
+- active_theme: 'awesome'
+```
+
+In the next step you see how you configure the **awesome** theme using the SyliusThemeBundle.
+
+#### Configure the SyliusThemeBundle:
+
+In order to use the bundle you have to add the following default configuration:
+
+```yaml
+# ./config/packages/sylius_theme.yaml
+
+sylius_theme:
+ sources:
+ filesystem: ~
+```
+
+By default, the bundle seeks for the themes in the `%kernel.project_dir%/themes` directory and looks for a configuration
+file named `composer.json`. This can be changed via the yaml configuration:
+
+```yaml
+sylius_theme:
+ sources:
+ filesystem:
+ filename: theme.json
+```
+
+#### Convert Theme Configuration
+
+In the SyliusThemeBundle every theme must have its own configuration file in form of a `theme.json`.
+Add a `theme.json` file and add the following minimal configuration:
+
+```diff
++ {
++ "name": "app/awesome"
++ }
+```
+
+Go to the [Theme Configuration Reference](https://github.com/Sylius/SyliusThemeBundle/blob/master/docs/theme_configuration_reference.md)
+for the detailed documentation about the configuration options.
+
+Most likely you have to change the theme name. It is important, that the `name` matches the naming convention of composer (`vendor/name`).
+Furthermore the `theme.json` has to be moved into the directory for this specific theme.
+
+For example: `%kernel.project_dir%/themes/awesome/theme.json`
+
+#### Update project structure
+
+Your templates have to be placed in a `templates` directory next to the `theme.json` file.
+
+For example: `%kernel.project_dir%/themes//templates`
+
+This results in the following project structure:
+
+```
+ProjectName
+├── composer.json
+├── assets
+├── bin
+├── config
+├── templates
+├── themes
+│ ├── awesome
+│ │ ├── templates
+│ │ │ └── base.html.twig
+│ │ └── theme.json
+│ └──
+│ ├── templates
+│ │ └── base.html.twig
+│ └── theme.json
+├── ...
+└── ...
+```
+
+As you can see in the project structure, each theme must have their own `theme.json` configuration file next to the
+templates directory.
+
+#### Update webspace configuration
+
+If your old theme name didn't match the naming convention you also have to change it in the `webspace.xml` to the new one.
+
+```diff
+- awesome
++ app/awesome
+```
diff --git a/composer.json b/composer.json
index 0e9e37e..9aa9a3e 100644
--- a/composer.json
+++ b/composer.json
@@ -1,7 +1,7 @@
{
"name": "sulu/theme-bundle",
"type": "sulu-bundle",
- "description": "The Sulu Bundle which provides themes",
+ "description": "The Sulu Bundle which provides theming functionality.",
"license": "MIT",
"keywords": [
"sulu",
@@ -14,26 +14,24 @@
}
],
"require": {
- "php": "^7.2",
- "liip/theme-bundle": "^1.5",
+ "php": "^7.3",
"sulu/sulu": "^2.0",
- "symfony/config": "^4.3",
- "symfony/dependency-injection": "^4.3",
- "symfony/http-kernel": "^4.3"
+ "symfony/config": "^4.4 || ^5.0",
+ "symfony/dependency-injection": "^4.4 || ^5.0",
+ "symfony/http-kernel": "^4.4 || ^5.0",
+ "sylius/theme-bundle": "^2.0"
},
"require-dev": {
"jackalope/jackalope-doctrine-dbal": "^1.3",
- "phpunit/phpunit": "^8.0",
+ "symfony/dotenv": "^4.4 || ^5.0",
+ "phpunit/phpunit": "^8.5.9",
"jangregor/phpstan-prophecy": "^0.8",
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-doctrine": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"phpstan/phpstan-symfony": "^0.12",
- "symfony/dotenv": "^4.3",
- "thecodingmachine/phpstan-strict-rules": "^0.12"
- },
- "conflict": {
- "liip/theme-bundle": "1.6.0"
+ "thecodingmachine/phpstan-strict-rules": "^0.12",
+ "symfony/phpunit-bridge": "^5.1"
},
"autoload": {
"psr-4": {
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 8aac5b0..f7f0df6 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -16,4 +16,14 @@
+
+
+
+
+
+
+
+
+
+