Alert: This function’s access is marked private. This means it is not intended for use by plugin or theme developers, only in other core functions. It is listed here for completeness.

LLMS_Admin_Builder::update_lessons( array $lessons, LLMS_Section $section, int $course_id )

Update lesson from heartbeat data.


Parameters Parameters

$lessons

(array) (Required) Lesson data from heartbeat.

$section

(LLMS_Section) (Required) Instance of the parent LLMS_Section.

$course_id

(int) (Required) WP_Post ID of the authorized builder course.


Top ↑

Return Return

(array)


Top ↑

Source Source

File: includes/admin/class.llms.admin.builder.php

	private static function update_lessons( $lessons, $section, $course_id = 0 ) {

		$ret = array();

		/**
		 * Resolve the course these lessons must belong to and confirm the current user can edit it.
		 *
		 * Authorizing the target relationship here keeps the method self-contained rather than
		 * relying solely on a permission check performed earlier in the heartbeat request.
		 */
		$authorized_course_id = $course_id ? absint( $course_id ) : absint( $section->get( 'parent_course' ) );
		$can_edit_course      = ! $authorized_course_id || current_user_can( 'edit_course', $authorized_course_id );

		foreach ( $lessons as $lesson_data ) {

			if ( ! isset( $lesson_data['id'] ) ) {
				continue;
			}

			$res = array_merge(
				$lesson_data,
				array(
					'orig_id' => $lesson_data['id'],
				)
			);

			if ( ! $can_edit_course ) {
				// Translators: %s = Lesson post id.
				$res['error'] = sprintf( esc_html__( 'Unable to update lesson "%s". You are not allowed to edit the parent course.', 'lifterlms' ), $lesson_data['id'] );
				array_push( $ret, $res );
				continue;
			}

			// Create a new lesson.
			if ( self::is_temp_id( $lesson_data['id'] ) ) {

				$lesson = new LLMS_Lesson(
					'new',
					array(
						'post_title' => isset( $lesson_data['title'] ) ? $lesson_data['title'] : __( 'New Lesson', 'lifterlms' ),
					)
				);

				$created = true;

			} else {

				$lesson  = llms_get_post( $lesson_data['id'] );
				$created = false;

				// Verify the lesson belongs to this course.
				if ( $course_id && $lesson && is_a( $lesson, 'LLMS_Lesson' ) ) {
					$parent = self::get_object_parent_course_id( $lesson->get( 'id' ) );
					if ( $parent && absint( $parent ) !== absint( $course_id ) ) {
						// Translators: %s = Lesson post id.
						$res['error'] = sprintf( esc_html__( 'Unable to update lesson "%s". Invalid lesson ID.', 'lifterlms' ), $lesson_data['id'] );
						array_push( $ret, $res );
						continue;
					}
					if ( ! $parent && ! current_user_can( 'edit_post', $lesson->get( 'id' ) ) ) {
						$res['error'] = sprintf( esc_html__( 'Unable to update lesson "%s". Invalid lesson ID.', 'lifterlms' ), $lesson_data['id'] );
						array_push( $ret, $res );
						continue;
					}
				}
			}

			if ( empty( $lesson ) || ! is_a( $lesson, 'LLMS_Lesson' ) ) {

				// Translators: %s = Lesson post id.
				$res['error'] = sprintf( esc_html__( 'Unable to update lesson "%s". Invalid lesson ID.', 'lifterlms' ), $lesson_data['id'] );

			} else {

				// Don't create useless revision on "creating".
				add_filter( 'wp_revisions_to_keep', '__return_zero', 999 );

				// Return the real ID (important when creating a new lesson).
				$res['id'] = $lesson->get( 'id' );

				$properties = array_merge(
					array_keys( $lesson->get_properties() ),
					array(
						'content',
						'title',
					)
				);

				$skip_props = apply_filters( 'llms_builder_update_lesson_skip_props', array( 'quiz' ) );

				/**
				 * Never trust client-supplied parent relationships.
				 *
				 * A lesson saved through the builder must belong to the authorized course and
				 * one of its sections. These props are skipped in the generic update loop and
				 * set explicitly below to prevent injecting or moving a lesson into a course
				 * the current user is not authorized to edit.
				 */
				$skip_props[] = 'parent_course';
				$skip_props[] = 'parent_section';

				// Don't overwrite content if the content editor doesn't display.
				if ( ! $created && '' !== $lesson->get( 'content' ) && ! llms_parse_bool( $lesson->get( 'content_added_in_builder' ) ) ) {
					$skip_props[] = 'content';
				}

				if ( '' === $lesson->get( 'content' ) && isset( $lesson_data['content'] ) && '' !== $lesson_data['content']
					&& ! isset( $lesson_data['content_added_in_builder'] ) ) {
					// We're adding content via the builder for the first time; add a flag saying so.
					$lesson_data['content_added_in_builder'] = 'yes';
				}

				// Update all updatable properties.
				foreach ( $properties as $prop ) {
					if ( isset( $lesson_data[ $prop ] ) && ! in_array( $prop, $skip_props, true ) ) {
						$lesson->set( $prop, $lesson_data[ $prop ] );
					}
				}

				// Force the lesson into the authorized course and section.
				$lesson->set( 'parent_section', $section->get( 'id' ) );
				if ( $authorized_course_id ) {
					$lesson->set( 'parent_course', $authorized_course_id );
				}
				$res['parent_section'] = $lesson->get( 'parent_section' );
				$res['parent_course']  = $lesson->get( 'parent_course' );

				// Update all custom fields.
				self::update_custom_schemas( 'lesson', $lesson, $lesson_data );

				// During clone's we want to ensure custom field data comes with the lesson.
				if ( $created && isset( $lesson_data['custom'] ) ) {
					foreach ( $lesson_data['custom'] as $custom_key => $custom_vals ) {
						foreach ( $custom_vals as $val ) {
							add_post_meta( $lesson->get( 'id' ), $custom_key, maybe_unserialize( $val ) );
						}
					}
				}

				// Ensure slug gets updated when changing title from default "New Lesson".
				if ( isset( $lesson_data['title'] ) && ! $lesson->has_modified_slug() ) {
					$lesson->set( 'name', sanitize_title( $lesson_data['title'] ) );
				}

				// Include permalink, slug, and editor type in the response so the builder can update the model.
				$res['permalink']                = get_permalink( $lesson->get( 'id' ) );
				$res['name']                     = $lesson->get( 'name' );
				$res['content_added_in_builder'] = $lesson->get( 'content_added_in_builder' );

				// Remove revision prevention.
				remove_filter( 'wp_revisions_to_keep', '__return_zero', 999 );

				if ( ! empty( $lesson_data['quiz'] ) && is_array( $lesson_data['quiz'] ) ) {
					$res['quiz'] = self::update_quiz( $lesson_data['quiz'], $lesson, $course_id );
				}
			}

			// Allow 3rd parties to update custom data.
			$res = apply_filters( 'llms_builder_update_lesson', $res, $lesson_data, $lesson, $created );

			array_push( $ret, $res );

		}

		return $ret;
	}


Top ↑

Changelog Changelog

Changelog
Version Description
7.3.0 Skip revision creation when creating a brand new lesson.
5.1.3 Made sure a lesson moved in a just created section is correctly assigned to it.
3.16.0 Introduced.

Top ↑

User Contributed Notes User Contributed Notes

You must log in before being able to contribute a note or feedback.