ServiceManager::getServiceParameters()   D
last analyzed

Complexity

Conditions 19
Paths 41

Size

Total Lines 63

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 380

Importance

Changes 0
Metric Value
dl 0
loc 63
ccs 0
cts 54
cp 0
rs 4.5166
c 0
b 0
f 0
cc 19
nc 41
nop 1
crap 380

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * provides accessors to the analytics services
4
 */
5
6
namespace Graviton\AnalyticsBundle\Manager;
7
8
use Doctrine\Common\Cache\CacheProvider;
9
use Graviton\AnalyticsBundle\Exception\AnalyticUsageException;
10
use Graviton\AnalyticsBundle\Helper\JsonMapper;
11
use Graviton\AnalyticsBundle\Model\AnalyticModel;
12
use Graviton\DocumentBundle\Service\DateConverter;
13
use MongoDB\BSON\Regex;
14
use MongoDB\BSON\UTCDateTime;
15
use Symfony\Component\Filesystem\Filesystem;
16
use Symfony\Component\HttpFoundation\RequestStack;
17
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
18
use Symfony\Component\Routing\Router;
19
20
/**
21
 * Service Request Converter and startup for Analytics
22
 *
23
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
24
 * @license  https://opensource.org/licenses/MIT MIT License
25
 * @link     http://swisscom.ch
26
 */
27
class ServiceManager
28
{
29
    /** Cache name for services */
30
    const CACHE_KEY_SERVICES = 'analytics_services';
31
    const CACHE_KEY_SERVICES_URLS = 'analytics_services_urls';
32
    const CACHE_KEY_SERVICES_PREFIX = 'analytics_';
33
34
    /** @var RequestStack */
35
    protected $requestStack;
36
37
    /** @var AnalyticsManager */
38
    protected $analyticsManager;
39
40
    /** @var CacheProvider */
41
    protected $cacheProvider;
42
43
    /** @var DateConverter */
44
    protected $dateConverter;
45
46
    /** @var Router */
47
    protected $router;
48
49
    /** @var string */
50
    protected $directory;
51
52
    /** @var int */
53
    protected $cacheTimeMetadata;
54
55
    /** @var Filesystem */
56
    protected $fs;
57
58
    /** @var JsonMapper */
59
    private $jsonMapper;
60
61
    /**
62
     * @var string
63
     */
64
    private $skipCacheHeaderName = 'x-analytics-no-cache';
65
66
    /**
67
     * @var array
68
     */
69
    private $analyticsServices = [];
70
71
    /**
72
     * ServiceConverter constructor.
73
     *
74
     * @param RequestStack     $requestStack      Sf Request information service
75
     * @param AnalyticsManager $analyticsManager  Db Manager and query control
76
     * @param CacheProvider    $cacheProvider     Cache service
77
     * @param DateConverter    $dateConverter     date converter
78
     * @param Router           $router            To manage routing generation
79
     * @param int              $cacheTimeMetadata How long to cache metadata
80
     * @param array            $analyticsServices the services
81
     */
82
    public function __construct(
83
        RequestStack $requestStack,
84
        AnalyticsManager $analyticsManager,
85
        CacheProvider $cacheProvider,
86
        DateConverter $dateConverter,
87
        Router $router,
88
        $cacheTimeMetadata,
89
        $analyticsServices
90
    ) {
91
        $this->requestStack = $requestStack;
92
        $this->analyticsManager = $analyticsManager;
93
        $this->cacheProvider = $cacheProvider;
94
        $this->dateConverter = $dateConverter;
95
        $this->router = $router;
96
        $this->cacheTimeMetadata = $cacheTimeMetadata;
97
        $this->fs = new Filesystem();
98
        $this->analyticsServices = $analyticsServices;
99
        $this->jsonMapper = new JsonMapper();
100
    }
101
102
    /**
103
     * Return array of available services
104
     *
105
     * @return array
106
     */
107
    public function getServices()
108
    {
109
        $services = $this->cacheProvider->fetch(self::CACHE_KEY_SERVICES_URLS);
110
        if (is_array($services)) {
111
            return $services;
112
        }
113
114
        $services = [];
115
        foreach ($this->analyticsServices as $name => $service) {
116
            if (is_numeric($name)) {
117
                continue;
118
            }
119
120
            $services[] = [
121
                '$ref' => $this->router->generate(
122
                    'graviton_analytics_service',
123
                    [
124
                        'service' => $service['route']
125
                    ],
126
                    false
127
                ),
128
                'profile' => $this->router->generate(
129
                    'graviton_analytics_service_schema',
130
                    [
131
                        'service' => $service['route']
132
                    ],
133
                    true
134
                )
135
            ];
136
        }
137
        $this->cacheProvider->save(
138
            self::CACHE_KEY_SERVICES_URLS,
139
            $services,
140
            $this->cacheTimeMetadata
141
        );
142
        return $services;
143
    }
144
145
    /**
146
     * Get service definition
147
     *
148
     * @param string $name Route name for service
149
     *
150
     * @throws NotFoundHttpException
151
     * @return AnalyticModel
152
     */
153
    private function getAnalyticModel($name)
154
    {
155
        if (!isset($this->analyticsServices[$name])) {
156
            throw new NotFoundHttpException(
157
                sprintf('Analytic definition "%s" was not found', $name)
158
            );
159
        }
160
161
        return $this->jsonMapper->map($this->analyticsServices[$name], new AnalyticModel());
162
    }
163
164
    /**
165
     * Will map and find data for defined route
166
     *
167
     * @return array
168
     */
169
    public function getData()
170
    {
171
        $serviceRoute = $this->requestStack->getCurrentRequest()
172
                                           ->get('service');
173
174
        // Locate the model definition
175
        $model = $this->getAnalyticModel($serviceRoute);
176
177
        $cacheTime = $model->getCacheTime();
178
        $cacheKey = $this->getCacheKey($model);
179
180
        //Cached data if configured
181
        if ($cacheTime &&
182
            !$this->requestStack->getCurrentRequest()->headers->has($this->skipCacheHeaderName) &&
183
            $cache = $this->cacheProvider->fetch($cacheKey)
184
        ) {
185
            return $cache;
186
        }
187
188
        $data = $this->analyticsManager->getData($model, $this->getServiceParameters($model));
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->analyticsManager-...iceParameters($model)); of type array|object adds the type object to the return on line 194 which is incompatible with the return type documented by Graviton\AnalyticsBundle...ServiceManager::getData of type array.
Loading history...
189
190
        if ($cacheTime) {
191
            $this->cacheProvider->save($cacheKey, $data, $cacheTime);
192
        }
193
194
        return $data;
195
    }
