Completed
Push — 5.3 ( 89941d...4b705f )
by Jeroen
23:30 queued 17:43
created

VersionChecker::check()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 4.0105

Importance

Changes 0
Metric Value
dl 0
loc 38
ccs 21
cts 23
cp 0.913
rs 9.312
c 0
b 0
f 0
cc 4
nc 8
nop 0
crap 4.0105
1
<?php
2
3
namespace Kunstmaan\AdminBundle\Helper\VersionCheck;
4
5
use Doctrine\Common\Cache\Cache;
6
use Exception;
7
use GuzzleHttp\Client;
8
use Kunstmaan\AdminBundle\Helper\VersionCheck\Exception\ParseException;
9
use Symfony\Component\DependencyInjection\ContainerInterface;
10
11
/**
12
 * Version checker
13
 */
14
class VersionChecker
15
{
16
    /**
17
     * @var ContainerInterface
18
     */
19
    private $container;
20
21
    /**
22
     * @var Cache
23
     */
24
    private $cache;
25
26
    /**
27
     * @var string
28
     */
29
    private $webserviceUrl;
30
31
    /**
32
     * @var int
33
     */
34
    private $cacheTimeframe;
35
36
    /**
37
     * @var bool
38
     */
39
    private $enabled;
40
41
    /**
42
     * @var Client
43
     */
44
    private $client;
45
46
    /**
47
     * Constructor
48
     *
49
     * @param ContainerInterface $container
50
     * @param Cache              $cache
51
     */
52 7
    public function __construct(ContainerInterface $container, Cache $cache)
53
    {
54 7
        $this->container = $container;
55 7
        $this->cache = $cache;
56
57 7
        $this->webserviceUrl = $this->container->getParameter('version_checker.url');
58 7
        $this->cacheTimeframe = $this->container->getParameter('version_checker.timeframe');
59 7
        $this->enabled = $this->container->getParameter('version_checker.enabled');
60 7
    }
61
62
    /**
63
     * Check that the version check is enabled.
64
     *
65
     * @return bool
66
     */
67 7
    public function isEnabled()
68
    {
69 7
        return $this->enabled;
70
    }
71
72
    /**
73
     * Check if we recently did a version check, if not do one now.
74
     *
75
     * @throws ParseException
76
     */
77 1
    public function periodicallyCheck()
78
    {
79 1
        if (!$this->isEnabled()) {
80
            return;
81
        }
82
83 1
        $data = $this->cache->fetch('version_check');
84 1
        if (!is_array($data)) {
85
            $this->check();
86
        }
87 1
    }
88
89
    /**
90
     * Get the version details via webservice.
91
     *
92
     * @return mixed a list of bundles if available
93
     *
94
     * @throws ParseException
95
     */
96 5
    public function check()
97
    {
98 5
        if (!$this->isEnabled()) {
99
            return;
100
        }
101
102 5
        $host = $this->container->get('request_stack')->getCurrentRequest()->getHttpHost();
103 5
        $console = realpath($this->container->get('kernel')->getProjectDir().'/bin/console');
104 5
        $installed = filectime($console);
105 5
        $bundles = $this->parseComposer();
106 2
        $title = $this->container->getParameter('kunstmaan_admin.website_title');
107
108 2
        $jsonData = json_encode(array(
109 2
            'host' => $host,
110 2
            'installed' => $installed,
111 2
            'bundles' => $bundles,
112 2
            'project' => $title,
113
        ));
114
115
        try {
116 2
            $client = $this->getClient();
117 2
            $response = $client->post($this->webserviceUrl, ['body' => $jsonData]);
118 1
            $contents = $response->getBody()->getContents();
119 1
            $data = json_decode($contents);
120
121 1
            if (null === $data) {
122
                return false;
123
            }
124
125
            // Save the result in the cache to make sure we don't do the check too often
126 1
            $this->cache->save('version_check', $data, $this->cacheTimeframe);
127
128 1
            return $data;
129 1
        } catch (Exception $e) {
130
            // We did not receive valid json
131 1
            return false;
132
        }
133
    }
134
135
    /**
136
     * @return Client
137
     */
138 1
    public function getClient()
139
    {
140 1
        if (!$this->client) {
141 1
            $this->client = new Client(array('connect_timeout' => 3, 'timeout' => 1));
142
        }
143
144 1
        return $this->client;
145
    }
146
147
    /**
148
     * @param Client $client
149
     */
150
    public function setClient($client)
151
    {
152
        $this->client = $client;
153
    }
154
155
    /**
156
     * Returns the absolute path to the composer.lock file.
157
     *
158
     * @return string
159
     */
160
    protected function getLockPath()
161
    {
162
        $kernel = $this->container->get('kernel');
163
        $rootPath = $kernel->getProjectDir();
164
165
        return $rootPath.'/composer.lock';
166
    }
167
168
    /**
169
     * Returns a list of composer packages.
170
     *
171
     * @return array
172
     *
173
     * @throws ParseException
174
     */
175 4
    protected function getPackages()
176
    {
177 4
        $translator = $this->container->get('translator');
178 4
        $errorMessage = $translator->trans('settings.version.error_parsing_composer');
179
180 4
        $composerPath = $this->getLockPath();
181 4
        if (!file_exists($composerPath)) {
182 1
            throw new ParseException($translator->trans('settings.version.composer_lock_not_found'));
183
        }
184
185 3
        $json = file_get_contents($composerPath);
186 3
        $result = json_decode($json, true);
187
188 3
        if (json_last_error() !== JSON_ERROR_NONE) {
189 1
            throw new ParseException($errorMessage.' (#'.json_last_error().')');
190
        }
191
192 2
        if (array_key_exists('packages', $result) && is_array($result['packages'])) {
193 1
            return $result['packages'];
194
        }
195
196
        // No package list in JSON structure
197 1
        throw new ParseException($errorMessage);
198
    }
199
200
    /**
201
     * Parse the composer.lock file to get the currently used versions of the kunstmaan bundles.
202
     *
203
     * @return array
204
     *
205
     * @throws ParseException
206
     */
207 4
    protected function parseComposer()
208
    {
209 4
        $bundles = array();
210 4
        foreach ($this->getPackages() as $package) {
211 1
            if (!strncmp($package['name'], 'kunstmaan/', strlen('kunstmaan/'))) {
212 1
                $bundles[] = array(
213 1
                    'name' => $package['name'],
214 1
                    'version' => $package['version'],
215 1
                    'reference' => $package['source']['reference'],
216
                );
217
            }
218
        }
219
220 1
        return $bundles;
221
    }
222
}
223