Completed
Pull Request — develop (#579)
by
unknown
15:32 queued 10:40
created

ServiceConverter   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 197
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 12

Test Coverage

Coverage 0%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 19
lcom 1
cbo 12
dl 0
loc 197
ccs 0
cts 99
cp 0
rs 10
c 2
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 1
B init() 0 29 6
A getServices() 0 18 3
A getServiceSchemaByRoute() 0 13 2
A getData() 0 21 4
A getSchema() 0 7 1
A supports() 0 4 1
A apply() 0 8 1
1
<?php
2
/**
3
 * ParamConverter class for entry point to Analytics Bundle
4
 */
5
6
namespace Graviton\AnalyticsBundle\Request\ParamConverter;
7
8
use Graviton\AnalyticsBundle\Helper\JsonMapper;
9
use Graviton\AnalyticsBundle\Manager\AnalyticsManager;
10
use Graviton\AnalyticsBundle\Model\AnalyticModel;
11
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
12
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;
13
use Symfony\Component\HttpFoundation\Request;
14
use Symfony\Component\Finder\Finder;
15
use Doctrine\Common\Cache\CacheProvider;
16
use Symfony\Component\Routing\Router;
17
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
18
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
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  http://opensource.org/licenses/gpl-license.php GNU Public License
25
 * @link     http://swisscom.ch
26
 */
27
class ServiceConverter implements ParamConverterInterface
28
{
29
    /** Cache name for services */
30
    const CACHE_KEY_SERVICES = 'analytics_services';
31
    const CACHE_KEY_SERVICES_TIME = 10;
32
    const CACHE_KEY_SERVICES_URLS = 'analytics_services_urls';
33
    const CACHE_KEY_SERVICES_URLS_TIME = 10;
34
    const CACHE_KEY_SERVICES_PREFIX = 'analytics_';
35
36
    /** @var AnalyticsManager */
37
    protected $analyticsManager;
38
39
    /** @var CacheProvider */
40
    protected $cacheProvider;
41
42
    /** @var Router */
43
    protected $router;
44
45
    /** @var string */
46
    protected $directory;
47
48
    /** @var array  */
49
    private $services = [];
50
51
    /**
52
     * ServiceConverter constructor.
53
     * @param AnalyticsManager $analyticsManager    Db Manager and query control
54
     * @param CacheProvider    $cacheProvider       Cache service
55
     * @param Router           $router              To manage routing generation
56
     * @param string           $definitionDirectory Where definitions are stored
57
     */
58
    public function __construct(
59
        AnalyticsManager $analyticsManager,
60
        CacheProvider $cacheProvider,
61
        Router $router,
62
        $definitionDirectory
63
    ) {
64
        $this->analyticsManager = $analyticsManager;
65
        $this->cacheProvider = $cacheProvider;
66
        $this->router = $router;
67
        $this->directory = $definitionDirectory;
68
        $this->init();
69
    }
70
71
    /**
72
     * Scan base root directory for analytic definitions
73
     * @return void
74
     */
75
    private function init()
76
    {
77
        $this->services = $this->cacheProvider->fetch(self::CACHE_KEY_SERVICES);
78
        if (is_array($this->services)) {
79
            return;
80
        }
81
        $this->services = [];
82
        if (strpos($this->directory, 'vendor/graviton/graviton')) {
83
            $this->directory = str_replace('vendor/graviton/graviton/', '', $this->directory);
84
        }
85
        if (!is_dir($this->directory)) {
86
            return;
87
        }
88
        $finder = new Finder();
89
        $finder->files()->in($this->directory)
90
            ->name('*.json')
91
            ->notName('_*');
92
        foreach ($finder as $file) {
93
            $key = $file->getFilename();
94
            $data = json_decode($file->getContents());
95
            if (json_last_error()) {
96
                throw new InvalidConfigurationException(
97
                    sprintf('Analytics file: %s could not be loaded due to error: ', $key, json_last_error_msg())
98
                );
99
            }
100
            $this->services[$data->route] = $data;
101
        }
102
        $this->cacheProvider->save(self::CACHE_KEY_SERVICES, $this->services, self::CACHE_KEY_SERVICES_TIME);
103
    }
104
105
    /**
106
     * Return array of available services
107
     *
108
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
109
     */
110
    public function getServices()
111
    {
112
        $services = $this->cacheProvider->fetch(self::CACHE_KEY_SERVICES_URLS);
113
        if (is_array($services)) {
114
            return ['services' => $services];
115
        }
116
        $services = [];
117
        $r = $this->router;
118
        $b = $r->getContext()->getScheme().'://'.$r->getContext()->getHost().':'.$r->getContext()->getHttpPort();
119
        foreach ($this->services as $name => $service) {
120
            $services[] = [
121
                '$ref' => $b.$r->generate('graviton_analytics_service', ['service' => $service->route], false),
122
                'profile' => $b.$r->generate('graviton_analytics_service_schema', ['service' => $service->route], true)
123
            ];
124
        }
125
        $this->cacheProvider->save(self::CACHE_KEY_SERVICES_URLS, $services, self::CACHE_KEY_SERVICES_URLS_TIME);
126
        return ['services' => $services];
127
    }
128
129
    /**
130
     * Get service definition
131
     *
132
     * @param string $name Route name for service
133
     * @throws NotFoundHttpException
134
     * @return AnalyticModel
135
     */
136
    private function getServiceSchemaByRoute($name)
137
    {
138
        // Locate the schema definition
139
        if (!array_key_exists($name, $this->services)) {
140
            throw new NotFoundHttpException(
141
                sprintf('Service Analytics for %s was not found', $name)
142
            );
143
        }
144
        $mapper = new JsonMapper();
145
        /** @var AnalyticModel $schema */
146
        $schema = $mapper->map($this->services[$name], new AnalyticModel());
147
        return $schema;
148
    }
149
150
    /**
151
     * Will map and find data for defined route
152
     *
153
     * @param string $serviceRoute Route name for service
154
     * @return array
155
     */
156
    public function getData($serviceRoute)
157
    {
158
        // Locate the schema definition
159
        $schema = $this->getServiceSchemaByRoute($serviceRoute);
160
        $cacheTime = $schema->getCacheTime();
161
162
        //Cached data if configured
163
        if ($cacheTime &&
164
            $cache = $this->cacheProvider->fetch(self::CACHE_KEY_SERVICES_PREFIX.$schema->getRoute())
165
        ) {
166
            return $cache;
167
        }
168
169
        $data = $this->analyticsManager->getData($schema);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->analyticsManager->getData($schema); of type array|object adds the type object to the return on line 175 which is incompatible with the return type documented by Graviton\AnalyticsBundle...rviceConverter::getData of type array.
Loading history...
170
171
        if ($cacheTime) {
172
            $this->cacheProvider->save(self::CACHE_KEY_SERVICES_PREFIX.$schema->getRoute(), $data, $cacheTime);
173
        }
174
175
        return $data;
176
    }
177
178
    /**
179
     * Schema definition
180
     *
181
     * @param string $serviceRoute Route name for service
182
     * @return mixed
183
     */
184
    public function getSchema($serviceRoute)
185
    {
186
        // Locate the schema definition
187
        $schema =  $this->getServiceSchemaByRoute($serviceRoute);
188
189
        return $schema->getSchema();
190
    }
191
192
    /**
193
     * Which service can load this Converter
194
     *
195
     * @param ParamConverter $configuration Configuration data
196
     * @return bool
197
     */
198
    public function supports(ParamConverter $configuration)
199
    {
200
        return true;
201
    }
202
203
    /**
204
     * {@inheritdoc}
205
     *
206
     * Applies converting
207
     *
208
     * @param Request        $request       SF request bag
209
     * @param ParamConverter $configuration Config data
210
     *
211
     * @throws \InvalidArgumentException When route attributes are missing
212
     * @throws NotFoundHttpException     When object not found
213
     * @return void
214
     */
215
    public function apply(Request $request, ParamConverter $configuration)
216
    {
217
        // we could use the request here if needed. $this->setRequest($request);
218
        $manager = $this;
219
220
        // Map found Service to the route's parameter
221
        $request->attributes->set($configuration->getName(), $manager);
222
    }
223
}
224