PluginProbe
FV Player 8 / 8.0.21
FV Player 8 v8.0.21
trunk 8.0.18 8.0.19 8.0.20 8.0.21 8.0.25 8.0.27 8.1 8.1.3
fv-player / models / seo.php

seo.php in FV Player 8 8.0.21, at models/seo.php

265 lines 7.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit;
5 }
6
7 class FV_Player_SEO {
8
9 var $can_seo = false;
10
11 public function __construct() {
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 add_filter('fv_flowplayer_args_pre', array($this, 'should_i'), 10, 3 );
18 add_filter('fv_flowplayer_attributes', array($this, 'single_attributes'), 10, 3 );
19 add_filter('fv_flowplayer_inner_html', array($this, 'single_video_seo'), 10, 2 );
20 add_filter('fv_player_item_html', array($this, 'playlist_video_seo'), 10, 7 );
21
22 }
23
24 function single_attributes( $attributes, $media, $fv_fp ) {
25 if( !empty($fv_fp->aCurArgs['playlist']) || $this->video_ads_active($fv_fp->aCurArgs) || !$this->can_seo ) {
26 return $attributes;
27 }
28
29 $attributes['itemprop'] = 'video';
30 $attributes['itemscope'] = '';
31 $attributes['itemtype'] = 'http://schema.org/VideoObject';
32
33 return $attributes;
34 }
35
36 function video_ads_active($args) {
37 $conf = get_option( 'fvwpflowplayer' );
38
39 // check globals ads
40 if(!empty($conf['pro']['video_ads_default'])) {
41 if( $conf['pro']['video_ads_default'] != 'no') return true;
42 }
43
44 if( !empty($conf['pro']['video_ads_postroll_default']) ) {
45 if( $conf['pro']['video_ads_postroll_default'] != 'no' ) return true;
46 }
47
48 // check meta ads
49 if( !empty($args['preroll']) ) {
50 if( $args['preroll'] != 'no' ) return true;
51 }
52
53 if( !empty($args['postroll']) ) {
54 if( $args['postroll'] != 'no' ) return true;
55 }
56
57 return false;
58 }
59
60 function get_markup( $args ) {
61 global $fv_fp;
62
63 $args = wp_parse_args( $args, array(
64 'title' => false,
65 'description' => false,
66 'splash' => false,
67 'url' => false,
68 'duration' => false,
69 'plays' => false
70 ) );
71
72 extract($args);
73
74 if( !$title ) {
75 $title = get_the_title();
76 }
77
78 if( !$description ) { // todo: read this from shortcode
79 $description = get_post_meta(get_the_ID(),'_aioseop_description', true );
80 }
81 $post_content = get_the_content();
82 if( !$description && strlen($post_content) > 0 ) {
83 $post_content = strip_shortcodes( $post_content );
84 $post_content = wp_strip_all_tags( $post_content );
85 $description = wp_trim_words( $post_content, 30 );
86 }
87 if( !$description ) {
88 $description = get_option('blogdescription');
89 }
90
91 /**
92 * Do not use $url if it's not MP4, M3U8, WebM or OGV
93 * https://developers.google.com/search/docs/appearance/video#supported-video-files
94 */
95 if ( $url ) {
96 $extension = wp_parse_url( $url, PHP_URL_PATH );
97 $extension = pathinfo( $extension, PATHINFO_EXTENSION );
98 $extension = strtolower( $extension );
99
100 if ( ! in_array( $extension, array( 'mp4', 'm3u8', 'webm', 'ogv' ) ) ) {
101 $url = false;
102 }
103 }
104
105 /**
106 * Do not use the video URL if it has a signature
107 * https://developers.google.com/search/docs/appearance/video#stable-url
108 */
109 if ( $url ) {
110 $signed_url = apply_filters( 'fv_flowplayer_video_src', $url, array( 'dynamic' => true ) );
111
112 if ( strcmp( $url, $signed_url ) !== 0 ) {
113 $url = false;
114 }
115 }
116
117 if( !$url ) {
118 $url = get_permalink();
119 }
120
121 if( stripos($splash,'://') === false ) {
122 $splash = home_url($splash);
123 }
124
125 $schema_tags = '<meta itemprop="name" content="'.esc_attr($title).'" />
126 <meta itemprop="description" content="'.esc_attr($description).'" />
127 <meta itemprop="thumbnailUrl" content="'.esc_attr($splash).'" />
128 <meta itemprop="contentURL" content="'.esc_attr($url).'" />
129 <meta itemprop="uploadDate" content="'.esc_attr(get_the_modified_date('c')).'" />';
130
131
132 global $fv_fp;
133 if( $fv_fp->current_video() ) {
134 if ( ! $duration ) {
135 $duration = $fv_fp->current_video()->getDuration();
136 }
137 $plays = $fv_fp->current_video()->getMetaValue( 'stats_play', true );
138 }
139
140 if( $duration ) {
141 $duration = self::time_to_iso8601_duration($duration);
142 $schema_tags .= "\n".' <meta itemprop="duration" content="'.esc_attr($duration).'" />';
143 }
144
145 if( $plays ) {
146 $schema_tags .= '<div itemprop="interactionStatistic" itemscope itemtype="https://schema.org/InteractionCounter">
147 <meta itemprop="interactionType" content="https://schema.org/WatchAction">
148 <meta itemprop="userInteractionCount" content="' . intval( $plays ) . '">
149 </div>';
150 }
151
152 return $schema_tags;
153 }
154
155 function playlist_video_seo( $sHTML, $aArgs, $sSplashImage, $sItemCaption, $aPlayer, $index, $tDuration ) {
156 if( $this->can_seo ) {
157 $sHTML = str_replace( '<a', '<a itemprop="video" itemscope itemtype="http://schema.org/VideoObject" ', $sHTML );
158
159 $args = array(
160 'title' => $sItemCaption,
161 'splash' => $sSplashImage,
162 );
163
164 if( $tDuration ) {
165 $args['duration'] = $tDuration;
166 }
167
168 if ( ! empty( $aPlayer['sources'][0]['src'] ) ) {
169 $args['url'] = $aPlayer['sources'][0]['src'];
170 }
171
172 $sHTML = str_replace( '</a>', $this->get_markup( $args ).'</a>', $sHTML );
173 }
174 return $sHTML;
175 }
176
177 function should_i( $args ) {
178 global $fv_fp;
179 if( !$fv_fp->_get_option( array( 'integrations', 'schema_org' ) ) ) {
180 $this->can_seo = false;
181 return $args;
182 }
183
184 if( !get_permalink() || !$fv_fp->get_splash() ) {
185 $this->can_seo = false;
186 }
187
188 $dynamic_domains = apply_filters('fv_player_pro_video_ajaxify_domains', array());
189 $amazon = $fv_fp->_get_option('amazon_bucket');
190 if( $amazon && is_array($amazon) && count($amazon) > 0 ) {
191 foreach( $amazon AS $bucket ) {
192 $dynamic_domains[] = 'amazonaws.com/'.$bucket.'/';
193 $dynamic_domains[] = '//'.$bucket.'.s3';
194 }
195 }
196
197 $cf = $fv_fp->_get_option( array('pro','cf_domain') );
198 if( $cf ) {
199 $cf = explode( ',', $cf );
200 if( is_array($cf) && count($cf) > 0 ) {
201 foreach( $cf AS $cf_domain ) {
202 $dynamic_domains[] = $cf_domain;
203 }
204 }
205 }
206
207 $this->can_seo = true;
208 return $args;
209 }
210
211 function single_video_seo( $html, $fv_fp ) {
212 if( !empty($fv_fp->aCurArgs['playlist']) || $this->video_ads_active($fv_fp->aCurArgs) || !$this->can_seo ) {
213 return $html;
214 }
215
216 // todo: use iframe or video link URL
217 $args = array(
218 'splash' => $fv_fp->get_splash()
219 );
220
221 if( !empty($fv_fp->aCurArgs['caption']) ) {
222 $args['title'] = $fv_fp->aCurArgs['caption'];
223 }
224
225 if( !empty($fv_fp->aCurArgs['src']) ) {
226 $args['url'] = $fv_fp->aCurArgs['src'];
227 }
228
229 $html .= "\n".$this->get_markup( $args )."\n";
230
231 return $html;
232 }
233
234 public static function time_to_iso8601_duration($time) {
235 $units = array(
236 "Y" => 365*24*3600,
237 "D" => 24*3600,
238 "H" => 3600,
239 "M" => 60,
240 "S" => 1,
241 );
242
243 $str = "P";
244 $istime = false;
245
246 foreach ($units as $unitName => &$unit) {
247 $quot = intval($time / $unit);
248 $time -= $quot * $unit;
249 $unit = $quot;
250 if ($unit > 0) {
251 if (!$istime && in_array($unitName, array("H", "M", "S"))) {
252 $str .= "T";
253 $istime = true;
254 }
255 $str .= strval($unit) . $unitName;
256 }
257 }
258
259 return $str;
260 }
261
262 }
263
264 $FV_Player_SEO = new FV_Player_SEO();
265