Completed
Pull Request — develop (#579)
by Narcotic
41:51 queued 21:51
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\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
125
     */
126
    public function getServices()
127
    {
128
        $services = $this->cacheProvider->fetch(self::CACHE_KEY_SERVICES_URLS);
129
        if (is_array($services)) {
130
            return $services;
131
        }
132
        $services = [];
133
        $r = $this->router;
134
        foreach ($this->services as $name => $service) {
135
            $services[] = [
136
                '$ref' => $r->generate('graviton_analytics_service', ['service' => $service->route], false),
137
                'profile' => $r->generate('graviton_analytics_service_schema', ['service' => $service->route], true)
138
            ];
139
        }
140
        $this->cacheProvider->save(self::CACHE_KEY_SERVICES_URLS, $services, self::CACHE_KEY_SERVICES_URLS_TIME);
141
        return $services;
142
    }
143
144
    /**
145
     * Get service definition
146
     *
147
     * @param string $name Route name for service
148
     * @throws NotFoundHttpException
149
     * @return AnalyticModel
150
     */
151
    private function getServiceSchemaByRoute($name)
152
    {
153
        // Locate the schema definition
154
        if (!array_key_exists($name, $this->services)) {
155
            throw new NotFoundHttpException(
156
                sprintf('Service Analytics for %s was not found', $name)
157
            );
158
        }
159
        $mapper = new JsonMapper();
160
        /** @var AnalyticModel $schema */
161
        $schema = $mapper->map($this->services[$name], new AnalyticModel());
162
        return $schema;
163
    }
164
165
    /**
166
     * Will map and find data for defined route
167
     *
168
     * @return array
169
     */
170
    public function getData()
171
    {
172
        $serviceRoute = $this->request->get('service');
173
        // Locate the schema definition
174
        $schema = $this->getServiceSchemaByRoute($serviceRoute);
175
        $cacheTime = $schema->getCacheTime();
176
177
        //Cached data if configured
178
        if ($cacheTime &&
179
            $cache = $this->cacheProvider->fetch(self::CACHE_KEY_SERVICES_PREFIX.$schema->getRoute())
180
        ) {
181
            return $cache;
182
        }
183
184
        $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 190 which is incompatible with the return type documented by Graviton\AnalyticsBundle...rviceConverter::getData of type array.
Loading history...
185
186
        if ($cacheTime) {
187
            $this->cacheProvider->save(self::CACHE_KEY_SERVICES_PREFIX.$schema->getRoute(), $data, $cacheTime);
188
        }
189
190
        return $data;
191
    }
192
193
    /**
194
     * Locate and display service definition schema
195
     *
196
     * @return mixed
197
     */
198
    public function getSchema()
199
    {
200
        $serviceRoute = $this->request->get('service');
201
202
        // Locate the schema definition
203
        $schema =  $this->getServiceSchemaByRoute($serviceRoute);
204
205
        return $schema->getSchema();
206
    }
207
208
    /**
209
     * Which service can load this Converter
210
     *
211
     * @param ParamConverter $configuration Configuration data
212
     * @return bool
213
     */
214
    public function supports(ParamConverter $configuration)
215
    {
216
        return true;
217
    }
218
219
    /**
220
     * {@inheritdoc}
221
     *
222
     * Applies converting
223
     *
224
     * @param Request        $request       SF request bag
225
     * @param ParamConverter $configuration Config data
226
     *
227
     * @throws \InvalidArgumentException When route attributes are missing
228
     * @throws NotFoundHttpException     When object not found
229
     * @return void
230
     */
231
    public function apply(Request $request, ParamConverter $configuration)
232
    {
233
        // we could use the request here if needed. $this->setRequest($request);
234
        $manager = $this;
235
236
        // Map found Service to the route's parameter
237
        $request->attributes->set($configuration->getName(), $manager);
238
    }
239
}
240