SafeValidator::getResponse()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2.0185

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 11
ccs 5
cts 6
cp 0.8333
rs 9.4285
cc 2
eloc 6
nc 2
nop 1
crap 2.0185
1
<?php
2
3
namespace EmanueleMinotto\SafeBrowsingBundle\Validator\Constraints;
4
5
use Doctrine\Common\Cache\ArrayCache;
6
use Doctrine\Common\Cache\Cache;
7
use GuzzleHttp\Client;
8
use GuzzleHttp\ClientInterface;
9
use GuzzleHttp\Exception\GuzzleException;
10
use Symfony\Component\Validator\Constraint;
11
use Symfony\Component\Validator\ConstraintValidator;
12
13
/**
14
 * Validator used for URL safety evaluation.
15
 *
16
 * @author Emanuele Minotto <[email protected]>
17
 */
18
class SafeValidator extends ConstraintValidator
19
{
20
    /**
21
     * Google safe browsing endpoint.
22
     *
23
     * @var string
24
     */
25
    const ENDPOINT = 'https://sb-ssl.google.com/safebrowsing/api/lookup';
26
27
    /**
28
     * HTTP client.
29
     *
30
     * @var ClientInterface
31
     */
32
    private $httpClient;
33
34
    /**
35
     * Validator cache.
36
     *
37
     * @var Cache
38
     */
39
    private $cache;
40
41
    /**
42
     * Request configurations.
43
     *
44
     * @var array
45
     */
46
    private $configs = [];
47
48
    /**
49
     * Constructor with attributes initialization.
50
     */
51 24
    public function __construct(array $configs = [])
52
    {
53 24
        $this->cache = new ArrayCache();
54 24
        $this->configs = $configs;
55 24
        $this->httpClient = new Client();
56 24
    }
57
58
    /**
59
     * Sets the HTTP client.
60
     *
61
     * @param ClientInterface $httpClient The HTTP client.
62
     */
63 24
    public function setHttpClient(ClientInterface $httpClient)
64
    {
65 24
        $this->httpClient = $httpClient;
66 24
    }
67
68
    /**
69
     * Sets the Validator cache.
70
     *
71
     * @param Cache $cache The caching implementation.
72
     */
73 3
    public function setCache(Cache $cache)
74
    {
75 3
        $this->cache = $cache;
76 3
    }
77
78
    /**
79
     * {@inheritdoc}
80
     */
81 24
    public function validate($value, Constraint $constraint)
82
    {
83 24
        if (!$value) {
84 6
            return;
85
        }
86
87 18
        $response = $this->getResponse($value);
88 18
        if (false === $response || 'ok' === $response) {
89 12
            return;
90
        }
91
92 6
        $this->context->addViolation($constraint->message, [
93 6
            '%response%' => $response,
94 6
        ]);
95 6
    }
96
97
    /**
98
     * Gets service output and cache it.
99
     *
100
     * @param string $url URL or domain.
101
     *
102
     * @return string|false
103
     */
104 18
    private function getResponse($url)
105
    {
106 18
        if ($this->cache->contains($url)) {
107
            return $this->cache->fetch($url);
108
        }
109
110 18
        $serviceOutput = $this->getHttpClientOutput($url);
111 18
        $this->cache->save($url, $serviceOutput);
112
113 18
        return $serviceOutput;
114
    }
115
116
    /**
117
     * Gets service output.
118
     *
119
     * @param string $url URL or domain.
120
     *
121
     * @return string|false
122
     */
123 18
    private function getHttpClientOutput($url)
124
    {
125
        try {
126 18
            $response = $this->httpClient->request('GET', self::ENDPOINT, [
127 18
                'query' => array_merge($this->configs, ['url' => $url]),
128 18
            ]);
129
130 15
            return trim($response->getBody()) ?: false;
131 3
        } catch (GuzzleException $exception) {
132 3
            return false;
133
        }
134
    }
135
}
136