PluginProbe
FV Player 8 / trunk
FV Player 8 vtrunk
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 trunk, at models/seo.php

270 lines 7.3 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 ) {
79 $description = get_post_meta(get_the_ID(),'_aioseo_description', true );
80 }
81
82 if( !$description ) { // todo: read this from shortcode
83 $description = get_post_meta(get_the_ID(),'_aioseop_description', true );
84 }
85
86 $post_content = get_the_content();
87 if( !$description && strlen($post_content) > 0 ) {
88 $post_content = strip_shortcodes( $post_content );
89 $post_content = wp_strip_all_tags( $post_content );
90 $description = wp_trim_words( $post_content, 30 );
91 }
92 if( !$description ) {
93 $description = get_option('blogdescription');
94 }
95
96 /**
97 * Do not use $url if it's not MP4, M3U8, WebM or OGV
98 * https://developers.google.com/search/docs/appearance/video#supported-video-files
99 */
100 if ( $url ) {
101 $extension = wp_parse_url( $url, PHP_URL_PATH );
102 $extension = pathinfo( $extension, PATHINFO_EXTENSION );
103 $extension = strtolower( $extension );
104
105 if ( ! in_array( $extension, array( 'mp4', 'm3u8', 'webm', 'ogv' ) ) ) {
106 $url = false;
107 }
108 }
109
110 /**
111 * Do not use the video URL if it has a signature
112 * https://developers.google.com/search/docs/appearance/video#stable-url
113 */
114 if ( $url ) {
115 $signed_url = apply_filters( 'fv_flowplayer_video_src', $url, array( 'dynamic' => true ) );
116
117 if ( strcmp( $url, $signed_url ) !== 0 ) {
118 $url = false;
119 }
120 }
121
122 if( !$url ) {
123 $url = get_permalink();
124 }
125
126 if( stripos($splash,'://') === false ) {
127 $splash = home_url($splash);
128 }
129
130 $schema_tags = '<meta itemprop="name" content="'.esc_attr($title).'" />
131 <meta itemprop="description" content="'.esc_attr($description).'" />
132 <meta itemprop="thumbnailUrl" content="'.esc_attr($splash).'" />
133 <meta itemprop="contentURL" content="'.esc_attr($url).'" />
134 <meta itemprop="uploadDate" content="'.esc_attr(get_the_modified_date('c')).'" />';
135
136
137 global $fv_fp;
138 if( $fv_fp->current_video() ) {
139 if ( ! $duration ) {
140 $duration = $fv_fp->current_video()->getDuration();
141 }
142 $plays = $fv_fp->current_video()->getMetaValue( 'stats_play', true );
143 }
144
145 if( $duration ) {
146 $duration = self::time_to_iso8601_duration($duration);
147 $schema_tags .= "\n".' <meta itemprop="duration" content="'.esc_attr($duration).'" />';
148 }
149
150 if( $plays ) {
151 $schema_tags .= '<div itemprop="interactionStatistic" itemscope itemtype="https://schema.org/InteractionCounter">
152 <meta itemprop="interactionType" content="https://schema.org/WatchAction">
153 <meta itemprop="userInteractionCount" content="' . intval( $plays ) . '">
154 </div>';
155 }
156
157 return $schema_tags;
158 }
159
160 function playlist_video_seo( $sHTML, $aArgs, $sSplashImage, $sItemCaption, $aPlayer, $index, $tDuration ) {
161 if( $this->can_seo ) {
162 $sHTML = str_replace( '<a', '<a itemprop="video" itemscope itemtype="http://schema.org/VideoObject" ', $sHTML );
163
164 $args = array(
165 'title' => $sItemCaption,
166 'splash' => $sSplashImage,
167 );
168
169 if( $tDuration ) {
170 $args['duration'] = $tDuration;
171 }
172
173 if ( ! empty( $aPlayer['sources'][0]['src'] ) ) {
174 $args['url'] = $aPlayer['sources'][0]['src'];
175 }
176
177 $sHTML = str_replace( '</a>', $this->get_markup( $args ).'</a>', $sHTML );
178 }
179 return $sHTML;
180 }
181
182 function should_i( $args ) {
183 global $fv_fp;
184 if( !$fv_fp->_get_option( array( 'integrations', 'schema_org' ) ) ) {
185 $this->can_seo = false;
186 return $args;
187 }
188
189 if( !get_permalink() || !$fv_fp->get_splash() ) {
190 $this->can_seo = false;
191 }
192
193 $dynamic_domains = apply_filters('fv_player_pro_video_ajaxify_domains', array());
194 $amazon = $fv_fp->_get_option('amazon_bucket');
195 if( $amazon && is_array($amazon) && count($amazon) > 0 ) {
196 foreach( $amazon AS $bucket ) {
197 $dynamic_domains[] = 'amazonaws.com/'.$bucket.'/';
198 $dynamic_domains[] = '//'.$bucket.'.s3';
199 }
200 }
201
202 $cf = $fv_fp->_get_option( array('pro','cf_domain') );
203 if( $cf ) {
204 $cf = explode( ',', $cf );
205 if( is_array($cf) && count($cf) > 0 ) {
206 foreach( $cf AS $cf_domain ) {
207 $dynamic_domains[] = $cf_domain;
208 }
209 }
210 }
211
212 $this->can_seo = true;
213 return $args;
214 }
215
216 function single_video_seo( $html, $fv_fp ) {
217 if( !empty($fv_fp->aCurArgs['playlist']) || $this->video_ads_active($fv_fp->aCurArgs) || !$this->can_seo ) {
218 return $html;
219 }
220
221 // todo: use iframe or video link URL
222 $args = array(
223 'splash' => $fv_fp->get_splash()
224 );
225
226 if( !empty($fv_fp->aCurArgs['caption']) ) {
227 $args['title'] = $fv_fp->aCurArgs['caption'];
228 }
229
230 if( !empty($fv_fp->aCurArgs['src']) ) {
231 $args['url'] = $fv_fp->aCurArgs['src'];
232 }
233
234 $html .= "\n".$this->get_markup( $args )."\n";
235
236 return $html;
237 }
238
239 public static function time_to_iso8601_duration($time) {
240 $units = array(
241 "Y" => 365*24*3600,
242 "D" => 24*3600,
243 "H" => 3600,
244 "M" => 60,
245 "S" => 1,
246 );
247
248 $str = "P";
249 $istime = false;
250
251 foreach ($units as $unitName => &$unit) {
252 $quot = intval($time / $unit);
253 $time -= $quot * $unit;
254 $unit = $quot;
255 if ($unit > 0) {
256 if (!$istime && in_array($unitName, array("H", "M", "S"))) {
257 $str .= "T";
258 $istime = true;
259 }
260 $str .= strval($unit) . $unitName;
261 }
262 }
263
264 return $str;
265 }
266
267 }
268
269 $FV_Player_SEO = new FV_Player_SEO();
270