class-ld-permalinks.php
29.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
<?php
/**
* LearnDash Permalink functions
*
* @since 2.5.0
*
* @package LearnDash
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'LearnDash_Permalinks' ) ) {
/**
* Class for LearnDash Permalinks
*/
class LearnDash_Permalinks {
/**
* Public constructor for class
*/
public function __construct() {
add_action( 'generate_rewrite_rules', array( $this, 'generate_rewrite_rules' ) );
add_filter( 'post_type_link', array( $this, 'post_type_link' ), 10, 4 );
add_filter( 'get_edit_post_link', array( $this, 'get_edit_post_link' ), 10, 3 );
add_filter( 'get_sample_permalink', array( $this, 'get_sample_permalink' ), 99, 5 );
add_filter( 'attachment_link', array( $this, 'attachment_link' ), 10, 2 );
add_action( 'comment_form_top', array( $this, 'comment_form_top' ) );
add_action( 'comment_post', array( $this, 'comment_post' ), 30, 3 );
}
/**
* Setup custom rewrite URLs.
*
* Important note: This is very much dependant on the order of the registered post types. This is import when WP goes to parse the request. See
* the logic in wp-includes/class-wp.php starting in the loop at line 289 where it loops the registered CPTs. Within this loop at line 311 it
* set the queried post_type with the last matched post_type per the parse/marched request. So if the Quiz CPT is registered before Topic then
* when we try to match the /courses/course-slug/lessons/lesson-slug/topics/topic-slug/quizzes/quiz-slug/ the queried 'post_type' will be set to
* topic not quiz. As a result in LD v2.5 in includes/class-ld-lms.php where we build the $post_args array we ensure the order of the to-be
* CPTs.
*
* @param array $wp_rewrite Global WP rewrite array.
*/
public function generate_rewrite_rules( $wp_rewrite ) {
if ( LearnDash_Settings_Section::get_section_setting( 'LearnDash_Settings_Section_Permalinks', 'nested_urls' ) == 'yes' ) {
$courses_cpt = get_post_type_object( learndash_get_post_type_slug( 'course' ) );
$lessons_cpt = get_post_type_object( learndash_get_post_type_slug( 'lesson' ) );
$topics_cpt = get_post_type_object( learndash_get_post_type_slug( 'topic' ) );
$quizzes_cpt = get_post_type_object( learndash_get_post_type_slug( 'quiz' ) );
$ld_rewrite_values = array(
learndash_get_post_type_slug( 'course' ) => array(
'name' => array(
'placeholder' => '{{courses_cpt_name}}',
'value' => $courses_cpt->name,
),
'slug' => array(
'placeholder' => '{{courses_cpt_slug}}',
'value' => $courses_cpt->rewrite['slug'],
),
),
learndash_get_post_type_slug( 'lesson' ) => array(
'name' => array(
'placeholder' => '{{lessons_cpt_name}}',
'value' => $lessons_cpt->name,
),
'slug' => array(
'placeholder' => '{{lessons_cpt_slug}}',
'value' => $lessons_cpt->rewrite['slug'],
),
),
learndash_get_post_type_slug( 'topic' ) => array(
'name' => array(
'placeholder' => '{{topics_cpt_name}}',
'value' => $topics_cpt->name,
),
'slug' => array(
'placeholder' => '{{topics_cpt_slug}}',
'value' => $topics_cpt->rewrite['slug'],
),
),
learndash_get_post_type_slug( 'quiz' ) => array(
'name' => array(
'placeholder' => '{{quizzes_cpt_name}}',
'value' => $quizzes_cpt->name,
),
'slug' => array(
'placeholder' => '{{quizzes_cpt_slug}}',
'value' => $quizzes_cpt->rewrite['slug'],
),
),
);
$ld_rewrite_patterns = array(
// Course > Quiz.
'{{courses_cpt_slug}}/([^/]+)/{{quizzes_cpt_slug}}/([^/]+)/comment-page-([0-9]{1,})/?$' => 'index.php?{{courses_cpt_name}}=$matches[1]&{{quizzes_cpt_name}}=$matches[2]&cpage=$matches[3]',
'{{courses_cpt_slug}}/([^/]+)/{{quizzes_cpt_slug}}/([^/]+)(?:/([0-9]+))?/?$' => 'index.php?{{courses_cpt_name}}=$matches[1]&{{quizzes_cpt_name}}=$matches[2]&page=$matches[3]',
// Course > Lesson.
'{{courses_cpt_slug}}/([^/]+)/{{lessons_cpt_slug}}/([^/]+)/comment-page-([0-9]{1,})/?$' => 'index.php?{{courses_cpt_name}}=$matches[1]&{{lessons_cpt_name}}=$matches[2]&cpage=$matches[3]',
'{{courses_cpt_slug}}/([^/]+)/{{lessons_cpt_slug}}/([^/]+)(?:/([0-9]+))?/?$' => 'index.php?{{courses_cpt_name}}=$matches[1]&{{lessons_cpt_name}}=$matches[2]&page=$matches[3]',
// Course > Lesson > Quiz.
'{{courses_cpt_slug}}/([^/]+)/{{lessons_cpt_slug}}/([^/]+)/{{quizzes_cpt_slug}}/([^/]+)/comment-page-([0-9]{1,})/?$' => 'index.php?{{courses_cpt_name}}=$matches[1]&{{lessons_cpt_name}}=$matches[2]&{{quizzes_cpt_name}}=$matches[3]&cpage=$matches[4]',
'{{courses_cpt_slug}}/([^/]+)/{{lessons_cpt_slug}}/([^/]+)/{{quizzes_cpt_slug}}/([^/]+)(?:/([0-9]+))?/?$' => 'index.php?{{courses_cpt_name}}=$matches[1]&{{lessons_cpt_name}}=$matches[2]&{{quizzes_cpt_name}}=$matches[3]&page=$matches[4]',
// Course > Lesson > Topic.
'{{courses_cpt_slug}}/([^/]+)/{{lessons_cpt_slug}}/([^/]+)/{{topics_cpt_slug}}/([^/]+)/comment-page-([0-9]{1,})/?$' => 'index.php?{{courses_cpt_name}}=$matches[1]&{{lessons_cpt_name}}=$matches[2]&{{topics_cpt_name}}=$matches[3]&cpage=$matches[4]',
'{{courses_cpt_slug}}/([^/]+)/{{lessons_cpt_slug}}/([^/]+)/{{topics_cpt_slug}}/([^/]+)(?:/([0-9]+))?/?$' => 'index.php?{{courses_cpt_name}}=$matches[1]&{{lessons_cpt_name}}=$matches[2]&{{topics_cpt_name}}=$matches[3]&page=$matches[4]',
// Course > Lesson > Topic > Quiz.
'{{courses_cpt_slug}}/([^/]+)/{{lessons_cpt_slug}}/([^/]+)/{{topics_cpt_slug}}/([^/]+)/{{quizzes_cpt_slug}}/([^/]+)/comment-page-([0-9]{1,})/?$' => 'index.php?{{courses_cpt_name}}=$matches[1]&{{lessons_cpt_name}}=$matches[2]&{{topics_cpt_name}}=$matches[3]&{{quizzes_cpt_name}}=$matches[4]&cpage=$matches[5]',
'{{courses_cpt_slug}}/([^/]+)/{{lessons_cpt_slug}}/([^/]+)/{{topics_cpt_slug}}/([^/]+)/{{quizzes_cpt_slug}}/([^/]+)(?:/([0-9]+))?/?$' => 'index.php?{{courses_cpt_name}}=$matches[1]&{{lessons_cpt_name}}=$matches[2]&{{topics_cpt_name}}=$matches[3]&{{quizzes_cpt_name}}=$matches[4]&page=$matches[5]',
);
$ld_rewrite_rules = array();
if ( ( ! empty( $ld_rewrite_patterns ) ) && ( ! empty( $ld_rewrite_values ) ) ) {
foreach ( $ld_rewrite_patterns as $rewrite_pattern_key => $rewrite_pattern_rule ) {
foreach ( $ld_rewrite_values as $post_type_name => $ld_rewrite_values_sets ) {
if ( ! empty( $ld_rewrite_values_sets ) ) {
foreach ( $ld_rewrite_values_sets as $ld_rewrite_values_set_key => $ld_rewrite_values_set ) {
if ( ! empty( $ld_rewrite_values_set ) ) {
if ( ( ! isset( $ld_rewrite_values_set['placeholder'] ) ) || ( empty( $ld_rewrite_values_set['placeholder'] ) ) ) {
continue;
}
if ( ( ! isset( $ld_rewrite_values_set['value'] ) ) || ( empty( $ld_rewrite_values_set['value'] ) ) ) {
continue;
}
$rewrite_pattern_key = str_replace( $ld_rewrite_values_set['placeholder'], $ld_rewrite_values_set['value'], $rewrite_pattern_key );
$rewrite_pattern_rule = str_replace( $ld_rewrite_values_set['placeholder'], $ld_rewrite_values_set['value'], $rewrite_pattern_rule );
}
}
}
}
$ld_rewrite_rules[ $rewrite_pattern_key ] = $rewrite_pattern_rule;
}
}
/**
* Filters list of permalinks structure rules.
*
* @param array $permalink_structure An array of permalink structure rules. @since 2.5.0
* @param array $ld_rewrite_patterns An array of rewrite patterns. @since 3.1.4
* @param array $ld_rewrite_values An array of rewrite placeholder/value pairs. @since 3.1.4
*/
$ld_rewrite_rules = apply_filters( 'learndash_permalinks_nested_urls', $ld_rewrite_rules, $ld_rewrite_patterns, $ld_rewrite_values );
if ( ! empty( $ld_rewrite_rules ) ) {
$wp_rewrite->rules = array_merge( $ld_rewrite_rules, $wp_rewrite->rules );
}
}
}
/**
* This second filter will correct calls to the WordPress get_permalink() function to use the new structure
*
* @param string $post_link The post's permalink.
* @param Object $post The WP_Post post in question.
* @param bool $leave_name Whether to keep the post name.
* @param bool $sample Is it a sample permalink.
*/
public function post_type_link( $post_link = '', $post = null, $leave_name = false, $sample = false ) {
global $pagenow, $wp_rewrite;
$url_part_old = '';
$url_part_new = '';
if ( ( LearnDash_Settings_Section::get_section_setting( 'LearnDash_Settings_Section_Permalinks', 'nested_urls' ) == 'yes' ) && ( in_array( $post->post_type, learndash_get_post_types( 'course_steps' ), true ) ) ) {
// If we are viewing one of the list tables we only effect the link if the course_id URL param is set.
if ( ( is_admin() ) && ( 'edit.php' == $pagenow ) ) {
if ( LearnDash_Settings_Section::get_section_setting( 'LearnDash_Settings_Courses_Builder', 'shared_steps' ) == 'yes' ) {
$course_id = 0;
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ( isset( $_GET['course_id'] ) ) && ( ! empty( $_GET['course_id'] ) ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$course_id = absint( $_GET['course_id'] );
}
$course_id = apply_filters( 'learndash_post_link_course_id', $course_id, $post_link, $post );
if ( empty( $course_id ) ) {
return $post_link;
}
}
}
$courses_cpt = get_post_type_object( learndash_get_post_type_slug( 'course' ) );
$lessons_cpt = get_post_type_object( learndash_get_post_type_slug( 'lesson' ) );
$topics_cpt = get_post_type_object( learndash_get_post_type_slug( 'topic' ) );
$quizzes_cpt = get_post_type_object( learndash_get_post_type_slug( 'quiz' ) );
/**
* Filters the rewrite slug for a post type.
*
* @param string $rewrite_slug Rewrite slug.
* @param string $post_type_slug Post type slug.
*/
$courses_cpt->rewrite['slug_alt'] = apply_filters( 'learndash_post_type_rewrite_slug', $courses_cpt->rewrite['slug'], learndash_get_post_type_slug( 'course' ) );
/** This filter is documented in includes/class-ld-permalinks.php */
$lessons_cpt->rewrite['slug_alt'] = apply_filters( 'learndash_post_type_rewrite_slug', $lessons_cpt->rewrite['slug'], learndash_get_post_type_slug( 'lesson' ) );
/** This filter is documented in includes/class-ld-permalinks.php */
$topics_cpt->rewrite['slug_alt'] = apply_filters( 'learndash_post_type_rewrite_slug', $topics_cpt->rewrite['slug'], learndash_get_post_type_slug( 'topic' ) );
/** This filter is documented in includes/class-ld-permalinks.php */
$quizzes_cpt->rewrite['slug_alt'] = apply_filters( 'learndash_post_type_rewrite_slug', $quizzes_cpt->rewrite['slug'], learndash_get_post_type_slug( 'quiz' ) );
$draft_or_pending = in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft', 'future' ), true );
if ( $lessons_cpt->name == $post->post_type ) {
$lesson = $post;
/**
* Filters course link post ID.
*
* @param int $course_id Course ID.
* @param string $post_link Post Link.
* @param WP_Post $post Post Object.
*/
$course_id = apply_filters(
'learndash_post_link_course_id',
learndash_get_course_id( $lesson->ID ),
$post_link,
$post
);
if ( ! empty( $course_id ) ) {
$course = get_post( $course_id );
if ( $course instanceof WP_Post ) {
$url_part_old = '';
$url_part_new = '';
$course_post_name = $course->post_name;
if ( false === $sample ) {
$lesson_post_name = $lesson->post_name;
} else {
$lesson_post_name = '%' . $lessons_cpt->name . '%';
}
if ( ( $wp_rewrite->using_permalinks() ) && ( ! $draft_or_pending ) ) {
// Old URL part.
if ( strstr( $post_link, $lessons_cpt->rewrite['slug'] . '/' . $lesson_post_name ) ) {
$url_part_old = '/' . $lessons_cpt->rewrite['slug'] . '/' . $lesson_post_name;
} elseif ( strstr( $post_link, $lessons_cpt->rewrite['slug_alt'] . '/' . $lesson_post_name ) ) {
$url_part_old = '/' . $lessons_cpt->rewrite['slug_alt'] . '/' . $lesson_post_name;
}
// New URL part.
if ( ! strstr( $post_link, $courses_cpt->rewrite['slug_alt'] . '/' . $course_post_name ) ) {
$url_part_new .= '/' . $courses_cpt->rewrite['slug_alt'] . '/' . $course_post_name;
}
$url_part_new .= '/' . $lessons_cpt->rewrite['slug_alt'] . '/' . $lesson_post_name;
} else {
// Old URL part.
$url_part_old = add_query_arg( $lessons_cpt->name, $lesson->post_name, $url_part_old );
// New URL part.
$url_part_new = add_query_arg( $courses_cpt->name, $course->post_name, $url_part_new );
$url_part_new = add_query_arg( $lessons_cpt->name, $lesson->post_name, $url_part_new );
}
}
}
} elseif ( $topics_cpt->name == $post->post_type ) {
$topic = $post;
/** This filter is documented in includes/class-ld-permalinks.php */
$course_id = apply_filters( 'learndash_post_link_course_id', learndash_get_course_id( $topic->ID ), $post_link, $post );
if ( ! empty( $course_id ) ) {
if ( LearnDash_Settings_Section::get_section_setting( 'LearnDash_Settings_Courses_Builder', 'shared_steps' ) == 'yes' ) {
$lesson_id = learndash_course_get_single_parent_step( $course_id, $topic->ID );
} else {
$lesson_id = learndash_get_lesson_id( $topic->ID );
}
if ( ! empty( $lesson_id ) ) {
$course = get_post( $course_id );
$lesson = get_post( $lesson_id );
if ( ( $course instanceof WP_Post ) && ( $lesson instanceof WP_Post ) ) {
$course_post_name = $course->post_name;
$lesson_post_name = $lesson->post_name;
if ( false === $sample ) {
$topic_post_name = $topic->post_name;
} else {
$topic_post_name = '%' . $topics_cpt->name . '%';
}
if ( ( $wp_rewrite->using_permalinks() ) && ( ! $draft_or_pending ) ) {
if ( strstr( $post_link, $topics_cpt->rewrite['slug'] . '/' . $topic_post_name ) ) {
$url_part_old = '/' . $topics_cpt->rewrite['slug'] . '/' . $topic_post_name;
} elseif ( strstr( $post_link, $topics_cpt->rewrite['slug_alt'] . '/' . $topic_post_name ) ) {
$url_part_old = '/' . $topics_cpt->rewrite['slug_alt'] . '/' . $topic_post_name;
}
if ( ! strstr( $post_link, $courses_cpt->rewrite['slug_alt'] . '/' . $course_post_name ) ) {
$url_part_new .= '/' . $courses_cpt->rewrite['slug_alt'] . '/' . $course_post_name;
}
if ( ! strstr( $post_link, $lessons_cpt->rewrite['slug_alt'] . '/' . $lesson_post_name ) ) {
$url_part_new .= '/' . $lessons_cpt->rewrite['slug_alt'] . '/' . $lesson_post_name;
}
$url_part_new .= '/' . $topics_cpt->rewrite['slug_alt'] . '/' . $topic_post_name;
} else {
$url_part_old = add_query_arg( $topics_cpt->name, $topic->post_name, $url_part_old );
$url_part_new = add_query_arg( $courses_cpt->name, $course->post_name, $url_part_new );
$url_part_new = add_query_arg( $lessons_cpt->name, $lesson->post_name, $url_part_new );
$url_part_new = add_query_arg( $topics_cpt->name, $topic->post_name, $url_part_new );
}
}
}
}
} elseif ( $quizzes_cpt->name == $post->post_type ) {
$quiz = $post;
/** This filter is documented in includes/class-ld-permalinks.php */
$course_id = apply_filters( 'learndash_post_link_course_id', learndash_get_course_id( $quiz->ID ), $post_link, $post );
if ( ! empty( $course_id ) ) {
$course = get_post( $course_id );
if ( $course instanceof WP_Post ) {
$course_post_name = $course->post_name;
if ( false === $sample ) {
$quiz_post_name = $quiz->post_name;
} else {
$quiz_post_name = '%' . $quizzes_cpt->name . '%';
}
if ( ( $wp_rewrite->using_permalinks() ) && ( ! $draft_or_pending ) ) {
if ( strstr( $post_link, $quizzes_cpt->rewrite['slug'] . '/' . $quiz_post_name ) ) {
$url_part_old = '/' . $quizzes_cpt->rewrite['slug'] . '/' . $quiz_post_name;
} elseif ( strstr( $post_link, $quizzes_cpt->rewrite['slug_alt'] . '/' . $quiz_post_name ) ) {
$url_part_old = '/' . $quizzes_cpt->rewrite['slug_alt'] . '/' . $quiz_post_name;
}
} else {
$url_part_old = add_query_arg( $quizzes_cpt->name, $quiz->post_name, $url_part_old );
}
$quiz_parents = array();
if ( LearnDash_Settings_Section::get_section_setting( 'LearnDash_Settings_Courses_Builder', 'shared_steps' ) == 'yes' ) {
$quiz_parents = learndash_course_get_all_parent_step_ids( $course_id, $quiz->ID );
} else {
$lesson_id = learndash_get_lesson_id( $quiz->ID );
if ( ! empty( $lesson_id ) ) {
if ( get_post_type( $lesson_id ) == $topics_cpt->name ) {
$topic_id = $lesson_id;
$lesson_id = learndash_get_lesson_id( $topic_id );
if ( ! empty( $lesson_id ) ) {
if ( get_post_type( $lesson_id ) == $lessons_cpt->name ) {
$quiz_parents[] = $lesson_id;
$quiz_parents[] = $topic_id;
}
}
} else {
$quiz_parents[] = $lesson_id;
}
}
}
if ( ( $wp_rewrite->using_permalinks() ) && ( ! $draft_or_pending ) ) {
if ( ! strstr( $post_link, $courses_cpt->rewrite['slug_alt'] . '/' . $course_post_name ) ) {
$url_part_new .= '/' . $courses_cpt->rewrite['slug_alt'] . '/' . $course_post_name;
}
} else {
$url_part_new = add_query_arg( $courses_cpt->name, $course->post_name, $url_part_new );
}
if ( ! empty( $quiz_parents ) ) {
foreach ( $quiz_parents as $quiz_parent_id ) {
$quiz_parent_post = get_post( $quiz_parent_id );
if ( $quiz_parent_post->post_type == $lessons_cpt->name ) {
if ( ( $wp_rewrite->using_permalinks() ) && ( ! $draft_or_pending ) ) {
$parent_slug = $lessons_cpt->rewrite['slug_alt'];
} else {
$parent_slug = $lessons_cpt->name;
}
} elseif ( $quiz_parent_post->post_type == $topics_cpt->name ) {
if ( ( $wp_rewrite->using_permalinks() ) && ( ! $draft_or_pending ) ) {
$parent_slug = $topics_cpt->rewrite['slug_alt'];
} else {
$parent_slug = $topics_cpt->name;
}
}
if ( ( $wp_rewrite->using_permalinks() ) && ( ! $draft_or_pending ) ) {
if ( ! strstr( $post_link, $parent_slug . '/' . $quiz_parent_post->post_name ) ) {
$url_part_new .= '/' . $parent_slug . '/' . $quiz_parent_post->post_name;
}
} else {
$url_part_new = add_query_arg( $parent_slug, $quiz_parent_post->post_name, $url_part_new );
}
}
}
if ( ( $wp_rewrite->using_permalinks() ) && ( ! $draft_or_pending ) ) {
$url_part_new .= '/' . $quizzes_cpt->rewrite['slug_alt'] . '/' . $quiz_post_name;
} else {
$url_part_new = add_query_arg( $quizzes_cpt->name, $quiz->post_name, $url_part_new );
}
}
}
}
}
if ( ( ! empty( $url_part_new ) ) && ( ! empty( $url_part_old ) ) && ( $url_part_old !== $url_part_new ) ) {
if ( ( ! $wp_rewrite->using_permalinks() ) || ( $draft_or_pending ) ) {
$url_part_old = str_replace( '?', '', $url_part_old );
$url_part_new = str_replace( '?', '', $url_part_new );
/**
* We could normally just append the new args to the end of the URL. But
* we want to control the ordering for readability.
*/
$args = wp_parse_args( $url_part_new, array() );
if ( ! empty( $args ) ) {
foreach ( $args as $arg_key => $arg_val ) {
$post_link = remove_query_arg( $arg_key, $post_link );
}
$post_link_parts_old = wp_parse_url( $post_link );
if ( ( isset( $post_link_parts_old['query'] ) ) && ( ! empty( $post_link_parts_old['query'] ) ) ) {
$post_link = str_replace( $post_link_parts_old['query'], '', $post_link );
}
$post_link = add_query_arg( $args, $post_link );
$post_link_parts_new = wp_parse_url( $post_link );
/**
* Here we have removed the original LD post type elements and any non-LD elements from the
* original URL. Now we want to add the non-LD elements back.
*/
if ( ( isset( $post_link_parts_old['query'] ) ) && ( ! empty( $post_link_parts_old['query'] ) ) ) {
if ( ( isset( $post_link_parts_old['query'] ) ) && ( ! empty( $post_link_parts_old['query'] ) ) ) {
$post_link .= '&' . $post_link_parts_old['query'];
} else {
$post_link .= '?' . $post_link_parts_old['query'];
}
}
}
} else {
$post_link = str_replace( $url_part_old, $url_part_new, $post_link );
}
}
return $post_link;
}
/**
* Called via the WordPress List Table instance. This function will adjust the course
* step permalinks to be nested if enabled.
*
* @since 2.5.0
* @param array $actions Array of row actions to be shown.
* @param object $post WP_Post object being displayed for the row.
*/
public function row_actions( $actions = array(), $post = '' ) {
global $pagenow, $typenow;
if ( ( is_admin() ) && ( 'edit.php' == $pagenow ) ) {
if ( ( 'yes' === LearnDash_Settings_Section::get_section_setting( 'LearnDash_Settings_Courses_Builder', 'shared_steps' ) ) && ( in_array( $typenow, learndash_get_post_types( 'course_steps' ), true ) ) ) {
$course_id = 0;
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( isset( $_GET['course_id'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$course_id = absint( $_GET['course_id'] );
}
if ( ( empty( $course_id ) ) && ( isset( $actions['view'] ) ) ) {
unset( $actions['view'] );
}
}
}
return $actions;
}
/**
* Override WordPress Get Edit Post Link to include nested URL.
*
* @since 2.5.0
* @param string $link The edit link.
* @param integer $post_id Post ID to edit.
* @param string $context The link context. If set to 'display' then ampersands are encoded.
*/
public function get_edit_post_link( $link = '', $post_id = 0, $context = '' ) {
global $pagenow;
if ( ( ! empty( $post_id ) ) && ( ! is_admin() ) || ( ( is_admin() && ( in_array( $pagenow, array( 'post.php', 'edit.php' ), true ) ) ) ) ) {
$post_type_name = get_post_type( $post_id );
if ( ( ! empty( $post_type_name ) ) && ( in_array( $post_type_name, learndash_get_post_types( 'course_steps' ), true ) ) ) {
if ( LearnDash_Settings_Section::get_section_setting( 'LearnDash_Settings_Courses_Builder', 'shared_steps' ) == 'yes' ) {
$course_id = 0;
$course_id = learndash_get_course_id( $post_id );
if ( ! empty( $course_id ) ) {
$link = add_query_arg( 'course_id', $course_id, $link );
}
}
}
if ( ( ! empty( $post_type_name ) ) && ( in_array( $post_type_name, LDLMS_Post_Types::get_post_types( 'quiz_questions' ), true ) ) ) {
$quiz_id = 0;
$quiz_id = learndash_get_quiz_id( $post_id );
if ( ! empty( $quiz_id ) ) {
$link = add_query_arg( 'quiz_id', $quiz_id, $link );
}
}
}
return $link;
}
/**
* Hook into the admin post editor Permalink display. We override the LD post
* items so they include the full nested URL
*
* @since 2.5.0
* @param array $permalink Array containing the sample permalink with placeholder for the post name, and the post name.
* @param int $post_id Post ID.
* @param string $title Post title.
* @param string $name Post name (slug).
* @param object $post (WP_Post) Post object.
*/
public function get_sample_permalink( $permalink = '', $post_id = 0, $title = '', $name = '', $post = '' ) {
global $pagenow;
if ( ( is_admin() ) && ( 'post.php' === $pagenow ) && ( is_a( $post, 'WP_Post' ) ) && ( in_array( $post->post_type, learndash_get_post_types( 'course_steps' ), true ) ) ) {
$permalink_new = $this->post_type_link( $permalink[0], $post, false, true );
if ( ( ! empty( $permalink_new ) ) && ( $permalink_new !== $permalink[0] ) ) {
$permalink[0] = $permalink_new;
}
}
return $permalink;
}
/**
* Filter the attachment link when using nested URLs.
*
* @since 3.4.1
*
* @param string $attachment_link Attachment link.
* @param integer $attachment_id Attachment post ID.
*
* @return string $attachment_link
*/
public function attachment_link( $attachment_link = '', $attachment_id = 0 ) {
global $wp_rewrite;
if ( ( ! empty( $attachment_link ) ) && ( ! empty( $attachment_id ) ) ) {
if ( ( $wp_rewrite->using_permalinks() ) && ( 'yes' === LearnDash_Settings_Section::get_section_setting( 'LearnDash_Settings_Section_Permalinks', 'nested_urls' ) ) ) {
$attachment_post = get_post( $attachment_id );
if ( ( $attachment_post ) && ( is_a( $attachment_post, 'WP_Post' ) ) ) {
if ( ( property_exists( $attachment_post, 'post_parent' ) ) && ( ! empty( $attachment_post->post_parent ) ) ) {
if ( in_array( get_post_type( $attachment_post->post_parent ), learndash_get_post_types( 'course' ), true ) ) {
$attachment_link = str_replace( '/' . $attachment_post->post_name . '/', '/attachment/' . $attachment_post->post_name . '/', $attachment_link );
}
}
}
}
}
return $attachment_link;
}
/**
* Action for comment form when nested URLs are enabled. This way the user is returned to this course step URL
*
* @since 2.5.5
*/
public function comment_form_top() {
$queried_object = get_queried_object();
if ( ( is_a( $queried_object, 'WP_Post' ) ) && ( LearnDash_Settings_Section::get_section_setting( 'LearnDash_Settings_Section_Permalinks', 'nested_urls' ) == 'yes' ) ) {
if ( in_array( $queried_object->post_type, learndash_get_post_types( 'course_steps' ), true ) ) {
echo '<input type="hidden" name="step_id" value="' . absint( $queried_object->ID ) . '" />';
$course_id = learndash_get_course_id( $queried_object->ID );
if ( ! empty( $course_id ) ) {
echo '<input type="hidden" name="course_id" value="' . absint( $course_id ) . '" />';
$redirect_to = learndash_get_step_permalink( $queried_object->ID, $course_id );
if ( ! empty( $redirect_to ) ) {
// This 'redirect_to' is used by WP in wp-comments-post.php to redirect back to a specific URL.
// This is the important part.
echo '<input type="hidden" name="redirect_to" value="' . esc_url( $redirect_to ) . '" />';
}
}
}
}
}
/**
* Add the course_id to comment meta
*
* @since 2.5.5
*
* @param int $comment_id The comment ID.
* @param int|string $comment_approved Comment Approve Status, 1 if the comment is approved, 0 if not, 'spam' if spam.
* @param array $comment_data Comment data.
*/
public function comment_post( $comment_id, $comment_approved, $comment_data ) {
// phpcs:ignore WordPress.Security.NonceVerification.Missing
if ( ( isset( $_POST['course_id'] ) ) && ( ! empty( $_POST['course_id'] ) ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Missing
update_comment_meta( $comment_id, 'course_id', absint( $_POST['course_id'] ) );
}
}
// End of function.
}
}
add_action(
'plugins_loaded',
function() {
new LearnDash_Permalinks();
}
);
/**
* Utility function to get the nested permalink of the course step within in the course.
*
* @since 2.5.0
* @param int $step_id Course Step Post ID.
* @param int $step_course_id Course ID.
*/
function learndash_get_step_permalink( $step_id = 0, $step_course_id = null ) {
if ( ! empty( $step_id ) ) {
if ( ! is_null( $step_course_id ) ) {
$GLOBALS['step_course_id'] = $step_course_id; //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
add_filter(
'learndash_post_link_course_id',
function( $course_id ) {
if ( ( isset( $GLOBALS['step_course_id'] ) ) && ( ! is_null( $GLOBALS['step_course_id'] ) ) ) { // @phpstan-ignore-line -- filter is processed later.
$course_id = $GLOBALS['step_course_id'];
}
return $course_id;
}
);
}
$step_permalink = get_permalink( $step_id );
if ( isset( $GLOBALS['step_course_id'] ) ) {
unset( $GLOBALS['step_course_id'] );
}
return $step_permalink;
}
}
/**
* Used when editing Lesson, Topic, Quiz or Question post items. This filter is needed to add
* the 'course_id' parameter back to the edit URL after the post is submitted (saved).
*
* @since 2.5.0
* @param string $location The destination URL.
* @param int $post_id The post ID.
*/
function learndash_redirect_post_location( $location = '', $post_id = 0 ) {
if ( ( is_admin() ) && ( ! empty( $location ) ) ) {
global $typenow;
check_admin_referer( 'update-post_' . $post_id );
if ( in_array( $typenow, learndash_get_post_types( 'course_steps' ), true ) ) {
if ( ( isset( $_POST['ld-course-switcher'] ) ) && ( ! empty( $_POST['ld-course-switcher'] ) ) ) {
$post_args = wp_parse_args( $_POST['ld-course-switcher'], array() );
if ( ( isset( $post_args['course_id'] ) ) && ( ! empty( $post_args['course_id'] ) ) ) {
$location = add_query_arg( 'course_id', intval( $post_args['course_id'] ), $location );
}
}
} elseif ( learndash_get_post_type_slug( 'question' ) === $typenow ) {
if ( ( isset( $_POST['ld-quiz-switcher'] ) ) && ( ! empty( $_POST['ld-quiz-switcher'] ) ) ) {
$post_args = wp_parse_args( $_POST['ld-quiz-switcher'], array() );
if ( ( isset( $post_args['quiz_id'] ) ) && ( ! empty( $post_args['quiz_id'] ) ) ) {
$location = add_query_arg( 'quiz_id', absint( $post_args['quiz_id'] ), $location );
}
}
}
}
return $location;
}
add_filter( 'redirect_post_location', 'learndash_redirect_post_location', 10, 2 );
/**
* Utility function to set the option to trigger flush of rewrite rules.
* This is checked during the 'shutdown' action where the rewrites will
* then be flushed.
*/
function learndash_setup_rewrite_flush() {
update_option( 'sfwd_lms_rewrite_flush', true, false );
}