diff --git a/.github/workflows/codeception.yml b/.github/workflows/codeception.yml index ec195d49..326a596c 100644 --- a/.github/workflows/codeception.yml +++ b/.github/workflows/codeception.yml @@ -15,7 +15,7 @@ jobs: TEST_PROJECT_ROOT_DIR: "${{ github.workspace }}" PIMCORE_CODECEPTION_FRAMEWORK: "${{ github.workspace }}/pimcore-codeception-framework" - PIMCORE_CODECEPTION_VERSION: "2.0" + PIMCORE_CODECEPTION_VERSION: "3.0" APP_ENV: test PIMCORE_TEST_DB_DSN: "mysql://test:test@127.0.0.1:3306/dachcom_bundle_test" @@ -38,12 +38,12 @@ jobs: options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 strategy: matrix: - php: [ 8.1 ] - symfony: [ ^5.4 ] - pimcore: [ ~10.6.0 ] + php: [ 8.2 ] + symfony: [ ^6.2 ] + pimcore: [ ~11.0.0 ] include: - - pimcore: ~10.6.0 - template_tag: v10.2.5 + - pimcore: ~11.0.0 + template_tag: v11.0.0 steps: - uses: actions/checkout@v2 with: diff --git a/.github/workflows/ecs.yml b/.github/workflows/ecs.yml index d3fd391a..e298b483 100644 --- a/.github/workflows/ecs.yml +++ b/.github/workflows/ecs.yml @@ -15,7 +15,7 @@ jobs: TEST_PROJECT_ROOT_DIR: "${{ github.workspace }}" PIMCORE_CODECEPTION_FRAMEWORK: "${{ github.workspace }}/pimcore-codeception-framework" - PIMCORE_CODECEPTION_VERSION: "2.0" + PIMCORE_CODECEPTION_VERSION: "3.0" APP_ENV: test PIMCORE_TEST_DB_DSN: "mysql://root:root@127.0.0.1:3306/dachcom_bundle_test" @@ -37,12 +37,12 @@ jobs: options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 strategy: matrix: - php: [ 8.1 ] - symfony: [ ^5.4 ] - pimcore: [ ~10.6.0 ] + php: [ 8.2 ] + symfony: [ ^6.2 ] + pimcore: [ ~11.0.0 ] include: - - pimcore: ~10.6.0 - template_tag: v10.2.5 + - pimcore: ~11.0.0 + template_tag: v11.0.0 steps: - uses: actions/checkout@v2 with: diff --git a/.github/workflows/php-stan.yml b/.github/workflows/php-stan.yml index e8bfc67e..47a69043 100644 --- a/.github/workflows/php-stan.yml +++ b/.github/workflows/php-stan.yml @@ -15,7 +15,7 @@ jobs: TEST_PROJECT_ROOT_DIR: "${{ github.workspace }}" PIMCORE_CODECEPTION_FRAMEWORK: "${{ github.workspace }}/pimcore-codeception-framework" - PIMCORE_CODECEPTION_VERSION: "2.0" + PIMCORE_CODECEPTION_VERSION: "3.0" APP_ENV: test PIMCORE_TEST_DB_DSN: "mysql://root:root@127.0.0.1:3306/dachcom_bundle_test" @@ -37,12 +37,12 @@ jobs: options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 strategy: matrix: - php: [ 8.1 ] - symfony: [ ^5.4 ] - pimcore: [ ~10.6.0 ] + php: [ 8.2 ] + symfony: [ ^6.2 ] + pimcore: [ ~11.0.0 ] include: - - pimcore: ~10.6.0 - template_tag: v10.2.5 + - pimcore: ~11.0.0 + template_tag: v11.0.0 steps: - uses: actions/checkout@v2 with: diff --git a/.gitignore b/.gitignore index 0139f99d..d4770f35 100644 --- a/.gitignore +++ b/.gitignore @@ -45,11 +45,11 @@ Vagrantfile php-cgi.core .sass-cache -# codeception (only stage *.dist.yml config files) -/codeception.yml -/tests/codeception.yml -/tests/*.suite.yml +# codeception (only stage *.dist.yaml config files) +/codeception.yaml +/tests/codeception.yaml +/tests/*.suite.yaml /tests/_output/* /tests/_data/* !/tests/_data/.gitkeep -/tests/_support/_generated/* \ No newline at end of file +/tests/Support/_generated/* \ No newline at end of file diff --git a/README.md b/README.md index 5c82d653..809e16fa 100644 --- a/README.md +++ b/README.md @@ -13,22 +13,29 @@ The Toolbox is a Kickstarter for your every day project. It provides some import ### Release Plan -| Release | Supported Pimcore Versions | Supported Symfony Versions | Release Date | Maintained | Branch | -|---------|-----------------------------------|----------------------------|--------------|----------------|------------| -| **4.x** | `10.5`, `10.6` | `5.4` | 01.10.2021 | Feature Branch | master | -| **3.x** | `6.0` - `6.9` | `3.4`, `^4.4` | 16.07.2019 | Unsupported | 3.x | -| **2.8** | `5.4`, `5.5`, `5.6`, `5.7`, `5.8` | `3.4` | 30.06.2019 | Unsupported | 2.8 | -| **1.8** | `4.0` | -- | 28.04.2017 | Unsupported | pimcore4 | +| Release | Supported Pimcore Versions | Supported Symfony Versions | Release Date | Maintained | Branch | +|---------|-----------------------------------|----------------------------|--------------|----------------|----------| +| **5.x** | `11.0` | `6.2` | -- | Feature Branch | master | +| **4.x** | `10.5`, `10.6` | `5.4` | 01.10.2021 | Bugfixes | 4.x | +| **3.x** | `6.0` - `6.9` | `3.4`, `^4.4` | 16.07.2019 | Unsupported | 3.x | +| **2.8** | `5.4`, `5.5`, `5.6`, `5.7`, `5.8` | `3.4` | 30.06.2019 | Unsupported | 2.8 | +| **1.8** | `4.0` | -- | 28.04.2017 | Unsupported | pimcore4 | ### Installation ```json "require" : { - "dachcom-digital/toolbox" : "~4.1.0" + "dachcom-digital/toolbox" : "~5.0.0" } ``` -- Execute: `$ bin/console pimcore:bundle:enable ToolboxBundle` +Add Bundle to `bundles.php`: +```php +return [ + ToolboxBundle\ToolboxBundle::class => ['all' => true], +]; +``` + - Execute: `$ bin/console pimcore:bundle:install ToolboxBundle` ## Upgrading @@ -83,7 +90,7 @@ The Toolbox provides a lot of [ready-to-use Bricks](docs/11_ElementsOverview.md) - [Code Style](docs/1_CodeStyle.md) - [Helper Commands](docs/2_Commands.md) - [Toolbox Elements Overview](docs/11_ElementsOverview.md) -- [CK-Editor Configuration](docs/13_CkEditor.md) +- [Wysiwyg Configuration](docs/13_Wysiwyg_Editor.md) - [Image Thumbnails Strategy](docs/14_ImageThumbnails.md) - [Configuration Context](docs/15_Context.md) - [Editable Store Provider](docs/16_EditableStoreProvider.md) @@ -94,6 +101,7 @@ The Toolbox provides a lot of [ready-to-use Bricks](docs/11_ElementsOverview.md) - [Column Adjuster](docs/60_ColumnAdjuster.md) - [Configuration Flags](docs/70_ConfigurationFlags.md) - [Javascript Plugins](docs/80_Javascript.md) +- [Headless Mode](docs/90_Headless.md) ## Pimcore Fixes / Overrides - Fix the pimcore iframe [maskFrames](src/ToolboxBundle/Resources/public/js/document/edit.js) bug (in some cases the iframe overlay field does not apply to the right position) diff --git a/UPGRADE.md b/UPGRADE.md index 020dd9f7..c40c6cb6 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,77 +1,78 @@ # Upgrade Notes -## Version 4.1.0 -- [FEATURE] PIMCORE 10.5 support only -- [IMPROVEMENT] Compatibility with Members 4.1 added -- [IMPROVEMENT] Remove unused js classes -- [BUGFIX] [VHS Element] Use right element context in video type selector +## Migrating from Version 4.x to Version 5.0.0 -## Version 4.0.10 -- [BUGFIX] fix case sensitivity for accordion in bootstrap3 theme `Resources/views/toolbox/bootstrap3/accordion/partial/Accordion => Resources/views/toolbox/bootstrap3/accordion/partial/accordion` - -## Version 4.0.9 -- [BUGFIX] Missing area layout for bricks without configuration [#182](https://github.com/dachcom-digital/pimcore-toolbox/issues/182) -- [IMPROVEMENT] Move permission command listener to maintenance task [#181](https://github.com/dachcom-digital/pimcore-toolbox/issues/181) - -## Version 4.0.8 -- [BUGFIX] Fix wrong query identifier for MembersBundle connector [@scrummer](https://github.com/dachcom-digital/pimcore-toolbox/pull/179) - -## Version 4.0.7 -- [BUGFIX] prevent type error in `DownloadExtension:getOptimizedFileSize` - -## Version 4.0.6 -- [BUGFIX] fix id for Accordion and Gallery: save class names - -## Version 4.0.5 -- [BUGFIX] fix type error in `Vhs:setDataFromResource` - -## Version 4.0.4 -- [BUGFIX] fix file size calculation -- [BUGFIX] add label for column adjuster [@blankse](https://github.com/dachcom-digital/pimcore-toolbox/pull/170) -- [BUGFIX] fix image thumbnail class [@NaincyKumariKnoldus](https://github.com/dachcom-digital/pimcore-toolbox/pull/168) - -## Version 4.0.3 -- [BUGFIX] return correct default value if editable is null +### New Features +- [Headless Mode](./docs/90_Headless.md) -## Version 4.0.2 -- [FEATURE] PIMCORE 10.2 Support +### Global Changes +- All folders and sub-folders in views are lowercase/underscore now (areas/accordion/accordion_tab, areas/google_map, areas/iframe, areas/link_list, areas/parallax_container, areas/parallax_container_section, areas/parallax_container_section, areas/slide_columns) +- All snippet views are underscore now (snippet_layout.html.twig, snippet/teaser_default, snippet/layout/teaser_layout) - check your views for includes! +- All views are lowercase/underscore now (areas/video/type_*, areas/google_map/info_window, parallax_container/partial/*, parallax_container/wrapper/container_wrapper) +- `dynamiclink` feature has finally been removed! If you're still using it, stay on v4 and [migrate first](https://github.com/dachcom-digital/pimcore-toolbox/blob/3.x/docs/70_ConfigurationFlags.md#-use_dynamic_links-flag) -## Version 4.0.1 -- [BUGFIX] Fetching edit mode state from editable instead of checking area param - -## Migrating from Version 3.x to Version 4.0.0 -⚠️ If you're still on version `2.x`, you need to install `3.x` first, then [migrate](https://github.com/dachcom-digital/pimcore-toolbox/blob/3.x/UPGRADE.md) to `3.3`. After that, you're able to update to `^4.0`. +### WYSIWYG Config Changes +- CK Editor support has been removed from PIMCORE. Toolbox currently only supports the new TinyMCE Editor. Read more about it [here](./docs/13_Wysiwyg_Editor.md) + - Config node `toolbox.ckeditor` changed to `toolbox.wysiwyg_editor` + - Config node `global_style_sets` has been removed (will be set via `wysiwyg_editor.config`) + - Twig Helper `toolbox_get_wysiwyg_config_path()` has been removed (will be added globally via edit mode js file injection) -### Global Changes -- All deprecations have been removed: - - Legacy Service Alias `toolbox.area.brick.base_brick` has been removed - - Config Node `toolbar.x`, `toolbar.y`, `toolbar.xAlign`, `toolbar.yAlign`, `toolbar.title` has been removed - - Config Node `area_block_configuration.controlsAlign`, `area_block_configuration.controlsTrigger` has added - - Config Node `disallowed_subareas`: `areas_appearance` - - Config Node `disallowed_content_snippet_areas`: `snippet_areas_appearance` - - Config Node `ToolboxBundle\Calculator\*`: `column_calculator|slide_calculator` - - ⚠️ Element `pimcore_dynamiclink` has been removed: If you're still using this element in your project, you need to [migrate](https://github.com/dachcom-digital/pimcore-toolbox/blob/3.x/docs/70_ConfigurationFlags.md#-use_dynamic_links-flag) to pimcore_link first (via TB 3.x)! -- All Folders in `views` are lowercase/dashed now (`areas/google-map`, `areas/iframe`, `areas/link-list`, `areas/paralax-container`, `areas/slide-columns`, `toolbox/bootstrap4`, ...) +### Areas Restriction Changes +- `areas_appearance` has been renamed to `areablock_restriction`, `snippet_areas_appearance` has been renamed to `snippet_areablock_restriction`. ### Editable Changes -- Instead of `pimcore.area.brick` you need to use the `toolbox.area.brick` tag to register your brick. Also remove `setAreaBrickType` call from your service definition -- Always use `$info->setParam(key, value)` instead of `$info->setParams()`, otherwise you'll overwrite given parameters from the toolbox abstract brick -- Remove `{{ elementConfigBar|raw }}` in your templates -- Conditional Logic feature for editable has been removed -- Reload property in node `config.reload` has been removed. Use `config_parameter.reload_on_close: true` instead -- Custom view has been removed, TB is now using the pimcore defaults dialog box configuration - - Config Node `col_class` (In`[BRICKNAME].config_elements.[ELEMENT]` has been removed - -### Type Changes -- `StoreProviderInterface::getValues():array` needs to return an array (return type declaration added) -- `ContextResolverInterface::getCurrentContextIdentifier():?string` needs to return null|string (return type declaration added) +- `custom_areas` has been removed. Please add your custom areas to the default `areas` node. + +### Editables States +Pimcore removed the extension manager, so it is not possible to enabled/disable them via pimcore anymore. +Therefor we removed all toolbox core editables by default, you need to enable every single one of them: + +```yaml +toolbox: + enabled_core_areas: + - accordion + - anchor + - columns + - container + - content + - download + - gallery + - googleMap + - headline + - iFrame + - image + - linkList + - parallaxContainer + - parallaxContainerSection + - separator + - slideColumns + - snippet + - spacer + - teaser + - video +``` + +You need to change the global state via configuration now: + +```yaml +toolbox: + areas: + accordion: + enabled: false +``` + +If you want to disable any area from third party bundles (for example the members brick) just use their brick id to disable them: +```yaml + areas: + members_login: + enabled: false +``` + +### Theme +The default theme section will be loaded, **only** if **no** `toolbox.theme.layout` has been defined. +If you're using the `Bootstrap4` layout, and it's explicitly configured in your project, you need to adopt the config from toolbox core `config/theme/bootstrap4_theme.yaml` +You also must configure `toolbox.calculators.*` explicitly, if you're using custom layout frameworks. -### New Features -- ⚠️ [Editable Permissions](https://github.com/dachcom-digital/pimcore-toolbox/issues/161) have been added. Non-Admin Users will **NOT** be able to add editables until you enabled specific permissions for them! -- Google Maps Improved: - - Only call API if address has changed - - Better Error Reporting: Display some notes (only in editmode), if something went wrong during API call -- Simple Area Brick: Create a simple editable without creating any php classes. Read more about it [here](./docs/10_CustomBricks.md#simple-brick)) *** -Toolbox 3.x Upgrade Notes: https://github.com/dachcom-digital/pimcore-toolbox/blob/3.x/UPGRADE.md +Toolbox 4.x Upgrade Notes: https://github.com/dachcom-digital/pimcore-toolbox/blob/4.x/UPGRADE.md diff --git a/codeception.dist.yml b/codeception.dist.yml index 882426c9..296aad20 100644 --- a/codeception.dist.yml +++ b/codeception.dist.yml @@ -1,14 +1,15 @@ namespace: DachcomBundle\Test +support_namespace: Support actor: Tester paths: tests: tests - output: tests/_output - data: tests/_data - support: tests/_support envs: tests/_envs + output: tests/_output log: tests/_output/var/logs + data: tests/_data + support: tests/Support +bootstrap: _bootstrap.php settings: - bootstrap: _bootstrap.php memory_limit: -1 colors: true params: diff --git a/composer.json b/composer.json index 4b71f3e0..7108b29e 100755 --- a/composer.json +++ b/composer.json @@ -31,12 +31,12 @@ } }, "require": { - "pimcore/pimcore": "^10.5" + "pimcore/pimcore": "^11.0" }, "require-dev": { - "codeception/codeception": "^4.1", - "codeception/module-webdriver": "^1.4", - "codeception/module-symfony": "^1.6", + "codeception/codeception": "^5.0", + "codeception/module-symfony": "^3.1", + "codeception/module-webdriver": "^4.0", "phpstan/phpstan": "^1.0", "phpstan/phpstan-symfony": "^1.0", "symplify/easy-coding-standard": "^9.0" diff --git a/docs/0_Usage.md b/docs/0_Usage.md index be34938f..c916808b 100644 --- a/docs/0_Usage.md +++ b/docs/0_Usage.md @@ -3,10 +3,38 @@ Some important advices if you're going to use this bundle in your project. ## Area Brick -![bildschirmfoto 2017-08-30 um 08 43 46](https://user-images.githubusercontent.com/700119/29858787-6198a2c4-8d5f-11e7-8376-8c3acd9d267f.png) +![areabrick](https://user-images.githubusercontent.com/700119/29858787-6198a2c4-8d5f-11e7-8376-8c3acd9d267f.png) The Toolbox Bundle will help you to display area bricks with some nice additions. +### Enable Bricks +Every preconfigured brick needs to be enabled: + +```yaml +toolbox: + enabled_core_areas: + - accordion + - anchor + - columns + - container + - content + - download + - gallery + - googleMap + - headline + - iFrame + - image + - linkList + - parallaxContainer + - parallaxContainerSection + - separator + - slideColumns + - snippet + - spacer + - teaser + - video +``` + #### Area Brick Configuration **Important!** Make sure that every `pimcore_areablock` in your project implements the `toolbox_areablock_config()` element. If you miss this, the toolbar will get messy. @@ -25,6 +53,7 @@ If you miss this, the toolbar will get messy. Of course, you're able to extend/modify the toolbar configuration: ```yaml + area_block_configuration: toolbar: width: 200 @@ -43,14 +72,31 @@ area_block_configuration: ``` ## Allow/Disallow Elements -#### In snippets +#### Globally +You're able to disable editables completely: + +```yaml +toolbox: + areas: + accordion: + enabled: false +``` + +If you want to disable any area from third party bundles (for example the members brick) just use their brick id to disable them: +```yaml + areas: + members_login: + enabled: false +``` + +#### In Snippets -Use the `snippet_areas_appearance` config node to disable bricks in specific snippets. +Use the `snippet_areablock_restriction` config node to disable bricks in specific snippets. ```yaml # define which elements should not appear in snippet documents toolbox: - snippet_areas_appearance: + snippet_areablock_restriction: snippet_c: disallowed: - parallaxContainer @@ -69,12 +115,12 @@ toolbox: #### In Area-Blocks -Use the `areas_appearance` config node to disable bricks in specific areas. +Use the `areablock_restriction` config node to disable bricks in specific areas. **Example** ```yaml toolbox: - areas_appearance: + areablock_restriction: container: allowed: # if "allowed" is configured the "disallowed" node will be ignored - container diff --git a/docs/10_CustomBricks.md b/docs/10_CustomBricks.md index 84b7c618..24c8d9f0 100644 --- a/docs/10_CustomBricks.md +++ b/docs/10_CustomBricks.md @@ -12,7 +12,7 @@ If you just want to create a simple brick, create a [simple brick](./10_CustomBr There are three simple steps to create a custom brick: -1. Add this configuration to `/config/packages/toolbox.yml`: +1. Add this configuration to `/config/packages/toolbox.yaml`: ```yaml services: @@ -22,7 +22,7 @@ services: - { name: toolbox.area.brick, id: my_brick } toolbox: - custom_areas: + areas: # that's the name of your brick. my_brick: config_elements: @@ -47,9 +47,7 @@ toolbox: namespace App\Document\Areabrick\MyBrick; -use Pimcore\Model\Document\Editable\Area\Info; -use Symfony\Component\HttpFoundation\Response; -use ToolboxBundle\Document\Areabrick\AbstractAreabrick; +use Pimcore\Model\Document\Editable\Area\Info;use Symfony\Component\HttpFoundation\Response;use ToolboxBundle\Document\Areabrick\AbstractAreabrick; class MyBrick extends AbstractAreabrick { @@ -109,7 +107,7 @@ That's it. If you want to refresh the permission table you also need to execute Two steps to create a simple brick: -1. Add this configuration to `/config/packages/toolbox.yml`: +1. Add this configuration to `/config/packages/toolbox.yaml`: ```yaml services: @@ -135,7 +133,7 @@ services: } toolbox: - custom_areas: + areas: # that's the name of your simple brick. # configuration behaves the same as a default brick my_simple_brick: @@ -187,7 +185,7 @@ To use tabs in your config dialog, you have to define them via the tab config no ```yaml toolbox: - custom_areas: + areas: dummy_brick: tabs: # <-- define tabs here first! tab1: 'Tab 1' diff --git a/docs/11_ElementsOverview.md b/docs/11_ElementsOverview.md index 8d925798..e289c77a 100644 --- a/docs/11_ElementsOverview.md +++ b/docs/11_ElementsOverview.md @@ -102,19 +102,19 @@ Create a container element. Useful if you're using a full width layout. ### Available Options -| Name | Type | Description | Default Value | Frontend -|------|------|-----------------------------|---------------|-------------------------------| -| `full_width_container` | checkbox | Adds the `container-fluid` class | false | `pimcore_checkbox('full_width_container')` | -| `additional_classes` | select | Add custom classes | - | see [section additional classes](#additional-classes) | +| Name | Type | Description | Default Value | Frontend | +|------------------------|----------|----------------------------------|---------------|-------------------------------------------------------| +| `full_width_container` | checkbox | Adds the `container-fluid` class | false | `pimcore_checkbox('full_width_container')` | +| `additional_classes` | select | Add custom classes | - | see [section additional classes](#additional-classes) | ## Content Create a wysiwyg editor. ### Available Options -| Name | Type | Description | Default Value | Frontend -|------|------|-----------------------------|---------------|-------------------------------| -| `additional_classes` | select | Add custom classes | - | see [section additional classes](#additional-classes) | +| Name | Type | Description | Default Value | Frontend | +|----------------------|--------|--------------------|---------------|-------------------------------------------------------| +| `additional_classes` | select | Add custom classes | - | see [section additional classes](#additional-classes) | ## Download @@ -241,13 +241,13 @@ Now you can include the script tag in your footer: ### Configuration Parameter -| Name | Type | Description | Default Value | -|------|------|-------------|---------------| -| `map_options` | array | Map Zoom | [] | -| `map_style_url` | string | Define a custom map style (path to json) | false | -| `marker_icon` | string | Define a custom marker_icon (path to icon) | false | -| `map_api_key` | string | Set a custom map api key. To extend the daily request to 2.500 per day. This key is used by frontend-api-requests | `'%toolbox.google_maps.browser_api_key%'` | -| `simple_api_key` | string | Set a custom simple api key. To extend the daily request to 2.500 per day. This key is used by backend-api-requests | `'%toolbox.google_maps.simple_api_key%'` | +| Name | Type | Description | Default Value | +|------------------|--------|---------------------------------------------------------------------------------------------------------------------|-------------------------------------------| +| `map_options` | array | Map Zoom | [] | +| `map_style_url` | string | Define a custom map style (path to json) | false | +| `marker_icon` | string | Define a custom marker_icon (path to icon) | false | +| `map_api_key` | string | Set a custom map api key. To extend the daily request to 2.500 per day. This key is used by frontend-api-requests | `'%toolbox.google_maps.browser_api_key%'` | +| `simple_api_key` | string | Set a custom simple api key. To extend the daily request to 2.500 per day. This key is used by backend-api-requests | `'%toolbox.google_maps.simple_api_key%'` | **Example** ```yaml @@ -269,7 +269,7 @@ toolbox: There is also a jquery plugin for the google maps element. Read more about it [here](80_Javascript.md) ### Route Link Renderer -There is a macro in `views/Macro/mapLink.html.twig` (used in `views/[THEME NAME]/google-map/info-window.html.twig`) which will render the map route link: +There is a macro in `views/Macro/mapLink.html.twig` (used in `views/[THEME NAME]/google_map/info-window.html.twig`) which will render the map route link: ```twig {# default #} @@ -324,11 +324,11 @@ Create an image field. ### Available Options -| Name | Type | Description | Default Value | Frontend -|------|------|-----------------------------|---------------|-------------------------------| -| `use_light_box` | checkbox | Add a `light-box` class and a wrapping link | false | `pimcore_checkbox('use_light_box')` | -| `show_caption` | checkbox | Render image caption | false | `pimcore_checkbox('show_caption')` | -| `additional_classes` | select | Add custom classes | - | see [section additional classes](#additional-classes) | +| Name | Type | Description | Default Value | Frontend | +|----------------------|----------|---------------------------------------------|---------------|-------------------------------------------------------| +| `use_light_box` | checkbox | Add a `light-box` class and a wrapping link | false | `pimcore_checkbox('use_light_box')` | +| `show_caption` | checkbox | Render image caption | false | `pimcore_checkbox('show_caption')` | +| `additional_classes` | select | Add custom classes | - | see [section additional classes](#additional-classes) | ## Link List @@ -336,9 +336,9 @@ Create a link list (via pimcore block element). ### Available Options -| Name | Type | Description | Default Value | Frontend -|------|------|-----------------------------|---------------|-------------------------------| -| `additional_classes` | select | Add custom classes | - | see [section additional classes](#additional-classes) | +| Name | Type | Description | Default Value | Frontend | +|----------------------|--------|--------------------|---------------|-------------------------------------------------------| +| `additional_classes` | select | Add custom classes | - | see [section additional classes](#additional-classes) | ## Parallax Container Build a Parallax Container. @@ -464,12 +464,12 @@ Create teaser elements. ### Available Options -| Name | Type | Description | Default Value | Frontend -|------|------|-----------------------------|---------------|-------------------------------| -| `type` | select | Define Teaser Type: direct or as snippet | direct | `pimcore_select('type')`. Read more about below in "Teaser Type" Section. | -| `layout` | select | Define Teaser Layout | default | `pimcore_select('layout')` | -| `use_light_box` | checkbox | Add a `light-box` class and a wrapping link for teaser image | false | `pimcore_checkbox('use_light_box')` | -| `additional_classes` | select | Add custom classes | - | see [section additional classes](#additional-classes) | +| Name | Type | Description | Default Value | Frontend | +|----------------------|----------|--------------------------------------------------------------|---------------|---------------------------------------------------------------------------| +| `type` | select | Define Teaser Type: direct or as snippet | direct | `pimcore_select('type')`. Read more about below in "Teaser Type" Section. | +| `layout` | select | Define Teaser Layout | default | `pimcore_select('layout')` | +| `use_light_box` | checkbox | Add a `light-box` class and a wrapping link for teaser image | false | `pimcore_checkbox('use_light_box')` | +| `additional_classes` | select | Add custom classes | - | see [section additional classes](#additional-classes) | ### Teaser Types Like explained above, it's possible to switch between two Types of Teasers: @@ -530,7 +530,7 @@ In short, you're able to use all the [pimcore editables](https://www.pimcore.org **Example** ```yaml toolbox: - custom_areas: + areas: container: config_elements: awesome_fields: diff --git a/docs/13_CkEditor.md b/docs/13_CkEditor.md deleted file mode 100644 index 1699ce93..00000000 --- a/docs/13_CkEditor.md +++ /dev/null @@ -1,120 +0,0 @@ -# CK-Editor Configuration - -The Toolbox Bundle allows you to override and specifiy the ckeditor configuration. -There are several reasons for that: - -- Keep the editor simple, remove unwanted dangerous elements from the ckeditor -- Define custom styles via configuration -- Use the same CK-Editor Layout in every wysiwyg element (Document, Emails, Objects) - -## CK Editor Toolbar -The Toolbox Bundle already removes some (mostly dangerous) elements. Feel free to modify them according to your needs. -You may use the [online toolbar configurator](https://ckeditor.com/latest/samples/toolbarconfigurator/index.html#basic) to do that. - -> Info: This is the global configuration for the CK-Editor Toolbar. -> If you need to provide a different configuration in objects or areas, use the object/area configuration (see below) - -> Info: It's possible to modify all the [CK-Editor Configuration](https://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-stylesSet) - -### Overriding Configuration -The config node is a variableNode, so the values **don't get merged** with the default ones. -If you're going to define the `toolbox -> ckeditor -> config` node, you must provide the complete configuration. - -**Example** -```yaml -toolbox: - ckeditor: - # with that node all the default values from toolbox configuration are overwritten now! - config: - uiColor: yellow # change the ui color of the editor for example - toolbar: - - name: basicstyles - items: - - Bold - - "-" - - RemoveFormat - - name: clipboard - items: - - Cut - - Copy - - Redo - - name: editing - items: - - Replace - - "-" - - SelectAll - - "/" -``` - -### Area CK-Editor Configuration -If you only need to modify the toolbar configuration for document areas, add this to your configuration: - -**Example** -```yaml -toolbox: - ckeditor: - area_editor: - config: - # this will merge the iframe element into the global toolbar configuration, if set - toolbar: - - name: insert - items: - - Iframe -``` - -### Object CK-Editor Configuration -If you only need to modify the toolbar configuration for objects, add this to your configuration: - -> **Note!** The object configuration does not respect different toolbox context environments at the moment. -> Objects are not restricted to any sites by nature which makes any context-binding quite impossible. - -**Example** -```yaml -toolbox: - ckeditor: - object_editor: - config: - # this will merge the iframe element into the global toolbar configuration, if set - toolbar: - - name: insert - items: - - Iframe - stylesSet: specialStyleSetForObjects # see global style sets configuration below - uiColor: green - -``` - -## CK Editor Global Style Sets -Define your custom styles here. - -**Example** -```yaml -toolbox: - ckeditor: - global_style_sets: - default: - - - name: 'Dark Grey' - element: [h1,h2,h3,h4,h5] - attributes: - class: 'grey-1' - - - name: 'Lead' - element: p - attributes: - class: 'lead' - specialStyleSetForObjects: - name: 'Secret Color' - element: p - attributes: - class: 'secret-color' -``` - -## Area CK-Editor Plugins -Toolbox provides some CK-Editor Plugins: - -### Google Opt Out -![ck-editor-google-opt-out](https://user-images.githubusercontent.com/700119/37820009-9dd6a418-2e7f-11e8-94b4-99c7a001a3a9.png) - -Add a link to allow user to disable google analytics tracking. -There is also a [frontend Javascript Plugin](./80_Javascript.md). diff --git a/docs/13_Wysiwyg_Editor.md b/docs/13_Wysiwyg_Editor.md new file mode 100644 index 00000000..2efe9277 --- /dev/null +++ b/docs/13_Wysiwyg_Editor.md @@ -0,0 +1,83 @@ +# CK-Editor Configuration + +The Toolbox Bundle allows you to override and specify the wysiwyg configuration. +There are several reasons for that: + +- Keep the editor simple, remove unwanted dangerous elements from the wysiwyg +- Define custom styles via configuration +- Use the same editor layout in every wysiwyg element (Document, Emails, Objects) + +> Currently, only TinyMce Editor is supported! + + +## TinyMce Toolbar +The Toolbox Bundle already removes some (mostly dangerous) elements. Feel free to modify them according to your needs. +Checkout the [available toolbar buttons](https://www.tiny.cloud/docs/advanced/available-toolbar-buttons/) to do that. + +> Info: This is the global configuration for the TinyMCE-Editor Toolbar. +> If you need to provide a different configuration in objects or areas, use the object/area configuration (see below) + +### Overriding Configuration + +**Example** +```yaml +toolbox: + wysiwyg_editor: + config: + block_formats: 'Paragraph=p; Header 1=h1; Header 2=h2; Header 3=h3' + style_formats: + - + title : 'Example' + inline : 'span' + classes : 'example' + selector: 'a' + toolbar2: 'blocks | styles' + +``` + +### Area Editor Configuration +If you only need to modify the toolbar configuration for document areas, add this to your configuration: + +**Example** +```yaml +toolbox: + wysiwyg_editor: + area_editor: + config: + # his will change the toolbar2 only for document editables editors + toolbar2: 'blocks' +``` + +### Object Editor Configuration +If you only need to modify the toolbar configuration for objects, add this to your configuration: + +> **Note!** The object configuration does not respect different toolbox context environments at the moment. +> Objects are not restricted to any sites by nature which makes any context-binding quite impossible. + +**Example** +```yaml +toolbox: + wysiwyg_editor: + object_editor: + config: + # this will change the toolbar2 only for object editors + toolbar2: 'blocks' + +``` + +## TinyMce Editor Plugins +Toolbox provides some CK-Editor Plugins: + +### Google Opt Out +![ck-editor-google-opt-out](https://user-images.githubusercontent.com/700119/37820009-9dd6a418-2e7f-11e8-94b4-99c7a001a3a9.png) + +Add a link to allow user to disable google analytics tracking. +There is also a [frontend Javascript Plugin](./80_Javascript.md). + +#### Enable Button +```yaml +toolbox: + wysiwyg_editor: + config: + toolbar2: 'tb_goo_link_button' +``` diff --git a/docs/14_ImageThumbnails.md b/docs/14_ImageThumbnails.md index 4b8c0fdd..4fb95d73 100644 --- a/docs/14_ImageThumbnails.md +++ b/docs/14_ImageThumbnails.md @@ -1,7 +1,7 @@ # Image Thumbnails To stay organized, the ToolboxBundle provides a dedicated configuration and a simple helper for image thumbnails. -Every required thumbnail size is defined in the [toolbox configuration](https://github.com/dachcom-digital/pimcore-toolbox/blob/master/src/ToolboxBundle/Resources/config/pimcore/image_thumbnails.yml). +Every required thumbnail size is defined in the [toolbox configuration](https://github.com/dachcom-digital/pimcore-toolbox/blob/master/src/ToolboxBundle/Resources/config/pimcore/image_thumbnails.yaml). So it's easy for you to simplify or change the [Image Thumbnail](https://www.pimcore.org/docs/5.0.0/Assets/Working_with_Thumbnails/Image_Thumbnails.html) reference. Although this is just an optional feature, it makes sense to use the view helper in your project and custom bricks. diff --git a/docs/15_Context.md b/docs/15_Context.md index a2c0ba3a..818198b5 100644 --- a/docs/15_Context.md +++ b/docs/15_Context.md @@ -11,11 +11,11 @@ If your client opens the document in the backend in a specific site tree for exa ## Context Configuration -| Name | Type | Description -|------|------|------------| -| `merge_with_root` | bool | Use the main toolbox configuration as base configuration and reconfigure them in the new context. **Note**: If you disable this note, you need to provide every single configuration by your own. | -| `enabled_areas` | array | Enable specific Areas | -| `disabled_areas` | array | Disable specific Areas. **Note:** If you have configured `enabled_areas` this option will be ignored. | +| Name | Type | Description | +|-------------------|-------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `merge_with_root` | bool | Use the main toolbox configuration as base configuration and reconfigure them in the new context. **Note**: If you disable this note, you need to provide every single configuration by your own. | +| `enabled_areas` | array | Enable specific Areas | +| `disabled_areas` | array | Disable specific Areas. **Note:** If you have configured `enabled_areas` this option will be ignored. | > **Note**: If you have enabled `merge_with_root` you cannot use a different theme in sub context since there would be a layout mismatch. @@ -79,8 +79,8 @@ toolbox: namespace App\Services\ToolboxBundle; +use Pimcore\Http\RequestHelper; use Pimcore\Model\Document; -use Symfony\Component\HttpFoundation\RequestStack; use ToolboxBundle\Resolver\ContextResolverInterface; use Pimcore\Http\Request\Resolver\DocumentResolver; use Pimcore\Http\Request\Resolver\EditmodeResolver; @@ -90,51 +90,42 @@ use Pimcore\Tool; class ToolboxContextResolver implements ContextResolverInterface { - protected SiteResolver $siteResolver; - protected RequestStack $requestStack; - private EditmodeResolver $editModeResolver; - private DocumentResolver $documentResolver; - public function __construct( - RequestStack $requestStack, - SiteResolver $siteResolver, - EditmodeResolver $editModeResolver, - DocumentResolver $documentResolver + protected SiteResolver $siteResolver, + protected RequestHelper $requestHelper, + protected EditmodeResolver $editModeResolver, + protected DocumentResolver $documentResolver ) { - $this->requestStack = $requestStack; - $this->siteResolver = $siteResolver; - $this->editModeResolver = $editModeResolver; - $this->documentResolver = $documentResolver; } public function getCurrentContextIdentifier(): ?string { - $request = $this->requestStack->getMainRequest(); + if (!$this->requestHelper->hasMainRequest()) { + return null; + } - $site = null; + $request = $this->requestHelper->getMainRequest(); - //if request is coming from a ckeditor configuration request (/admin/*.js) + //if request is coming from a wysiwyg configuration request (/admin/*.js) if ($request->query->has('tb_document_request_id')) { + try { $currentDocument = Document::getById($request->query->get('tb_document_request_id')); } catch (\Exception $e) { $currentDocument = null; } - if ($currentDocument instanceof Document) { - $site = Tool\Frontend::getSiteForDocument($currentDocument); - } + $site = $currentDocument instanceof Document ? Tool\Frontend::getSiteForDocument($currentDocument) : null; + + } elseif ( + $this->editModeResolver->isEditmode($request) || + $this->requestHelper->isFrontendRequestByAdmin($request) + ) { + // in backend, we don't have any site request, we need to fetch it via document + $currentDocument = $this->documentResolver->getDocument(); + $site = Tool\Frontend::getSiteForDocument($currentDocument); } else { - //if request is not in editmode we can determinate site by site resolver - if (!$this->editModeResolver->isEditmode($request)) { - if ($this->siteResolver->isSiteRequest($request)) { - $site = $this->siteResolver->getSite($request); - } - // in backend we don't have any site request, we need to fetch it via document - } else { - $currentDocument = $this->documentResolver->getDocument(); - $site = Tool\Frontend::getSiteForDocument($currentDocument); - } + $site = $this->siteResolver->isSiteRequest($request) ? $this->siteResolver->getSite($request) : null; } if (!$site instanceof Site) { diff --git a/docs/16_EditableStoreProvider.md b/docs/16_EditableStoreProvider.md index 4006fb35..80de6796 100644 --- a/docs/16_EditableStoreProvider.md +++ b/docs/16_EditableStoreProvider.md @@ -36,7 +36,7 @@ toolbox: Now we need to register our new service: ```yml -# app/config.yml +# app/config.yaml services: App\Toolbox\MyStoreProvider: tags: diff --git a/docs/1_CodeStyle.md b/docs/1_CodeStyle.md index 53605474..cd611867 100644 --- a/docs/1_CodeStyle.md +++ b/docs/1_CodeStyle.md @@ -11,7 +11,7 @@ All Configuration Elements are written in underscore: ```yaml toolbox: - custom_areas: + areas: anchor: config_elements: anchor_name: # underscore: in view, you'll call it with pimcore_input('anchor_name'); diff --git a/docs/20_DynamicLinkElement.md b/docs/20_DynamicLinkElement.md deleted file mode 100644 index 23ac4fdd..00000000 --- a/docs/20_DynamicLinkElement.md +++ /dev/null @@ -1,70 +0,0 @@ -# Dynamic Link Element -The dynamic link extends the pimcore link element. It allows you to drag objects into the url field. -Of course it's impossible to generate a valid url from objects, so you need to do some further work. - -> **WARNING!!** This Service has been deprecated. -> Please use the default Pimcore Link Tag which also allows object paths by using a [linkGenerator service](https://pimcore.com/docs/5.x/Development_Documentation/Objects/Object_Classes/Class_Settings/Link_Generator.html). -> If you want to migrate existing dynamic links read more about it [here](./70_ConfigurationFlags.md#-use_dynamic_links-flag) . - -### Usage - -```twig -{{ pimcore_dynamiclink('link', {'class' : 'btn btn-default teaser-link'}) }} -``` -### Configuration - -#### Service -```yaml -# config/services.yaml -services: - - _defaults: - autowire: true - public: false - - App\EventListener\ObjectUrlListener: - tags: - - { name: kernel.event_listener, event: toolbox.dynamiclink.object.url, method: checkUrl } -``` - -#### Mapping - -This mapper will transformed your dragged object path into a valid frontend path. -You also need to setup a static route (in this case the `news_detail` route). - -```php -generator = $generator; - } - - public function checkUrl(GenericEvent $e) - { - if ( $e->getArgument('className') === 'news') { - $obj = DataObject\News::getByPath($e->getArgument('path')); - if ($obj instanceof DataObject\News) { - - $url = $this->generator->generate('news_detail', [ - 'text' => $obj->getTitle(), - 'id' => $obj->getId(), - 'newsId' => $obj->getId() - ]); - - $e->setArgument('objectFrontendUrl', $url); - } - } - } -} -``` \ No newline at end of file diff --git a/docs/30_ToolboxTheme.md b/docs/30_ToolboxTheme.md index 29c02433..b5d0f792 100644 --- a/docs/30_ToolboxTheme.md +++ b/docs/30_ToolboxTheme.md @@ -5,6 +5,7 @@ The Toolbox Bundle is currently using Bootstrap 4 as default framework. - [Bootstrap 4](./themes/Bootstrap4.md) - [Bootstrap 3](./themes/Bootstrap3.md) - [UIkit3](./themes/UiKit3.md) +- [Headless](./themes/Headless.md) *** @@ -18,7 +19,7 @@ toolbox: theme: grid: ~ # defines the view namespace [LAYOUT_NAME] - layout: 'Bootstrap4' + layout: !php/const ToolboxBundle\Manager\LayoutManagerInterface::TOOLBOX_LAYOUT_BOOTSTRAP4 default_layout: false wrapper: image: @@ -142,7 +143,6 @@ class ColumnCalculator implements ColumnCalculatorInterface public function setConfigManager(ConfigManagerInterface $configManager) { $this->configManager = $configManager; - $this->configManager->setAreaNameSpace(ConfigManager::AREABRICK_NAMESPACE_INTERNAL); return $this; } diff --git a/docs/90_Headless.md b/docs/90_Headless.md new file mode 100644 index 00000000..3c88e87b --- /dev/null +++ b/docs/90_Headless.md @@ -0,0 +1,166 @@ +# Headless +Learn, how to put toolbox into headless mode. + +## Thinks to know +- The Headless layout will super simplify the backend edit mode. No views will be generated there, but only the configuration fields. +- In the frontend layer, the editable output will be a simple array (already nested) +- All toolbox editables except `parallax` and `slidecolumn` are headless ready out of the box +- Since the output is json, you're not able to add or modify data in view. Use the `HEADLESS_EDITABLE_ACTION` event to add more data and use a tagged `toolbox.property.normalizer` to change the json output + +## Headless Aware Editable +If your editable should work within the headless layout, you need to add some more stuff: + +- Add `ToolboxHeadlessAwareBrickInterface` +- Add `headlessAction` method + +Example: + +```php +buildInfoParameters($info); + + return parent::action($info); + } + + public function headlessAction(Info $info, HeadlessResponse $headlessResponse): void + { + $this->buildInfoParameters($info, $headlessResponse); + + parent::headlessAction($info, $headlessResponse); + } + + private function buildInfoParameters(Info $info, ?HeadlessResponse $headlessResponse = null): void + { + $infoParams = $info->getParams(); + + $mySpecialParameter = '[AWESOME]'; + + if ($headlessResponse instanceof HeadlessResponse) { + // will be used in fe output + $headlessResponse->addAdditionalConfigData('mySpecialParameter', $mySpecialParameter); + + return; + } + + // will be used in editmode + $info->setParam('mySpecialParameter', $mySpecialParameter); + } +} +``` + +## Setup + +```yaml + +toolbox: + theme: + layout: !php/const ToolboxBundle\Manager\LayoutManagerInterface::TOOLBOX_LAYOUT_HEADLESS + calculators: + column_calculator: ToolboxBundle\Calculator\Bootstrap4\ColumnCalculator # or your custom headless calculator + slide_calculator: ToolboxBundle\Calculator\Bootstrap4\SlideColumnCalculator # or your custom headless calculator. slide columns aren't supported right now, so it doesn't matter which service you're using +``` + +## Headless Documents +It's possible to create simple headless documents: + +- Only two types are supported: `areablock` and `area` + +```yaml +toolbox: + enabled_core_areas: + - content + - headline + - image + + theme: + layout: !php/const ToolboxBundle\Manager\LayoutManagerInterface::TOOLBOX_LAYOUT_HEADLESS + headless_documents: + index: + areas: + indexHeadline: + type: area + areaType: headline + myBlock: + type: areablock +``` + +Add `ToolboxBundle\Controller\HeadlessController::headlessDocumentAction` as action to your document. + +## Extend existing headless editables +Just register an event listener to `ToolboxBundle::HEADLESS_EDITABLE_ACTION` which will provide you an `HeadlessEditableActionEvent` object +where you're allowed to add additional data to the `HeadlessResponse` object + +## Normalize data +In headless context, you're not able to modify output via view files and in some scenarios you also want to output data differently in a given context. + +Toolbox comes with some pre-configured normalizers: + +### DownloadRelationsNormalizer +This normalizer will transform download relations to meaningful data arrays (like the `toolbox_download_info` twig helper) + +### GalleryRelationsNormalizer +This normalizer will transform gallery relations to thumbnail data arrays + +### ImageEditableNormalizer +This normalizer will transform the inline image editable to a thumbnail data array + +## Custom normalizer +First, you need to add your normalizer: + +```yaml +services: + App\Normalizer\MyNormalizer: + tags: + - { name: toolbox.property.normalizer } +``` + +```php +
-
@@ -57,7 +56,6 @@ toolbox:
-
diff --git a/docs/themes/Bootstrap4.md b/docs/themes/Bootstrap4.md index 87adcfed..c9c080f0 100644 --- a/docs/themes/Bootstrap4.md +++ b/docs/themes/Bootstrap4.md @@ -46,7 +46,6 @@ toolbox:
-
@@ -56,7 +55,6 @@ toolbox:
-
diff --git a/docs/themes/Headless.md b/docs/themes/Headless.md new file mode 100644 index 00000000..05e6dcf2 --- /dev/null +++ b/docs/themes/Headless.md @@ -0,0 +1,2 @@ +# Headless Theme +If you want to put toolbox into headless mode, read more about it [here](../90_Headless.md). \ No newline at end of file diff --git a/docs/themes/UiKit3.md b/docs/themes/UiKit3.md index eef377f5..60f8e2e9 100644 --- a/docs/themes/UiKit3.md +++ b/docs/themes/UiKit3.md @@ -6,7 +6,7 @@ toolbox: theme: - layout: 'UIkit3' + layout: !php/const ToolboxBundle\Manager\LayoutManagerInterface::TOOLBOX_LAYOUT_UIKIT3 calculators: column_calculator: ToolboxBundle\Calculator\UIkit3\ColumnCalculator slide_calculator: ToolboxBundle\Calculator\UIkit3\SlideColumnCalculator diff --git a/src/ToolboxBundle/Builder/AbstractConfigBuilder.php b/src/ToolboxBundle/Builder/AbstractConfigBuilder.php new file mode 100644 index 00000000..688a890d --- /dev/null +++ b/src/ToolboxBundle/Builder/AbstractConfigBuilder.php @@ -0,0 +1,367 @@ + $elementData) { + + // skip inline rendered config elements + if ($isInlineContext === true && array_key_exists('inline_rendered', $elementData) && $elementData['inline_rendered'] === true) { + continue; + } + + $editableNode = $this->parseConfigElement($info, $configElementName, $elementData, $acStoreProcessed, $brickId, $themeOptions); + + //if element need's a store and store is empty: skip field + if ($this->needStore($elementData['type']) && $this->hasValidStore($editableNode['config']) === false) { + continue; + } + + $editableNodes[] = $editableNode; + + $editableNodes = $this->checkColumnAdjusterField($brickId, $elementData['tab'], $themeOptions, $configElementName, $editableNodes); + + if ($elementData['type'] === 'additionalClasses') { + $acStoreProcessed = true; + } + } + + // move additional classes to bottom + $defaultFields = []; + $acFields = []; + + foreach ($editableNodes as $editableNode) { + if ($editableNode['additional_classes_element'] === true) { + $acFields[] = $editableNode; + } else { + $defaultFields[] = $editableNode; + } + } + + $editableNodes = array_merge($defaultFields, $acFields); + + // assign tabs, if configured + if ($allowTabs === true && count($tabs) > 0) { + $tabbedEditableNodes = []; + foreach ($tabs as $tabId => $tabName) { + $tabbedEditableNodes[] = [ + 'type' => 'panel', + 'title' => $this->translator->trans($tabName, [], 'admin'), + 'items' => array_values( + array_filter($editableNodes, static function ($editableNode) use ($tabId) { + return $editableNode['tab'] === $tabId; + }) + ) + ]; + } + + return [ + 'type' => 'tabpanel', + 'items' => $tabbedEditableNodes + ]; + } + + return $editableNodes; + } + + private function parseConfigElement(?Info $info, string $elementName, array $elementData, bool $acStoreProcessed, string $brickId, array $themeOptions): array + { + $editableConfig = $elementData['config']; + $editableType = $elementData['type']; + + //set element config data + $parsedNode = $this->parseElementNode($elementName, $elementData, $acStoreProcessed); + + //set width + if ($this->canHaveDynamicWidth($editableType)) { + $parsedNode['width'] = $parsedNode['width'] ?? '100%'; + } else { + unset($parsedNode['width']); + } + + //set height + if ($this->canHaveDynamicHeight($editableType)) { + $parsedNode['height'] = $parsedNode['height'] ?? 200; + } else { + unset($parsedNode['height']); + } + + // set default + $parsedNode['config']['defaultValue'] = $this->getSelectedValue($info, $parsedNode, $editableConfig['default'] ?? null); + + // check store + if ($this->needStore($editableType) && $this->hasValidStore($editableConfig)) { + $parsedNode['config']['store'] = $this->buildStore($editableType, $editableConfig); + } + + if ($editableType === 'block' && array_key_exists('children', $elementData) && is_array($elementData['children']) && count($elementData['children']) > 0) { + $parsedNode['children'] = $this->parseConfigElements($info, $brickId, $themeOptions, $elementData['children'], []); + } + + return $parsedNode; + } + + private function parseElementNode(string $configElementName, array $elementData, bool $acStoreProcessed): array + { + $elementNode = [ + 'type' => $elementData['type'], + 'name' => $configElementName, + 'tab' => $elementData['tab'], + 'label' => !empty($elementData['title']) ? $elementData['title'] : null, + 'description' => !empty($elementData['description']) ? $elementData['description'] : null, + 'config' => $elementData['config'] ?? [], + 'additional_classes_element' => false, + ]; + + if ($elementData['type'] === 'additionalClasses') { + if ($acStoreProcessed === true) { + throw new \Exception( + sprintf( + 'A element of type "additionalClasses" in element "%s" already has been defined. You can only add one field of type "%s" per area. Use "%s" instead.', + $configElementName, + 'additionalClasses', + 'additionalClassesChained' + ) + ); + } + + $elementNode['type'] = 'select'; + $elementNode['label'] = !empty($elementData['title']) ? $elementData['title'] : 'Additional'; + $elementNode['additional_classes_element'] = true; + $elementNode['name'] = 'add_classes'; + } elseif ($elementData['type'] === 'additionalClassesChained') { + if ($acStoreProcessed === false) { + throw new \Exception( + sprintf( + 'You need to add a element of type "%s" before adding a "%s" element.', + 'additionalClasses', + 'additionalClassesChained' + ) + ); + } + + if (!str_starts_with($configElementName, 'additional_classes_chain_')) { + throw new \Exception( + sprintf( + 'Chained AC element name needs to start with "%s" followed by a numeric. "%s" given.', + 'additional_classes_chain_', + $configElementName + ) + ); + } + + $chainedElementName = explode('_', $configElementName); + $chainedIncrementor = end($chainedElementName); + if (!is_numeric($chainedIncrementor)) { + throw new \Exception('Chained AC element name must end with an numeric. "' . $chainedIncrementor . '" given.'); + } + + $elementNode['type'] = 'select'; + $elementNode['label'] = !empty($elementData['title']) ? $elementData['title'] : 'Additional'; + $elementNode['additional_classes_element'] = true; + $elementNode['name'] = 'add_cclasses_' . $chainedIncrementor; + } + + // translate title + if (!empty($elementNode['label'])) { + $elementNode['label'] = $this->translator->trans($elementNode['label'], [], 'admin'); + } + + // translate description + if (!empty($elementNode['description'])) { + $elementNode['description'] = $this->translator->trans($elementNode['description'], [], 'admin'); + } + + return $elementNode; + } + + private function getSelectedValue(?Info $info, array $config, mixed $defaultConfigValue): mixed + { + if (!$info instanceof Info) { + return $this->castPimcoreEditableValue($config['type'], $defaultConfigValue); + } + + $el = $info->getDocumentElement($config['name'], $config['type']); + + if ($el === null) { + return $this->castPimcoreEditableValue($config['type'], $defaultConfigValue); + } + + // force default (only if it returns false) + // checkboxes may return an empty string and are impossible to track into default mode + if (!empty($defaultConfigValue) && (method_exists($el, 'isEmpty') && $el->isEmpty() === true)) { + $el->setDataFromResource($defaultConfigValue); + } + + $value = $el instanceof Checkbox ? $el->isChecked() : $el->getData(); + + $fallbackAwareValue = !empty($value) ? $value : $defaultConfigValue; + + return $this->castPimcoreEditableValue($config['type'], $fallbackAwareValue); + } + + private function checkColumnAdjusterField(string $brickId, ?string $tab, array $themeOptions, string $configElementName, array $editableNodes): array + { + if ($brickId !== 'columns') { + return $editableNodes; + } + + if ($configElementName !== 'type') { + return $editableNodes; + } + + if (empty($themeOptions['grid']['breakpoints'])) { + return $editableNodes; + } + + $editableNodes[] = [ + 'type' => 'columnadjuster', + 'name' => 'columnadjuster', + 'tab' => $tab, + 'label' => $this->translator->trans('Column adjuster', [], 'admin'), + 'config' => [], + 'additional_classes_element' => false, + ]; + + return $editableNodes; + } + + private function buildStore($type, $config): array + { + $storeValues = []; + if (isset($config['store'])) { + $storeValues = $config['store']; + } elseif (isset($config['store_provider'])) { + $storeProvider = $this->storeProvider->get($config['store_provider']); + $storeValues = $storeProvider->getValues(); + } + + if (count($storeValues) === 0) { + throw new \Exception($type . ' has no valid configured store'); + } + + $store = []; + foreach ($storeValues as $k => $v) { + if (is_array($v)) { + $v = $v['name']; + } + $store[] = [$k, $this->translator->trans($v, [], 'admin')]; + } + + return $store; + } + + private function hasValidStore($parsedConfig): bool + { + if (isset($parsedConfig['store']) && is_array($parsedConfig['store']) && count($parsedConfig['store']) > 0) { + return true; + } + + if (isset($parsedConfig['store_provider']) && $this->storeProvider->has($parsedConfig['store_provider'])) { + return true; + } + + return false; + } + + private function needStore($type): bool + { + return in_array($type, ['select', 'multiselect', 'additionalClasses', 'additionalClassesChained']); + } + + private function canHaveDynamicWidth($type): bool + { + return in_array( + $type, + [ + 'multihref', + 'relations', + 'href', + 'relation', + 'image', + 'input', + 'multiselect', + 'numeric', + 'embed', + 'pdf', + 'renderlet', + 'select', + 'snippet', + 'table', + 'textarea', + 'video', + 'wysiwyg', + 'parallaximage', + 'additionalClasses', + 'additionalClassesChained' + ] + ); + } + + private function canHaveDynamicHeight($type): bool + { + return in_array($type, [ + 'multihref', + 'relations', + 'image', + 'multiselect', + 'embed', + 'pdf', + 'renderlet', + 'snippet', + 'textarea', + 'video', + 'wysiwyg', + 'parallaximage' + ]); + } + + private function castPimcoreEditableValue(string $type, mixed $value): mixed + { + // pimcore numeric editable requires string type + if ($type === 'numeric') { + return $value === null ? null : (string) $value; + } + + if ($type === 'areablock') { + return $value === null ? null : (is_string($value) ? $value : serialize($value)); + } + + return $value; + } +} diff --git a/src/ToolboxBundle/Builder/BrickConfigBuilder.php b/src/ToolboxBundle/Builder/BrickConfigBuilder.php index db758eb7..1dcc58bf 100644 --- a/src/ToolboxBundle/Builder/BrickConfigBuilder.php +++ b/src/ToolboxBundle/Builder/BrickConfigBuilder.php @@ -4,49 +4,52 @@ use Pimcore\Extension\Document\Areabrick\EditableDialogBoxConfiguration; use Pimcore\Model\Document\Editable\Area\Info; -use Pimcore\Model\Document\Editable\Checkbox; -use Pimcore\Translation\Translator; -use ToolboxBundle\Registry\StoreProviderRegistryInterface; -use Twig\Environment; -class BrickConfigBuilder implements BrickConfigBuilderInterface +class BrickConfigBuilder extends AbstractConfigBuilder implements BrickConfigBuilderInterface { - protected Translator $translator; - protected Environment $templating; - protected StoreProviderRegistryInterface $storeProvider; - - public function __construct( - Translator $translator, - Environment $templating, - StoreProviderRegistryInterface $storeProvider - ) { - $this->translator = $translator; - $this->templating = $templating; - $this->storeProvider = $storeProvider; - } - - public function buildDialogBoxConfiguration(?Info $info, string $brickId, array $configNode = [], array $themeOptions = []): EditableDialogBoxConfiguration + public function buildConfiguration(?Info $info, string $brickId, array $areaConfig = [], array $themeOptions = [], bool $isInlineContext = false): EditableDialogBoxConfiguration { $config = new EditableDialogBoxConfiguration(); - $configParameter = $configNode['config_parameter'] ?? []; - $configElements = $configNode['config_elements'] ?? []; - $tabs = $configNode['tabs'] ?? []; + $configParameter = $areaConfig['config_parameter'] ?? []; + $configElements = $areaConfig['config_elements'] ?? []; + $tabs = $areaConfig['tabs'] ?? []; $configWindowSize = $this->getConfigWindowSize($configParameter); $config->setHeight($configWindowSize['height']); $config->setWidth($configWindowSize['width']); - $config->setReloadOnClose($configParameter['reload_on_close'] ?? false); - $items = $this->parseConfigElements($info, $brickId, $themeOptions, $configElements, $tabs); + $items = $this->parseConfigElements($info, $brickId, $themeOptions, $configElements, $tabs, true, $isInlineContext); $config->setItems($items); return $config; } + public function buildConfigurationData(Info $info, string $brickId, array $areaConfig = [], array $themeOptions = [], bool $isInlineContext = false): array + { + $data = []; + $invalidTypes = ['additionalClasses', 'additionalClassesChained']; + $configElements = $areaConfig['config_elements'] ?? []; + + foreach ($configElements as $itemName => $elementData) { + + if ($isInlineContext === true && array_key_exists('inline_rendered', $elementData) && $elementData['inline_rendered'] === true) { + continue; + } + + if (in_array($elementData['type'], $invalidTypes, true)) { + continue; + } + + $data[$itemName] = $this->editableRenderer->getEditable($info->getDocument(), $elementData['type'], $itemName, [], false)->getData(); + } + + return $data; + } + private function getConfigWindowSize(array $configParameter): array { $configWindowSize = $configParameter['window_size'] ?? null; @@ -70,313 +73,4 @@ private function getConfigWindowSize(array $configParameter): array 'height' => 370, ]; } - - private function parseConfigElements(?Info $info, string $brickId, array $themeOptions, array $configElements, array $tabs): array - { - $editableNodes = []; - - if (empty($configElements)) { - return $editableNodes; - } - - $acStoreProcessed = false; - - foreach ($configElements as $configElementName => $elementData) { - $editableNode = $this->parseConfigElement($info, $configElementName, $elementData, $acStoreProcessed); - - //if element need's a store and store is empty: skip field - if ($this->needStore($elementData['type']) && $this->hasValidStore($editableNode['config']) === false) { - continue; - } - - $editableNodes[] = $editableNode; - - $editableNodes = $this->checkColumnAdjusterField($brickId, $elementData['tab'], $themeOptions, $configElementName, $editableNodes); - - if ($elementData['type'] === 'additionalClasses') { - $acStoreProcessed = true; - } - } - - // move additional classes to bottom - $defaultFields = []; - $acFields = []; - - foreach ($editableNodes as $editableNode) { - if ($editableNode['additional_classes_element'] === true) { - $acFields[] = $editableNode; - } else { - $defaultFields[] = $editableNode; - } - } - - $editableNodes = array_merge($defaultFields, $acFields); - - // assign tabs, if configured - if (count($tabs) > 0) { - $tabbedEditableNodes = []; - foreach ($tabs as $tabId => $tabName) { - $tabbedEditableNodes[] = [ - 'type' => 'panel', - 'title' => $this->translator->trans($tabName, [], 'admin'), - 'items' => array_values( - array_filter($editableNodes, static function ($editableNode) use ($tabId) { - return $editableNode['tab'] === $tabId; - }) - ) - ]; - } - - return [ - 'type' => 'tabpanel', - 'items' => $tabbedEditableNodes - ]; - } - - return $editableNodes; - } - - private function parseConfigElement(?Info $info, string $elementName, array $elementData, bool $acStoreProcessed): array - { - $editableConfig = $elementData['config']; - $editableType = $elementData['type']; - - //set element config data - $parsedNode = $this->parseElementNode($elementName, $elementData, $acStoreProcessed); - - //set width - if ($this->canHaveDynamicWidth($editableType)) { - $parsedNode['width'] = $parsedNode['width'] ?? '100%'; - } else { - unset($parsedNode['width']); - } - - //set height - if ($this->canHaveDynamicHeight($editableType)) { - $parsedNode['height'] = $parsedNode['height'] ?? 200; - } else { - unset($parsedNode['height']); - } - - //set default - $parsedNode['config']['defaultValue'] = $this->getSelectedValue($info, $parsedNode, $editableConfig['default'] ?? null); - - //check store - if ($this->needStore($editableType) && $this->hasValidStore($editableConfig)) { - $parsedNode['config']['store'] = $this->buildStore($editableType, $editableConfig); - } - - return $parsedNode; - } - - private function parseElementNode(string $configElementName, array $elementData, bool $acStoreProcessed): array - { - $elementNode = [ - 'type' => $elementData['type'], - 'name' => $configElementName, - 'tab' => $elementData['tab'], - 'label' => isset($elementData['title']) && !empty($elementData['title']) ? $elementData['title'] : null, - 'description' => isset($elementData['description']) && !empty($elementData['description']) ? $elementData['description'] : null, - 'config' => $elementData['config'] ?? [], - 'additional_classes_element' => false, - ]; - - if ($elementData['type'] === 'additionalClasses') { - if ($acStoreProcessed === true) { - throw new \Exception( - sprintf( - 'A element of type "additionalClasses" in element "%s" already has been defined. You can only add one field of type "%s" per area. Use "%s" instead.', - $configElementName, - 'additionalClasses', - 'additionalClassesChained' - ) - ); - } - - $elementNode['type'] = 'select'; - $elementNode['label'] = isset($elementData['title']) && !empty($elementData['title']) ? $elementData['title'] : 'Additional'; - $elementNode['additional_classes_element'] = true; - $elementNode['name'] = 'add_classes'; - } elseif ($elementData['type'] === 'additionalClassesChained') { - if ($acStoreProcessed === false) { - throw new \Exception( - sprintf( - 'You need to add a element of type "%s" before adding a "%s" element.', - 'additionalClasses', - 'additionalClassesChained' - ) - ); - } elseif (!str_starts_with($configElementName, 'additional_classes_chain_')) { - throw new \Exception( - sprintf( - 'Chained AC element name needs to start with "%s" followed by a numeric. "%s" given.', - 'additional_classes_chain_', - $configElementName - ) - ); - } - - $chainedElementName = explode('_', $configElementName); - $chainedIncrementor = end($chainedElementName); - if (!is_numeric($chainedIncrementor)) { - throw new \Exception('Chained AC element name must end with an numeric. "' . $chainedIncrementor . '" given.'); - } - - $elementNode['type'] = 'select'; - $elementNode['label'] = isset($elementData['title']) && !empty($elementData['title']) ? $elementData['title'] : 'Additional'; - $elementNode['additional_classes_element'] = true; - $elementNode['name'] = 'add_cclasses_' . $chainedIncrementor; - } - - // translate title - if (!empty($elementNode['label'])) { - $elementNode['label'] = $this->translator->trans($elementNode['label'], [], 'admin'); - } - - // translate description - if (!empty($elementNode['description'])) { - $elementNode['description'] = $this->translator->trans($elementNode['description'], [], 'admin'); - } - - return $elementNode; - } - - private function getSelectedValue(?Info $info, array $config, mixed $defaultConfigValue): mixed - { - if (!$info instanceof Info) { - return $defaultConfigValue; - } - - $el = $info->getDocumentElement($config['name'], $config['type']); - - if ($el === null) { - return $defaultConfigValue; - } - - // force default (only if it returns false) - // checkboxes may return an empty string and are impossible to track into default mode - if (!empty($defaultConfigValue) && (method_exists($el, 'isEmpty') && $el->isEmpty() === true)) { - $el->setDataFromResource($defaultConfigValue); - } - - $value = $el instanceof Checkbox ? $el->isChecked() : $el->getData(); - - return !empty($value) ? $value : $defaultConfigValue; - } - - private function checkColumnAdjusterField(string $brickId, ?string $tab, array $themeOptions, string $configElementName, array $editableNodes): array - { - if ($brickId !== 'columns') { - return $editableNodes; - } - - if ($configElementName !== 'type') { - return $editableNodes; - } - - if (empty($themeOptions['grid']['breakpoints'])) { - return $editableNodes; - } - - $editableNodes[] = [ - 'type' => 'columnadjuster', - 'name' => 'columnadjuster', - 'tab' => $tab, - 'label' => $this->translator->trans('Column adjuster', [], 'admin'), - 'config' => [], - 'additional_classes_element' => false, - ]; - - return $editableNodes; - } - - private function buildStore($type, $config): array - { - $storeValues = []; - if (isset($config['store'])) { - $storeValues = $config['store']; - } elseif (isset($config['store_provider'])) { - $storeProvider = $this->storeProvider->get($config['store_provider']); - $storeValues = $storeProvider->getValues(); - } - - if (count($storeValues) === 0) { - throw new \Exception($type . ' has no valid configured store'); - } - - $store = []; - foreach ($storeValues as $k => $v) { - if (is_array($v)) { - $v = $v['name']; - } - $store[] = [$k, $this->translator->trans($v, [], 'admin')]; - } - - return $store; - } - - private function hasValidStore($parsedConfig): bool - { - if (isset($parsedConfig['store']) && is_array($parsedConfig['store']) && count($parsedConfig['store']) > 0) { - return true; - } - - if (isset($parsedConfig['store_provider']) && $this->storeProvider->has($parsedConfig['store_provider'])) { - return true; - } - - return false; - } - - private function needStore($type): bool - { - return in_array($type, ['select', 'multiselect', 'additionalClasses', 'additionalClassesChained']); - } - - private function canHaveDynamicWidth($type): bool - { - return in_array( - $type, - [ - 'multihref', - 'relations', - 'href', - 'relation', - 'image', - 'input', - 'multiselect', - 'numeric', - 'embed', - 'pdf', - 'renderlet', - 'select', - 'snippet', - 'table', - 'textarea', - 'video', - 'wysiwyg', - 'parallaximage', - 'additionalClasses', - 'additionalClassesChained' - ] - ); - } - - private function canHaveDynamicHeight($type): bool - { - return in_array($type, [ - 'multihref', - 'relations', - 'image', - 'multiselect', - 'embed', - 'pdf', - 'renderlet', - 'snippet', - 'textarea', - 'video', - 'wysiwyg', - 'parallaximage' - ]); - } } diff --git a/src/ToolboxBundle/Builder/BrickConfigBuilderInterface.php b/src/ToolboxBundle/Builder/BrickConfigBuilderInterface.php index 36d00bbb..59aa605a 100644 --- a/src/ToolboxBundle/Builder/BrickConfigBuilderInterface.php +++ b/src/ToolboxBundle/Builder/BrickConfigBuilderInterface.php @@ -7,5 +7,7 @@ interface BrickConfigBuilderInterface { - public function buildDialogBoxConfiguration(?Info $info, string $brickId, array $configNode = [], array $themeOptions = []): EditableDialogBoxConfiguration; + public function buildConfiguration(?Info $info, string $brickId, array $areaConfig = [], array $themeOptions = [], bool $isInlineContext = false): EditableDialogBoxConfiguration; + + public function buildConfigurationData(Info $info, string $brickId, array $areaConfig = [], array $themeOptions = [], bool $isInlineContext = false): array; } diff --git a/src/ToolboxBundle/Builder/InlineConfigBuilder.php b/src/ToolboxBundle/Builder/InlineConfigBuilder.php new file mode 100644 index 00000000..042fe138 --- /dev/null +++ b/src/ToolboxBundle/Builder/InlineConfigBuilder.php @@ -0,0 +1,254 @@ +editableWorker = $editableWorker; + } + + public function buildInlineConfiguration(Info $info, string $brickId, array $areaConfig = [], array $themeOptions = [], bool $editMode = false): string + { + $configurationView = []; + $inlineConfigElements = $areaConfig['inline_config_elements'] ?? []; + + $items = $this->parseConfigElements($info, $brickId, $themeOptions, $inlineConfigElements, [], false); + + foreach ($items as $item) { + $configurationView[] = $this->templating->render( + '@Toolbox/admin/inline_config/editable.html.twig', + [ + 'item' => $item, + 'editable' => $this->buildEditable($info, $item, $editMode) + ] + ); + } + + if (count($configurationView) === 0) { + return ''; + } + + return sprintf('
%s
', implode(PHP_EOL, $configurationView)); + } + + public function buildInlineConfigurationData(Info $info, string $brickId, array $areaConfig = [], array $themeOptions = []): array + { + $data = []; + $inlineConfigElements = $areaConfig['inline_config_elements'] ?? []; + + foreach ($inlineConfigElements as $itemName => $itemData) { + + $item = [ + 'name' => $itemName, + 'type' => $itemData['type'], + 'config' => $itemData['config'] ?? [] + ]; + + if (array_key_exists('children', $itemData)) { + foreach ($itemData['children'] as $childName => $childData) { + $item['children'][] = [ + 'name' => $childName, + 'type' => $childData['type'], + 'config' => $childData['config'] ?? [] + ]; + } + } + + $editableData = $this->buildEditable($info, $item, false); + + $data[$itemName] = $editableData; + } + + return $data; + } + + private function buildEditable(Info $info, array $item, bool $editMode): Editable|string|array + { + if ($item['type'] === 'block') { + return $this->buildBlockEditable($info, $item['name'], $item['config'], $item['children'] ?? [], $editMode); + } + + if ($item['type'] === 'areablock') { + return $this->buildAreaBlockEditable($info, $item['name'], $item['config'], $editMode); + } + + if ($item['type'] === 'column') { + return $this->buildColumnEditable($info, $item['config'], $editMode); + } + + return $this->buildStandardEditable($info, $item['type'], $item['name'], $item['config'], $editMode); + } + + private function buildStandardEditable(Info $info, string $type, string $inputName, array $config, bool $editMode): Editable|string|array + { + return $this->processEditable($info->getDocument(), $type, $inputName, $config, $editMode); + } + + private function buildColumnEditable(Info $info, array $config, bool $editMode): string|array + { + $data = []; + $document = $info->getDocument(); + $columns = $info->getParam('columns'); + + if ($columns === null) { + throw new ConfigurationException( + sprintf( + 'Cannot render "columns" editable. Brick "%s" does not provide any "columns" definitions in $info parameter', + $info->getId() + ) + ); + } + + foreach ($columns as $column) { + + $areaBlockDataResponse = null; + $columnName = sprintf('c%s', $column['name']); + + $config['areablock_config_name'] = $info->getId(); + + ob_start(); + + echo $this->processEditable($document, 'areablock', $columnName, $config, $editMode, true); + + if ($editMode === false) { + $areaBlockDataResponse = $this->processEditable($document, 'areablock', $columnName, $config, false); + } + + $areaBlockHtmlResponse = ob_get_clean(); + + $data[$columnName] = $editMode + ? sprintf('
%s
', $column['columnClass'], $column['innerClass'], $areaBlockHtmlResponse) + : $areaBlockDataResponse; + } + + return $editMode ? implode(PHP_EOL, $data) : $data; + } + + private function buildAreaBlockEditable(Info $info, string $inputName, array $config, bool $editMode): string|array + { + $areaBlockDataResponse = ''; + $document = $info->getDocument(); + + $config['areablock_config_name'] = $info->getId(); + + ob_start(); + + echo $this->processEditable($document, 'areablock', $inputName, $config, $editMode, true); + + if ($editMode === false) { + $areaBlockDataResponse = $this->processEditable($document, 'areablock', $inputName, $config, false); + } + + $areaBlockHtmlResponse = ob_get_clean(); + + return $editMode ? $areaBlockHtmlResponse : $areaBlockDataResponse; + } + + private function buildBlockEditable(Info $info, string $inputName, array $config, array $blockElements, bool $editMode): string|array + { + $data = []; + $document = $info->getDocument(); + + ob_start(); + + if (!array_key_exists('default', $config)) { + $config['default'] = 1; + } + + /** @var Block $blockEditable */ + $blockEditable = $this->editableRenderer->getEditable($document, 'block', $inputName, $config, $editMode); + + foreach ($blockEditable->getIterator() as $blockIndex) { + foreach ($blockElements as $blockElement) { + + $beType = $blockElement['type']; + $beName = $blockElement['name']; + $beConfig = $blockElement['config']; + + echo $this->processEditable($document, $beType, $beName, $beConfig, $editMode, true); + + if ($editMode === false) { + $data[] = $this->processEditable($document, $beType, $beName, $beConfig, false, false, $info->getId()); + } + } + } + + $areaBlockHtmlResponse = ob_get_clean(); + + return $editMode ? $areaBlockHtmlResponse : $data; + } + + private function processEditable( + PageSnippet $document, + string $type, + string $name, + array $config, + bool $editMode, + bool $forceRendering = false, + ?string $brickParent = null, + ): mixed { + + $isSimple = !$this->isBlockEditable($type); + + // override config with area block config + if ($type === 'areablock' && $editMode === true) { + + $areaBlockConfigurationName = $name; + if (array_key_exists('areablock_config_name', $config)) { + $areaBlockConfigurationName = $config['areablock_config_name']; + unset($config['areablock_config_name']); + } + + $config = $this->areaManager->getAreaBlockConfiguration($areaBlockConfigurationName, $document instanceof Snippet, true); + } + + /** @var Editable $editable */ + $editable = $this->editableRenderer->getEditable($document, $type, $name, $config, $editMode); + + if ($isSimple === true && $brickParent !== null) { + + if ($editMode === false) { + + $simpleHeadlessResponse = new HeadlessResponse(HeadlessResponse::TYPE_EDITABLE, $brickParent); + $simpleHeadlessResponse->setInlineConfigElementData([$editable->getRealName() => $editable]); + + $this->editableWorker->processEditable($simpleHeadlessResponse, $editable); + + return $editable; + } + + return $editable->render(); + } + + if ($forceRendering === false && $editMode === false) { + return $editable; + } + + // simple editables output can be returned + if ($isSimple === true) { + return $editable->render(); + } + + echo $editable->render(); + + return ''; + } + + private function isBlockEditable(string $type): bool + { + return in_array($type, ['area', 'block', 'areablock', 'scheduledblock'], true); + } +} diff --git a/src/ToolboxBundle/Builder/InlineConfigBuilderInterface.php b/src/ToolboxBundle/Builder/InlineConfigBuilderInterface.php new file mode 100644 index 00000000..18dc8040 --- /dev/null +++ b/src/ToolboxBundle/Builder/InlineConfigBuilderInterface.php @@ -0,0 +1,12 @@ +configManager = $configManager; - $this->configManager->setAreaNameSpace(ConfigManagerInterface::AREABRICK_NAMESPACE_INTERNAL); return $this; } @@ -30,7 +29,7 @@ public function calculateColumns(?string $value, ?array $customColumnConfigurati $columnConfiguration = $customColumnConfiguration; } else { $columnConfigNode = $this->configManager->getAreaElementConfig('columns', 'type'); - $columnConfiguration = isset($columnConfigNode['config']['store']) ? $columnConfigNode['config']['store'] : []; + $columnConfiguration = $columnConfigNode['config']['store'] ?? []; } $columns = []; @@ -69,7 +68,7 @@ public function calculateColumns(?string $value, ?array $customColumnConfigurati } } - if (substr($columnClass, 0, 1) === 'o') { + if (str_starts_with($columnClass, 'o')) { $offset = (int) substr($columnClass, 1); $gridOffsetConfig = $customColumnConfiguration ? [] : [ @@ -85,8 +84,8 @@ public function calculateColumns(?string $value, ?array $customColumnConfigurati $customBreakPoints = $columnConfiguration[$value]['breakpoints']; foreach ($customBreakPoints as $customBreakPointName => $customBreakPointData) { $customBreakPointDataColumns = explode('_', $customBreakPointData); - $customColAmount = isset($customBreakPointDataColumns[$i]) ? $customBreakPointDataColumns[$i] : $gridSize; - if (substr($customColAmount, 0, 1) === 'o') { + $customColAmount = $customBreakPointDataColumns[$i] ?? $gridSize; + if (str_starts_with($customColAmount, 'o')) { $customOffset = (int) substr($customColAmount, 1); $bootstrapOffsetConfig[$customBreakPointName] = 'col-' . $customBreakPointName . '-offset-' . $customOffset; $gridOffsetConfig[$customBreakPointName] = $customOffset; diff --git a/src/ToolboxBundle/Calculator/Bootstrap4/ColumnCalculator.php b/src/ToolboxBundle/Calculator/Bootstrap4/ColumnCalculator.php index cd86e0a5..c7b77803 100644 --- a/src/ToolboxBundle/Calculator/Bootstrap4/ColumnCalculator.php +++ b/src/ToolboxBundle/Calculator/Bootstrap4/ColumnCalculator.php @@ -12,7 +12,6 @@ class ColumnCalculator implements ColumnCalculatorInterface public function setConfigManager(ConfigManagerInterface $configManager): self { $this->configManager = $configManager; - $this->configManager->setAreaNameSpace(ConfigManagerInterface::AREABRICK_NAMESPACE_INTERNAL); return $this; } @@ -33,7 +32,7 @@ public function calculateColumns(?string $value, ?array $customColumnConfigurati $columnConfiguration = $customColumnConfiguration; } else { $columnConfigNode = $this->configManager->getAreaElementConfig('columns', 'type'); - $columnConfiguration = isset($columnConfigNode['config']['store']) ? $columnConfigNode['config']['store'] : []; + $columnConfiguration = $columnConfigNode['config']['store'] ?? []; } $columns = []; @@ -44,13 +43,13 @@ public function calculateColumns(?string $value, ?array $customColumnConfigurati $t = explode('_', $value); //remove "column" in string. - $_columns = array_splice($t, 1); + $rawColumns = array_splice($t, 1); $bootstrapOffsetConfig = []; $gridOffsetConfig = []; $columnCounter = 0; - foreach ($_columns as $i => $columnClass) { + foreach ($rawColumns as $i => $columnClass) { $gridConfig = $customColumnConfiguration ? [] : [ 'xs' => $gridSize, 'sm' => (int) $columnClass @@ -73,7 +72,7 @@ public function calculateColumns(?string $value, ?array $customColumnConfigurati } } - if (substr($columnClass, 0, 1) === 'o') { + if (str_starts_with($columnClass, 'o')) { $offset = (int) substr($columnClass, 1); $gridOffsetConfig = $customColumnConfiguration ? [] : [ @@ -89,8 +88,8 @@ public function calculateColumns(?string $value, ?array $customColumnConfigurati $customBreakPoints = $columnConfiguration[$value]['breakpoints']; foreach ($customBreakPoints as $customBreakPointName => $customBreakPointData) { $customBreakPointDataColumns = explode('_', $customBreakPointData); - $customColAmount = isset($customBreakPointDataColumns[$i]) ? $customBreakPointDataColumns[$i] : $gridSize; - if (substr($customColAmount, 0, 1) === 'o') { + $customColAmount = $customBreakPointDataColumns[$i] ?? $gridSize; + if (str_starts_with($customColAmount, 'o')) { $customOffset = (int) substr($customColAmount, 1); $bpPrefix = $customBreakPointName === 'xs' ? '' : $customBreakPointName . '-'; $bootstrapOffsetConfig[$customBreakPointName] = 'offset-' . $bpPrefix . $customOffset; @@ -105,7 +104,7 @@ public function calculateColumns(?string $value, ?array $customColumnConfigurati $columnName = $strictColumnCounter ? 'column_' . $i : 'column_' . $columnCounter; $columns[] = [ - 'columnClass' => implode(' ', $bootstrapClassConfig) . ' ' . join(' ', $bootstrapOffsetConfig), + 'columnClass' => implode(' ', $bootstrapClassConfig) . ' ' . implode(' ', $bootstrapOffsetConfig), 'columnData' => [ 'grid' => $gridConfig, 'gridOffset' => $gridOffsetConfig diff --git a/src/ToolboxBundle/Calculator/UIkit3/ColumnCalculator.php b/src/ToolboxBundle/Calculator/UIkit3/ColumnCalculator.php index 4f8c30af..82510b77 100644 --- a/src/ToolboxBundle/Calculator/UIkit3/ColumnCalculator.php +++ b/src/ToolboxBundle/Calculator/UIkit3/ColumnCalculator.php @@ -12,7 +12,6 @@ class ColumnCalculator implements ColumnCalculatorInterface public function setConfigManager(ConfigManagerInterface $configManager): self { $this->configManager = $configManager; - $this->configManager->setAreaNameSpace(ConfigManagerInterface::AREABRICK_NAMESPACE_INTERNAL); return $this; } @@ -42,10 +41,10 @@ public function calculateColumns(?string $value, ?array $customColumnConfigurati $t = explode('_', $value); // remove "column" in string. - $_columns = array_splice($t, 1); + $rawColumns = array_splice($t, 1); $columnCounter = 0; - foreach ($_columns as $i => $columnClass) { + foreach ($rawColumns as $i => $columnClass) { // set when no custom config exists $gridConfig = $customColumnConfiguration ? [] : [ 's' => $gridSize, diff --git a/src/ToolboxBundle/Command/AreaConfigurationCommand.php b/src/ToolboxBundle/Command/AreaConfigurationCommand.php index f2af5d57..ea65545e 100644 --- a/src/ToolboxBundle/Command/AreaConfigurationCommand.php +++ b/src/ToolboxBundle/Command/AreaConfigurationCommand.php @@ -17,11 +17,9 @@ class AreaConfigurationCommand extends Command { protected static $defaultName = 'toolbox:check-config'; protected static $defaultDescription = 'Check configuration of a given area element.'; - protected AdaptiveConfigManagerInterface $adaptiveConfigManager; - public function __construct(AdaptiveConfigManagerInterface $adaptiveConfigManager) + public function __construct(protected AdaptiveConfigManagerInterface $adaptiveConfigManager) { - $this->adaptiveConfigManager = $adaptiveConfigManager; parent::__construct(); } @@ -58,12 +56,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int return Command::SUCCESS; } - $namespace = ConfigManagerInterface::AREABRICK_NAMESPACE_INTERNAL; - if (!in_array($brickId, ToolboxConfig::TOOLBOX_TYPES)) { - $namespace = ConfigManagerInterface::AREABRICK_NAMESPACE_EXTERNAL; - } - - $this->adaptiveConfigManager->setAreaNameSpace($namespace); $this->adaptiveConfigManager->setContextNameSpace($contextId); $brickConfig = $this->adaptiveConfigManager->getAreaConfig($brickId); diff --git a/src/ToolboxBundle/Controller/Admin/ColumnAdjusterController.php b/src/ToolboxBundle/Controller/Admin/ColumnAdjusterController.php index aec3c91d..c30d64e2 100644 --- a/src/ToolboxBundle/Controller/Admin/ColumnAdjusterController.php +++ b/src/ToolboxBundle/Controller/Admin/ColumnAdjusterController.php @@ -2,23 +2,18 @@ namespace ToolboxBundle\Controller\Admin; -use Pimcore\Bundle\AdminBundle\Controller; +use Pimcore\Bundle\AdminBundle\Controller\AdminAbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use ToolboxBundle\Manager\ConfigManagerInterface; use ToolboxBundle\Registry\CalculatorRegistryInterface; -class ColumnAdjusterController extends Controller\AdminController +class ColumnAdjusterController extends AdminAbstractController { - private CalculatorRegistryInterface $calculatorRegistry; - private ConfigManagerInterface $configManager; - public function __construct( - ConfigManagerInterface $configManager, - CalculatorRegistryInterface $calculatorRegistry + private ConfigManagerInterface $configManager, + private CalculatorRegistryInterface $calculatorRegistry ) { - $this->configManager = $configManager; - $this->calculatorRegistry = $calculatorRegistry; } /** diff --git a/src/ToolboxBundle/Controller/Admin/SettingsController.php b/src/ToolboxBundle/Controller/Admin/SettingsController.php index bbd5fd31..a1803a7f 100644 --- a/src/ToolboxBundle/Controller/Admin/SettingsController.php +++ b/src/ToolboxBundle/Controller/Admin/SettingsController.php @@ -3,32 +3,25 @@ namespace ToolboxBundle\Controller\Admin; use Exception; -use Pimcore\Bundle\AdminBundle\Controller; +use Pimcore\Bundle\AdminBundle\Controller\AdminAbstractController; use Symfony\Component\HttpFoundation\Response; use ToolboxBundle\Manager\ConfigManagerInterface; -class SettingsController extends Controller\AdminController +class SettingsController extends AdminAbstractController { - protected array $globalStyleSets = []; - protected array $ckEditorObjectConfig = []; - protected array $ckEditorAreaConfig = []; - protected ConfigManagerInterface $configManager; - - public function __construct(ConfigManagerInterface $configManager) + public function __construct(protected ConfigManagerInterface $configManager) { - $this->configManager = $configManager; } /** * @throws Exception */ - public function ckEditorAreaStyleAction(): Response + public function wysiwygAreaStyleAction(): Response { - $this->setData(); + [$wysiwygObjectConfig, $wysiwygAreaConfig] = $this->parseData(); - $response = $this->render('@Toolbox/admin/settings/ckeditor-area-style.html.twig', [ - 'globalStyleSets' => $this->globalStyleSets, - 'config' => $this->ckEditorAreaConfig + $response = $this->render('@Toolbox/admin/settings/wysiwyg-area-style.html.twig', [ + 'config' => $wysiwygAreaConfig ]); $response->headers->set('Content-Type', 'application/javascript'); @@ -41,13 +34,12 @@ public function ckEditorAreaStyleAction(): Response /** * @throws Exception */ - public function ckEditorObjectStyleAction(): Response + public function wysiwygObjectStyleAction(): Response { - $this->setData(); + [$wysiwygObjectConfig, $wysiwygAreaConfig] = $this->parseData(); - $response = $this->render('@Toolbox/admin/settings/ckeditor-object-style.html.twig', [ - 'globalStyleSets' => $this->globalStyleSets, - 'config' => $this->ckEditorObjectConfig + $response = $this->render('@Toolbox/admin/settings/wysiwyg-object-style.html.twig', [ + 'config' => $wysiwygObjectConfig ]); $response->headers->set('Content-Type', 'application/javascript'); @@ -60,31 +52,28 @@ public function ckEditorObjectStyleAction(): Response /** * @throws Exception */ - private function setData(): void + private function parseData(): array { - $ckEditorSettings = $this->configManager->getConfig('ckeditor'); + $wysiwygSettings = $this->configManager->getConfig('wysiwyg_editor'); - $ckEditorGlobalConfig = $ckEditorSettings['config']; + $wysiwygEditorConfig = $wysiwygSettings['config']; //object config - $userCkEditorObjectConfig = []; - if (isset($ckEditorSettings['object_editor']['config'])) { - $userCkEditorObjectConfig = $ckEditorSettings['object_editor']['config']; + $userWysiwygEditorObjectConfig = []; + if (isset($wysiwygSettings['object_editor']['config'])) { + $userWysiwygEditorObjectConfig = $wysiwygSettings['object_editor']['config']; } //area config - $userCkEditorAreaConfig = []; - if (isset($ckEditorSettings['area_editor']['config'])) { - $userCkEditorAreaConfig = $ckEditorSettings['area_editor']['config']; - } - - //global style sets config - if (isset($ckEditorSettings['global_style_sets'])) { - $this->globalStyleSets = $ckEditorSettings['global_style_sets']; + $userWysiwygEditorAreaConfig = []; + if (isset($wysiwygSettings['area_editor']['config'])) { + $userWysiwygEditorAreaConfig = $wysiwygSettings['area_editor']['config']; } - $this->ckEditorObjectConfig = $this->parseToolbarConfig($ckEditorGlobalConfig, $userCkEditorObjectConfig); - $this->ckEditorAreaConfig = $this->parseToolbarConfig($ckEditorGlobalConfig, $userCkEditorAreaConfig); + return [ + $this->parseToolbarConfig($wysiwygEditorConfig, $userWysiwygEditorObjectConfig), + $this->parseToolbarConfig($wysiwygEditorConfig, $userWysiwygEditorAreaConfig) + ]; } private function parseToolbarConfig(array $defaultConfig, array $userConfig): array diff --git a/src/ToolboxBundle/Controller/AjaxController.php b/src/ToolboxBundle/Controller/AjaxController.php index 1b9d68b8..01023581 100644 --- a/src/ToolboxBundle/Controller/AjaxController.php +++ b/src/ToolboxBundle/Controller/AjaxController.php @@ -14,7 +14,7 @@ class AjaxController extends FrontendController public function gmInfoWindowAction(Request $request, LayoutManagerInterface $layoutManager): Response { return $this->render( - $layoutManager->getAreaTemplatePath('googleMap', 'google-map', 'info-window'), + $layoutManager->getAreaTemplatePath('googleMap', 'google_map', 'info_window'), [ 'mapParams' => $request->get('mapParams'), 'googleMapsHostUrl' => $this->getParameter('toolbox_google_maps_host_url') @@ -27,7 +27,7 @@ public function gmInfoWindowAction(Request $request, LayoutManagerInterface $lay */ public function videoGetTypesAction(Request $request, ConfigManagerInterface $configManager): JsonResponse { - $videoAreaSettings = $configManager->setAreaNameSpace(ConfigManagerInterface::AREABRICK_NAMESPACE_INTERNAL)->getAreaParameterConfig('video'); + $videoAreaSettings = $configManager->getAreaParameterConfig('video'); $videoOptions = $videoAreaSettings['video_types']; $allowedVideoTypes = []; diff --git a/src/ToolboxBundle/Controller/HeadlessController.php b/src/ToolboxBundle/Controller/HeadlessController.php new file mode 100644 index 00000000..9b80c6ce --- /dev/null +++ b/src/ToolboxBundle/Controller/HeadlessController.php @@ -0,0 +1,16 @@ +resolveDocument($request, $this->document, 'index'); + } +} diff --git a/src/ToolboxBundle/Controller/SnippetController.php b/src/ToolboxBundle/Controller/SnippetController.php index 40411252..de2fd08a 100644 --- a/src/ToolboxBundle/Controller/SnippetController.php +++ b/src/ToolboxBundle/Controller/SnippetController.php @@ -14,8 +14,8 @@ class SnippetController extends FrontendController */ public function teaserAction(Request $request, ConfigManagerInterface $configManager): Response { - $layoutStore = $configManager->setAreaNameSpace(ConfigManagerInterface::AREABRICK_NAMESPACE_INTERNAL)->getAreaElementConfig('teaser', 'layout'); - $addClStore = $configManager->setAreaNameSpace(ConfigManagerInterface::AREABRICK_NAMESPACE_INTERNAL)->getAreaElementConfig('teaser', 'additional_classes'); + $layoutStore = $configManager->getAreaElementConfig('teaser', 'layout'); + $addClStore = $configManager->getAreaElementConfig('teaser', 'additional_classes'); $layoutExtJsStore = []; $addClExtJsStore = []; @@ -35,7 +35,7 @@ public function teaserAction(Request $request, ConfigManagerInterface $configMan } return $this->renderTemplate( - '@Toolbox/snippet/layout/teaser-layout.html.twig', + '@Toolbox/snippet/layout/teaser_layout.html.twig', [ 'mapParams' => $request->get('mapParams'), 'layoutStore' => $layoutExtJsStore, diff --git a/src/ToolboxBundle/DependencyInjection/Compiler/AreaBrickRegistryPass.php b/src/ToolboxBundle/DependencyInjection/Compiler/AreaBrickRegistryPass.php index 18597314..1f0c3070 100644 --- a/src/ToolboxBundle/DependencyInjection/Compiler/AreaBrickRegistryPass.php +++ b/src/ToolboxBundle/DependencyInjection/Compiler/AreaBrickRegistryPass.php @@ -8,11 +8,14 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use ToolboxBundle\Builder\BrickConfigBuilderInterface; +use ToolboxBundle\Builder\InlineConfigBuilderInterface; use ToolboxBundle\Document\Areabrick\AbstractAreabrick; use ToolboxBundle\Document\Areabrick\AbstractBaseAreabrick; use ToolboxBundle\Document\SimpleAreabrick\SimpleAreaBrick; use ToolboxBundle\Document\SimpleAreabrick\SimpleAreaBrickConfigurable; +use ToolboxBundle\Manager\ConfigManager; use ToolboxBundle\Manager\ConfigManagerInterface; use ToolboxBundle\Manager\LayoutManagerInterface; use ToolboxBundle\ToolboxConfig; @@ -27,7 +30,9 @@ public function process(ContainerBuilder $container): void $abstractBrickDefinition = new Definition(AbstractBaseAreabrick::class); $abstractBrickDefinition->setAbstract(true); $abstractBrickDefinition->addMethodCall('setLayoutManager', [new Reference(LayoutManagerInterface::class)]); + $abstractBrickDefinition->addMethodCall('setInlineConfigBuilder', [new Reference(InlineConfigBuilderInterface::class)]); $abstractBrickDefinition->addMethodCall('setConfigManager', [new Reference(ConfigManagerInterface::class)]); + $abstractBrickDefinition->addMethodCall('setEventDispatcher', [new Reference(EventDispatcherInterface::class)]); $container->setDefinition(AbstractBaseAreabrick::class, $abstractBrickDefinition); @@ -39,9 +44,11 @@ public function process(ContainerBuilder $container): void $container->setDefinition(AbstractAreabrick::class, $abstractConfigurableBrickDefinition); + $additionalAreaBricksConfig = []; + // check for legacy naming - $pimcoreTaggedServices = $container->findTaggedServiceIds('pimcore.area.brick', true); - foreach ($pimcoreTaggedServices as $legacyId => $legacyTags) { + $pimcoreTaggedAreaBricksServices = $container->findTaggedServiceIds('pimcore.area.brick', true); + foreach ($pimcoreTaggedAreaBricksServices as $legacyId => $legacyTags) { $legacyBrickDefinition = $container->getDefinition($legacyId); if ($legacyBrickDefinition instanceof ChildDefinition && $legacyBrickDefinition->getParent() === AbstractAreabrick::class) { throw new InvalidDefinitionException(sprintf( @@ -51,11 +58,16 @@ public function process(ContainerBuilder $container): void $legacyId )); } + + foreach ($legacyTags as $pimcoreAreaBrickAttributes) { + $additionalAreaBricksConfig[] = $pimcoreAreaBrickAttributes['id']; + } + } // register toolbox bricks - $toolboxTaggedServices = $container->findTaggedServiceIds('toolbox.area.brick', true); - foreach ($toolboxTaggedServices as $id => $tags) { + $toolboxTaggedAreaBricksServices = $container->findTaggedServiceIds('toolbox.area.brick', true); + foreach ($toolboxTaggedAreaBricksServices as $id => $tags) { $brickDefinition = $container->getDefinition($id); if (!$brickDefinition instanceof ChildDefinition) { @@ -66,14 +78,6 @@ public function process(ContainerBuilder $container): void )); } - if ($brickDefinition->hasMethodCall('setAreaBrickType')) { - throw new InvalidDefinitionException(sprintf( - 'Please remove methodCall "%s" from your brick "%s". The type declaration will be processed internally.', - 'setAreaBrickType', - $id - )); - } - foreach ($tags as $attributes) { $type = AbstractBaseAreabrick::AREABRICK_TYPE_EXTERNAL; @@ -81,12 +85,12 @@ public function process(ContainerBuilder $container): void $type = AbstractBaseAreabrick::AREABRICK_TYPE_INTERNAL; } - if ($type === AbstractBaseAreabrick::AREABRICK_TYPE_EXTERNAL && in_array($attributes['id'], ToolboxConfig::TOOLBOX_TYPES, true)) { + if ($type === AbstractBaseAreabrick::AREABRICK_TYPE_EXTERNAL && in_array($attributes['id'], ToolboxConfig::TOOLBOX_AREA_TYPES, true)) { throw new InvalidDefinitionException(sprintf( 'ID "%s" for AreaBrick "%s is a reserved identifier. Please change the id of your custom AreaBrick. Internal IDs are: %s.', $attributes['id'], $id, - implode(', ', ToolboxConfig::TOOLBOX_TYPES) + implode(', ', ToolboxConfig::TOOLBOX_AREA_TYPES) )); } @@ -100,8 +104,8 @@ public function process(ContainerBuilder $container): void } // register simple toolbox bricks - $toolboxTaggedServices = $container->findTaggedServiceIds('toolbox.area.simple_brick', true); - foreach ($toolboxTaggedServices as $id => $tags) { + $toolboxTaggedSimpleAreaBricksServices = $container->findTaggedServiceIds('toolbox.area.simple_brick', true); + foreach ($toolboxTaggedSimpleAreaBricksServices as $id => $tags) { $simpleBrickDefinition = $container->getDefinition($id); if (!$simpleBrickDefinition instanceof ChildDefinition) { @@ -120,21 +124,22 @@ public function process(ContainerBuilder $container): void $simpleBrickDefinition->addMethodCall('setAreaBrickType', [AbstractBaseAreabrick::AREABRICK_TYPE_EXTERNAL]); foreach ($tags as $attributes) { - if (!isset($attributes['title']) || empty($attributes['title'])) { + + if (empty($attributes['title'])) { throw new InvalidDefinitionException(sprintf('Simple Areabrick "%s" has an invalid title', $attributes['id'])); } $simpleBrickDefinition->addMethodCall('setName', [$attributes['title']]); - if (isset($attributes['description']) && !empty($attributes['description'])) { + if (!empty($attributes['description'])) { $simpleBrickDefinition->addMethodCall('setDescription', [$attributes['description']]); } - if (isset($attributes['template']) && !empty($attributes['template'])) { + if (!empty($attributes['template'])) { $simpleBrickDefinition->addMethodCall('setTemplate', [$attributes['template']]); } - if (isset($attributes['icon']) && !empty($attributes['icon'])) { + if (!empty($attributes['icon'])) { $simpleBrickDefinition->addMethodCall('setIcon', [$attributes['icon']]); } @@ -143,6 +148,8 @@ public function process(ContainerBuilder $container): void if ($simpleBrickDefinition->getParent() === AbstractBaseAreabrick::class) { $notEditDialogAwareBricks[] = $attributes['id']; } + + $additionalAreaBricksConfig[] = $attributes['id']; } } @@ -152,7 +159,7 @@ public function process(ContainerBuilder $container): void if (in_array($requestedEditDialogAwareBrickId, $notEditDialogAwareBricks, true)) { throw new InvalidDefinitionException( sprintf( - 'Areabrick "%s" has some dialog editables but has been registered as a non-configurable brick. Please set "%s" as parent class or remove the config node from custom_areas.%s', + 'Areabrick "%s" has some dialog editables but has been registered as a non-configurable brick. Please set "%s" as parent class or remove the config node from areas.%s', $requestedEditDialogAwareBrickId, AbstractAreabrick::class, $requestedEditDialogAwareBrickId @@ -161,5 +168,10 @@ public function process(ContainerBuilder $container): void } } } + + if(count($additionalAreaBricksConfig) > 0) { + $configManagerDefinition = $container->getDefinition(ConfigManager::class); + $configManagerDefinition->addMethodCall('addAdditionalAreaConfig', [$additionalAreaBricksConfig]); + } } } diff --git a/src/ToolboxBundle/DependencyInjection/Compiler/CalculatorRegistryPass.php b/src/ToolboxBundle/DependencyInjection/Compiler/CalculatorRegistryPass.php index 5290d835..b3680435 100644 --- a/src/ToolboxBundle/DependencyInjection/Compiler/CalculatorRegistryPass.php +++ b/src/ToolboxBundle/DependencyInjection/Compiler/CalculatorRegistryPass.php @@ -14,9 +14,10 @@ final class CalculatorRegistryPass implements CompilerPassInterface public function process(ContainerBuilder $container): void { + $definition = $container->getDefinition(CalculatorRegistry::class); $taggedServices = $container->findTaggedServiceIds('toolbox.calculator', true); + foreach ($taggedServices as $id => $tags) { - $definition = $container->getDefinition(CalculatorRegistry::class); foreach ($tags as $attributes) { $definition->addMethodCall('register', [$id, new Reference($id), $attributes['type']]); } diff --git a/src/ToolboxBundle/DependencyInjection/Compiler/EditableHandlerPass.php b/src/ToolboxBundle/DependencyInjection/Compiler/EditableHandlerPass.php new file mode 100644 index 00000000..0c0a11cc --- /dev/null +++ b/src/ToolboxBundle/DependencyInjection/Compiler/EditableHandlerPass.php @@ -0,0 +1,19 @@ +getParameter('toolbox.headless_aware')) { + return; + } + + $container->getDefinition(EditableHandler::class)->setClass(\ToolboxBundle\Document\Editable\EditableHandler::class); + } +} diff --git a/src/ToolboxBundle/DependencyInjection/Compiler/NormalizerRegistryPass.php b/src/ToolboxBundle/DependencyInjection/Compiler/NormalizerRegistryPass.php new file mode 100644 index 00000000..a8b9d845 --- /dev/null +++ b/src/ToolboxBundle/DependencyInjection/Compiler/NormalizerRegistryPass.php @@ -0,0 +1,24 @@ +getDefinition(NormalizerRegistry::class); + $taggedServices = $container->findTaggedServiceIds('toolbox.property.normalizer', true); + + foreach ($taggedServices as $id => $tags) { + $definition->addMethodCall('register', [$id, new Reference($id)]); + } + } +} diff --git a/src/ToolboxBundle/DependencyInjection/Configuration.php b/src/ToolboxBundle/DependencyInjection/Configuration.php index 91c16622..fe2d95b9 100644 --- a/src/ToolboxBundle/DependencyInjection/Configuration.php +++ b/src/ToolboxBundle/DependencyInjection/Configuration.php @@ -3,13 +3,12 @@ namespace ToolboxBundle\DependencyInjection; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; -use Symfony\Component\Config\Definition\Builder\EnumNodeDefinition; +use Symfony\Component\Config\Definition\Builder\BooleanNodeDefinition; +use Symfony\Component\Config\Definition\Builder\NodeDefinition; use Symfony\Component\Config\Definition\Builder\ScalarNodeDefinition; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Form\Exception\InvalidConfigurationException; -use ToolboxBundle\Calculator\Bootstrap4\ColumnCalculator; -use ToolboxBundle\Calculator\Bootstrap4\SlideColumnCalculator; +use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use ToolboxBundle\Resolver\ContextResolver; use ToolboxBundle\ToolboxConfig; @@ -20,7 +19,7 @@ public function getConfigTreeBuilder(): TreeBuilder $treeBuilder = new TreeBuilder('toolbox'); $rootNode = $treeBuilder->getRootNode(); - $this->getConfigNode($rootNode); + $this->addRootNode($rootNode); $this->addContextNode($rootNode); $rootNode @@ -41,12 +40,11 @@ public function addContextNode(ArrayNodeDefinition $rootNode): void ->children() ->append($this->buildContextSettingsNode()) ->append($this->buildFlagsConfiguration()) - ->append($this->buildAreasSection(true)) ->append($this->buildAreasSection()) - ->append($this->buildCkEditorConfigSection()) + ->append($this->buildWysiwygEditorConfigSection()) ->append($this->buildImageThumbnailSection()) - ->append($this->buildAreasAppearanceConfiguration('areas_appearance')) - ->append($this->buildAreasAppearanceConfiguration('snippet_areas_appearance')) + ->append($this->buildAreaBlockRestrictionConfiguration('areablock_restriction')) + ->append($this->buildAreaBlockRestrictionConfiguration('snippet_areablock_restriction')) ->append($this->buildAreaBlockConfiguration()) ->append($this->buildThemeConfiguration()) ->append($this->buildDataAttributeConfiguration()) @@ -56,23 +54,47 @@ public function addContextNode(ArrayNodeDefinition $rootNode): void ->end(); } - public function getConfigNode(ArrayNodeDefinition $rootNode): void + public function addRootNode(ArrayNodeDefinition $rootNode): void { $rootNode ->children() + ->append($this->buildCoreAreasConfiguration()) ->append($this->buildFlagsConfiguration()) - ->append($this->buildAreasSection(true)) ->append($this->buildAreasSection()) - ->append($this->buildCkEditorConfigSection()) + ->append($this->buildWysiwygEditorConfigSection()) ->append($this->buildImageThumbnailSection()) - ->append($this->buildAreasAppearanceConfiguration('areas_appearance')) - ->append($this->buildAreasAppearanceConfiguration('snippet_areas_appearance')) + ->append($this->buildAreaBlockRestrictionConfiguration('areablock_restriction')) + ->append($this->buildAreaBlockRestrictionConfiguration('snippet_areablock_restriction')) ->append($this->buildAreaBlockConfiguration()) ->append($this->buildThemeConfiguration()) ->append($this->buildDataAttributeConfiguration()) ->end(); } + protected function buildCoreAreasConfiguration(): ArrayNodeDefinition + { + $treeBuilder = new ArrayNodeDefinition('enabled_core_areas'); + + $treeBuilder + ->prototype('scalar') + ->defaultValue([]) + ->validate() + ->ifTrue(function ($areaName) { + return !in_array($areaName, ToolboxConfig::TOOLBOX_AREA_TYPES, true); + }) + ->then(function ($areaName) { + throw new InvalidConfigurationException(sprintf( + 'Invalid core element "%s" in toolbox "enabled_core_areas" configuration". Available types for "enabled_core_areas" are: %s', + $areaName, + implode(', ', ToolboxConfig::TOOLBOX_AREA_TYPES) + )); + }) + ->end() + ->end(); + + return $treeBuilder; + + } protected function buildContextSettingsNode(): ArrayNodeDefinition { $treeBuilder = new ArrayNodeDefinition('settings'); @@ -113,22 +135,21 @@ protected function buildFlagsConfiguration(): ArrayNodeDefinition ->addDefaultsIfNotSet() ->children() ->booleanNode('strict_column_counter')->defaultValue(false)->end() - ->booleanNode('use_dynamic_links')->defaultValue(false)->end() ->end(); return $treeBuilder; } - protected function buildCkEditorConfigSection(): ArrayNodeDefinition + protected function buildWysiwygEditorConfigSection(): ArrayNodeDefinition { - $treeBuilder = new ArrayNodeDefinition('ckeditor'); + $treeBuilder = new ArrayNodeDefinition('wysiwyg_editor'); $treeBuilder ->addDefaultsIfNotSet() ->children() ->variableNode('config')->defaultValue([])->end() - ->variableNode('global_style_sets')->defaultValue([])->end() ->arrayNode('area_editor') + ->addDefaultsIfNotSet() ->children() ->variableNode('config') ->validate()->ifEmpty()->thenUnset()->end() @@ -136,6 +157,7 @@ protected function buildCkEditorConfigSection(): ArrayNodeDefinition ->end() ->end() ->arrayNode('object_editor') + ->addDefaultsIfNotSet() ->children() ->variableNode('config') ->validate()->ifEmpty()->thenUnset()->end() @@ -158,7 +180,7 @@ protected function buildImageThumbnailSection(): ArrayNodeDefinition return $treeBuilder; } - protected function buildAreasAppearanceConfiguration(string $type): ArrayNodeDefinition + protected function buildAreaBlockRestrictionConfiguration(string $type): ArrayNodeDefinition { $treeBuilder = new ArrayNodeDefinition($type); @@ -208,17 +230,17 @@ protected function buildThemeConfiguration(): ArrayNodeDefinition $treeBuilder ->children() - ->scalarNode('layout') - ->cannotBeEmpty() - ->end() + ->scalarNode('layout')->cannotBeEmpty()->end() + ->append($this->buildHeadlessDocumentsSection()) ->scalarNode('default_layout') ->defaultValue(false) ->end() ->arrayNode('calculators') ->addDefaultsIfNotSet() + ->isRequired() ->children() - ->scalarNode('column_calculator')->defaultValue(ColumnCalculator::class)->end() - ->scalarNode('slide_calculator')->defaultValue(SlideColumnCalculator::class)->end() + ->scalarNode('column_calculator')->isRequired()->end() + ->scalarNode('slide_calculator')->isRequired()->end() ->end() ->end() ->arrayNode('grid') @@ -294,36 +316,19 @@ protected function buildDataAttributeConfiguration(): ArrayNodeDefinition return $treeBuilder; } - protected function buildAreasSection(bool $internalTypes = false): ArrayNodeDefinition + protected function buildAreasSection(): ArrayNodeDefinition { - $treeBuilder = new ArrayNodeDefinition($internalTypes ? 'areas' : 'custom_areas'); + $treeBuilder = new ArrayNodeDefinition('areas'); $treeBuilder - ->validate() - ->ifTrue(function ($v) use ($internalTypes) { - if ($internalTypes === false) { - return false; - } - - return count(array_diff(array_keys($v), ToolboxConfig::TOOLBOX_TYPES)) > 0; - }) - ->then(function ($v) { - $invalidTags = array_diff(array_keys($v), ToolboxConfig::TOOLBOX_TYPES); - - throw new InvalidConfigurationException(sprintf( - 'Invalid elements in toolbox "area" configuration: %s. to add custom areas, use the "custom_area" node. allowed tags for "area" are: %s', - implode(', ', $invalidTags), - implode(', ', ToolboxConfig::TOOLBOX_TYPES) - )); - }) - ->end() ->useAttributeAsKey('name') ->prototype('array') ->validate() ->ifTrue(function ($v) { + $tabs = $v['tabs']; - return count($tabs) > 0 && count(array_filter($v['config_elements'], function($configElement) use ($tabs) { + return count($tabs) > 0 && count(array_filter($v['config_elements'], static function($configElement) use ($tabs) { return !array_key_exists($configElement['tab'], $tabs); })) > 0; }) @@ -336,9 +341,10 @@ protected function buildAreasSection(bool $internalTypes = false): ArrayNodeDefi ->end() ->validate() ->ifTrue(function ($v) { + $tabs = $v['tabs']; - return count($tabs) === 0 && count(array_filter($v['config_elements'], function($configElement) { + return count($tabs) === 0 && count(array_filter($v['config_elements'], static function($configElement) { return $configElement['tab'] !== null; })) > 0; }) @@ -346,9 +352,33 @@ protected function buildAreasSection(bool $internalTypes = false): ArrayNodeDefi @trigger_error('Unknown configured area tabs in config_elements. No tabs have been defined', E_USER_ERROR); }) ->end() + ->beforeNormalization() + ->ifTrue(function ($v) { + foreach ($v['inline_config_elements'] ?? [] as $inlineConfigId => $inlineConfigElement) { + if ($inlineConfigElement === '<') { + return true; + } + } + return false; + }) + ->then(function ($v) { + + foreach ($v['inline_config_elements'] ?? [] as $inlineConfigId => $inlineConfigElement) { + if ($inlineConfigElement === '<') { + $v['inline_config_elements'][$inlineConfigId] = $v['config_elements'][$inlineConfigId]; + $v['config_elements'][$inlineConfigId]['inline_rendered'] = true; + } + } + + return $v; + }) + ->end() ->children() + ->booleanNode('enabled')->defaultTrue()->end() ->append($this->buildConfigElementsTabSection()) - ->append($this->buildConfigElementsSection($internalTypes)) + ->append($this->buildConfigElementsSection('config_elements')) + ->append($this->buildConfigElementsSection('inline_config_elements')) + ->append($this->buildConfigPropertyNormalizerSection()) ->variableNode('config_parameter')->end() ->end() ->end() @@ -372,31 +402,42 @@ protected function buildConfigElementsTabSection(): ArrayNodeDefinition return $treeBuilder; } - protected function buildConfigElementsSection(bool $internalTypes = false): ArrayNodeDefinition + protected function buildConfigElementsSection(string $configType = 'config_elements', ?string $parent = null): NodeDefinition { - $treeBuilder = new ArrayNodeDefinition('config_elements'); + if ($parent === 'config_elements') { + return (new BooleanNodeDefinition($configType))->defaultFalse()->cannotBeOverwritten(); + } - if ($internalTypes === true) { - //@todo: get them dynamically!! - $allowedTypes = array_merge(ToolboxConfig::CORE_TYPES, ToolboxConfig::CUSTOM_TYPES); + $treeBuilder = new ArrayNodeDefinition($configType); - $typeNode = new EnumNodeDefinition('type'); - $typeNode->isRequired()->values($allowedTypes)->end(); - } else { - $typeNode = new ScalarNodeDefinition('type'); - $typeNode->isRequired()->end(); - } + $typeNode = new ScalarNodeDefinition('type'); + $typeNode->isRequired()->end(); $treeBuilder ->useAttributeAsKey('name') ->prototype('array') + ->validate() + ->ifTrue(function ($v) { + return $v['type'] !== 'block' && is_array($v['children']) && count($v['children']) > 0; + }) + ->then(function($v) { + @trigger_error(sprintf('Type "%s" cannot have child elements', $v['type']), E_USER_ERROR); + }) + ->end() ->addDefaultsIfNotSet() ->children() ->append($typeNode) ->scalarNode('title')->defaultValue(null)->end() ->scalarNode('description')->defaultValue(null)->end() + ->scalarNode('property_normalizer')->defaultValue(null)->end() ->scalarNode('tab')->defaultValue(null)->end() ->variableNode('config')->defaultValue([])->end() + ->booleanNode('inline_rendered')->cannotBeOverwritten()->defaultFalse()->end() + ->append( + $parent !== null + ? (new BooleanNodeDefinition($configType))->defaultFalse()->cannotBeOverwritten() + : $this->buildConfigElementsSection('children', $configType) + ) ->end() ->validate() ->ifTrue(function ($v) { @@ -411,4 +452,42 @@ protected function buildConfigElementsSection(bool $internalTypes = false): Arra return $treeBuilder; } + + protected function buildConfigPropertyNormalizerSection(): ArrayNodeDefinition + { + $treeBuilder = new ArrayNodeDefinition('additional_property_normalizer'); + + $treeBuilder + ->useAttributeAsKey('name') + ->prototype('scalar')->end(); + + return $treeBuilder; + } + + protected function buildHeadlessDocumentsSection(): ArrayNodeDefinition + { + $treeBuilder = new ArrayNodeDefinition('headless_documents'); + + $treeBuilder + ->prototype('array') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('name')->defaultValue(null)->end() + ->arrayNode('areas') + ->useAttributeAsKey('name') + ->prototype('array') + ->children() + ->enumNode('type')->values(['areablock', 'area'])->isRequired()->end() + ->scalarNode('areaType')->defaultNull()->end() + ->end() + ->end() + ->end() + ->end() + ->canBeUnset() + ->canBeDisabled() + ->treatnullLike(['enabled' => false]) + ->end(); + + return $treeBuilder; + } } diff --git a/src/ToolboxBundle/DependencyInjection/ToolboxExtension.php b/src/ToolboxBundle/DependencyInjection/ToolboxExtension.php index 7f69e756..19bf87c8 100644 --- a/src/ToolboxBundle/DependencyInjection/ToolboxExtension.php +++ b/src/ToolboxBundle/DependencyInjection/ToolboxExtension.php @@ -8,89 +8,63 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\FileLocator; use ToolboxBundle\Manager\ConfigManager; +use ToolboxBundle\Manager\LayoutManagerInterface; use ToolboxBundle\Resolver\ContextResolver; class ToolboxExtension extends Extension implements PrependExtensionInterface { - protected array $contextMergeData = []; - protected array $contextConfigData = []; - public function prepend(ContainerBuilder $container): void { - $selfConfigs = $container->getExtensionConfig($this->getAlias()); + $hasTheme = false; + $headlessAware = false; - $rootConfigs = []; - foreach ($selfConfigs as $rootConfig) { - unset($rootConfig['context'], $rootConfig['context_resolver']); - $rootConfigs[] = $rootConfig; + $wysiwygEditor = null; + if ($container->hasExtension('pimcore_tinymce') === true) { + $wysiwygEditor = 'tiny_mce'; } - $contextMerge = []; - foreach ($selfConfigs as $config) { - if (isset($config['context'])) { - foreach ($config['context'] as $contextName => $contextConfig) { - if (isset($contextConfig['settings']['merge_with_root'])) { - $contextMerge[$contextName] = $contextConfig['settings']['merge_with_root']; - } - } - } - } + $coreLoader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); + $coreLoader->load('config.yaml'); - $data = []; + $loaded = []; - //get context data - foreach ($selfConfigs as $config) { - if (isset($config['context'])) { - foreach ($config['context'] as $contextName => $contextConfig) { - if (!isset($contextMerge[$contextName]) || $contextMerge[$contextName] !== true) { - continue; - } - - $cleanContextConfig = $contextConfig; - unset($cleanContextConfig['settings']); - $this->contextConfigData[$contextName][] = $cleanContextConfig; - } + foreach ($container->getExtensionConfig($this->getAlias()) as $toolboxConfigNode) { + + if (!empty($toolboxConfigNode['theme']['layout'])) { + $hasTheme = true; + $headlessAware = $toolboxConfigNode['theme']['layout'] === LayoutManagerInterface::TOOLBOX_LAYOUT_HEADLESS; } - } - //get context merge data - foreach ($contextMerge as $contextName => $merge) { - if ($merge === false) { + if (($toolboxConfigNode['enabled_core_areas'] ?? null) === null) { continue; } - foreach ($rootConfigs as $rootConfig) { - $data[] = [ - 'context' => [ - $contextName => $rootConfig - ] - ]; + foreach ($toolboxConfigNode['enabled_core_areas'] as $areaName) { + + if (in_array($areaName, $loaded, true)) { + continue; + } + + $coreLoader->load(sprintf('core_areas/%s.yaml', $areaName)); + $loaded[] = $areaName; } } - $this->contextMergeData = $data; + // add default theme (b4) if not set + if ($hasTheme === false) { + $coreLoader->load('theme/bootstrap4_theme.yaml'); + } + + $container->setParameter('toolbox.wysiwyg_editor', $wysiwygEditor); + $container->setParameter('toolbox.headless_aware', $headlessAware); } public function load(array $configs, ContainerBuilder $container): void { - //append merge data - foreach ($this->contextMergeData as $append) { - $configs[] = $append; - } - - //append custom context data - foreach ($this->contextConfigData as $contextName => $contextConfigs) { - foreach ($contextConfigs as $el) { - $configs[] = [ - 'context' => [ - $contextName => $el - ] - ]; - } - } + $contextAwareConfigs = $this->parseContextConfigs($configs); $configuration = new Configuration(); - $config = $this->processConfiguration($configuration, $configs); + $config = $this->processConfiguration($configuration, $contextAwareConfigs); $this->validateToolboxContextConfig($config); $this->allocateGoogleMapsApiKey($container); @@ -99,7 +73,7 @@ public function load(array $configs, ContainerBuilder $container): void unset($config['context_resolver']); $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); - $loader->load('services.yml'); + $loader->load('services.yaml'); $configManagerDefinition = $container->getDefinition(ConfigManager::class); $configManagerDefinition->addMethodCall('setConfig', [$config]); @@ -115,14 +89,14 @@ private function determinateConfigDialogAwareBricks(array $config): array { $configDialogAwareBricks = []; - foreach ($config['custom_areas'] as $areaId => $areaSection) { + foreach ($config['areas'] as $areaId => $areaSection) { if (isset($areaSection['config_elements']) && count($areaSection['config_elements']) > 0) { $configDialogAwareBricks[] = $areaId; } } foreach ($config['context'] as $context) { - foreach ($context['custom_areas'] as $areaId => $areaSection) { + foreach ($context['areas'] as $areaId => $areaSection) { if (isset($areaSection['config_elements']) && count($areaSection['config_elements']) > 0) { $configDialogAwareBricks[] = $areaId; } @@ -137,20 +111,25 @@ private function allocateGoogleMapsApiKey(ContainerBuilder $container): void $googleBrowserApiKey = null; $googleSimpleApiKey = null; - $pimcoreCoreConfig = $container->getParameter('pimcore.config'); + $pimcoreGoogleBrowserApiKey = null; + $pimcoreGoogleSimpleApiKey = null; + /** @phpstan-ignore-next-line */ - $pimcoreGoogleServiceConfig = $pimcoreCoreConfig['services']['google'] ?? []; + if ($container->hasParameter('pimcore_google_marketing')) { + $pimcoreGoogleMarketingSettings = $container->getParameter('pimcore_google_marketing'); + /** @phpstan-ignore-next-line */ + $pimcoreGoogleBrowserApiKey = $pimcoreGoogleMarketingSettings['browser_api_key'] ?? null; + /** @phpstan-ignore-next-line */ + $pimcoreGoogleSimpleApiKey = $pimcoreGoogleMarketingSettings['simple_api_key'] ?? null; + } // browser api key /** @phpstan-ignore-next-line */ - if ($container->hasParameter('pimcore_system_config.services.google.browserapikey')) { - $googleBrowserApiKey = $container->getParameter('pimcore_system_config.services.google.browserapikey'); - /** @phpstan-ignore-next-line */ - } elseif ($container->hasParameter('toolbox_google_service_browser_api_key')) { + if ($container->hasParameter('toolbox_google_service_browser_api_key')) { $googleBrowserApiKey = $container->getParameter('toolbox_google_service_browser_api_key'); /** @phpstan-ignore-next-line */ - } elseif (isset($pimcoreGoogleServiceConfig['browser_api_key'])) { - $googleBrowserApiKey = $pimcoreGoogleServiceConfig['browser_api_key']; + } elseif ($pimcoreGoogleBrowserApiKey !== null) { + $googleBrowserApiKey = $pimcoreGoogleBrowserApiKey; } //simple api key @@ -161,8 +140,8 @@ private function allocateGoogleMapsApiKey(ContainerBuilder $container): void } elseif ($container->hasParameter('toolbox_google_service_simple_api_key')) { $googleSimpleApiKey = $container->getParameter('toolbox_google_service_simple_api_key'); /** @phpstan-ignore-next-line */ - } elseif (isset($pimcoreGoogleServiceConfig['simple_api_key'])) { - $googleSimpleApiKey = $pimcoreGoogleServiceConfig['simple_api_key']; + } elseif ($pimcoreGoogleSimpleApiKey !== null) { + $googleSimpleApiKey = $pimcoreGoogleSimpleApiKey; } $container->setParameter('toolbox.google_maps.browser_api_key', $googleBrowserApiKey); @@ -183,4 +162,83 @@ private function validateToolboxContextConfig(array $config): void } } } + + private function parseContextConfigs(array $configs): array + { + $data = []; + $rootConfigs = []; + $contextConfigData = []; + $contextMergeCandidates = []; + + foreach ($configs as $rootConfig) { + unset($rootConfig['context'], $rootConfig['context_resolver'], $rootConfig['enabled_core_areas']); + $rootConfigs[] = $rootConfig; + } + + foreach ($configs as $config) { + + if (!isset($config['context'])) { + continue; + } + + foreach ($config['context'] as $contextName => $contextConfig) { + $contextMergeCandidates[$contextName] = $contextConfig['settings']['merge_with_root'] ?? false; + } + } + + //get context data + foreach ($configs as $config) { + + if (!isset($config['context'])) { + continue; + } + + foreach ($config['context'] as $contextName => $contextConfig) { + + if ($contextMergeCandidates[$contextName] === false) { + continue; + } + + $cleanContextConfig = $contextConfig; + + unset($cleanContextConfig['settings']); + + $contextConfigData[$contextName][] = $cleanContextConfig; + } + } + + // get context merge data + foreach ($contextMergeCandidates as $contextName => $merge) { + + if ($merge === false) { + continue; + } + + foreach ($rootConfigs as $rootConfig) { + $data[] = [ + 'context' => [ + $contextName => $rootConfig + ] + ]; + } + } + + // append merge data + foreach ($data as $append) { + $configs[] = $append; + } + + // append custom context data + foreach ($contextConfigData as $contextName => $contextConfigs) { + foreach ($contextConfigs as $el) { + $configs[] = [ + 'context' => [ + $contextName => $el + ] + ]; + } + } + + return $configs; + } } diff --git a/src/ToolboxBundle/Document/Areabrick/AbstractAreabrick.php b/src/ToolboxBundle/Document/Areabrick/AbstractAreabrick.php index 1297f9bb..66b90fb7 100644 --- a/src/ToolboxBundle/Document/Areabrick/AbstractAreabrick.php +++ b/src/ToolboxBundle/Document/Areabrick/AbstractAreabrick.php @@ -6,6 +6,9 @@ use Pimcore\Extension\Document\Areabrick\EditableDialogBoxInterface; use Pimcore\Model\Document; use ToolboxBundle\Builder\BrickConfigBuilderInterface; +use ToolboxBundle\Document\Response\HeadlessResponse; +use ToolboxBundle\Event\HeadlessEditableActionEvent; +use ToolboxBundle\ToolboxEvents; abstract class AbstractAreabrick extends AbstractBaseAreabrick implements EditableDialogBoxInterface { @@ -16,11 +19,31 @@ public function setBrickConfigBuilder(BrickConfigBuilderInterface $brickConfigBu $this->brickConfigBuilder = $brickConfigBuilder; } - public function getEditableDialogBoxConfiguration(Document\Editable $area, ?Document\Editable\Area\Info $info): EditableDialogBoxConfiguration + public function headlessAction(Document\Editable\Area\Info $info, HeadlessResponse $headlessResponse): void { - $configNode = $this->getConfigManager()->getAreaConfig($this->getId()); - $themeOptions = $this->getConfigManager()->getConfig('theme'); + parent::headlessAction($info, $headlessResponse); + + $headlessResponse->setConfigElementData( + $this->brickConfigBuilder->buildConfigurationData( + $info, + $this->getId(), + $this->getAreaConfig(), + $this->getAreaThemeOptions(), + $this->isHeadlessLayoutAware() + ) + ); + + $this->triggerHeadlessEditableActionEvent($info, $headlessResponse); + } - return $this->brickConfigBuilder->buildDialogBoxConfiguration($info, $this->getId(), $configNode, $themeOptions); + public function getEditableDialogBoxConfiguration(Document\Editable $area, ?Document\Editable\Area\Info $info): EditableDialogBoxConfiguration + { + return $this->brickConfigBuilder->buildConfiguration( + $info, + $this->getId(), + $this->getAreaConfig(), + $this->getAreaThemeOptions(), + $this->isHeadlessLayoutAware() + ); } } diff --git a/src/ToolboxBundle/Document/Areabrick/AbstractBaseAreabrick.php b/src/ToolboxBundle/Document/Areabrick/AbstractBaseAreabrick.php index b3addfa4..58970214 100644 --- a/src/ToolboxBundle/Document/Areabrick/AbstractBaseAreabrick.php +++ b/src/ToolboxBundle/Document/Areabrick/AbstractBaseAreabrick.php @@ -4,70 +4,166 @@ use Pimcore\Extension\Document\Areabrick\AbstractAreabrick as PimcoreAbstractAreabrick; use Pimcore\Model\Document; +use Pimcore\Model\Document\PageSnippet; use Symfony\Component\HttpFoundation\Response; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use ToolboxBundle\Builder\InlineConfigBuilderInterface; +use ToolboxBundle\Document\Response\HeadlessResponse; +use ToolboxBundle\Event\HeadlessEditableActionEvent; use ToolboxBundle\Manager\ConfigManagerInterface; -use ToolboxBundle\Manager\LayoutManager; +use ToolboxBundle\Manager\LayoutManagerInterface; +use ToolboxBundle\ToolboxEvents; abstract class AbstractBaseAreabrick extends PimcoreAbstractAreabrick { public const AREABRICK_TYPE_INTERNAL = 'internal'; public const AREABRICK_TYPE_EXTERNAL = 'external'; + protected ConfigManagerInterface $configManager; - protected LayoutManager $layoutManager; + protected LayoutManagerInterface $layoutManager; + protected InlineConfigBuilderInterface $inlineConfigBuilder; + protected EventDispatcherInterface $eventDispatcher; + protected string $areaBrickType = 'internal'; + protected ?array $areaConfig = null; + protected ?array $areaThemeConfig = null; + protected ?array $areaThemeOptions = null; - public function setAreaBrickType(string $type = self::AREABRICK_TYPE_INTERNAL): void + public function action(Document\Editable\Area\Info $info): ?Response { - $this->areaBrickType = $type; + $info->setParams( + array_merge( + $info->getParams(), + [ + 'areaId' => $this->getId(), + 'areaTemplateDirectory' => $this->getTemplateDirectoryName(), + 'additionalClassesData' => $this->configureAdditionalClasses($info), + 'elementThemeConfig' => $this->getAreaThemeConfig(), + ] + ) + ); + + $this->checkInlineConfigElements($info); + + return null; } - public function getAreaBrickType(): string + public function headlessAction(Document\Editable\Area\Info $info, HeadlessResponse $headlessResponse): void { - return $this->areaBrickType; + $configNode = $this->getAreaConfig(); + $themeOptions = $this->getAreaThemeOptions(); + + $headlessResponse->setBrickConfiguration([ + 'areaId' => $this->getId(), + 'additionalClassesData' => $this->configureAdditionalClasses($info), + ]); + + $headlessResponse->setInlineConfigElementData( + $this->inlineConfigBuilder->buildInlineConfigurationData( + $info, + $this->getId(), + $configNode, + $themeOptions + ) + ); + + if (!$this instanceof AbstractAreabrick) { + $this->triggerHeadlessEditableActionEvent($info, $headlessResponse); + } + } - public function setConfigManager(ConfigManagerInterface $configManager): void + public function getTemplateDirectoryName(): string { - $this->configManager = $configManager; + return $this->getId(); } - public function getConfigManager(): ConfigManagerInterface + public function getTemplatePath(string $viewName = 'view'): string { - $space = $this->getAreaBrickType() === self::AREABRICK_TYPE_INTERNAL - ? ConfigManagerInterface::AREABRICK_NAMESPACE_INTERNAL - : ConfigManagerInterface::AREABRICK_NAMESPACE_EXTERNAL; + return $this->layoutManager->getAreaTemplatePath($this->getId(), $this->getTemplateDirectoryName(), $viewName); + } + + public function getTemplateLocation(): string + { + if ($this->getAreaBrickType() === self::AREABRICK_TYPE_INTERNAL) { + return static::TEMPLATE_LOCATION_BUNDLE; + } - return $this->configManager->setAreaNameSpace($space); + return static::TEMPLATE_LOCATION_GLOBAL; } - public function setLayoutManager(LayoutManager $layoutManager): void + public function getTemplate(): ?string { - $this->layoutManager = $layoutManager; + return null; } - public function action(Document\Editable\Area\Info $info): ?Response + public function getTemplateSuffix(): string { - $configNode = $this->getConfigManager()->getAreaConfig($this->getId()); + return static::TEMPLATE_SUFFIX_TWIG; + } - $info->setParams(array_merge($info->getParams(), [ - 'additionalClassesData' => $this->configureAdditionalClasses($info, $configNode), - 'elementThemeConfig' => $this->layoutManager->getAreaThemeConfig($this->getId()), - 'areaId' => $this->getId(), - 'areaTemplateDirectory' => $this->getTemplateDirectoryName(), - ])); + public function getIcon(): ?string + { + if ($this->getAreaBrickType() === self::AREABRICK_TYPE_EXTERNAL) { + return null; + } - return null; + return '/bundles/toolbox/areas/' . $this->getTemplateDirectoryName() . '/icon.svg'; + } + + public function getHtmlTagOpen(Document\Editable\Area\Info $info): string + { + return ''; } - private function configureAdditionalClasses(Document\Editable\Area\Info $info, array $configNode): array + public function getHtmlTagClose(Document\Editable\Area\Info $info): string + { + return ''; + } + + public function isHeadlessLayoutAware(): bool + { + $themeConfig = $this->getAreaThemeConfig(); + + return $themeConfig['layout'] === LayoutManagerInterface::TOOLBOX_LAYOUT_HEADLESS; + } + + + private function checkInlineConfigElements(Document\Editable\Area\Info $info): void + { + $areaConfig = $this->getAreaConfig(); + $areaThemeOptions = $this->getAreaThemeOptions(); + + if ($this->isHeadlessLayoutAware() === false) { + return; + } + + if ($info->getEditable()?->getEditmode() === false) { + return; + } + + $info->setParam( + 'inlineConfigElements', + $this->inlineConfigBuilder->buildInlineConfiguration( + $info, + $this->getId(), + $areaConfig, + $areaThemeOptions, + true + ) + ); + } + + private function configureAdditionalClasses(Document\Editable\Area\Info $info): array { $classesArray = []; + $areaConfig = $this->getAreaConfig(); - if (!isset($configNode['config_elements'])) { + if (!isset($areaConfig['config_elements'])) { return $classesArray; } - foreach ($configNode['config_elements'] as $name => $configElement) { + foreach ($areaConfig['config_elements'] as $name => $configElement) { if (!isset($configElement['type'])) { continue; } @@ -90,51 +186,78 @@ private function configureAdditionalClasses(Document\Editable\Area\Info $info, a return $classesArray; } - public function getTemplateDirectoryName(): string + protected function triggerHeadlessEditableActionEvent(Document\Editable\Area\Info $info, HeadlessResponse $headlessResponse): void { - return $this->getId(); + $this->eventDispatcher->dispatch( + new HeadlessEditableActionEvent($info, $headlessResponse, function (PageSnippet $document, string $type, string $inputName, array $options = []) { + return $this->getDocumentEditable($document, $type, $inputName, $options); + }), + ToolboxEvents::HEADLESS_EDITABLE_ACTION + ); } - public function getTemplatePath(string $viewName = 'view'): string + protected function getAreaConfigNode(string $node, string $configProperty): mixed { - return $this->layoutManager->getAreaTemplatePath($this->getId(), $this->getTemplateDirectoryName(), $viewName); + $config = $this->getAreaConfig(); + + if (isset($config['config_elements'][$node]['config'][$configProperty])) { + return $config['config_elements'][$node]['config'][$configProperty]; + } + + if (isset($config['inline_config_elements'][$node]['config'][$configProperty])) { + return $config['inline_config_elements'][$node]['config'][$configProperty]; + } + + return null; } - public function getTemplateLocation(): string + protected function getAreaConfig(): array { - if ($this->getAreaBrickType() === self::AREABRICK_TYPE_INTERNAL) { - return static::TEMPLATE_LOCATION_BUNDLE; - } + return $this->areaConfig ?? ($this->areaConfig = $this->getConfigManager()->getAreaConfig($this->getId())); + } - return static::TEMPLATE_LOCATION_GLOBAL; + protected function getAreaThemeConfig(): array + { + return $this->areaThemeConfig ?? ($this->areaThemeConfig = $this->layoutManager->getAreaThemeConfig($this->getId())); } - public function getTemplate() + protected function getAreaThemeOptions(): array { - return null; + return $this->areaThemeOptions ?? ($this->areaThemeOptions = $this->getConfigManager()->getConfig('theme')); } - public function getTemplateSuffix() + public function setAreaBrickType(string $type = self::AREABRICK_TYPE_INTERNAL): void { - return static::TEMPLATE_SUFFIX_TWIG; + $this->areaBrickType = $type; } - public function getIcon(): ?string + public function getAreaBrickType(): string { - if ($this->getAreaBrickType() === self::AREABRICK_TYPE_EXTERNAL) { - return null; - } + return $this->areaBrickType; + } - return '/bundles/toolbox/areas/' . $this->getTemplateDirectoryName() . '/icon.svg'; + public function setConfigManager(ConfigManagerInterface $configManager): void + { + $this->configManager = $configManager; } - public function getHtmlTagOpen(Document\Editable\Area\Info $info): string + public function getConfigManager(): ConfigManagerInterface { - return ''; + return $this->configManager; } - public function getHtmlTagClose(Document\Editable\Area\Info $info): string + public function setLayoutManager(LayoutManagerInterface $layoutManager): void { - return ''; + $this->layoutManager = $layoutManager; + } + + public function setInlineConfigBuilder(InlineConfigBuilderInterface $inlineConfigBuilder): void + { + $this->inlineConfigBuilder = $inlineConfigBuilder; + } + + public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void + { + $this->eventDispatcher = $eventDispatcher; } } diff --git a/src/ToolboxBundle/Document/Areabrick/Accordion/Accordion.php b/src/ToolboxBundle/Document/Areabrick/Accordion/Accordion.php deleted file mode 100644 index b6019d1a..00000000 --- a/src/ToolboxBundle/Document/Areabrick/Accordion/Accordion.php +++ /dev/null @@ -1,45 +0,0 @@ -getParams(); - if (isset($infoParams['toolboxAccordionId'])) { - $id = $infoParams['toolboxAccordionId']; - } else { - $id = str_replace('.', '', uniqid('accordion-', true)); - } - - $info->setParam('id', $id); - - return null; - } - - /** - * @return string - */ - public function getName() - { - return 'Accordion'; - } - - /** - * @return string - */ - public function getDescription() - { - return 'Toolbox Accordion / Tabs'; - } -} diff --git a/src/ToolboxBundle/Document/Areabrick/Anchor/Anchor.php b/src/ToolboxBundle/Document/Areabrick/Anchor/Anchor.php deleted file mode 100644 index 455e5312..00000000 --- a/src/ToolboxBundle/Document/Areabrick/Anchor/Anchor.php +++ /dev/null @@ -1,34 +0,0 @@ -getParams(); - $id = $infoParams['toolboxGalleryId'] ?? str_replace('.', '', uniqid('gallery-', true)); - - /** @var Relations $imagesField */ - $imagesField = $this->getDocumentEditable($info->getDocument(), 'relations', 'images'); - - $info->setParams(array_merge($info->getParams(), [ - 'galleryId' => $id, - 'images' => $this->getAssetArray($imagesField->getElements()) - ])); - - return null; - } - - public function getName(): string - { - return 'Gallery'; - } - - public function getDescription(): string - { - return 'Toolbox Gallery'; - } - - public function getAssetArray(array $data): array - { - if (empty($data)) { - return []; - } - - $assets = []; - - foreach ($data as $element) { - if ($element instanceof Asset\Image) { - $assets[] = $element; - } elseif ($element instanceof Asset\Folder) { - foreach ($element->getChildren() as $child) { - if ($child instanceof Asset\Image) { - $assets[] = $child; - } - } - } - } - - return $assets; - } -} diff --git a/src/ToolboxBundle/Document/Areabrick/GoogleMap/GoogleMap.php b/src/ToolboxBundle/Document/Areabrick/GoogleMap/GoogleMap.php deleted file mode 100644 index a4d4a022..00000000 --- a/src/ToolboxBundle/Document/Areabrick/GoogleMap/GoogleMap.php +++ /dev/null @@ -1,46 +0,0 @@ -googleMapsHostUrl = $googleMapsHostUrl; - } - - public function action(Info $info): ?Response - { - parent::action($info); - - $info->setParam('googleMapsHostUrl', $this->googleMapsHostUrl); - - return null; - } - - public function getTemplateDirectoryName(): string - { - return 'google-map'; - } - - public function getTemplate(): string - { - return sprintf('@Toolbox/areas/%s/view.%s', $this->getTemplateDirectoryName(), $this->getTemplateSuffix()); - } - - public function getName(): string - { - return 'Google Map'; - } - - public function getDescription(): string - { - return 'Toolbox Google Map'; - } -} diff --git a/src/ToolboxBundle/Document/Areabrick/Headline/Headline.php b/src/ToolboxBundle/Document/Areabrick/Headline/Headline.php deleted file mode 100644 index 6af8a2cd..00000000 --- a/src/ToolboxBundle/Document/Areabrick/Headline/Headline.php +++ /dev/null @@ -1,39 +0,0 @@ -getDocumentEditable($info->getDocument(), 'input', 'anchor_name'); - - if (!$anchorNameElement->isEmpty()) { - $anchorName = File::getValidFilename($anchorNameElement->getData()); - } - - $info->setParam('anchorName', $anchorName); - - return null; - } - - public function getName() - { - return 'Headline'; - } - - public function getDescription() - { - return 'Toolbox Headline'; - } -} diff --git a/src/ToolboxBundle/Document/Areabrick/Image/Image.php b/src/ToolboxBundle/Document/Areabrick/Image/Image.php deleted file mode 100644 index 9f48e294..00000000 --- a/src/ToolboxBundle/Document/Areabrick/Image/Image.php +++ /dev/null @@ -1,25 +0,0 @@ -editmodeResolver->isEditmode(); + + // in edit mode, render everything like pimcore want us to + if ($editMode === true) { + return parent::renderAreaFrontend($info, $templateParams); + } + + // check, if brick is headless aware in the first place + $brick = $this->brickManager->getBrick($info->getId()); + if (!$brick instanceof ToolboxHeadlessAwareBrickInterface) { + return parent::renderAreaFrontend($info, $templateParams); + } + + // check if theme config is available. if so, we only allow headless layouts + if ($brick->isHeadlessLayoutAware() === false) { + return parent::renderAreaFrontend($info, $templateParams); + } + + $request = $this->requestHelper->getCurrentRequest(); + $brickInfoRestoreValue = $request->attributes->get(self::ATTRIBUTE_AREABRICK_INFO); + $request->attributes->set(self::ATTRIBUTE_AREABRICK_INFO, $info); + + $info->setRequest($request); + + $headlessResponse = new HeadlessResponse(HeadlessResponse::TYPE_BRICK); + + $brick->headlessAction($info, $headlessResponse); + + \Pimcore::getContainer()->get(EditableWorker::class)->processBrick($headlessResponse, $brick); + + if ($brickInfoRestoreValue === null) { + $request->attributes->remove(self::ATTRIBUTE_AREABRICK_INFO); + } else { + $request->attributes->set(self::ATTRIBUTE_AREABRICK_INFO, $brickInfoRestoreValue); + } + + // just return nothing + + return ''; + } + + protected function getBlockState(): BlockState + { + return $this->getBlockStateStack()->getCurrentState(); + } + + protected function getBlockStateStack(): BlockStateStack + { + return \Pimcore::getContainer()->get(BlockStateStack::class); + } +} diff --git a/src/ToolboxBundle/Document/Editable/EditableJsonFetcher.php b/src/ToolboxBundle/Document/Editable/EditableJsonFetcher.php new file mode 100644 index 00000000..913d9b35 --- /dev/null +++ b/src/ToolboxBundle/Document/Editable/EditableJsonFetcher.php @@ -0,0 +1,91 @@ +registerEventSubscriber(); + + ob_start(); + + foreach ($editables as $editable) { + + try { + $this->editableRenderer->getEditable($document, $editable['type'], $editable['name'], $editable['config'], $editMode)->render(); + } catch (\Throwable $e) { + $error = $e; + } + } + + ob_end_clean(); + + $jsonEditables = $error !== null ? [] : $this->subscriber->getJsonEditables(); + + $this->unregisterEventSubscriber(); + + if ($error !== null) { + throw $error; + } + + return $jsonEditables; + } + + public function fetchEditableAsArray(Document $document, string $editableType, string $editableName, array $editableConfig, bool $editMode): array + { + $error = null; + $this->registerEventSubscriber(); + + ob_start(); + + try { + $this->editableRenderer->getEditable($document, $editableType, $editableName, $editableConfig, $editMode)->render(); + } catch (\Throwable $e) { + $error = $e; + } + + ob_end_clean(); + + $jsonEditables = $error !== null ? [] : $this->subscriber->getJsonEditables(); + + $this->unregisterEventSubscriber(); + + if ($error !== null) { + throw $error; + } + + return $jsonEditables; + } + + private function registerEventSubscriber(): void + { + if (!$this->subscriber) { + $this->subscriber = new EditableJsonSubscriber(); + $this->eventDispatcher->addSubscriber($this->subscriber); + } + } + + private function unregisterEventSubscriber(): void + { + if ($this->subscriber) { + $this->eventDispatcher->removeSubscriber($this->subscriber); + $this->subscriber = null; + } + } +} diff --git a/src/ToolboxBundle/Document/Editable/EditableJsonSubscriber.php b/src/ToolboxBundle/Document/Editable/EditableJsonSubscriber.php new file mode 100644 index 00000000..9db2b5ad --- /dev/null +++ b/src/ToolboxBundle/Document/Editable/EditableJsonSubscriber.php @@ -0,0 +1,118 @@ + 'onHeadlessElementAdd', + ]; + } + + public function onHeadlessElementAdd(HeadlessElementEvent $event): void + { + $this->jsonEditables[$event->getElementNamespace()] = [$event->getElementType(), $event->getElementSubType(), $event->getData()]; + } + + public function getJsonEditables(): array + { + $convertedEditables = $this->convertNestedArray($this->jsonEditables); + + $this->sortNestedArray($convertedEditables); + $this->simplifyNestedArray($convertedEditables); + + return $convertedEditables; + } + + private function convertNestedArray($flatArray): array + { + $nestedArray = []; + + foreach ($flatArray as $key => $value) { + + $keys = explode(':', $key); + $currentArray = &$nestedArray; + + foreach ($keys as $nestedKey) { + /** @phpstan-ignore-next-line */ + if (!isset($currentArray[self::ELEMENTS_IDENTIFIER][$nestedKey])) { + $currentArray[self::ELEMENTS_IDENTIFIER][$nestedKey] = []; + } + + $currentArray = &$currentArray[self::ELEMENTS_IDENTIFIER][$nestedKey]; + } + + $currentArray[self::ELEMENT_TYPE_IDENTIFIER] = $value[0]; + $currentArray[self::ELEMENT_SUB_TYPE_IDENTIFIER] = $value[1]; + $currentArray[self::ELEMENT_DATA_IDENTIFIER] = $value[2]; + } + + /** @phpstan-ignore-next-line */ + return $nestedArray[self::ELEMENTS_IDENTIFIER] ?? []; + } + + private function simplifyNestedArray(&$array): void + { + if (!is_array($array)) { + return; + } + + foreach ($array as &$value) { + + if ( + is_array($value) && + count($value) === 1 && + isset($value[self::ELEMENTS_IDENTIFIER]) && + !array_is_list($value[self::ELEMENTS_IDENTIFIER]) + ) { + $value = $value[self::ELEMENTS_IDENTIFIER]; + } + + $this->simplifyNestedArray($value); + } + } + + private function sortNestedArray(&$array): void + { + if (!is_array($array)) { + return; + } + + foreach ($array as &$item) { + + if (!is_array($item)) { + continue; + } + + if (isset($item[self::ELEMENTS_IDENTIFIER]) && is_array($item[self::ELEMENTS_IDENTIFIER])) { + $isNumericKeyedArray = array_unique(array_map('is_numeric', array_keys($item[self::ELEMENTS_IDENTIFIER]))) === [true]; + if ($isNumericKeyedArray) { + $item[self::ELEMENTS_IDENTIFIER] = array_values($item[self::ELEMENTS_IDENTIFIER]); + } + } + + $this->sortNestedArray($item); + + if (isset($item[self::ELEMENTS_IDENTIFIER])) { + $elements = $item[self::ELEMENTS_IDENTIFIER]; + unset($item[self::ELEMENTS_IDENTIFIER]); + $item[self::ELEMENTS_IDENTIFIER] = $elements; + } + } + } +} diff --git a/src/ToolboxBundle/Document/Editable/EditableWorker.php b/src/ToolboxBundle/Document/Editable/EditableWorker.php new file mode 100644 index 00000000..c54faa57 --- /dev/null +++ b/src/ToolboxBundle/Document/Editable/EditableWorker.php @@ -0,0 +1,157 @@ +dispatch([ + 'elementType' => $data->getType(), + 'elementSubType' => $areabrick->getId(), + 'elementNamespace' => $this->buildBrickNamespace(), + 'data' => $this->processBrickData($data, $areabrick->getId()) + ]); + } + + public function processEditable(HeadlessResponse $data, Editable $editable): void + { + $this->dispatch([ + 'elementType' => $data->getType(), + 'elementSubType' => $editable->getType(), + 'elementNamespace' => $this->buildEditableNamespace($editable), + 'data' => $this->processEditableData($data) + ]); + } + + private function dispatch(array $arguments): void + { + $this->eventDispatcher->dispatch( + new HeadlessElementEvent(...$arguments), + ToolboxEvents::HEADLESS_ELEMENT_STACK_ADD + ); + } + + private function buildEditableNamespace(Editable $editable): string + { + return str_replace('.', ':', $editable->getName()); + } + + private function buildBrickNamespace(): string + { + $indexes = $this->getBlockState()->getIndexes(); + $blocks = $this->getBlockState()->getBlocks(); + + $parts = []; + for ($i = 0, $iMax = count($blocks); $i < $iMax; $i++) { + $part = $blocks[$i]->getRealName(); + if (isset($indexes[$i])) { + $part = sprintf('%s:%d', $part, $indexes[$i]); + } + + $parts[] = $part; + } + + return implode(':', $parts); + } + + private function processBrickData(HeadlessResponse $data, string $areaName): array + { + return [ + 'configuration' => $data->getBrickConfiguration(), + 'data' => $this->processElementData($data, $areaName) + ]; + } + + private function processEditableData(HeadlessResponse $data): array + { + $parentAreaName = $data->getParent(); + + return [ + 'data' => $parentAreaName === null ? $data->getInlineConfigElementData() : $this->processElementData($data, $parentAreaName) + ]; + } + + private function processElementData(HeadlessResponse $data, string $areaName): array + { + $normalizedData = []; + $brickConfig = $this->configManager->getAreaConfig($areaName); + + $configBlocks = [ + 'config_elements' => $data->getConfigElementData(), + 'inline_config_elements' => $data->getInlineConfigElementData(), + 'additional_property_normalizer' => $data->getAdditionalConfigData(), + ]; + + foreach ($configBlocks as $configBlockName => $configBlockData) { + + $configElements = $brickConfig[$configBlockName] ?? []; + foreach ($configBlockData as $configName => $configData) { + + if ($configBlockName === 'additional_property_normalizer' && array_key_exists($configName, $configElements)) { + $configData = $this->applyNormalizer($configElements[$configName], $configData); + } elseif ($configBlockName !== 'additional_property_normalizer') { + $configNode = $this->findBrickConfigNode($configName, $configElements); + if ($configNode !== null && $configNode['property_normalizer'] !== null) { + $configData = $this->applyNormalizer($configNode['property_normalizer'], $configData); + } + } + + // not normalized, use default editable data + if ($configData instanceof Editable\EditableInterface) { + $configData = $configData->getData(); + } + + $normalizedData[$configName] = $configData; + } + } + + return $normalizedData; + } + + private function findBrickConfigNode(string $configName, array $configElements) + { + if (array_key_exists($configName, $configElements)) { + return $configElements[$configName]; + } + + foreach ($configElements as $configElement) { + if (array_key_exists('children', $configElement) && null !== $childNode = $this->findBrickConfigNode($configName, $configElement['children'])) { + return $childNode; + } + } + + return null; + } + + private function applyNormalizer(string $normalizerName, mixed $value) + { + return $this->normalizerRegistry->get($normalizerName)->normalize($value, $this->configManager->getContextIdentifier()); + } + + private function getBlockState(): BlockState + { + return $this->blockStateStack->getCurrentState(); + } +} diff --git a/src/ToolboxBundle/Document/Response/HeadlessResponse.php b/src/ToolboxBundle/Document/Response/HeadlessResponse.php new file mode 100644 index 00000000..a4f0ac0a --- /dev/null +++ b/src/ToolboxBundle/Document/Response/HeadlessResponse.php @@ -0,0 +1,106 @@ +type = $type; + $this->parent = $parent; + } + + public function getType(): string + { + return $this->type; + } + + public function getParent(): ?string + { + return $this->parent; + } + + public function getConfigElementData(): array + { + return $this->configElementData; + } + + public function getConfigElementDataItem(string $key): mixed + { + if (!array_key_exists($key, $this->configElementData)) { + return null; + } + + return $this->configElementData[$key]; + } + + public function setConfigElementData(array $configElementData): void + { + if ($this->getType() === self::TYPE_EDITABLE) { + throw new \Exception('Editables cannot contain config data'); + } + + $this->configElementData = $configElementData; + } + + public function getInlineConfigElementData(): array + { + return $this->inlineConfigElementData; + } + + public function getInlineConfigElementDataItem(string $key): mixed + { + if (!array_key_exists($key, $this->inlineConfigElementData)) { + return null; + } + + return $this->inlineConfigElementData[$key]; + } + + public function setInlineConfigElementData(array $inlineConfigElementData): void + { + $this->inlineConfigElementData = $inlineConfigElementData; + } + + public function getAdditionalConfigData(): array + { + return $this->additionalConfigData; + } + + public function setAdditionalConfigData(array $additionalConfigData): void + { + if ($this->getType() === self::TYPE_EDITABLE) { + throw new \Exception('Editables cannot contain additional config data'); + } + + $this->additionalConfigData = $additionalConfigData; + } + + public function addAdditionalConfigData(string $key, mixed $data): void + { + $this->additionalConfigData[$key] = $data; + } + + public function getBrickConfiguration(): array + { + return $this->brickConfiguration; + } + + public function setBrickConfiguration(array $brickConfiguration): void + { + $this->brickConfiguration = $brickConfiguration; + } +} diff --git a/src/ToolboxBundle/Document/SimpleAreabrick/SimpleAreaBrick.php b/src/ToolboxBundle/Document/SimpleAreabrick/SimpleAreaBrick.php index 2ba97c31..424995a3 100644 --- a/src/ToolboxBundle/Document/SimpleAreabrick/SimpleAreaBrick.php +++ b/src/ToolboxBundle/Document/SimpleAreabrick/SimpleAreaBrick.php @@ -3,8 +3,9 @@ namespace ToolboxBundle\Document\SimpleAreabrick; use ToolboxBundle\Document\Areabrick\AbstractBaseAreabrick; +use ToolboxBundle\Document\Areabrick\ToolboxHeadlessAwareBrickInterface; -class SimpleAreaBrick extends AbstractBaseAreabrick +class SimpleAreaBrick extends AbstractBaseAreabrick implements ToolboxHeadlessAwareBrickInterface { use SimpleAreaBrickTrait; } diff --git a/src/ToolboxBundle/Document/SimpleAreabrick/SimpleAreaBrickConfigurable.php b/src/ToolboxBundle/Document/SimpleAreabrick/SimpleAreaBrickConfigurable.php index 532374b9..ac03ed93 100644 --- a/src/ToolboxBundle/Document/SimpleAreabrick/SimpleAreaBrickConfigurable.php +++ b/src/ToolboxBundle/Document/SimpleAreabrick/SimpleAreaBrickConfigurable.php @@ -3,8 +3,9 @@ namespace ToolboxBundle\Document\SimpleAreabrick; use ToolboxBundle\Document\Areabrick\AbstractAreabrick; +use ToolboxBundle\Document\Areabrick\ToolboxHeadlessAwareBrickInterface; -class SimpleAreaBrickConfigurable extends AbstractAreabrick +class SimpleAreaBrickConfigurable extends AbstractAreabrick implements ToolboxHeadlessAwareBrickInterface { use SimpleAreaBrickTrait; } diff --git a/src/ToolboxBundle/Document/ToolboxAreabrick/Accordion/Accordion.php b/src/ToolboxBundle/Document/ToolboxAreabrick/Accordion/Accordion.php new file mode 100644 index 00000000..6189a087 --- /dev/null +++ b/src/ToolboxBundle/Document/ToolboxAreabrick/Accordion/Accordion.php @@ -0,0 +1,50 @@ +buildInfoParameters($info); + + return parent::action($info); + } + + public function headlessAction(Info $info, HeadlessResponse $headlessResponse): void + { + $this->buildInfoParameters($info, $headlessResponse); + + parent::headlessAction($info, $headlessResponse); + } + + private function buildInfoParameters(Info $info, ?HeadlessResponse $headlessResponse = null): void + { + $infoParams = $info->getParams(); + $id = $infoParams['toolboxAccordionId'] ?? str_replace('.', '', uniqid('accordion-', true)); + + if ($headlessResponse instanceof HeadlessResponse) { + $headlessResponse->addAdditionalConfigData('id', $id); + + return; + } + + $info->setParam('id', $id); + } + + public function getName(): string + { + return 'Accordion'; + } + + public function getDescription(): string + { + return 'Toolbox Accordion / Tabs'; + } +} diff --git a/src/ToolboxBundle/Document/ToolboxAreabrick/Anchor/Anchor.php b/src/ToolboxBundle/Document/ToolboxAreabrick/Anchor/Anchor.php new file mode 100644 index 00000000..e8480f56 --- /dev/null +++ b/src/ToolboxBundle/Document/ToolboxAreabrick/Anchor/Anchor.php @@ -0,0 +1,19 @@ +calculatorRegistry = $calculatorRegistry; - $this->templating = $templating; } public function action(Info $info): ?Response { - parent::action($info); + $this->buildInfoParameters($info); + + return parent::action($info); + } + + public function headlessAction(Info $info, HeadlessResponse $headlessResponse): void + { + $this->buildInfoParameters($info, $headlessResponse); - $editMode = $info->getEditable()->getEditmode(); + parent::headlessAction($info, $headlessResponse); + } + + private function buildInfoParameters(Info $info, ?HeadlessResponse $headlessResponse = null): void + { + $editMode = $info->getEditable()?->getEditmode() === true; /** @var Checkbox $equalHeightElement */ $equalHeightElement = $this->getDocumentEditable($info->getDocument(), 'checkbox', 'equal_height'); @@ -61,22 +70,30 @@ public function action(Info $info): ?Response } } - $info->setParams(array_merge($info->getParams(), [ + $info->setParam('columns', $columns); + + $brickParams = [ 'type' => $type . ($customColumnConfiguration !== null ? '-grid-adjuster' : ''), 'columns' => $columns, 'partialName' => $partialName, 'equalHeight' => $equalHeight - ])); + ]; + + if ($headlessResponse instanceof HeadlessResponse) { + $headlessResponse->setAdditionalConfigData($brickParams); + + return; + } - return null; + $info->setParams(array_merge($info->getParams(), $brickParams)); } - public function getName() + public function getName(): string { return 'Columns'; } - public function getDescription() + public function getDescription(): string { return 'Toolbox Grid Columns'; } diff --git a/src/ToolboxBundle/Document/ToolboxAreabrick/Container/Container.php b/src/ToolboxBundle/Document/ToolboxAreabrick/Container/Container.php new file mode 100644 index 00000000..8b1f1b71 --- /dev/null +++ b/src/ToolboxBundle/Document/ToolboxAreabrick/Container/Container.php @@ -0,0 +1,19 @@ +buildInfoParameters($info); + + return parent::action($info); + } + + public function headlessAction(Info $info, HeadlessResponse $headlessResponse): void + { + $this->buildInfoParameters($info, $headlessResponse); + parent::headlessAction($info, $headlessResponse); + } + + protected function buildInfoParameters(Info $info, ?HeadlessResponse $headlessResponse = null): void + { /** @var Relations $downloadField */ $downloadField = $this->getDocumentEditable($info->getDocument(), 'relations', 'downloads'); @@ -35,9 +49,13 @@ public function action(Info $info): ?Response } } - $info->setParam('downloads', $assets); + if ($headlessResponse instanceof HeadlessResponse) { + $headlessResponse->addAdditionalConfigData('downloads', $assets); - return null; + return; + } + + $info->setParam('downloads', $assets); } protected function getByFile(Asset $node): array diff --git a/src/ToolboxBundle/Document/ToolboxAreabrick/Gallery/Gallery.php b/src/ToolboxBundle/Document/ToolboxAreabrick/Gallery/Gallery.php new file mode 100644 index 00000000..78a602a8 --- /dev/null +++ b/src/ToolboxBundle/Document/ToolboxAreabrick/Gallery/Gallery.php @@ -0,0 +1,95 @@ +buildInfoParameters($info); + + return parent::action($info); + } + + public function headlessAction(Info $info, HeadlessResponse $headlessResponse): void + { + $this->buildInfoParameters($info, $headlessResponse); + + parent::headlessAction($info, $headlessResponse); + } + + protected function buildInfoParameters(Info $info, ?HeadlessResponse $headlessResponse = null): void + { + $infoParams = $info->getParams(); + $id = $infoParams['toolboxGalleryId'] ?? str_replace('.', '', uniqid('gallery-', true)); + + /** @var Relations $imagesField */ + $imagesField = $this->getDocumentEditable($info->getDocument(), 'relations', 'images'); + + $brickParams = [ + 'galleryId' => $id, + 'images' => $this->getAssetArray($imagesField->getElements()) + ]; + + if ($headlessResponse instanceof HeadlessResponse) { + + $brickParams = array_merge($brickParams, [ + 'galleryDataAttributes' => $this->dataAttributeService->generateDataAttributesAsArray('gallery'), + 'thumbsDataAttributes' => $this->dataAttributeService->generateDataAttributesAsArray('gallery_thumbs'), + ]); + + $headlessResponse->setAdditionalConfigData($brickParams); + + return; + } + + $info->setParams(array_merge($info->getParams(), $brickParams)); + } + + public function getName(): string + { + return 'Gallery'; + } + + public function getDescription(): string + { + return 'Toolbox Gallery'; + } + + protected function getAssetArray(array $data): array + { + if (empty($data)) { + return []; + } + + $assets = []; + + foreach ($data as $element) { + if ($element instanceof Asset\Image) { + $assets[] = $element; + } elseif ($element instanceof Asset\Folder) { + foreach ($element->getChildren() as $child) { + if ($child instanceof Asset\Image) { + $assets[] = $child; + } + } + } + } + + return $assets; + } +} diff --git a/src/ToolboxBundle/Document/ToolboxAreabrick/GoogleMap/GoogleMap.php b/src/ToolboxBundle/Document/ToolboxAreabrick/GoogleMap/GoogleMap.php new file mode 100644 index 00000000..b9c0deff --- /dev/null +++ b/src/ToolboxBundle/Document/ToolboxAreabrick/GoogleMap/GoogleMap.php @@ -0,0 +1,61 @@ +buildInfoParameters($info); + + return parent::action($info); + } + + public function headlessAction(Info $info, HeadlessResponse $headlessResponse): void + { + $this->buildInfoParameters($info, $headlessResponse); + + parent::headlessAction($info, $headlessResponse); + } + + protected function buildInfoParameters(Info $info, ?HeadlessResponse $headlessResponse = null): void + { + if ($headlessResponse instanceof HeadlessResponse) { + $headlessResponse->addAdditionalConfigData('googleMapsHostUrl', $this->googleMapsHostUrl); + + return; + } + + $info->setParam('googleMapsHostUrl', $this->googleMapsHostUrl); + } + + public function getTemplateDirectoryName(): string + { + return 'google_map'; + } + + public function getTemplate(): string + { + return sprintf('@Toolbox/areas/%s/view.%s', $this->getTemplateDirectoryName(), $this->getTemplateSuffix()); + } + + public function getName(): string + { + return 'Google Map'; + } + + public function getDescription(): string + { + return 'Toolbox Google Map'; + } +} diff --git a/src/ToolboxBundle/Document/ToolboxAreabrick/Headline/Headline.php b/src/ToolboxBundle/Document/ToolboxAreabrick/Headline/Headline.php new file mode 100644 index 00000000..edcc2064 --- /dev/null +++ b/src/ToolboxBundle/Document/ToolboxAreabrick/Headline/Headline.php @@ -0,0 +1,57 @@ +buildInfoParameters($info); + + return parent::action($info); + } + + public function headlessAction(Info $info, HeadlessResponse $headlessResponse): void + { + $this->buildInfoParameters($info, $headlessResponse); + + parent::headlessAction($info, $headlessResponse); + } + + private function buildInfoParameters(Info $info, ?HeadlessResponse $headlessResponse = null): void + { + $anchorName = null; + /** @var Input $anchorNameElement */ + $anchorNameElement = $this->getDocumentEditable($info->getDocument(), 'input', 'anchor_name'); + + if (!$anchorNameElement->isEmpty()) { + $anchorName = File::getValidFilename($anchorNameElement->getData()); + } + + if ($headlessResponse instanceof HeadlessResponse) { + $headlessResponse->addAdditionalConfigData('anchorName', $anchorName); + + return; + } + + $info->setParam('anchorName', $anchorName); + } + + public function getName(): string + { + return 'Headline'; + } + + public function getDescription(): string + { + return 'Toolbox Headline'; + } +} diff --git a/src/ToolboxBundle/Document/Areabrick/IFrame/IFrame.php b/src/ToolboxBundle/Document/ToolboxAreabrick/IFrame/IFrame.php similarity index 66% rename from src/ToolboxBundle/Document/Areabrick/IFrame/IFrame.php rename to src/ToolboxBundle/Document/ToolboxAreabrick/IFrame/IFrame.php index dd677a25..1867bd79 100644 --- a/src/ToolboxBundle/Document/Areabrick/IFrame/IFrame.php +++ b/src/ToolboxBundle/Document/ToolboxAreabrick/IFrame/IFrame.php @@ -1,25 +1,39 @@ buildInfoParameters($info); + + return parent::action($info); + } + + public function headlessAction(Info $info, HeadlessResponse $headlessResponse): void + { + $this->buildInfoParameters($info, $headlessResponse); + parent::headlessAction($info, $headlessResponse); + } + + protected function buildInfoParameters(Info $info, ?HeadlessResponse $headlessResponse = null): void + { $iFrameUrl = $this->getDocumentEditable($info->getDocument(), 'input', 'url')->getData(); $initialHeight = $this->getDocumentEditable($info->getDocument(), 'numeric', 'iheight')->getData(); $isValid = true; $errorMessage = null; - if (!empty($iFrameUrl) && $info->getEditable()->getEditmode() === true) { + if (!empty($iFrameUrl) && $info->getEditable()?->getEditmode() === true) { $response = $this->checkIfUrlIsEmbeddable($iFrameUrl); if ($response !== true) { $isValid = false; @@ -27,14 +41,20 @@ public function action(Info $info): ?Response } } - $info->setParams(array_merge($info->getParams(), [ + $brickParams = [ 'isValid' => $isValid, 'errorMessage' => $errorMessage, 'initialHeight' => is_numeric($initialHeight) ? (int) $initialHeight : null, 'iFrameUrl' => $iFrameUrl - ])); + ]; + + if ($headlessResponse instanceof HeadlessResponse) { + $headlessResponse->setAdditionalConfigData($brickParams); + + return; + } - return null; + $info->setParams(array_merge($info->getParams(), $brickParams)); } private function checkIfUrlIsEmbeddable($iFrameUrl): bool|string diff --git a/src/ToolboxBundle/Document/ToolboxAreabrick/Image/Image.php b/src/ToolboxBundle/Document/ToolboxAreabrick/Image/Image.php new file mode 100644 index 00000000..0a57502c --- /dev/null +++ b/src/ToolboxBundle/Document/ToolboxAreabrick/Image/Image.php @@ -0,0 +1,19 @@ +translator = $translator; - $this->templating = $templating; + public function __construct( + private Translator $translator, + private EngineInterface $templating + ) { } public function action(Editable\Area\Info $info): ?Response @@ -43,13 +40,13 @@ public function action(Editable\Area\Info $info): ?Response $behindElements = !$parallaxFront->isEmpty() ? $this->templating->render( - $this->getTemplatePath('partial/behind-front-elements'), + $this->getTemplatePath('partial/behind_front_elements'), ['elements' => $parallaxBehind, 'backgroundImageMode' => $backgroundImageMode, 'document' => $info->getDocument()] ) : null; $frontElements = !$parallaxFront->isEmpty() ? $this->templating->render( - $this->getTemplatePath('partial/behind-front-elements'), + $this->getTemplatePath('partial/behind_front_elements'), ['elements' => $parallaxFront, 'backgroundImageMode' => $backgroundImageMode, 'document' => $info->getDocument()] ) : null; @@ -60,20 +57,16 @@ public function action(Editable\Area\Info $info): ?Response 'backgroundColorClass' => $backgroundColorClass, 'behindElements' => $behindElements, 'frontElements' => $frontElements, - 'sectionContent' => $this->_buildSectionContent($info) + 'sectionContent' => $this->buildSectionContent($info) ])); return null; } /** - * @param Editable\Area\Info $info - * - * @return string - * * @throws \Exception */ - private function _buildSectionContent(Editable\Area\Info $info) + private function buildSectionContent(Editable\Area\Info $info): string { ob_start(); @@ -100,7 +93,7 @@ private function _buildSectionContent(Editable\Area\Info $info) if ($containerWrapper !== 'none') { $wrapperArgs = ['containerWrapperClass' => $containerWrapper, 'document' => $info->getDocument()]; - $wrapContent = $this->templating->render($this->getTemplatePath('wrapper/container-wrapper'), $wrapperArgs); + $wrapContent = $this->templating->render($this->getTemplatePath('wrapper/container_wrapper'), $wrapperArgs); $areaBlock = sprintf($wrapContent, $areaBlock); } @@ -196,7 +189,7 @@ private function getBackgroundColorClass(?string $backgroundColor, array $config public function getTemplateDirectoryName(): string { - return 'parallax-container'; + return 'parallax_container'; } public function getTemplate(): string diff --git a/src/ToolboxBundle/Document/ToolboxAreabrick/Separator/Separator.php b/src/ToolboxBundle/Document/ToolboxAreabrick/Separator/Separator.php new file mode 100644 index 00000000..63c2b9fc --- /dev/null +++ b/src/ToolboxBundle/Document/ToolboxAreabrick/Separator/Separator.php @@ -0,0 +1,21 @@ +calculatorRegistry = $calculatorRegistry; } public function action(Info $info): ?Response @@ -54,7 +51,7 @@ private function calculateSlideColumnBreakpoints(int $columnType): array $configInfo = $this->getConfigManager()->getAreaParameterConfig('slideColumns'); $breakpoints = []; - if (!empty($configInfo) && isset($configInfo['breakpoints'], $configInfo['breakpoints'][$columnType])) { + if (isset($configInfo['breakpoints'][$columnType]) && !empty($configInfo)) { $breakpoints = $configInfo['breakpoints'][$columnType]; } @@ -63,7 +60,7 @@ private function calculateSlideColumnBreakpoints(int $columnType): array public function getTemplateDirectoryName(): string { - return 'slide-columns'; + return 'slide_columns'; } public function getTemplate(): string diff --git a/src/ToolboxBundle/Document/ToolboxAreabrick/Snippet/Snippet.php b/src/ToolboxBundle/Document/ToolboxAreabrick/Snippet/Snippet.php new file mode 100644 index 00000000..40408471 --- /dev/null +++ b/src/ToolboxBundle/Document/ToolboxAreabrick/Snippet/Snippet.php @@ -0,0 +1,30 @@ +isHeadlessLayoutAware()) { + $info->setParam('isHeadless', true); + } + + return parent::action($info); + } + + public function getName(): string + { + return 'Snippet'; + } + + public function getDescription(): string + { + return 'Toolbox Snippet'; + } +} diff --git a/src/ToolboxBundle/Document/ToolboxAreabrick/Spacer/Spacer.php b/src/ToolboxBundle/Document/ToolboxAreabrick/Spacer/Spacer.php new file mode 100644 index 00000000..977b5746 --- /dev/null +++ b/src/ToolboxBundle/Document/ToolboxAreabrick/Spacer/Spacer.php @@ -0,0 +1,19 @@ +buildInfoParameters($info); + + return parent::action($info); + } + + public function headlessAction(Info $info, HeadlessResponse $headlessResponse): void + { + $this->buildInfoParameters($info, $headlessResponse); + + parent::headlessAction($info, $headlessResponse); + } + protected function buildInfoParameters(Info $info, ?HeadlessResponse $headlessResponse = null): void + { /** @var Vhs $videoTag */ $videoTag = $this->getDocumentEditable($info->getDocument(), 'vhs', 'video'); @@ -26,37 +40,37 @@ public function action(Info $info): ?Response $autoPlay = $autoPlayElement->isChecked() === true && !$info->getEditable()->getEditmode(); $videoType = $videoTag->getVideoType(); $posterPath = null; - $poster = $videoTag->getPosterAsset(); + $poster = $videoTag->getPoster() ? $videoTag->getPosterAsset() : null; if ($poster instanceof Asset\Image) { $imageThumbnail = $this->getConfigManager()->getImageThumbnailFromConfig('video_poster'); $posterPath = $poster->getThumbnail($imageThumbnail); } - $info->setParams(array_merge($info->getParams(), [ + $brickParams = [ 'autoPlay' => $autoPlay, 'posterPath' => $posterPath, 'videoType' => $videoType, 'playInLightbox' => $playInLightBox, 'videoParameter' => $videoParameter, 'videoId' => $videoTag->getId() - ])); + ]; + + if ($headlessResponse instanceof HeadlessResponse) { + $headlessResponse->setAdditionalConfigData($brickParams); + + return; + } - return null; + $info->setParams(array_merge($info->getParams(), $brickParams)); } - /** - * @return string - */ - public function getName() + public function getName(): string { return 'Video'; } - /** - * @return string - */ - public function getDescription() + public function getDescription(): string { return 'Toolbox Video'; } diff --git a/src/ToolboxBundle/Event/HeadlessEditableActionEvent.php b/src/ToolboxBundle/Event/HeadlessEditableActionEvent.php new file mode 100644 index 00000000..1e03d799 --- /dev/null +++ b/src/ToolboxBundle/Event/HeadlessEditableActionEvent.php @@ -0,0 +1,39 @@ +info = $info; + $this->headlessResponse = $headlessResponse; + $this->editableFinder = $editableFinder; + } + + public function getInfo(): Info + { + return $this->info; + } + + public function getHeadlessResponse(): HeadlessResponse + { + return $this->headlessResponse; + } + + public function findDocumentEditable(string $type, string $inputName, array $options = []) + { + return call_user_func($this->editableFinder, $this->info->getDocument(), $type, $inputName, $options); + } +} diff --git a/src/ToolboxBundle/Event/HeadlessElementEvent.php b/src/ToolboxBundle/Event/HeadlessElementEvent.php new file mode 100644 index 00000000..79d6f601 --- /dev/null +++ b/src/ToolboxBundle/Event/HeadlessElementEvent.php @@ -0,0 +1,36 @@ +data; + } + + public function getElementType(): string + { + return $this->elementType; + } + + public function getElementSubType(): string + { + return $this->elementSubType; + } + + public function getElementNamespace(): string + { + return $this->elementNamespace; + } +} diff --git a/src/ToolboxBundle/EventListener/Admin/AssetListener.php b/src/ToolboxBundle/EventListener/Admin/AssetListener.php new file mode 100644 index 00000000..55d1ca92 --- /dev/null +++ b/src/ToolboxBundle/EventListener/Admin/AssetListener.php @@ -0,0 +1,50 @@ + 'addEditModeCssFiles', + BundleManagerEvents::JS_PATHS => 'addJsFiles', + BundleManagerEvents::EDITMODE_JS_PATHS => 'addEditModeJsFiles' + ]; + } + + public function addEditModeCssFiles(PathsEvent $event): void + { + $event->addPaths([ + '/bundles/toolbox/css/admin.css', + '/bundles/toolbox/css/admin_uikit.css' + ]); + } + + public function addJsFiles(PathsEvent $event): void + { + $event->addPaths([ + '/admin/toolbox-wysiwyg-object-style.js', + '/bundles/toolbox/js/toolbox-wysiwyg-plugins.js', + '/bundles/toolbox/js/document/edit.js' + ]); + } + + public function addEditModeJsFiles(PathsEvent $event): void + { + $event->addPaths([ + '/bundles/toolbox/js/toolbox-wysiwyg-plugins.js', + '/bundles/toolbox/js/document/editables/area.js', + '/bundles/toolbox/js/document/editables/areablock.js', + '/bundles/toolbox/js/document/editables/googlemap.js', + '/bundles/toolbox/js/document/editables/parallaximage.js', + '/bundles/toolbox/js/document/editables/columnadjuster.js', + '/bundles/toolbox/js/document/editables/vhs.js', + '/bundles/toolbox/js/document/editables/vhs/editor.js', + ]); + } +} diff --git a/src/ToolboxBundle/EventListener/Admin/EditmodeListener.php b/src/ToolboxBundle/EventListener/Admin/EditmodeListener.php new file mode 100644 index 00000000..e8251f27 --- /dev/null +++ b/src/ToolboxBundle/EventListener/Admin/EditmodeListener.php @@ -0,0 +1,61 @@ + ['onKernelResponse', -255], + ]; + } + + public function onKernelResponse(ResponseEvent $event): void + { + $request = $event->getRequest(); + $response = $event->getResponse(); + + $scripts = [ + 'head' => sprintf('', '/admin/toolbox-wysiwyg-document-style.js', Version::getRevision()), + ]; + + if (!$event->isMainRequest()) { + return; // only main requests inject edit mode assets + } + + if (!$this->contextResolver->matchesPimcoreContext($request, PimcoreContextResolver::CONTEXT_DEFAULT)) { + return; + } + + if (!$this->editmodeResolver->isEditmode($request)) { + return; + } + + $html = $response->getContent(); + if (!str_contains($html, '')) { + return; + } + + $html = str_replace( + '', + sprintf("%s%s", $scripts['head'], PHP_EOL), + $html + ); + + $response->setContent($html); + } +} diff --git a/src/ToolboxBundle/EventListener/Frontend/FrontendJsListener.php b/src/ToolboxBundle/EventListener/Frontend/FrontendJsListener.php index b0389a8d..bc1cd309 100644 --- a/src/ToolboxBundle/EventListener/Frontend/FrontendJsListener.php +++ b/src/ToolboxBundle/EventListener/Frontend/FrontendJsListener.php @@ -3,7 +3,6 @@ namespace ToolboxBundle\EventListener\Frontend; use Pimcore\Tool; -use Pimcore\Bundle\CoreBundle\EventListener\Traits\EnabledTrait; use Pimcore\Bundle\CoreBundle\EventListener\Traits\PimcoreContextAwareTrait; use Pimcore\Bundle\CoreBundle\EventListener\Traits\ResponseInjectionTrait; use Pimcore\Http\Request\Resolver\PimcoreContextResolver; @@ -12,7 +11,6 @@ class FrontendJsListener { - use EnabledTrait; use ResponseInjectionTrait; use PimcoreContextAwareTrait; private EngineInterface $templatingEngine; @@ -24,10 +22,6 @@ public function __construct(EngineInterface $templatingEngine) public function onKernelResponse(ResponseEvent $event): void { - if (!$this->isEnabled()) { - return; - } - $request = $event->getRequest(); if (!$event->isMainRequest()) { return; diff --git a/src/ToolboxBundle/HeadlessDocument/HeadlessDocumentResolver.php b/src/ToolboxBundle/HeadlessDocument/HeadlessDocumentResolver.php new file mode 100644 index 00000000..e5edb84b --- /dev/null +++ b/src/ToolboxBundle/HeadlessDocument/HeadlessDocumentResolver.php @@ -0,0 +1,96 @@ +editmodeResolver->isEditmode($request); + $headlessDocumentConfig = $this->configManager->getHeadlessDocumentConfig($headlessDocumentName); + + if ($editMode === true) { + return $this->buildEditModeOutput($document, $headlessDocumentName, $headlessDocumentConfig['areas']); + } + + return $this->buildJsonOutput($document, $headlessDocumentName, $headlessDocumentConfig['areas']); + } + + private function buildEditModeOutput(Document $document, string $headlessDocumentName, array $areas): Response + { + $editModeEditables = []; + + foreach ($areas as $areaName => $areaConfig) { + if ($areaConfig['type'] === 'areablock') { + $areaBlockConfig = $this->areaManager->getAreaBlockConfiguration($areaName, $document instanceof Snippet, true); + $editModeEditables[$areaName] = [$areaConfig['type'], $areaBlockConfig]; + } else { + $editModeEditables[$areaName] = [ + $areaConfig['type'], + [ + 'type' => $areaConfig['areaType'], + ] + ]; + } + } + + $response = new Response(); + $editModeView = sprintf('@Toolbox/headless_document/%s.html.twig', $headlessDocumentName); + $response->setContent($this->environment->render($editModeView, [ + 'headless_document_name' => $headlessDocumentName, + 'editables' => $editModeEditables, + ])); + + return $response; + } + + private function buildJsonOutput(Document $document, string $headlessDocumentName, array $areas): JsonResponse + { + $editables = []; + foreach ($areas as $areaName => $areaConfig) { + + $editableConfig = [ + 'name' => $areaName, + 'type' => $areaConfig['type'], + ]; + + if ($areaConfig['type'] === 'areablock') { + // override config with area block config + $areaBlockConfig = $this->areaManager->getAreaBlockConfiguration($areaName, $document instanceof Snippet, true); + $editableConfig['config'] = $areaBlockConfig; + } elseif ($areaConfig['type'] === 'area') { + $editableConfig['config'] = [ + 'type' => $areaConfig['areaType'] + ]; + } else { + throw new \Exception(sprintf('Invalid type "%s" in headless document', $areaConfig['type'])); + } + + $editables[] = $editableConfig; + } + + $editableResponse = $this->editableJsonFetcher->fetchEditablesAsArray($document, $editables, false); + + return new JsonResponse($editableResponse); + } +} diff --git a/src/ToolboxBundle/Maintenance/AreaPermissionTask.php b/src/ToolboxBundle/Maintenance/AreaPermissionTask.php index 6d916c69..78e3fc1e 100644 --- a/src/ToolboxBundle/Maintenance/AreaPermissionTask.php +++ b/src/ToolboxBundle/Maintenance/AreaPermissionTask.php @@ -7,11 +7,8 @@ class AreaPermissionTask implements TaskInterface { - protected PermissionManagerInterface $permissionManager; - - public function __construct(PermissionManagerInterface $permissionManager) + public function __construct(protected PermissionManagerInterface $permissionManager) { - $this->permissionManager = $permissionManager; } public function execute(): void diff --git a/src/ToolboxBundle/Manager/AreaManager.php b/src/ToolboxBundle/Manager/AreaManager.php index d0a8a512..098c2a68 100644 --- a/src/ToolboxBundle/Manager/AreaManager.php +++ b/src/ToolboxBundle/Manager/AreaManager.php @@ -7,18 +7,11 @@ class AreaManager implements AreaManagerInterface { - public ConfigManagerInterface $configManager; - public AreabrickManager $brickManager; - public PermissionManagerInterface $permissionManager; - public function __construct( - ConfigManagerInterface $configManager, - AreabrickManager $brickManager, - PermissionManagerInterface $permissionManager + protected ConfigManagerInterface $configManager, + protected AreabrickManager $brickManager, + protected PermissionManagerInterface $permissionManager ) { - $this->configManager = $configManager; - $this->brickManager = $brickManager; - $this->permissionManager = $permissionManager; } public function getAreaBlockName(?string $type = null): string @@ -109,7 +102,7 @@ private function getActiveBricks(bool $arrayKeys = true): array /** @var AbstractTemplateAreabrick $areaElementData */ foreach ($areaElements as $areaElementName => $areaElementData) { - if (!$this->brickManager->isEnabled($areaElementName)) { + if (!$this->configManager->areaIsEnabled($areaElementName)) { unset($areaElements[$areaElementName]); } } @@ -134,10 +127,8 @@ private function getActiveBricks(bool $arrayKeys = true): array } } else { foreach ($areaElements as $areaElementName => $areaElementData) { - $coreAreas = $this->configManager->getConfig('areas'); - $customAreas = $this->configManager->getConfig('custom_areas'); - if (!array_key_exists($areaElementName, $coreAreas) && - !array_key_exists($areaElementName, $customAreas)) { + $areas = $this->configManager->getConfig('areas'); + if (!array_key_exists($areaElementName, $areas)) { unset($areaElements[$areaElementName]); } } @@ -158,7 +149,7 @@ private function getAvailableBricks(string $type): array { $areaElements = $this->getActiveBricks(); - $areaAppearance = $this->configManager->getConfig('areas_appearance'); + $areaAppearance = $this->configManager->getConfig('areablock_restriction'); $elementAllowed = isset($areaAppearance[$type]) ? $areaAppearance[$type]['allowed'] : []; $elementDisallowed = isset($areaAppearance[$type]) ? $areaAppearance[$type]['disallowed'] : []; @@ -189,7 +180,7 @@ private function getAvailableBricksForSnippets(string $type): array { $areaElements = $this->getActiveBricks(); - $areaAppearance = $this->configManager->getConfig('snippet_areas_appearance'); + $areaAppearance = $this->configManager->getConfig('snippet_areablock_restriction'); $elementAllowed = isset($areaAppearance[$type]) ? $areaAppearance[$type]['allowed'] : []; $elementDisallowed = isset($areaAppearance[$type]) ? $areaAppearance[$type]['disallowed'] : []; diff --git a/src/ToolboxBundle/Manager/ConfigManager.php b/src/ToolboxBundle/Manager/ConfigManager.php index ab9d4fa7..6cffe43f 100644 --- a/src/ToolboxBundle/Manager/ConfigManager.php +++ b/src/ToolboxBundle/Manager/ConfigManager.php @@ -12,7 +12,6 @@ class ConfigManager implements ConfigManagerInterface protected array $context = []; protected array $contextSettings = []; protected ?string $currentContextId = null; - private ?string $areaNamespace = null; public function __construct(ContextResolverInterface $contextResolver) { @@ -24,11 +23,19 @@ public function setConfig(array $config = []): void $this->config = $config; } - public function setAreaNameSpace(string $namespace = ConfigManagerInterface::AREABRICK_NAMESPACE_INTERNAL): self + public function addAdditionalAreaConfig(array $additionalAreaConfig = []): void { - $this->areaNamespace = $namespace; + foreach ($additionalAreaConfig as $additionalAreaId) { - return $this; + if (array_key_exists($additionalAreaId, $this->config['areas'])) { + continue; + } + + $this->config['areas'][$additionalAreaId] = [ + 'enabled' => true + ]; + + } } public function getConfig(string $section): mixed @@ -56,28 +63,43 @@ public function getCurrentContextSettings(): array return $this->contextSettings[$this->currentContextId]; } + public function getHeadlessDocumentConfig(string $headlessDocumentName): array + { + $this->ensureCoreConfig(); + + return $this->config['theme']['headless_documents'][$headlessDocumentName] ?? []; + } + + public function areaIsEnabled(string $areaName): bool + { + $this->ensureCoreConfig(); + + if (array_key_exists($areaName, $this->config['areas'])) { + return $this->config['areas'][$areaName]['enabled'] === true; + } + + return true; + } + public function getAreaConfig(string $areaName): mixed { $this->ensureCoreConfig(); - $this->ensureConfigNamespace(); - return $this->config[$this->areaNamespace][$areaName] ?? []; + return $this->config['areas'][$areaName] ?? []; } public function getAreaElementConfig(string $areaName, string $configElementName): mixed { $this->ensureCoreConfig(); - $this->ensureConfigNamespace(); - return $this->config[$this->areaNamespace][$areaName]['config_elements'][$configElementName]; + return $this->config['areas'][$areaName]['config_elements'][$configElementName]; } public function getAreaParameterConfig(string $areaName): mixed { $this->ensureCoreConfig(); - $this->ensureConfigNamespace(); - return $this->config[$this->areaNamespace][$areaName]['config_parameter']; + return $this->config['areas'][$areaName]['config_parameter']; } public function getImageThumbnailFromConfig(string $thumbnailName = ''): ?string @@ -117,16 +139,6 @@ private function ensureCoreConfig(): void $this->contextResolved = true; } - /** - * @throws \Exception - */ - private function ensureConfigNamespace(): void - { - if (is_null($this->areaNamespace)) { - throw new \Exception('ConfigManager has no defined namespace.'); - } - } - /** * @throws \Exception */ @@ -149,25 +161,20 @@ private function parseContextConfig(string $currentContextId): array // enabled areas passes first! if (!empty($contextSettings['enabled_areas'])) { - $filteredElements = ['areas' => [], 'custom_areas' => []]; + $filteredElements = []; foreach ($contextSettings['enabled_areas'] as $areaId) { if (isset($parsedData['areas'][$areaId])) { - $filteredElements['areas'][$areaId] = $parsedData['areas'][$areaId]; - } elseif (isset($parsedData['custom_areas'][$areaId])) { - $filteredElements['areas'][$areaId] = $parsedData['custom_areas'][$areaId]; + $filteredElements[$areaId] = $parsedData['areas'][$areaId]; } } - $parsedData['areas'] = $filteredElements['areas']; - $parsedData['custom_areas'] = $filteredElements['custom_areas']; + $parsedData['areas'] = $filteredElements; - // remove disabled areas for this context + // remove disabled areas for this context } elseif (!empty($contextSettings['disabled_areas'])) { foreach ($contextSettings['disabled_areas'] as $areaId) { if (isset($parsedData['areas'][$areaId])) { unset($parsedData['areas'][$areaId]); - } elseif (isset($parsedData['custom_areas'][$areaId])) { - unset($parsedData['custom_areas'][$areaId]); } } } @@ -175,6 +182,9 @@ private function parseContextConfig(string $currentContextId): array $parsedData = $contextData; } - return ['config' => $parsedData, 'settings' => $contextSettings]; + return [ + 'config' => $parsedData, + 'settings' => $contextSettings + ]; } } diff --git a/src/ToolboxBundle/Manager/ConfigManagerInterface.php b/src/ToolboxBundle/Manager/ConfigManagerInterface.php index 43398cf8..ffac1296 100644 --- a/src/ToolboxBundle/Manager/ConfigManagerInterface.php +++ b/src/ToolboxBundle/Manager/ConfigManagerInterface.php @@ -4,13 +4,8 @@ interface ConfigManagerInterface { - public const AREABRICK_NAMESPACE_INTERNAL = 'areas'; - public const AREABRICK_NAMESPACE_EXTERNAL = 'custom_areas'; - public function setConfig(array $config = []): void; - public function setAreaNameSpace(string $namespace = self::AREABRICK_NAMESPACE_INTERNAL): self; - /** * @throws \Exception */ @@ -26,6 +21,16 @@ public function isContextConfig(): bool; */ public function getCurrentContextSettings(): array; + /** + * @throws \Exception + */ + public function getHeadlessDocumentConfig(string $headlessDocumentName): array; + + /** + * @throws \Exception + */ + public function areaIsEnabled(string $areaName,): bool; + /** * @throws \Exception */ diff --git a/src/ToolboxBundle/Manager/LayoutManager.php b/src/ToolboxBundle/Manager/LayoutManager.php index adf123fa..5cc2b718 100644 --- a/src/ToolboxBundle/Manager/LayoutManager.php +++ b/src/ToolboxBundle/Manager/LayoutManager.php @@ -6,17 +6,10 @@ class LayoutManager implements LayoutManagerInterface { - protected ConfigManager $configManager; - protected EngineInterface $templating; - - public function __construct(ConfigManager $configManager) - { - $this->configManager = $configManager; - } - - public function setTemplating(EngineInterface $templating): void - { - $this->templating = $templating; + public function __construct( + protected ConfigManagerInterface $configManager, + protected EngineInterface $templating + ) { } public function getAreaTemplateDir(string $areaId, string $areaTemplateDir, string $viewName = 'view', string $extension = 'html.twig'): string @@ -31,8 +24,8 @@ public function getAreaTemplateDir(string $areaId, string $areaTemplateDir, stri $areaTemplateDir ); - //no fallback layout defined. return default. - if ($elementThemeConfig['default_layout'] === false || empty($elementThemeConfig['default_layout'])) { + // no fallback layout defined, return default + if (empty($elementThemeConfig['default_layout'])) { return $defaultDir; } @@ -40,7 +33,7 @@ public function getAreaTemplateDir(string $areaId, string $areaTemplateDir, stri return $defaultDir; } - //return fallback layout. + // return fallback layout return sprintf( $pathStructure, $elementThemeConfig['default_layout'], @@ -55,7 +48,7 @@ public function getAreaTemplatePath($areaId, string $areaTemplateDir, string $vi public function getAreaThemeConfig(string $areaName): array { - $layoutConfiguration = $this->configManager->setAreaNameSpace(ConfigManagerInterface::AREABRICK_NAMESPACE_INTERNAL)->getConfig('theme'); + $layoutConfiguration = $this->configManager->getConfig('theme'); $theme = [ 'layout' => $layoutConfiguration['layout'], diff --git a/src/ToolboxBundle/Manager/LayoutManagerInterface.php b/src/ToolboxBundle/Manager/LayoutManagerInterface.php index edbc48aa..8883067d 100644 --- a/src/ToolboxBundle/Manager/LayoutManagerInterface.php +++ b/src/ToolboxBundle/Manager/LayoutManagerInterface.php @@ -2,11 +2,12 @@ namespace ToolboxBundle\Manager; -use Symfony\Component\Templating\EngineInterface; - interface LayoutManagerInterface { - public function setTemplating(EngineInterface $templating): void; + public const TOOLBOX_LAYOUT_BOOTSTRAP3 = 'Bootstrap3'; + public const TOOLBOX_LAYOUT_BOOTSTRAP4 = 'Bootstrap4'; + public const TOOLBOX_LAYOUT_UIKIT3 = 'UIkit3'; + public const TOOLBOX_LAYOUT_HEADLESS = 'Headless'; /** * @throws \Exception diff --git a/src/ToolboxBundle/Manager/PermissionManager.php b/src/ToolboxBundle/Manager/PermissionManager.php index 667ae654..6f3137af 100644 --- a/src/ToolboxBundle/Manager/PermissionManager.php +++ b/src/ToolboxBundle/Manager/PermissionManager.php @@ -2,23 +2,18 @@ namespace ToolboxBundle\Manager; -use Pimcore\Bundle\AdminBundle\Security\User\UserLoader; use Pimcore\Extension\Document\Areabrick\AreabrickInterface; use Pimcore\Extension\Document\Areabrick\AreabrickManager; use Pimcore\Model\User; use Pimcore\Model\Translation; +use Pimcore\Security\User\UserLoader; class PermissionManager implements PermissionManagerInterface { - protected UserLoader $userLoader; - protected AreabrickManager $brickManager; - public function __construct( - AreabrickManager $brickManager, - UserLoader $userLoader + protected AreabrickManager $brickManager, + protected UserLoader $userLoader ) { - $this->brickManager = $brickManager; - $this->userLoader = $userLoader; } public function synchroniseEditablePermissions(): void diff --git a/src/ToolboxBundle/Model/Document/Editable/ColumnAdjuster.php b/src/ToolboxBundle/Model/Document/Editable/ColumnAdjuster.php index 3dada4a1..5fcfb9ff 100644 --- a/src/ToolboxBundle/Model/Document/Editable/ColumnAdjuster.php +++ b/src/ToolboxBundle/Model/Document/Editable/ColumnAdjuster.php @@ -29,7 +29,7 @@ public function isEmpty(): bool return empty($this->data); } - public function setDataFromResource($data): self + public function setDataFromResource(mixed $data): static { $data = Serialize::unserialize($data); @@ -42,7 +42,7 @@ public function setDataFromResource($data): self return $this; } - public function setDataFromEditmode(mixed $data): self + public function setDataFromEditmode(mixed $data): static { if (!is_array($data)) { $data = []; diff --git a/src/ToolboxBundle/Model/Document/Editable/GoogleMap.php b/src/ToolboxBundle/Model/Document/Editable/GoogleMap.php index 78780bc2..49e00816 100644 --- a/src/ToolboxBundle/Model/Document/Editable/GoogleMap.php +++ b/src/ToolboxBundle/Model/Document/Editable/GoogleMap.php @@ -5,9 +5,8 @@ use Pimcore\Model\Document; use Pimcore\Tool\Serialize; use ToolboxBundle\Manager\ConfigManager; -use ToolboxBundle\Manager\ConfigManagerInterface; -class GoogleMap extends Document\Editable +class GoogleMap extends Document\Editable implements Document\Editable\EditmodeDataInterface { private bool $disableGoogleLookUp = false; private ?string $mapId = null; @@ -55,9 +54,6 @@ public function isEmpty(): bool return empty($this->data); } - /** - * {@inheritdoc} - */ public function admin() { $html = parent::admin(); @@ -67,7 +63,7 @@ public function admin() return str_replace('', $this->frontend() . '', $html); } - public function setDataFromResource(mixed $data): self + public function setDataFromResource(mixed $data): static { $this->setId(uniqid('map-', true)); @@ -85,7 +81,7 @@ public function setDataFromResource(mixed $data): self /** * @throws \Exception */ - public function setDataFromEditmode(mixed $data): self + public function setDataFromEditmode(mixed $data): static { $this->setId(uniqid('map-', true)); @@ -151,7 +147,7 @@ protected function buildMapAttributes(): array /** @var ConfigManager $configManager */ $configManager = \Pimcore::getContainer()->get(ConfigManager::class); - $configNode = $configManager->setAreaNameSpace(ConfigManagerInterface::AREABRICK_NAMESPACE_INTERNAL)->getAreaParameterConfig('googleMap'); + $configNode = $configManager->getAreaParameterConfig('googleMap'); if (!empty($configNode)) { $mapOptions = $configNode['map_options']; @@ -229,13 +225,13 @@ protected function detectKey(): ?string { /** @var ConfigManager $configManager */ $configManager = \Pimcore::getContainer()->get(ConfigManager::class); - $configNode = $configManager->setAreaNameSpace(ConfigManagerInterface::AREABRICK_NAMESPACE_INTERNAL)->getAreaParameterConfig('googleMap'); + $configNode = $configManager->getAreaParameterConfig('googleMap'); $fallbackSimpleKey = \Pimcore::getContainer()->getParameter('toolbox.google_maps.simple_api_key'); $fallbackBrowserKey = \Pimcore::getContainer()->getParameter('toolbox.google_maps.browser_api_key'); // first try to get server-api-key - if (!empty($configNode) && isset($configNode['simple_api_key']) && !empty($configNode['simple_api_key'])) { + if (!empty($configNode) && !empty($configNode['simple_api_key'])) { return $configNode['simple_api_key']; } @@ -243,7 +239,7 @@ protected function detectKey(): ?string return $fallbackSimpleKey; } - if (!empty($configNode) && isset($configNode['map_api_key']) && !empty($configNode['map_api_key'])) { + if (!empty($configNode) && !empty($configNode['map_api_key'])) { return $configNode['map_api_key']; } @@ -280,7 +276,7 @@ protected function validateLocationValues(array $locations): array return $filteredLocations; } - public function __sleep() + public function __sleep(): array { $parentVars = parent::__sleep(); diff --git a/src/ToolboxBundle/Model/Document/Editable/ParallaxImage.php b/src/ToolboxBundle/Model/Document/Editable/ParallaxImage.php index 69fb8a50..c01cbac4 100644 --- a/src/ToolboxBundle/Model/Document/Editable/ParallaxImage.php +++ b/src/ToolboxBundle/Model/Document/Editable/ParallaxImage.php @@ -27,7 +27,7 @@ public function getType(): string return 'parallaximage'; } - public function setElements(): self + public function setElements(): static { if (empty($this->elements)) { $this->elements = []; diff --git a/src/ToolboxBundle/Model/Document/Editable/Vhs.php b/src/ToolboxBundle/Model/Document/Editable/Vhs.php index fe741c65..a551f33b 100644 --- a/src/ToolboxBundle/Model/Document/Editable/Vhs.php +++ b/src/ToolboxBundle/Model/Document/Editable/Vhs.php @@ -54,7 +54,7 @@ public function getDataForResource(): array return $data; } - public function setDataFromResource(mixed $data): self + public function setDataFromResource(mixed $data): static { parent::setDataFromResource($data); @@ -68,7 +68,7 @@ public function setDataFromResource(mixed $data): self return $this; } - public function setDataFromEditmode($data): self + public function setDataFromEditmode(mixed $data): static { parent::setDataFromEditmode($data); diff --git a/src/ToolboxBundle/Normalizer/DownloadRelationsNormalizer.php b/src/ToolboxBundle/Normalizer/DownloadRelationsNormalizer.php new file mode 100644 index 00000000..b582a72f --- /dev/null +++ b/src/ToolboxBundle/Normalizer/DownloadRelationsNormalizer.php @@ -0,0 +1,27 @@ +downloadInfoService->getDownloadInfo($asset, true, 'optimized'); + } + + return $normalizedData; + } +} diff --git a/src/ToolboxBundle/Normalizer/GalleryRelationsNormalizer.php b/src/ToolboxBundle/Normalizer/GalleryRelationsNormalizer.php new file mode 100644 index 00000000..12f4afd0 --- /dev/null +++ b/src/ToolboxBundle/Normalizer/GalleryRelationsNormalizer.php @@ -0,0 +1,44 @@ +configManager->getImageThumbnailFromConfig('gallery_lightbox'); + $galleryElement = $this->configManager->getImageThumbnailFromConfig('gallery_element'); + $galleryThumbnail = $this->configManager->getImageThumbnailFromConfig('gallery_thumbnail'); + + $normalizedData[] = [ + 'lightbox' => $this->assetService->generateImageThumbnail($asset, $galleryLightbox), + 'image' => $this->assetService->generateImageThumbnail($asset, $galleryElement), + 'thumbnail' => $this->assetService->generateImageThumbnail($asset, $galleryThumbnail), + ]; + } + + return $normalizedData; + } +} diff --git a/src/ToolboxBundle/Normalizer/ImageEditableNormalizer.php b/src/ToolboxBundle/Normalizer/ImageEditableNormalizer.php new file mode 100644 index 00000000..64367fa8 --- /dev/null +++ b/src/ToolboxBundle/Normalizer/ImageEditableNormalizer.php @@ -0,0 +1,35 @@ +configManager->getImageThumbnailFromConfig('image_lightbox'); + $imageElement = $this->configManager->getImageThumbnailFromConfig('image_element'); + + if ($value->getThumbnailConfig()) { + $imageElement = $value->getThumbnailConfig(); + } + + return [ + 'lightbox' => $this->assetService->generateImageThumbnailFromEditable($value, $imageLightbox), + 'image' => $this->assetService->generateImageThumbnailFromEditable($value, $imageElement), + ]; + } +} diff --git a/src/ToolboxBundle/Normalizer/PropertyNormalizerInterface.php b/src/ToolboxBundle/Normalizer/PropertyNormalizerInterface.php new file mode 100644 index 00000000..29bcdb6f --- /dev/null +++ b/src/ToolboxBundle/Normalizer/PropertyNormalizerInterface.php @@ -0,0 +1,8 @@ + [], 'slide_column' => [] ]; - private string $columnInterface; - private string $slideColumnInterface; - public function __construct(string $columnInterface, string $slideColumnInterface) + public function __construct(protected string $columnInterface, protected string $slideColumnInterface) { - $this->columnInterface = $columnInterface; - $this->slideColumnInterface = $slideColumnInterface; } public function register(string $id, mixed $service, string $type): void diff --git a/src/ToolboxBundle/Registry/NormalizerRegistry.php b/src/ToolboxBundle/Registry/NormalizerRegistry.php new file mode 100644 index 00000000..3f5ffb74 --- /dev/null +++ b/src/ToolboxBundle/Registry/NormalizerRegistry.php @@ -0,0 +1,35 @@ +normalizer[$normalizerName] = $service; + } + + public function has(string $normalizerName): bool + { + return isset($this->normalizer[$normalizerName]); + } + + public function get($normalizerName): PropertyNormalizerInterface + { + if (!$this->has($normalizerName)) { + throw new \Exception('"' . $normalizerName . '" Normalizer does not exist'); + } + + return $this->normalizer[$normalizerName]; + } +} diff --git a/src/ToolboxBundle/Registry/NormalizerRegistryInterface.php b/src/ToolboxBundle/Registry/NormalizerRegistryInterface.php new file mode 100644 index 00000000..4f437a71 --- /dev/null +++ b/src/ToolboxBundle/Registry/NormalizerRegistryInterface.php @@ -0,0 +1,17 @@ + .single-teaser img { .editable-blocked .toolbox-element-edit-button { min-height: 35px; +} + + +/* + [TOOLBOX HEADLESS] Inline Editables +*/ + +.toolbox-headless { + margin: 10px; +} + +.toolbox-headless .pimcore_area_buttons { + margin-top: 5px; + margin-bottom: 5px; +} + +.toolbox-headless .toolbox-inline-editable-panel { + background: #7891b92b; + border-radius: 3px; + padding: 5px; + position: relative; +} + +.toolbox-headless .toolbox-inline-editable-panel .x-fieldset { + border: 0; + border-top: 0 !important; + padding: 3px; + margin: 0 0 10px 0; +} + +.toolbox-headless .toolbox-inline-editable-panel .x-fieldset-header-text { + color: black; + font-size: 13px; +} + +.toolbox-headless .toolbox-inline-editable-panel label { + margin: 0; +} + +.toolbox-headless .toolbox-inline-editable-panel .x-fieldset-header { + background: transparent; + padding: 0; + margin: 0; +} + +.toolbox-headless .pimcore_editable_input { + background: white; + padding: 2px 4px; + border: 1px dashed #d6d6d6; + font-size: 14px; +} + +.toolbox-headless .toolbox-columns .toolbox-column { + background: transparent; + border: none; +} + +/* + [TOOLBOX HEADLESS] Inline Editables - Config Node +*/ + +.toolbox-headless .inline-config-area { + border: 1px dashed #d6d6d6; + padding: 10px; + border-radius: 3px; +} + +.toolbox-headless .inline-config-area .inline-config-node { + margin: 0 0 10px 0; +} + +.toolbox-headless .inline-config-area .inline-config-node:first-child .inline-config-label { + margin: 0 0 5px 0; +} + +.toolbox-headless .inline-config-area .inline-config-node .inline-config-label { + padding: 3px; + margin: 5px 0; + display: block; + color: #645081; +} + +.toolbox-headless .inline-config-area .inline-config-node .inline-config-label .inline-config-icon { + box-sizing: border-box; + display: inline-block; + font-style: normal; + position: relative; + text-indent: -9999px; + vertical-align: middle; + font-size: 7px; + transform: scale(1); + margin: 0 10px 0 0; +} + +.toolbox-headless .inline-config-area .inline-config-node .inline-config-label .inline-config-icon::before { + content: ""; + display: block; + left: 50%; + position: absolute; + top: 50%; + border: .1rem solid currentColor; + border-bottom: 0; + border-right: 0; + height: .65em; + width: .65em; + transform: translate(-75%, -50%) rotate(135deg); +} + +.toolbox-headless .inline-config-area .inline-config-node .inline-config-description { + font-size: 12px; + display: block; + font-style: italic; } \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/public/js/document/editables/area.js b/src/ToolboxBundle/Resources/public/js/document/editables/area.js new file mode 100644 index 00000000..94e0d1d8 --- /dev/null +++ b/src/ToolboxBundle/Resources/public/js/document/editables/area.js @@ -0,0 +1,57 @@ +pimcore.registerNS('pimcore.document.editables.area'); +pimcore.document.editables.area = Class.create(pimcore.document.editables.area, { + + initialize: function ($super, id, name, config, data, inherited) { + + $super(id, name, config, data, inherited); + + this.parseEditable(id); + }, + + parseEditable: function (id) { + + var $areaEl, $areaDialog, $editDiv, $el, isConfigurable; + + try { + + $areaEl = Ext.get(id); + + $areaDialog = $areaEl.query('.pimcore_area_dialog[data-name="' + this.name + '"]')[0]; + $editDiv = $areaEl.query('.pimcore_block_button_dialog')[0]; + isConfigurable = typeof $editDiv !== 'undefined'; + + if ($areaEl && !$areaEl.hasCls('toolbox-initialized')) { + + $areaEl.addCls('toolbox-initialized'); + + $el = Ext.DomHelper.insertBefore($areaEl, { + 'tag': 'div', + 'class': 'toolbox-element-edit-button' + (isConfigurable ? '' : ' not-configurable'), + 'data-title': 'area' + }, true); + + if (isConfigurable === true) { + // remove pimcore default edit button! + Ext.get($editDiv).setVisible(false); + this.dispatchToolboxDialogBoxEditing($areaEl, $el, $areaDialog); + } + } + + } catch (e) { + console.error(e); + } + }, + + dispatchToolboxDialogBoxEditing: function ($areaEl, $el, $areaDialog) { + + var $editButton = new Ext.Button({ + cls: 'pimcore_block_button_plus', + iconCls: 'pimcore_icon_edit', + text: t('edit'), + handler: this.openEditableDialogBox.bind(this, $areaEl, $areaDialog) + }); + + $editButton.render($el); + } + +}); diff --git a/src/ToolboxBundle/Resources/public/js/document/editables/areablock.js b/src/ToolboxBundle/Resources/public/js/document/editables/areablock.js index 8455ca17..ab576222 100644 --- a/src/ToolboxBundle/Resources/public/js/document/editables/areablock.js +++ b/src/ToolboxBundle/Resources/public/js/document/editables/areablock.js @@ -16,11 +16,9 @@ pimcore.document.editables.areablock = Class.create(pimcore.document.editables.a $super(id, name, config, data, inherited); - if(setupToolbar === true) { + if (setupToolbar === true) { this.createToolBar(); } - - this.addToolboxEditBar(); }, filterEditablesByPermission: function () { @@ -64,15 +62,13 @@ pimcore.document.editables.areablock = Class.create(pimcore.document.editables.a }, refresh: function ($super) { - $super(); - this.addToolboxEditBar(); }, - hasToolboxPermissionForEditable: function(type) { + hasToolboxPermissionForEditable: function (type) { - if(!this.config.hasOwnProperty('toolbox_permissions')) { + if (!this.config.hasOwnProperty('toolbox_permissions')) { return true; } @@ -81,62 +77,71 @@ pimcore.document.editables.areablock = Class.create(pimcore.document.editables.a addToolboxEditBar: function () { - var i, $areaEl, $areaButtonsEl, $editDiv, $labelDiv, $el, $editButton, isConfigurable; + var i; if (this.elements.length === 0) { return; } for (i = 0; i < this.elements.length; i++) { + this.parseEditable(i); + } + }, - try { - - $areaEl = Ext.get(this.elements[i]); - $areaButtonsEl = $areaEl.query('.pimcore_area_buttons[data-name="' + this.name + '"]')[0]; - $editDiv = $areaEl.query('.pimcore_block_dialog[data-name="' + this.name + '"]')[0]; - $labelDiv = $areaEl.query('.pimcore_block_label[data-name="' + this.name + '"] b')[0]; - isConfigurable = typeof $editDiv !== 'undefined'; + parseEditable: function (i) { - // check for permission - if (this.hasToolboxPermissionForEditable($areaEl.getAttribute('type')) === false) { - $areaEl.addCls('editable-blocked'); - } + var $areaEl, $areaButtonsEl, $editDiv, $labelDiv, $el, isConfigurable; - if ($labelDiv && !$areaEl.hasCls('toolbox-initialized')) { + try { - $areaEl.addCls('toolbox-initialized'); + $areaEl = Ext.get(this.elements[i]); + $areaButtonsEl = $areaEl.query('.pimcore_area_buttons[data-name="' + this.name + '"]')[0]; + $editDiv = $areaEl.query('.pimcore_block_dialog[data-name="' + this.name + '"]')[0]; + $labelDiv = $areaEl.query('.pimcore_block_label[data-name="' + this.name + '"] b')[0]; + isConfigurable = typeof $editDiv !== 'undefined'; - $el = Ext.DomHelper.insertAfter($areaButtonsEl, { - 'tag': 'div', - 'class': 'toolbox-element-edit-button' + ( isConfigurable ? '' : ' not-configurable'), - 'data-title': $labelDiv.innerHTML - }, true); + // check for permission + if (this.hasToolboxPermissionForEditable($areaEl.getAttribute('type')) === false) { + $areaEl.addCls('editable-blocked'); + } - if (isConfigurable === true) { + if ($labelDiv && !$areaEl.hasCls('toolbox-initialized')) { - //remove pimcore default edit button! - Ext.get($editDiv).setVisible(false); + $areaEl.addCls('toolbox-initialized'); - $editButton = new Ext.Button({ - cls: 'pimcore_block_button_plus', - iconCls: 'pimcore_icon_edit', - text: t('edit'), - handler: this.openEditableDialogBox.bind(this, this.elements[i], $editDiv), - listeners: { - afterrender: function(ev) { - $areaEl.fireEvent('toolbox.bar.added', $areaEl); - } - } - }); + $el = Ext.DomHelper.insertAfter($areaButtonsEl, { + 'tag': 'div', + 'class': 'toolbox-element-edit-button' + (isConfigurable ? '' : ' not-configurable'), + 'data-title': $labelDiv.innerHTML + }, true); - $editButton.render($el); - } + if (isConfigurable === true) { + // remove pimcore default edit button! + Ext.get($editDiv).setVisible(false); + this.dispatchToolboxDialogBoxEditing(i, $areaEl, $el, $editDiv); } - - } catch (e) { - console.error(e); } + + } catch (e) { + console.error(e); } + }, + + dispatchToolboxDialogBoxEditing: function (index, $areaEl, $el, $editDiv) { + var $editButton = new Ext.Button({ + cls: 'pimcore_block_button_plus', + iconCls: 'pimcore_icon_edit', + text: t('edit'), + handler: this.openEditableDialogBox.bind(this, this.elements[index], $editDiv), + listeners: { + afterrender: function (ev) { + $areaEl.fireEvent('toolbox.bar.added', $areaEl); + } + } + }); + + $editButton.render($el); } + }); diff --git a/src/ToolboxBundle/Resources/public/js/toolbox-ckeditor-plugins.js b/src/ToolboxBundle/Resources/public/js/toolbox-ckeditor-plugins.js deleted file mode 100644 index d8ca5cde..00000000 --- a/src/ToolboxBundle/Resources/public/js/toolbox-ckeditor-plugins.js +++ /dev/null @@ -1,92 +0,0 @@ -CKEDITOR.plugins.add('tbGoogleOptOutLink', { - init: function (editor) { - editor.addCommand('tbGoogleOptOutLink', new CKEDITOR.dialogCommand('tbGoogleOptOutLinkDialog')); - - editor.on('selectionChange', function (e) { - if (e.data.selection.getStartElement().hasClass('google-opt-out-link')) - editor.getCommand('tbGoogleOptOutLink').setState(CKEDITOR.TRISTATE_DISABLED); - else - editor.getCommand('tbGoogleOptOutLink').setState(CKEDITOR.TRISTATE_ENABLED); - }); - - editor.ui.addButton('GoogleOptOutLink', { - label: 'Toolbox Google Opt-Out Link', - command: 'tbGoogleOptOutLink', - icon: '/bundles/toolbox/images/ckeditor/gOptOut.png' - }); - } -}); - -CKEDITOR.dialog.add('tbGoogleOptOutLinkDialog', function (editor) { - return { - title: 'Google Opt Out Properties', - minWidth: 400, - minHeight: 200, - contents: [ - { - id: 'tab-basic', - label: 'Basic Settings', - elements: [ - { - type: 'text', - id: 'gac', - label: 'Google Analytics Code', - validate: CKEDITOR.dialog.validate.notEmpty('Google Analytics Code field cannot be empty.'), - setup: function (element) { - this.data(element.getAttribute('name')); - }, - commit: function (element) { - var gac = this.getValue(); - element.setAttribute('name', gac); - } - }, - { - type: 'text', - id: 'title', - label: 'Text', - validate: CKEDITOR.dialog.validate.notEmpty('Text field cannot be empty.'), - setup: function (element) { - this.data(element.getText()); - }, - commit: function (element) { - var text = this.getValue(); - element.setText(text); - } - }, - ] - } - ], - onShow: function () { - - var selection = editor.getSelection(); - var element = selection.getStartElement(); - - if (element) { - element = element.getAscendant('a', true); - } - - if (!element || element.getName() !== 'a' || !element.hasClass('google-opt-out-link')) { - element = editor.document.createElement('a'); - element.setAttribute('class', 'google-opt-out-link'); - element.setAttribute('href', '#'); - element.setText('click here to opt-out of google analytics'); - this.insertMode = true; - } else { - this.insertMode = false; - } - - this.element = element; - if (!this.insertMode) { - this.setupContent(this.element); - } - }, - - onOk: function () { - var aLink = this.element; - this.commitContent(aLink); - - if (this.insertMode) - editor.insertElement(aLink); - } - }; -}); \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/public/js/toolbox-wysiwyg-plugins.js b/src/ToolboxBundle/Resources/public/js/toolbox-wysiwyg-plugins.js new file mode 100644 index 00000000..c9fa755e --- /dev/null +++ b/src/ToolboxBundle/Resources/public/js/toolbox-wysiwyg-plugins.js @@ -0,0 +1,75 @@ +tinymce.PluginManager.add('tb_goo_link', function (editor, url) { + + let createOptOutLink = function (data) { + return '' + data.title + ''; + }; + + editor.ui.registry.addButton('tb_goo_link_button', { + text: 'Google Opt-Out Link', + disabled: true, + onAction: function (_) { + + editor.windowManager.open({ + title: 'Basic Settings', + body: { + type: 'panel', + items: [ + { + label: 'Google Analytics Code', + name: 'gac', + type: 'input' + }, + { + label: 'Text', + name: 'title', + type: 'input' + } + ] + }, + buttons: [ + { + type: 'cancel', + name: 'cancel', + text: 'Cancel' + }, + { + type: 'submit', + name: 'save', + text: 'Save', + primary: true + } + ], + initialData: { + preview: 'some html url' + }, + onSubmit: (dialogApi) => { + editor.insertContent(createOptOutLink(dialogApi.getData())); + editor.windowManager.close(); + } + }); + + }, + onSetup: function (buttonApi) { + + let editorEventCallback = function (eventApi) { + buttonApi.setEnabled(!eventApi.element.classList.contains('google-opt-out-link')); + }; + + editor.on('NodeChange', editorEventCallback); + + return function (buttonApi) { + editor.off('NodeChange', editorEventCallback); + }; + } + }); + + return { + + getMetadata: function () { + return { + name: 'Toolbox Google Opt-Out Link', + url: 'https://github.com/dachcom-digital/pimcore-toolbox' + }; + } + } +}); diff --git a/src/ToolboxBundle/Resources/translations/admin.de.yml b/src/ToolboxBundle/Resources/translations/admin.de.yaml similarity index 100% rename from src/ToolboxBundle/Resources/translations/admin.de.yml rename to src/ToolboxBundle/Resources/translations/admin.de.yaml diff --git a/src/ToolboxBundle/Resources/translations/admin.en.yml b/src/ToolboxBundle/Resources/translations/admin.en.yaml similarity index 100% rename from src/ToolboxBundle/Resources/translations/admin.en.yml rename to src/ToolboxBundle/Resources/translations/admin.en.yaml diff --git a/src/ToolboxBundle/Resources/views/admin/area-config/Elements/tag.html.twig b/src/ToolboxBundle/Resources/views/admin/area-config/Elements/tag.html.twig deleted file mode 100644 index a18e8392..00000000 --- a/src/ToolboxBundle/Resources/views/admin/area-config/Elements/tag.html.twig +++ /dev/null @@ -1,2 +0,0 @@ -{% set editmode = editmode is defined ? editmode : null %} -{{ toolbox_document_tag(type, tag_name, tag_config) }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/admin/inline_config/editable.html.twig b/src/ToolboxBundle/Resources/views/admin/inline_config/editable.html.twig new file mode 100644 index 00000000..9ad790b5 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/admin/inline_config/editable.html.twig @@ -0,0 +1,11 @@ +
+ {% if item.label is not empty %} + {{ item.label }} + {% endif %} + {% if editable is not null %} + {{ editable|raw }} + {% endif %} + {% if item.description is not empty %} + {{ item.description }} + {% endif %} +
\ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/admin/settings/ckeditor-area-style.html.twig b/src/ToolboxBundle/Resources/views/admin/settings/ckeditor-area-style.html.twig deleted file mode 100644 index 0c7a931c..00000000 --- a/src/ToolboxBundle/Resources/views/admin/settings/ckeditor-area-style.html.twig +++ /dev/null @@ -1,17 +0,0 @@ -{% if globalStyleSets is defined and globalStyleSets is iterable %} - {% for stylesSetName, stylesSetData in globalStyleSets %} - if(CKEDITOR.stylesSet.get('{{ stylesSetName }}') === null) { - CKEDITOR.stylesSet.add('{{ stylesSetName }}', {{ stylesSetData|json_encode|raw }}); - } else { - console.warn('toolbox: ckeditor style set "{{ stylesSetName }}" already has been set. did you forget to add the config? usage: pimcore_wysiwyg("text", {"customConfig":toolbox_get_ckeditor_config_path()})'); - } - {% endfor %} -{% endif %} - -CKEDITOR.editorConfig = function( config ) { -{% if config is iterable %} - {% for configName, configData in config %} - config.{{ configName }} = {{ configData|json_encode|raw }}; - {% endfor %} -{% endif %} -}; \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/admin/settings/ckeditor-object-style.html.twig b/src/ToolboxBundle/Resources/views/admin/settings/ckeditor-object-style.html.twig deleted file mode 100644 index 05da5b7f..00000000 --- a/src/ToolboxBundle/Resources/views/admin/settings/ckeditor-object-style.html.twig +++ /dev/null @@ -1,26 +0,0 @@ -{% if globalStyleSets is defined and globalStyleSets is iterable %} - {% for stylesSetName, stylesSetData in globalStyleSets %} - CKEDITOR.stylesSet.add('{{ stylesSetName }}', {{ stylesSetData|json_encode|raw }}); - {% endfor %} -{% endif %} - -CKEDITOR.on( 'instanceCreated', function( event ) { - - var editor = event.editor; - - //http://ckeditor.com/latest/samples/toolbarconfigurator/index.html#advanced - editor.on( 'configLoaded', function() { - - editor.config.allowedContent = undefined; - - {% if config is iterable %} - {% for configName, configData in config %} - if( editor.config.{{ configName }} === undefined || editor.config.{{ configName }} === '' ) { - editor.config.{{ configName }} = {{ configData|json_encode|raw }}; - } - {% endfor %} - {% endif %} - - }); - -}); diff --git a/src/ToolboxBundle/Resources/views/admin/settings/wysiwyg-area-style.html.twig b/src/ToolboxBundle/Resources/views/admin/settings/wysiwyg-area-style.html.twig new file mode 100644 index 00000000..f1c3d799 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/admin/settings/wysiwyg-area-style.html.twig @@ -0,0 +1,2 @@ +pimcore.document.editables.wysiwyg.defaultEditorConfig = pimcore.document.editables.wysiwyg.defaultEditorConfig || {}; +pimcore.document.editables.wysiwyg.defaultEditorConfig = {{ config|json_encode|raw }}; \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/admin/settings/wysiwyg-object-style.html.twig b/src/ToolboxBundle/Resources/views/admin/settings/wysiwyg-object-style.html.twig new file mode 100644 index 00000000..bd96d066 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/admin/settings/wysiwyg-object-style.html.twig @@ -0,0 +1,2 @@ +pimcore.object.tags.wysiwyg.defaultEditorConfig = pimcore.object.tags.wysiwyg.defaultEditorConfig || {}; +pimcore.object.tags.wysiwyg.defaultEditorConfig = {{ config|json_encode|raw }}; \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/areas/google-map/view.html.twig b/src/ToolboxBundle/Resources/views/areas/google_map/view.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/areas/google-map/view.html.twig rename to src/ToolboxBundle/Resources/views/areas/google_map/view.html.twig diff --git a/src/ToolboxBundle/Resources/views/areas/link-list/view.html.twig b/src/ToolboxBundle/Resources/views/areas/link_list/view.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/areas/link-list/view.html.twig rename to src/ToolboxBundle/Resources/views/areas/link_list/view.html.twig diff --git a/src/ToolboxBundle/Resources/views/areas/parallax-container/view.html.twig b/src/ToolboxBundle/Resources/views/areas/parallax_container/view.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/areas/parallax-container/view.html.twig rename to src/ToolboxBundle/Resources/views/areas/parallax_container/view.html.twig diff --git a/src/ToolboxBundle/Resources/views/areas/slide-columns/view.html.twig b/src/ToolboxBundle/Resources/views/areas/slide_columns/view.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/areas/slide-columns/view.html.twig rename to src/ToolboxBundle/Resources/views/areas/slide_columns/view.html.twig diff --git a/src/ToolboxBundle/Resources/views/areas/snippet/view.html.twig b/src/ToolboxBundle/Resources/views/areas/snippet/view.html.twig index d905b89f..5b2deefb 100644 --- a/src/ToolboxBundle/Resources/views/areas/snippet/view.html.twig +++ b/src/ToolboxBundle/Resources/views/areas/snippet/view.html.twig @@ -1,6 +1,10 @@ -{% import '@Toolbox/macro/wrap.html.twig' as wrap_macro %} -
- {{ wrap_macro.createWrapHead(elementThemeConfig) }} - {{ pimcore_snippet('snippet') }} - {{ wrap_macro.createWrapFoot(elementThemeConfig) }} -
\ No newline at end of file +{% if isHeadless is defined and isHeadless == true %} + {{ editmode ? inlineConfigElements|raw : '' }} +{% else %} + {% import '@Toolbox/macro/wrap.html.twig' as wrap_macro %} +
+ {{ wrap_macro.createWrapHead(elementThemeConfig) }} + {{ pimcore_snippet('snippet') }} + {{ wrap_macro.createWrapFoot(elementThemeConfig) }} +
+{% endif %} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/headless_document/index.html.twig b/src/ToolboxBundle/Resources/views/headless_document/index.html.twig new file mode 100644 index 00000000..d22e0152 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/headless_document/index.html.twig @@ -0,0 +1,4 @@ +{% extends '@Toolbox/headless_layout.html.twig' %} +{% block headless_document_content %} + {{ parent() }} +{% endblock headless_document_content %} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/headless_layout.html.twig b/src/ToolboxBundle/Resources/views/headless_layout.html.twig new file mode 100644 index 00000000..de808ef4 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/headless_layout.html.twig @@ -0,0 +1,13 @@ +{% block headless_document %} +
+ {% block headless_document_content %} + {% for editable_name, editable_config in editables %} + {% if editable_config.0 == 'areablock' %} + {{ pimcore_areablock(editable_name, editable_config.1) }} + {% elseif editable_config.0 == 'area' %} + {{ pimcore_area(editable_name, editable_config.1) }} + {% endif %} + {% endfor %} + {% endblock headless_document_content %} +
+{% endblock headless_document %} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/snippet/layout/teaser-layout.html.twig b/src/ToolboxBundle/Resources/views/snippet/layout/teaser_layout.html.twig similarity index 89% rename from src/ToolboxBundle/Resources/views/snippet/layout/teaser-layout.html.twig rename to src/ToolboxBundle/Resources/views/snippet/layout/teaser_layout.html.twig index 7aa821eb..3aabcfa6 100644 --- a/src/ToolboxBundle/Resources/views/snippet/layout/teaser-layout.html.twig +++ b/src/ToolboxBundle/Resources/views/snippet/layout/teaser_layout.html.twig @@ -1,4 +1,4 @@ -{% extends '@Toolbox/snippet-layout.html.twig' %} +{% extends '@Toolbox/snippet_layout.html.twig' %} {% block snippet_content %} {% if editmode %}
@@ -18,7 +18,7 @@
{% endif %} {% if pimcore_select('ts_type').isEmpty() == false %} - {% include '@Toolbox/snippet/teaser-' ~ pimcore_select('ts_type').getData() ~ '.html.twig' %} + {% include '@Toolbox/snippet/teaser_' ~ pimcore_select('ts_type').getData() ~ '.html.twig' %} {% endif %} {% if editmode %}
diff --git a/src/ToolboxBundle/Resources/views/snippet/teaser-default.html.twig b/src/ToolboxBundle/Resources/views/snippet/teaser_default.html.twig similarity index 92% rename from src/ToolboxBundle/Resources/views/snippet/teaser-default.html.twig rename to src/ToolboxBundle/Resources/views/snippet/teaser_default.html.twig index dcee69d6..80677b28 100644 --- a/src/ToolboxBundle/Resources/views/snippet/teaser-default.html.twig +++ b/src/ToolboxBundle/Resources/views/snippet/teaser_default.html.twig @@ -21,7 +21,7 @@

{{ pimcore_input('headline') }}

- {{ pimcore_wysiwyg('text', {'height' : 100, 'customConfig' : toolbox_get_ckeditor_config_path()}) }} + {{ pimcore_wysiwyg('text', {'height' : 100}) }}
{{ pimcore_link('link', {'class' : 'btn btn-default teaser-link'}) }} diff --git a/src/ToolboxBundle/Resources/views/snippet-layout.html.twig b/src/ToolboxBundle/Resources/views/snippet_layout.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/snippet-layout.html.twig rename to src/ToolboxBundle/Resources/views/snippet_layout.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/accordion/accordion-tab/accordion.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/accordion/accordion_tab/accordion.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap3/accordion/accordion-tab/accordion.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap3/accordion/accordion_tab/accordion.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/accordion/accordion-tab/tab.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/accordion/accordion_tab/tab.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap3/accordion/accordion-tab/tab.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap3/accordion/accordion_tab/tab.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/accordion/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/accordion/view.html.twig index 4519a4d6..45406986 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/accordion/view.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/accordion/view.html.twig @@ -1 +1 @@ -{% include toolbox_area_path(areaId, areaTemplateDirectory, '/accordion-tab/' ~ (pimcore_select('component').data == 'tab' ? 'tab' : 'accordion')) %} \ No newline at end of file +{% include toolbox_area_path(areaId, areaTemplateDirectory, '/accordion_tab/' ~ (pimcore_select('component').data == 'tab' ? 'tab' : 'accordion')) %} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/content/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/content/view.html.twig index 60b956a6..fd5b928a 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/content/view.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/content/view.html.twig @@ -1 +1 @@ -{{ pimcore_wysiwyg('wysiwyg', {'width' : '100%', 'customConfig' : toolbox_get_ckeditor_config_path()}) }} +{{ pimcore_wysiwyg('wysiwyg', {'width' : '100%'}) }} diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/google-map/info-window.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/google_map/info_window.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap3/google-map/info-window.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap3/google_map/info_window.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/google-map/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/google_map/view.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap3/google-map/view.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap3/google_map/view.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/link-list/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/link_list/view.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap3/link-list/view.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap3/link_list/view.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/partial/background-prepend.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/partial/background_prepend.html.twig similarity index 90% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/partial/background-prepend.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/partial/background_prepend.html.twig index 3e272b49..4693f6dc 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/partial/background-prepend.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/partial/background_prepend.html.twig @@ -1,6 +1,6 @@
- {% include toolbox_area_path(areaId, areaTemplateDirectory, 'partial/parallax-content') with { + {% include toolbox_area_path(areaId, areaTemplateDirectory, 'partial/parallax_content') with { 'behindElements' : behindElements, 'frontElements' : frontElements, 'sectionContent' : sectionContent diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/partial/background-wrap.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/partial/background_wrap.html.twig similarity index 88% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/partial/background-wrap.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/partial/background_wrap.html.twig index 7ce94dec..c3a3872b 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/partial/background-wrap.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/partial/background_wrap.html.twig @@ -1,5 +1,5 @@
- {% include toolbox_area_path(areaId, areaTemplateDirectory, 'partial/parallax-content') with { + {% include toolbox_area_path(areaId, areaTemplateDirectory, 'partial/parallax_content') with { 'behindElements' : behindElements, 'frontElements' : frontElements, 'sectionContent' : sectionContent diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/partial/behind-front-elements.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/partial/behind_front_elements.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/partial/behind-front-elements.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/partial/behind_front_elements.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/partial/parallax-content.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/partial/parallax_content.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/partial/parallax-content.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/partial/parallax_content.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/section.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/section.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/section.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/section.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/view.html.twig similarity index 62% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/view.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/view.html.twig index a1317c9a..5ff9aabc 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/view.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/view.html.twig @@ -1 +1 @@ -{% include toolbox_area_path(areaId, areaTemplateDirectory, 'partial/background-' ~ backgroundMode) %} +{% include toolbox_area_path(areaId, areaTemplateDirectory, 'partial/background_' ~ backgroundMode) %} diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/wrapper/container-wrapper.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/wrapper/container_wrapper.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax-container/wrapper/container-wrapper.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap3/parallax_container/wrapper/container_wrapper.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/slide-columns/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/slide_columns/view.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap3/slide-columns/view.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap3/slide_columns/view.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/teaser/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/teaser/view.html.twig index 69836885..729fb91a 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/teaser/view.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/teaser/view.html.twig @@ -4,7 +4,7 @@ {% if layout is empty %} {% set layout = 'standard' %} {% endif %} - {% include '@Toolbox/snippet/teaser-' ~ layout ~ '.html.twig' %} + {% include '@Toolbox/snippet/teaser_' ~ layout ~ '.html.twig' %} {% else %} {# "teaser-standard" is the snippet name. define your teaser layout in the specific teaser snippet! #} {{ pimcore_snippet('teaser-standard', {'useLightBox' : pimcore_checkbox('use_light_box').isChecked()}) }} diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/video/type-asset.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/video/type_asset.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap3/video/type-asset.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap3/video/type_asset.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/video/type-vimeo.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/video/type_vimeo.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap3/video/type-vimeo.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap3/video/type_vimeo.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/video/type-youtube.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/video/type_youtube.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap3/video/type-youtube.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap3/video/type_youtube.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/video/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/video/view.html.twig index 00f15267..1c257939 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/video/view.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/bootstrap3/video/view.html.twig @@ -14,7 +14,7 @@ {% else %}
- {% include toolbox_area_path(areaId, areaTemplateDirectory, 'type-' ~ videoType) %} + {% include toolbox_area_path(areaId, areaTemplateDirectory, 'type_' ~ videoType) %}
{% endif %} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/accordion/accordion-tab/accordion.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/accordion/accordion_tab/accordion.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap4/accordion/accordion-tab/accordion.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap4/accordion/accordion_tab/accordion.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/accordion/accordion-tab/tab.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/accordion/accordion_tab/tab.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap4/accordion/accordion-tab/tab.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap4/accordion/accordion_tab/tab.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/accordion/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/accordion/view.html.twig index 4519a4d6..45406986 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/accordion/view.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/accordion/view.html.twig @@ -1 +1 @@ -{% include toolbox_area_path(areaId, areaTemplateDirectory, '/accordion-tab/' ~ (pimcore_select('component').data == 'tab' ? 'tab' : 'accordion')) %} \ No newline at end of file +{% include toolbox_area_path(areaId, areaTemplateDirectory, '/accordion_tab/' ~ (pimcore_select('component').data == 'tab' ? 'tab' : 'accordion')) %} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/content/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/content/view.html.twig index 97bc5037..3b1c6ff9 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/content/view.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/content/view.html.twig @@ -1 +1 @@ -{{ pimcore_wysiwyg('wysiwyg', {'width' : '100%', 'customConfig' : toolbox_get_ckeditor_config_path()}) }} \ No newline at end of file +{{ pimcore_wysiwyg('wysiwyg', {'width' : '100%'}) }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/google-map/info-window.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/google_map/info_window.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap4/google-map/info-window.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap4/google_map/info_window.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/google-map/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/google_map/view.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap4/google-map/view.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap4/google_map/view.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/link-list/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/link_list/view.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap4/link-list/view.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap4/link_list/view.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/partial/background-prepend.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/partial/background_prepend.html.twig similarity index 90% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/partial/background-prepend.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/partial/background_prepend.html.twig index 2b885e2f..e1a9a416 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/partial/background-prepend.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/partial/background_prepend.html.twig @@ -1,6 +1,6 @@
- {% include toolbox_area_path(areaId, areaTemplateDirectory, 'partial/parallax-content') with { + {% include toolbox_area_path(areaId, areaTemplateDirectory, 'partial/parallax_content') with { 'behindElements' : behindElements, 'frontElements' : frontElements, 'sectionContent' : sectionContent diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/partial/background-wrap.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/partial/background_wrap.html.twig similarity index 88% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/partial/background-wrap.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/partial/background_wrap.html.twig index 5638f5f4..cfde289a 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/partial/background-wrap.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/partial/background_wrap.html.twig @@ -1,5 +1,5 @@
- {% include toolbox_area_path(areaId, areaTemplateDirectory, 'partial/parallax-content') with { + {% include toolbox_area_path(areaId, areaTemplateDirectory, 'partial/parallax_content') with { 'behindElements' : behindElements, 'frontElements' : frontElements, 'sectionContent' : sectionContent diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/partial/behind-front-elements.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/partial/behind_front_elements.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/partial/behind-front-elements.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/partial/behind_front_elements.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/partial/parallax-content.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/partial/parallax_content.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/partial/parallax-content.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/partial/parallax_content.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/section.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/section.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/section.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/section.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/view.html.twig similarity index 62% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/view.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/view.html.twig index a1317c9a..5ff9aabc 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/view.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/view.html.twig @@ -1 +1 @@ -{% include toolbox_area_path(areaId, areaTemplateDirectory, 'partial/background-' ~ backgroundMode) %} +{% include toolbox_area_path(areaId, areaTemplateDirectory, 'partial/background_' ~ backgroundMode) %} diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/wrapper/container-wrapper.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/wrapper/container_wrapper.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax-container/wrapper/container-wrapper.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap4/parallax_container/wrapper/container_wrapper.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/slide-columns/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/slide_columns/view.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap4/slide-columns/view.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap4/slide_columns/view.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/teaser/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/teaser/view.html.twig index 69836885..729fb91a 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/teaser/view.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/teaser/view.html.twig @@ -4,7 +4,7 @@ {% if layout is empty %} {% set layout = 'standard' %} {% endif %} - {% include '@Toolbox/snippet/teaser-' ~ layout ~ '.html.twig' %} + {% include '@Toolbox/snippet/teaser_' ~ layout ~ '.html.twig' %} {% else %} {# "teaser-standard" is the snippet name. define your teaser layout in the specific teaser snippet! #} {{ pimcore_snippet('teaser-standard', {'useLightBox' : pimcore_checkbox('use_light_box').isChecked()}) }} diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/video/type-asset.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/video/type_asset.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap4/video/type-asset.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap4/video/type_asset.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/video/type-vimeo.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/video/type_vimeo.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap4/video/type-vimeo.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap4/video/type_vimeo.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/video/type-youtube.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/video/type_youtube.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/bootstrap4/video/type-youtube.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/bootstrap4/video/type_youtube.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/video/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/video/view.html.twig index 00f15267..1c257939 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/video/view.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/bootstrap4/video/view.html.twig @@ -14,7 +14,7 @@ {% else %}
- {% include toolbox_area_path(areaId, areaTemplateDirectory, 'type-' ~ videoType) %} + {% include toolbox_area_path(areaId, areaTemplateDirectory, 'type_' ~ videoType) %}
{% endif %} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/accordion/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/accordion/view.html.twig new file mode 100644 index 00000000..25c45456 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/accordion/view.html.twig @@ -0,0 +1 @@ +{{ editmode ? inlineConfigElements|raw : '' }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/anchor/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/anchor/view.html.twig new file mode 100644 index 00000000..25c45456 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/anchor/view.html.twig @@ -0,0 +1 @@ +{{ editmode ? inlineConfigElements|raw : '' }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/columns/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/columns/view.html.twig new file mode 100644 index 00000000..25c45456 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/columns/view.html.twig @@ -0,0 +1 @@ +{{ editmode ? inlineConfigElements|raw : '' }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/container/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/container/view.html.twig new file mode 100644 index 00000000..25c45456 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/container/view.html.twig @@ -0,0 +1 @@ +{{ editmode ? inlineConfigElements|raw : '' }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/content/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/content/view.html.twig new file mode 100644 index 00000000..25c45456 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/content/view.html.twig @@ -0,0 +1 @@ +{{ editmode ? inlineConfigElements|raw : '' }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/download/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/download/view.html.twig new file mode 100644 index 00000000..25c45456 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/download/view.html.twig @@ -0,0 +1 @@ +{{ editmode ? inlineConfigElements|raw : '' }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/gallery/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/gallery/view.html.twig new file mode 100644 index 00000000..25c45456 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/gallery/view.html.twig @@ -0,0 +1 @@ +{{ editmode ? inlineConfigElements|raw : '' }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/google_map/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/google_map/view.html.twig new file mode 100644 index 00000000..25c45456 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/google_map/view.html.twig @@ -0,0 +1 @@ +{{ editmode ? inlineConfigElements|raw : '' }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/headline/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/headline/view.html.twig new file mode 100644 index 00000000..25c45456 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/headline/view.html.twig @@ -0,0 +1 @@ +{{ editmode ? inlineConfigElements|raw : '' }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/iframe/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/iframe/view.html.twig new file mode 100644 index 00000000..25c45456 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/iframe/view.html.twig @@ -0,0 +1 @@ +{{ editmode ? inlineConfigElements|raw : '' }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/image/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/image/view.html.twig new file mode 100644 index 00000000..25c45456 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/image/view.html.twig @@ -0,0 +1 @@ +{{ editmode ? inlineConfigElements|raw : '' }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/link_list/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/link_list/view.html.twig new file mode 100644 index 00000000..25c45456 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/link_list/view.html.twig @@ -0,0 +1 @@ +{{ editmode ? inlineConfigElements|raw : '' }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/parallax_container/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/parallax_container/view.html.twig new file mode 100644 index 00000000..b4413cbc --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/parallax_container/view.html.twig @@ -0,0 +1 @@ +{# not supported #} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/separator/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/separator/view.html.twig new file mode 100644 index 00000000..25c45456 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/separator/view.html.twig @@ -0,0 +1 @@ +{{ editmode ? inlineConfigElements|raw : '' }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/slide_columns/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/slide_columns/view.html.twig new file mode 100644 index 00000000..b4413cbc --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/slide_columns/view.html.twig @@ -0,0 +1 @@ +{# not supported #} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/spacer/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/spacer/view.html.twig new file mode 100644 index 00000000..25c45456 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/spacer/view.html.twig @@ -0,0 +1 @@ +{{ editmode ? inlineConfigElements|raw : '' }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/teaser/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/teaser/view.html.twig new file mode 100644 index 00000000..25c45456 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/teaser/view.html.twig @@ -0,0 +1 @@ +{{ editmode ? inlineConfigElements|raw : '' }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/headless/video/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/headless/video/view.html.twig new file mode 100644 index 00000000..25c45456 --- /dev/null +++ b/src/ToolboxBundle/Resources/views/toolbox/headless/video/view.html.twig @@ -0,0 +1 @@ +{{ editmode ? inlineConfigElements|raw : '' }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/uikit3/accordion/accordion-tab/accordion.html.twig b/src/ToolboxBundle/Resources/views/toolbox/uikit3/accordion/accordion_tab/accordion.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/uikit3/accordion/accordion-tab/accordion.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/uikit3/accordion/accordion_tab/accordion.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/uikit3/accordion/accordion-tab/tab.html.twig b/src/ToolboxBundle/Resources/views/toolbox/uikit3/accordion/accordion_tab/tab.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/uikit3/accordion/accordion-tab/tab.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/uikit3/accordion/accordion_tab/tab.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/uikit3/accordion/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/uikit3/accordion/view.html.twig index 4519a4d6..45406986 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/uikit3/accordion/view.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/uikit3/accordion/view.html.twig @@ -1 +1 @@ -{% include toolbox_area_path(areaId, areaTemplateDirectory, '/accordion-tab/' ~ (pimcore_select('component').data == 'tab' ? 'tab' : 'accordion')) %} \ No newline at end of file +{% include toolbox_area_path(areaId, areaTemplateDirectory, '/accordion_tab/' ~ (pimcore_select('component').data == 'tab' ? 'tab' : 'accordion')) %} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/uikit3/content/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/uikit3/content/view.html.twig index 97bc5037..3b1c6ff9 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/uikit3/content/view.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/uikit3/content/view.html.twig @@ -1 +1 @@ -{{ pimcore_wysiwyg('wysiwyg', {'width' : '100%', 'customConfig' : toolbox_get_ckeditor_config_path()}) }} \ No newline at end of file +{{ pimcore_wysiwyg('wysiwyg', {'width' : '100%'}) }} \ No newline at end of file diff --git a/src/ToolboxBundle/Resources/views/toolbox/uikit3/google-map/info-window.html.twig b/src/ToolboxBundle/Resources/views/toolbox/uikit3/google_map/info_window.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/uikit3/google-map/info-window.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/uikit3/google_map/info_window.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/uikit3/google-map/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/uikit3/google_map/view.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/uikit3/google-map/view.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/uikit3/google_map/view.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/uikit3/link-list/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/uikit3/link_list/view.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/uikit3/link-list/view.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/uikit3/link_list/view.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/uikit3/slide-columns/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/uikit3/slide_columns/view.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/uikit3/slide-columns/view.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/uikit3/slide_columns/view.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/uikit3/teaser/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/uikit3/teaser/view.html.twig index 69836885..729fb91a 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/uikit3/teaser/view.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/uikit3/teaser/view.html.twig @@ -4,7 +4,7 @@ {% if layout is empty %} {% set layout = 'standard' %} {% endif %} - {% include '@Toolbox/snippet/teaser-' ~ layout ~ '.html.twig' %} + {% include '@Toolbox/snippet/teaser_' ~ layout ~ '.html.twig' %} {% else %} {# "teaser-standard" is the snippet name. define your teaser layout in the specific teaser snippet! #} {{ pimcore_snippet('teaser-standard', {'useLightBox' : pimcore_checkbox('use_light_box').isChecked()}) }} diff --git a/src/ToolboxBundle/Resources/views/toolbox/uikit3/video/type-asset.html.twig b/src/ToolboxBundle/Resources/views/toolbox/uikit3/video/type_asset.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/uikit3/video/type-asset.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/uikit3/video/type_asset.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/uikit3/video/type-vimeo.html.twig b/src/ToolboxBundle/Resources/views/toolbox/uikit3/video/type_vimeo.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/uikit3/video/type-vimeo.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/uikit3/video/type_vimeo.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/uikit3/video/type-youtube.html.twig b/src/ToolboxBundle/Resources/views/toolbox/uikit3/video/type_youtube.html.twig similarity index 100% rename from src/ToolboxBundle/Resources/views/toolbox/uikit3/video/type-youtube.html.twig rename to src/ToolboxBundle/Resources/views/toolbox/uikit3/video/type_youtube.html.twig diff --git a/src/ToolboxBundle/Resources/views/toolbox/uikit3/video/view.html.twig b/src/ToolboxBundle/Resources/views/toolbox/uikit3/video/view.html.twig index 5410d037..8117c4d0 100644 --- a/src/ToolboxBundle/Resources/views/toolbox/uikit3/video/view.html.twig +++ b/src/ToolboxBundle/Resources/views/toolbox/uikit3/video/view.html.twig @@ -18,6 +18,6 @@ {% include toolbox_area_path(areaId, areaTemplateDirectory, '/partial/overlay') with {'posterPath' : posterPath, 'playInLightbox': playInLightbox} %} {% endif %} - {% include toolbox_area_path(areaId, areaTemplateDirectory, 'type-' ~ videoType) %} + {% include toolbox_area_path(areaId, areaTemplateDirectory, 'type_' ~ videoType) %}
{% endif %} \ No newline at end of file diff --git a/src/ToolboxBundle/Service/AssetService.php b/src/ToolboxBundle/Service/AssetService.php new file mode 100644 index 00000000..6a8fb763 --- /dev/null +++ b/src/ToolboxBundle/Service/AssetService.php @@ -0,0 +1,158 @@ +getThumbnail($thumbnailName); + + return $this->buildAssetData($image->getImage(), $thumbnail, $thumbnailOptions); + } + + public function generateImageThumbnail(Asset\Image $asset, ?string $thumbnailName, array $thumbnailOptions = []): array + { + $thumbnail = $asset->getThumbnail($thumbnailName); + + return $this->buildAssetData($asset, $thumbnail, $thumbnailOptions); + } + + private function buildAssetData(Asset $asset, Image\Thumbnail $thumbnail, array $options): array + { + $title = $asset->getMetadata('title'); + $description = $asset->getMetadata('description'); + $copyright = $asset->getMetadata('copyright'); + + return [ + 'title' => $title, + 'description' => $description, + 'copyright' => $copyright, + 'markup' => $thumbnail->getHtml($options), + 'mediaList' => $this->parseThumbnailPictureList($thumbnail, $options), + 'path' => $thumbnail->getFrontendPath(), + 'lowQualityPlaceholder' => $this->parseLowQualityPlaceholder($asset), + ]; + } + + private function parseLowQualityPlaceholder(Asset\Image $asset): string + { + $emptyGif = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; + + return $asset->getLowQualityPreviewDataUri() ?: $emptyGif; + } + + private function parseThumbnailPictureList(Asset\Image\Thumbnail $thumbnail, array $thumbnailOptions): array + { + $image = $thumbnail->getAsset(); + $thumbConfig = $thumbnail->getConfig(); + $mediaConfigs = $thumbConfig->getMedias(); + + $isAutoFormat = $thumbConfig instanceof Config && strtolower($thumbConfig->getFormat()) === 'source'; + + ksort($mediaConfigs, SORT_NUMERIC); + $mediaConfigs[] = $thumbConfig->getItems(); + + $data = []; + + foreach ($mediaConfigs as $mediaQuery => $config) { + + $thumbConfig->setItems($config); + $sourceAttributes = $this->getSourceTagAttributes($thumbnail, $thumbConfig, $mediaQuery, $image, $thumbnailOptions); + + if (empty($sourceAttributes)) { + continue; + } + + if (!$isAutoFormat) { + continue; + } + + foreach ($thumbConfig->getAutoFormatThumbnailConfigs() as $autoFormatConfig) { + $autoFormatThumbnailAttributes = $this->getSourceTagAttributes($thumbnail, $autoFormatConfig, $mediaQuery, $image, $thumbnailOptions); + if (!empty($autoFormatThumbnailAttributes)) { + $data[] = $autoFormatThumbnailAttributes; + } + } + + $data[] = $sourceAttributes; + } + + return $data; + + } + + private function getSourceTagAttributes(Asset\Image\Thumbnail $thumbnail, Config $thumbConfig, mixed $mediaQuery, Image $image, array $options): array + { + $sourceTagAttributes = []; + $sourceTagAttributes['srcset'] = $this->getSrcset($thumbnail->getAsset()->getFilename(), $thumbConfig, $image, $mediaQuery); + $thumb = $image->getThumbnail($thumbConfig, true); + + if ($mediaQuery) { + $sourceTagAttributes['media'] = $mediaQuery; + $thumb->reset(); + } + + if (isset($options['previewDataUri'])) { + $sourceTagAttributes['data-srcset'] = $sourceTagAttributes['srcset']; + unset($sourceTagAttributes['srcset']); + } + + if (!isset($options['disableWidthHeightAttributes'])) { + if ($thumb->getWidth()) { + $sourceTagAttributes['width'] = $thumb->getWidth(); + } + + if ($thumb->getHeight()) { + $sourceTagAttributes['height'] = $thumb->getHeight(); + } + } + + $sourceTagAttributes['type'] = $thumb->getMimeType(); + + $sourceCallback = $options['sourceCallback'] ?? null; + if ($sourceCallback) { + $sourceTagAttributes = $sourceCallback($sourceTagAttributes); + } + + return $sourceTagAttributes; + } + + private function getSrcset(string $fileName, Config $thumbConfig, Image $image, mixed $mediaQuery = null): string + { + $useOriginalFile = !$thumbConfig->isRasterizeSVG() && preg_match("@\.svgz?$@", $fileName); + + $srcSetValues = []; + foreach ([1, 2] as $highRes) { + + $thumbConfigRes = clone $thumbConfig; + + if ($mediaQuery) { + $thumbConfigRes->selectMedia($mediaQuery); + } + + $thumbConfigRes->setHighResolution($highRes); + $thumb = $image->getThumbnail($thumbConfigRes, true); + + $descriptor = $highRes . 'x'; + // encode comma in thumbnail path as srcset is a comma separated list + $srcSetValues[] = str_replace(',', '%2C', $thumb . ' ' . $descriptor); + + if ($useOriginalFile && $thumbConfig->isSvgTargetFormatPossible()) { + break; + } + } + + return implode(', ', $srcSetValues); + } +} diff --git a/src/ToolboxBundle/Service/DataAttributeService.php b/src/ToolboxBundle/Service/DataAttributeService.php new file mode 100644 index 00000000..f29eaa00 --- /dev/null +++ b/src/ToolboxBundle/Service/DataAttributeService.php @@ -0,0 +1,80 @@ +generateAttributeStack($node, $overrides, $ignoreNonExistingCoreAttributes); + + if ($values === null) { + return ''; + } + + return $this->parseValues($values); + } + + public function generateDataAttributesAsArray(string $node, array $overrides = [], bool $ignoreNonExistingCoreAttributes = false): array + { + $values = $this->generateAttributeStack($node, $overrides, $ignoreNonExistingCoreAttributes); + + if ($values === null) { + return []; + } + + return $values; + } + + private function generateAttributeStack(string $node, array $overrides = [], bool $ignoreNonExistingCoreAttributes = false): ?array + { + $attributesNode = $this->configManager->getConfig('data_attributes'); + + $coreAttributesAvailable = !empty($attributesNode[$node]['values']) && is_array($attributesNode[$node]['values']); + + if ($ignoreNonExistingCoreAttributes === false && $coreAttributesAvailable === false) { + return null; + } + + $coreAttributes = $coreAttributesAvailable === false ? [] : $attributesNode[$node]['values']; + + return array_merge($coreAttributes, $overrides); + } + + private function parseValues(array $values): string + { + $attributes = []; + + foreach ($values as $key => $value) { + //continue if real empty + if (!is_bool($value) && (($value === 0 || $value) === false)) { + continue; + } + + if (is_array($value)) { + $parsedValue = htmlspecialchars(json_encode($value)); + } elseif (is_bool($value)) { + $parsedValue = $value ? 'true' : 'false'; + } elseif (is_object($value)) { + $parsedValue = get_class($value); + } else { + $parsedValue = $value; + } + + $attributes[] = 'data-' . $this->lineToDash($key) . '="' . $parsedValue . '"'; + } + + return implode(' ', $attributes); + } + + private function lineToDash(string $input): string + { + return preg_replace('/_/', '-', $input); + } +} diff --git a/src/ToolboxBundle/Service/DownloadInfoService.php b/src/ToolboxBundle/Service/DownloadInfoService.php new file mode 100644 index 00000000..07ee79cb --- /dev/null +++ b/src/ToolboxBundle/Service/DownloadInfoService.php @@ -0,0 +1,112 @@ +bundleConnector->hasBundle('MembersBundle') === true && + $this->bundleConnector->getBundleService(\MembersBundle\Manager\RestrictionManager::class)->elementIsInProtectedStorageFolder($download) + ) { + $dPath = $this->bundleConnector->getBundleService(\MembersBundle\Security\RestrictionUri::class)->generateAssetUrl($download); + } else { + $dPath = $download->getFullPath(); + } + + if ($fileSizeUnit === 'optimized') { + $realSize = $download->getFileSize(); + $dSize = $this->getOptimizedFileSize($realSize, $fileSizePrecision); + } else { + $dSize = $download->getFileSize($fileSizeUnit, $fileSizePrecision); + } + + $dType = pathinfo($download->getFilename(), PATHINFO_EXTENSION); + $downloadTitle = $showFileNameIfTitleEmpty ? $download->getFilename() : $this->translator->trans('Download', [], 'admin'); + $dName = ($download->getMetadata('title')) ?: $downloadTitle; + $dAltText = $download->getMetadata('alt') ?: ''; + $dImageAltText = !empty($dAltText) ? $dAltText : $dName; + + $dPreviewImage = null; + $previewThumbName = $this->configManager->getImageThumbnailFromConfig('download_preview_thumbnail'); + + if ($showPreviewImage) { + $metaPreviewImage = $download->getMetadata('previewImage'); + /** @phpstan-ignore-next-line */ + if ($metaPreviewImage instanceof Asset\Image) { + $dPreviewImage = $metaPreviewImage->getThumbnail($previewThumbName); + } elseif ($download instanceof Asset\Image) { + $dPreviewImage = $download->getThumbnail($previewThumbName); + } elseif ($download instanceof Asset\Document) { + $dPreviewImage = $download->getImageThumbnail($previewThumbName); + } + } + + $dPreviewImagePath = null; + $hasPreviewImage = false; + + if ($dPreviewImage instanceof Asset\Image\Thumbnail) { + $dPreviewImagePath = $dPreviewImage->getPath(); + $hasPreviewImage = true; + } elseif ($dPreviewImage instanceof Asset\Document\ImageThumbnail && !empty($dPreviewImage->getConfig())) { + $dPreviewImagePath = $dPreviewImage->getPath(); + $hasPreviewImage = true; + } + + return [ + 'path' => $dPath, + 'size' => $dSize, + 'type' => $dType, + 'name' => $dName, + 'altText' => $dAltText, + 'imageAltText' => $dImageAltText, + 'previewImage' => $dPreviewImage, + 'hasPreviewImage' => $hasPreviewImage, + 'previewImagePath' => $dPreviewImagePath + ]; + } + + public function getOptimizedFileSize(mixed $bytes, int $precision): string + { + if ($bytes >= 1073741824) { + $bytes = number_format($bytes / 1073741824, 2); + $format = 'gb'; + } elseif ($bytes >= 1048576) { + $bytes = number_format($bytes / 1048576, 2); + $format = 'mb'; + } elseif ($bytes >= 1024) { + $bytes = number_format($bytes / 1024, 2); + $format = 'kb'; + } elseif ($bytes > 1) { + $format = 'bytes'; + } elseif ($bytes === 1) { + $format = 'byte'; + } else { + $format = 'bytes'; + } + + return round((float) $bytes, $precision) . ' ' . $format; + } +} diff --git a/src/ToolboxBundle/Tool/Install.php b/src/ToolboxBundle/Tool/Install.php index ea22c6a2..15904ba6 100644 --- a/src/ToolboxBundle/Tool/Install.php +++ b/src/ToolboxBundle/Tool/Install.php @@ -38,7 +38,6 @@ private function installDocumentTypes(): void $skipInstall = false; $elementName = 'Teaser Snippet'; - /** @var DocType $type */ foreach ($list->getDocTypes() as $type) { if ($type->getName() === $elementName) { $skipInstall = true; diff --git a/src/ToolboxBundle/ToolboxBundle.php b/src/ToolboxBundle/ToolboxBundle.php index 991b540f..9b17ea77 100644 --- a/src/ToolboxBundle/ToolboxBundle.php +++ b/src/ToolboxBundle/ToolboxBundle.php @@ -9,7 +9,9 @@ use ToolboxBundle\DependencyInjection\Compiler\AreaBrickAutoloadWatcherPass; use ToolboxBundle\DependencyInjection\Compiler\AreaBrickRegistryPass; use ToolboxBundle\DependencyInjection\Compiler\CalculatorRegistryPass; +use ToolboxBundle\DependencyInjection\Compiler\EditableHandlerPass; use ToolboxBundle\DependencyInjection\Compiler\MembersBundlePass; +use ToolboxBundle\DependencyInjection\Compiler\NormalizerRegistryPass; use ToolboxBundle\DependencyInjection\Compiler\StoreProviderPass; use ToolboxBundle\Tool\Install; @@ -19,16 +21,15 @@ class ToolboxBundle extends AbstractPimcoreBundle public const PACKAGE_NAME = 'dachcom-digital/toolbox'; - /** - * {@inheritdoc} - */ - public function build(ContainerBuilder $container) + public function build(ContainerBuilder $container): void { $container->addCompilerPass(new AreaBrickRegistryPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 255); $container->addCompilerPass(new AreaBrickAutoloadWatcherPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -255); + $container->addCompilerPass(new EditableHandlerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -255); $container->addCompilerPass(new MembersBundlePass()); $container->addCompilerPass(new CalculatorRegistryPass()); $container->addCompilerPass(new StoreProviderPass()); + $container->addCompilerPass(new NormalizerRegistryPass()); } public function getInstaller(): Install @@ -36,46 +37,8 @@ public function getInstaller(): Install return $this->container->get(Install::class); } - public function getJsPaths(): array - { - return [ - '/admin/toolbox-ckeditor-object-style.js', - '/bundles/toolbox/js/toolbox-ckeditor-plugins.js', - '/bundles/toolbox/js/document/edit.js' - ]; - } - - public function getEditmodeJsPaths(): array - { - return [ - '/bundles/toolbox/js/toolbox-ckeditor-plugins.js', - '/bundles/toolbox/js/document/editables/areablock.js', - '/bundles/toolbox/js/document/editables/googlemap.js', - '/bundles/toolbox/js/document/editables/parallaximage.js', - '/bundles/toolbox/js/document/editables/columnadjuster.js', - '/bundles/toolbox/js/document/editables/vhs.js', - '/bundles/toolbox/js/document/editables/vhs/editor.js', - ]; - } - - public function getEditmodeCssPaths(): array - { - return [ - '/bundles/toolbox/css/admin.css', - '/bundles/toolbox/css/admin_uikit.css' - ]; - } - protected function getComposerPackageName(): string { return self::PACKAGE_NAME; } - - /** - * @return string - */ - protected static function getPimcoreVersion() - { - return preg_replace('/[^0-9.]/', '', \Pimcore\Version::getVersion()); - } } diff --git a/src/ToolboxBundle/ToolboxConfig.php b/src/ToolboxBundle/ToolboxConfig.php index c259599e..87e38c50 100644 --- a/src/ToolboxBundle/ToolboxConfig.php +++ b/src/ToolboxBundle/ToolboxConfig.php @@ -4,7 +4,7 @@ final class ToolboxConfig { - public const TOOLBOX_TYPES = [ + public const TOOLBOX_AREA_TYPES = [ 'accordion', 'anchor', 'columns', @@ -26,38 +26,4 @@ final class ToolboxConfig 'teaser', 'video' ]; - - public const CORE_TYPES = [ - 'areablock', - 'area', - 'block', - 'checkbox', - 'date', - 'href', - 'image', - 'input', - 'link', - 'multihref', - 'multiselect', - 'numeric', - 'embed', - 'pdf', - 'relation', - 'relations', - 'renderlet', - 'select', - 'snippet', - 'table', - 'textarea', - 'video', - 'wysiwyg' - ]; - - public const CUSTOM_TYPES = [ - 'additionalClasses', - 'additionalClassesChained', - 'parallaximage', - 'googlemap', - 'vhs', - ]; } diff --git a/src/ToolboxBundle/ToolboxEvents.php b/src/ToolboxBundle/ToolboxEvents.php new file mode 100644 index 00000000..9e95bde1 --- /dev/null +++ b/src/ToolboxBundle/ToolboxEvents.php @@ -0,0 +1,13 @@ +configManager = $configManager; - $this->areaManager = $areaManager; } public function getFunctions(): array diff --git a/src/ToolboxBundle/Twig/Extension/CkEditorExtension.php b/src/ToolboxBundle/Twig/Extension/CkEditorExtension.php deleted file mode 100644 index 8d87702f..00000000 --- a/src/ToolboxBundle/Twig/Extension/CkEditorExtension.php +++ /dev/null @@ -1,30 +0,0 @@ - true - ]) - ]; - } - - public function getConfigPath(array $context): string - { - $document = $context['document']; - $documentId = 0; - if ($document instanceof Document) { - $documentId = $document->getId(); - } - - return sprintf('/admin/toolbox-ckeditor-style.js?tb_document_request_id=%s', $documentId); - } -} diff --git a/src/ToolboxBundle/Twig/Extension/DataAttributesExtension.php b/src/ToolboxBundle/Twig/Extension/DataAttributesExtension.php index 960dbcae..f6f4d0a6 100644 --- a/src/ToolboxBundle/Twig/Extension/DataAttributesExtension.php +++ b/src/ToolboxBundle/Twig/Extension/DataAttributesExtension.php @@ -2,90 +2,21 @@ namespace ToolboxBundle\Twig\Extension; -use ToolboxBundle\Manager\ConfigManagerInterface; +use ToolboxBundle\Service\DataAttributeService; use Twig\Extension\AbstractExtension; use Twig\TwigFunction; class DataAttributesExtension extends AbstractExtension { - protected ConfigManagerInterface $configManager; - - public function __construct(ConfigManagerInterface $configManager) + public function __construct(protected DataAttributeService $dataAttributeService) { - $this->configManager = $configManager; } public function getFunctions(): array { return [ - new TwigFunction('toolbox_data_attributes_generator', [$this, 'generateDataAttributes']), + new TwigFunction('toolbox_data_attributes_generator', [$this->dataAttributeService, 'generateDataAttributes']), ]; } - /** - * @param string $node - * @param array $overrides - * @param bool $ignoreNonExistingCoreAttributes - * - * @return string - * - * @throws \Exception - */ - public function generateDataAttributes($node, $overrides = [], $ignoreNonExistingCoreAttributes = false) - { - $attributesNode = $this->configManager->getConfig('data_attributes'); - - $coreAttributesAvailable = isset($attributesNode[$node]['values']) && is_array($attributesNode[$node]['values']) && !empty($attributesNode[$node]['values']); - - if ($ignoreNonExistingCoreAttributes === false && $coreAttributesAvailable === false) { - return ''; - } - - $coreAttributes = $coreAttributesAvailable === false ? [] : $attributesNode[$node]['values']; - - $values = array_merge($coreAttributes, $overrides); - - return $this->parseValues($values); - } - - /** - * @param array $values - * - * @return string - */ - private function parseValues($values) - { - $attributes = []; - - foreach ($values as $key => $value) { - //continue if real empty - if (!is_bool($value) && (($value === 0 || $value) === false)) { - continue; - } - - if (is_array($value)) { - $parsedValue = htmlspecialchars(json_encode($value)); - } elseif (is_bool($value)) { - $parsedValue = $value ? 'true' : 'false'; - } elseif (is_object($value)) { - $parsedValue = get_class($value); - } else { - $parsedValue = $value; - } - - $attributes[] = 'data-' . $this->lineToDash($key) . '="' . $parsedValue . '"'; - } - - return implode(' ', $attributes); - } - - /** - * @param string $input - * - * @return mixed - */ - private function lineToDash($input) - { - return preg_replace('/_/', '-', $input); - } } diff --git a/src/ToolboxBundle/Twig/Extension/DownloadExtension.php b/src/ToolboxBundle/Twig/Extension/DownloadExtension.php index 1b4cadaf..18bbf417 100644 --- a/src/ToolboxBundle/Twig/Extension/DownloadExtension.php +++ b/src/ToolboxBundle/Twig/Extension/DownloadExtension.php @@ -2,11 +2,8 @@ namespace ToolboxBundle\Twig\Extension; -use Pimcore\File; -use Pimcore\Model\Asset; -use ToolboxBundle\Connector\BundleConnector; -use Pimcore\Translation\Translator; use ToolboxBundle\Manager\ConfigManagerInterface; +use ToolboxBundle\Service\DownloadInfoService; use Twig\Extension\AbstractExtension; use Twig\TwigFunction; @@ -14,20 +11,15 @@ class DownloadExtension extends AbstractExtension { public function __construct( protected ConfigManagerInterface $configManager, - protected BundleConnector $bundleConnector, - protected Translator $translator + protected DownloadInfoService $downloadInfoService ) { } public function getFunctions(): array { return [ - new TwigFunction('toolbox_download_info', [$this, 'getDownloadInfo']), - new TwigFunction( - 'toolbox_download_tracker', - [$this, 'getDownloadTracker'], - ['is_safe' => ['html']] - ) + new TwigFunction('toolbox_download_info', [$this->downloadInfoService, 'getDownloadInfo']), + new TwigFunction('toolbox_download_tracker', [$this, 'getDownloadTracker'], ['is_safe' => ['html']]) ]; } @@ -43,7 +35,7 @@ public function getDownloadTracker(mixed $areaType, mixed $element = null): stri if (is_array($areaType)) { $trackerInfo = $areaType; } else { - $configNode = $this->configManager->setAreaNameSpace(ConfigManagerInterface::AREABRICK_NAMESPACE_INTERNAL)->getAreaParameterConfig($areaType); + $configNode = $this->configManager->getAreaParameterConfig($areaType); if (empty($configNode) || !isset($configNode['event_tracker'])) { return ''; @@ -75,98 +67,4 @@ public function getDownloadTracker(mixed $areaType, mixed $element = null): stri return $str; } - - /** - * @throws \Exception - */ - public function getDownloadInfo( - Asset $download, - bool $showPreviewImage = false, - string $fileSizeUnit = 'optimized', - int $fileSizePrecision = 0, - bool $showFileNameIfTitleEmpty = false - ): array { - - if ( - $this->bundleConnector->hasBundle('MembersBundle') === true && - $this->bundleConnector->getBundleService(\MembersBundle\Manager\RestrictionManager::class)->elementIsInProtectedStorageFolder($download) - ) { - $dPath = $this->bundleConnector->getBundleService(\MembersBundle\Security\RestrictionUri::class)->generateAssetUrl($download); - } else { - $dPath = $download->getFullPath(); - } - - if ($fileSizeUnit === 'optimized') { - $realSize = $download->getFileSize(); - $dSize = $this->getOptimizedFileSize($realSize, $fileSizePrecision); - } else { - $dSize = $download->getFileSize($fileSizeUnit, $fileSizePrecision); - } - - $dType = File::getFileExtension($download->getFilename()); - $downloadTitle = $showFileNameIfTitleEmpty ? $download->getFilename() : $this->translator->trans('Download', [], 'admin'); - $dName = ($download->getMetadata('title')) ?: $downloadTitle; - $dAltText = $download->getMetadata('alt') ?: ''; - $dImageAltText = !empty($dAltText) ? $dAltText : $dName; - - $dPreviewImage = null; - $previewThumbName = $this->configManager->getImageThumbnailFromConfig('download_preview_thumbnail'); - - if ($showPreviewImage) { - $metaPreviewImage = $download->getMetadata('previewImage'); - /** @phpstan-ignore-next-line */ - if ($metaPreviewImage instanceof Asset\Image) { - $dPreviewImage = $metaPreviewImage->getThumbnail($previewThumbName); - } elseif ($download instanceof Asset\Image) { - $dPreviewImage = $download->getThumbnail($previewThumbName); - } elseif ($download instanceof Asset\Document) { - $dPreviewImage = $download->getImageThumbnail($previewThumbName); - } - } - - $dPreviewImagePath = null; - $hasPreviewImage = false; - - if ($dPreviewImage instanceof Asset\Image\Thumbnail) { - $dPreviewImagePath = $dPreviewImage->getPath(); - $hasPreviewImage = true; - } elseif ($dPreviewImage instanceof Asset\Document\ImageThumbnail && !empty($dPreviewImage->getConfig())) { - $dPreviewImagePath = $dPreviewImage->getPath(); - $hasPreviewImage = true; - } - - return [ - 'path' => $dPath, - 'size' => $dSize, - 'type' => $dType, - 'name' => $dName, - 'altText' => $dAltText, - 'imageAltText' => $dImageAltText, - 'previewImage' => $dPreviewImage, - 'hasPreviewImage' => $hasPreviewImage, - 'previewImagePath' => $dPreviewImagePath - ]; - } - - public function getOptimizedFileSize(mixed $bytes, int $precision): string - { - if ($bytes >= 1073741824) { - $bytes = number_format($bytes / 1073741824, 2); - $format = 'gb'; - } elseif ($bytes >= 1048576) { - $bytes = number_format($bytes / 1048576, 2); - $format = 'mb'; - } elseif ($bytes >= 1024) { - $bytes = number_format($bytes / 1024, 2); - $format = 'kb'; - } elseif ($bytes > 1) { - $format = 'bytes'; - } elseif ($bytes === 1) { - $format = 'byte'; - } else { - $format = 'bytes'; - } - - return round((float) $bytes, $precision) . ' ' . $format; - } } diff --git a/src/ToolboxBundle/Twig/Extension/GoogleAPIKeysExtension.php b/src/ToolboxBundle/Twig/Extension/GoogleAPIKeysExtension.php index 36491f25..4f0e43de 100644 --- a/src/ToolboxBundle/Twig/Extension/GoogleAPIKeysExtension.php +++ b/src/ToolboxBundle/Twig/Extension/GoogleAPIKeysExtension.php @@ -8,15 +8,10 @@ class GoogleAPIKeysExtension extends AbstractExtension { - protected ?string $fallbackBrowserKey; - protected ConfigManagerInterface $configManager; - public function __construct( - ?string $fallbackBrowserKey, - ConfigManagerInterface $configManager + protected ?string $fallbackBrowserKey, + protected ConfigManagerInterface $configManager ) { - $this->fallbackBrowserKey = $fallbackBrowserKey; - $this->configManager = $configManager; } public function getFunctions(): array @@ -27,16 +22,14 @@ public function getFunctions(): array } /** - * @return mixed - * * @throws \Exception */ - public function getGoogleMapAPIKey() + public function getGoogleMapAPIKey(): mixed { $browserKey = 'please_configure_key_in_systemsettings'; - $configNode = $this->configManager->setAreaNameSpace(ConfigManagerInterface::AREABRICK_NAMESPACE_INTERNAL)->getAreaParameterConfig('googleMap'); + $configNode = $this->configManager->getAreaParameterConfig('googleMap'); - if (!empty($configNode) && isset($configNode['map_api_key']) && !empty($configNode['map_api_key'])) { + if (!empty($configNode) && !empty($configNode['map_api_key'])) { return $configNode['map_api_key']; } diff --git a/src/ToolboxBundle/Twig/Extension/ImageThumbnailExtension.php b/src/ToolboxBundle/Twig/Extension/ImageThumbnailExtension.php index e2c34732..bf4069d1 100644 --- a/src/ToolboxBundle/Twig/Extension/ImageThumbnailExtension.php +++ b/src/ToolboxBundle/Twig/Extension/ImageThumbnailExtension.php @@ -8,11 +8,8 @@ class ImageThumbnailExtension extends AbstractExtension { - protected ConfigManagerInterface $configManager; - - public function __construct(ConfigManagerInterface $configManager) + public function __construct(protected ConfigManagerInterface $configManager) { - $this->configManager = $configManager; } public function getFunctions(): array @@ -23,13 +20,9 @@ public function getFunctions(): array } /** - * @param null $thumbnailName - * - * @return mixed - * * @throws \Exception */ - public function getImageThumbnail($thumbnailName = null) + public function getImageThumbnail(string $thumbnailName): ?string { return $this->configManager->getImageThumbnailFromConfig($thumbnailName); } diff --git a/src/ToolboxBundle/Twig/Extension/LayoutExtension.php b/src/ToolboxBundle/Twig/Extension/LayoutExtension.php index 99c5cb15..f019cbff 100644 --- a/src/ToolboxBundle/Twig/Extension/LayoutExtension.php +++ b/src/ToolboxBundle/Twig/Extension/LayoutExtension.php @@ -8,11 +8,8 @@ class LayoutExtension extends AbstractExtension { - protected LayoutManager $layoutManager; - - public function __construct(LayoutManager $layoutManager) + public function __construct(protected LayoutManager $layoutManager) { - $this->layoutManager = $layoutManager; } public function getFunctions(): array diff --git a/tests/AcceptanceDefault.suite.dist.yml b/tests/AcceptanceDefault.suite.dist.yml new file mode 100644 index 00000000..68f19580 --- /dev/null +++ b/tests/AcceptanceDefault.suite.dist.yml @@ -0,0 +1,21 @@ +actor: AcceptanceTester +error_level: '%PIMCORE_PHP_ERROR_REPORTING%' +modules: + config: + \Dachcom\Codeception\Support\Helper\Browser\WebDriver: + host: '%WEBDRIVER_HOST%' + url: '%WEBDRIVER_URL%' + browser: chrome + port: 4444 + restart: true + enabled: + - \Dachcom\Codeception\Support\Helper\PimcoreCore: + part: SERVICES + connect_db: true + rebootable_client: true + - \Dachcom\Codeception\Support\Helper\PimcoreBundleCore: + run_installer: true + - \DachcomBundle\Test\Support\Helper\Toolbox + - \Dachcom\Codeception\Support\Helper\Browser\WebDriver + - \Dachcom\Codeception\Support\Helper\PimcoreBackend + - \Dachcom\Codeception\Support\Helper\PimcoreUser \ No newline at end of file diff --git a/tests/acceptance.default/AreaPositionCest.php b/tests/AcceptanceDefault/AreaPositionCest.php similarity index 96% rename from tests/acceptance.default/AreaPositionCest.php rename to tests/AcceptanceDefault/AreaPositionCest.php index 7c35ef64..11b75ff8 100644 --- a/tests/acceptance.default/AreaPositionCest.php +++ b/tests/AcceptanceDefault/AreaPositionCest.php @@ -2,13 +2,11 @@ namespace DachcomBundle\Test\AcceptanceDefault; -use DachcomBundle\Test\AcceptanceTester; +use DachcomBundle\Test\Support\AcceptanceTester; class AreaPositionCest { /** - * @param AcceptanceTester $I - * * @throws \Exception */ public function testAreaButtonsPosition(AcceptanceTester $I) diff --git a/tests/acceptance.default/_bootstrap.php b/tests/AcceptanceDefault/_bootstrap.php similarity index 100% rename from tests/acceptance.default/_bootstrap.php rename to tests/AcceptanceDefault/_bootstrap.php diff --git a/tests/FunctionalDefault.suite.dist.yml b/tests/FunctionalDefault.suite.dist.yml new file mode 100644 index 00000000..696491a2 --- /dev/null +++ b/tests/FunctionalDefault.suite.dist.yml @@ -0,0 +1,15 @@ +actor: FunctionalTester +error_level: '%PIMCORE_PHP_ERROR_REPORTING%' +modules: + enabled: + - \Dachcom\Codeception\Support\Helper\PimcoreCore: + connect_db: true + rebootable_client: true + - \Dachcom\Codeception\Support\Helper\PimcoreBundleCore: + run_installer: true + - \Dachcom\Codeception\Support\Helper\Browser\PhpBrowser: + depends: \Dachcom\Codeception\Support\Helper\PimcoreCore + - \Dachcom\Codeception\Support\Helper\PimcoreAdminJson: + depends: \Dachcom\Codeception\Support\Helper\PimcoreCore + - \Dachcom\Codeception\Support\Helper\PimcoreBackend + - \Dachcom\Codeception\Support\Helper\PimcoreUser \ No newline at end of file diff --git a/tests/functional.default/Controller/AdminColumnAdjusterControllerCest.php b/tests/FunctionalDefault/Controller/AdminColumnAdjusterControllerCest.php similarity index 99% rename from tests/functional.default/Controller/AdminColumnAdjusterControllerCest.php rename to tests/FunctionalDefault/Controller/AdminColumnAdjusterControllerCest.php index 975c7766..9df6d39c 100644 --- a/tests/functional.default/Controller/AdminColumnAdjusterControllerCest.php +++ b/tests/FunctionalDefault/Controller/AdminColumnAdjusterControllerCest.php @@ -2,13 +2,10 @@ namespace DachcomBundle\Test\FunctionalDefault\Controller; -use DachcomBundle\Test\FunctionalTester; +use DachcomBundle\Test\Support\FunctionalTester; class AdminColumnAdjusterControllerCest { - /** - * @param FunctionalTester $I - */ public function testToolboxColumnInfoWithoutCustomInfo(FunctionalTester $I) { $I->haveAUser('dachcom_test'); diff --git a/tests/functional.default/Controller/AjaxControllerCest.php b/tests/FunctionalDefault/Controller/AjaxControllerCest.php similarity index 93% rename from tests/functional.default/Controller/AjaxControllerCest.php rename to tests/FunctionalDefault/Controller/AjaxControllerCest.php index 69b9b2d9..40340406 100644 --- a/tests/functional.default/Controller/AjaxControllerCest.php +++ b/tests/FunctionalDefault/Controller/AjaxControllerCest.php @@ -2,13 +2,10 @@ namespace DachcomBundle\Test\FunctionalDefault\Controller; -use DachcomBundle\Test\FunctionalTester; +use DachcomBundle\Test\Support\FunctionalTester; class AjaxControllerCest { - /** - * @param FunctionalTester $I - */ public function testGoogleMapInfoWindow(FunctionalTester $I) { $query = [ diff --git a/tests/functional.default/Controller/SnippetControllerCest.php b/tests/FunctionalDefault/Controller/SnippetControllerCest.php similarity index 95% rename from tests/functional.default/Controller/SnippetControllerCest.php rename to tests/FunctionalDefault/Controller/SnippetControllerCest.php index f3f984cb..9b94c48b 100644 --- a/tests/functional.default/Controller/SnippetControllerCest.php +++ b/tests/FunctionalDefault/Controller/SnippetControllerCest.php @@ -2,13 +2,10 @@ namespace DachcomBundle\Test\FunctionalDefault\Controller; -use DachcomBundle\Test\FunctionalTester; +use DachcomBundle\Test\Support\FunctionalTester; class SnippetControllerCest { - /** - * @param FunctionalTester $I - */ public function testSnippetController(FunctionalTester $I) { $snippetParams = [ diff --git a/tests/functional.default/_bootstrap.php b/tests/FunctionalDefault/_bootstrap.php similarity index 100% rename from tests/functional.default/_bootstrap.php rename to tests/FunctionalDefault/_bootstrap.php diff --git a/tests/Support/AcceptanceTester.php b/tests/Support/AcceptanceTester.php new file mode 100644 index 00000000..8c034363 --- /dev/null +++ b/tests/Support/AcceptanceTester.php @@ -0,0 +1,8 @@ +setupRequest(['mock_toolbox_context' => 'disabled']); /** @var ConfigManagerInterface $configManager */ $configManager = $this->getContainer()->get(ConfigManager::class); - $ckEditorSettings = $configManager->getConfig('ckeditor'); + $wysiwygSettings = $configManager->getConfig('wysiwyg_editor'); - $this->assertArrayHasKey('config', $ckEditorSettings); - $this->assertArrayHasKey('global_style_sets', $ckEditorSettings); - $globalStyleSets = $ckEditorSettings['global_style_sets']; - - $this->assertArrayHasKey('default', $globalStyleSets); + $this->assertArrayHasKey('config', $wysiwygSettings); + $this->assertArrayHasKey('style_formats', $wysiwygSettings['config']); + $styleFormats = $wysiwygSettings['config']['style_formats']; $data = [ [ - 'name' => 'Lead Global', - 'element' => 'p', - 'attributes' => ['class' => 'lead'], + 'title' => 'Lead Global', + 'selector' => 'p', + 'classes' => 'lead', ] ]; - $this->assertEquals($data, $globalStyleSets['default']); + $this->assertEquals($data, $styleFormats); } /** * @throws \Codeception\Exception\ModuleException */ - public function testCkEditorSettingsOnContextConfiguration() + public function testWysiwygEditorSettingsOnContextConfiguration() { $this->setupRequest(['mock_toolbox_context' => 'context_a']); /** @var ConfigManagerInterface $configManager */ $configManager = $this->getContainer()->get(ConfigManager::class); - $ckEditorSettings = $configManager->getConfig('ckeditor'); - - $this->assertArrayHasKey('config', $ckEditorSettings); - $this->assertArrayHasKey('global_style_sets', $ckEditorSettings); - $globalStyleSets = $ckEditorSettings['global_style_sets']; + $wysiwygSettings = $configManager->getConfig('wysiwyg_editor'); - $this->assertArrayHasKey('default', $globalStyleSets); + $this->assertArrayHasKey('config', $wysiwygSettings); + $this->assertArrayHasKey('style_formats', $wysiwygSettings['config']); + $styleFormats = $wysiwygSettings['config']['style_formats']; $data = [ [ - 'name' => 'Lead For Portal1', - 'element' => 'p', - 'attributes' => ['class' => 'lead-portal'] + 'title' => 'Lead For Portal1', + 'selector' => 'p', + 'classes' => 'lead-portal' ], [ - 'name' => 'Dark Grey', - 'element' => 'h1', - 'attributes' => ['class' => 'grey-1'] + 'title' => 'Dark Grey', + 'selector' => 'h1', + 'classes' => 'grey-1' ] ]; - $this->assertEquals($data, $globalStyleSets['default']); + $this->assertEquals($data, $styleFormats); } /** @@ -159,7 +155,6 @@ public function testThemeGridOnContextConfiguration() } - /** * @param array $query * diff --git a/tests/unit.context/_bootstrap.php b/tests/UnitContext/_bootstrap.php similarity index 100% rename from tests/unit.context/_bootstrap.php rename to tests/UnitContext/_bootstrap.php diff --git a/tests/UnitDefault.suite.dist.yml b/tests/UnitDefault.suite.dist.yml new file mode 100644 index 00000000..3ac1420f --- /dev/null +++ b/tests/UnitDefault.suite.dist.yml @@ -0,0 +1,9 @@ +actor: UnitTester +error_level: '%PIMCORE_PHP_ERROR_REPORTING%' +modules: + enabled: + - \Dachcom\Codeception\Support\Helper\PimcoreCore: + connect_db: true + - \Dachcom\Codeception\Support\Helper\PimcoreBundleCore: + run_installer: true + - \Dachcom\Codeception\Support\Helper\Unit \ No newline at end of file diff --git a/tests/unit.default/Areas/AbstractAreaTest.php b/tests/UnitDefault/Areas/AbstractAreaTest.php similarity index 85% rename from tests/unit.default/Areas/AbstractAreaTest.php rename to tests/UnitDefault/Areas/AbstractAreaTest.php index 619e5522..44389e49 100644 --- a/tests/unit.default/Areas/AbstractAreaTest.php +++ b/tests/UnitDefault/Areas/AbstractAreaTest.php @@ -3,11 +3,11 @@ namespace DachcomBundle\Test\UnitDefault\Areas; use Codeception\Exception\ModuleException; -use Dachcom\Codeception\Test\BundleTestCase; +use Dachcom\Codeception\Support\Test\BundleTestCase; use Pimcore\Extension\Document\Areabrick\EditableDialogBoxConfiguration; use Pimcore\Model\Document\Editable; use Pimcore\Model\Document\Editable\Area; -use Pimcore\Tests\Util\TestHelper; +use Pimcore\Tests\Support\Util\TestHelper; use Symfony\Component\HttpFoundation\Request; use ToolboxBundle\Builder\BrickConfigBuilder; use ToolboxBundle\Manager\ConfigManager; @@ -16,15 +16,11 @@ abstract class AbstractAreaTest extends BundleTestCase { /** - * @return object|ConfigManager * @throws ModuleException */ - public function getToolboxConfig() + public function getToolboxConfig(): ConfigManager { - $configManager = $this->getContainer()->get(ConfigManager::class); - $configManager->setAreaNameSpace(ConfigManagerInterface::AREABRICK_NAMESPACE_INTERNAL); - - return $configManager; + return $this->getContainer()->get(ConfigManager::class); } /** @@ -108,12 +104,11 @@ public function generateBackendArea($id) $builder = $this->getContainer()->get(BrickConfigBuilder::class); $configManager = $this->getContainer()->get(ConfigManager::class); - $configManager->setAreaNameSpace(ConfigManagerInterface::AREABRICK_NAMESPACE_INTERNAL); $configNode = $configManager->getAreaConfig($info->getId()); $themeOptions = $configManager->getConfig('theme'); - return $builder->buildDialogBoxConfiguration($info, $info->getId(), $configNode, $themeOptions)->getItems(); + return $builder->buildConfiguration($info, $info->getId(), $configNode, $themeOptions)->getItems(); } /** diff --git a/tests/unit.default/Areas/AccordionTest.php b/tests/UnitDefault/Areas/AccordionTest.php similarity index 100% rename from tests/unit.default/Areas/AccordionTest.php rename to tests/UnitDefault/Areas/AccordionTest.php diff --git a/tests/unit.default/Areas/AnchorTest.php b/tests/UnitDefault/Areas/AnchorTest.php similarity index 100% rename from tests/unit.default/Areas/AnchorTest.php rename to tests/UnitDefault/Areas/AnchorTest.php diff --git a/tests/unit.default/Areas/ColumnsTest.php b/tests/UnitDefault/Areas/ColumnsTest.php similarity index 100% rename from tests/unit.default/Areas/ColumnsTest.php rename to tests/UnitDefault/Areas/ColumnsTest.php diff --git a/tests/unit.default/Areas/ContainerTest.php b/tests/UnitDefault/Areas/ContainerTest.php similarity index 100% rename from tests/unit.default/Areas/ContainerTest.php rename to tests/UnitDefault/Areas/ContainerTest.php diff --git a/tests/unit.default/Areas/ContentTest.php b/tests/UnitDefault/Areas/ContentTest.php similarity index 100% rename from tests/unit.default/Areas/ContentTest.php rename to tests/UnitDefault/Areas/ContentTest.php diff --git a/tests/unit.default/Areas/DownloadTest.php b/tests/UnitDefault/Areas/DownloadTest.php similarity index 99% rename from tests/unit.default/Areas/DownloadTest.php rename to tests/UnitDefault/Areas/DownloadTest.php index 4dde35af..ed57d2f3 100644 --- a/tests/unit.default/Areas/DownloadTest.php +++ b/tests/UnitDefault/Areas/DownloadTest.php @@ -5,7 +5,7 @@ use Pimcore\Model\Document\Editable\Checkbox; use Pimcore\Model\Document\Editable\Relations; use Pimcore\Model\Document\Editable\Select; -use Pimcore\Tests\Util\TestHelper; +use Pimcore\Tests\Support\Util\TestHelper; class DownloadTest extends AbstractAreaTest { diff --git a/tests/unit.default/Areas/GalleryTest.php b/tests/UnitDefault/Areas/GalleryTest.php similarity index 99% rename from tests/unit.default/Areas/GalleryTest.php rename to tests/UnitDefault/Areas/GalleryTest.php index 336f75b6..c57d4d25 100644 --- a/tests/unit.default/Areas/GalleryTest.php +++ b/tests/UnitDefault/Areas/GalleryTest.php @@ -5,7 +5,7 @@ use Pimcore\Model\Document\Editable\Checkbox; use Pimcore\Model\Document\Editable\Relations; use Pimcore\Model\Document\Editable\Select; -use Pimcore\Tests\Util\TestHelper; +use Pimcore\Tests\Support\Util\TestHelper; class GalleryTest extends AbstractAreaTest { diff --git a/tests/unit.default/Areas/GoogleMapTest.php b/tests/UnitDefault/Areas/GoogleMapTest.php similarity index 98% rename from tests/unit.default/Areas/GoogleMapTest.php rename to tests/UnitDefault/Areas/GoogleMapTest.php index 9040aefd..5212c548 100644 --- a/tests/unit.default/Areas/GoogleMapTest.php +++ b/tests/UnitDefault/Areas/GoogleMapTest.php @@ -70,7 +70,7 @@ public function testGoogleMap() $googleMapElement->setDataFromEditmode($locations); $mapZoom = new Numeric(); - $mapZoom->setDataFromResource(5); + $mapZoom->setDataFromResource('5'); $mapType = new Select(); $mapType->setDataFromResource('roadmap'); @@ -116,7 +116,7 @@ public function testGoogleMapWidthAdditionalClass() $googleMapElement->setDataFromEditmode($locations); $mapZoom = new Numeric(); - $mapZoom->setDataFromResource(12); + $mapZoom->setDataFromResource('12'); $mapType = new Select(); $mapType->setDataFromResource('satellite'); diff --git a/tests/unit.default/Areas/HeadlineTest.php b/tests/UnitDefault/Areas/HeadlineTest.php similarity index 100% rename from tests/unit.default/Areas/HeadlineTest.php rename to tests/UnitDefault/Areas/HeadlineTest.php diff --git a/tests/unit.default/Areas/IframeTest.php b/tests/UnitDefault/Areas/IframeTest.php similarity index 98% rename from tests/unit.default/Areas/IframeTest.php rename to tests/UnitDefault/Areas/IframeTest.php index 9c5ed044..8f2f1582 100644 --- a/tests/unit.default/Areas/IframeTest.php +++ b/tests/UnitDefault/Areas/IframeTest.php @@ -49,7 +49,7 @@ public function testIframeWithHeight() $url->setDataFromResource('https://www.dachcom.com'); $height = new Numeric(); - $height->setDataFromResource(200); + $height->setDataFromResource('200'); $elements = [ 'url' => $url, diff --git a/tests/unit.default/Areas/ImageTest.php b/tests/UnitDefault/Areas/ImageTest.php similarity index 98% rename from tests/unit.default/Areas/ImageTest.php rename to tests/UnitDefault/Areas/ImageTest.php index 166b32d8..0c1cc020 100644 --- a/tests/unit.default/Areas/ImageTest.php +++ b/tests/UnitDefault/Areas/ImageTest.php @@ -6,7 +6,7 @@ use Pimcore\Model\Document\Editable\Image; use Pimcore\Model\Document\Editable\Link; use Pimcore\Model\Document\Editable\Select; -use Pimcore\Tests\Util\TestHelper; +use Pimcore\Tests\Support\Util\TestHelper; class ImageTest extends AbstractAreaTest { @@ -104,7 +104,7 @@ public function testImageWithLink() $imageTag->setText('caption'); $link = new Link(); - $link->setDataFromResource(['path' => '/test/test2']); + $link->setDataFromResource(serialize(['path' => '/test/test2'])); $elements = [ 'ci' => $imageTag, diff --git a/tests/unit.default/Areas/LinkListTest.php b/tests/UnitDefault/Areas/LinkListTest.php similarity index 100% rename from tests/unit.default/Areas/LinkListTest.php rename to tests/UnitDefault/Areas/LinkListTest.php diff --git a/tests/unit.default/Areas/ParallaxContainerSectionTest.php b/tests/UnitDefault/Areas/ParallaxContainerSectionTest.php similarity index 100% rename from tests/unit.default/Areas/ParallaxContainerSectionTest.php rename to tests/UnitDefault/Areas/ParallaxContainerSectionTest.php diff --git a/tests/unit.default/Areas/ParallaxContainerTest.php b/tests/UnitDefault/Areas/ParallaxContainerTest.php similarity index 95% rename from tests/unit.default/Areas/ParallaxContainerTest.php rename to tests/UnitDefault/Areas/ParallaxContainerTest.php index faf343b3..fbf1abc5 100644 --- a/tests/unit.default/Areas/ParallaxContainerTest.php +++ b/tests/UnitDefault/Areas/ParallaxContainerTest.php @@ -2,7 +2,7 @@ namespace DachcomBundle\Test\UnitDefault\Areas; -use Pimcore\Tests\Util\TestHelper; +use Pimcore\Tests\Support\Util\TestHelper; use Pimcore\Model\Document\Editable; use ToolboxBundle\Model\Document\Editable\ParallaxImage; @@ -175,8 +175,8 @@ private function getCompare(\Pimcore\Model\Asset\Image $asset) return '
-
-
+
+
@@ -195,8 +195,8 @@ private function getCompare(\Pimcore\Model\Asset\Image $asset)
-
-
+
+
'; @@ -208,8 +208,8 @@ private function getCompareWithAdditionalClass(\Pimcore\Model\Asset\Image $asset return '
-
-
+
+
@@ -228,8 +228,8 @@ private function getCompareWithAdditionalClass(\Pimcore\Model\Asset\Image $asset
-
-
+
+
'; diff --git a/tests/unit.default/Areas/SeparatorTest.php b/tests/UnitDefault/Areas/SeparatorTest.php similarity index 100% rename from tests/unit.default/Areas/SeparatorTest.php rename to tests/UnitDefault/Areas/SeparatorTest.php diff --git a/tests/unit.default/Areas/SlideColumnsTest.php b/tests/UnitDefault/Areas/SlideColumnsTest.php similarity index 99% rename from tests/unit.default/Areas/SlideColumnsTest.php rename to tests/UnitDefault/Areas/SlideColumnsTest.php index 740d0fef..5fd2a282 100644 --- a/tests/unit.default/Areas/SlideColumnsTest.php +++ b/tests/UnitDefault/Areas/SlideColumnsTest.php @@ -129,7 +129,7 @@ public function testSlideColumnsWithBreakPoints() 'controlsAlign' => 'top', 'controlsTrigger' => 'hover', ], - 'areas_appearance' => [], + 'areablock_restriction' => [], ]); $elements = [ diff --git a/tests/unit.default/Areas/SpacerTest.php b/tests/UnitDefault/Areas/SpacerTest.php similarity index 100% rename from tests/unit.default/Areas/SpacerTest.php rename to tests/UnitDefault/Areas/SpacerTest.php diff --git a/tests/unit.default/Areas/TeaserSnippetTest.php b/tests/UnitDefault/Areas/TeaserSnippetTest.php similarity index 100% rename from tests/unit.default/Areas/TeaserSnippetTest.php rename to tests/UnitDefault/Areas/TeaserSnippetTest.php diff --git a/tests/unit.default/Areas/TeaserTest.php b/tests/UnitDefault/Areas/TeaserTest.php similarity index 97% rename from tests/unit.default/Areas/TeaserTest.php rename to tests/UnitDefault/Areas/TeaserTest.php index 6bd94d41..cf1c99a9 100644 --- a/tests/unit.default/Areas/TeaserTest.php +++ b/tests/UnitDefault/Areas/TeaserTest.php @@ -8,7 +8,7 @@ use Pimcore\Model\Document\Editable\Link; use Pimcore\Model\Document\Editable\Select; use Pimcore\Model\Document\Editable\Wysiwyg; -use Pimcore\Tests\Util\TestHelper; +use Pimcore\Tests\Support\Util\TestHelper; class TeaserTest extends AbstractAreaTest { @@ -89,7 +89,7 @@ private function getDefaultElements($asset) $layout->setDataFromResource('default'); $link = new Link(); - $link->setDataFromResource(['path' => '/test/test2', 'linktype' => 'direct', 'text' => '']); + $link->setDataFromResource(serialize(['path' => '/test/test2', 'linktype' => 'direct', 'text' => ''])); $image = new Image(); $image->setDataFromEditmode([ diff --git a/tests/unit.default/Areas/VideoTest.php b/tests/UnitDefault/Areas/VideoTest.php similarity index 99% rename from tests/unit.default/Areas/VideoTest.php rename to tests/UnitDefault/Areas/VideoTest.php index c35dc43a..f94bbb3a 100644 --- a/tests/unit.default/Areas/VideoTest.php +++ b/tests/UnitDefault/Areas/VideoTest.php @@ -4,7 +4,7 @@ use Pimcore\Model\Document\Editable\Checkbox; use Pimcore\Model\Document\Editable\Select; -use Pimcore\Tests\Util\TestHelper; +use Pimcore\Tests\Support\Util\TestHelper; use ToolboxBundle\Model\Document\Editable\Vhs; class VideoTest extends AbstractAreaTest diff --git a/tests/unit.default/_bootstrap.php b/tests/UnitDefault/_bootstrap.php similarity index 100% rename from tests/unit.default/_bootstrap.php rename to tests/UnitDefault/_bootstrap.php diff --git a/tests/UnitTheme.suite.dist.yml b/tests/UnitTheme.suite.dist.yml new file mode 100644 index 00000000..28589d69 --- /dev/null +++ b/tests/UnitTheme.suite.dist.yml @@ -0,0 +1,10 @@ +actor: UnitTester +error_level: '%PIMCORE_PHP_ERROR_REPORTING%' +modules: + enabled: + - \Dachcom\Codeception\Support\Helper\PimcoreCore: + configuration_file: 'config_theme.yaml' + connect_db: true + - \Dachcom\Codeception\Support\Helper\PimcoreBundleCore: + run_installer: true + - \Dachcom\Codeception\Support\Helper\Unit \ No newline at end of file diff --git a/tests/unit.theme/AreaManagerTest.php b/tests/UnitTheme/AreaManagerTest.php similarity index 97% rename from tests/unit.theme/AreaManagerTest.php rename to tests/UnitTheme/AreaManagerTest.php index 2ace9125..67f7962c 100644 --- a/tests/unit.theme/AreaManagerTest.php +++ b/tests/UnitTheme/AreaManagerTest.php @@ -2,8 +2,8 @@ namespace DachcomBundle\Test\UnitTheme; +use Dachcom\Codeception\Support\Test\BundleTestCase; use Symfony\Component\HttpFoundation\Request; -use Dachcom\Codeception\Test\BundleTestCase; use ToolboxBundle\Manager\AreaManager; use ToolboxBundle\Manager\AreaManagerInterface; diff --git a/tests/unit.theme/ColumnCalculatorTest.php b/tests/UnitTheme/ColumnCalculatorTest.php similarity index 99% rename from tests/unit.theme/ColumnCalculatorTest.php rename to tests/UnitTheme/ColumnCalculatorTest.php index aa171f78..f81f3cd9 100644 --- a/tests/unit.theme/ColumnCalculatorTest.php +++ b/tests/UnitTheme/ColumnCalculatorTest.php @@ -2,7 +2,7 @@ namespace DachcomBundle\Test\UnitTheme; -use Dachcom\Codeception\Test\BundleTestCase; +use Dachcom\Codeception\Support\Test\BundleTestCase; use ToolboxBundle\Calculator\ColumnCalculatorInterface; class ColumnCalculatorTest extends BundleTestCase diff --git a/tests/unit.theme/_bootstrap.php b/tests/UnitTheme/_bootstrap.php similarity index 100% rename from tests/unit.theme/_bootstrap.php rename to tests/UnitTheme/_bootstrap.php diff --git a/tests/_bootstrap.php b/tests/_bootstrap.php index f4138acf..fc47a3e5 100644 --- a/tests/_bootstrap.php +++ b/tests/_bootstrap.php @@ -1,8 +1,3 @@ [ - "items" => [ - [ - "method" => "scaleByWidth", - "arguments" => [ - "width" => 500, - "forceResize" => FALSE - ] - ] - ], - "medias" => [ - - ], - "name" => "downloadPreviewImage", - "description" => "", - "group" => "", - "format" => "JPEG", - "quality" => 85, - "highResolution" => 0.0, - "preserveColor" => FALSE, - "preserveMetaData" => FALSE, - "rasterizeSVG" => FALSE, - "downloadable" => FALSE, - "modificationDate" => 1604413615, - "creationDate" => 1604413601, - "forcePictureTag" => FALSE, - "id" => "downloadPreviewImage" - ], - "parallaxImage" => [ - "items" => [ - [ - "method" => "scaleByWidth", - "arguments" => [ - "width" => 500, - "forceResize" => FALSE - ] - ] - ], - "medias" => [ - - ], - "name" => "parallaxImage", - "description" => "", - "group" => "", - "format" => "JPEG", - "quality" => 85, - "highResolution" => NULL, - "preserveColor" => FALSE, - "preserveMetaData" => FALSE, - "rasterizeSVG" => FALSE, - "downloadable" => FALSE, - "modificationDate" => 1632325543, - "creationDate" => 1632325543, - "preserveAnimation" => FALSE, - "id" => "parallaxImage" - ], - "parallaxSectionBackground" => [ - "items" => [ - [ - "method" => "scaleByWidth", - "arguments" => [ - "width" => 500, - "forceResize" => FALSE - ] - ] - ], - "medias" => [ - - ], - "name" => "parallaxSectionBackground", - "description" => "", - "group" => "", - "format" => "JPEG", - "quality" => 85, - "highResolution" => 0.0, - "preserveColor" => FALSE, - "preserveMetaData" => FALSE, - "rasterizeSVG" => FALSE, - "downloadable" => FALSE, - "modificationDate" => 1632481410, - "creationDate" => 1632406242, - "preserveAnimation" => FALSE, - "id" => "parallaxSectionBackground" - ], - "lightBoxImage" => [ - "items" => [ - [ - "method" => "scaleByWidth", - "arguments" => [ - "width" => 500, - "forceResize" => FALSE - ] - ] - ], - "medias" => [ - - ], - "name" => "lightBoxImage", - "description" => "", - "group" => "", - "format" => "JPEG", - "quality" => 85, - "highResolution" => 0.0, - "preserveColor" => FALSE, - "preserveMetaData" => FALSE, - "rasterizeSVG" => FALSE, - "downloadable" => FALSE, - "modificationDate" => 1632481410, - "creationDate" => 1632406242, - "preserveAnimation" => FALSE, - "id" => "lightBoxImage" - ], - "videoPoster" => [ - "items" => [ - [ - "method" => "scaleByWidth", - "arguments" => [ - "width" => 500, - "forceResize" => FALSE - ] - ] - ], - "medias" => [ - - ], - "name" => "videoPoster", - "description" => "", - "group" => "", - "format" => "JPEG", - "quality" => 85, - "highResolution" => 0.0, - "preserveColor" => FALSE, - "preserveMetaData" => FALSE, - "rasterizeSVG" => FALSE, - "downloadable" => FALSE, - "modificationDate" => 1632481410, - "creationDate" => 1632406242, - "preserveAnimation" => FALSE, - "id" => "videoPoster" - ], - "standardTeaser" => [ - "items" => [ - [ - "method" => "scaleByWidth", - "arguments" => [ - "width" => 500, - "forceResize" => FALSE - ] - ] - ], - "medias" => [ - - ], - "name" => "standardTeaser", - "description" => "", - "group" => "", - "format" => "JPEG", - "quality" => 85, - "highResolution" => 0.0, - "preserveColor" => FALSE, - "preserveMetaData" => FALSE, - "rasterizeSVG" => FALSE, - "downloadable" => FALSE, - "modificationDate" => 1632481410, - "creationDate" => 1632406242, - "preserveAnimation" => FALSE, - "id" => "standardTeaser" - ], - "contentImage" => [ - "items" => [ - [ - "method" => "scaleByWidth", - "arguments" => [ - "width" => 500, - "forceResize" => FALSE - ] - ] - ], - "medias" => [ - - ], - "name" => "contentImage", - "description" => "", - "group" => "", - "format" => "JPEG", - "quality" => 85, - "highResolution" => 0.0, - "preserveColor" => FALSE, - "preserveMetaData" => FALSE, - "rasterizeSVG" => FALSE, - "downloadable" => FALSE, - "modificationDate" => 1632481410, - "creationDate" => 1632406242, - "preserveAnimation" => FALSE, - "id" => "contentImage" - ], - "galleryImage" => [ - "items" => [ - [ - "method" => "scaleByWidth", - "arguments" => [ - "width" => 500, - "forceResize" => FALSE - ] - ] - ], - "medias" => [ - - ], - "name" => "galleryImage", - "description" => "", - "group" => "", - "format" => "JPEG", - "quality" => 85, - "highResolution" => 0.0, - "preserveColor" => FALSE, - "preserveMetaData" => FALSE, - "rasterizeSVG" => FALSE, - "downloadable" => FALSE, - "modificationDate" => 1632481410, - "creationDate" => 1632406242, - "preserveAnimation" => FALSE, - "id" => "galleryImage" - ], - "galleryThumb" => [ - "items" => [ - [ - "method" => "scaleByWidth", - "arguments" => [ - "width" => 500, - "forceResize" => FALSE - ] - ] - ], - "medias" => [ - - ], - "name" => "galleryThumb", - "description" => "", - "group" => "", - "format" => "JPEG", - "quality" => 85, - "highResolution" => 0.0, - "preserveColor" => FALSE, - "preserveMetaData" => FALSE, - "rasterizeSVG" => FALSE, - "downloadable" => FALSE, - "modificationDate" => 1632481410, - "creationDate" => 1632406242, - "preserveAnimation" => FALSE, - "id" => "galleryThumb" - ], -]; diff --git a/tests/_etc/config/app/image_thumbnails/contentImage.yaml b/tests/_etc/config/app/image_thumbnails/contentImage.yaml new file mode 100644 index 00000000..1084888a --- /dev/null +++ b/tests/_etc/config/app/image_thumbnails/contentImage.yaml @@ -0,0 +1,24 @@ +pimcore: + assets: + image: + thumbnails: + definitions: + contentImage: + items: + - + method: grayscale + arguments: { } + medias: { } + name: contentImage + description: '' + group: '' + format: SOURCE + quality: 85 + highResolution: 0.0 + preserveColor: false + preserveMetaData: false + rasterizeSVG: false + downloadable: false + modificationDate: 1684761377 + creationDate: 1684761361 + preserveAnimation: false diff --git a/tests/_etc/config/app/image_thumbnails/downloadPreviewImage.yaml b/tests/_etc/config/app/image_thumbnails/downloadPreviewImage.yaml new file mode 100755 index 00000000..e53c6645 --- /dev/null +++ b/tests/_etc/config/app/image_thumbnails/downloadPreviewImage.yaml @@ -0,0 +1,26 @@ +pimcore: + assets: + image: + thumbnails: + definitions: + downloadPreviewImage: + items: + - + method: scaleByWidth + arguments: + width: 500 + forceResize: false + medias: { } + name: downloadPreviewImage + description: '' + group: '' + format: SOURCE + quality: 85 + highResolution: 0.0 + preserveColor: false + preserveMetaData: false + rasterizeSVG: false + downloadable: false + modificationDate: 1641460931 + creationDate: 1604413601 + preserveAnimation: false diff --git a/tests/_etc/config/app/image_thumbnails/galleryImage.yaml b/tests/_etc/config/app/image_thumbnails/galleryImage.yaml new file mode 100644 index 00000000..68d6d977 --- /dev/null +++ b/tests/_etc/config/app/image_thumbnails/galleryImage.yaml @@ -0,0 +1,24 @@ +pimcore: + assets: + image: + thumbnails: + definitions: + galleryImage: + items: + - + method: grayscale + arguments: { } + medias: { } + name: galleryImage + description: '' + group: '' + format: SOURCE + quality: 85 + highResolution: 0.0 + preserveColor: false + preserveMetaData: false + rasterizeSVG: false + downloadable: false + modificationDate: 1684761377 + creationDate: 1684761361 + preserveAnimation: false diff --git a/tests/_etc/config/app/image_thumbnails/galleryThumb.yaml b/tests/_etc/config/app/image_thumbnails/galleryThumb.yaml new file mode 100644 index 00000000..d06940df --- /dev/null +++ b/tests/_etc/config/app/image_thumbnails/galleryThumb.yaml @@ -0,0 +1,24 @@ +pimcore: + assets: + image: + thumbnails: + definitions: + galleryThumb: + items: + - + method: grayscale + arguments: { } + medias: { } + name: galleryThumb + description: '' + group: '' + format: SOURCE + quality: 85 + highResolution: 0.0 + preserveColor: false + preserveMetaData: false + rasterizeSVG: false + downloadable: false + modificationDate: 1684761377 + creationDate: 1684761361 + preserveAnimation: false diff --git a/tests/_etc/config/app/image_thumbnails/lightBoxImage.yaml b/tests/_etc/config/app/image_thumbnails/lightBoxImage.yaml new file mode 100644 index 00000000..d658af62 --- /dev/null +++ b/tests/_etc/config/app/image_thumbnails/lightBoxImage.yaml @@ -0,0 +1,24 @@ +pimcore: + assets: + image: + thumbnails: + definitions: + lightBoxImage: + items: + - + method: grayscale + arguments: { } + medias: { } + name: lightBoxImage + description: '' + group: '' + format: SOURCE + quality: 85 + highResolution: 0.0 + preserveColor: false + preserveMetaData: false + rasterizeSVG: false + downloadable: false + modificationDate: 1684761377 + creationDate: 1684761361 + preserveAnimation: false diff --git a/tests/_etc/config/app/image_thumbnails/parallaxImage.yaml b/tests/_etc/config/app/image_thumbnails/parallaxImage.yaml new file mode 100755 index 00000000..ee49d52a --- /dev/null +++ b/tests/_etc/config/app/image_thumbnails/parallaxImage.yaml @@ -0,0 +1,21 @@ +pimcore: + assets: + image: + thumbnails: + definitions: + parallaxImage: + items: { } + medias: { } + name: parallaxImage + description: '' + group: '' + format: SOURCE + quality: 85 + highResolution: 0.0 + preserveColor: false + preserveMetaData: false + rasterizeSVG: false + downloadable: false + modificationDate: 1641460931 + creationDate: 1632325543 + preserveAnimation: false diff --git a/tests/_etc/config/app/image_thumbnails/parallaxSectionBackground.yaml b/tests/_etc/config/app/image_thumbnails/parallaxSectionBackground.yaml new file mode 100644 index 00000000..beb7f9e5 --- /dev/null +++ b/tests/_etc/config/app/image_thumbnails/parallaxSectionBackground.yaml @@ -0,0 +1,24 @@ +pimcore: + assets: + image: + thumbnails: + definitions: + parallaxSectionBackground: + items: + - + method: grayscale + arguments: { } + medias: { } + name: parallaxSectionBackground + description: '' + group: '' + format: SOURCE + quality: 85 + highResolution: 0.0 + preserveColor: false + preserveMetaData: false + rasterizeSVG: false + downloadable: false + modificationDate: 1684761377 + creationDate: 1684761361 + preserveAnimation: false diff --git a/tests/_etc/config/app/image_thumbnails/standardTeaser.yaml b/tests/_etc/config/app/image_thumbnails/standardTeaser.yaml new file mode 100644 index 00000000..8f3e0782 --- /dev/null +++ b/tests/_etc/config/app/image_thumbnails/standardTeaser.yaml @@ -0,0 +1,24 @@ +pimcore: + assets: + image: + thumbnails: + definitions: + standardTeaser: + items: + - + method: grayscale + arguments: { } + medias: { } + name: standardTeaser + description: '' + group: '' + format: SOURCE + quality: 85 + highResolution: 0.0 + preserveColor: false + preserveMetaData: false + rasterizeSVG: false + downloadable: false + modificationDate: 1684761377 + creationDate: 1684761361 + preserveAnimation: false diff --git a/tests/_etc/config/app/image_thumbnails/videoPoster.yaml b/tests/_etc/config/app/image_thumbnails/videoPoster.yaml new file mode 100644 index 00000000..a4c68a61 --- /dev/null +++ b/tests/_etc/config/app/image_thumbnails/videoPoster.yaml @@ -0,0 +1,26 @@ +pimcore: + assets: + image: + thumbnails: + definitions: + videoPoster: + items: + - + method: resize + arguments: + width: 800 + height: 600 + medias: { } + name: videoPoster + description: '' + group: '' + format: SOURCE + quality: 85 + highResolution: 0.0 + preserveColor: false + preserveMetaData: false + rasterizeSVG: false + downloadable: false + modificationDate: 1684751200 + creationDate: 1684751193 + preserveAnimation: false diff --git a/tests/_etc/config/app/system.yml b/tests/_etc/config/app/system.yml deleted file mode 100755 index 45732b19..00000000 --- a/tests/_etc/config/app/system.yml +++ /dev/null @@ -1,66 +0,0 @@ -pimcore: - general: - timezone: Europe/Berlin - language: en - valid_languages: 'en,de' - fallback_languages: - en: '' - de: '' - path_variable: '' - domain: 'localhost' - redirect_to_maindomain: false - default_language: en - disable_usage_statistics: true - debug_admin_translations: false - instance_identifier: '' - documents: - versions: - steps: 10 - days: null - error_pages: - default: /404 - allow_trailing_slash: 'no' - generate_preview: false - objects: - versions: - steps: 10 - days: null - assets: - versions: - steps: 10 - days: null - icc_rgb_profile: '' - icc_cmyk_profile: '' - hide_edit_image: false - disable_tree_preview: true - services: - google: - client_id: '' - email: '' - simple_api_key: '' - browser_api_key: '' - full_page_cache: - exclude_cookie: '' - enabled: false - lifetime: null - exclude_patterns: '' - httpclient: - adapter: Socket - proxy_host: '' - proxy_port: '' - proxy_user: '' - proxy_pass: '' - applicationlog: - mail_notification: - send_log_summary: false - filter_priority: null - mail_receiver: '' - archive_treshold: '30' - archive_alternative_database: '' - delete_archive_threshold: '6' -pimcore_admin: - branding: - color_login_screen: '' - color_admin_interface: '' - login_screen_custom_image: '' - login_screen_invert_colors: false diff --git a/tests/_etc/config/app/system_settings.yaml b/tests/_etc/config/app/system_settings.yaml new file mode 100755 index 00000000..52951c74 --- /dev/null +++ b/tests/_etc/config/app/system_settings.yaml @@ -0,0 +1,47 @@ +pimcore: + general: + timezone: Europe/Berlin + domain: 'localhost' + redirect_to_maindomain: false + disable_usage_statistics: true + debug_admin_translations: false + language: en + default_language: en + valid_languages: + - en + - de + fallback_languages: + en: '' + de: '' + documents: + allow_trailing_slash: 'no' + generate_preview: false + versions: + days: null + steps: 10 + error_pages: + default: '/error' + localized: + en: '' + de: '' + objects: + versions: + days: null + steps: 10 + assets: + versions: + days: null + steps: 10 + email: + debug: + email_addresses: shagspiel@dachcom.ch +pimcore_admin: + assets: + hide_edit_image: true + disable_tree_preview: true + branding: + login_screen_invert_colors: false + color_login_screen: '' + color_admin_interface: '' + color_admin_interface_background: '' + login_screen_custom_image: '' diff --git a/tests/_etc/config/bundle/config_context.yml b/tests/_etc/config/bundle/config_context.yaml similarity index 53% rename from tests/_etc/config/bundle/config_context.yml rename to tests/_etc/config/bundle/config_context.yaml index 1f49f887..d6c1f651 100755 --- a/tests/_etc/config/bundle/config_context.yml +++ b/tests/_etc/config/bundle/config_context.yaml @@ -1,31 +1,51 @@ toolbox: - ckeditor: - global_style_sets: - default: - - name: 'Lead Global' - element: p - attributes: - class: 'lead' + enabled_core_areas: + - accordion + - anchor + - columns + - container + - content + - download + - gallery + - googleMap + - headline + - iFrame + - image + - linkList + - parallaxContainer + - parallaxContainerSection + - separator + - slideColumns + - snippet + - spacer + - teaser + - video - context_resolver: 'DachcomBundle\Test\Services\ContextResolverTestClass' + wysiwyg_editor: + config: + style_formats: + - title: 'Lead Global' + classes: 'lead' + selector: 'p' + + context_resolver: 'DachcomBundle\Test\Support\Services\ContextResolverTestClass' context: context_a: settings: merge_with_root: true enabled_areas: - 'headline' - ckeditor: - global_style_sets: - default: - - name: 'Lead For Portal1' - element: p - attributes: - class: 'lead-portal' - - name: 'Dark Grey' - element: h1 - attributes: - class: 'grey-1' + wysiwyg_editor: + config: + style_formats: + - title: 'Lead For Portal1' + classes: 'lead-portal' + selector: 'p' + - title: 'Dark Grey' + classes: 'grey-1' + selector: 'h1' + context_b: settings: merge_with_root: true @@ -52,6 +72,10 @@ toolbox: settings: merge_with_root: false theme: + layout: !php/const ToolboxBundle\Manager\LayoutManagerInterface::TOOLBOX_LAYOUT_BOOTSTRAP4 + calculators: + column_calculator: ToolboxBundle\Calculator\Bootstrap4\ColumnCalculator + slide_calculator: ToolboxBundle\Calculator\Bootstrap4\SlideColumnCalculator grid: grid_size: 8 breakpoints: diff --git a/tests/_etc/config/bundle/config_default.yml b/tests/_etc/config/bundle/config_default.yaml similarity index 59% rename from tests/_etc/config/bundle/config_default.yml rename to tests/_etc/config/bundle/config_default.yaml index 0e38536b..6563c61b 100755 --- a/tests/_etc/config/bundle/config_default.yml +++ b/tests/_etc/config/bundle/config_default.yaml @@ -1,4 +1,27 @@ toolbox: + + enabled_core_areas: + - accordion + - anchor + - columns + - container + - content + - download + - gallery + - googleMap + - headline + - iFrame + - image + - linkList + - parallaxContainer + - parallaxContainerSection + - separator + - slideColumns + - snippet + - spacer + - teaser + - video + theme: grid: grid_size: 12 diff --git a/tests/_etc/config/bundle/config_theme.yml b/tests/_etc/config/bundle/config_theme.yaml similarity index 67% rename from tests/_etc/config/bundle/config_theme.yml rename to tests/_etc/config/bundle/config_theme.yaml index 2d17aca9..3d1b8399 100755 --- a/tests/_etc/config/bundle/config_theme.yml +++ b/tests/_etc/config/bundle/config_theme.yaml @@ -1,4 +1,27 @@ toolbox: + + enabled_core_areas: + - accordion + - anchor + - columns + - container + - content + - download + - gallery + - googleMap + - headline + - iFrame + - image + - linkList + - parallaxContainer + - parallaxContainerSection + - separator + - slideColumns + - snippet + - spacer + - teaser + - video + theme: grid: grid_size: 12 @@ -19,7 +42,8 @@ toolbox: identifier: 'lg' name: 'Breakpoint: LG' description: 'Your Description' - areas_appearance: + + areablock_restriction: disallowed_content: disallowed: - image @@ -31,7 +55,8 @@ toolbox: - image disallowed: - image - snippet_areas_appearance: + + snippet_areablock_restriction: disallowed_content: disallowed: - headline diff --git a/tests/_output/.gitignore b/tests/_output/.gitignore deleted file mode 100644 index c96a04f0..00000000 --- a/tests/_output/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/tests/_phpstan-bootstrap.php b/tests/_phpstan-bootstrap.php index 0c3c5270..dea88192 100644 --- a/tests/_phpstan-bootstrap.php +++ b/tests/_phpstan-bootstrap.php @@ -3,4 +3,4 @@ # prevent php warnings in phpstan. if (!defined('PIMCORE_PRIVATE_VAR')) { define('PIMCORE_PRIVATE_VAR', ''); -} \ No newline at end of file +} diff --git a/tests/_support/AcceptanceTester.php b/tests/_support/AcceptanceTester.php deleted file mode 100644 index 5df874f7..00000000 --- a/tests/_support/AcceptanceTester.php +++ /dev/null @@ -1,8 +0,0 @@ -