Completed
Pull Request — develop (#579)
by Narcotic
17:25 queued 12:30
created

ServiceConverter::init()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 38
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 38
ccs 0
cts 33
cp 0
rs 8.439
cc 6
eloc 25
nc 9
nop 0
crap 42
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
79
        if (is_array($this->services)) {
80
            return;
81
        }
82
83
        $this->services = [];
84
        if (strpos($this->directory, 'vendor/graviton/graviton')) {
85
            $this->directory = str_replace('vendor/graviton/graviton/', '', $this->directory);
86
        }
87
        if (!is_dir($this->directory)) {
88
            return;
89
        }
90
91
        $finder = new Finder();
92
        $finder
93
            ->files()
94
            ->in($this->directory)
95
            ->path('/\/analytics\//i')
96
            ->name('*.json')
97
            ->notName('_*')
98
            ->sortByName();
99
100
        foreach ($finder as $file) {
101
            $key = $file->getFilename();
102
            $data = json_decode($file->getContents());
103
            if (json_last_error()) {
104
                throw new InvalidConfigurationException(
105
                    sprintf('Analytics file: %s could not be loaded due to error: ', $key, json_last_error_msg())
106
                );
107
            }
108
            $this->services[$data->route] = $data;
109
        }
110
111
        $this->cacheProvider->save(self::CACHE_KEY_SERVICES, $this->services, self::CACHE_KEY_SERVICES_TIME);
112
    }
113
114
    /**
115
     * Return array of available services
116
     *
117
     * @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...
118
     */
119
    public function getServices()
120
    {
121
        $services = $this->cacheProvider->fetch(self::CACHE_KEY_SERVICES_URLS);
122
        if (is_array($services)) {
123
            return ['services' => $services];
124
        }
125
        $services = [];
126
        $r = $this->router;
127
        $b = $r->getContext()->getScheme().'://'.$r->getContext()->getHost().':'.$r->getContext()->getHttpPort();
128
        foreach ($this->services as $name => $service) {
129
            $services[] = [
130
                '$ref' => $b.$r->generate('graviton_analytics_service', ['service' => $service->route], false),
131
                'profile' => $b.$r->generate('graviton_analytics_service_schema', ['service' => $service->route], true)
132
            ];
133
        }
134
        $this->cacheProvider->save(self::CACHE_KEY_SERVICES_URLS, $services, self::CACHE_KEY_SERVICES_URLS_TIME);
135
        return ['services' => $services];
136
    }
137
138
    /**
139
     * Get service definition
140
     *
141
     * @param string $name Route name for service
142
     * @throws NotFoundHttpException
143
     * @return AnalyticModel
144
     */
145
    private function getServiceSchemaByRoute($name)
146
    {
147
        // Locate the schema definition
148
        if (!array_key_exists($name, $this->services)) {
149
            throw new NotFoundHttpException(
150
                sprintf('Service Analytics for %s was not found', $name)
151
            );
152
        }
153
        $mapper = new JsonMapper();
154
        /** @var AnalyticModel $schema */
155
        $schema = $mapper->map($this->services[$name], new AnalyticModel());
156
        return $schema;
157
    }
158
159
    /**
160
     * Will map and find data for defined route
161
     *
162
     * @param string $serviceRoute Route name for service
163
     * @return array
164
     */
165
    public function getData($serviceRoute)
166
    {
167
        // Locate the schema definition
168
        $schema = $this->getServiceSchemaByRoute($serviceRoute);
169
        $cacheTime = $schema->getCacheTime();
170
171
        //Cached data if configured
172
        if ($cacheTime &&
173
            $cache = $this->cacheProvider->fetch(self::CACHE_KEY_SERVICES_PREFIX.$schema->getRoute())
174
        ) {
175
            return $cache;
176
        }
177
178
        $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 184 which is incompatible with the return type documented by Graviton\AnalyticsBundle...rviceConverter::getData of type array.
Loading history...
179
180
        if ($cacheTime) {
181
            $this->cacheProvider->save(self::CACHE_KEY_SERVICES_PREFIX.$schema->getRoute(), $data, $cacheTime);
182
        }
183
184
        return $data;
185
    }
186
187
    /**
188
     * Schema definition
189
     *
190
     * @param string $serviceRoute Route name for service
191
     * @return mixed
192
     */
193
    public function getSchema($serviceRoute)
194
    {
195
        // Locate the schema definition
196
        $schema =  $this->getServiceSchemaByRoute($serviceRoute);
197
198
        return $schema->getSchema();
199
    }
200
201
    /**
202
     * Which service can load this Converter
203
     *
204
     * @param ParamConverter $configuration Configuration data
205
     * @return bool
206
     */
207
    public function supports(ParamConverter $configuration)
208
    {
209
        return true;
210
    }
211
212
    /**
213
     * {@inheritdoc}
214
     *
215
     * Applies converting
216
     *
217
     * @param Request        $request       SF request bag
218
     * @param ParamConverter $configuration Config data
219
     *
220
     * @throws \InvalidArgumentException When route attributes are missing
221
     * @throws NotFoundHttpException     When object not found
222
     * @return void
223
     */
224
    public function apply(Request $request, ParamConverter $configuration)
225
    {
226
        // we could use the request here if needed. $this->setRequest($request);
227
        $manager = $this;
228
229
        // Map found Service to the route's parameter
230
        $request->attributes->set($configuration->getName(), $manager);
231
    }
232
}
233