BreakDownComponentFactory::supports()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace BenTools\OpenCubes\Component\BreakDown;
4
5
use BenTools\OpenCubes\Component\BreakDown\Model\Group;
6
use BenTools\OpenCubes\Component\ComponentFactoryInterface;
7
use BenTools\OpenCubes\Component\ComponentInterface;
8
use BenTools\OpenCubes\OptionsTrait;
9
use Psr\Http\Message\UriInterface;
10
use Symfony\Component\OptionsResolver\OptionsResolver;
11
12
final class BreakDownComponentFactory implements ComponentFactoryInterface
13
{
14
    use OptionsTrait;
15
    
16
    public const OPT_AVAILABLE_GROUPS = 'available_groups';
17
    public const OPT_DEFAULT_GROUPS = 'default_groups';
18
    public const OPT_APPLIED_GROUPS = 'applied_groups';
19
    public const OPT_ENABLE_MULTIGROUP = 'enable_multiple_groups';
20
21
    /**
22
     * @var BreakDownUriManagerInterface
23
     */
24
    private $uriManager;
25
26
    /**
27
     * BreakDownComponentFactory constructor.
28
     * @param array                             $options
29
     * @param BreakDownUriManagerInterface|null $uriManager
30
     */
31
    public function __construct(array $options = [], BreakDownUriManagerInterface $uriManager = null)
32
    {
33
        $this->options = $options;
34
        $this->uriManager = $uriManager ?? new BreakDownUriManager();
35
    }
36
37
    /**
38
     * @inheritDoc
39
     */
40
    public function supports(string $name): bool
41
    {
42
        return BreakDownComponent::getName() === $name;
43
    }
44
45
    /**
46
     * @param array $options
47
     * @return array
48
     * @throws \Symfony\Component\OptionsResolver\Exception\AccessException
49
     * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
50
     * @throws \Symfony\Component\OptionsResolver\Exception\MissingOptionsException
51
     * @throws \Symfony\Component\OptionsResolver\Exception\NoSuchOptionException
52
     * @throws \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException
53
     * @throws \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
54
     */
55
    protected function resolveOptions(array $options): array
56
    {
57
        $resolver = new OptionsResolver();
58
        $resolver->setDefaults([
59
            self::OPT_AVAILABLE_GROUPS  => [],
60
            self::OPT_DEFAULT_GROUPS    => [],
61
            self::OPT_APPLIED_GROUPS    => [],
62
            self::OPT_ENABLE_MULTIGROUP => true,
63
        ]);
64
65
        $resolver->setAllowedTypes(self::OPT_AVAILABLE_GROUPS, 'array');
66
        $resolver->setAllowedTypes(self::OPT_DEFAULT_GROUPS, 'array');
67
        $resolver->setAllowedTypes(self::OPT_APPLIED_GROUPS, 'array');
68
        $resolver->setAllowedTypes(self::OPT_ENABLE_MULTIGROUP, 'bool');
69
70
        return $resolver->resolve($options);
71
    }
72
73
    /**
74
     * @inheritDoc
75
     * @return BreakDownComponent
76
     */
77
    public function createComponent(UriInterface $uri, array $options = []): ComponentInterface
78
    {
79
        $options = $this->resolveOptions(
80
            $this->getMergedOptions($options, [
81
                self::OPT_APPLIED_GROUPS => $this->uriManager->getAppliedGroups($uri),
82
            ])
83
        );
84
85
        $rawAppliedGroups = [] !== $this->getOption(self::OPT_APPLIED_GROUPS, $options) ? $this->getOption(self::OPT_APPLIED_GROUPS, $options) : $this->getOption(self::OPT_DEFAULT_GROUPS, $options);
86
        $rawAvailableGroups = $this->getOption(self::OPT_AVAILABLE_GROUPS, $options);
87
        $appliedGroups = [];
88
        $availableGroups = [];
89
90
91
        // Add to available if necessary
92
        foreach ($rawAppliedGroups as $field) {
93
            if (!array_key_exists($field, $rawAvailableGroups)) {
94
                $rawAvailableGroups[] = $field;
95
            }
96
        }
97
98
        // Create URIs
99
        foreach ($rawAppliedGroups as $f => $field) {
100
            $stack = $rawAppliedGroups;
101
            unset($stack[$f]);
102
            $stack = array_values($stack);
103
104
            $uri = $this->uriManager->buildGroupUri($uri, $stack);
105
            $appliedGroups[] = new Group($field, true, $uri);
106
        }
107
108
109
        // Cleanup
110
        foreach ($rawAvailableGroups as $f => $field) {
111
            if (in_array($field, $rawAppliedGroups)) {
112
                unset($rawAvailableGroups[$f]);
113
            }
114
        }
115
        $rawAvailableGroups = array_values($rawAvailableGroups);
116
117
        // Generate available groups
118
        foreach ($rawAvailableGroups as $field) {
119
            if (true === $this->getOption(self::OPT_ENABLE_MULTIGROUP, $options)) {
120
                $stack = $rawAppliedGroups;
121
                $stack[] = $field;
122
            } else {
123
                $stack = [$field];
124
            }
125
            $uri = $this->uriManager->buildGroupUri($uri, $stack);
126
            $availableGroups[] = new Group($field, false, $uri);
127
        }
128
129
130
        return new BreakDownComponent(array_merge($appliedGroups, $availableGroups));
131
    }
132
}
133