Skip to content

Commit 6cabba2

Browse files
committed
Fix note
1 parent 54d41cb commit 6cabba2

File tree

4 files changed

+195
-5
lines changed

4 files changed

+195
-5
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace MetaModels\CoreBundle\Contao\Picker;
4+
5+
use ContaoCommunityAlliance\DcGeneral\Picker\IdTranscoderInterface;
6+
use InvalidArgumentException;
7+
8+
use function preg_match;
9+
use function strtr;
10+
11+
final readonly class InsertTagIdTranscoder implements IdTranscoderInterface
12+
{
13+
public function __construct(
14+
private string $metaModel,
15+
private string $renderSettingId,
16+
){
17+
}
18+
19+
public function encode(string $id): string
20+
{
21+
return strtr(
22+
'{{mm::jumpTo::<metaModel>::<id>::<rendersettingId>}}',
23+
[
24+
'<metaModel>' => $this->metaModel,
25+
'<rendersettingId>' => $this->renderSettingId,
26+
'<id>' => $id
27+
]
28+
);
29+
}
30+
31+
public function decode(string $encodedId): string
32+
{
33+
if (
34+
1 !== preg_match(
35+
'#^{{mm::jumpTo::(?<metaModel>[^:]*)::(?<id>[^:]*)::(?<rendersettingId>[^|}]*)(:?\|.*)?}}$#',
36+
$encodedId,
37+
$matches
38+
)
39+
) {
40+
throw new InvalidArgumentException('Unparsable id value');
41+
}
42+
if ($matches['metaModel'] !== $this->metaModel || $matches['rendersettingId'] !== $this->renderSettingId) {
43+
throw new InvalidArgumentException('Not my id value');
44+
}
45+
46+
return $matches['id'];
47+
}
48+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MetaModels\CoreBundle\Contao\Picker;
6+
7+
use Contao\CoreBundle\Picker\PickerConfig;
8+
use Contao\CoreBundle\Picker\PickerProviderInterface;
9+
use ContaoCommunityAlliance\DcGeneral\Picker\IdTranscoderInterface;
10+
use ContaoCommunityAlliance\DcGeneral\Picker\IdTranscodingPickerProviderInterface;
11+
use Knp\Menu\FactoryInterface;
12+
use Knp\Menu\ItemInterface;
13+
use Symfony\Component\Routing\RouterInterface;
14+
use Symfony\Contracts\Translation\TranslatorInterface;
15+
use Throwable;
16+
17+
use function strtr;
18+
19+
class MetaModelsJumpToPickerProvider implements PickerProviderInterface, IdTranscodingPickerProviderInterface
20+
{
21+
public function __construct(
22+
private readonly FactoryInterface $menuFactory,
23+
private readonly RouterInterface $router,
24+
private readonly TranslatorInterface $translator,
25+
private readonly string $tableName,
26+
private readonly string $renderSettingId,
27+
private readonly ?string $linkIcon,
28+
) {
29+
}
30+
31+
public function getName(): string
32+
{
33+
return 'metamodelPicker_' . $this->tableName . '_' . $this->renderSettingId;
34+
}
35+
36+
public function getUrl(PickerConfig $config): ?string
37+
{
38+
return $this->generateUrl($config);
39+
}
40+
41+
public function createMenuItem(PickerConfig $config): ItemInterface
42+
{
43+
$label = $this->translator->trans('name', [], $this->tableName);
44+
45+
$attributes = ['class' => $this->tableName];
46+
if (null !== $this->linkIcon) {
47+
$attributes['style'] = strtr('background-image: url(:icon-url:)', [':icon-url:' => $this->linkIcon]);
48+
}
49+
50+
return $this->menuFactory->createItem($this->tableName, [
51+
'label' => ('name' !== $label) ? $label : $this->tableName,
52+
'linkAttributes' => $attributes,
53+
'current' => $this->isCurrent($config),
54+
'uri' => $this->generateUrl($config),
55+
]);
56+
}
57+
58+
public function supportsContext($context): bool
59+
{
60+
return 'link' === $context;
61+
}
62+
63+
public function supportsValue(PickerConfig $config): bool
64+
{
65+
try {
66+
$this->createIdTranscoder($config)->decode($config->getValue());
67+
} catch (Throwable $e) {
68+
return false;
69+
}
70+
71+
return true;
72+
}
73+
74+
public function isCurrent(PickerConfig $config): bool
75+
{
76+
return $config->getCurrent() === $this->getName();
77+
}
78+
79+
public function createIdTranscoder(PickerConfig $config): IdTranscoderInterface
80+
{
81+
return new InsertTagIdTranscoder($this->tableName, $this->renderSettingId);
82+
}
83+
84+
private function generateUrl(PickerConfig $config): ?string
85+
{
86+
$newConfig = $config->cloneForCurrent($this->getName());
87+
$newConfig->setExtra('sourceName', $this->tableName);
88+
$params = [
89+
'fieldType' => 'radio',
90+
'picker' => $newConfig->urlEncode(),
91+
'propertyName' => 'id',
92+
];
93+
94+
return $this->router->generate('cca_dc_general_picker_tree', $params);
95+
}
96+
}

src/CoreBundle/DependencyInjection/Configuration.php

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
/**
44
* This file is part of MetaModels/core.
55
*
6-
* (c) 2012-2023 The MetaModels team.
6+
* (c) 2012-2025 The MetaModels team.
77
*
88
* For the full copyright and license information, please view the LICENSE
99
* file that was distributed with this source code.
@@ -14,13 +14,14 @@
1414
* @author Christian Schiffler <[email protected]>
1515
* @author Sven Baumann <[email protected]>
1616
* @author Ingolf Steinhardt <[email protected]>
17-
* @copyright 2012-2023 The MetaModels team.
17+
* @copyright 2012-2025 The MetaModels team.
1818
* @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later
1919
* @filesource
2020
*/
2121

2222
namespace MetaModels\CoreBundle\DependencyInjection;
2323

24+
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
2425
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
2526
use Symfony\Component\Config\Definition\ConfigurationInterface;
2627
use Symfony\Component\Filesystem\Path;
@@ -66,10 +67,9 @@ public function __construct($debug, $rootDir)
6667
public function getConfigTreeBuilder()
6768
{
6869
$treeBuilder = new TreeBuilder('metamodels');
69-
7070
$treeBuilder
7171
->getRootNode()
72-
->children()
72+
->children()
7373
->booleanNode('enable_cache')
7474
->defaultValue(!$this->debug)
7575
->end()
@@ -89,11 +89,29 @@ public function getConfigTreeBuilder()
8989
->cannotBeEmpty()
9090
->defaultValue('/assets/metamodels')
9191
->end()
92-
->end();
92+
->append($this->addJumpToPickerNode());
9393

9494
return $treeBuilder;
9595
}
9696

97+
private function addJumpToPickerNode(): NodeDefinition
98+
{
99+
$treeBuilder = new TreeBuilder('picker_jumpto');
100+
$node = $treeBuilder->getRootNode();
101+
$node
102+
->useAttributeAsKey('name')
103+
->arrayPrototype()
104+
->children()
105+
->scalarNode('render_setting')->cannotBeEmpty()->end()
106+
->integerNode('priority')->defaultValue(0)->end()
107+
->scalarNode('icon')->defaultNull()->end()
108+
->end()
109+
->end()
110+
->end();
111+
112+
return $node;
113+
}
114+
97115
/**
98116
* Resolves a path.
99117
*

src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,19 @@
2424
namespace MetaModels\CoreBundle\DependencyInjection;
2525

2626
use MetaModels\CoreBundle\Attribute\DoctrineSchemaProvider;
27+
use MetaModels\CoreBundle\Contao\Picker\MetaModelsJumpToPickerProvider;
2728
use MetaModels\CoreBundle\DependencyInjection\CompilerPass\CollectDoctrineSchemaGeneratorsPass;
2829
use MetaModels\CoreBundle\Migration\TableCollationMigration;
2930
use Symfony\Component\Cache\Adapter\ArrayAdapter;
3031
use Symfony\Component\Config\Definition\ConfigurationInterface;
3132
use Symfony\Component\Config\FileLocator;
3233
use Symfony\Component\DependencyInjection\ChildDefinition;
3334
use Symfony\Component\DependencyInjection\ContainerBuilder;
35+
use Symfony\Component\DependencyInjection\Definition;
3436
use Symfony\Component\DependencyInjection\Extension\Extension;
3537
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
3638
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
39+
use Symfony\Component\DependencyInjection\Reference;
3740

3841
/**
3942
* This is the class that loads and manages the bundle configuration
@@ -119,6 +122,11 @@ static function (ChildDefinition $definition, DoctrineSchemaProvider $attribute)
119122

120123
$container->getDefinition(TableCollationMigration::class)
121124
->setArgument('$defaultTableOptions', $this->defaultTableOptions);
125+
126+
$jumpToPicker = $config['picker_jumpto'];
127+
if (null !== $jumpToPicker) {
128+
$this->processJumpToPicker($jumpToPicker, $container);
129+
}
122130
}
123131

124132
/**
@@ -185,4 +193,24 @@ private function collectDefaultTableOptionsFromDoctrineExtension(ContainerBuilde
185193
}
186194
$this->defaultTableOptions = \array_merge(...$defaultTableOptions);
187195
}
196+
197+
/** @param array<string, array{render_setting: string, priority: int, icon: ?string}> $jumpToPicker */
198+
private function processJumpToPicker(mixed $jumpToPicker, ContainerBuilder $container): void
199+
{
200+
$menuFactory = new Reference('knp_menu.factory');
201+
$router = new Reference('router');
202+
$translator = new Reference('translator');
203+
foreach ($jumpToPicker as $metaModelName => $config) {
204+
$definition = new Definition(MetaModelsJumpToPickerProvider::class);
205+
$definition->setArgument('$menuFactory', $menuFactory);
206+
$definition->setArgument('$router', $router);
207+
$definition->setArgument('$translator', $translator);
208+
$definition->setArgument('$tableName', $metaModelName);
209+
$definition->setArgument('$renderSettingId', $config['render_setting']);
210+
$definition->setArgument('$linkIcon', $config['icon']);
211+
$definition->addTag('contao.picker_provider', ['priority' => $config['priority']]);
212+
213+
$container->setDefinition('metamodels_jump_to_picker_' . $metaModelName, $definition);
214+
}
215+
}
188216
}

0 commit comments

Comments
 (0)