PluginProbe ʕ •ᴥ•ʔ
EmbedPress – PDF Embedder, 3D PDF FlipBook, Google Reviews, YouTube Videos, Upload & Embed PDF documents / 3.6.0
EmbedPress – PDF Embedder, 3D PDF FlipBook, Google Reviews, YouTube Videos, Upload & Embed PDF documents v3.6.0
4.6.5 4.6.4 4.6.3 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 trunk 1.0.0 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 2.0.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.2.0 2.2.1 2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.4.0 2.4.1 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.1.3 3.2.0 3.2.1 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.4.0 3.4.1 3.4.2 3.4.3 3.5.0 3.5.1 3.5.2 3.5.3 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.7.0 3.7.1 3.7.2 3.7.3 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.9.0 3.9.1 3.9.10 3.9.11 3.9.12 3.9.13 3.9.14 3.9.15 3.9.16 3.9.17 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9 4.0.0 4.0.1 4.0.10 4.0.11 4.0.12 4.0.13 4.0.14 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.0.9 4.1.0 4.1.1 4.1.10 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.7 4.1.8 4.1.9 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.8 4.2.9 4.3.0 4.3.1 4.4.0 4.4.1 4.4.10 4.4.11 4.4.2 4.4.3 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 4.5.0 4.5.1
embedpress / EmbedPress / Providers / Youtube.php
embedpress / EmbedPress / Providers Last commit date
Boomplay.php 5 years ago Giphy.php 5 years ago GoogleDocs.php 5 years ago GoogleMaps.php 5 years ago OpenSea.php 3 years ago Twitch.php 5 years ago Youtube.php 3 years ago index.html 7 years ago
Youtube.php
841 lines
1 <?php
2
3 /**
4 * Youtube.php
5 *
6 * @package Embera
7 * @author Michael Pratt <yo@michael-pratt.com>
8 * @link http://www.michael-pratt.com/
9 *
10 * For the full copyright and license information, please view the LICENSE
11 * file that was distributed with this source code.
12 */
13
14 namespace EmbedPress\Providers;
15
16 use Embera\Provider\ProviderAdapter;
17 use Embera\Provider\ProviderInterface;
18 use Embera\Url;
19
20 /**
21 * youtube.com Provider
22 * @link https://youtube.com
23 * @link https://youtube-eng.googleblog.com/2009/10/oembed-support_9.html
24 */
25
26
27 class Youtube extends ProviderAdapter implements ProviderInterface {
28 /** inline {@inheritdoc} */
29 protected $shouldSendRequest = false;
30 public static $curltimeout = 30;
31 /** inline {@inheritdoc} */
32 protected $endpoint = 'https://www.youtube.com/oembed?format=json&scheme=https';
33 protected static $channel_endpoint = 'https://www.googleapis.com/youtube/v3/';
34 /** @var array Array with allowed params for the current Provider */
35 protected $allowedParams = [ 'maxwidth', 'maxheight', 'pagesize', 'thumbnail', 'gallery', 'hideprivate', 'columns', 'ispagination', 'gapbetweenvideos' ];
36
37 /** inline {@inheritdoc} */
38 protected static $hosts = [
39 'm.youtube.com', 'youtube.com', 'youtu.be',
40 ];
41
42 /** inline {@inheritdoc} */
43 protected $httpsSupport = true;
44
45 public function getAllowedParams(){
46 return $this->allowedParams;
47 }
48
49 /** inline {@inheritdoc} */
50 public function validateUrl(Url $url) {
51 return (bool) (preg_match('~\/channel\/|\/c\/|\/user\/|(?:https?:\/\/)?(?:www\.)?(?:youtube.com\/)(\w+)[^?\/]*$~i', (string) $url));
52 }
53
54 /** inline {@inheritdoc} */
55 public function normalizeUrl(Url $url) {
56 return $url;
57 }
58
59 public function isChannel($url = null) {
60 if (empty($url)) {
61 $url = $this->url;
62 }
63 $channel = $this->getChannel($url);
64 return !empty($channel['id']);
65 }
66
67 public function getChannel($url = null) {
68 if (empty($url)) {
69 $url = $this->url;
70 }
71 preg_match('~\/(channel|c|user)\/(.+)~i', (string) $url, $matches);
72 if(empty($matches[1])){
73 preg_match('~(?:https?:\/\/)?(?:www\.)?(?:youtube.com\/)(\w+)[^?\/]*$~i', (string) $url, $matches);
74 if(!empty($matches[1])){
75 return [
76 "type" => 'user',
77 "id" => $matches[1],
78 ];
79 }
80 }
81 return [
82 "type" => isset($matches[1]) ? $matches[1] : '',
83 "id" => isset($matches[2]) ? $matches[2] : '',
84 ];
85 }
86
87 /** inline {@inheritdoc} */
88 public function getEndpoint() {
89 if ($this->isChannel()) {
90 $apiEndpoint = 'https://www.googleapis.com/youtube/v3/channels';
91 return $apiEndpoint;
92 }
93 return (string) $this->endpoint;
94 }
95
96 protected static function get_api_key() {
97 $settings = (array) get_option(EMBEDPRESS_PLG_NAME . ':youtube', []);
98 return !empty($settings['api_key']) ? $settings['api_key'] : '';
99 }
100
101 protected static function get_pagesize() {
102 $settings = (array) get_option(EMBEDPRESS_PLG_NAME . ':youtube', []);
103 return !empty($settings['pagesize']) ? $settings['pagesize'] : '';
104 }
105
106 /** inline {@inheritdoc} */
107 public function getParams() {
108 $params = parent::getParams();
109 if ($this->isChannel() && self::get_api_key()) {
110 $channel = $this->getChannel();
111 $params['part'] = 'contentDetails,snippet';
112 $params['key'] = self::get_api_key();
113 if ($channel['type'] == 'c') {
114 $params['forUsername'] = $channel['id'];
115 } else {
116 $params['id'] = $channel['id'];
117 }
118 unset($params['url']);
119 }
120 return $params;
121 }
122
123 /**
124 * Builds a valid Oembed query string based on the given parameters,
125 * Since this method uses the http_build_query function, there is no
126 * need to pass urlencoded parameters, http_build_query already does
127 * this for us.
128 *
129 * @param string $endpoint The Url to the Oembed endpoint
130 * @param array $params Parameters for the query string
131 * @return string
132 */
133
134 protected function constructUrl($endpoint, array $params = array())
135 {
136 $endpoint = self::$channel_endpoint . $endpoint;
137
138 return $endpoint . ((strpos($endpoint, '?') === false) ? '?' : '&') . http_build_query(array_filter($params));
139 }
140
141 public function getStaticResponse() {
142 $results = [
143 "title" => "",
144 "type" => "video",
145 'provider_name' => $this->getProviderName(),
146 "provider_url" => "https://www.youtube.com/",
147 'html' => '',
148 ];
149 if($this->isChannel()){
150 $channel = $this->getChannelGallery();
151 $results = array_merge($results, $channel);
152 }
153 return $results;
154 }
155
156 public function getChannelPlaylist(){
157 $result = [
158 "playlistID" => '',
159 "title" => '',
160 ];
161 $channel = $this->getChannel();
162 $channel_url = $this->constructUrl('channels', $this->getParams());
163 $transient_key = 'ep_embed_youtube_channel_playlist_id_' . md5($channel_url);
164 $jsonResult = get_transient($transient_key);
165
166 if(!empty($jsonResult)){
167 return $jsonResult;
168 }
169
170 if($channel['type'] == 'user' || $channel['type'] == 'c'){
171 $this->getChannelIDbyUsername();
172 $channel_url = $this->constructUrl('channels', $this->getParams());
173 }
174
175 if (empty(self::get_api_key())) {
176 $result['error'] = true;
177 $result['html'] = self::get_api_key_error_message();
178 return $result;
179 }
180
181 $apiResult = wp_remote_get($channel_url, array('timeout' => self::$curltimeout));
182 if (is_wp_error($apiResult)) {
183 $result['error'] = true;
184 $result['html'] = self::clean_api_error_html($apiResult->get_error_message(), true);
185 set_transient($transient_key, $result, 10);
186 return $result;
187 }
188 $jsonResult = json_decode($apiResult['body']);
189
190
191 if (isset($jsonResult->error)) {
192 $result['error'] = true;
193 if (isset($jsonResult->error->message)) {
194 $result['html'] = self::clean_api_error_html($jsonResult->error->message, true);
195 }
196 else{
197 $result['html'] = self::clean_api_error_html(__('Sorry, there may be an issue with your YouTube API key.', 'embedpress'));
198 }
199 set_transient($transient_key, $result, MINUTE_IN_SECONDS);
200 return $result;
201 }
202 elseif(!empty($jsonResult->items[0]->contentDetails->relatedPlaylists->uploads)){
203 $result['playlistID'] = $jsonResult->items[0]->contentDetails->relatedPlaylists->uploads;
204 $result['title'] = isset($jsonResult->items[0]->snippet->title) ? $jsonResult->items[0]->snippet->title : '';
205 set_transient($transient_key, $result, DAY_IN_SECONDS);
206 }
207
208 return $result;
209 }
210
211 public function getChannelIDbyUsername(){
212 $url = $this->getUrl();
213 $apiResult = wp_remote_get($url, array('timeout' => self::$curltimeout));
214
215 if (!is_wp_error($apiResult)) {
216 $channel_html = $apiResult['body'];
217 preg_match("/<meta\s+itemprop=[\"']channelId[\"']\s+content=[\"'](.*?)[\"']\/?>/", $channel_html, $matches);
218 if(!empty($matches[1])){
219 $url = "https://www.youtube.com/channel/{$matches[1]}";
220 $this->url = $this->normalizeUrl(new Url($url));
221 }
222 }
223 }
224
225 /** inline {@inheritdoc} */
226 public function getChannelGallery() {
227 $response = [];
228 $channel = $this->getChannelPlaylist();
229 if(!empty($channel['error'])){
230 return $channel;
231 }
232 if (!empty($channel["playlistID"])) {
233 $params = $this->getParams();
234 $the_playlist_id = $channel["playlistID"];
235 $rel = 'https://www.youtube.com/embed?listType=playlist&list=' . esc_attr($the_playlist_id);
236 $title = $channel['title'];
237 $main_iframe = "";
238 $gallery_args = [
239 'playlistId' => $the_playlist_id,
240 ];
241 if(!empty($params['pagesize'])){
242 $gallery_args['pagesize'] = $params['pagesize'];
243 }
244 $gallery = self::get_gallery_page($gallery_args);
245
246 if (!empty($gallery->first_vid)) {
247 $rel = "https://www.youtube.com/embed/{$gallery->first_vid}?feature=oembed";
248 $main_iframe = "<div class='ep-first-video'><iframe width='{$params['maxwidth']}' height='{$params['maxheight']}' src='$rel' frameborder='0' allow='accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture' allowfullscreen title='{$title}'></iframe></div>";
249 }
250 if($gallery->html){
251 $styles = self::styles($params, $this->getUrl());
252 return [
253 "title" => $title,
254 "html" => "<div class='ep-player-wrap'>$main_iframe {$gallery->html} $styles</div>",
255 ];
256 }
257 }
258 elseif ($this->isChannel() && empty(self::get_api_key()) && current_user_can('manage_options')) {
259 return [
260 "html" => "<div class='ep-player-wrap'>" . __('Please enter your YouTube API key to embed YouTube Channel.', 'embedpress') . "</div>",
261 ];
262 }
263
264 return $response;
265 }
266
267 /**
268 * Undocumented function
269 *
270 * @param array $options
271 * @return object
272 */
273 public static function get_gallery_page($options) {
274 $nextPageToken = '';
275 $prevPageToken = '';
276 $gallobj = new \stdClass();
277 $options = wp_parse_args($options, [
278 'playlistId' => '',
279 'pageToken' => '',
280 'pagesize' => self::get_pagesize() ? self::get_pagesize() : 6,
281 'currentpage' => '',
282 'columns' => 3,
283 'thumbnail' => 'medium',
284 'gallery' => true,
285 'autonext' => true,
286 'thumbplay' => true,
287 'apiKey' => self::get_api_key(),
288 'hideprivate' => '',
289 ]);
290 $options['pagesize'] = $options['pagesize'] > 50 ? 50 : $options['pagesize'];
291 $options['pagesize'] = $options['pagesize'] < 1 ? 1 : $options['pagesize'];
292
293 if (empty($options['apiKey'])) {
294 $gallobj->html = self::get_api_key_error_message();
295 return $gallobj;
296 }
297
298 $apiEndpoint = 'https://www.googleapis.com/youtube/v3/playlistItems?part=snippet,status&playlistId=' . $options['playlistId']
299 . '&maxResults=' . $options['pagesize']
300 . '&key=' . $options['apiKey'];
301 if ($options['pageToken'] != null) {
302 $apiEndpoint .= '&pageToken=' . $options['pageToken'];
303 }
304
305 $transient_key = 'ep_embed_youtube_channel_' . md5($apiEndpoint);
306 $gallobj->transient_key = $transient_key;
307 $jsonResult = get_transient($transient_key);
308 if (empty($jsonResult)) {
309 $apiResult = wp_remote_get($apiEndpoint, array('timeout' => self::$curltimeout));
310 if (is_wp_error($apiResult)) {
311 $gallobj->html = self::clean_api_error_html($apiResult->get_error_message(), true);
312 return $gallobj;
313 }
314 $jsonResult = json_decode($apiResult['body']);
315 if (empty($jsonResult->error)) {
316 set_transient($transient_key, $jsonResult, MINUTE_IN_SECONDS * 20);
317 }
318 else{
319 set_transient($transient_key, $jsonResult, 10);
320 }
321 }
322
323
324 if (isset($jsonResult->error)) {
325 if(!empty($jsonResult->error->errors[0]->reason) && $jsonResult->error->errors[0]->reason == 'playlistNotFound'){
326 $gallobj->html = self::clean_api_error_html(__('There is nothing on the playlist.', 'embedpress'));
327 return $gallobj;
328 }
329 if (isset($jsonResult->error->message)) {
330 $gallobj->html = self::clean_api_error_html($jsonResult->error->message);
331 return $gallobj;
332 }
333 $gallobj->html = self::clean_api_error_html(__('Sorry, there may be an issue with your YouTube API key.', 'embedpress'));
334 return $gallobj;
335 }
336
337
338
339 $resultsPerPage = $jsonResult->pageInfo->resultsPerPage;
340 $totalResults = $jsonResult->pageInfo->totalResults;
341 $totalPages = ceil($totalResults / $resultsPerPage);
342 if (isset($jsonResult->nextPageToken)) {
343 $nextPageToken = $jsonResult->nextPageToken;
344 }
345
346 if (isset($jsonResult->prevPageToken)) {
347 $prevPageToken = $jsonResult->prevPageToken;
348 }
349
350
351 if (!empty($jsonResult->items) && is_array($jsonResult->items)) :
352 if($options['gallery'] === "false"){
353 $gallobj->html = "";
354 if(count($jsonResult->items) === 1){
355 $gallobj->first_vid = self::get_id($jsonResult->items[0]);
356 }
357 return $gallobj;
358 }
359
360 if(count($jsonResult->items) === 1 && empty($nextPageToken) && empty($prevPageToken)){
361 $gallobj->first_vid = self::get_id($jsonResult->items[0]);
362 $gallobj->html = "";
363 return $gallobj;
364 }
365
366 if (strpos($options['playlistId'], 'UU') === 0) {
367 // sort only channels
368 usort($jsonResult->items, array(get_class(), 'compare_vid_date')); // sorts in place
369 }
370
371 ob_start();
372 ?>
373 <div class="ep-youtube__content__block" data-unique-id="<?php echo wp_rand(); ?>">
374 <div class="youtube__content__body">
375 <div class="content__wrap">
376 <?php foreach ($jsonResult->items as $item) : ?>
377 <?php
378 $privacyStatus = isset($item->status->privacyStatus) ? $item->status->privacyStatus : null;
379 $thumbnail = self::get_thumbnail_url($item, $options['thumbnail'], $privacyStatus);
380 $vid = self::get_id($item);
381 if (empty($gallobj->first_vid)) {
382 $gallobj->first_vid = $vid;
383 }
384 if ($privacyStatus == 'private' && $options['hideprivate']) {
385 continue;
386 }
387 ?>
388 <div class="item" data-vid="<?php echo $vid; ?>">
389 <div class="thumb" style="background: <?php echo "url({$thumbnail}) no-repeat center"; ?>">
390 <div class="play-icon">
391 <img src="<?php echo EMBEDPRESS_URL_ASSETS . 'images/youtube/youtube-play.png'; ?>" alt="">
392 </div>
393 </div>
394 <div class="body">
395 <p><?php echo $item->snippet->title; ?></p>
396 </div>
397 </div>
398
399 <?php endforeach; ?>
400 <div class="item" style="height: 0"></div>
401 </div>
402
403
404 <?php if ($totalPages > 1) : ?>
405 <div class="ep-youtube__content__pagination <?php echo (empty($prevPageToken) && empty($nextPageToken)) ? ' hide ' : ''; ?>">
406 <div
407 class="ep-prev" <?php echo empty($prevPageToken) ? ' style="display:none" ' : ''; ?>
408 data-playlistid="<?php echo esc_attr($options['playlistId']) ?>"
409 data-pagetoken="<?php echo esc_attr($prevPageToken) ?>"
410 data-pagesize="<?php echo intval($options['pagesize']) ?>"
411 >
412 <span><?php _e("Prev", "embedpress"); ?></span>
413 </div>
414 <div class="is_desktop_device ep-page-numbers <?php echo $totalPages > 1 ? '' : 'hide'; ?>">
415 <?php
416
417 $numOfPages = $totalPages;
418 $renderedEllipses = false;
419
420 $currentPage = !empty($options['currentpage'])?$options['currentpage'] : 1;
421
422 for($i = 1; $i<=$numOfPages; $i++)
423 {
424 //render pages 1 - 3
425 if($i < 4) {
426 //render link
427 $is_current = $i == (int)$currentPage? "active__current_page" : "";
428
429 echo wp_kses_post("<span class='page-number $is_current' data-page='$i'>$i</span>");
430
431 }
432
433 //render current page number
434 else if($i == (int)$currentPage) {
435 //render link
436 echo wp_kses_post('<span class="page-number active__current_page" data-page="'.$i.'">'.$i.'</span>');
437 //reset ellipses
438 $renderedEllipses = false;
439 }
440
441 //last page number
442 else if ($i >= $numOfPages - 1) {
443 //render link
444 echo wp_kses_post('<span class="page-number" data-page="'.$i.'">'.$i.'</span>');
445 }
446
447 //make sure you only do this once per ellipses group
448 else {
449 if (!$renderedEllipses){
450 print("...");
451 $renderedEllipses = true;
452 }
453 }
454 }
455 ?>
456
457 </div>
458
459 <div class="is_mobile_device ep-page-numbers <?php echo $totalPages > 1 ? '' : 'hide'; ?>">
460 <?php
461
462 $numOfPages = $totalPages;
463 $renderedEllipses = false;
464
465 $currentPage = !empty($options['currentpage'])?$options['currentpage'] : 1;
466
467 for($i = 1; $i<=$numOfPages; $i++)
468 {
469
470 //render current page number
471 if($i == (int)$currentPage) {
472 //render link
473 echo wp_kses_post('<span class="page-number-mobile" data-page="'.$i.'">'.$i.'</span>');
474 //reset ellipses
475 $renderedEllipses = false;
476 }
477
478 //last page number
479 else if ($i >= $numOfPages ) {
480 //render link
481 echo wp_kses_post('...<span class="page-number-mobile" data-page="'.$i.'">'.$i.'</span>');
482 }
483 }
484 ?>
485
486 </div>
487
488
489 <div
490 class="ep-next " <?php echo empty($nextPageToken) ? ' style="display:none" ' : ''; ?>
491 data-playlistid="<?php echo esc_attr($options['playlistId']) ?>"
492 data-pagetoken="<?php echo esc_attr($nextPageToken) ?>"
493 data-pagesize="<?php echo intval($options['pagesize']) ?>"
494 >
495 <span><?php _e("Next ", "embedpress"); ?> </span>
496 </div>
497 </div>
498 <?php endif; ?>
499
500 <div class="ep-loader-wrap">
501 <div class="ep-loader"><img alt="loading" src="<?php echo EMBEDPRESS_URL_ASSETS . 'images/youtube/spin.gif'; ?>"></div>
502 </div>
503
504 </div>
505 </div>
506 <?php
507 $gallobj->html = ob_get_clean();
508 else:
509 $gallobj->html = self::clean_api_error_html(__("There is nothing on the playlist.", 'embedpress'));
510 endif;
511
512 return $gallobj;
513 }
514
515 public static function get_api_key_error_message(){
516 return '<div>' . sprintf(__("EmbedPress: Please enter your YouTube API key at <a class='ep-link' href='%s' target='_blank' style='color: #5b4e96; text-decoration: none'>EmbedPress > Platforms > YouTube</a> to embed YouTube Channel.", "embedpress"), admin_url('?page=embedpress&page_type=youtube#api_key')) . '</div>';
517 }
518
519 public static function get_id($item){
520 $vid = isset($item->snippet->resourceId->videoId) ? $item->snippet->resourceId->videoId : null;
521 $vid = $vid ? $vid : (isset($item->id->videoId) ? $item->id->videoId : null);
522 $vid = $vid ? $vid : (isset($item->id) ? $item->id : null);
523 return $vid;
524 }
525 public static function get_thumbnail_url($item, $quality, $privacyStatus) {
526 $url = "";
527 if ($privacyStatus == 'private') {
528 $url = EMBEDPRESS_URL_ASSETS . 'images/youtube/private.png';
529 } elseif (isset($item->snippet->thumbnails->{$quality}->url)) {
530 $url = $item->snippet->thumbnails->{$quality}->url;
531 } elseif (isset($item->snippet->thumbnails->medium->url)) {
532 $url = $item->snippet->thumbnails->medium->url;
533 } elseif (isset($item->snippet->thumbnails->default->url)) {
534 $url = $item->snippet->thumbnails->default->url;
535 } elseif (isset($item->snippet->thumbnails->high->url)) {
536 $url = $item->snippet->thumbnails->high->url;
537 } else {
538 $url = EMBEDPRESS_URL_ASSETS . 'images/youtube/deleted-video-thumb.png';
539 }
540 return $url;
541 }
542
543 public static function compare_vid_date($a, $b) {
544 if ($a->snippet->publishedAt == $b->snippet->publishedAt) {
545 return 0;
546 }
547 return ($a->snippet->publishedAt > $b->snippet->publishedAt) ? -1 : 1;
548 }
549
550 public static function clean_api_error($raw_message) {
551 return htmlspecialchars(strip_tags(preg_replace('@&key=[^& ]+@i', '&key=*******', $raw_message)));
552 }
553
554 public static function clean_api_error_html($raw_message) {
555 $clean_html = '';
556 if ((defined('REST_REQUEST') && REST_REQUEST) || current_user_can('manage_options')) {
557 $clean_html = '<div>' . __('EmbedPress: ', 'embedpress') . self::clean_api_error($raw_message) . '</div>';
558 }
559 return $clean_html;
560 }
561
562 /** inline {@inheritdoc} */
563 public function getFakeResponse() {
564 preg_match('~v=([a-z0-9_\-]+)~i', (string) $this->url, $matches);
565
566 $embedUrl = 'https://www.youtube.com/embed/' . $matches['1'] . '?feature=oembed';
567
568 $attr = [];
569 $attr[] = 'width="{width}"';
570 $attr[] = 'height="{height}"';
571 $attr[] = 'src="' . $embedUrl . '"';
572 $attr[] = 'frameborder="0"';
573 $attr[] = 'allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"';
574 $attr[] = 'allowfullscreen';
575
576 return [
577 'type' => 'video',
578 'provider_name' => 'Youtube',
579 'provider_url' => 'https://www.youtube.com',
580 'title' => 'Unknown title',
581 'html' => '<iframe ' . implode(' ', $attr) . '></iframe>',
582 ];
583 }
584
585 // public static $num = 0;
586
587
588
589 public static $x = 0;
590
591 public static function styles($params, $url){
592
593 $uniqid = '.ose-youtube.ose-uid-'.md5($url);
594
595 ob_start();
596 ?>
597 <style>
598 html {
599 scroll-behavior: smooth;
600 }
601 .ep-player-wrap .hide {
602 display: none;
603 }
604
605 .ep-gdrp-content {
606 background: #222;
607 padding: 50px 30px;
608 color: #fff;
609 }
610
611 .ep-gdrp-content a {
612 color: #fff;
613 }
614
615 .ep-youtube__content__pagination {
616 display: flex;
617 justify-content: center;
618 align-items: center;
619 margin-top: 30px;
620 gap: 10px;
621 }
622 .ep-loader-wrap {
623 margin-top: 30px;
624 display: flex;
625 justify-content: center;
626 }
627
628 .ep-youtube__content__pagination .ep-prev,
629 .ep-youtube__content__pagination .ep-next {
630 cursor: pointer;
631 border: 1px solid rgba(0, 0, 0, .1);
632 border-radius: 30px;
633 padding: 0 20px;
634 height: 40px;
635 transition: .3s;
636 display: flex;
637 align-items: center;
638 }
639 .ep-youtube__content__pagination .ep-prev:hover,
640 .ep-youtube__content__pagination .ep-next:hover{
641 background-color: #5B4E96;
642 color: #fff;
643 }
644 .ep-youtube__content__pagination .ep-page-numbers {
645 display: flex;
646 align-items: center;
647 gap: 10px;
648 flex-wrap: wrap;
649 }
650 .ep-youtube__content__pagination .ep-page-numbers > span {
651 border: 1px solid rgba(0, 0, 0, .1);
652 border-radius: 30px;
653 display: inline-block;
654 width: 45px;
655 height: 45px;
656 display: flex;
657 align-items: center;
658 justify-content: center;
659 }
660 .active__current_page{
661 background: #5B4E96;
662 color: #fff;
663 }
664
665 .ep-youtube__content__block .youtube__content__body .content__wrap {
666 margin-top: 30px;
667 display: grid;
668 grid-template-columns:repeat(auto-fit, minmax(250px, 1fr));
669 gap: 30px;
670 }
671
672 .ep-youtube__content__block .item {
673 cursor: pointer;
674 white-space: initial;
675 }
676
677 .ep-youtube__content__block .item:hover .thumb .play-icon {
678 opacity: 1;
679 top: 50%;
680 }
681
682 .ep-youtube__content__block .item:hover .thumb:after {
683 opacity: .4;
684 z-index: 0;
685 }
686
687 .ep-youtube__content__block .thumb {
688 padding-top: 56.25%;
689 margin-bottom: 5px;
690 position: relative;
691 background: #222;
692 background-size: contain !important;
693 }
694
695 .ep-youtube__content__block .thumb:after {
696 position: absolute;
697 top: 0;
698 left: 0;
699 height: 100%;
700 width: 100%;
701 content: '';
702 background: #000;
703 opacity: 0;
704 transition: opacity .3s ease;
705 }
706
707 .ep-youtube__content__block .thumb:before {
708 position: absolute;
709 top: 0;
710 left: 0;
711 height: 100%;
712 width: 100%;
713 content: '';
714 background: #222;
715 z-index: -1;
716 }
717
718 .ep-youtube__content__block .thumb img {
719 width: 100%;
720 height: 100%;
721 object-fit: cover;
722 }
723
724 .ep-youtube__content__block .thumb .play-icon {
725 width: 50px;
726 height: auto;
727 position: absolute;
728 top: 40%;
729 left: 50%;
730 transform: translate(-50%, -50%);
731 opacity: 0;
732 transition: all .3s ease;
733 z-index: 2;
734 }
735
736 .ep-youtube__content__block .thumb .play-icon img {
737 width: 100;
738 }
739
740 .ep-youtube__content__block .body p {
741 margin-bottom: 0;
742 font-size: 15px;
743 text-align: left;
744 line-height: 1.5;
745 font-weight: 400;
746 }
747 .ep-youtube__content__block.loading .ep-youtube__content__pagination {
748 display: none;
749 }
750
751 .ep-youtube__content__block .ep-loader {
752 display: none;
753 }
754
755 .ep-youtube__content__block.loading .ep-loader {
756 display: block;
757 }
758 .ep-loader img {
759 width: 20px;
760 }
761 .is_mobile_device{
762 display: none!important;
763 }
764
765
766 .is_mobile_devic.ep-page-numbers {
767 gap: 5px;
768 }
769
770 @media only screen and (max-width: 480px) {
771 .is_desktop_device{
772 display: none!important;
773 }
774 .ep-youtube__content__pagination .ep-page-numbers > span {
775 width: 35px;
776 height: 35px;
777 }
778 .ep-youtube__content__pagination .ep-prev, .ep-youtube__content__pagination .ep-next{
779 height: 35px;
780 }
781 .is_mobile_device{
782 display: flex!important;;
783 }
784 .ep-youtube__content__pagination .ep-page-numbers {
785 gap: 5px;
786 }
787 }
788 <?php
789 $attributes_data = $params;
790
791 $is_pagination = 'flex';
792
793 $gap = '30';
794 $columns = '';
795
796 if (isset($attributes_data['ispagination']) && $attributes_data['ispagination']) {
797 $is_pagination = 'none';
798 }
799 if(isset($attributes_data['gapbetweenvideos'])){
800 $gap = $attributes_data['gapbetweenvideos'];
801 }
802 if(isset($attributes_data['columns'])){
803 $columns = $attributes_data['columns'];
804 }
805
806
807
808 if(!empty($columns) && (int) $columns > 0){
809 $repeatCol = 'repeat(auto-fit, minmax('.esc_html('calc('.(100 / (int) $columns).'% - '.$gap.'px)').', 1fr))';
810 }
811 else{
812 $repeatCol = 'repeat(auto-fit, minmax(250px, 1fr))';
813 }
814
815 ?>
816 <?php echo esc_attr($uniqid); ?> .ep-youtube__content__block .youtube__content__body .content__wrap {
817 gap: <?php echo esc_html($gap); ?>px !important;
818 margin-top: <?php echo esc_html($gap); ?>px !important;
819 }
820 <?php echo esc_attr($uniqid); ?> .ep-youtube__content__block .ep-youtube__content__pagination {
821 display: <?php echo esc_html($is_pagination); ?>!important;
822 }
823 <?php echo esc_attr($uniqid); ?> .ep-youtube__content__block .youtube__content__body .content__wrap {
824 grid-template-columns: <?php echo $repeatCol; ?>;
825 gap: <?php echo $gap.'px'; ?>;
826 }
827
828 <?php
829 if($is_pagination){
830 echo esc_attr($uniqid) ?> {
831 height: 100%!important;
832 }
833 <?php
834 }
835 ?>
836 </style>
837 <?php
838 return ob_get_clean();
839 }
840 }
841