Completed
Push — master ( e48220...15f13c )
by
unknown
07:36
created

YouTubeProvider::supportsDownload()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
3
namespace MediaMonks\SonataMediaBundle\Provider;
4
5
use MediaMonks\SonataMediaBundle\Entity\Media;
6
use MediaMonks\SonataMediaBundle\Model\MediaInterface;
7
use Sonata\AdminBundle\Form\FormMapper;
8
use Symfony\Component\Form\Extension\Core\Type\TextType;
9
use Symfony\Component\HttpFoundation\Response;
10
use Symfony\Component\Validator\Constraints as Constraint;
11
12
class YouTubeProvider extends AbstractProvider implements ProviderInterface
13
{
14
    const URL_OEMBED = 'http://www.youtube.com/oembed?url=http://www.youtube.com/watch?v=%s&format=json';
15
    const URL_IMAGE_MAX_RES = 'https://i.ytimg.com/vi/%s/maxresdefault.jpg';
16
    const URL_IMAGE_HQ = 'https://i.ytimg.com/vi/%s/hqdefault.jpg';
17
18
    /**
19
     * @param FormMapper $formMapper
20
     */
21
    public function buildProviderCreateForm(FormMapper $formMapper)
22
    {
23
        $formMapper->add('providerReference', TextType::class, ['label' => 'YouTube ID']);
24
    }
25
26
    /**
27
     * @param FormMapper $formMapper
28
     */
29
    public function buildProviderEditForm(FormMapper $formMapper)
30
    {
31
        $formMapper->add('providerReference', TextType::class, ['label' => 'YouTube ID']);
32
    }
33
34
    /**
35
     * @param Media $media
36
     * @throws \Exception
37
     */
38
    public function update(Media $media)
39
    {
40
        $currentYoutubeId = $media->getProviderReference();
41
        $media->setProviderReference($this->parseYouTubeId($media->getProviderReference()));
42
43
        if ($currentYoutubeId !== $media->getProviderReference()) {
44
            $data = $this->getDataByYouTubeId($media->getProviderReference());
45
46
            if (empty($media->getTitle())) {
47
                $media->setTitle($data['title']);
48
            }
49
            if (empty($media->getAuthorName())) {
50
                $media->setAuthorName($data['author_name']);
51
            }
52
53
            if (empty($media->getImage())) {
54
                $this->refreshThumbnail($media);
55
            }
56
        }
57
58
        parent::update($media);
59
    }
60
61
    /**
62
     * @param Media $media
63
     */
64
    public function refreshThumbnail(Media $media)
65
    {
66
        $filename = sprintf('%s_%d.%s', sha1($media->getProviderReference()), time(), 'jpg');
67
        $thumbnailUrl = $this->getThumbnailUrlByYouTubeId($media->getProviderReference());
68
        $this->getFilesystem()->write(
69
            $filename,
70
            file_get_contents($thumbnailUrl)
71
        );
72
        $media->setImage($filename);
73
    }
74
75
    /**
76
     * @param string $id
77
     * @return string
78
     */
79
    public function getThumbnailUrlByYouTubeId($id)
80
    {
81
        // try to get max res image (only available for 720P videos)
82
        $urlMaxRes = sprintf(self::URL_IMAGE_MAX_RES, $id);
83
        stream_context_set_default(['http' => ['method' => 'HEAD']]);
84
        $headers = get_headers($urlMaxRes);
85
        stream_context_set_default(['http' => ['method' => 'GET']]);
86
        if ((int)substr($headers[0], 9, 3) === Response::HTTP_OK) {
87
            return $urlMaxRes;
88
        }
89
90
        return sprintf(self::URL_IMAGE_HQ, $id); // this one always exists
91
    }
92
93
    /**
94
     * @param $id
95
     * @return mixed
96
     * @throws \Exception
97
     */
98
    protected function getDataByYouTubeId($id)
99
    {
100
        set_error_handler(
101
            function () {
102
            }
103
        );
104
        $data = json_decode(file_get_contents(sprintf(self::URL_OEMBED, $id)), true);
105
        restore_error_handler();
106
107
        if (empty($data['title'])) {
108
            throw new \Exception(sprintf('Could not get data from YouTube for id "%s", is the id correct?', $id));
109
        }
110
111
        return $data;
112
    }
113
114
    /**
115
     * @param $value
116
     * @return string
117
     * @throws \Exception
118
     */
119
    protected function parseYouTubeId($value)
120
    {
121
        if (strpos($value, 'youtube.com')) {
122
            $url = parse_url($value);
123
            if (empty($url['query'])) {
124
                throw new \Exception('The supplied URL does not look like a Youtube URL');
125
            }
126
            parse_str($url['query'], $params);
127
            if (empty($params['v'])) {
128
                throw new \Exception('The supplied URL does not look like a Youtube URL');
129
            }
130
131
            return $params['v'];
132
        }
133
134
        if (strpos($value, 'youtu.be')) {
135
            $url = parse_url($value);
136
            $id = substr($url['path'], 1);
137
138
            return $id;
139
        }
140
141
        return $value;
142
    }
143
144
    /**
145
     * @param MediaInterface $media
146
     * @param array $options
147
     * @return array
148
     */
149
    public function toArray(MediaInterface $media, array $options = [])
150
    {
151
        return parent::toArray($media, $options) + [
152
                'id'   => $media->getProviderReference(),
153
            ];
154
    }
155
156
    /**
157
     * @return string
158
     */
159
    public function getIcon()
160
    {
161
        return 'youtube-play';
162
    }
163
164
    /**
165
     * @return string
166
     */
167
    public function getTitle()
168
    {
169
        return 'YouTube Video';
170
    }
171
172
    public function getType()
173
    {
174
        return 'youtube';
175
    }
176
177
    /**
178
     * @return string
179
     */
180
    public function getMediaTemplate()
181
    {
182
        return 'MediaMonksSonataMediaBundle:Provider:youtube_media.html.twig';
183
    }
184
185
    /**
186
     * @return bool
187
     */
188
    public function supportsDownload()
189
    {
190
        return false;
191
    }
192
193
    /**
194
     * @return bool
195
     */
196
    public function supportsEmbed()
197
    {
198
        return true;
199
    }
200
201
    /**
202
     * @return bool
203
     */
204
    public function supportsImage()
205
    {
206
        return true;
207
    }
208
}
209