ServiceFactory   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 198
Duplicated Lines 0 %

Importance

Changes 7
Bugs 3 Features 0
Metric Value
wmc 17
eloc 56
c 7
b 3
f 0
dl 0
loc 198
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A buildV1Service() 0 14 2
A resolveScopes() 0 17 3
A getFullyQualifiedServiceName() 0 9 2
A registerService() 0 17 4
A buildV2Service() 0 15 1
A setHttpClient() 0 5 1
A createService() 0 29 4
1
<?php
2
3
/**
4
 * OAuth service factory.
5
 *
6
 * PHP version 5.4
7
 *
8
 * @author     David Desberg <[email protected]>
9
 * @author     Pieter Hordijk <[email protected]>
10
 * @license    http://www.opensource.org/licenses/mit-license.html  MIT License
11
 */
12
13
namespace OAuth;
14
15
use OAuth\Common\Consumer\CredentialsInterface;
16
use OAuth\Common\Exception\Exception;
17
use OAuth\Common\Http\Client\ClientInterface;
18
use OAuth\Common\Http\Client\StreamClient;
19
use OAuth\Common\Http\Uri\UriInterface;
20
use OAuth\Common\Service\ServiceInterface;
21
use OAuth\Common\Storage\TokenStorageInterface;
22
use OAuth\OAuth1\Signature\Signature;
23
use ReflectionClass;
24
25
class ServiceFactory
26
{
27
    /**
28
     *@var ClientInterface
29
     */
30
    protected $httpClient;
31
32
    /**
33
     * @var array
34
     */
35
    protected $serviceClassMap = [
36
        'OAuth1' => [],
37
        'OAuth2' => [],
38
    ];
39
40
    /**
41
     * @var array
42
     */
43
    protected $serviceBuilders = [
44
        'OAuth2' => 'buildV2Service',
45
        'OAuth1' => 'buildV1Service',
46
    ];
47
48
    /**
49
     * @return ServiceFactory
50
     */
51
    public function setHttpClient(ClientInterface $httpClient)
52
    {
53
        $this->httpClient = $httpClient;
54
55
        return $this;
56
    }
57
58
    /**
59
     * Register a custom service to classname mapping.
60
     *
61
     * @param string $serviceName Name of the service
62
     * @param string $className   Class to instantiate
63
     *
64
     * @return ServiceFactory
65
     */
66
    public function registerService($serviceName, $className)
67
    {
68
        if (!class_exists($className)) {
69
            throw new Exception(sprintf('Service class %s does not exist.', $className));
70
        }
71
72
        $reflClass = new ReflectionClass($className);
73
74
        foreach (['OAuth2', 'OAuth1'] as $version) {
75
            if ($reflClass->implementsInterface('OAuth\\' . $version . '\\Service\\ServiceInterface')) {
76
                $this->serviceClassMap[$version][ucfirst($serviceName)] = $className;
77
78
                return $this;
79
            }
80
        }
81
82
        throw new Exception(sprintf('Service class %s must implement ServiceInterface.', $className));
83
    }
84
85
    /**
86
     * Builds and returns oauth services.
87
     *
88
     * It will first try to build an OAuth2 service and if none found it will try to build an OAuth1 service
89
     *
90
     * @param string                $serviceName Name of service to create
91
     * @param null|array            $scopes      If creating an oauth2 service, array of scopes
92
     * @param string                $apiVersion version of the api call
93
     *
94
     * @return ServiceInterface
95
     */
96
    public function createService(
97
        $serviceName,
98
        CredentialsInterface $credentials,
99
        TokenStorageInterface $storage,
100
        $scopes = [],
101
        ?UriInterface $baseApiUri = null,
102
        $apiVersion = ''
103
    ) {
104
        if (!$this->httpClient) {
105
            // for backwards compatibility.
106
            $this->httpClient = new StreamClient();
107
        }
108
109
        foreach ($this->serviceBuilders as $version => $buildMethod) {
110
            $fullyQualifiedServiceName = $this->getFullyQualifiedServiceName($serviceName, $version);
111
112
            if (class_exists($fullyQualifiedServiceName)) {
113
                return $this->$buildMethod(
114
                    $fullyQualifiedServiceName,
115
                    $credentials,
116
                    $storage,
117
                    $scopes,
118
                    $baseApiUri,
119
                    $apiVersion
120
                );
121
            }
122
        }
123
124
        return null;
125
    }
126
127
    /**
128
     * Gets the fully qualified name of the service.
129
     *
130
     * @param string $serviceName The name of the service of which to get the fully qualified name
131
     * @param string $type        The type of the service to get (either OAuth1 or OAuth2)
132
     *
133
     * @return string The fully qualified name of the service
134
     */
135
    private function getFullyQualifiedServiceName($serviceName, $type)
136
    {
137
        $serviceName = ucfirst($serviceName);
138
139
        if (isset($this->serviceClassMap[$type][$serviceName])) {
140
            return $this->serviceClassMap[$type][$serviceName];
141
        }
142
143
        return '\\OAuth\\' . $type . '\\Service\\' . $serviceName;
144
    }
145
146
    /**
147
     * Builds v2 services.
148
     *
149
     * @param string                $serviceName The fully qualified service name
150
     * @param null|array            $scopes      Array of scopes for the service
151
     * @param mixed $apiVersion
152
     *
153
     * @return ServiceInterface
154
     */
155
    private function buildV2Service(
156
        $serviceName,
157
        CredentialsInterface $credentials,
158
        TokenStorageInterface $storage,
159
        array $scopes,
160
        ?UriInterface $baseApiUri = null,
161
        $apiVersion = ''
162
    ) {
163
        return new $serviceName(
164
            $credentials,
165
            $this->httpClient,
166
            $storage,
167
            $this->resolveScopes($serviceName, $scopes),
168
            $baseApiUri,
169
            $apiVersion
170
        );
171
    }
172
173
    /**
174
     * Resolves scopes for v2 services.
175
     *
176
     * @param string  $serviceName The fully qualified service name
177
     * @param array   $scopes      List of scopes for the service
178
     *
179
     * @return array List of resolved scopes
180
     */
181
    private function resolveScopes($serviceName, array $scopes)
182
    {
183
        $reflClass = new ReflectionClass($serviceName);
184
        $constants = $reflClass->getConstants();
185
186
        $resolvedScopes = [];
187
        foreach ($scopes as $scope) {
188
            $key = strtoupper('SCOPE_' . $scope);
189
190
            if (array_key_exists($key, $constants)) {
191
                $resolvedScopes[] = $constants[$key];
192
            } else {
193
                $resolvedScopes[] = $scope;
194
            }
195
        }
196
197
        return $resolvedScopes;
198
    }
199
200
    /**
201
     * Builds v1 services.
202
     *
203
     * @param string                $serviceName The fully qualified service name
204
     * @param array                 $scopes
205
     * @param UriInterface          $baseApiUri
206
     *
207
     * @return ServiceInterface
208
     */
209
    private function buildV1Service(
210
        $serviceName,
211
        CredentialsInterface $credentials,
212
        TokenStorageInterface $storage,
213
        $scopes,
214
        ?UriInterface $baseApiUri = null
215
    ) {
216
        if (!empty($scopes)) {
217
            throw new Exception(
218
                'Scopes passed to ServiceFactory::createService but an OAuth1 service was requested.'
219
            );
220
        }
221
222
        return new $serviceName($credentials, $this->httpClient, $storage, new Signature($credentials), $baseApiUri);
223
    }
224
}
225