PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
← All changes | inc/TemplateHooks/CourseBuilder/Lesson/BuilderEditLessonTemplate.php +476 -466 4.3.84.4.8 View file →
@@ -1,466 +1,476 @@
1 -<?php
2 -/**
3 - * Template hooks Course Builder.
4 - *
5 - * @since 4.3.0
6 - * @version 1.0.0
7 - */
8 -
9 -namespace LearnPress\TemplateHooks\CourseBuilder\Lesson;
10 -
11 -use Exception;
12 -use LearnPress\CourseBuilder\CourseBuilder;
13 -use LearnPress\CourseBuilder\CourseBuilderAccessPolicy;
14 -use LearnPress\Helpers\Singleton;
15 -use LearnPress\Helpers\Template;
16 -use LearnPress\Models\LessonPostModel;
17 -use LearnPress\Models\UserModel;
18 -use LearnPress\TemplateHooks\CourseBuilder\Course\BuilderCourseTemplate;
19 -use LearnPress\TemplateHooks\Course\AdminEditCurriculumTemplate;
20 -use LP_Settings;
21 -use WP_User;
22 -
23 -class BuilderEditLessonTemplate {
24 - use Singleton;
25 -
26 - public function init() {
27 - add_filter( 'lp/rest/ajax/allow_callback', [ $this, 'allow_callback' ] );
28 - }
29 -
30 - /**
31 - * Display layout edit/create lesson.
32 - *
33 - * @param array $data [ 'userModel' => UserModel, 'item_id' => int|string ]
34 - *
35 - * @throws Exception
36 - */
37 - public function layout( array $data = [] ) {
38 - $userModel = $data['userModel'] ?? false;
39 - if ( ! $userModel || ! $userModel->is_instructor() ) {
40 - throw new Exception( __( 'You do not have permission to create or edit lessons', 'learnpress' ) );
41 - }
42 -
43 - $item_id = $data['item_id'] ?? '';
44 - if ( empty( $item_id ) ) {
45 - throw new Exception( __( 'Invalid lesson ID', 'learnpress' ) );
46 - }
47 -
48 - if ( ! CourseBuilderAccessPolicy::can_access_tab_post( 'lessons', $item_id ) ) {
49 - throw new Exception( __( "Sorry, you don't have permission to access this content", 'learnpress' ) );
50 - }
51 -
52 - $is_create_new = $item_id === CourseBuilder::POST_NEW;
53 - $lessonModel = false;
54 -
55 - if ( ! $is_create_new ) {
56 - $lessonModel = LessonPostModel::find( (int) $item_id, true );
57 - if ( ! $lessonModel ) {
58 - throw new Exception( __( 'Lesson not found', 'learnpress' ) );
59 - }
60 - }
61 -
62 - $data['lessonModel'] = $lessonModel;
63 -
64 - $section = [
65 - 'wrap' => sprintf(
66 - '<div class="lp-cb-content" data-post-id="%1$s">',
67 - esc_attr( $item_id )
68 - ),
69 - 'header' => $this->html_header( $data ),
70 - 'tabs' => $this->html_tabs( $data ),
71 - 'wrap_end' => '</div>',
72 - ];
73 -
74 - echo Template::combine_components( $section );
75 - }
76 -
77 - public function html_header( array $data = [] ): string {
78 - $userModel = $data['userModel'] ?? false;
79 - if ( ! $userModel instanceof UserModel ) {
80 - return '';
81 - }
82 -
83 - $wp_user = new WP_User( $userModel );
84 - $lessonModel = $data['lessonModel'] ?? false;
85 - $hide_instructor_access_admin_screen = LP_Settings::is_hide_instructor_access_admin_screen();
86 - $title = $lessonModel ? $lessonModel->get_the_title() : __( 'Add New Lesson', 'learnpress' );
87 - $status = $lessonModel ? sanitize_key( (string) $lessonModel->post_status ) : '';
88 - $status_label = 'future' === $status ? __( 'scheduled', 'learnpress' ) : $status;
89 - $hide_wp_edit_link = $hide_instructor_access_admin_screen && user_can( $wp_user, UserModel::ROLE_INSTRUCTOR );
90 - $main_action_label = $lessonModel && 'publish' === $status ? __( 'Update', 'learnpress' ) : __( 'Publish', 'learnpress' );
91 -
92 - $section = [
93 - 'header_wrap' => '<div class="lp-cb-header">',
94 - 'header_left' => '<div class="lp-cb-header__left">',
95 - 'title' => sprintf(
96 - '<h1 class="lp-cb-header__title">%s</h1>',
97 - esc_html( $title )
98 - ),
99 - 'status_badge' => $lessonModel && $status ? sprintf(
100 - '<span class="lesson-status %1$s">%2$s</span>',
101 - esc_attr( $status ),
102 - esc_html( $status_label )
103 - ) : '',
104 - 'link_edit_on_wp' => $lessonModel && ! $hide_wp_edit_link ? sprintf(
105 - '<a href="%1$s" class="lp-cb-admin-link" target="_blank" title="%2$s"%3$s>
106 - <span class="dashicons dashicons-wordpress"></span>
107 - <span>%2$s</span>
108 - </a>',
109 - esc_url( admin_url( 'post.php?post=' . $lessonModel->get_id() . '&action=edit' ) ),
110 - esc_attr__( 'Edit with WordPress', 'learnpress' ),
111 - 'trash' === $status ? ' style="display:none"' : ''
112 - ) : '',
113 - 'header_left_end' => '</div>',
114 - 'header_actions' => '<div class="lp-cb-header__actions">',
115 - 'dropdown_wrap' => '<div class="cb-header-actions-dropdown cb-header-actions-dropdown--single">',
116 - 'update_btn' => sprintf(
117 - '<div class="cb-btn-update cb-btn-primary cb-btn-main-action"
118 - data-status="%1$s"
119 - data-title-update="%2$s"
120 - data-title-publish="%3$s">%4$s</div>',
121 - esc_attr( 'publish' ),
122 - esc_attr__( 'Update', 'learnpress' ),
123 - esc_attr__( 'Publish', 'learnpress' ),
124 - esc_html( $main_action_label )
125 - ),
126 - 'dropdown_wrap_end' => '</div>',
127 - 'header_actions_end' => '</div>',
128 - 'header_end' => '</div>',
129 - ];
130 -
131 - return Template::combine_components( $section );
132 - }
133 -
134 - public function html_tabs( array $data = [] ): string {
135 - $section_tab = [
136 - 'tabs_wrap' => '<div class="lp-cb-tabs">',
137 - 'tabs' => '',
138 - 'tabs_end' => '</div>',
139 - ];
140 -
141 - $section_content = [
142 - 'wrap' => '<div class="lp-cb-tab-content">',
143 - 'content' => '',
144 - 'wrap-end' => '</div>',
145 - ];
146 -
147 - $tabs = apply_filters(
148 - 'learn-press/course-builder/lessons/edit/tabs',
149 - [
150 - 'overview' => [
151 - 'title' => esc_html__( 'Overview', 'learnpress' ),
152 - 'html' => $this->html_tab_overview( $data ),
153 - ],
154 - 'settings' => [
155 - 'title' => esc_html__( 'Settings', 'learnpress' ),
156 - 'html' => $this->html_tab_settings( $data ),
157 - ],
158 - ],
159 - $data
160 - );
161 -
162 - $tab_active = array_key_first( $tabs );
163 - if ( isset( $_GET['tab'] ) && isset( $tabs[ $_GET['tab'] ] ) ) {
164 - $tab_active = $_GET['tab'];
165 - }
166 -
167 - foreach ( $tabs as $key => $tab ) {
168 - $is_active = $key === $tab_active;
169 -
170 - $section_tab['tabs'] .= sprintf(
171 - '<a href="#" class="lp-cb-tabs__item %s" data-tab-section="%s">%s</a>',
172 - $is_active ? 'is-active' : '',
173 - esc_attr( $tab['slug'] ?? $key ),
174 - esc_html( $tab['title'] ?? '' )
175 - );
176 -
177 - $section_content['content'] .= sprintf(
178 - '<div class="lp-cb-tab-panel %s" data-section="%s">%s</div>',
179 - $is_active ? '' : 'lp-hidden',
180 - esc_attr( $tab['slug'] ?? $key ),
181 - $tab['html'] ?? ''
182 - );
183 - }
184 -
185 - return Template::combine_components(
186 - [
187 - 'tabs' => Template::combine_components( $section_tab ),
188 - 'contents' => Template::combine_components( $section_content ),
189 - ]
190 - );
191 - }
192 -
193 - public function html_tab_overview( array $data = [] ): string {
194 - wp_enqueue_script( 'lp-course-builder' );
195 -
196 - $lesson_model = $data['lessonModel'] ?? false;
197 - $lesson_id = $data['item_id'] ?? ( $lesson_model ? $lesson_model->get_id() : CourseBuilder::POST_NEW );
198 -
199 - if ( absint( $lesson_id ) && ! $lesson_model ) {
200 - $lesson_model = LessonPostModel::find( absint( $lesson_id ), true );
201 - if ( empty( $lesson_model ) ) {
202 - return '';
203 - }
204 - }
205 -
206 - $html_assigned = $this->assigned_course( $lesson_model );
207 - $html_edit_title = $this->edit_title( $lesson_model );
208 - $html_permalink = $this->edit_permalink( $lesson_model );
209 - $html_edit_desc = $this->edit_desc( $lesson_model );
210 - $section = [
211 - 'wrapper' => sprintf( '<div class="cb-section__lesson-edit" data-lesson-id="%s">', $lesson_id ),
212 - 'edit_title' => $html_edit_title,
213 - 'wrapper_title_assigned' => '<div class="cb-section__lesson-title-assigned">',
214 - 'assigned_course' => $html_assigned,
215 - 'wrapper_title_assigned_end' => '</div>',
216 - 'edit_permalink' => $html_permalink,
217 - 'edit_desc' => $html_edit_desc,
218 - 'wrapper_end' => '</div>',
219 - ];
220 -
221 - return Template::combine_components( $section );
222 - }
223 -
224 - public function html_tab_settings( array $data = [] ): string {
225 - $lesson_model = $data['lessonModel'] ?? false;
226 - $lesson_id = $data['item_id'] ?? ( $lesson_model ? $lesson_model->get_id() : CourseBuilder::POST_NEW );
227 -
228 - if ( $lesson_id === CourseBuilder::POST_NEW || absint( $lesson_id ) <= 0 ) {
229 - return sprintf( '<span class="lp-message lp-message--info">%s</span>', __( 'Please save Lesson before setting lesson', 'learnpress' ) );
230 - }
231 -
232 - if ( ! $lesson_model ) {
233 - $lesson_model = LessonPostModel::find( absint( $lesson_id ), true );
234 - if ( empty( $lesson_model ) ) {
235 - return '';
236 - }
237 - }
238 -
239 - if ( ! class_exists( 'LP_Meta_Box_Lesson' ) ) {
240 - require_once LP_PLUGIN_PATH . 'inc/admin/views/meta-boxes/lesson/settings.php';
241 - }
242 -
243 - $metabox = new \LP_Meta_Box_Lesson();
244 - ob_start();
245 - $metabox->output( $lesson_model );
246 - $settings = ob_get_clean();
247 -
248 - $output = [
249 - 'wrapper' => sprintf( '<div class="cb-section__lesson-edit" data-lesson-id="%s">', $lesson_id ),
250 - 'form_setting' => '<form name="lp-form-setting-lesson" class="lp-form-setting-lesson" method="post" enctype="multipart/form-data">',
251 - 'settings' => $settings,
252 - 'form_setting_end' => '</form>',
253 - 'wrapper_end' => '</div>',
254 - ];
255 -
256 - return Template::combine_components( $output );
257 - }
258 -
259 - /**
260 - * Allow callback for AJAX.
261 - * @use self::render_edit_course_curriculum
262 - * @use self::render_html
263 - *
264 - * @param array $callbacks
265 - *
266 - * @return array
267 - */
268 - public function allow_callback( array $callbacks ): array {
269 - $callbacks[] = AdminEditCurriculumTemplate::class . ':render_edit_course_curriculum';
270 -
271 - return $callbacks;
272 - }
273 -
274 - public function assigned_course( $lesson_model ) {
275 - $assign_course = ! empty( $lesson_model ) ? $this->get_assigned( $lesson_model->get_id() ) : '';
276 - $html_courses = '';
277 - $assigned = sprintf( '<span class="lesson-not-assigned">%s</span>', __( 'Not assigned yet', 'learnpress' ) );
278 - if ( ! empty( $assign_course ) ) {
279 - $courses = is_array( $assign_course ) && isset( $assign_course['id'] )
280 - ? array( $assign_course )
281 - : $assign_course;
282 -
283 - $course_htmls = array();
284 - foreach ( $courses as $course ) {
285 - $course_id = $course['id'] ?? 0;
286 - $course_title = $course['title'] ?? '';
287 -
288 - if ( $course_id && $course_title ) {
289 - $course_link = BuilderCourseTemplate::instance()->get_link_edit( $course_id );
290 - $course_htmls[] = sprintf(
291 - '<a href="%s" target="_blank">%s</a>',
292 - esc_url( $course_link ),
293 - esc_html( $course_title )
294 - );
295 - }
296 - }
297 -
298 - if ( ! empty( $course_htmls ) ) {
299 - $assigned = implode( ', ', $course_htmls );
300 - }
301 - }
302 -
303 - $html_courses = sprintf(
304 - '<div class="cb-item-edit-assigned lesson-assigned-courses"><span class="label">%s</span> %s</div>',
305 - __( 'Assigned', 'learnpress' ),
306 - $assigned
307 - );
308 -
309 - return $html_courses;
310 - }
311 -
312 - public function edit_permalink( $lesson_model ): string {
313 - $post_id = ! empty( $lesson_model ) ? absint( $lesson_model->get_id() ) : 0;
314 - $post = $post_id ? get_post( $post_id ) : null;
315 - $post_name = $post && ! empty( $post->post_name ) ? (string) $post->post_name : '';
316 - $full_url = '';
317 - $base_url = '';
318 - $display_classes = 'cb-permalink-display';
319 - $placeholder_class = 'cb-item-edit-permalink__placeholder';
320 - $notice_no_link = __(
321 - 'Permalink is only available if the item is already assigned to a course.',
322 - 'learnpress'
323 - );
324 - $placeholder_text = __( 'Permalink will be available after saving.', 'learnpress' );
325 - $show_unavailable = true;
326 -
327 - if ( $post_id ) {
328 - $current_status = $post && ! empty( $post->post_status ) ? sanitize_key( $post->post_status ) : '';
329 - if ( 'draft' !== $current_status ) {
330 - $course_id_of_item = \LP_Course_DB::getInstance()->get_course_by_item_id( $post_id );
331 - if ( $course_id_of_item ) {
332 - $course = learn_press_get_course( $course_id_of_item );
333 - if ( $course ) {
334 - $full_url = urldecode( $course->get_item_link( $post_id ) );
335 - $base_url = $full_url;
336 - $show_unavailable = false;
337 -
338 - if ( ! empty( $post_name ) ) {
339 - $base_url = trailingslashit( preg_replace( '/' . preg_quote( $post_name, '/' ) . '\/?$/', '', $full_url ) );
340 - }
341 - }
342 - }
343 - }
344 - }
345 -
346 - if ( $show_unavailable && $post_id ) {
347 - $placeholder_text = $notice_no_link;
348 - }
349 -
350 - if ( $show_unavailable ) {
351 - $display_classes .= ' lp-hidden';
352 - } else {
353 - $placeholder_class .= ' lp-hidden';
354 - }
355 -
356 - $state_a = sprintf(
357 - '<span class="cb-item-edit-permalink__label">%s</span>
358 - <div class="%s">
359 - <a href="%s" target="_blank" class="cb-permalink-url">%s</a>
360 - <button type="button" class="cb-permalink-edit-btn" title="%s">
361 - <span class="dashicons dashicons-edit"></span>
362 - </button>
363 - </div>',
364 - __( 'Permalink', 'learnpress' ),
365 - esc_attr( $display_classes ),
366 - esc_url( $full_url ),
367 - esc_html( $full_url ),
368 - __( 'Edit', 'learnpress' )
369 - );
370 -
371 - $state_b = sprintf(
372 - '<div class="cb-permalink-editor lp-hidden">
373 - <span class="cb-permalink-prefix">%s</span>
374 - <div class="cb-permalink-input-row">
375 - <input type="text" name="lesson_permalink" id="lesson_permalink" value="%s" class="cb-permalink-slug-input" placeholder="%s">
376 - <div class="cb-permalink-actions">
377 - <button type="button" class="cb-permalink-ok-btn">%s</button>
378 - <button type="button" class="cb-permalink-cancel-btn">%s</button>
379 - </div>
380 - </div>
381 - </div>',
382 - esc_html( $base_url ),
383 - esc_attr( $post_name ),
384 - esc_attr__( 'your-slug', 'learnpress' ),
385 - __( 'OK', 'learnpress' ),
386 - __( 'Cancel', 'learnpress' )
387 - );
388 -
389 - $hidden_base = sprintf(
390 - '<input type="hidden" id="cb-permalink-base-url" value="%s">',
391 - esc_attr( $base_url )
392 - );
393 -
394 - $placeholder = sprintf(
395 - '<span class="%s">%s</span>',
396 - esc_attr( $placeholder_class ),
397 - esc_html( $placeholder_text )
398 - );
399 -
400 - $view = [
401 - 'wrapper' => '<div class="cb-item-edit-permalink cb-course-edit-permalink">',
402 - 'state_a' => $state_a,
403 - 'state_b' => $state_b,
404 - 'hidden_base' => $hidden_base,
405 - 'placeholder' => $placeholder,
406 - 'wrapper_end' => '</div>',
407 - ];
408 -
409 - return Template::combine_components( $view );
410 - }
411 -
412 - public function edit_title( $lesson_model ) {
413 - $title = ! empty( $lesson_model ) ? $lesson_model->get_the_title() : '';
414 - $edit = [
415 - 'wrapper' => '<div class="cb-lesson-edit-title">',
416 - 'label' => sprintf( '<label for="title" class="cb-lesson-edit-title__label">%s</label>', __( 'Title', 'learnpress' ) ),
417 - 'input' => sprintf( '<input type="text" name="lesson_title" size="30" value="%s" id="title" class="cb-lesson-edit-title__input">', $title ),
418 - 'wrapper_end' => '</div>',
419 - ];
420 -
421 - return Template::combine_components( $edit );
422 - }
423 -
424 - public function edit_desc( $lesson_model ) {
425 - $desc = ! empty( $lesson_model ) ? $lesson_model->get_the_content() : '';
426 - $editor_id = 'lesson_description_editor';
427 - $editor_settings = array(
428 - 'textarea_name' => 'lesson_description',
429 - 'textarea_rows' => 10,
430 - 'teeny' => false,
431 - 'media_buttons' => true,
432 - 'tinymce' => array(
433 - 'content_style' => "body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif; font-size: 14px; line-height: 1.6; color: #1e1e1e; }",
434 - 'toolbar1' => 'formatselect,bold,italic,underline,bullist,numlist,blockquote,alignleft,aligncenter,alignright,link,unlink,spellchecker,wp_adv',
435 - 'toolbar2' => 'strikethrough,hr,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help',
436 - ),
437 - 'quicktags' => true,
438 - );
439 -
440 - ob_start();
441 - wp_editor( $desc, $editor_id, $editor_settings );
442 - $editor_html = ob_get_clean();
443 -
444 - $edit = [
445 - 'wrapper' => '<div class="cb-lesson-edit-desc">',
446 - 'label' => sprintf( '<label for="lesson_description" class="cb-lesson-edit-desc__label">%s</label>', __( 'Description', 'learnpress' ) ),
447 - 'edit' => $editor_html,
448 - 'wrapper_end' => '</div>',
449 - ];
450 -
451 - return Template::combine_components( $edit );
452 - }
453 -
454 - public function get_assigned( $id ) {
455 - $courses = learn_press_get_item_courses( $id );
456 -
457 - if ( empty( $courses ) ) {
458 - return array();
459 - }
460 -
461 - return array(
462 - 'id' => $courses[0]->ID,
463 - 'title' => $courses[0]->post_title ?? '',
464 - );
465 - }
466 -}
1 +<?php
2 +/**
3 + * Template hooks Course Builder.
4 + *
5 + * @since 4.3.0
6 + * @version 1.0.0
7 + */
8 +
9 +namespace LearnPress\TemplateHooks\CourseBuilder\Lesson;
10 +
11 +use Exception;
12 +use LearnPress\CourseBuilder\CourseBuilder;
13 +use LearnPress\CourseBuilder\CourseBuilderAccessPolicy;
14 +use LearnPress\Helpers\Singleton;
15 +use LearnPress\Helpers\Template;
16 +use LearnPress\Models\LessonPostModel;
17 +use LearnPress\Models\UserModel;
18 +use LearnPress\TemplateHooks\CourseBuilder\Course\BuilderCourseTemplate;
19 +use LearnPress\TemplateHooks\Course\AdminEditCurriculumTemplate;
20 +use LP_Settings;
21 +use WP_User;
22 +
23 +class BuilderEditLessonTemplate {
24 + use Singleton;
25 +
26 + public function init() {
27 + add_filter( 'lp/rest/ajax/allow_callback', [ $this, 'allow_callback' ] );
28 + }
29 +
30 + /**
31 + * Display layout edit/create lesson.
32 + *
33 + * @param array $data [ 'userModel' => UserModel, 'item_id' => int|string ]
34 + *
35 + * @throws Exception
36 + */
37 + public function layout( array $data = [] ) {
38 + /** @var UserModel|false $userModel */
39 + $userModel = $data['userModel'] ?? false;
40 + if ( ! $userModel || ! $userModel->is_instructor() ) {
41 + throw new Exception( __( 'You do not have permission to create or edit lessons', 'learnpress' ) );
42 + }
43 +
44 + $item_id = $data['item_id'] ?? '';
45 + if ( empty( $item_id ) ) {
46 + throw new Exception( __( 'Invalid lesson ID', 'learnpress' ) );
47 + }
48 +
49 + /*if ( ! CourseBuilderAccessPolicy::can_access_tab_post( 'lessons', $item_id ) ) {
50 + throw new Exception( __( "Sorry, you don't have permission to access this content", 'learnpress' ) );
51 + }*/
52 +
53 + $is_create_new = $item_id === CourseBuilder::POST_NEW;
54 + $lessonPostModel = false;
55 +
56 + if ( ! $is_create_new ) {
57 + $lessonPostModel = LessonPostModel::find( (int) $item_id, true );
58 + if ( ! $lessonPostModel ) {
59 + throw new Exception( __( 'Lesson not found', 'learnpress' ) );
60 + }
61 +
62 + $lessonPostModel->check_capabilities_update_item_course();
63 + } else {
64 + $lessonPostModelNew = new LessonPostModel();
65 + $lessonPostModelNew->check_capabilities_create_item_course();
66 + }
67 +
68 + $data['lessonModel'] = $lessonPostModel;
69 +
70 + $section = [
71 + 'wrap' => sprintf(
72 + '<div class="lp-cb-content" data-post-id="%1$s">',
73 + esc_attr( $item_id )
74 + ),
75 + 'header' => $this->html_header( $data ),
76 + 'tabs' => $this->html_tabs( $data ),
77 + 'wrap_end' => '</div>',
78 + ];
79 +
80 + echo Template::combine_components( $section );
81 + }
82 +
83 + public function html_header( array $data = [] ): string {
84 + $userModel = $data['userModel'] ?? false;
85 + if ( ! $userModel instanceof UserModel ) {
86 + return '';
87 + }
88 +
89 + $wp_user = new WP_User( $userModel );
90 + $lessonModel = $data['lessonModel'] ?? false;
91 + $hide_instructor_access_admin_screen = LP_Settings::is_hide_instructor_access_admin_screen();
92 + $title = $lessonModel ? $lessonModel->get_the_title() : __( 'Add New Lesson', 'learnpress' );
93 + $status = $lessonModel ? sanitize_key( (string) $lessonModel->post_status ) : '';
94 + $status_label = 'future' === $status ? __( 'scheduled', 'learnpress' ) : $status;
95 + $hide_wp_edit_link = $hide_instructor_access_admin_screen && user_can( $wp_user, UserModel::ROLE_INSTRUCTOR );
96 + $main_action_label = $lessonModel && 'publish' === $status ? __( 'Update', 'learnpress' ) : __( 'Publish', 'learnpress' );
97 +
98 + $section = [
99 + 'header_wrap' => '<div class="lp-cb-header">',
100 + 'header_left' => '<div class="lp-cb-header__left">',
101 + 'title' => sprintf(
102 + '<h1 class="lp-cb-header__title">%s</h1>',
103 + esc_html( $title )
104 + ),
105 + 'status_badge' => $lessonModel && $status ? sprintf(
106 + '<span class="lesson-status %1$s">%2$s</span>',
107 + esc_attr( $status ),
108 + esc_html( $status_label )
109 + ) : '',
110 + 'link_edit_on_wp' => $lessonModel && ! $hide_wp_edit_link ? sprintf(
111 + '<a href="%1$s" class="lp-cb-admin-link" target="_blank" title="%2$s"%3$s>
112 + <span class="dashicons dashicons-wordpress"></span>
113 + <span>%2$s</span>
114 + </a>',
115 + esc_url( admin_url( 'post.php?post=' . $lessonModel->get_id() . '&action=edit' ) ),
116 + esc_attr__( 'Edit with WordPress', 'learnpress' ),
117 + 'trash' === $status ? ' style="display:none"' : ''
118 + ) : '',
119 + 'header_left_end' => '</div>',
120 + 'header_actions' => '<div class="lp-cb-header__actions">',
121 + 'dropdown_wrap' => '<div class="cb-header-actions-dropdown cb-header-actions-dropdown--single">',
122 + 'update_btn' => sprintf(
123 + '<div class="cb-btn-update cb-btn-primary cb-btn-main-action"
124 + data-status="%1$s"
125 + data-title-update="%2$s"
126 + data-title-publish="%3$s">%4$s</div>',
127 + esc_attr( 'publish' ),
128 + esc_attr__( 'Update', 'learnpress' ),
129 + esc_attr__( 'Publish', 'learnpress' ),
130 + esc_html( $main_action_label )
131 + ),
132 + 'dropdown_wrap_end' => '</div>',
133 + 'header_actions_end' => '</div>',
134 + 'header_end' => '</div>',
135 + ];
136 +
137 + return Template::combine_components( $section );
138 + }
139 +
140 + public function html_tabs( array $data = [] ): string {
141 + $section_tab = [
142 + 'tabs_wrap' => '<div class="lp-cb-tabs">',
143 + 'tabs' => '',
144 + 'tabs_end' => '</div>',
145 + ];
146 +
147 + $section_content = [
148 + 'wrap' => '<div class="lp-cb-tab-content">',
149 + 'content' => '',
150 + 'wrap-end' => '</div>',
151 + ];
152 +
153 + $tabs = apply_filters(
154 + 'learn-press/course-builder/lessons/edit/tabs',
155 + [
156 + 'overview' => [
157 + 'title' => esc_html__( 'Overview', 'learnpress' ),
158 + 'html' => $this->html_tab_overview( $data ),
159 + ],
160 + 'settings' => [
161 + 'title' => esc_html__( 'Settings', 'learnpress' ),
162 + 'html' => $this->html_tab_settings( $data ),
163 + ],
164 + ],
165 + $data
166 + );
167 +
168 + $tab_active = array_key_first( $tabs );
169 + if ( isset( $_GET['tab'] ) && isset( $tabs[ $_GET['tab'] ] ) ) {
170 + $tab_active = $_GET['tab'];
171 + }
172 +
173 + foreach ( $tabs as $key => $tab ) {
174 + $is_active = $key === $tab_active;
175 +
176 + $section_tab['tabs'] .= sprintf(
177 + '<a href="#" class="lp-cb-tabs__item %s" data-tab-section="%s">%s</a>',
178 + $is_active ? 'is-active' : '',
179 + esc_attr( $tab['slug'] ?? $key ),
180 + esc_html( $tab['title'] ?? '' )
181 + );
182 +
183 + $section_content['content'] .= sprintf(
184 + '<div class="lp-cb-tab-panel %s" data-section="%s">%s</div>',
185 + $is_active ? '' : 'lp-hidden',
186 + esc_attr( $tab['slug'] ?? $key ),
187 + $tab['html'] ?? ''
188 + );
189 + }
190 +
191 + return Template::combine_components(
192 + [
193 + 'tabs' => Template::combine_components( $section_tab ),
194 + 'contents' => Template::combine_components( $section_content ),
195 + ]
196 + );
197 + }
198 +
199 + public function html_tab_overview( array $data = [] ): string {
200 + wp_enqueue_script( 'lp-course-builder' );
201 +
202 + $lesson_model = $data['lessonModel'] ?? false;
203 + $lesson_id = $data['item_id'] ?? ( $lesson_model ? $lesson_model->get_id() : CourseBuilder::POST_NEW );
204 +
205 + if ( absint( $lesson_id ) && ! $lesson_model ) {
206 + $lesson_model = LessonPostModel::find( absint( $lesson_id ), true );
207 + if ( empty( $lesson_model ) ) {
208 + return '';
209 + }
210 + }
211 +
212 + $html_assigned = $this->assigned_course( $lesson_model );
213 + $html_edit_title = $this->edit_title( $lesson_model );
214 + $html_permalink = $this->edit_permalink( $lesson_model );
215 + $html_edit_desc = $this->edit_desc( $lesson_model );
216 + $section = [
217 + 'wrapper' => sprintf( '<div class="cb-section__lesson-edit" data-lesson-id="%s">', $lesson_id ),
218 + 'edit_title' => $html_edit_title,
219 + 'wrapper_title_assigned' => '<div class="cb-section__lesson-title-assigned">',
220 + 'assigned_course' => $html_assigned,
221 + 'wrapper_title_assigned_end' => '</div>',
222 + 'edit_permalink' => $html_permalink,
223 + 'edit_desc' => $html_edit_desc,
224 + 'wrapper_end' => '</div>',
225 + ];
226 +
227 + return Template::combine_components( $section );
228 + }
229 +
230 + public function html_tab_settings( array $data = [] ): string {
231 + $lesson_model = $data['lessonModel'] ?? false;
232 + $lesson_id = $data['item_id'] ?? ( $lesson_model ? $lesson_model->get_id() : CourseBuilder::POST_NEW );
233 +
234 + if ( $lesson_id === CourseBuilder::POST_NEW || absint( $lesson_id ) <= 0 ) {
235 + return sprintf( '<span class="lp-message lp-message--info">%s</span>', __( 'Please save Lesson before setting lesson', 'learnpress' ) );
236 + }
237 +
238 + if ( ! $lesson_model ) {
239 + $lesson_model = LessonPostModel::find( absint( $lesson_id ), true );
240 + if ( empty( $lesson_model ) ) {
241 + return '';
242 + }
243 + }
244 +
245 + if ( ! class_exists( 'LP_Meta_Box_Lesson' ) ) {
246 + require_once LP_PLUGIN_PATH . 'inc/admin/views/meta-boxes/lesson/settings.php';
247 + }
248 +
249 + $metabox = new \LP_Meta_Box_Lesson();
250 + ob_start();
251 + $metabox->output( $lesson_model );
252 + $settings = ob_get_clean();
253 +
254 + $output = [
255 + 'wrapper' => sprintf( '<div class="cb-section__lesson-edit" data-lesson-id="%s">', $lesson_id ),
256 + 'form_setting' => '<form name="lp-form-setting-lesson" class="lp-form-setting-lesson" method="post" enctype="multipart/form-data">',
257 + 'settings' => $settings,
258 + 'form_setting_end' => '</form>',
259 + 'wrapper_end' => '</div>',
260 + ];
261 +
262 + return Template::combine_components( $output );
263 + }
264 +
265 + /**
266 + * Allow callback for AJAX.
267 + * @use self::render_edit_course_curriculum
268 + * @use self::render_html
269 + *
270 + * @param array $callbacks
271 + *
272 + * @return array
273 + */
274 + public function allow_callback( array $callbacks ): array {
275 + $callbacks[] = AdminEditCurriculumTemplate::class . ':render_edit_course_curriculum';
276 +
277 + return $callbacks;
278 + }
279 +
280 + public function assigned_course( $lesson_model ) {
281 + $assign_course = ! empty( $lesson_model ) ? $this->get_assigned( $lesson_model->get_id() ) : '';
282 + $html_courses = '';
283 + $assigned = sprintf( '<span class="lesson-not-assigned">%s</span>', __( 'Not assigned yet', 'learnpress' ) );
284 + if ( ! empty( $assign_course ) ) {
285 + $courses = is_array( $assign_course ) && isset( $assign_course['id'] )
286 + ? array( $assign_course )
287 + : $assign_course;
288 +
289 + $course_htmls = array();
290 + foreach ( $courses as $course ) {
291 + $course_id = $course['id'] ?? 0;
292 + $course_title = $course['title'] ?? '';
293 +
294 + if ( $course_id && $course_title ) {
295 + $course_link = BuilderCourseTemplate::instance()->get_link_edit( $course_id );
296 + $course_htmls[] = sprintf(
297 + '<a href="%s" target="_blank">%s</a>',
298 + esc_url( $course_link ),
299 + esc_html( $course_title )
300 + );
301 + }
302 + }
303 +
304 + if ( ! empty( $course_htmls ) ) {
305 + $assigned = implode( ', ', $course_htmls );
306 + }
307 + }
308 +
309 + $html_courses = sprintf(
310 + '<div class="cb-item-edit-assigned lesson-assigned-courses"><span class="label">%s</span> %s</div>',
311 + __( 'Assigned', 'learnpress' ),
312 + $assigned
313 + );
314 +
315 + return $html_courses;
316 + }
317 +
318 + public function edit_permalink( $lesson_model ): string {
319 + $post_id = ! empty( $lesson_model ) ? absint( $lesson_model->get_id() ) : 0;
320 + $post = $post_id ? get_post( $post_id ) : null;
321 + $post_name = $post && ! empty( $post->post_name ) ? (string) $post->post_name : '';
322 + $full_url = '';
323 + $base_url = '';
324 + $display_classes = 'cb-permalink-display';
325 + $placeholder_class = 'cb-item-edit-permalink__placeholder';
326 + $notice_no_link = __(
327 + 'Permalink is only available if the item is already assigned to a course.',
328 + 'learnpress'
329 + );
330 + $placeholder_text = __( 'Permalink will be available after saving.', 'learnpress' );
331 + $show_unavailable = true;
332 +
333 + if ( $post_id ) {
334 + $current_status = $post && ! empty( $post->post_status ) ? sanitize_key( $post->post_status ) : '';
335 + if ( 'draft' !== $current_status ) {
336 + $course_id_of_item = \LP_Course_DB::getInstance()->get_course_by_item_id( $post_id );
337 + if ( $course_id_of_item ) {
338 + $course = learn_press_get_course( $course_id_of_item );
339 + if ( $course ) {
340 + $full_url = urldecode( $course->get_item_link( $post_id ) );
341 + $base_url = $full_url;
342 + $show_unavailable = false;
343 +
344 + if ( ! empty( $post_name ) ) {
345 + $base_url = trailingslashit( preg_replace( '/' . preg_quote( $post_name, '/' ) . '\/?$/', '', $full_url ) );
346 + }
347 + }
348 + }
349 + }
350 + }
351 +
352 + if ( $show_unavailable && $post_id ) {
353 + $placeholder_text = $notice_no_link;
354 + }
355 +
356 + if ( $show_unavailable ) {
357 + $display_classes .= ' lp-hidden';
358 + } else {
359 + $placeholder_class .= ' lp-hidden';
360 + }
361 +
362 + $state_a = sprintf(
363 + '<span class="cb-item-edit-permalink__label">%s</span>
364 + <div class="%s">
365 + <a href="%s" target="_blank" class="cb-permalink-url">%s</a>
366 + <button type="button" class="cb-permalink-edit-btn" title="%s">
367 + <span class="dashicons dashicons-edit"></span>
368 + </button>
369 + </div>',
370 + __( 'Permalink', 'learnpress' ),
371 + esc_attr( $display_classes ),
372 + esc_url( $full_url ),
373 + esc_html( $full_url ),
374 + __( 'Edit', 'learnpress' )
375 + );
376 +
377 + $state_b = sprintf(
378 + '<div class="cb-permalink-editor lp-hidden">
379 + <span class="cb-permalink-prefix">%s</span>
380 + <div class="cb-permalink-input-row">
381 + <input type="text" name="lesson_permalink" id="lesson_permalink" value="%s" class="cb-permalink-slug-input" placeholder="%s">
382 + <div class="cb-permalink-actions">
383 + <button type="button" class="cb-permalink-ok-btn">%s</button>
384 + <button type="button" class="cb-permalink-cancel-btn">%s</button>
385 + </div>
386 + </div>
387 + </div>',
388 + esc_html( $base_url ),
389 + esc_attr( $post_name ),
390 + esc_attr__( 'your-slug', 'learnpress' ),
391 + __( 'OK', 'learnpress' ),
392 + __( 'Cancel', 'learnpress' )
393 + );
394 +
395 + $hidden_base = sprintf(
396 + '<input type="hidden" id="cb-permalink-base-url" value="%s">',
397 + esc_attr( $base_url )
398 + );
399 +
400 + $placeholder = sprintf(
401 + '<span class="%s">%s</span>',
402 + esc_attr( $placeholder_class ),
403 + esc_html( $placeholder_text )
404 + );
405 +
406 + $view = [
407 + 'wrapper' => '<div class="cb-item-edit-permalink cb-course-edit-permalink">',
408 + 'state_a' => $state_a,
409 + 'state_b' => $state_b,
410 + 'hidden_base' => $hidden_base,
411 + 'placeholder' => $placeholder,
412 + 'wrapper_end' => '</div>',
413 + ];
414 +
415 + return Template::combine_components( $view );
416 + }
417 +
418 + public function edit_title( $lesson_model ) {
419 + $title = ! empty( $lesson_model ) ? $lesson_model->get_the_title() : '';
420 + $edit = [
421 + 'wrapper' => '<div class="cb-lesson-edit-title">',
422 + 'label' => sprintf( '<label for="title" class="cb-lesson-edit-title__label">%s</label>', __( 'Title', 'learnpress' ) ),
423 + 'input' => sprintf( '<input type="text" name="lesson_title" size="30" value="%s" id="title" class="cb-lesson-edit-title__input">', esc_attr( $title ) ),
424 + 'wrapper_end' => '</div>',
425 + ];
426 +
427 + return Template::combine_components( $edit );
428 + }
429 +
430 + /**
431 + * @param LessonPostModel $lesson_model
432 + * @return string
433 + */
434 + public function edit_desc( $lesson_model ) {
435 + $desc = ! empty( $lesson_model ) ? $lesson_model->post_content : '';
436 + $editor_id = 'lesson_description_editor';
437 + $editor_settings = array(
438 + 'textarea_name' => 'lesson_description',
439 + 'textarea_rows' => 10,
440 + 'teeny' => false,
441 + 'media_buttons' => true,
442 + 'tinymce' => array(
443 + 'content_style' => "body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif; font-size: 14px; line-height: 1.6; color: #1e1e1e; }",
444 + 'toolbar1' => 'formatselect,bold,italic,underline,bullist,numlist,blockquote,alignleft,aligncenter,alignright,link,unlink,spellchecker,wp_adv',
445 + 'toolbar2' => 'strikethrough,hr,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help',
446 + ),
447 + 'quicktags' => true,
448 + );
449 +
450 + ob_start();
451 + wp_editor( $desc, $editor_id, $editor_settings );
452 + $editor_html = ob_get_clean();
453 +
454 + $edit = [
455 + 'wrapper' => '<div class="cb-lesson-edit-desc">',
456 + 'label' => sprintf( '<label for="lesson_description" class="cb-lesson-edit-desc__label">%s</label>', __( 'Description', 'learnpress' ) ),
457 + 'edit' => $editor_html,
458 + 'wrapper_end' => '</div>',
459 + ];
460 +
461 + return Template::combine_components( $edit );
462 + }
463 +
464 + public function get_assigned( $id ) {
465 + $courses = learn_press_get_item_courses( $id );
466 +
467 + if ( empty( $courses ) ) {
468 + return array();
469 + }
470 +
471 + return array(
472 + 'id' => $courses[0]->ID,
473 + 'title' => $courses[0]->post_title ?? '',
474 + );
475 + }
476 +}