diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 51d1b7d..3fe8d1f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,16 +1,25 @@
name: CI
-on: [ push ]
+on:
+ push:
+ branches:
+ - main
+ - v2
+ pull_request:
+ types: [ opened, reopened, synchronize, ready_for_review ]
+ branches:
+ - '**'
jobs:
tests:
name: PHP ${{ matrix.php }}
runs-on: ubuntu-latest
+ if: github.event.pull_request.draft == false
strategy:
fail-fast: false
matrix:
php: [ 8.1, 8.2, 8.3, 8.4 ]
- contao: [ 4.13.*, 5.3.*, 5.4.* ]
+ contao: [ 4.13.*, 5.3.*]
steps:
- name: Setup PHP
@@ -34,6 +43,7 @@ jobs:
coverage:
runs-on: ubuntu-latest
+ if: github.event.pull_request.draft == false
steps:
- name: Setup PHP
uses: shivammathur/setup-php@v2
@@ -61,6 +71,7 @@ jobs:
phpstan:
runs-on: ubuntu-latest
+ if: github.event.pull_request.draft == false
steps:
- name: Setup PHP
uses: shivammathur/setup-php@v2
@@ -79,6 +90,7 @@ jobs:
ecs:
name: ECS
runs-on: ubuntu-latest
+ if: github.event.pull_request.draft == false
steps:
- name: Setup PHP
uses: shivammathur/setup-php@v2
diff --git a/.gitignore b/.gitignore
index 4972bf1..02ff242 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,4 +8,5 @@ composer.json~
composer.phar
.ddev/
.phpunit.result.cache
-phpunit.xml.dist.bak
\ No newline at end of file
+phpunit.xml.dist.bak
+.codex
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 474271e..39fef55 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,15 @@
All notable changes to this project will be documented in this file.
+## [2.2.0] - 2026-04-20
+- Added: support for modern twig layouts of contao 5.7 ([#34](https://github.com/heimrichhannot/contao-encore-bundle/pull/34))
+- Added: EntrypointsBuilder concept for retriving current page entrypoints ([#34](https://github.com/heimrichhannot/contao-encore-bundle/pull/34))
+- Changed: add constant for default field name ([#34](https://github.com/heimrichhannot/contao-encore-bundle/pull/34))
+- Fixed: removed dead or unnecessary code and checks ([#34](https://github.com/heimrichhannot/contao-encore-bundle/pull/34))
+- Deprecated: `src/Asset/PageEntrypoints.php`, `src/Asset/TemplateAsset.php` and `src/Asset/TemplateAssetGenerator.php` ([#34](https://github.com/heimrichhannot/contao-encore-bundle/pull/34))
+- Deprecated: `ConfigurationHelper::isEnabledOnPage()` ([#34](https://github.com/heimrichhannot/contao-encore-bundle/pull/34))
+- Deprecated: getter-Methods in `EncoreEnabledEvent` ([#34](https://github.com/heimrichhannot/contao-encore-bundle/pull/34))
+
## [2.1.1] - 2026-03-30
- Fixed: compatibility issue with symfony 7
diff --git a/composer.json b/composer.json
index fc205e2..3e63f58 100644
--- a/composer.json
+++ b/composer.json
@@ -27,6 +27,7 @@
"symfony/config": "^5.4 || ^6.0 || ^7.0",
"symfony/console": "^5.4 || ^6.0 || ^7.0",
"symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0",
+ "symfony/deprecation-contracts": "^1.0 || ^2.0 || ^3.0",
"symfony/filesystem": "^5.4 || ^6.0 || ^7.0",
"symfony/http-foundation": "^5.4 || ^6.0 || ^7.0",
"symfony/http-kernel": "^5.4 || ^6.0 || ^7.0",
@@ -36,15 +37,16 @@
"twig/twig": "^1.38.3 || ^2.7 || ^3.0"
},
"require-dev": {
- "contao/test-case": "^4.0 || ^5.0",
+ "contao/core-bundle": "^4.13",
+ "contao/test-case": "^4.0",
"contao/manager-plugin": "^2.13",
"phpunit/phpunit": "^8.0 || ^9.0",
"php-coveralls/php-coveralls": "^2.0",
"symfony/phpunit-bridge": "^3.2 || ^4.0 || ^5.0 || ^6.0",
"heimrichhannot/contao-test-utilities-bundle": "^0.1.4",
- "phpstan/phpstan": "^1.12",
- "phpstan/phpstan-symfony": "^1.4",
- "rector/rector": "^1.2",
+ "phpstan/phpstan": "^1.12 || ^2.0",
+ "phpstan/phpstan-symfony": "^1.4 || ^2.0",
+ "rector/rector": "^1.2 || ^2.0",
"contao/contao-rector": "dev-main",
"symplify/easy-coding-standard": "^12.5"
},
diff --git a/config/services.php b/config/services.php
new file mode 100644
index 0000000..c3a3e72
--- /dev/null
+++ b/config/services.php
@@ -0,0 +1,53 @@
+services();
+
+ $services
+ ->defaults()
+ ->autowire()
+ ->bind('$bundleConfig', '%huh_encore%')
+ ->bind('$webDir', '%contao.web_dir%')
+ ->bind('$encoreCache', service('webpack_encore.cache'))
+ ->bind(CacheItemPoolInterface::class, service('webpack_encore.cache'))
+ ->bind(TagRenderer::class, service('webpack_encore.tag_renderer'))
+ ;
+
+ $services
+ ->load('HeimrichHannot\\EncoreBundle\\', '../src/{Asset,Collection,Command,DataContainer,EventListener,Helper}/*')
+ ->exclude('../src/Asset/{EntrypointCollection.php}')
+ ->public()
+ ->autoconfigure()
+ ;
+
+ $services
+ ->set(EntryPointBuilderFactory::class)
+ ;
+
+ $services
+ ->alias('huh.encore.asset.frontend', FrontendAsset::class)
+ ->public()
+ ;
+
+ $services
+ ->alias('huh.encore.asset.template', TemplateAsset::class)
+ ->public()
+ ;
+};
diff --git a/config/services.yml b/config/services.yml
deleted file mode 100644
index d418eaf..0000000
--- a/config/services.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-services:
- _defaults:
- autowire: true
- bind:
- $bundleConfig: '%huh_encore%'
- $webDir: '%contao.web_dir%'
- $encoreCache: '@webpack_encore.cache'
- Psr\Cache\CacheItemPoolInterface: "@webpack_encore.cache"
-
- HeimrichHannot\EncoreBundle\:
- resource: "../src/{Asset,Collection,Command,DataContainer,EventListener,Helper}/*"
- exclude: '../src/Asset/{EntrypointCollection.php}'
- public: true
- autoconfigure: true
-
- huh.encore.asset.frontend:
- alias: HeimrichHannot\EncoreBundle\Asset\FrontendAsset
- public: true
-
- huh.encore.asset.template:
- alias: HeimrichHannot\EncoreBundle\Asset\TemplateAsset
- public: true
\ No newline at end of file
diff --git a/contao/dca/tl_layout.php b/contao/dca/tl_layout.php
index b50a07b..6bb5416 100644
--- a/contao/dca/tl_layout.php
+++ b/contao/dca/tl_layout.php
@@ -27,7 +27,7 @@
/*
* Subpalettes
*/
-$dca['subpalettes']['addEncore'] = 'encoreEntries,encoreStylesheetsImportsTemplate,encoreScriptsImportsTemplate';
+$dca['subpalettes']['addEncore'] = EncoreEntriesSelectField::NAME_DEFAULT . ',encoreStylesheetsImportsTemplate,encoreScriptsImportsTemplate';
/**
* Fields.
diff --git a/docs/developers.md b/docs/developers.md
index 1223ccf..6849788 100644
--- a/docs/developers.md
+++ b/docs/developers.md
@@ -4,8 +4,6 @@ This document contains additional information for developers working with encore
## Add entries from your code (frontend module, content element,...)
-Since version 1.3 it is possible to add encore entries from your code. So for example the slider assets are automatically included, if the slider module is added to the page.
-
The most simple method is to use the `PageAssetsTrait` of [Contao Encore Contracts](https://github.com/heimrichhannot/contao-encore-contracts).
Use this trait in your class in combination with `ServiceSubscriberInterface` and make sure your class is registered as service with autoconfigure activated.
Now you have a new method `addPageEntrypoint()` available.
@@ -64,41 +62,58 @@ PaletteManipulator::create()
## Add encore entries to custom template
-If you don't want to render assets on page basis, it is possible to generate a custom set of encore entries.
-
-1. Create an `EntrypointCollection` with the `EntrypointCollectionFactory` service
-1. Get your assets with `TemplateAssetGenerator` service.
-1. Optional: If you want an input field in the contao backend to select entries, you can use the `DcaGenerator` service to generate an input like on layout or page settings.
+To collect or render assets in custom templates or abstinent from the normal page rendering, use the `EntryPointsBuilder`.
```php
-use Contao\FrontendTemplate;
-use HeimrichHannot\EncoreBundle\Asset\EntrypointCollectionFactory;
-use HeimrichHannot\EncoreBundle\Asset\TemplateAssetGenerator;
+createCollection($entrypoints);
- $template->stylesheets = $templateAssetGenerator->linkTags($collection);
- $template->headJavaScript = $templateAssetGenerator->headScriptTags($collection);
- $template->javaScript = $templateAssetGenerator->scriptTags($collection);
- return $template->getResponse();
-}
-```
-
-It is also possible to get the stylesheets inline:
+namespace App\CustomController;
-```php
-use Contao\FrontendTemplate;
-use HeimrichHannot\EncoreBundle\Asset\EntrypointCollectionFactory;
-use HeimrichHannot\EncoreBundle\Asset\TemplateAssetGenerator;
+use HeimrichHannot\EncoreBundle\Asset\FrontendAsset;
+use HeimrichHannot\EncoreBundle\EntryPoint\EntryPointBuilderFactory;
+use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\WebpackEncoreBundle\Asset\TagRenderer;use Twig\Environment;
-function renderTemplateWithEncore(array $entrypoints, EntrypointCollectionFactory $entrypointCollectionFactory, TemplateAssetGenerator $templateAssetGenerator)
+class CustomController
{
- $template = new FrontendTemplate();
- $collection = $entrypointCollectionFactory->createCollection($entrypoints);
- $template->inlineCss = $templateAssetGenerator->inlineCssLinkTag($collection);
- return $template->getResponse();
+ private readonly TagRenderer $tagRenderer;
+ private readonly EntryPointBuilderFactory $entrypointBuilderFactory;
+ private readonly Environment $twig;
+ private readonly FrontendAsset $frontendAsset;
+
+ public function __invoke(): Response
+ {
+ // collect entry points from the different sources
+ $entryPoints = $this->entrypointBuilderFactory->create()
+ // add the sources you want:
+ ->setPage($event->getPage())
+ ->setLayout($event->getLayout())
+ ->setFrontendAsset($this->frontendAsset)
+ // build the collection:
+ ->build();
+
+ // render the tags, for example with the tag renderer of webpack encore bundle
+ $this->tagRenderer->reset();
+ $css = $head = $body = [];
+ foreach ($entryPoints->allActive() as $entrypoint) {
+ if ($entrypoint->requiresCss) {
+ $css[] = $this->tagRenderer->renderWebpackLinkTags($entrypoint->name);
+ }
+ if ($entrypoint->head) {
+ $head[] = $this->tagRenderer->renderWebpackScriptTags($entrypoint->name);
+ } else {
+ $body[] = $this->tagRenderer->renderWebpackScriptTags($entrypoint->name);
+ }
+ }
+
+ // render the template
+ return new Response($this->twig->render('custom_template.html.twig', [
+ 'css' => $css,
+ 'head' => $head,
+ 'body' => $body,
+ ]));
+ }
}
```
@@ -106,23 +121,8 @@ function renderTemplateWithEncore(array $entrypoints, EntrypointCollectionFactor
The `ConfigurationHelper` service can be used to obtain some configuration information. Following methods are available:
-`isEnabledOnCurrentPage(?PageModel $pageModel = null): bool` - Return if encore is enabled for the current frontend page. You can pass a page object to check for a custom page, otherweise `global $objPage` is used.
+`isEnabledOnPage(PageModel $page, ?LayoutModel $layout = null): bool` - Return if encore is enabled for the current frontend page.
`getRelativeOutputPath(): string` - Return the relative output path configured by webpack encore bundle. Typical this is `build`.
-`getAbsoluteOutputPath(): string` - Return the absolute output path configured by webpack encore bundle. For example `/var/www/html/project/web/build`
-
-## Custom import templates
-
-If you need custom templates for the import of javascript and stylesheet assets files, Encore Bundle provide support for this.
-Create a twig template (see `src/Resources/views` for examples) and register them in your (project) bundle config.
-
-Example:
-
-```yaml
-huh_encore:
- templates:
- imports:
- - { name: default_css, template: "@HeimrichHannotEncore/encore_css_imports.html.twig" }
- - { name: default_js, template: "@HeimrichHannotEncore/encore_js_imports.html.twig" }
-```
\ No newline at end of file
+`getAbsoluteOutputPath(): string` - Return the absolute output path configured by webpack encore bundle. For example `/var/www/html/project/public/build`
\ No newline at end of file
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index a0a9f7f..3f32295 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -1,6 +1,19 @@
parameters:
ignoreErrors:
-
- message: "#^Offset 'fields' on array\\{\\} in isset\\(\\) does not exist\\.$#"
+ message: '#^Call to method getLayout\(\) on an unknown class Contao\\CoreBundle\\Event\\LayoutEvent\.$#'
+ identifier: class.notFound
count: 2
- path: tests/EventListener/DcaField/EncoreEntriesSelectFieldListenerTest.php
+ path: src/EventListener/InjectPageEntriesListener.php
+
+ -
+ message: '#^Call to method getPage\(\) on an unknown class Contao\\CoreBundle\\Event\\LayoutEvent\.$#'
+ identifier: class.notFound
+ count: 2
+ path: src/EventListener/InjectPageEntriesListener.php
+
+ -
+ message: '#^Parameter \$event of method HeimrichHannot\\EncoreBundle\\EventListener\\InjectPageEntriesListener\:\:onLayoutEvent\(\) has invalid type Contao\\CoreBundle\\Event\\LayoutEvent\.$#'
+ identifier: class.notFound
+ count: 1
+ path: src/EventListener/InjectPageEntriesListener.php
diff --git a/phpstan.neon b/phpstan.neon
index e630b1c..3a4bf3f 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -1,8 +1,7 @@
parameters:
- level: 4
+ level: 5
paths:
- src
- - tests
- contao
universalObjectCratesClasses:
- Contao\LayoutModel
diff --git a/rector.php b/rector.php
index 77d1b97..d31bad3 100644
--- a/rector.php
+++ b/rector.php
@@ -5,30 +5,42 @@
use Contao\Rector\Set\ContaoLevelSetList;
use Contao\Rector\Set\ContaoSetList;
use Rector\Config\RectorConfig;
+use Rector\Php81\Rector\Array_\ArrayToFirstClassCallableRector;
use Rector\Php84\Rector\Param\ExplicitNullableParamTypeRector;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Symfony\Set\SymfonySetList;
use Rector\TypeDeclaration\Rector\ClassMethod\AddVoidReturnTypeWhereNoReturnRector;
+use Rector\ValueObject\PhpVersion;
return RectorConfig::configure()
->withPaths([
__DIR__ . '/src',
__DIR__ . '/contao',
+ __DIR__ . '/config',
])
+ ->withPhpVersion(PhpVersion::PHP_84)
->withRules([
AddVoidReturnTypeWhereNoReturnRector::class,
- # In Vorbereitung für PHP 8.4:
ExplicitNullableParamTypeRector::class
])
- ->withImportNames(importShortClasses: false, removeUnusedImports: true)
+ ->withImportNames(
+ importShortClasses: false,
+ removeUnusedImports: true,
+ )
+ ->withComposerBased(
+ twig: true,
+ doctrine: true,
+ phpunit: true,
+ symfony: true,
+ )
->withSets([
LevelSetList::UP_TO_PHP_81,
- SymfonySetList::SYMFONY_54,
- SymfonySetList::SYMFONY_CONSTRUCTOR_INJECTION,
- # Erst mit Symfony 6 (Contao 5) nutzen:
- // SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES,
ContaoLevelSetList::UP_TO_CONTAO_413,
ContaoSetList::FQCN,
ContaoSetList::ANNOTATIONS_TO_ATTRIBUTES,
- ]);
\ No newline at end of file
+ ])
+ ->withSkip([
+ ArrayToFirstClassCallableRector::class,
+ ])
+ ;
\ No newline at end of file
diff --git a/src/Asset/PageEntrypoints.php b/src/Asset/PageEntrypoints.php
index 6d24403..8fecf24 100644
--- a/src/Asset/PageEntrypoints.php
+++ b/src/Asset/PageEntrypoints.php
@@ -16,6 +16,9 @@
use HeimrichHannot\EncoreBundle\Helper\ArrayHelper;
use HeimrichHannot\UtilsBundle\Util\Utils;
+/**
+ * @deprecated Since version 2.2
+ */
class PageEntrypoints
{
protected $jsEntries = [];
@@ -81,9 +84,7 @@ public function collectPageEntries(LayoutModel $layout, PageModel $currentPage,
$parents = [$layout];
$parentPages = $this->utils->model()->findParentsRecursively($currentPage, 'pid');
- if (\is_array($parentPages)) {
- $parents = array_merge($parents, $parentPages);
- }
+ $parents = array_merge($parents, $parentPages);
$parents = array_merge($parents, [$currentPage]);
$parents = array_reverse($parents);
diff --git a/src/Asset/TemplateAsset.php b/src/Asset/TemplateAsset.php
index a194423..52a9e27 100644
--- a/src/Asset/TemplateAsset.php
+++ b/src/Asset/TemplateAsset.php
@@ -14,6 +14,9 @@
use Twig\Environment;
use Twig\Error\RuntimeError;
+/**
+ * @deprecated Since version 2.2
+ */
class TemplateAsset
{
/**
diff --git a/src/Asset/TemplateAssetGenerator.php b/src/Asset/TemplateAssetGenerator.php
index 2897e72..5edb7c5 100644
--- a/src/Asset/TemplateAssetGenerator.php
+++ b/src/Asset/TemplateAssetGenerator.php
@@ -14,6 +14,9 @@
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
+/**
+ * @deprecated Since 2.2
+ */
class TemplateAssetGenerator
{
/**
diff --git a/src/ContaoManager/Plugin.php b/src/ContaoManager/Plugin.php
index 2b6bf5c..0eda75b 100644
--- a/src/ContaoManager/Plugin.php
+++ b/src/ContaoManager/Plugin.php
@@ -33,6 +33,6 @@ public function getBundles(ParserInterface $parser): array
public function registerContainerConfiguration(LoaderInterface $loader, array $managerConfig): void
{
$loader->load('@HeimrichHannotEncoreBundle/config/config.yml');
- $loader->load('@HeimrichHannotEncoreBundle/config/services.yml');
+ $loader->load('@HeimrichHannotEncoreBundle/config/services.php');
}
}
diff --git a/src/Dca/EncoreEntriesSelectField.php b/src/Dca/EncoreEntriesSelectField.php
index ea4b1ad..721a2fd 100644
--- a/src/Dca/EncoreEntriesSelectField.php
+++ b/src/Dca/EncoreEntriesSelectField.php
@@ -4,6 +4,8 @@
class EncoreEntriesSelectField
{
+ public const NAME_DEFAULT = 'encoreEntries';
+
protected static array $tables = [];
/**
diff --git a/src/Dca/EncoreEntriesSelectFieldOptions.php b/src/Dca/EncoreEntriesSelectFieldOptions.php
index 2abfa75..091df03 100644
--- a/src/Dca/EncoreEntriesSelectFieldOptions.php
+++ b/src/Dca/EncoreEntriesSelectFieldOptions.php
@@ -4,7 +4,7 @@
class EncoreEntriesSelectFieldOptions
{
- protected string $fieldName = 'encoreEntries';
+ protected string $fieldName = EncoreEntriesSelectField::NAME_DEFAULT;
protected bool $includeActiveCheckbox = false;
protected ?array $fieldLabel = null;
protected ?array $selectLabel = null;
diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php
index ec9ff12..60836c0 100644
--- a/src/DependencyInjection/Configuration.php
+++ b/src/DependencyInjection/Configuration.php
@@ -20,6 +20,7 @@ public function getConfigTreeBuilder(): TreeBuilder
$treeBuilder->getRootNode()
->children()
->arrayNode('templates')
+ ->setDeprecated('heimrichhannot/contao-encore-bundle', '2.2.0')
->addDefaultsIfNotSet()
->children()
->arrayNode('imports')
diff --git a/src/EntryPoint/EntryPoint.php b/src/EntryPoint/EntryPoint.php
new file mode 100644
index 0000000..e49910b
--- /dev/null
+++ b/src/EntryPoint/EntryPoint.php
@@ -0,0 +1,16 @@
+utils,
+ $this->entryCollection,
+ );
+ }
+}
diff --git a/src/EntryPoint/EntryPoints.php b/src/EntryPoint/EntryPoints.php
new file mode 100644
index 0000000..f763773
--- /dev/null
+++ b/src/EntryPoint/EntryPoints.php
@@ -0,0 +1,41 @@
+entryPoints[$entryPoint->name] = $entryPoint;
+ if ($entryPoint->active) {
+ $this->active[$entryPoint->name] = $entryPoint;
+ } else {
+ unset($this->active[$entryPoint->name]);
+ }
+ }
+
+ /**
+ * @return EntryPoint[]
+ */
+ public function all(): array
+ {
+ return $this->entryPoints;
+ }
+
+ /**
+ * @return EntryPoint[]
+ */
+ public function allActive(): array
+ {
+ return $this->active;
+ }
+}
diff --git a/src/EntryPoint/EntryPointsBuilder.php b/src/EntryPoint/EntryPointsBuilder.php
new file mode 100644
index 0000000..dd83180
--- /dev/null
+++ b/src/EntryPoint/EntryPointsBuilder.php
@@ -0,0 +1,130 @@
+pageModel = $page;
+ $this->pageField = $field;
+
+ return $this;
+ }
+
+ public function setLayout(?LayoutModel $layout, string $field = EncoreEntriesSelectField::NAME_DEFAULT): self
+ {
+ $this->layout = $layout;
+ $this->layoutField = $field;
+
+ return $this;
+ }
+
+ public function setFrontendAsset(?FrontendAsset $frontendAsset): self
+ {
+ $this->frontendAsset = $frontendAsset;
+
+ return $this;
+ }
+
+ public function build(): EntryPoints
+ {
+ $entryPoints = new EntryPoints();
+ $available = $this->entryCollection->getEntries();
+ if ([] !== $available) {
+ $available = array_combine(array_column($available, 'name'), $available);
+ }
+ $this->available = $available;
+
+ if ($this->frontendAsset) {
+ foreach ($this->frontendAsset->getActiveEntrypoints() as $entryPoint) {
+ $this->addEntryPoint(
+ entryPoints: $entryPoints,
+ name: $entryPoint,
+ origin: FrontendAsset::class,
+ );
+ }
+ }
+
+ if ($this->pageModel && !$this->layout) {
+ $this->pageModel->loadDetails();
+ $layout = LayoutModel::findByPk($this->pageModel->layoutId ?? $this->pageModel->layout);
+ if ($layout) {
+ $this->setLayout($layout);
+ }
+ }
+
+ if ($this->layout) {
+ foreach (StringUtil::deserialize($this->layout->{$this->layoutField}, true) as $entrypoint) {
+ $this->addEntryPoint(
+ entryPoints: $entryPoints,
+ name: $entrypoint['entry'] ?? '',
+ active: (bool) ($entrypoint['active'] ?? true),
+ origin: 'tl_layout.' . $this->layout->id,
+ extension: 'App',
+ );
+ }
+ }
+
+ if (null !== $this->pageModel) {
+ $pages = $this->utils->model()->findParentsRecursively($this->pageModel, 'pid');
+ $pages[] = $this->pageModel;
+
+ foreach ($pages as $page) {
+ foreach (StringUtil::deserialize($page->{$this->pageField}, true) as $entrypoint) {
+ $this->addEntryPoint(
+ entryPoints: $entryPoints,
+ name: $entrypoint['entry'] ?? '',
+ active: (bool) ($entrypoint['active'] ?? true),
+ origin: 'tl_page.' . $page->id,
+ extension: 'App',
+ );
+ }
+ }
+ }
+
+ return $entryPoints;
+ }
+
+ private function addEntryPoint(EntryPoints $entryPoints, string $name, bool $active = true, string $origin = '', string $extension = ''): void
+ {
+ if ('' === $name) {
+ return;
+ }
+
+ if (!isset($this->available[$name])) {
+ return;
+ }
+
+ $entryPoints->add(new EntryPoint(
+ name: $name,
+ active: $active,
+ head: $this->available[$name]['head'] ?? false,
+ requiresCss: (bool) ($this->available[$name]['requires_css'] ?? true),
+ origin: $origin,
+ extension: $extension,
+ ));
+ }
+}
diff --git a/src/Event/EncoreEnabledEvent.php b/src/Event/EncoreEnabledEvent.php
index 0c2e9fc..d8085ef 100644
--- a/src/Event/EncoreEnabledEvent.php
+++ b/src/Event/EncoreEnabledEvent.php
@@ -8,6 +8,7 @@
namespace HeimrichHannot\EncoreBundle\Event;
+use Contao\LayoutModel;
use Contao\PageModel;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Contracts\EventDispatcher\Event;
@@ -15,14 +16,24 @@
class EncoreEnabledEvent extends Event
{
public function __construct(
- private bool $enabled,
- private readonly Request $request,
- private readonly ?PageModel $pageModel,
+ public bool $enabled,
+ public readonly Request $request,
+ public readonly ?PageModel $pageModel = null,
+ public readonly ?LayoutModel $layoutModel = null,
) {
}
+ /**
+ * @deprecated
+ */
public function isEnabled(): bool
{
+ trigger_deprecation(
+ 'heimrichhannot/contao-encore-bundle',
+ '2.2.0',
+ 'Use class properties instead.'
+ );
+
return $this->enabled;
}
@@ -33,13 +44,31 @@ public function setEnabled(bool $enabled): self
return $this;
}
+ /**
+ * @deprecated
+ */
public function getRequest(): Request
{
+ trigger_deprecation(
+ 'heimrichhannot/contao-encore-bundle',
+ '2.2.0',
+ 'Use class properties instead.'
+ );
+
return $this->request;
}
+ /**
+ * @deprecated
+ */
public function getPageModel(): ?PageModel
{
+ trigger_deprecation(
+ 'heimrichhannot/contao-encore-bundle',
+ '2.2.0',
+ 'Use class properties instead.'
+ );
+
return $this->pageModel;
}
}
diff --git a/src/EventListener/Contao/ReplaceDynamicScriptTagsListener.php b/src/EventListener/Contao/ReplaceDynamicScriptTagsListener.php
index d62c492..4f49303 100644
--- a/src/EventListener/Contao/ReplaceDynamicScriptTagsListener.php
+++ b/src/EventListener/Contao/ReplaceDynamicScriptTagsListener.php
@@ -10,78 +10,64 @@
use Contao\CoreBundle\DependencyInjection\Attribute\AsHook;
use Contao\CoreBundle\Framework\ContaoFramework;
-use Contao\LayoutModel;
-use Contao\PageModel;
+use HeimrichHannot\EncoreBundle\Asset\FrontendAsset;
use HeimrichHannot\EncoreBundle\Asset\GlobalContaoAsset;
-use HeimrichHannot\EncoreBundle\Asset\TemplateAsset;
+use HeimrichHannot\EncoreBundle\EntryPoint\EntryPointBuilderFactory;
use HeimrichHannot\EncoreBundle\Helper\ConfigurationHelper;
use HeimrichHannot\UtilsBundle\Util\Utils;
+use Symfony\WebpackEncoreBundle\Asset\TagRenderer;
#[AsHook('replaceDynamicScriptTags')]
class ReplaceDynamicScriptTagsListener
{
public function __construct(
- protected array $bundleConfig,
- private readonly ContaoFramework $contaoFramework,
private readonly Utils $utils,
- protected TemplateAsset $templateAsset,
protected ConfigurationHelper $configurationHelper,
private readonly GlobalContaoAsset $globalContaoAsset,
+ private readonly EntryPointBuilderFactory $entryPointBuilderFactory,
+ private readonly FrontendAsset $frontendAsset,
+ private readonly TagRenderer $tagRenderer,
) {
}
public function __invoke(string $buffer): string
{
- if (!$this->configurationHelper->isEnabledOnCurrentPage()) {
- return $buffer;
- }
-
$pageModel = $this->utils->request()->getCurrentPageModel();
if (!$pageModel) {
return $buffer;
}
- $pageModel->loadDetails();
-
- if (!($layout = $this->contaoFramework->getAdapter(LayoutModel::class)->findByPk($pageModel->layoutId ?? $pageModel->layout))) {
+ if (!$this->configurationHelper->isEnabledOnPage($pageModel)) {
return $buffer;
}
- /* @var LayoutModel|null $layout */
- $buffer = $this->replaceContaoTags($buffer, $pageModel, $layout);
- $this->globalContaoAsset->cleanGlobalArrayFromConfiguration();
- return $buffer;
- }
-
- protected function replaceEncoreTags(string $buffer, PageModel $page, LayoutModel $layout): string
- {
- $templateAssets = $this->templateAsset->createInstance($page, $layout, 'encoreEntries');
-
- $replace = [];
- $replace['[[HUH_ENCORE_CSS]]'] = trim($templateAssets->linkTags());
- // caution: always render head first because of global dependencies like jQuery
- $replace['[[HUH_ENCORE_HEAD_JS]]'] = trim($templateAssets->headScriptTags());
- $replace['[[HUH_ENCORE_JS]]'] = trim($templateAssets->scriptTags());
-
- return str_replace(array_keys($replace), $replace, $buffer);
- }
-
- protected function replaceContaoTags(string $buffer, PageModel $page, LayoutModel $layout): string
- {
- $templateAssets = $this->templateAsset->createInstance($page, $layout, 'encoreEntries');
-
- $nonce = '';
- if (method_exists(ContaoFramework::class, 'getNonce')) {
- $nonce = '_' . ContaoFramework::getNonce();
+ $entryPoints = $this->entryPointBuilderFactory->create()
+ ->setFrontendAsset($this->frontendAsset)
+ ->setPage($pageModel)
+ ->build();
+
+ $css = '';
+ $headJs = '';
+ $bodyJs = '';
+ foreach ($entryPoints->allActive() as $entrypoint) {
+ if ($entrypoint->requiresCss) {
+ $css .= $this->tagRenderer->renderWebpackLinkTags($entrypoint->name);
+ }
+ if ($entrypoint->head) {
+ $headJs .= $this->tagRenderer->renderWebpackScriptTags($entrypoint->name);
+ } else {
+ $bodyJs .= $this->tagRenderer->renderWebpackScriptTags($entrypoint->name);
+ }
}
- $replace = [];
- $replace["[[TL_CSS$nonce]]"] = "[[TL_CSS$nonce]]" . trim($templateAssets->linkTags());
+ $this->globalContaoAsset->cleanGlobalArrayFromConfiguration();
- // caution: always render head first because of global dependencies like jQuery
- $replace["[[TL_HEAD$nonce]]"] = trim($templateAssets->headScriptTags()) . "[[TL_HEAD$nonce]]";
- $replace["[[TL_BODY$nonce]]"] = trim($templateAssets->scriptTags()) . "[[TL_BODY$nonce]]";
+ $nonce = '_' . ContaoFramework::getNonce();
+ $replace = [];
+ $replace["[[TL_CSS$nonce]]"] = "[[TL_CSS$nonce]]" . trim($css);
+ $replace["[[TL_HEAD$nonce]]"] = trim($headJs) . "[[TL_HEAD$nonce]]";
+ $replace["[[TL_BODY$nonce]]"] = trim($bodyJs) . "[[TL_BODY$nonce]]";
return str_replace(array_keys($replace), $replace, $buffer);
}
diff --git a/src/EventListener/InjectPageEntriesListener.php b/src/EventListener/InjectPageEntriesListener.php
new file mode 100644
index 0000000..526db6f
--- /dev/null
+++ b/src/EventListener/InjectPageEntriesListener.php
@@ -0,0 +1,52 @@
+configurationHelper->isEnabledOnPage($event->getPage(), $event->getLayout())) {
+ return;
+ }
+
+ $this->globalContaoAsset->cleanGlobalArrayFromConfiguration();
+
+ $entryPoints = $this->entrypointBuilderFactory->create()
+ ->setPage($event->getPage())
+ ->setLayout($event->getLayout())
+ ->setFrontendAsset($this->frontendAsset)
+ ->build();
+
+ $this->tagRenderer->reset();
+
+ foreach ($entryPoints->allActive() as $entrypoint) {
+ if ($entrypoint->requiresCss) {
+ $GLOBALS['TL_HEAD'][] = $this->tagRenderer->renderWebpackLinkTags($entrypoint->name);
+ }
+ if ($entrypoint->head) {
+ $GLOBALS['TL_HEAD'][] = $this->tagRenderer->renderWebpackScriptTags($entrypoint->name);
+ } else {
+ $GLOBALS['TL_BODY'][] = $this->tagRenderer->renderWebpackScriptTags($entrypoint->name);
+ }
+ }
+ }
+}
diff --git a/src/Helper/ConfigurationHelper.php b/src/Helper/ConfigurationHelper.php
index d81f98f..f2c7a58 100644
--- a/src/Helper/ConfigurationHelper.php
+++ b/src/Helper/ConfigurationHelper.php
@@ -21,49 +21,81 @@
class ConfigurationHelper
{
- /**
- * @var RequestStack
- */
- protected $requestStack;
- /**
- * @var array
- */
- protected $bundleConfig;
- /**
- * @var string
- */
- protected $webDir;
+ protected array $bundleConfig;
+ protected string $webDir;
public function __construct(
- RequestStack $requestStack,
+ private readonly RequestStack $requestStack,
ParameterBagInterface $parameterBag,
private readonly ScopeMatcher $scopeMatcher,
private readonly ContaoFramework $contaoFramework,
private readonly EventDispatcherInterface $eventDispatcher,
) {
- $this->requestStack = $requestStack;
$this->bundleConfig = $parameterBag->has('huh_encore') ? $parameterBag->get('huh_encore') : [];
$this->webDir = $parameterBag->has('contao.web_dir') ? $parameterBag->get('contao.web_dir') : '';
}
/**
* Check if encore is enabled on the current page.
+ *
+ * @deprecated
*/
- public function isEnabledOnCurrentPage(?PageModel $pageModel = null): bool
+ public function isEnabledOnCurrentPage(?PageModel $pageModel = null, ?LayoutModel $layout = null): bool
+ {
+ trigger_deprecation(
+ 'heimrichhannot/contao-encore-bundle',
+ '2.2.0',
+ 'The method "isEnabledOnCurrentPage" is deprecated since version 2.2.0 and will be removed in version 3.0.0. Please use "isEnabledOnPage" instead.'
+ );
+
+ $pageModel ??= $this->getPageModel();
+
+ if (null === $pageModel) {
+ return false;
+ }
+
+ return $this->isEnabledOnPage($pageModel, $layout);
+ }
+
+ public function isEnabledOnPage(PageModel $page, ?LayoutModel $layout = null): bool
{
$request = $this->requestStack->getCurrentRequest();
+ if (!$request || !$this->scopeMatcher->isFrontendRequest($request)) {
+ return $this->dispatchEvent(false, $request);
+ }
+
+ if (!$layout) {
+ $page->loadDetails();
+ $layout = $this->contaoFramework
+ ->getAdapter(LayoutModel::class)
+ ->findByPk($page->layoutId ?? $page->layout);
+ }
+
+ if (!$layout?->addEncore) {
+ return $this->dispatchEvent(false, $request, $page, $layout);
+ }
+
+ if ('modern' !== $layout->type) {
+ if (false === $this->evaluateIsEnabled($page)) {
+ return $this->dispatchEvent(false, $request, $page, $layout);
+ }
+ }
+
+ return $this->dispatchEvent(true, $request, $page, $layout);
+ }
+
+ private function dispatchEvent(bool $result, ?Request $request = null, ?PageModel $page = null, ?LayoutModel $layout = null): bool
+ {
+ // ToDo: allow request = null in event
if (!$request) {
return false;
}
- $result = $this->evaluateIsEnabled($pageModel, $request);
-
- /** @var EncoreEnabledEvent $event */
$event = $this->eventDispatcher->dispatch(
- new EncoreEnabledEvent($result, $request, $pageModel)
+ new EncoreEnabledEvent($result, $request, $page, $layout)
);
- return $event->isEnabled();
+ return $event->enabled;
}
/**
@@ -107,12 +139,8 @@ public function getPageModel(): ?PageModel
return $this->contaoFramework->getAdapter(PageModel::class)->findByPk((int) $pageModel);
}
- private function evaluateIsEnabled(?PageModel $pageModel, Request $request): bool
+ private function evaluateIsEnabled(?PageModel $pageModel): bool
{
- if (!$this->scopeMatcher->isFrontendRequest($request)) {
- return false;
- }
-
$parentPageModel = $this->getPageModel();
// Check if error page
@@ -130,13 +158,6 @@ private function evaluateIsEnabled(?PageModel $pageModel, Request $request): boo
return false;
}
- $pageModel->loadDetails();
- $layout = $this->contaoFramework->getAdapter(LayoutModel::class)->findByPk($pageModel->layoutId ?? $pageModel->layout);
-
- if (!$layout || !$layout->addEncore) {
- return false;
- }
-
return true;
}
}
diff --git a/tests/EntryPoint/EntryPointsBuilderTest.php b/tests/EntryPoint/EntryPointsBuilderTest.php
new file mode 100644
index 0000000..2598343
--- /dev/null
+++ b/tests/EntryPoint/EntryPointsBuilderTest.php
@@ -0,0 +1,161 @@
+createMock(Utils::class);
+ $entryCollection = $this->createMock(EntryCollection::class);
+
+ $factory = new EntryPointBuilderFactory($utils, $entryCollection);
+
+ $firstBuilder = $factory->create();
+ $secondBuilder = $factory->create();
+
+ $this->assertInstanceOf(EntryPointsBuilder::class, $firstBuilder);
+ $this->assertInstanceOf(EntryPointsBuilder::class, $secondBuilder);
+ $this->assertNotSame($firstBuilder, $secondBuilder);
+ }
+
+ public function testEntryPointsTracksAllAndActiveEntries(): void
+ {
+ $entryPoint = new EntryPoint(
+ name: 'app',
+ active: true,
+ head: true,
+ requiresCss: true,
+ origin: 'frontend',
+ extension: 'App',
+ );
+
+ $this->assertSame('app', $entryPoint->name);
+ $this->assertTrue($entryPoint->active);
+ $this->assertTrue($entryPoint->head);
+ $this->assertTrue($entryPoint->requiresCss);
+ $this->assertSame('frontend', $entryPoint->origin);
+ $this->assertSame('App', $entryPoint->extension);
+
+ $entryPoints = new EntryPoints();
+ $entryPoints->add($entryPoint);
+ $entryPoints->add(new EntryPoint('deferred', head: false, requiresCss: false));
+ $entryPoints->add(new EntryPoint('app', active: false, origin: 'tl_page.1'));
+
+ $all = $entryPoints->all();
+ $active = $entryPoints->allActive();
+
+ $this->assertCount(2, $all);
+ $this->assertCount(1, $active);
+ $this->assertFalse($all['app']->active);
+ $this->assertSame('tl_page.1', $all['app']->origin);
+ $this->assertArrayNotHasKey('app', $active);
+ $this->assertSame('deferred', $active['deferred']->name);
+ }
+
+ public function testBuildCombinesFrontendLayoutAndPageEntries(): void
+ {
+ $entryCollection = $this->createMock(EntryCollection::class);
+ $entryCollection->expects($this->once())
+ ->method('getEntries')
+ ->willReturn([
+ ['name' => 'frontend-entry', 'requires_css' => false],
+ ['name' => 'layout-entry', 'head' => true, 'requires_css' => true],
+ ['name' => 'shared-entry', 'head' => false, 'requires_css' => true],
+ ['name' => 'parent-entry'],
+ ['name' => 'page-entry', 'requires_css' => false],
+ ]);
+
+ $parentPage = $this->mockModelObject(PageModel::class, [
+ 'id' => 2,
+ 'customEntries' => serialize([
+ ['entry' => 'shared-entry', 'active' => '1'],
+ ['entry' => 'parent-entry', 'active' => '1'],
+ ['entry' => 'missing-entry', 'active' => '1'],
+ ]),
+ ]);
+
+ $page = $this->mockModelObject(PageModel::class, [
+ 'id' => 3,
+ 'customEntries' => serialize([
+ ['entry' => 'shared-entry', 'active' => ''],
+ ['entry' => 'page-entry', 'active' => '1'],
+ ['entry' => '', 'active' => '1'],
+ ]),
+ ]);
+
+ $layout = $this->mockClassWithProperties(LayoutModel::class, [
+ 'id' => 5,
+ 'layoutEntries' => serialize([
+ ['entry' => 'layout-entry', 'active' => '1'],
+ ['entry' => 'missing-layout-entry', 'active' => '1'],
+ ]),
+ ]);
+
+ $modelUtil = $this->createMock(ModelUtil::class);
+ $modelUtil->expects($this->once())
+ ->method('findParentsRecursively')
+ ->with($page, 'pid')
+ ->willReturn([$parentPage]);
+
+ $utils = $this->createMock(Utils::class);
+ $utils->expects($this->once())
+ ->method('model')
+ ->willReturn($modelUtil);
+
+ $frontendAsset = new FrontendAsset();
+ $frontendAsset->addActiveEntrypoint('frontend-entry');
+ $frontendAsset->addActiveEntrypoint('missing-frontend-entry');
+
+ $builder = new EntryPointsBuilder($utils, $entryCollection);
+ $result = $builder
+ ->setFrontendAsset($frontendAsset)
+ ->setLayout($layout, 'layoutEntries')
+ ->setPage($page, 'customEntries')
+ ->build();
+
+ $this->assertInstanceOf(EntryPoints::class, $result);
+
+ $all = $result->all();
+ $active = $result->allActive();
+
+ $this->assertSame(
+ ['frontend-entry', 'layout-entry', 'shared-entry', 'parent-entry', 'page-entry'],
+ array_keys($all)
+ );
+ $this->assertSame(
+ ['frontend-entry', 'layout-entry', 'parent-entry', 'page-entry'],
+ array_keys($active)
+ );
+
+ $this->assertSame(FrontendAsset::class, $all['frontend-entry']->origin);
+ $this->assertFalse($all['frontend-entry']->requiresCss);
+ $this->assertTrue($all['layout-entry']->head);
+ $this->assertTrue($all['layout-entry']->requiresCss);
+ $this->assertSame('tl_layout.5', $all['layout-entry']->origin);
+ $this->assertSame('App', $all['layout-entry']->extension);
+ $this->assertFalse($all['shared-entry']->active);
+ $this->assertSame('tl_page.3', $all['shared-entry']->origin);
+ $this->assertArrayNotHasKey('shared-entry', $active);
+ $this->assertTrue($all['parent-entry']->requiresCss);
+ $this->assertSame('tl_page.2', $all['parent-entry']->origin);
+ $this->assertFalse($all['page-entry']->head);
+ $this->assertFalse($all['page-entry']->requiresCss);
+ $this->assertSame('tl_page.3', $all['page-entry']->origin);
+ }
+}
diff --git a/tests/EventListener/Contao/ReplaceDynamicScriptTagsListenerTest.php b/tests/EventListener/Contao/ReplaceDynamicScriptTagsListenerTest.php
index 9c55c63..0400668 100644
--- a/tests/EventListener/Contao/ReplaceDynamicScriptTagsListenerTest.php
+++ b/tests/EventListener/Contao/ReplaceDynamicScriptTagsListenerTest.php
@@ -9,161 +9,148 @@
namespace HeimrichHannot\EncoreBundle\Test\EventListener\Contao;
use Contao\CoreBundle\Framework\ContaoFramework;
-use Contao\CoreBundle\ServiceAnnotation\Page;
-use Contao\LayoutModel;
use Contao\PageModel;
use Contao\TestCase\ContaoTestCase;
+use HeimrichHannot\EncoreBundle\Asset\FrontendAsset;
use HeimrichHannot\EncoreBundle\Asset\GlobalContaoAsset;
-use HeimrichHannot\EncoreBundle\Asset\TemplateAsset;
+use HeimrichHannot\EncoreBundle\EntryPoint\EntryPoint;
+use HeimrichHannot\EncoreBundle\EntryPoint\EntryPointBuilderFactory;
+use HeimrichHannot\EncoreBundle\EntryPoint\EntryPoints;
+use HeimrichHannot\EncoreBundle\EntryPoint\EntryPointsBuilder;
use HeimrichHannot\EncoreBundle\EventListener\Contao\ReplaceDynamicScriptTagsListener;
use HeimrichHannot\EncoreBundle\Helper\ConfigurationHelper;
use HeimrichHannot\TestUtilitiesBundle\Mock\ModelMockTrait;
use HeimrichHannot\UtilsBundle\Util\RequestUtil;
use HeimrichHannot\UtilsBundle\Util\Utils;
-use PHPUnit\Framework\MockObject\MockBuilder;
-use PHPUnit\Framework\MockObject\MockObject;
+use Symfony\WebpackEncoreBundle\Asset\TagRenderer;
class ReplaceDynamicScriptTagsListenerTest extends ContaoTestCase
{
use ModelMockTrait;
- /**
- * @return ReplaceDynamicScriptTagsListener|MockObject
- */
- public function createTestInstance(array $parameter = [], ?MockBuilder $mockBuilder = null)
+ public function createTestInstance(array $parameter = []): ReplaceDynamicScriptTagsListener
{
- $parameter['bundleConfig'] = $parameter['bundleConfig'] ?? [];
- $parameter['contaoFramework'] = $parameter['contaoFramework'] ?? $this->mockContaoFramework();
$parameter['utils'] = $parameter['utils'] ?? $this->createMock(Utils::class);
- $parameter['templateAsset'] = $parameter['templateAsset'] ?? $this->createMock(TemplateAsset::class);
$parameter['configurationHelper'] = $parameter['configurationHelper'] ?? $this->createMock(ConfigurationHelper::class);
$parameter['globalContaoAsset'] = $parameter['globalContaoAsset'] ?? $this->createMock(GlobalContaoAsset::class);
-
- if ($mockBuilder) {
- $instance = $mockBuilder->setConstructorArgs([
- $parameter['bundleConfig'],
- $parameter['contaoFramework'],
- $parameter['utils'],
- $parameter['templateAsset'],
- $parameter['configurationHelper'],
- $parameter['globalContaoAsset'],
- ])->getMock();
- } else {
- $instance = new ReplaceDynamicScriptTagsListener(
- $parameter['bundleConfig'],
- $parameter['contaoFramework'],
- $parameter['utils'],
- $parameter['templateAsset'],
- $parameter['configurationHelper'],
- $parameter['globalContaoAsset'],
- );
- }
-
- return $instance;
+ $parameter['entryPointBuilderFactory'] = $parameter['entryPointBuilderFactory'] ?? $this->createMock(EntryPointBuilderFactory::class);
+ $parameter['frontendAsset'] = $parameter['frontendAsset'] ?? $this->createMock(FrontendAsset::class);
+ $parameter['tagRenderer'] = $parameter['tagRenderer'] ?? $this->createMock(TagRenderer::class);
+
+ return new ReplaceDynamicScriptTagsListener(
+ $parameter['utils'],
+ $parameter['configurationHelper'],
+ $parameter['globalContaoAsset'],
+ entryPointBuilderFactory: $parameter['entryPointBuilderFactory'],
+ frontendAsset: $parameter['frontendAsset'],
+ tagRenderer: $parameter['tagRenderer'],
+ );
}
public function testInvoke()
{
- //
- // Encore not enabled
- //
-
- $configurationHelper = $this->createMock(ConfigurationHelper::class);
- $configurationHelper->method('isEnabledOnCurrentPage')->willReturn(false);
-
- $utils = $this->createMock(Utils::class);
- $utils->expects($this->never())->method('request');
-
- $instance = $this->createTestInstance([
- 'utils' => $utils,
- 'configurationHelper' => $configurationHelper,
- ]);
- $instance->__invoke('test');
-
- //
- // No page
- //
-
- $configurationHelper = $this->createMock(ConfigurationHelper::class);
- $configurationHelper->method('isEnabledOnCurrentPage')->willReturn(true);
-
$requestUtil = $this->createMock(RequestUtil::class);
$requestUtil->method('getCurrentPageModel')->willReturn(null);
+
$utils = $this->createMock(Utils::class);
$utils->method('request')->willReturn($requestUtil);
- $layoutAdapter = $this->mockAdapter(['findByPk']);
- $layoutAdapter->expects($this->never())->method('findByPk');
+ $configurationHelper = $this->createMock(ConfigurationHelper::class);
+ $configurationHelper->expects($this->never())->method('isEnabledOnPage');
+
+ $entryPointBuilderFactory = $this->createMock(EntryPointBuilderFactory::class);
+ $entryPointBuilderFactory->expects($this->never())->method('create');
- $framework = $this->mockContaoFramework([
- LayoutModel::class => $layoutAdapter,
- ]);
+ $globalContaoAsset = $this->createMock(GlobalContaoAsset::class);
+ $globalContaoAsset->expects($this->never())->method('cleanGlobalArrayFromConfiguration');
$instance = $this->createTestInstance([
'utils' => $utils,
'configurationHelper' => $configurationHelper,
- 'contaoFramework' => $framework,
+ 'globalContaoAsset' => $globalContaoAsset,
+ 'entryPointBuilderFactory' => $entryPointBuilderFactory,
]);
- $instance->__invoke('test');
+ $this->assertSame('test', $instance->__invoke('test'));
- //
- // No Layout
- //
+ $pageModel = $this->mockModelObject(PageModel::class, [
+ 'id' => 1,
+ ]);
$requestUtil = $this->createMock(RequestUtil::class);
- $requestUtil->method('getCurrentPageModel')->willReturn($this->mockModelObject(PageModel::class, [
- 'layoutId' => 3,
- ]));
+ $requestUtil->method('getCurrentPageModel')->willReturn($pageModel);
+
$utils = $this->createMock(Utils::class);
$utils->method('request')->willReturn($requestUtil);
- $layoutAdapter = $this->mockAdapter(['findByPk']);
- $layoutAdapter->method('findByPk')->willReturn(null);
+ $configurationHelper = $this->createMock(ConfigurationHelper::class);
+ $configurationHelper->expects($this->once())
+ ->method('isEnabledOnPage')
+ ->with($pageModel)
+ ->willReturn(false);
- $framework = $this->mockContaoFramework([
- LayoutModel::class => $layoutAdapter,
- ]);
+ $entryPointBuilderFactory = $this->createMock(EntryPointBuilderFactory::class);
+ $entryPointBuilderFactory->expects($this->never())->method('create');
- $templateAssetMock = $this->createMock(TemplateAsset::class);
- $templateAssetMock->method('createInstance')->willReturnSelf();
- $templateAssetMock->method('linkTags')->willReturn('');
- $templateAssetMock->method('scriptTags')->willReturn('