Completed
Push — master ( 3b23f0...80edcc )
by
unknown
13:12
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
11
class YouTubeProvider extends AbstractProvider implements ProviderInterface
12
{
13
    const URL_OEMBED = 'http://www.youtube.com/oembed?url=http://www.youtube.com/watch?v=%s&format=json';
14
    const URL_IMAGE_MAX_RES = 'https://i.ytimg.com/vi/%s/maxresdefault.jpg';
15
    const URL_IMAGE_HQ = 'https://i.ytimg.com/vi/%s/hqdefault.jpg';
16
17
    /**
18
     * @param FormMapper $formMapper
19
     */
20
    public function buildProviderCreateForm(FormMapper $formMapper)
21
    {
22
        $formMapper->add('providerReference', TextType::class, ['label' => 'YouTube ID']);
23
    }
24
25
    /**
26
     * @param FormMapper $formMapper
27
     */
28
    public function buildProviderEditForm(FormMapper $formMapper)
29
    {
30
        $formMapper->add('providerReference', TextType::class, ['label' => 'YouTube ID']);
31
    }
32
33
    /**
34
     * @param Media $media
35
     * @throws \Exception
36
     */
37
    public function update(Media $media)
38
    {
39
        $currentYoutubeId = $media->getProviderReference();
40
        $media->setProviderReference($this->parseYouTubeId($media->getProviderReference()));
41
42
        if ($currentYoutubeId !== $media->getProviderReference()) {
43
            $data = $this->getDataByYouTubeId($media->getProviderReference());
44
45
            if (empty($media->getTitle())) {
46
                $media->setTitle($data['title']);
47
            }
48
            if (empty($media->getAuthorName())) {
49
                $media->setAuthorName($data['author_name']);
50
            }
51
52
            if (empty($media->getImage())) {
53
                $this->refreshThumbnail($media);
54
            }
55
        }
56
57
        parent::update($media);
58
    }
59
60
    /**
61
     * @param Media $media
62
     */
63
    public function refreshThumbnail(Media $media)
64
    {
65
        $filename = sprintf('%s_%d.%s', sha1($media->getProviderReference()), time(), 'jpg');
66
        $thumbnailUrl = $this->getThumbnailUrlByYouTubeId($media->getProviderReference());
67
        $this->getFilesystem()->write(
68
            $filename,
69
            file_get_contents($thumbnailUrl)
70
        );
71
        $media->setImage($filename);
72
    }
73
74
    /**
75
     * @param string $id
76
     * @return string
77
     */
78
    public function getThumbnailUrlByYouTubeId($id)
79
    {
80
        // try to get max res image (only available for 720P videos)
81
        $urlMaxRes = sprintf(self::URL_IMAGE_MAX_RES, $id);
82
        stream_context_set_default(['http' => ['method' => 'HEAD']]);
83
        $headers = get_headers($urlMaxRes);
84
        stream_context_set_default(['http' => ['method' => 'GET']]);
85
        if ((int)substr($headers[0], 9, 3) === Response::HTTP_OK) {
86
            return $urlMaxRes;
87
        }
88
89
        return sprintf(self::URL_IMAGE_HQ, $id); // this one always exists
90
    }
91
92
    /**
93
     * @param $id
94
     * @return mixed
95
     * @throws \Exception
96
     */
97 View Code Duplication
    protected function getDataByYouTubeId($id)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
98
    {
99
        $this->disableErrorHandler();
100
        $data = json_decode(file_get_contents(sprintf(self::URL_OEMBED, $id)), true);
101
        $this->restoreErrorHandler();
102
103
        if (empty($data['title'])) {
104
            throw new \Exception(sprintf('Could not get data from YouTube for id "%s", is the id correct?', $id));
105
        }
106
107
        return $data;
108
    }
109
110
    /**
111
     * @param $value
112
     * @return string
113
     * @throws \Exception
114
     */
115
    protected function parseYouTubeId($value)
116
    {
117
        if (strpos($value, 'youtube.com')) {
118
            $url = parse_url($value);
119
            if (empty($url['query'])) {
120
                throw new \Exception('The supplied URL does not look like a Youtube URL');
121
            }
122
            parse_str($url['query'], $params);
123
            if (empty($params['v'])) {
124
                throw new \Exception('The supplied URL does not look like a Youtube URL');
125
            }
126
127
            return $params['v'];
128
        }
129
130
        if (strpos($value, 'youtu.be')) {
131
            $url = parse_url($value);
132
            $id = substr($url['path'], 1);
133
134
            return $id;
135
        }
136
137
        return $value;
138
    }
139
140
    /**
141
     * @param MediaInterface $media
142
     * @param array $options
143
     * @return array
144
     */
145
    public function toArray(MediaInterface $media, array $options = [])
146
    {
147
        return parent::toArray($media, $options) + [
148
                'id'   => $media->getProviderReference(),
149
            ];
150
    }
151
152
    /**
153
     * @return string
154
     */
155
    public function getIcon()
156
    {
157
        return 'youtube-play';
158
    }
159
160
    /**
161
     * @return string
162
     */
163
    public function getTitle()
164
    {
165
        return 'YouTube Video';
166
    }
167
168
    public function getType()
169
    {
170
        return 'youtube';
171
    }
172
173
    /**
174
     * @return string
175
     */
176
    public function getEmbedTemplate()
177
    {
178
        return 'MediaMonksSonataMediaBundle:Provider:youtube_embed.html.twig';
179
    }
180
181
    /**
182
     * @return bool
183
     */
184
    public function supportsDownload()
185
    {
186
        return false;
187
    }
188
189
    /**
190
     * @return bool
191
     */
192
    public function supportsEmbed()
193
    {
194
        return true;
195
    }
196
197
    /**
198
     * @return bool
199
     */
200
    public function supportsImage()
201
    {
202
        return true;
203
    }
204
}
205