196
197
    /**
198
     * generate a cache key also based on query
199
     *
200
     * @param AnalyticModel $schema schema
201
     *
202
     * @return string cache key
203
     */
204
    private function getCacheKey($schema)
205
    {
206
        return self::CACHE_KEY_SERVICES_PREFIX
207
            . $schema->getRoute()
208
            . sha1(serialize($this->requestStack->getCurrentRequest()->query->all()));
209
    }
210
211
    /**
212
     * Locate and display service definition schema
213
     *
214
     * @return mixed
215
     */
216
    public function getSchema()
217
    {
218
        $serviceRoute = $this->requestStack->getCurrentRequest()
219
                                           ->get('service');
220
221
        // Locate the schema definition
222
        $model = $this->getAnalyticModel($serviceRoute);
223
224
        return $model->getSchema();
225
    }
226
227
    /**
228
     * returns the params as passed from the user
229
     *
230
     * @param AnalyticModel $model model
231
     *
232
     * @return array the params, converted as specified
233
     * @throws AnalyticUsageException
234
     */
235
    private function getServiceParameters(AnalyticModel $model)
236
    {
237
        $params = [];
238
        if (!is_array($model->getParams())) {
239
            return $params;
240
        }
241
242
        foreach ($model->getParams() as $param) {
243
            if (!isset($param['name'])) {
244
                throw new \LogicException("Incorrect spec (no name) of param in analytics route " . $model->getRoute());
245
            }
246
247
            $paramValue = $this->requestStack->getCurrentRequest()->query->get($param['name'], null);
248
249
            // default set?
250
            if (is_null($paramValue) && isset($param['default'])) {
251
                $paramValue = $param['default'];
252
            }
253
254
            // required missing?
255
            if (is_null($paramValue) && (isset($param['required']) && $param['required'] === true)) {
256
                throw new AnalyticUsageException(
257
                    sprintf(
258
                        "Missing parameter '%s' in analytics route '%s'",
259
                        $param['name'],
260
                        $model->getRoute()
261
                    )
262
                );
263
            }
264
265
            if (!is_null($param['type']) && !is_null($paramValue)) {
266
                switch ($param['type']) {
267
                    case "integer":
268
                        $paramValue = intval($paramValue);
269
                        break;
270
                    case "boolean":
271
                        $paramValue = boolval($paramValue);
272
                        break;
273
                    case "array":
274
                        $paramValue = explode(',', $paramValue);
275
                        break;
276
                    case "date":
277
                        $paramValue = new UTCDateTime($this->dateConverter->getDateTimeFromString($paramValue));
278
                        break;
279
                    case "regex":
280
                        $paramValue = new Regex($paramValue, 'i');
281
                        break;
282
                    case "array<integer>":
283
                        $paramValue = array_map('intval', explode(',', $paramValue));
284
                        break;
285
                    case "array<boolean>":
286
                        $paramValue = array_map('boolval', explode(',', $paramValue));
287
                        break;
288
                }
289
            }
290
291
            if (!is_null($paramValue)) {
292
                $params[$param['name']] = $paramValue;
293
            }
294
        }
295
296
        return $params;
297
    }
298
}
299