Completed
Push — feature/EVO-10415-Analytics-wi... ( e2b3ad )
by
unknown
12:30
created

ServiceConverter::getSchema()   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);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->cacheProvider->fe...lf::CACHE_KEY_SERVICES) of type * is incompatible with the declared type array of property $services.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
77
        if (is_array($this->services)) {
78
            return;
79
        }
80
        if (strpos($this->directory, 'vendor/graviton/graviton')) {
81
            $this->directory = str_replace('vendor/graviton/graviton/', '', $this->directory);
82
        }
83
        $finder = new Finder();
84
        $finder->files()->in($this->directory)
85
            ->name('*.json')
86
            ->notName('_*');
87
        foreach ($finder as $file) {
88
            $key = $file->getFilename();
89
            $data = json_decode($file->getContents());
90
            if (json_last_error()) {
91
                throw new InvalidConfigurationException(
92
                    sprintf('Analytics file: %s could not be loaded due to error: ', $key, json_last_error_msg())
93
                );
94
            }
95
            $this->services[$data->route] = $data;
96
        }
97
        $this->cacheProvider->save(self::CACHE_KEY_SERVICES, $this->services, self::CACHE_KEY_SERVICES_TIME);
98
    }
99
100
    /**
101
     * Return array of available services
102
     *
103
     * @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...
104
     */
105
    public function getServices()
106
    {
107
        $services = $this->cacheProvider->fetch(self::CACHE_KEY_SERVICES_URLS);
108
        if (is_array($services)) {
109
            return ['services' => $services];
110
        }
111
        $services = [];
112
        $r = $this->router;
113
        $b = $r->getContext()->getScheme().'://'.$r->getContext()->getHost().':'.$r->getContext()->getHttpPort();
114
        foreach ($this->services as $name => $service) {
115
            $services[] = [
116
                '$ref' => $b.$r->generate('graviton_analytics_service', ['service' => $service->route], false),
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
117
                'profile' => $b.$r->generate('graviton_analytics_service_schema', ['service' => $service->route], true)
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
118
            ];
119
        }
120
        $this->cacheProvider->save(self::CACHE_KEY_SERVICES_URLS, $services, self::CACHE_KEY_SERVICES_URLS_TIME);
121
        return ['services' => $services];
122
    }
123
124
    /**
125
     * Get service definition
126
     *
127
     * @param string $name Route name for service
128
     * @throws NotFoundHttpException
129
     * @return AnalyticModel
130
     */
131
    private function getServiceSchemaByRoute($name)
132
    {
133
        // Locate the schema definition
134
        if (!array_key_exists($name, $this->services)) {
135
            throw new NotFoundHttpException(
136
                sprintf('Service Analytics for %s was not found', $name)
137
            );
138
        }
139
        $mapper = new JsonMapper();
140
        /** @var AnalyticModel $schema */
141
        $schema = $mapper->map($this->services[$name], new AnalyticModel());
142
        return $schema;
143
    }
144
145
    /**
146
     * Will map and find data for defined route
147
     *
148
     * @param string $serviceRoute Route name for service
149
     * @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...
150
     */
151
    public function getData($serviceRoute)
152
    {
153
        // Locate the schema definition
154
        $schema = $this->getServiceSchemaByRoute($serviceRoute);
155
156
        return $this->analyticsManager->getData($schema);
157
    }
158
159
    /**
160
     * Schema definition
161
     *
162
     * @param string $serviceRoute Route name for service
163
     * @return mixed
164
     */
165
    public function getSchema($serviceRoute)
166
    {
167
        // Locate the schema definition
168
        $schema =  $this->getServiceSchemaByRoute($serviceRoute);
169
170
        return $schema->getSchema();
171
    }
172
173
    /**
174
     * Which service can load this Converter
175
     *
176
     * @param ParamConverter $configuration Configuration data
177
     * @return bool
178
     */
179
    public function supports(ParamConverter $configuration)
180
    {
181
        return true;
182
    }
183
184
    /**
185
     * {@inheritdoc}
186
     *
187
     * Applies converting
188
     *
189
     * @param Request        $request       SF request bag
190
     * @param ParamConverter $configuration Config data
191
     *
192
     * @throws \InvalidArgumentException When route attributes are missing
193
     * @throws NotFoundHttpException     When object not found
194
     * @return void
195
     */
196
    public function apply(Request $request, ParamConverter $configuration)
197
    {
198
        // we could use the request here if needed. $this->setRequest($request);
199
        $manager = $this;
200
201
        // Map found Service to the route's parameter
202
        $request->attributes->set($configuration->getName(), $manager);
203
    }
204
}
205