Completed
Pull Request — develop (#579)
by
unknown
09:25
created

ServiceConverter::getData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 0
cts 5
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
crap 2
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
35
    /** @var AnalyticsManager */
36
    protected $analyticsManager;
37
38
    /** @var CacheProvider */
39
    protected $cacheProvider;
40
41
    /** @var Router */
42
    protected $router;
43
44
    /** @var string */
45
    protected $directory;
46
47
    /** @var array  */
48
    private $services = [];
49
50
    /**
51
     * ServiceConverter constructor.
52
     * @param AnalyticsManager $analyticsManager    Db Manager and query control
53
     * @param CacheProvider    $cacheProvider       Cache service
54
     * @param Router           $router              To manage routing generation
55
     * @param string           $definitionDirectory Where definitions are stored
56
     */
57
    public function __construct(
58
        AnalyticsManager $analyticsManager,
59
        CacheProvider $cacheProvider,
60
        Router $router,
61
        $definitionDirectory
62
    ) {
63
        $this->analyticsManager = $analyticsManager;
64
        $this->cacheProvider = $cacheProvider;
65
        $this->router = $router;
66
        $this->directory = $definitionDirectory;
67
        $this->init();
68
    }
69
70
    /**
71
     * Scan base root directory for analytic definitions
72
     * @return void
73
     */
74
    private function init()
75
    {
76
        $this->services = $this->cacheProvider->fetch(self::CACHE_KEY_SERVICES);
77
        if (is_array($this->services)) {
78
            return;
79
        }
80
        $this->services = [];
81
        if (strpos($this->directory, 'vendor/graviton/graviton')) {
82
            $this->directory = str_replace('vendor/graviton/graviton/', '', $this->directory);
83
        }
84
        $finder = new Finder();
85
        $finder->files()->in($this->directory)
86
            ->name('*.json')
87
            ->notName('_*');
88
        foreach ($finder as $file) {
89
            $key = $file->getFilename();
90
            $data = json_decode($file->getContents());
91
            if (json_last_error()) {
92
                throw new InvalidConfigurationException(
93
                    sprintf('Analytics file: %s could not be loaded due to error: ', $key, json_last_error_msg())
94
                );
95
            }
96
            $this->services[$data->route] = $data;
97
        }
98
        $this->cacheProvider->save(self::CACHE_KEY_SERVICES, $this->services, self::CACHE_KEY_SERVICES_TIME);
99
    }
100
101
    /**
102
     * Return array of available services
103
     *
104
     * @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...
105
     */
106
    public function getServices()
107
    {
108
        $services = $this->cacheProvider->fetch(self::CACHE_KEY_SERVICES_URLS);
109
        if (is_array($services)) {
110
            return ['services' => $services];
111
        }
112
        $services = [];
113
        $r = $this->router;
114
        $b = $r->getContext()->getScheme().'://'.$r->getContext()->getHost().':'.$r->getContext()->getHttpPort();
115
        foreach ($this->services as $name => $service) {
116
            $services[] = [
117
                '$ref' => $b.$r->generate('graviton_analytics_service', ['service' => $service->route], false),
118
                'profile' => $b.$r->generate('graviton_analytics_service_schema', ['service' => $service->route], true)
119
            ];
120
        }
121
        $this->cacheProvider->save(self::CACHE_KEY_SERVICES_URLS, $services, self::CACHE_KEY_SERVICES_URLS_TIME);
122
        return ['services' => $services];
123
    }
124
125
    /**
126
     * Get service definition
127
     *
128
     * @param string $name Route name for service
129
     * @throws NotFoundHttpException
130
     * @return AnalyticModel
131
     */
132
    private function getServiceSchemaByRoute($name)
133
    {
134
        // Locate the schema definition
135
        if (!array_key_exists($name, $this->services)) {
136
            throw new NotFoundHttpException(
137
                sprintf('Service Analytics for %s was not found', $name)
138
            );
139
        }
140
        $mapper = new JsonMapper();
141
        /** @var AnalyticModel $schema */
142
        $schema = $mapper->map($this->services[$name], new AnalyticModel());
143
        return $schema;
144
    }
145
146
    /**
147
     * Will map and find data for defined route
148
     *
149
     * @param string $serviceRoute Route name for service
150
     * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be array|object? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
151
     */
152
    public function getData($serviceRoute)
153
    {
154
        // Locate the schema definition
155
        $schema = $this->getServiceSchemaByRoute($serviceRoute);
156
157
        return $this->analyticsManager->getData($schema);
158
    }
159
160
    /**
161
     * Schema definition
162
     *
163
     * @param string $serviceRoute Route name for service
164
     * @return mixed
165
     */
166
    public function getSchema($serviceRoute)
167
    {
168
        // Locate the schema definition
169
        $schema =  $this->getServiceSchemaByRoute($serviceRoute);
170
171
        return $schema->getSchema();
172
    }
173
174
    /**
175
     * Which service can load this Converter
176
     *
177
     * @param ParamConverter $configuration Configuration data
178
     * @return bool
179
     */
180
    public function supports(ParamConverter $configuration)
181
    {
182
        return true;
183
    }
184
185
    /**
186
     * {@inheritdoc}
187
     *
188
     * Applies converting
189
     *
190
     * @param Request        $request       SF request bag
191
     * @param ParamConverter $configuration Config data
192
     *
193
     * @throws \InvalidArgumentException When route attributes are missing
194
     * @throws NotFoundHttpException     When object not found
195
     * @return void
196
     */
197
    public function apply(Request $request, ParamConverter $configuration)
198
    {
199
        // we could use the request here if needed. $this->setRequest($request);
200
        $manager = $this;
201
202
        // Map found Service to the route's parameter
203
        $request->attributes->set($configuration->getName(), $manager);
204
    }
205
}
206