PluginProbe ʕ •ᴥ•ʔ
Presto Player / 4.3.1
Presto Player v4.3.1
4.3.1 4.3.0 4.2.4 4.2.3 4.2.2 4.2.0 4.2.1 trunk 1.10.0 1.10.1 1.10.2 1.11.0 1.12.0 1.13.0 1.14.0 1.14.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 1.6.13 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.3-beta1 2.3.0 2.3.1 2.3.2 2.3.3 3.0.0 3.0.0-beta1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.1.0 3.1.1 3.1.2 3.1.3 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4
presto-player / inc / Integrations / LearnDash / LearnDash.php
presto-player / inc / Integrations / LearnDash Last commit date
LearnDash.php 3 weeks ago
LearnDash.php
401 lines
1 <?php
2 /**
3 * LearnDash integration for Presto Player.
4 *
5 * @package PrestoPlayer
6 */
7
8 namespace PrestoPlayer\Integrations\LearnDash;
9
10 use PrestoPlayer\Models\Post;
11 use PrestoPlayer\Support\Utility;
12 use PrestoPlayer\Contracts\Service;
13
14 /**
15 * Integrates Presto Player video progression with LearnDash.
16 */
17 class LearnDash implements Service {
18
19 /**
20 * Register the integration hooks.
21 *
22 * @return void
23 */
24 public function register() {
25 add_action(
26 'plugins_loaded',
27 function () {
28 if ( ! self::isEnabled() ) {
29 return;
30 }
31
32 add_filter( 'learndash_settings_fields', array( $this, 'settingsFields' ), 10, 2 );
33 add_filter( 'ld_video_provider', array( $this, 'addProvider' ), 10, 2 );
34 add_filter( 'presto-settings-block-js-options', array( $this, 'jsOptions' ) );
35 add_filter( 'get_post_metadata', array( $this, 'filterVideoURL' ), 10, 3 );
36
37 add_filter( 'presto_player/block/default_attributes', array( $this, 'addVideoAttributes' ) );
38 add_filter( 'presto_player/templates/player_tag', array( $this, 'addPlayerTags' ) );
39 }
40 );
41 }
42
43 /**
44 * Add tags to player
45 *
46 * @param array $data Player data containing cookie key and video progress.
47 * @return void
48 */
49 public function addPlayerTags( $data ) {
50 if ( empty( $data['cookieKey'] ) || empty( $data['videoProgress'] ) ) {
51 return;
52 }
53
54 ob_start();
55 ?>
56 data-video-cookie-key="<?php echo esc_attr( $data['cookieKey'] ); ?>"
57 data-video-progression="<?php echo esc_attr( $data['videoProgress'] ); ?>"
58 data-video-provider="presto"
59 <?php
60 echo ob_get_clean(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output composed of the esc_attr() escaped data attributes above.
61 }
62
63 /**
64 * Add attributes to video for video progression
65 *
66 * @param array $attributes Block attributes.
67 * @return array
68 */
69 public function addVideoAttributes( $attributes ) {
70 global $post;
71
72 // Bail if not a learndash post type.
73 if ( ! self::isLearnDashPost( $post ) ) {
74 return $attributes;
75 }
76
77 $logic_video = true;
78 $video_id = ! empty( $attributes['id'] ) ? '(presto-' . $attributes['id'] . ')' : '(presto)';
79 $video_completed = $this->stepIsCompleted( $post->ID );
80
81 if ( $video_completed ) {
82 $logic_video = false;
83 } else {
84 // Get lesson settings.
85 $step_settings = learndash_get_setting( $post );
86
87 if ( 'BEFORE' === ( $step_settings['lesson_video_shown'] ?? '' ) ) {
88 $logic_video = true;
89
90 $topics = learndash_get_topic_list( $post->ID );
91 if ( ! empty( $topics ) ) {
92 $progress = learndash_get_course_progress( null, $topics[0]->ID );
93 if ( ! empty( $progress ) ) {
94 $topics_completed = 0;
95 foreach ( $progress['posts'] as $topic ) {
96 if ( (int) 1 === (int) $topic->completed ) {
97 ++$topics_completed;
98 break;
99 }
100 }
101
102 if ( ! empty( $topics_completed ) ) {
103 $logic_video = false;
104 }
105 }
106 }
107 }
108 }
109
110 if ( true === $logic_video ) {
111 $logic_video_str = 'true';
112 } else {
113 $logic_video_str = 'false';
114 }
115
116 $attributes['cookieKey'] = $this->buildVideoCookieKey( $video_id );
117 $attributes['videoProgress'] = $logic_video_str;
118
119 return $attributes;
120 }
121
122 /**
123 * Build unique video progress cookie key. This is used to track the video state
124 * in the user's browser.
125 *
126 * @param integer $attach_id Attachment ID of the video.
127 *
128 * @return string $cookie_key.
129 */
130 public function buildVideoCookieKey( $attach_id = '' ) {
131 $cookie_key = '';
132 $cookie_key = $this->getNonceSlug();
133
134 if ( ( isset( $attach_id ) ) && ( ! empty( $attach_id ) ) ) {
135 $lesson_video_url = trim( $attach_id );
136 $lesson_video_url = html_entity_decode( $lesson_video_url );
137
138 $cookie_key .= '_' . $lesson_video_url;
139 }
140 $cookie_key = 'learndash-video-progress-' . md5( $cookie_key );
141
142 return $cookie_key;
143 }
144
145 /**
146 * Utility function to get the nonce slug.
147 *
148 * @since 3.2.3
149 */
150 protected function getNonceSlug() {
151 $post_id = get_the_ID();
152 $step_id = $post_id;
153 $course_id = learndash_get_course_id( $post_id );
154 $user_id = (int) get_current_user_id();
155
156 return 'learndash_video_' . $user_id . '_' . $course_id . '_' . $step_id;
157 }
158
159 /**
160 * Dynamically replace (presto) with (presto-$video_id)
161 *
162 * @param mixed $value The meta value being filtered.
163 * @param integer $object_id The post ID the meta belongs to.
164 * @param string $meta_key The meta key being requested.
165 *
166 * @return mixed
167 */
168 public function filterVideoURL( $value, $object_id, $meta_key ) {
169 // Prevent recursion.
170 remove_filter( current_filter(), __FUNCTION__ );
171
172 // Only learndash meta.
173 if ( ! in_array( $meta_key, array( '_sfwd-topic', '_sfwd-lessons' ) ) ) {
174 return $value;
175 }
176
177 // Get meta.
178 $meta_cache = wp_cache_get( $object_id, 'post_meta' );
179 if ( ! $meta_cache ) {
180 $meta_cache = update_meta_cache( 'post', array( $object_id ) );
181 if ( isset( $meta_cache[ $object_id ] ) ) {
182 $meta_cache = $meta_cache[ $object_id ];
183 } else {
184 $meta_cache = null;
185 }
186 }
187 if ( ! $meta_key ) {
188 return $meta_cache;
189 }
190
191 if ( isset( $meta_cache[ $meta_key ] ) ) {
192 $saved = maybe_unserialize( $meta_cache[ $meta_key ][0] );
193
194 if ( is_array( $saved ) ) {
195 $key = array_key_exists( 'sfwd-lessons_lesson_video_url', $saved ) ? 'sfwd-lessons_lesson_video_url' : '';
196 $key = array_key_exists( 'sfwd-topic_lesson_video_url', $saved ) ? 'sfwd-topic_lesson_video_url' : $key;
197 }
198
199 if ( ! $key ) {
200 return $value;
201 }
202
203 if ( strpos( $saved[ $key ], '(presto' ) === false ) {
204 return $value;
205 }
206
207 $post_model = new Post( get_post( $object_id ) );
208 $video_id = $post_model->findVideoId();
209 $saved[ $key ] = "(presto-$video_id)";
210 $meta_cache[ $meta_key ][0] = $saved;
211 return $meta_cache[ $meta_key ];
212 }
213
214 return $value;
215 }
216
217 /**
218 * Pass javascript options to presto player
219 *
220 * @param array $options Javascript options passed to the player.
221 * @return array
222 */
223 public function jsOptions( $options ) {
224 if ( self::isEnabled() ) {
225 global $post;
226 $settings = learndash_get_setting( $post );
227
228 if ( ! empty( $settings['lesson_video_auto_complete_delay'] ) ) {
229 $post_type_obj = get_post_type_object( $post->post_type );
230 $settings['videos_auto_complete_delay_message'] = sprintf(
231 // translators: placeholders: 1. Lesson or Topic label, 2. span for counter.
232 wp_kses_post( _x( '<p class="ld-video-delay-message">%1$s will auto complete in %2$s seconds</p>', 'placeholders: 1. Lesson or Topic label, 2. span for counter', 'presto-player' ) ),
233 $post_type_obj->labels->singular_name,
234 '<span class="time-countdown">' . $settings['lesson_video_auto_complete_delay'] . '</span>'
235 );
236 }
237
238 $options['learndash'] = $settings;
239 }
240
241 return $options;
242 }
243
244 /**
245 * Is LearnDash enabled?
246 *
247 * @return boolean
248 */
249 public static function isEnabled() {
250 return defined( 'LEARNDASH_VERSION' );
251 }
252
253 /**
254 * Should the video load on the learndash page
255 *
256 * @return boolean
257 */
258 public static function shouldVideoLoad() {
259 global $post;
260
261 // Bail if not a learndash post type.
262 if ( ! self::isLearnDashPost( $post ) ) {
263 return true;
264 }
265
266 // Step is completed, load video.
267 if ( self::stepIsCompleted( $post ) ) {
268 return true;
269 }
270
271 // Check if lesson steps are complete.
272 return self::areStepsComplete( $post );
273 }
274
275 /**
276 * Is this a learndash post?
277 *
278 * @param \WP_Post $post The post to check.
279 * @return boolean
280 */
281 public static function isLearnDashPost( $post ) {
282 if ( ! $post ) {
283 return false;
284 }
285
286 return in_array( $post->post_type, array( 'sfwd-lessons', 'sfwd-topic' ) );
287 }
288
289 /**
290 * Is the learndash step completed
291 *
292 * @param \WP_Post $post The post to check.
293 * @return bool
294 */
295 public static function stepIsCompleted( $post ) {
296 if ( ! function_exists( 'learndash_get_course_progress' ) ) {
297 return true;
298 }
299
300 global $post;
301 $progress = learndash_get_course_progress( null, $post->ID );
302 return ( ! empty( $progress['this'] ) ) && ( $progress['this'] instanceof \WP_Post ) && ( true === (bool) $progress['this']->completed );
303 }
304
305 /**
306 * Are lesson/topic steps complete?
307 *
308 * @param \WP_Post $post The post to check.
309 * @return boolean
310 */
311 public static function areStepsComplete( \WP_Post $post ) {
312 // Get lesson settings.
313 $lesson_settings = learndash_get_setting( $post );
314
315 // We're only concerned with "AFTER".
316 if ( 'AFTER' !== ( $lesson_settings['lesson_video_shown'] ?? '' ) ) {
317 return true;
318 }
319
320 // If this is a lesson, check if topics are completed.
321 if ( 'sfwd-lessons' === $post->post_type ) {
322 if ( ! learndash_lesson_topics_completed( $post->ID ) ) {
323 return false;
324 }
325 }
326
327 // Quizes must also be completed.
328 return self::areQuizzesCompleted( $post );
329 }
330
331 /**
332 * Are quizzes completed?
333 *
334 * @param \WP_Post $post The post to check.
335 * @return boolean
336 */
337 public static function areQuizzesCompleted( \WP_Post $post ) {
338 // Quizes must also be completed.
339 $quizzes_completed = true;
340 $lesson_quizzes_list = learndash_get_lesson_quiz_list( $post->ID );
341 if ( ! empty( $lesson_quizzes_list ) ) {
342 foreach ( $lesson_quizzes_list as $quiz ) {
343 if ( 'completed' !== $quiz['status'] ) {
344 $quizzes_completed = false;
345 break;
346 }
347 }
348 }
349 return (bool) $quizzes_completed;
350 }
351
352 /**
353 * Add our video provider to learndash
354 *
355 * @param array $video_data The current video provider data.
356 * @param array $step_settings The LearnDash step settings.
357 * @return array
358 */
359 public function addProvider( $video_data, $step_settings ) {
360 if ( strpos( $step_settings['lesson_video_url'], '(presto' ) !== false ) {
361 return 'presto';
362 }
363 return $video_data;
364 }
365
366 /**
367 * Adds our setting to the lesson settings page
368 *
369 * @param array $settings The current settings fields.
370 * @param string $meta_box_key The settings meta box key.
371 * @return array
372 */
373 public function settingsFields( $settings, $meta_box_key ) {
374 // If it's not one of these settings pages, bail.
375 if ( ! in_array( $meta_box_key, array( 'learndash-lesson-display-content-settings', 'learndash-topic-display-content-settings' ) ) ) {
376 return $settings;
377 }
378
379 $setting = array(
380 'lesson_use_presto_video' => array(
381 'name' => 'lesson_use_presto_video',
382 'label' => esc_html__( 'Use Presto Video', 'presto-player' ),
383 'type' => 'checkbox-switch',
384 'value' => ! empty( $settings['use_presto_video'] ) ? $settings['use_presto_video'] : '',
385 'help_text' => esc_html__( 'Use the Presto Player video in your post content for video progression.', 'presto-player' ),
386 'default' => '',
387 'options' => array(
388 'on' => esc_html__( 'The presto video in this post will be used for video progression.', 'presto-player' ),
389 '' => '',
390 ),
391 'parent_setting' => 'lesson_video_enabled',
392 ),
393 );
394
395 // Insert before video url.
396 $settings = Utility::arrayInsert( $settings, $setting, 'lesson_video_url', 'before' );
397
398 return $settings;
399 }
400 }
401