Passed
Push — master ( 442a9a...3948f8 )
by Dāvis
05:23
created

DependencyInjection/Component/Oauth.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace Sludio\HelperBundle\DependencyInjection\Component;
4
5
use LogicException;
6
use Sludio\HelperBundle\Oauth\Configurator;
7
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
8
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
9
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
10
use Symfony\Component\Config\Definition\Processor;
11
use Symfony\Component\DependencyInjection\ContainerBuilder;
12
use Symfony\Component\DependencyInjection\Reference;
13
14
class Oauth extends AbstractComponent implements ExtensionInterface
15
{
16
    /**
17
     * List of available Oauth providers
18
     * @var array
19
     */
20
    protected static $supportedProviderTypes = [
21
        'custom' => Configurator\CustomProviderConfigurator::class,
22
        'facebook' => Configurator\FacebookProviderConfigurator::class,
23
        'google' => Configurator\GoogleProviderConfigurator::class,
24
        'twitter' => Configurator\TwitterProviderConfigurator::class,
25
        'draugiem' => Configurator\DraugiemProviderConfigurator::class,
26
    ];
27
    protected $checkClassExistence;
28
    protected $configurators = [];
29
    protected $type;
30
    protected $alias;
31
32
    public function __construct($checkClassExistence = true)
33
    {
34
        $this->checkClassExistence = $checkClassExistence;
35
    }
36
37
    public static function getAllSupportedTypes()
38
    {
39
        return array_keys(self::$supportedProviderTypes);
40
    }
41
42
    public function getConfigurator($type)
43
    {
44
        if (!isset($this->configurators[$type])) {
45
            $class = self::$supportedProviderTypes[$type];
46
47
            $this->configurators[$type] = new $class();
48
        }
49
50
        return $this->configurators[$type];
51
    }
52
53
    public function buildClientConfiguration(NodeDefinition $node)
54
    {
55
        $node->addDefaultsIfNotSet();
0 ignored issues
show
The method addDefaultsIfNotSet() does not exist on Symfony\Component\Config...\Builder\NodeDefinition. It seems like you code against a sub-type of Symfony\Component\Config...\Builder\NodeDefinition such as Symfony\Component\Config...der\ArrayNodeDefinition. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

55
        $node->/** @scrutinizer ignore-call */ 
56
               addDefaultsIfNotSet();
Loading history...
56
        $optionsNode = $node->children();
57
58
        // @formatter:off
59
        $optionsNode
60
            ->scalarNode('client_id')->isRequired()->cannotBeEmpty()->end()
61
            ->scalarNode('client_secret')->isRequired()->cannotBeEmpty()->end()
62
            ->booleanNode('use_state')->defaultValue(true)->end()
63
        ;
64
        // @formatter:on
65
66
        $this->getConfigurator($this->getType())->buildConfiguration($optionsNode);
67
        $optionsNode->end();
68
    }
69
70
    public function configureClient(ContainerBuilder $container, $clientServiceKey, array $options = [])
71
    {
72
        $providerClass = $options['provider_class'];
73
        if ($this->checkClassExistence && !class_exists($providerClass)) {
74
            throw new LogicException(sprintf('Class "%s" does not exist.', $providerClass));
75
        }
76
77
        $providerServiceKey = sprintf($this->alias.'.provider.%s', $clientServiceKey);
78
79
        $providerDefinition = $container->register($providerServiceKey, $providerClass);
80
        $providerDefinition->setPublic(false);
81
82
        $providerDefinition->setFactory([
83
            new Reference($this->alias.'.provider_factory'),
84
            'createProvider',
85
        ]);
86
87
        $mandatory = [
88
            $providerClass,
89
            $options['provider_options'],
90
        ];
91
92
        $optional = [];
93
94
        if (isset($options['provider_options']['params'])) {
95
            $optional[] = $options['provider_options']['params'];
96
        }
97
98
        $providerDefinition->setArguments(array_merge($mandatory, $optional));
99
100
        $clientServiceKey = sprintf($this->alias.'.client.%s', $clientServiceKey);
101
        $clientClass = $options['client_class'];
102
        $clientDefinition = $container->register($clientServiceKey, $clientClass);
103
        $clientDefinition->setArguments([
104
            new Reference($providerServiceKey),
105
            new Reference('request_stack')
106
        ]);
107
108
        if (!$options['state']) {
109
            $clientDefinition->addMethodCall('setAsStateless');
110
        }
111
112
        return $clientServiceKey;
113
    }
114
115
    public function configure(ContainerBuilder $container, $alias)
116
    {
117
        $this->alias = $alias.'.oauth';
118
        $clientConfigurations = $container->getParameter($this->alias.'.clients');
119
        $clientServiceKeys = [];
120
        /** @var $clientConfigurations array */
121
        foreach ($clientConfigurations as $key => $clientConfig) {
122
            $tree = new TreeBuilder();
123
            $processor = new Processor();
124
125
            if (!isset($clientConfig['type'])) {
126
                throw new InvalidConfigurationException(sprintf('Your "sludio_helper_oauth_client.clients.%s" config entry is missing the "type" key.', $key));
127
            }
128
129
            $this->type = $clientConfig['type'];
130
            unset($clientConfig['type']);
131
            if (!isset(self::$supportedProviderTypes[$this->type])) {
132
                $supportedKeys = array_keys(self::$supportedProviderTypes);
133
                sort($supportedKeys);
134
                throw new InvalidConfigurationException(sprintf('The "sludio_helper_oauth_client.clients" config "type" key "%s" is not supported. We support: %s', $this->type, implode(', ', $supportedKeys)));
135
            }
136
137
            $node = $tree->root('sludio_helper_oauth_client/clients/'.$key);
138
            $this->buildClientConfiguration($node);
139
            $config = $processor->process($tree->buildTree(), [$clientConfig]);
140
141
            $configurator = $this->getConfigurator($this->type);
142
143
            $options = [
144
                'provider_class' => $configurator->getProviderClass($config),
145
                'client_class' => $configurator->getClientClass($config),
146
                'provider_options' => $configurator->getProviderOptions($config),
147
                'state' => $config['use_state'],
148
            ];
149
150
            $clientServiceKey = $this->configureClient($container, $key, $options);
151
152
            $service = [
153
                'key' => $clientServiceKey,
154
            ];
155
            if (isset($config['provider_options']['name'])) {
156
                $service['name'] = $config['provider_options']['name'];
157
            } else {
158
                $service['name'] = ucfirst($key);
159
            }
160
161
            $clientServiceKeys[$key] = $service;
162
        }
163
164
        $container->getDefinition($this->alias.'.registry')->replaceArgument(1, $clientServiceKeys);
165
        $container->getDefinition($alias.'.registry')->replaceArgument(1, $clientServiceKeys);
166
    }
167
168
    /**
169
     * @return mixed
170
     */
171
    public function getType()
172
    {
173
        return $this->type;
174
    }
175
176
    /**
177
     * @param $type
178
     *
179
     * @return $this
180
     */
181
    public function setType($type)
182
    {
183
        $this->type = $type;
184
185
        return $this;
186
    }
187
}
188