Skip to content

Commit 87a1e00

Browse files
pixel81ksolverat
andauthored
Store Provider (#128)
* implementation for issue #127 - implement ToolboxStoreProviderInterface and adapt BrickConfigBuilder - updated UPGRADE.md * fix annotation Co-authored-by: Stefan Hagspiel <info@solverat.com>
1 parent 5b61cba commit 87a1e00

File tree

11 files changed

+255
-27
lines changed

11 files changed

+255
-27
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ The Toolbox provides a lot of [ready-to-use Bricks](docs/11_ElementsOverview.md)
9999
- [Conditional Logic in Configuration](docs/12_ConditionalLogic.md)
100100
- [CK-Editor Configuration](docs/13_CkEditor.md)
101101
- [Image Thumbnails Strategy](docs/14_ImageThumbnails.md)
102-
- [Configuration Context](docs/15_Context.md) (New!)
102+
- [Configuration Context](docs/15_Context.md)
103+
- [Editable Store Provider](docs/16_EditableStoreProvider.md)
103104
- [Create a Custom Brick](docs/10_CustomBricks.md)
104105
- [Theme / Layout](docs/30_ToolboxTheme.md)
105106
- [Overriding Views](docs/31_OverridingViews.md)
@@ -109,7 +110,7 @@ The Toolbox provides a lot of [ready-to-use Bricks](docs/11_ElementsOverview.md)
109110
- [Javascript Plugins](docs/80_Javascript.md)
110111

111112
## Pimcore Fixes / Overrides
112-
- fix the pimcore iframe [maskFrames](src/ToolboxBundle/Resources/public/js/document/edit.js#L8) bug (in some cases the iframe overlay field does not apply to the right position)
113+
- Fix the pimcore iframe [maskFrames](src/ToolboxBundle/Resources/public/js/document/edit.js#L8) bug (in some cases the iframe overlay field does not apply to the right position)
113114
- Transforms all the brick config buttons (`pimcore_area_edit_button_*`) to more grateful ones.
114115

115116
## Copyright and license

UPGRADE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Just click the "update" button or execute the migration command to finish the bu
88

99
#### Update from Version 3.1.x to Version 3.2.0
1010
- **[NEW FEATURE]**: Pimcore 6.4.0 and Pimcore 6.5.0 ready
11+
- **[NEW FEATURE]**: Store Provider added (https://github.com/dachcom-digital/pimcore-toolbox/pull/128)
1112
- **[BUG FIX]**: Video Autoplay Fix (https://github.com/dachcom-digital/pimcore-toolbox/issues/129)
1213

1314
#### Update from Version 3.x to Version 3.1.0

docs/11_ElementsOverview.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,6 @@ toolbox:
497497
There is also a jquery plugin for the video element. Read more about it [here](80_Javascript.md#video-extension)
498498

499499
# Element Config Field Overview
500-
501500
In short, you're able to use all the [pimcore editables](https://www.pimcore.org/docs/5.0.0/Documents/Editables/index.html).
502501

503502
**Example**
@@ -513,8 +512,10 @@ toolbox:
513512
# https://www.pimcore.org/docs/5.0.0/Documents/Editables/Input.html#page_Configuration
514513
```
515514

516-
# Additional Classes
515+
## Editable Store Provider
516+
In addition, you could use the toolbox editable store provider to generate dynamic store data. Read more about it [here](./16_EditableStoreProvider.md).
517517

518+
# Additional Classes
518519
Almost every toolbox element supports the `additionalClasses` field type.
519520
This Element will help you to generate some additional classes for every toolbox element.
520521
This is great since you don't need to override the element view, just add one or more additional classes via config.

docs/16_EditableStoreProvider.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Store Provider for (Multi-) Select Editables
2+
3+
This Bundle allows you to generate dynamic data for your dropdown elements.
4+
If you're in pimcore context, a typical store looks like this:
5+
6+
```yml
7+
toolbox:
8+
areas:
9+
video:
10+
config_elements:
11+
a_classical_store:
12+
type: multiselect
13+
title: 'Test 2'
14+
config:
15+
store:
16+
my_value: 'My Value'
17+
foo: 'Bar'
18+
```
19+
20+
### Configure Dynamic Store Provider
21+
But you're also able to provide your data from a symfony service:
22+
23+
```yml
24+
toolbox:
25+
areas:
26+
video:
27+
config_elements:
28+
my_dynamic_store_provider:
29+
type: select
30+
title: 'Test'
31+
config:
32+
store_provider: 'my_awesome_store_provider'
33+
```
34+
35+
### Register Custom Store Provider
36+
Now we need to register our new service:
37+
38+
```yml
39+
# app/config.yml
40+
services:
41+
AppBundle\Toolbox\MyStoreProvider:
42+
tags:
43+
- { name: toolbox.editable.store_provider, identifier: 'my_awesome_store_provider' }
44+
45+
```
46+
47+
### Create Store Provider
48+
49+
```php
50+
<?php
51+
52+
namespace AppBundle\Toolbox;
53+
54+
use ToolboxBundle\Provider\StoreProviderInterface;
55+
56+
class MyStoreProvider implements StoreProviderInterface
57+
{
58+
/**
59+
* {@inheritDoc}
60+
*/
61+
public function getValues()
62+
{
63+
return [
64+
'my_value' => 'My Value',
65+
'foo' => 'Bar'
66+
];
67+
}
68+
}
69+
```

src/ToolboxBundle/Builder/BrickConfigBuilder.php

Lines changed: 60 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44

55
use Pimcore\Model\Document\Tag\Area\Info;
66
use Pimcore\Model\Document\Tag\Checkbox;
7-
use Pimcore\Translation\Translator;
87
use Pimcore\Templating\Renderer\TagRenderer;
8+
use Pimcore\Translation\Translator;
99
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
10+
use ToolboxBundle\Registry\StoreProviderRegistryInterface;
1011

1112
class BrickConfigBuilder
1213
{
@@ -66,20 +67,26 @@ class BrickConfigBuilder
6667
protected $configWindowSize = null;
6768

6869
/**
69-
* ElementBuilder constructor.
70-
*
70+
* @var StoreProviderRegistryInterface
71+
*/
72+
protected $storeProvider = null;
73+
74+
/**
7175
* @param Translator $translator
7276
* @param TagRenderer $tagRenderer
7377
* @param EngineInterface $templating
78+
* @param StoreProviderRegistryInterface $storeProvider
7479
*/
7580
public function __construct(
7681
Translator $translator,
7782
TagRenderer $tagRenderer,
78-
EngineInterface $templating
83+
EngineInterface $templating,
84+
StoreProviderRegistryInterface $storeProvider
7985
) {
8086
$this->translator = $translator;
8187
$this->tagRenderer = $tagRenderer;
8288
$this->templating = $templating;
89+
$this->storeProvider = $storeProvider;
8390
}
8491

8592
/**
@@ -181,7 +188,53 @@ private function needStore($type)
181188
*/
182189
private function hasValidStore($parsedConfig)
183190
{
184-
return isset($parsedConfig['store']) && is_array($parsedConfig['store']) && count($parsedConfig['store']) > 0;
191+
if (isset($parsedConfig['store']) && is_array($parsedConfig['store']) && count($parsedConfig['store']) > 0) {
192+
return true;
193+
}
194+
195+
if (isset($parsedConfig['store_provider']) && $this->storeProvider->has($parsedConfig['store_provider'])) {
196+
return true;
197+
}
198+
199+
return false;
200+
}
201+
202+
/**
203+
* @param string $type
204+
* @param array $config
205+
*
206+
* @return array
207+
* @throws \Exception
208+
*/
209+
private function buildStore($type, $config)
210+
{
211+
$dataConfig = $config;
212+
213+
unset($dataConfig['store'], $dataConfig['store_provider']);
214+
215+
$storeValues = [];
216+
if (isset($config['store']) && !is_null($config['store'])) {
217+
$storeValues = $config['store'];
218+
} elseif (isset($config['store_provider']) && !is_null($config['store_provider'])) {
219+
$storeProvider = $this->storeProvider->get($config['store_provider']);
220+
$storeValues = $storeProvider->getValues();
221+
}
222+
223+
if (count($storeValues) === 0) {
224+
throw new \Exception($type . ' (' . $this->documentEditableId . ') has no valid configured store');
225+
}
226+
227+
$store = [];
228+
foreach ($storeValues as $k => $v) {
229+
if (is_array($v)) {
230+
$v = $v['name'];
231+
}
232+
$store[] = [$k, $this->translator->trans($v, [], 'admin')];
233+
}
234+
235+
$dataConfig['store'] = $store;
236+
237+
return $dataConfig;
185238
}
186239

187240
/**
@@ -293,23 +346,8 @@ private function getTagConfig($type, $config, $additionalConfig)
293346
}
294347

295348
//check store
296-
if ($this->needStore($type) && isset($parsedConfig['store']) && !is_null($parsedConfig['store'])) {
297-
if (empty($parsedConfig['store'])) {
298-
throw new \Exception($type . ' (' . $this->documentEditableId . ') has no valid configured store');
299-
}
300-
301-
$store = [];
302-
foreach ($parsedConfig['store'] as $k => $v) {
303-
if (is_array($v)) {
304-
$v = $v['name'];
305-
}
306-
307-
$store[] = [$k, $this->translator->trans($v, [], 'admin')];
308-
}
309-
310-
$parsedConfig['store'] = $store;
311-
} else {
312-
unset($parsedConfig['store']);
349+
if ($this->needStore($type) && $this->hasValidStore($parsedConfig)) {
350+
$parsedConfig = $this->buildStore($type, $parsedConfig);
313351
}
314352

315353
return $parsedConfig;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace ToolboxBundle\DependencyInjection\Compiler;
4+
5+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
6+
use Symfony\Component\DependencyInjection\ContainerBuilder;
7+
use Symfony\Component\DependencyInjection\Reference;
8+
use ToolboxBundle\Registry\StoreProviderRegistry;
9+
10+
final class StoreProviderPass implements CompilerPassInterface
11+
{
12+
/**
13+
* @param ContainerBuilder $container
14+
*/
15+
public function process(ContainerBuilder $container)
16+
{
17+
$definition = $container->getDefinition(StoreProviderRegistry::class);
18+
foreach ($container->findTaggedServiceIds('toolbox.editable.store_provider') as $id => $tags) {
19+
foreach ($tags as $attributes) {
20+
$definition->addMethodCall('register', [$attributes['identifier'], new Reference($id)]);
21+
}
22+
}
23+
}
24+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace ToolboxBundle\Provider;
4+
5+
interface StoreProviderInterface
6+
{
7+
/**
8+
* @return mixed
9+
*/
10+
public function getValues();
11+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
namespace ToolboxBundle\Registry;
4+
5+
use ToolboxBundle\Provider\StoreProviderInterface;
6+
7+
class StoreProviderRegistry implements StoreProviderRegistryInterface
8+
{
9+
/**
10+
* @var array
11+
*/
12+
protected $services = [];
13+
14+
/**
15+
* {@inheritDoc}
16+
*/
17+
public function register($identifier, $service)
18+
{
19+
if (!in_array(StoreProviderInterface::class, class_implements($service), true)) {
20+
throw new \InvalidArgumentException(
21+
sprintf('%s needs to implement "%s", "%s" given.', get_class($service), StoreProviderInterface::class, implode(', ', class_implements($service)))
22+
);
23+
}
24+
25+
$this->services[$identifier] = $service;
26+
}
27+
28+
/**
29+
* {@inheritDoc}
30+
*/
31+
public function has($identifier)
32+
{
33+
return isset($this->services[$identifier]);
34+
}
35+
36+
/**
37+
* {@inheritDoc}
38+
*/
39+
public function get($identifier)
40+
{
41+
if (!$this->has($identifier)) {
42+
throw new \Exception('"' . $identifier . '" Store provider does not exist.');
43+
}
44+
45+
return $this->services[$identifier];
46+
}
47+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace ToolboxBundle\Registry;
4+
5+
use ToolboxBundle\Provider\StoreProviderInterface;
6+
7+
interface StoreProviderRegistryInterface
8+
{
9+
/**
10+
* @param string $identifier
11+
* @param StoreProviderInterface $service
12+
*/
13+
public function register($identifier, $service);
14+
15+
/**
16+
* @param string $identifier
17+
*
18+
* @return bool
19+
*/
20+
public function has($identifier);
21+
22+
/**
23+
* @param string $identifier
24+
*
25+
* @return StoreProviderInterface
26+
*
27+
* @throws \Exception
28+
*/
29+
public function get($identifier);
30+
}

src/ToolboxBundle/Resources/config/pimcore/registry.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,8 @@ services:
1010
ToolboxBundle\Registry\CalculatorRegistry:
1111
arguments:
1212
$columnInterface: 'ToolboxBundle\Calculator\ColumnCalculatorInterface'
13-
$slideColumnInterface: 'ToolboxBundle\Calculator\SlideColumnCalculatorInterface'
13+
$slideColumnInterface: 'ToolboxBundle\Calculator\SlideColumnCalculatorInterface'
14+
15+
# registry: store provider
16+
ToolboxBundle\Registry\StoreProviderRegistryInterface: '@ToolboxBundle\Registry\StoreProviderRegistry'
17+
ToolboxBundle\Registry\StoreProviderRegistry: ~

0 commit comments

Comments
 (0)