Passed
Pull Request — master (#110)
by Arnaud
02:33
created

ActionCollectionField   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 155
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 89
dl 0
loc 155
rs 10
c 0
b 0
f 0
wmc 19

4 Methods

Rating   Name   Duplication   Size   Complexity  
A render() 0 14 3
C resolveActionLinkConfiguration() 0 98 11
A configureOptions() 0 27 4
A isSortable() 0 3 1
1
<?php
2
3
namespace LAG\AdminBundle\Field;
4
5
use LAG\AdminBundle\Configuration\ActionConfiguration;
6
use LAG\AdminBundle\Field\Traits\EntityAwareTrait;
7
use LAG\AdminBundle\Field\Traits\TwigAwareTrait;
8
use LAG\AdminBundle\Routing\RoutingLoader;
9
use LAG\AdminBundle\Utils\StringUtils;
10
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
11
use Symfony\Component\OptionsResolver\Options;
12
use Symfony\Component\OptionsResolver\OptionsResolver;
13
use Symfony\Component\PropertyAccess\PropertyAccess;
14
15
class ActionCollectionField extends CollectionField implements TwigAwareFieldInterface, EntityAwareFieldInterface
16
{
17
    use TwigAwareTrait, EntityAwareTrait;
18
19
    public function configureOptions(OptionsResolver $resolver, ActionConfiguration $actionConfiguration)
20
    {
21
        parent::configureOptions($resolver, $actionConfiguration);
22
23
        $resolver
24
            ->setDefaults([
25
                'template' => '@LAGAdmin/Field/actionCollection.html.twig',
26
                'actions' => [],
27
            ])
28
            ->setNormalizer('actions', function (Options $options, $value) use ($actionConfiguration) {
29
                if (!is_array($value) || 0 === count($value)) {
30
                    $value = [
31
                        'edit' => [],
32
                        'delete' => [],
33
                    ];
34
                }
35
                $data = [];
36
37
                foreach ($value as $name => $actionLinkConfiguration) {
38
                    $data[$name] = $this->resolveActionLinkConfiguration(
39
                        $actionConfiguration,
40
                        $name,
41
                        $actionLinkConfiguration
42
                    );
43
                }
44
45
                return $data;
46
            })
47
        ;
48
    }
49
50
    public function isSortable(): bool
51
    {
52
        return false;
53
    }
54
55
    public function render($value = null): string
56
    {
57
        $accessor = PropertyAccess::createPropertyAccessor();
58
59
        if (key_exists('edit', $this->options['actions'])) {
60
            $this->options['actions']['edit']['parameters']['id'] = $accessor->getValue($this->entity, 'id');
61
        }
62
63
        if (key_exists('delete', $this->options['actions'])) {
64
            $this->options['actions']['delete']['parameters']['id'] = $accessor->getValue($this->entity, 'id');
65
        }
66
67
        return $this->twig->render($this->options['template'], [
68
            'actions' => $this->options['actions'],
69
        ]);
70
    }
71
72
    protected function resolveActionLinkConfiguration(
73
        ActionConfiguration $actionConfiguration,
74
        string $actionName,
75
        array $actionLinkConfiguration = []
76
    ): array {
77
        $translationPattern = $actionConfiguration
78
            ->getAdminConfiguration()
79
            ->getParameter('translation_pattern')
80
        ;
81
82
        $icon = '';
83
        $cssClass = '';
84
        $routeParameters = [];
85
86
        if ('delete' === $actionName) {
87
            $icon = 'remove';
88
            $cssClass = 'btn btn-danger btn-sm';
89
            $routeParameters = [
90
                'id' => '',
91
            ];
92
        }
93
        if ('edit' === $actionName) {
94
            $icon = 'pencil';
95
            $cssClass = 'btn btn-secondary btn-sm';
96
        }
97
98
        $resolver = new OptionsResolver();
99
        $resolver
100
            ->setDefaults([
101
                'title' => StringUtils::getTranslationKey(
102
                    $translationPattern,
103
                    $actionConfiguration->getAdminName(),
104
                    $actionName
105
                ),
106
                'icon' => $icon,
107
                'target' => '_self',
108
                'route' => '',
109
                'parameters' => $routeParameters,
110
                'url' => '',
111
                'text' => StringUtils::getTranslationKey(
112
                    $translationPattern,
113
                    $actionConfiguration->getAdminName(),
114
                    $actionName
115
                ),
116
                'admin' => $actionConfiguration->getAdminName(),
117
                'action' => $actionName,
118
                'class' => $cssClass,
119
            ])
120
            ->setAllowedTypes('route', 'string')
121
            ->setAllowedTypes('parameters', 'array')
122
            ->setAllowedTypes('url', 'string')
123
            ->setAllowedValues('target', [
124
                '_self',
125
                '_blank',
126
            ])
127
            ->setNormalizer('route', function (Options $options, $value) use ($actionConfiguration) {
128
                // route or url should be defined
129
                if (!$value && !$options->offsetGet('url') && !$options->offsetGet('admin')) {
130
                    throw new InvalidOptionsException(
131
                        'You must set either an url or a route for the property'
132
                    );
133
                }
134
135
                if ($options->offsetGet('admin')) {
136
                    $value = RoutingLoader::generateRouteName(
137
                        $options->offsetGet('admin'),
138
                        $options->offsetGet('action'),
139
                        $actionConfiguration->getAdminConfiguration()->getParameter('routing_name_pattern')
140
                    );
141
                }
142
143
                return $value;
144
            })
145
            ->setNormalizer('admin', function (Options $options, $value) {
146
                // if a Admin is defined, an Action should be defined too
147
                if ($value && !$options->offsetGet('action')) {
148
                    throw new InvalidOptionsException(
149
                        'An Action should be provided if an Admin is provided'
150
                    );
151
                }
152
153
                return $value;
154
            })
155
            ->setNormalizer('parameters', function (Options $options, $values) {
156
                $cleanedValues = [];
157
158
                foreach ($values as $name => $method) {
159
                    if (null === $method) {
160
                        $method = $name;
161
                    }
162
                    $cleanedValues[$name] = $method;
163
                }
164
165
                return $cleanedValues;
166
            })
167
        ;
168
169
        return $resolver->resolve($actionLinkConfiguration);
170
    }
171
}
172