Completed
Push — master ( 09a899...000445 )
by
unknown
12:05 queued 03:39
created

YouTubeProvider::getAdminMediaTemplate()   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 3
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\Model\MediaInterface;
6
use Sonata\AdminBundle\Form\FormMapper;
7
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
8
use Symfony\Component\Form\Extension\Core\Type\FileType;
9
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
10
use Symfony\Component\Form\Extension\Core\Type\TextType;
11
use Symfony\Component\HttpFoundation\Response;
12
use Symfony\Component\Validator\Constraints as Constraint;
13
14
class YouTubeProvider extends ImageProvider implements ProviderInterface
15
{
16
    const URL_OEMBED = 'http://www.youtube.com/oembed?url=http://www.youtube.com/watch?v=%s&format=json';
17
    const URL_IMAGE_MAX_RES = 'https://i.ytimg.com/vi/%s/maxresdefault.jpg';
18
    const URL_IMAGE_HQ = 'https://i.ytimg.com/vi/%s/hqdefault.jpg';
19
20
    /**
21
     * @param FormMapper $formMapper
22
     */
23
    public function buildEditForm(FormMapper $formMapper)
24
    {
25
        $formMapper
26
            ->with('General')
27
            ->add('providerName', HiddenType::class)
28
            ->add('providerReference', TextType::class, ['label' => 'YouTube ID'])
29
            ->add(
30
                'binaryContent',
31
                FileType::class,
32
                [
33
                    'required'    => false,
34
                    'constraints' => [
35
                        new Constraint\File(),
36
                    ],
37
                    'label'       => 'Replacement Image',
38
                ]
39
            )
40
            ->add('title')
41
            ->add('description')
42
            ->add('authorName')
43
            ->add('copyright')
44
            ->add('tags')
45
            ->add(
46
                'pointOfInterest',
47
                ChoiceType::class,
48
                [
49
                    'required' => false,
50
                    'label'    => 'Point Of Interest',
51
                    'choices'  => $this->getPointOfInterestChoices(),
52
                ]
53
            )
54
            ->end()
55
            ->end();
56
    }
57
58
    /**
59
     * @param FormMapper $formMapper
60
     */
61
    public function buildCreateForm(FormMapper $formMapper)
62
    {
63
        $formMapper
64
            ->add('providerName', 'hidden')
65
            ->add('providerReference', 'text', ['label' => 'YouTube ID']);
66
    }
67
68
    /**
69
     * @param MediaInterface $media
70
     * @throws \Exception
71
     */
72
    public function update(MediaInterface $media)
73
    {
74
        $currentYoutubeId = $media->getProviderReference();
75
        $media->setProviderReference($this->parseYouTubeId($media->getProviderReference()));
76
77
        if ($currentYoutubeId !== $media->getProviderReference()) {
78
            $data = $this->getDataByYouTubeId($media->getProviderReference());
79
80
            if (empty($media->getTitle())) {
81
                $media->setTitle($data['title']);
82
            }
83
            if (empty($media->getAuthorName())) {
84
                $media->setAuthorName($data['author_name']);
85
            }
86
87
            if (empty($media->getImage())) {
88
                $this->refreshThumbnail($media);
89
            }
90
        }
91
92
        if (!is_null($media->getBinaryContent())) {
93
            $this->handleFileUpload($media);
0 ignored issues
show
Compatibility introduced by
$media of type object<MediaMonks\Sonata...e\Model\MediaInterface> is not a sub-type of object<MediaMonks\SonataMediaBundle\Entity\Media>. It seems like you assume a concrete implementation of the interface MediaMonks\SonataMediaBundle\Model\MediaInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
94
        }
95
    }
96
97
    /**
98
     * @param MediaInterface $media
99
     */
100
    public function refreshThumbnail(MediaInterface $media)
101
    {
102
        $filename = sprintf('%s_%d.%s', sha1($media->getProviderReference()), time(), 'jpg');
103
        $thumbnailUrl = $this->getThumbnailUrlByYouTubeId($media->getProviderReference());
104
        $this->getFilesystem()->write(
105
            $filename,
106
            file_get_contents($thumbnailUrl)
107
        );
108
        $media->setImage($filename);
109
    }
110
111
    /**
112
     * @param string $id
113
     * @return string
114
     */
115
    public function getThumbnailUrlByYouTubeId($id)
116
    {
117
        // try to get max res image (only available for 720P videos)
118
        $urlMaxRes = sprintf(self::URL_IMAGE_MAX_RES, $id);
119
        stream_context_set_default(['http' => ['method' => 'HEAD']]);
120
        $headers = get_headers($urlMaxRes);
121
        stream_context_set_default(['http' => ['method' => 'GET']]);
122
        if ((int)substr($headers[0], 9, 3) === Response::HTTP_OK) {
123
            return $urlMaxRes;
124
        }
125
126
        return sprintf(self::URL_IMAGE_HQ, $id); // this one always exists
127
    }
128
129
    /**
130
     * @param $id
131
     * @return mixed
132
     * @throws \Exception
133
     */
134
    protected function getDataByYouTubeId($id)
135
    {
136
        $data = json_decode(
137
            @file_get_contents(
138
                sprintf(self::URL_OEMBED, $id)
139
            ),
140
            true
141
        );
142
        if (empty($data)) {
143
            throw new \Exception(sprintf('Could not get data from YouTube for id "%s", is the id correct?', $id));
144
        }
145
146
        return $data;
147
    }
148
149
    /**
150
     * @param $value
151
     * @return string
152
     * @throws \Exception
153
     */
154
    protected function parseYouTubeId($value)
155
    {
156
        if (strpos($value, 'youtube.com')) {
157
            $url = parse_url($value);
158
            if (empty($url['query'])) {
159
                throw new \Exception('The supplied URL does not look like a Youtube URL');
160
            }
161
            parse_str($url['query'], $params);
162
            if (empty($params['v'])) {
163
                throw new \Exception('The supplied URL does not look like a Youtube URL');
164
            }
165
166
            return $params['v'];
167
        }
168
169
        if (strpos($value, 'youtu.be')) {
170
            $url = parse_url($value);
171
            $vid = substr($url['path'], 1);
172
173
            return $vid;
174
        }
175
176
        return $value;
177
    }
178
179
    /**
180
     * @param MediaInterface $media
181
     * @param array $options
182
     * @return array
183
     */
184
    public function toArray(MediaInterface $media, array $options = [])
185
    {
186
        return parent::toArray($media, $options) + [
187
                'type' => $this->getTypeName(),
188
                'id'   => $media->getProviderReference(),
189
            ];
190
    }
191
192
    /**
193
     * @return string
194
     */
195
    public function getIcon()
196
    {
197
        return 'youtube-play';
198
    }
199
200
    /**
201
     * @return string
202
     */
203
    public function getName()
204
    {
205
        return 'YouTube Video';
206
    }
207
208
    public function getTypeName()
209
    {
210
        return 'youtube';
211
    }
212
213
    /**
214
     * @return string
215
     */
216
    public function getMediaTemplate()
217
    {
218
        return 'MediaMonksSonataMediaBundle:Provider:youtube_media.html.twig';
219
    }
220
}
221