Completed
Push — feature/EVO-10415-Analytics-wi... ( 19ad96...6ffc5a )
by
unknown
18:18
created

ServiceConverter::getData()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 0
cts 16
cp 0
rs 8.9197
c 0
b 0
f 0
cc 4
eloc 11
nc 3
nop 0
crap 20
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\HttpFoundation\RequestStack;
17
use Symfony\Component\Routing\Router;
18
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
19
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
20
21
/**
22
 * Service Request Converter and startup for Analytics
23
 *
24
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
25
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
26
 * @link     http://swisscom.ch
27
 */
28
class ServiceConverter implements ParamConverterInterface
29
{
30
    /** Cache name for services */
31
    const CACHE_KEY_SERVICES = 'analytics_services';
32
    const CACHE_KEY_SERVICES_TIME = 10;
33
    const CACHE_KEY_SERVICES_URLS = 'analytics_services_urls';
34
    const CACHE_KEY_SERVICES_URLS_TIME = 10;
35
    const CACHE_KEY_SERVICES_PREFIX = 'analytics_';
36
37
    /** @var Request */
38
    protected $request;
39
40
    /** @var AnalyticsManager */
41
    protected $analyticsManager;
42
43
    /** @var CacheProvider */
44
    protected $cacheProvider;
45
46
    /** @var Router */
47
    protected $router;
48
49
    /** @var string */
50
    protected $directory;
51
52
    /** @var array  */
53
    private $services = [];
54
55
    /**
56
     * ServiceConverter constructor.
57
     * @param RequestStack     $requestStack        Sf Request information service
58
     * @param AnalyticsManager $analyticsManager    Db Manager and query control
59
     * @param CacheProvider    $cacheProvider       Cache service
60
     * @param Router           $router              To manage routing generation
61
     * @param string           $definitionDirectory Where definitions are stored
62
     */
63
    public function __construct(
64
        RequestStack $requestStack,
65
        AnalyticsManager $analyticsManager,
66
        CacheProvider $cacheProvider,
67
        Router $router,
68
        $definitionDirectory
69
    ) {
70
        $this->request = $requestStack->getCurrentRequest();
71
        $this->analyticsManager = $analyticsManager;
72
        $this->cacheProvider = $cacheProvider;
73
        $this->router = $router;
74
        $this->directory = $definitionDirectory;
75
        $this->init();
76
    }
77
78
    /**
79
     * Scan base root directory for analytic definitions
80
     * @return void
81
     */
82
    private function init()
83
    {
84
        $this->services = $this->cacheProvider->fetch(self::CACHE_KEY_SERVICES);
85
86
        if (is_array($this->services)) {
87
            return;
88
        }
89
90
        $this->services = [];
91
        if (strpos($this->directory, 'vendor/graviton/graviton')) {
92
            $this->directory = str_replace('vendor/graviton/graviton/', '', $this->directory);
93
        }
94
        if (!is_dir($this->directory)) {
95
            return;
96
        }
97
98
        $finder = new Finder();
99
        $finder
100
            ->files()
101
            ->in($this->directory)
102
            ->path('/\/analytics\//i')
103
            ->name('*.json')
104
            ->notName('_*')
105
            ->sortByName();
106
107
        foreach ($finder as $file) {
108
            $key = $file->getFilename();
109
            $data = json_decode($file->getContents());
110
            if (json_last_error()) {
111
                throw new InvalidConfigurationException(
112
                    sprintf('Analytics file: %s could not be loaded due to error: ', $key, json_last_error_msg())
113
                );
114
            }
115
            $this->services[$data->route] = $data;
116
        }
117
118
        $this->cacheProvider->save(self::CACHE_KEY_SERVICES, $this->services, self::CACHE_KEY_SERVICES_TIME);
119
    }
120
121
    /**
122
     * Return array of available services
123
     *
124
     * @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...
125
     */
126
    public function getServices()
127
    {
128
        $services = $this->cacheProvider->fetch(self::CACHE_KEY_SERVICES_URLS);
129
        if (is_array($services)) {
130
            return ['services' => $services];
131
        }
132
        $services = [];
133
        $r = $this->router;
134
        $b = $r->getContext()->getScheme().'://'.$r->getContext()->getHost().':'.$r->getContext()->getHttpPort();
135
        foreach ($this->services as $name => $service) {
136
            $services[] = [
137
                '$ref' => $b.$r->generate('graviton_analytics_service', ['service' => $service->route], false),
138
                'profile' => $b.$r->generate('graviton_analytics_service_schema', ['service' => $service->route], true)
139
            ];
140
        }
141
        $this->cacheProvider->save(self::CACHE_KEY_SERVICES_URLS, $services, self::CACHE_KEY_SERVICES_URLS_TIME);
142
        return ['services' => $services];
143
    }
144
145
    /**
146
     * Get service definition
147
     *
148
     * @param string $name Route name for service
149
     * @throws NotFoundHttpException
150
     * @return AnalyticModel
151
     */
152
    private function getServiceSchemaByRoute($name)
153
    {
154
        // Locate the schema definition
155
        if (!array_key_exists($name, $this->services)) {
156
            throw new NotFoundHttpException(
157
                sprintf('Service Analytics for %s was not found', $name)
158
            );
159
        }
160
        $mapper = new JsonMapper();
161
        /** @var AnalyticModel $schema */
162
        $schema = $mapper->map($this->services[$name], new AnalyticModel());
163
        return $schema;
164
    }
165
166
    /**
167
     * Will map and find data for defined route
168
     *
169
     * @return array
170
     */
171
    public function getData()
172
    {
173
        $serviceRoute = $this->request->get('service');
174
        // Locate the schema definition
175
        $schema = $this->getServiceSchemaByRoute($serviceRoute);
176
        $cacheTime = $schema->getCacheTime();
177
178
        //Cached data if configured
179
        if ($cacheTime &&
180
            $cache = $this->cacheProvider->fetch(self::CACHE_KEY_SERVICES_PREFIX.$schema->getRoute())
181
        ) {
182
            return $cache;
183
        }
184
185
        $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 191 which is incompatible with the return type documented by Graviton\AnalyticsBundle...rviceConverter::getData of type array.
Loading history...
186
187
        if ($cacheTime) {
188
            $this->cacheProvider->save(self::CACHE_KEY_SERVICES_PREFIX.$schema->getRoute(), $data, $cacheTime);
189
        }
190
191
        return $data;
192
    }
193
194
    /**
195
     * Locate and display service definition schema
196
     *
197
     * @return mixed
198
     */
199
    public function getSchema()
200
    {
201
        $serviceRoute = $this->request->get('service');
202
203
        // Locate the schema definition
204
        $schema =  $this->getServiceSchemaByRoute($serviceRoute);
205
206
        return $schema->getSchema();
207
    }
208
209
    /**
210
     * Which service can load this Converter
211
     *
212
     * @param ParamConverter $configuration Configuration data
213
     * @return bool
214
     */
215
    public function supports(ParamConverter $configuration)
216
    {
217
        return true;
218
    }
219
220
    /**
221
     * {@inheritdoc}
222
     *
223
     * Applies converting
224
     *
225
     * @param Request        $request       SF request bag
226
     * @param ParamConverter $configuration Config data
227
     *
228
     * @throws \InvalidArgumentException When route attributes are missing
229
     * @throws NotFoundHttpException     When object not found
230
     * @return void
231
     */
232
    public function apply(Request $request, ParamConverter $configuration)
233
    {
234
        // we could use the request here if needed. $this->setRequest($request);
235
        $manager = $this;
236
237
        // Map found Service to the route's parameter
238
        $request->attributes->set($configuration->getName(), $manager);
239
    }
240
}
241