DiscoveryProvider::supports()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 2
crap 1
1
<?php
2
3
namespace Bangpound\oEmbed\Provider;
4
5
use Bangpound\oEmbed\Exception\UnknownFormatException;
6
use GuzzleHttp\ClientInterface;
7
use GuzzleHttp\Psr7;
8
use Negotiation\FormatNegotiatorInterface;
9
use Psr\Http\Message\ResponseInterface;
10
use Symfony\Component\DomCrawler\Crawler;
11
12
class DiscoveryProvider implements ProviderInterface
13
{
14
    const LINK_ANY_XPATH = '//head/link[@rel = \'alternate\' and (@type = \'application/json+oembed\' or @type = \'text/xml+oembed\')]';
15
    const LINK_JSON_XPATH = '//head/link[@rel = \'alternate\' and @type = \'application/json+oembed\']';
16
    const LINK_XML_XPATH = '//head/link[@rel = \'alternate\' and @type = \'text/xml+oembed\']';
17
18
    /**
19
     * @var ClientInterface
20
     */
21
    private $client;
22
23
    /**
24
     * @var FormatNegotiatorInterface
25
     */
26
    private $negotiator;
27
28
    /**
29
     * @param ClientInterface           $client
30
     * @param FormatNegotiatorInterface $negotiator
31
     */
32 68
    public function __construct(ClientInterface $client, FormatNegotiatorInterface $negotiator)
33
    {
34 68
        $this->client = $client;
35 68
        $this->negotiator = $negotiator;
36 68
    }
37
38
    /**
39
     * Returns whether this class supports the given resource.
40
     *
41
     * @param string $url    A url
42
     * @param array  $params The resource type or null if unknown
43
     *
44
     * @return bool True if this class supports the given url, false otherwise
45
     */
46 60
    public function supports($url, array $params = array())
47
    {
48 60
        $links = $this->discoverLinks($url, $params);
49
50 58
        return !empty($links);
51
    }
52
53
    /**
54
     * @param $url
55
     * @param array $params
56
     *
57
     * @return Psr7\Request
58
     */
59 50
    public function request($url, array $params = array())
60
    {
61 50
        $links = self::discoverLinks($url, $params);
62
63 50
        $uri = new Psr7\Uri($links[0][0]);
64
65 50
        return new Psr7\Request('get', $uri);
66
    }
67
68
    /**
69
     * @param string $url
70
     * @param array  $params
71
     *
72
     * @return array
73
     */
74 68
    private function discoverLinks($url, array $params = array())
75
    {
76 68
        $request = new Psr7\Request('get', $url);
77 68
        $response = $this->client->send($request);
78
79 68
        $xpath = isset($params['format']) ? self::xpathForFormat($params['format']) : self::LINK_ANY_XPATH;
80 66
        $links = self::responseBodyOEmbedLinks($response, $xpath);
81
82 66
        if (!empty($links) && isset($params['format'])) {
83 8
            $links = array_filter($links, function ($link) use ($params) {
84 8
                return $this->negotiator->getFormat($link[1]) !== null && $params['format'] === $this->negotiator->getFormat($link[1]);
85 8
            });
86 8
        }
87
88 66
        return $links;
89
    }
90
91
    /**
92
     * @param $format
93
     *
94
     * @return string
95
     */
96 14
    private static function xpathForFormat($format)
97
    {
98 14
        if ($format === 'json') {
99 6
            return self::LINK_JSON_XPATH;
100
        }
101
102 8
        if ($format === 'xml') {
103 6
            return self::LINK_XML_XPATH;
104
        }
105
106 2
        throw new UnknownFormatException();
107
    }
108
109
    /**
110
     * @param ResponseInterface $response
111
     * @param string            $xpath
112
     *
113
     * @return array
114
     */
115 66
    private static function responseBodyOEmbedLinks(ResponseInterface $response, $xpath)
116
    {
117 66
        $contents = $response->getBody()->getContents();
118 66
        $crawler = new Crawler($contents);
119
120 66
        return $crawler->filterXPath($xpath)->extract(array('href', 'type'));
121
    }
122
}
123