Forum Replies Created

Viewing 3 replies - 1 through 3 (of 3 total)
  • Thread Starter shiftlessatol

    (@shiftlessatol)

    Still doesn’t work on Latest Version ( May 28th, 2018) | Version 2.2.0 |
    I’m including the updated file below

    wp-content/plugins/coursepress/2.0/include/coursepress/template/class-module.php

    <?php
    /**
     * Use to print the different modules.
     *
     * @package WordPress
     * @subpackage CoursePress
     **/
    class CoursePress_Template_Module {
    	private static $args = array();
    
    	protected static $student_progress = array();
    
    	/**
    	 * Helper function get module attributes.
    	 **/
    	protected static function attributes( $module_id ) {
    		return CoursePress_Data_Module::attributes( $module_id );
    	}
    
    	/**
    	 * Helper function to quickly retrieve student response
    	 **/
    	protected static function get_response( $module_id, $student_id, $all = false ) {
    		$unit_id = get_post_field( 'post_parent', $module_id );
    		$course_id = get_post_field( 'post_parent', $unit_id );
    
    		$response = CoursePress_Data_Student::get_response( $student_id, $course_id, $unit_id, $module_id );
    
    		if ( false === $all && isset( $response['response'] ) ) {
    			$response = $response['response'];
    		}
    
    		return $response;
    	}
    
    	public static function get_student_answer( $module_id, $student_id ) {
    		$attributes = self::attributes( $module_id );
    		$module_type = $attributes['module_type'];
    		$unit_id = get_post_field( 'post_parent', $module_id );
    		$course_id = get_post_field( 'post_parent', $unit_id );
    		$content = '';
    		$response = self::get_response( $module_id, $student_id );
    
    		switch ( $module_type ) {
    			case 'input-checkbox': case 'input-radio': case 'input-select':
    						$answers = $attributes['answers'];
    						$selected = $attributes['answers_selected'];
    						$content .= '<ul class="cp-answers">';
    
    						// $selected is of string type, change it to int
    						$ints = array_fill( 0, 10, true );
    
    						if ( ! is_array( $selected ) && ! empty( $ints[ $selected ] ) ) {
    							$selected = (int) $selected;
    						}
    
    						foreach ( $answers as $key => $answer ) {
    							if ( 'input-checkbox' !== $module_type ) {
    								$the_answer = $selected === $key || $selected === $answer;
    								$student_answer = $response == $key || $response === $answer;
    							} else {
    								$the_answer = in_array( $key, $selected );
    								$student_answer = is_array( $response ) ? in_array( $key, $response ) : $response == $key;
    							}
    
    							if ( $student_answer ) {
    								if ( $the_answer ) {
    									$answer = '<span class="chosen-answer correct"></span>' . $answer;
    								} else {
    									$answer = '<span class="chosen-answer incorrect"></span>' . $answer;
    								}
    								$content .= sprintf( '<li>%s</li>', $answer );
    							}
    						}
    						$content .= '</ul>';
    
    				break;
    			case 'input-textarea': case 'input-text':
    					if ( ! empty( $response ) ) {
    						$content .= sprintf( '<div class="cp-answer-box">%s</div>', $response );
    					}
    				break;
    
    			case 'input-upload':
    				if ( ! empty( $response['url'] ) ) {
    					$url = $response['url'];
    					$filename = basename( $url );
    					$url = CoursePress_Helper_Utility::encode( $url );
    					$url = trailingslashit( home_url() ) . '?fdcpf=' . $url;
    
    					$content .= sprintf( '<a href="%s" class="button-primary cp-download">%s</a>', esc_url( $url ), $filename );
    				}
    				break;
    
    			case 'input-quiz':
    				if ( is_admin() ) {
    					if ( ! empty( $attributes['questions'] ) ) {
    						$questions = $attributes['questions'];
    
    						foreach ( $questions as $q_index => $question ) {
    							$options = (array) $question['options'];
    							$checked = (array) $options['checked'];
    							$checked = array_filter( $checked );
    							$student_response = $response[ $q_index ];
    
    							$content .= sprintf( '<div class="cp-q"><hr /><p class="description cp-question">%s</p><ul>', esc_html( $question['question'] ) );
    
    							foreach ( $options['answers'] as $p_index => $answer ) {
    								$the_answer = isset( $checked[ $p_index ] ) ? $checked[ $p_index ] : false;
    								$student_answer = '';
    
    								if ( isset( $student_response[ $p_index ] ) && $student_response[ $p_index ] ) {
    									$student_answer = $student_response[ $p_index ];
    
    									if ( $the_answer ) {
    										$student_answer = '<span class="chosen-answer correct"></span>';
    									} else {
    										$student_answer = '<span class="chosen-answer incorrect"></span>';
    									}
    									$content .= '<li>' . $student_answer . esc_html( $answer ) . '</li>';
    								}
    							}
    							$content .= '</ul></div>';
    
    						}
    					}
    				} else {
    					$content .= self::quiz_result_content( $student_id, $course_id, $unit_id, $module_id );
    				}
    				break;
    
    			case 'input-form':
    				if ( ! empty( $attributes['questions'] ) ) {
    					$questions = $attributes['questions'];
    
    					foreach ( $questions as $q_index => $question ) {
    						$student_response = ! empty( $response[ $q_index ] ) ? $response[ $q_index ] : '';
    						$format = '<div class="cp-q"><hr /><p class="description cp-question">%s</p>';
    						$content .= sprintf( $format, esc_html( $question['question'] ) );
    						$content .= '<ul>';
    
    						if ( 'selectable' == $question['type'] ) {
    							$options = $question['options']['answers'];
    							$checked = $question['options']['checked'];
    
    							foreach ( $options as $ai => $answer ) {
    								if ( $student_response == $ai ) {
    									$the_answer = ! empty( $checked[ $ai ] );
    
    									if ( $the_answer === $student_response ) {
    										$student_answer = '<span class="chosen-answer correct"></span>';
    									} else {
    										$student_answer = '<span class="chosen-answer incorrect"></span>';
    									}
    									$content .= sprintf( '<li>%s %s</li>', $student_answer, $answer );
    								}
    							}
    						} else {
    							$content .= sprintf( '<li>%s</li>', esc_html( $student_response ) );
    						}
    						$content .= '</ul></div>';
    					}
    				}
    				break;
    		}
    
    		/**
    		 * Filter the student response template.
    		 **/
    		$content = apply_filters( 'coursepress_student_reponse_template', $content, $module_id, $module_type );
    
    		return $content;
    	}
    
    	public static function get_module_status( $module_id, $student_id ) {
    		$attributes = self::attributes( $module_id );
    		$module_type = $attributes['module_type'];
    		$assessables = array( 'input-text', 'input-textarea', 'input-upload', 'input-form' );
    		$response = self::get_response( $module_id, $student_id, true );
    		$grades = (array) CoursePress_Helper_Utility::get_array_val( $response, 'grades' );
    		$grades = array_pop( $grades );
    		$grade = (int) CoursePress_Helper_Utility::get_array_val( $grades, 'grade' );
    		$minimum_grade = (int) $attributes['minimum_grade'];
    		$require_assessment = false;
    		$pass = $grade >= $minimum_grade;
    		$status = '';
    
    		if ( in_array( $module_type, $assessables ) ) {
    			if ( ! empty( $attributes['assessable'] ) ) {
    				$graded_by = CoursePress_Helper_Utility::get_array_val( $grades, 'graded_by' );
    				if ( 'auto' === $graded_by || empty( $grades ) ) {
    					$status = __( 'Pending', 'coursepress' );
    				} elseif ( $pass ) {
    					$status = __( 'Pass', 'coursepress' );
    				} else {
    				    $status = __( 'Failed', 'coursepress' );
    				}
    			} else {
    				$status = __( 'Non Gradable', 'coursepress' );
    			}
    		} else {
    			$status = $pass ? __( 'Pass', 'coursepress' ) : __( 'Fail', 'coursepress' );
    		}
    
    		return $status;
    	}
    
    	/**
    	 *
    	 * @param integer $module_id Modile ID.
    	 * @param boolean $is_focus Is in focus mode?
    	 * @param string $view_type View type, possible values "normal", "preview" @since 2.0.4
    	 */
    	public static function template( $module_id = 0, $is_focus = false, $view_type = 'normal' ) {
    		if ( empty( $module_id ) ) {
    			return ''; // Nothing to process, bail!
    		}
    
    		$attributes = self::attributes( $module_id );
    		$module_type = $attributes['module_type'];
    		$is_required = ! empty( $attributes['mandatory'] );
    		$method = 'render_' . str_replace( '-', '_', $module_type );
    		$module = get_post( $module_id );
    		$unit_id = $module->post_parent;
    		$course_id = get_post_field( 'post_parent', $unit_id );
    		$course_status = CoursePress_Data_Course::get_course_status( $course_id );
    		$is_module_answerable = preg_match( '%input-%', $module_type ) || 'video' === $module_type;
    		$disabled = false;
    		$element_class = array();
    		$student_id = get_current_user_id();
    		$content = '<div class="module-container">';
    
    		/**
    		 * Fire before the module template is printed
    		 *
    		 * @since 2.0
    		 *
    		 * @param (int) $module_id			The WP_Post object ID.
    		 * @param (int) $student_id			Current user ID.
    		 **/
    		do_action( 'coursepress_module_view', $module_id, $student_id );
    
    		// Marked module and page as visited
    		$module_page = get_post_meta( $module_id, 'module_page', true );
    		CoursePress_Data_Student::visited_module( $student_id, $course_id, $unit_id, $module_id );
    		CoursePress_Data_Student::visited_page( $student_id, $course_id, $unit_id, $module_page );
    
    		$content .= sprintf( '<input type="hidden" name="course_id" value="%s" />', $course_id );
    		$content .= sprintf( '<input type="hidden" name="unit_id" value="%s" />', $unit_id );
    		$content .= sprintf( '<input type="hidden" name="student_id" value="%s" />', $student_id );
    		$content .= sprintf( '<input type="hidden" name="module_id[]" value="%s" />', $module_id );
    
    		if ( $is_focus ) {
    			$content .= wp_nonce_field( 'coursepress_submit_modules', '_wpnonce', true, false );
    			$content .= sprintf( '<div class="cp-error">%s</div>', apply_filters( 'coursepress_before_unit_modules', '' ) );
    		}
    
    		// Module header
    		$content .= self::render_module_head( $module, $attributes );
    		// The question or text content
    		$content .= self::_wrap_content( $module->post_content );
    
    		if ( method_exists( __CLASS__, $method ) ) {
    			// Get student progress if it is not retrieve yet
    			if ( empty( self::$student_progress ) ) {
    				$student_progress = self::$student_progress = CoursePress_Data_Student::get_completion_data( $student_id, $course_id );
    			} else {
    				$student_progress = self::$student_progress;
    			}
    
    			// Record module visit
    			CoursePress_Data_Student::visited_module( $student_id, $course_id, $unit_id, $module_id, self::$student_progress );
    
    			$retry = 'TRY';
    			$element_class = array( 'module-elements' );
    			if ( $is_module_answerable ) {
    				$responses = CoursePress_Data_Student::get_responses( $student_id, $course_id, $unit_id, $module_id, true, $student_progress );
    				$last_response = self::get_response( $module_id, $student_id );
    				if ( ! empty( $responses ) ) {
    					$element_class[] = 'hide';
    				}
    
    				// Set value to 1 only if not attempted this module.
    				$is_module_hidden = empty( $responses ) ? 0 : 1;
    				// Add a hidden field to track if student really submitted the form.
    				$content .= sprintf( '<input type="hidden" class="cp-is-hidden-module" name="is_module_hidden[%s]" value="%s" />', $module_id, $is_module_hidden );
    
    				$response_count = ! empty( $responses ) ? count( $responses ) : 0;
    
    				// Get recorded time lapsed
    				$keys = array( $course_id, $unit_id, $module_id, $student_id );
    				$key = 'response_' . implode( '_', $keys );
    				$lapses = (int) get_user_meta( $student_id, $key, true );
    				$response_count += $lapses;
    
    				$try_again_label = __( 'Try Again', 'coursepress' );
    
    				switch ( $module_type ) {
    					case 'input-upload':
    						$try_again_label = __( 'Upload a different file', 'coursepress' );
    					break;
    				}
    				$retry = sprintf( '<p class="cp-try-again"><a data-module="%s" onclick="javascript:ShowQuiz(%s);" class="button module-submit-action button-reload-module">%s</a></p>', $module_id,$module_id, $try_again_label );
    
    				// Check if retry is disabled
    				if ( empty( $attributes['allow_retries'] ) ) {
    					$retry = '';
    				} elseif ( ! empty( $attributes['retry_attempts'] ) && 0 < $response_count ) {
    					$attempts = (int) $attributes['retry_attempts'];
    
    					// Retries + 1 normal attempt.
    					if ( $response_count > $attempts ) {
    						$disabled = true;
    						$retry = '';
    					} else {
    						$retry .= sprintf(
    							'<p class="number-of-fails">%s</p>',
    							sprintf( __( 'Number of failed attempts: %d', 'coursepress' ), $response_count )
    						);
    					}
    				}
    
    				if ( ! empty( $attributes['use_timer'] ) && ! empty( $attributes['duration'] ) ) {
    					$allow_retry = true;
    					$attempts = (int) $attributes['retry_attempts'];
    					$duration = $attributes['duration'];
    					$dur = explode( ':', $duration );
    					/**
    					 * sanitize time format
    					 */
    					switch ( sizeof( $dur ) ) {
    						case 1:
    							$duration = sprintf( '00:%02d', $dur[0] );
    						break;
    						case 2:
    							$duration = sprintf( '%02d:%02d', $dur[0], $dur[1] );
    						break;
    						case 3:
    							$duration = sprintf( '%02d:%02d:%02d', $dur[0], $dur[1], $dur[2] );
    						break;
    					}
    
    					$format = '<span class="quiz_timer" data-limit="%1$s" data-retry="%2$s">%1$s</span><span class="quiz_timer_info">%3$s</span>';
    
    					if ( empty( $retry ) ) {
    						$attempts = 'no';
    						if ( $response_count > 0 ) {
    							$duration = '00:00:00';
    						}
    					}
    
    					$timer_info = __( 'Session Expired', 'coursepress' ) . $retry;
    					$content .= sprintf( $format, $duration, $attempts, $timer_info );
    				}
    			}
    
    			if ( 'closed' == $course_status ) {
    				$disabled = true;
    				$retry = '';
    			}
    
    			$disabled_attr = $disabled ? 'disabled="disabled"' : '';
    			$module_elements = call_user_func( array( __CLASS__, $method ), $module, $attributes, $student_progress );
    			if ( $is_module_answerable && 'preview' == $view_type  ) {
    				$module_elements = '';
    			}
    
    			switch ( $module_type ) {
    				case 'input-quiz';
    					$module_elements = sprintf( '<div class="module-quiz-questions">%s</div>', $module_elements );
    					break;
    			}
    
    			$element_class[] = sprintf( 'module-type-%s', $module_type );
    
    			$module_elements = sprintf( '<div id="cp-element-%s" class="%s" data-type="%s" data-required="%s">%s</div>', $module_id, implode( ' ', $element_class ), $module_type, $is_required, $module_elements );
    
    			if ( $is_module_answerable && ! empty( $responses ) ) {
    
    				$status = self::get_module_status( $module->ID, $student_id );
    
    				if ( 'Pass' == $status ) {
    					$retry = '';
    				}
    
    				$student_answers = sprintf( '<span class="cp-status status-%s">%s</span>', strtolower( $status ), $status );
    				$student_answers = sprintf( '<div class="cp-student-status">%s</div>', $student_answers );
    				$student_answers .= self::get_student_answer( $module->ID, $student_id );
    				$student_answers .= $retry;
    
    				$module_elements .= sprintf( '<div id="cp-response-%s" class="module-response">%s</div>', $module_id, $student_answers );
    			}
    
    			if ( 'closed' == $course_status ) {
    				$format = '<div class="module-warnings"><p>%s</p></div>';
    				$module_warning = sprintf( $format, esc_html__( 'This course is completed, you can not submit answers anymore.', 'coursepress' ) );
    
    				/**
    				 * Filter the warning message.
    				 *
    				 * @since 2.0
    				 **/
    				$module_elements .= apply_filters( 'coursepress_course_readonly_message', $module_warning, $module_id, $course_id );
    			}
    
    			/**
    			 * custom wrappers
    			 */
    			switch ( $module_type ) {
    				case 'discussion':
    					$module_elements = sprintf( '<div id="comments" class="comments-area"><div class="comments-list-container">%s</div></div>', $module_elements );
    					break;
    			}
    
    			/**
    			 * Filter the module elements template.
    			 *
    			 * @since 2.0
    			 **/
    			$content .= apply_filters( 'coursepress_module_template', $module_elements, $module_type, $module_id );
    
    			/**
    			 * Filter the module container classes
    			 *
    			 * @since 2.0.6
    			 **/
    			$module_container_classes = apply_filters( 'coursepress_module_container_classes', array( 'cp-module-content' ), $module_type, $module_id );
    
    			$content = sprintf(
    				'<div class="%4$s" data-type="%1$s" data-id="%2$s" id="cp-module-%2$s">%3$s</div>',
    				esc_attr( $module_type ),
    				esc_attr( $module_id ),
    				$content,
    				esc_attr( implode( ' ', $module_container_classes ) )
    			);
    		}
    		/**
    		 * div.module-container
    		 */
    		$content .= '</div>';
    		return $content;
    	}
    
    	/**
    	 * Module header
    	 **/
    	private static function render_module_head( $module, $attributes = false ) {
    		if ( false === $module || empty( $module ) ) {
    			return; // Bail
    		}
    
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$content = '';
    
    		$show_title = ! empty( $attributes['show_title'] );
    		$mandatory = ! empty( $attributes['mandatory'] );
    
    		if ( $show_title ) {
    			$content .= '<h4 class="module-title">';
    			$content .= $module->post_title;
    			if ( $mandatory ) {
    				$content .= sprintf( '<span class="is-mandatory">%s</span>', __( 'Required', 'coursepress' ) );
    			}
    			$content .= '</h4>';
    		} else if ( $mandatory ) {
    			$content .= sprintf( '<div class="is-mandatory">%s</div>', __( 'Required', 'coursepress' ) );
    		}
    		$format = '<div class="module-header module %1$s module-%2$s %3$s" data-type="%1$s" data-module="%2$s">%4$s</div>';
    		$content = sprintf( $format, $attributes['module_type'], $module->ID, $attributes['mode'], $content );
    
    		/**
    		 * Filter the module header template.
    		 *
    		 * @since 2.0
    		 **/
    		$content = apply_filters( 'coursepress_module_header', $content, $module );
    
    		return $content;
    	}
    
    	public static function render_image( $module, $attributes = false ) {
    		$content = self::do_caption_media( $attributes );
    
    		return $content;
    	}
    
    	/**
    	 * @param $data
    	 * @param null|WP_Post $module
    	 * @return string
    	 */
    	private static function do_caption_media( $data, $module = null ) {
    		if ( empty( $data['image_url'] ) && empty( $data['video_url'] ) ) {
    			return '';
    		}
    
    		$the_caption = '';
    		$alt_text = '';
    		$media_width = '';
    
    		$type = $data['module_type'];
    		if ( 'video' === $type ) {
    			$url = $data['video_url'];
    		}
    		if ( 'image' === $type ) {
    			$url = $data['image_url'];
    		}
    
    		$caption_source = isset( $data['caption_field'] ) ? $data['caption_field'] : 'media';
    		$attachment = CoursePress_Helper_Utility::attachment_from_url( $url );
    
    		if ( 'media' === $caption_source ) {
    
    			if ( ! empty( $attachment ) ) {
    
    				$alt_text = CoursePress_Helper_Utility::filter_content( get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ) );
    				if ( empty( $alt_text ) ) {
    					$alt_text = isset( $data['caption_custom_text'] ) ? CoursePress_Helper_Utility::filter_content( $data['caption_custom_text'] ) : '';
    				}
    
    				$meta = wp_get_attachment_metadata( $attachment->ID );
    				$media_width = $meta['width'];
    
    				$the_caption = $attachment->post_excerpt;
    
    			} else {
    				$the_caption = '';
    				$alt_text = isset( $data['caption_custom_text'] ) ? CoursePress_Helper_Utility::filter_content( $data['caption_custom_text'] ) : '';
    			}
    		} else {
    
    			$alt_text = isset( $data['caption_custom_text'] ) ? CoursePress_Helper_Utility::filter_content( $data['caption_custom_text'] ) : '';
    
    			global $content_width;
    			if ( ! empty( $content_width ) ) {
    				$media_width = $content_width;
    			} else {
    				$media_width = get_option( 'large_size_w' );
    			}
    
    			// Get the custom caption text
    			$the_caption = isset( $data['caption_custom_text'] ) ? CoursePress_Helper_Utility::filter_content( $data['caption_custom_text'] ) : '';
    		}
    
    		$html = '';
    
    		$show_caption = isset( $data['show_media_caption'] ) ? cp_is_true( $data['show_media_caption'] ) : false;
    
    		if ( ! empty( $attachment ) ) {
    			$attachment_id = ' id="attachment_' . $attachment->ID . '" ';
    		} else {
    			$attachment_id = ' id="attachment_' . time() . '" ';
    		}
    
    		if ( 'image' === $type ) {
    			if ( $show_caption ) {
    				$html .= '<div class="image_holder">';
    				$img = '<img src="' . esc_url( $url ) . '" alt="' . esc_attr( $alt_text ) . '" />';
    				$html .= do_shortcode( '[caption width="' . $media_width . '"' . $attachment_id . ']' . $img . ' ' . $the_caption . '[/caption]' );
    				$html .= '</div>';
    			} else {
    				$html .= '<div class="image_holder">';
    				$html .= '<img src="' . esc_url( $url ) . '" alt="' . esc_attr( $alt_text ) . '" />';
    				$html .= '</div>';
    			}
    		}
    
    		if ( 'video' === $type ) {
    			$player_width = CoursePress_Helper_Utility::get_array_val( $data, 'video_player_width' );
    			$player_width = $player_width ? $player_width : '640';
    			$player_height = CoursePress_Helper_Utility::get_array_val( $data, 'video_player_height' );
    			$player_height = $player_height ? $player_height : '360';
    			$autoplay = CoursePress_Helper_Utility::get_array_val( $data, 'video_autoplay' ) ? 'autoplay' : '';
    			$loop = CoursePress_Helper_Utility::get_array_val( $data, 'video_loop' ) ? 'loop' : '';
    			$controls = CoursePress_Helper_Utility::get_array_val( $data, 'video_hide_controls' ) ? '' : 'controls';
    			$module_video_id = isset( $module->ID ) ? 'module-video-' . $module->ID : '';
    
    			ob_start();
    			?>
    				<video
    					id="<?php echo $module_video_id; ?>"
    					class="video-js vjs-default-skin vjs-big-play-centered"
    					width="<?php echo $player_width; ?>"
    					height="<?php echo $player_height; ?>"
    					src="<?php echo $url; ?>"
    					data-setup='<?php echo CoursePress_Helper_Utility::create_video_js_setup_data( $url, $data ); ?>'
    					<?php echo $controls; ?>
    					<?php echo $autoplay; ?>
    					<?php echo $loop; ?>>
    				</video>
    			<?php
    			$video = ob_get_clean();
    
    			if ( $show_caption ) {
    				$html .= '<div class="video_holder">';
    				$html .= '<figure ' . $attachment_id . ' class="wp-caption" style="width: ' . $media_width . 'px;">';
    				$html .= '<div class="video_player">';
    				$html .= $video;
    				$html .= '</div>';
    				if ( ! empty( $the_caption ) ) {
    					$html .= '<figcaption class="wp-caption-text">' . $the_caption . '</figcaption>';
    				}
    				$html .= '</figure>';
    				$html .= '</div>';
    			} else {
    				$html .= '<div class="video_player">';
    				$html .= $video;
    				$html .= '</div>';
    			}
    		}
    
    		return $html;
    	}
    
    	public static function render_video( $module, $attributes = false ) {
    		$content = self::do_caption_media( $attributes, $module );
    
    		return $content;
    	}
    
    	public static function render_audio( $module, $attributes = false ) {
    		$content = '';
    
    		if ( isset( $attributes['audio_url'] ) ) {
    			$loop = isset( $attributes['loop'] ) ? cp_is_true( $attributes['loop'] ) : false;
    			$autoplay = isset( $attributes['autoplay'] ) ? cp_is_true( $attributes['autoplay'] ) : false;
    			$attr = array(
    				'src' => $attributes['audio_url'],
    				'loop' => $loop,
    				'autoplay' => $autoplay,
    			);
    
    			$content .= '<div class="module-content">
    					<div class="audio_player">
    						' . wp_audio_shortcode( $attr ) . '
    					</div>
    				</div>
    			';
    		}
    
    		return $content;
    	}
    
    	public static function render_download( $module, $attributes = false ) {
    		$content = '';
    
    		if ( isset( $attributes['file_url'] ) ) {
    
    			$url = $attributes['file_url'];
    
    			$file_size = CoursePress_Helper_Utility::get_file_size( $url );
    
    			if ( $file_size > 0 ) {
    				$filesize = '<small>(' . esc_html( $file_size ) . ')</small>';
    			} else {
    				$filesize = '';
    			}
    
    			$url = CoursePress_Helper_Utility::encode( $url );
    			$url = trailingslashit( home_url() ) . '?fdcpf=' . $url;
    
    			$link_text = isset( $attributes['link_text'] ) ? $attributes['link_text'] : $module->post_title;
    			$after_content = sprintf(
    				'<div class="file_holder"><a href="%s">%s <span class="file-size">%s</span></a></div>',
    				esc_url( $url ),
    				esc_html( $link_text ),
    				CoursePress_Helper_Utility::filter_content( $filesize )
    			);
    			$content .= $after_content;
    		}
    
    		return $content;
    	}
    
    	public static function render_zipped( $module, $attributes = false ) {
    		$content = '';
    
    		if ( isset( $attributes['zip_url'] ) && ! empty( $attributes['primary_file'] ) ) {
    
    			$url = $attributes['zip_url'];
    
    			$url = CoursePress_Helper_Utility::encode( $url );
    			$url = trailingslashit( home_url() ) . '?oacpf=' . $url . '&module=' . $module->ID . '&file=' . $attributes['primary_file'];
    
    			$link_text = isset( $attributes['link_text'] ) ? $attributes['link_text'] : $module->post_title;
    			$after_content = sprintf(
    				'<div class="zip_holder"><a href="%s">%s</a></div>',
    				esc_url( $url ),
    				esc_html( $link_text )
    			);
    			$content .= $after_content;
    		} elseif ( empty( $attributes['primary_file'] ) ) {
    			$content .= sprintf(
    				'<div class="zip_holder error">%s</div>',
    				__( 'Primary File not set, please come back later.', 'coursepress' )
    			);
    		}
    
    		return $content;
    	}
    
    	public static function render_section( $module, $attributes = false ) {
    		return '<hr />';
    	}
    
    	private static function comment_form( $post_id, $attributes = false ) {
    		if ( ! is_user_logged_in() ) {
    			return '';
    		}
    		$enrolled = false;
    		$student_id = get_current_user_id();
    		$course_id = CoursePress_Data_Module::get_course_id_by_module( $post_id );
    		$enrolled = CoursePress_Data_Course::student_enrolled( $student_id, $course_id );
    		/**
    		 * Instructor as enrolled user.
    		 */
    		if ( false == $enrolled ) {
    			$instructors = array_filter( CoursePress_Data_Course::get_instructors( $course_id ) );
    			if ( in_array( $student_id, $instructors ) ) {
    				$enrolled = true;
    			}
    		}
    		/**
    		 * Author as enrolled user.
    		 */
    		if ( false == $enrolled ) {
    			$enrolled = CoursePress_Data_Capabilities::can_update_course( $course_id );
    		}
    		if ( false == $enrolled ) {
    			return '';
    		}
    
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    
    		ob_start();
    
    		$form_class = array( 'comment-form', 'cp-comment-form' );
    		$comment_order = get_option( 'comment_order' );
    		$form_class[] = 'comment-form-' . $comment_order;
    
    		$args = array(
    			'class_form' => implode( ' ', $form_class ),
    			'title_reply' => __( 'Post Here', 'coursepress' ),
    			'label_submit' => __( 'Post', 'coursepress' ),
    			'must_log_in' => '',
    			'logged_in_as' => '',
    			'action' => '',
    			'class_submit' => 'submit cp-comment-submit',
    			'comment_field' => '<p class="comment-form-comment"><textarea id="comment" name="comment" cols="45" rows="8" maxlength="65525"></textarea></p>',
    		);
    
    		/**
    		 * Comment form args filter.
    		 *
    		 * @since 2.0.8
    		 */
    		$args = apply_filters( 'coursepress_comment_form_args', false );
    
    		add_filter( 'comment_form_submit_button', array( 'CoursePress_Template_Discussion', 'add_subscribe_button' ) );
    		comment_form( $args, $post_id );
    		$comment_form = ob_get_clean();
    		$comment_form = str_replace(
    			array( '<form', '</form>' ),
    			array( '<div', '</div>' ),
    			$comment_form
    		);
    
    		/**
    		 * remove required="required" from textarea
    		 */
    		$mandatory = false;
    		if ( isset( $attributes['mandatory'] ) ) {
    			$mandatory = cp_is_true( $attributes['mandatory'] );
    		}
    		if ( false === $mandatory ) {
    			$pattern = '/(<textarea[^>]+>)/';
    			preg_match( $pattern, $comment_form, $matches );
    			if ( 2 == sizeof( $matches ) ) {
    				$replacement = $matches[1];
    				$replacement = preg_replace( '/ required(="[^"]+")?/', '', $replacement );
    				$replacement = preg_replace( '/ aria-required="true"/', '', $replacement );
    				$comment_form = preg_replace( $pattern, $replacement, $comment_form );
    			}
    		}
    
    		remove_filter( 'comment_form_submit_button', array( 'CoursePress_Template_Discussion', 'add_subscribe_button' ) );
    		return $comment_form;
    	}
    
    	public static function comment_list( $module_id ) {
    		ob_start();
    
    		$comments = get_comments(
    			array(
    				'post_id' => $module_id,
    			)
    		);
    
    		$args = array(
    			'style'	   => 'ol',
    			'short_ping'  => true,
    			'avatar_size' => 42,
    		);
    		/**
    		 * Comment list arguments filter.
    		 *
    		 * @since 2.0.8
    		 */
    		$args = apply_filters( 'coursepress_comment_list_args', $args );
    
    		?>
    		<ol class="comment-list">
    			<?php
    				wp_list_comments( $args, $comments );
    			?>
    		</ol><!-- .comment-list -->
    
    		<?php
    		$comment_list = ob_get_clean();
    
    		return $comment_list;
    	}
    
    	public static function discussion_url( $post_id ) {
    		$unit_id = get_post_field( 'post_parent', $post_id );
    		$unit_url = CoursePress_Data_Unit::get_unit_url( $unit_id );
    		$page_number = get_post_meta( $post_id, 'page_number', true );
    		$page_number = max( $page_number, 1 );
    
    		$url = sprintf( '%spage/%s/module_id/%s', $unit_url, $page_number, $post_id );
    
    		return $url;
    	}
    
    	public static function comment_reply_link( $link, $args, $comment, $post ) {
    		$discussion_link = self::discussion_url( $post->ID );
    		$discussion_link = add_query_arg( 'replytocom', $comment->comment_ID, $discussion_link );
    		$discussion_link .= '#respond';
    		$link = preg_replace( '%href=([\'"])(.*?)([\'"])%', 'href=$1' . $discussion_link . '$3', $link );
    		$link = sprintf( '<div data-comid="%s" data-parentid="%s">%s</div>', $comment->comment_ID, $post->ID, $link );
    
    		return $link;
    	}
    
    	public static function render_discussion( $module, $attributes = false ) {
    		global $post;
    
    		$post = $module;
    		// Add comment filters
    		add_filter( 'comments_open', '__return_true' );
    		add_filter( 'comment_reply_link', array( __CLASS__, 'comment_reply_link' ), 10, 4 );
    		setup_postdata( $module );
    
    		$content = '';
    
    		$content .= self::comment_form( $module->ID, $attributes );
    		$content .= self::comment_list( $module->ID );
    
    		// Remove comment filters, etc
    		wp_reset_postdata();
    		remove_filter( 'comments_open', '__return_true' );
    		remove_filter( 'comment_reply_link', array( __CLASS__, 'comment_reply_link' ), 10, 4 );
    
    		return $content;
    	}
    
    	public static function render_input_checkbox( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$student_progress = false === $student_progress ? self::$student_progress : $student_progress;
    		$content = '';
    
    		if ( ! empty( $attributes['answers'] ) ) {
    			$disabled_attr = true === $disabled ? 'disabled="disabled"' : '';
    			$oddeven = 'odd';
    			$alt = '';
    			$response = self::get_response( $module->ID, get_current_user_id() );
    
    			$content .= '<ul class="quiz-question quiz-question-checkbox">';
    			foreach ( $attributes['answers'] as $key => $answer ) {
    				$checked = ' ' . checked( 1, is_array( $response ) && in_array( $key, $response ), false );
    
    				$format = '<li class="%1$s %2$s"><input type="checkbox" value="%5$s" name="module[%3$s][]" id="module-%3$s-%5$s" %6$s /> <label for="module-%3$s-%5$s">%4$s</label></li>';
    				$content .= sprintf( $format, $oddeven, $alt, $module->ID, $answer, esc_attr( $key ), $disabled_attr . $checked );
    
    				$oddeven = 'odd' === $oddeven ? 'even' : 'odd';
    			}
    			$content .= '</ul>';
    		}
    
    		return $content;
    	}
    
    	public static function render_input_radio( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$student_progress = false === $student_progress ? self::$student_progress : $student_progress;
    		$content = '';
    
    		if ( ! empty( $attributes['answers'] ) ) {
    
    			$disabled_attr = $disabled ? 'disabled="disabled"' : '';
    			$oddeven = 'odd';
    			$alt = '';
    			$response = self::get_response( $module->ID, get_current_user_id() );
    
    			$content .= '<ul class="quiz-question quiz-question-radio">';
    
    			foreach ( $attributes['answers'] as $key => $answer ) {
    				$checked = '' !== $response ? ' ' . checked( 1, '' != $response && (int) $response === $key, false ) : '';
    				$format = '<li class="%1$s %2$s"><input type="radio" value="%5$s" name="module[%3$s]" id="module-%3$s-%5$s" %6$s /> <label for="module-%3$s-%5$s">%4$s</label> </li>';
    				$content .= sprintf( $format, $oddeven, $alt, $module->ID, $answer, esc_attr( $key ), $disabled_attr . $checked );
    				$oddeven = 'odd' === $oddeven ? 'even' : 'odd';
    				$alt = empty( $alt ) ? 'alt' : '';
    			}
    
    			$content .= '</ul>';
    		}
    
    		return $content;
    	}
    
    	public static function render_input_select( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$student_progress = false === $student_progress ? self::$student_progress : $student_progress;
    		$content = '';
    
    		if ( ! empty( $attributes['answers'] ) ) {
    			$disabled_attr = $disabled ? 'disabled="disabled"' : '';
    			$options = '';
    			$response = self::get_response( $module->ID, get_current_user_id() );
    
    			foreach ( $attributes['answers'] as $key => $answer ) {
    				$options .= sprintf( '<option value="%s" %s>%s</option>', esc_attr( $key ), selected( 1, $response == $key, false ), esc_html( $answer ) );
    			}
    			$content .= sprintf( '<select class="wide" name="module[%s]" %s>%s</select>', $module->ID, $disabled_attr, $options );
    		}
    
    		return $content;
    	}
    
    	public static function render_input_text( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$student_progress = false === $student_progress ? self::$student_progress : $student_progress;
    		$placeholder_text = get_post_meta( $module->ID, 'placeholder_text', true );
    		$placeholder_text = ! empty( $placeholder_text ) ? $placeholder_text : '';
    		$disabled_attr = $disabled ? 'disabled="disabled"' : '';
    		$response = self::get_response( $module->ID, get_current_user_id() );
    		$format = '<input type="text" name="module[%s]" placeholder="%s" value="%s" %s />';
    
    		$content = sprintf( $format, $module->ID, esc_attr( $placeholder_text ), esc_attr( $response ), $disabled_attr );
    
    		return $content;
    	}
    
    	public static function render_input_textarea( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$student_progress = false === $student_progress ? self::$student_progress : $student_progress;
    		$placeholder_text = get_post_meta( $module->ID, 'placeholder_text', true );
    		$placeholder_text = ! empty( $placeholder_text ) ? $placeholder_text : '';
    		$disabled_attr = $disabled ? 'disabled="disabled"' : '';
    
    		$response = self::get_response( $module->ID, get_current_user_id() );
    		$format = '<textarea name="module[%s]" placeholder="%s" %s rows="3">%s</textarea>';
    
    		$content = sprintf( $format, $module->ID, esc_attr( $placeholder_text ), $disabled_attr, esc_textarea( $response ) );
    
    		return $content;
    	}
    
    	public static function render_input_upload( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$student_progress = false === $student_progress ? self::$student_progress : $student_progress;
    		$disabled_attr = $disabled ? 'disabled="disabled"' : '';
    		$response = self::get_response( $module->ID, get_current_user_id() );
    
    		$format = '<label class="file"><input type="file" name="module[%s]" %s /><span class="button" data-change="%s" data-upload="%s">%s <span class="upload-progress"></span></label>';
    		$content = sprintf( $format, $module->ID, $disabled_attr, __( 'Change File', 'coursepress' ), __( 'Upload File', 'coursepress' ), __( 'Upload File', 'coursepress' ) );
    
    		$upload_types = CoursePress_Helper_Utility::allowed_student_mimes();
    		$upload_types = array_map( 'strtoupper', array_keys( $upload_types ) );
    		$format = '<div class="cp-sub"><p>%s %s</p><p>%s %s</p></div>';
    
    		$content .= sprintf( $format,
    			__( 'Accepted File Format: ', 'coursepress' ),
    			implode( ' ', $upload_types ),
    			__( 'Max File Size:', 'coursepress' ),
    			ini_get( 'upload_max_filesize' )
    		);
    		return $content;
    	}
    
    	public static function render_input_quiz( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$student_progress = false === $student_progress ? self::$student_progress : $student_progress;
    		$disabled_attr = $disabled ? 'disabled="disabled"' : '';
    		$content = '';
    
    		if ( ! empty( $attributes['questions'] ) ) {
    			$response = self::get_response( $module->ID, get_current_user_id() );
    
    			foreach ( $attributes['questions'] as $qi => $question ) {
    				$questions = '<ul class="quiz-question quiz-question-input">';
    
    				foreach ( $question['options']['answers'] as $ai => $answer ) {
    					$module_name = sprintf( 'module[%s][%s]', $module->ID, $qi );
    					$quiz_id = 'quiz-module-' . $module->ID . '-' . $qi . '-' . $ai;
    					$type = 'radio';
    
    					if ( 'multiple' == $question['type'] ) {
    						$type = 'checkbox';
    						$module_name .= '[]';
    					}
    
    					$checked = ' ';
    					if ( is_array( $response ) && ! empty( $response[ $qi ] ) ) {
    						$checked .= checked( 1, ! empty( $response[ $qi ][ $ai ] ), false );
    					}
    
    					$format = '<li><input type="%3$s" id="%1$s" name="%4$s" value="%5$s" %6$s/> <label for="%1$s">%2$s</label></li>';
    					$questions .= sprintf( $format, $quiz_id, esc_html( $answer ), $type, $module_name, $ai, $disabled_attr . $checked );
    				}
    				$questions .= '</ul>';
    				$questions = sprintf( '<p class="question">%s</p>%s', esc_html( $question['question'] ), $questions );
    				$container_format = '<div class="module-quiz-question question-%s" data-type="%s">%s</div>';
    				$content .= sprintf( $container_format, $qi, $question['type'], $questions );
    			}
    		}
    
    		/**
    		 * Filter allow to cange questions in input quiz.
    		 *
    		 * @since 2.0.6
    		 *
    		 * @param string $questions Quiz module questions.
    		 */
    		$content = apply_filters( 'coursepress_template_module_render_input_quiz_content', $content );
    		return $content;
    	}
    
    	public static function render_input_form( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$student_progress = false === $student_progress ? self::$student_progress : $student_progress;
    		$disabled_attr = $disabled ? 'disabled="disabled"' : '';
    		$content = '';
    		$response = self::get_response( $module->ID, get_current_user_id() );
    
    		foreach ( $attributes['questions'] as $qi => $question ) {
    			$field_id = 'form-module-' . $module->ID . '-' . $qi;
    			$label = sprintf( '<label for="%s">%s</label>', $field_id, esc_html( $question['question'] ) );
    
    			switch ( $question['type'] ) {
    				case 'short':
    					$value = ! empty( $response[ $qi ] ) ? $response[ $qi ] : '';
    					$field = '<input type="text" name="module[%s][%s]" placeholder="%s" id="%s" value="%s" %s />';
    					$field = sprintf( $field, $module->ID, $qi, esc_attr( $question['placeholder'] ), $field_id, esc_attr( $value ), $disabled_attr );
    					break;
    
    				case 'long':
    					$value = ! empty( $response[ $qi ] ) ? $response[ $qi ] : '';
    					$field = '<textarea name="module[%s][%s]" placeholder="%s" id="%s" %s>%s</textarea>';
    					$field = sprintf( $field, $module->ID, $qi, esc_attr( $question['placeholder'] ), $field_id, $disabled_attr, esc_textarea( $value ) );
    					break;
    
    				case 'selectable':
    					$options = '';
    					foreach ( $question['options']['answers'] as $ai => $answer ) {
    						$selected = selected( 1, isset( $response[ $qi ] ) && $response[ $qi ] == $ai, false );
    						$options .= sprintf( '<option value="%s" %s>%s</option>', esc_attr( $ai ), $selected, $answer );
    					}
    					$field = '<select class="wide" name="module[%s][%s]" id="%s" %s>%s</select>';
    					$field = sprintf( $field, $module->ID, $qi, $field_id, $disabled_attr, $options );
    					break;
    			}
    
    			$container_format = '<div class="module-quiz-question question-%s" data-type="%s">%s</div>';
    			$content .= sprintf( $container_format, $qi, $question['type'], $label . $field );
    		}
    
    		return $content;
    	}
    
    	/**
    	 * Chat Module
    	 **/
    	public static function render_chat( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		if ( cp_is_chat_plugin_active() ) {
    			$content = sprintf( '<div class="cp-chat-module">[chat id="%s"]</div>', $module->ID );
    			$content = do_shortcode( $content );
    
    			return $content;
    		}
    		return '';
    	}
    
    	/**
    	 * Wrap Content by div, apply filter and shortcodes.
    	 *
    	 * @access private
    	 *
    	 * @since 2.0.0
    	 *
    	 * @param string $content Content to wrap.
    	 * @param string $after_content String to paste after content, but before * wrapper.
    	 * @return string Wrapped and processed content.
    	 */
    	private static function _wrap_content( $content, $after_content = '' ) {
    		return sprintf(
    			'<div class="module-content">%s%s</div>',
    			do_shortcode( apply_filters( 'the_content', $content ) ),
    			$after_content
    		);
    	}
    
    	public static function quiz_result_content( $student_id, $course_id, $unit_id, $module_id, $quiz_result = false ) {
    
    		// Get last submitted result
    		if ( empty( $quiz_result ) ) {
    			$quiz_result = CoursePress_Data_Module::get_quiz_results( $student_id, $course_id, $unit_id, $module_id );
    		}
    		$quiz_passed = ! empty( $quiz_result['passed'] );
    
    		$passed_class = $quiz_passed ? 'passed' : 'not-passed';
    		$passed_message = ! empty( $quiz_result['passed'] ) ? __( 'You have successfully passed the quiz. Here are your results.', 'coursepress' ) : __( 'You did not pass the quiz this time. Here are your results.', 'coursepress' );
    
    		$template = '<div class="module-quiz-questions">
    			<div class="coursepress-quiz-results ' . esc_attr( $passed_class ) . '">
    				<div class="quiz-message"><p class="result-message">' . $passed_message . '</p></div>
    				<div class="quiz-results">
    					<table>
    					<tr><th>' . esc_html__( 'Total Questions', 'coursepress' ) . '</th><td>' . esc_html( $quiz_result['total_questions'] ) . '</td></tr>
    					<tr><th>' . esc_html__( 'Correct', 'coursepress' ) . '</th><td>' . esc_html( $quiz_result['correct'] ) . '</td></tr>
    					<tr><th>' . esc_html__( 'Incorrect', 'coursepress' ) . '</th><td>' . esc_html( $quiz_result['wrong'] ) . '</td></tr>
    					<tr><th>' . esc_html__( 'Grade', 'coursepress' ) . '</th><td>' . esc_html( $quiz_result['grade'] ) . '%</td></tr>
    					</table>
    				</div>
    			</div>
    		</div>
    <script>
    		function ShowQuiz(id){
    		document.getElementById("cp-element-"+id).classList.remove("hide");
    		}
    		</script>';
    
    		$attributes = array(
    			'course_id' => $course_id,
    			'unit_id' => $unit_id,
    			'module_id' => $module_id,
    			'student_id' => $student_id,
    			'quiz_result' => $quiz_result,
    		);
    
    		// Can't use shortcodes this time as this also loads via AJAX
    		$template = apply_filters( 'coursepress_template_quiz_results', $template, $attributes );
    
    		return $template;
    	}
    
    	public static function oembed_result_add_autoplay( $html, $url, $attr ) {
    		wp_parse_str( $url, $attr );
    		if ( isset( $attr['autoplay'] ) && $attr['autoplay'] ) {
    			preg_match( '/src="([^"]+)"/', $html, $matches );
    			if ( 1 < sizeof( $matches ) ) {
    				$url = add_query_arg(
    					array(
    						'autoplay' => 1,
    					),
    					$matches[1]
    				);
    				$src = sprintf( 'src="%s"', esc_url( $url ) );
    				$html = preg_replace( '/src="[^"]+"/', $src, $html );
    			}
    		}
    		return $html;
    	}
    
    	/**
    	 * Check and show form input results.
    	 *
    	 * @since 2.0.6
    	 *
    	 * @param integer $student_id student ID.
    	 * @param integer $course_id Course ID.
    	 * @param integer $unit_id Unit ID.
    	 * @param integer $module_id Modue ID.
    	 * @param array $form_result Result of rorm input.
    	 *
    	 * @return array
    	 */
    	public static function form_result_content( $student_id, $course_id, $unit_id, $module_id, $form_result = false ) {
    		// Get last submitted result
    		if ( empty( $form_result ) ) {
    			$form_result = CoursePress_Data_Module::get_form_results( $student_id, $course_id, $unit_id, $module_id );
    		}
    
    		if ( ! empty( $form_result['pending'] ) ) {
    			$template = sprintf( '<div class="module-form-message">%s</div>', $form_result['message'] );
    		} else {
    
    		    /*
                $form_passed = !empty($form_result['passed']);
                $passed_class = $form_passed ? 'passed' : 'not-passed';
                $passed_message = !empty($form_result['passed']) ? __('You have successfully passed the form. Here are your results.', 'coursepress') : __('You did not pass the form this time. Here are your results.', 'coursepress');
                $template = '<div class="module-form-questions">
                    <div class="coursepress-form-results ' . esc_attr($passed_class) . '">
                        <div class="form-message"><p class="result-message">' . $passed_message . '</p></div>
                        <div class="form-results">
                            <table>
                            <tr><th>' . esc_html__('Total Questions', 'coursepress') . '</th><td>' . esc_html($form_result['total_questions']) . '</td></tr>
                            <tr><th>' . esc_html__('Correct', 'coursepress') . '</th><td>' . esc_html($form_result['correct']) . '</td></tr>
                            <tr><th>' . esc_html__('Incorrect', 'coursepress') . '</th><td>' . esc_html($form_result['wrong']) . '</td></tr>
                            <tr><th>' . esc_html__('Grade', 'coursepress') . '</th><td>' . esc_html($form_result['grade']) . '%</td></tr>
                            </table>
                        </div>
                    </div>
                </div>';
    		    */
    		}
    
    		$attributes = array(
    			'course_id' => $course_id,
    			'unit_id' => $unit_id,
    			'module_id' => $module_id,
    			'student_id' => $student_id,
    			'form_result' => $form_result,
    		);
    		// Can't use shortcodes this time as this also loads via AJAX
    		$template = apply_filters( 'coursepress_template_form_results', $template, $attributes );
    		return $template;
    	}
    }
    
    • This reply was modified 7 years, 10 months ago by shiftlessatol.
    Thread Starter shiftlessatol

    (@shiftlessatol)

    I’ve applied a fix for now

    replace this file with code content below.
    File::

    wp-content/plugins/coursepress/2.0/include/coursepress/template/class-module.php

    
    <?php
    /**
     * Use to print the different modules.
     *
     * @package WordPress
     * @subpackage CoursePress
     **/
    class CoursePress_Template_Module {
    	private static $args = array();
    
    	protected static $student_progress = array();
    
    	/**
    	 * Helper function get module attributes.
    	 **/
    	protected static function attributes( $module_id ) {
    		return CoursePress_Data_Module::attributes( $module_id );
    	}
    
    	/**
    	 * Helper function to quickly retrieve student response
    	 **/
    	protected static function get_response( $module_id, $student_id, $all = false ) {
    		$unit_id = get_post_field( 'post_parent', $module_id );
    		$course_id = get_post_field( 'post_parent', $unit_id );
    
    		$response = CoursePress_Data_Student::get_response( $student_id, $course_id, $unit_id, $module_id );
    
    		if ( false === $all && isset( $response['response'] ) ) {
    			$response = $response['response'];
    		}
    
    		return $response;
    	}
    
    	public static function get_student_answer( $module_id, $student_id ) {
    		$attributes = self::attributes( $module_id );
    		$module_type = $attributes['module_type'];
    		$unit_id = get_post_field( 'post_parent', $module_id );
    		$course_id = get_post_field( 'post_parent', $unit_id );
    		$content = '';
    		$response = self::get_response( $module_id, $student_id );
    
    		switch ( $module_type ) {
    			case 'input-checkbox': case 'input-radio': case 'input-select':
    						$answers = $attributes['answers'];
    						$selected = $attributes['answers_selected'];
    						$content .= '<ul class="cp-answers">';
    
    						// $selected is of string type, change it to int
    						$ints = array_fill( 0, 10, true );
    
    						if ( ! is_array( $selected ) && ! empty( $ints[ $selected ] ) ) {
    							$selected = (int) $selected;
    						}
    
    						foreach ( $answers as $key => $answer ) {
    							if ( 'input-checkbox' !== $module_type ) {
    								$the_answer = $selected === $key || $selected === $answer;
    								$student_answer = $response == $key || $response === $answer;
    							} else {
    								$the_answer = in_array( $key, $selected );
    								$student_answer = is_array( $response ) ? in_array( $key, $response ) : $response == $key;
    							}
    
    							if ( $student_answer ) {
    								if ( $the_answer ) {
    									$answer = '<span class="chosen-answer correct"></span>' . $answer;
    								} else {
    									$answer = '<span class="chosen-answer incorrect"></span>' . $answer;
    								}
    								$content .= sprintf( '<li>%s</li>', $answer );
    							}
    						}
    						$content .= '</ul>';
    
    				break;
    			case 'input-textarea': case 'input-text':
    					if ( ! empty( $response ) ) {
    						$content .= sprintf( '<div class="cp-answer-box">%s</div>', $response );
    					}
    				break;
    
    			case 'input-upload':
    				if ( ! empty( $response['url'] ) ) {
    					$url = $response['url'];
    					$filename = basename( $url );
    					$url = CoursePress_Helper_Utility::encode( $url );
    					$url = trailingslashit( home_url() ) . '?fdcpf=' . $url;
    
    					$content .= sprintf( '<a href="%s" class="button-primary cp-download">%s</a>', esc_url( $url ), $filename );
    				}
    				break;
    
    			case 'input-quiz':
    				if ( is_admin() ) {
    					if ( ! empty( $attributes['questions'] ) ) {
    						$questions = $attributes['questions'];
    
    						foreach ( $questions as $q_index => $question ) {
    							$options = (array) $question['options'];
    							$checked = (array) $options['checked'];
    							$checked = array_filter( $checked );
    							$student_response = $response[ $q_index ];
    
    							$content .= sprintf( '<div class="cp-q"><hr /><p class="description cp-question">%s</p><ul>', esc_html( $question['question'] ) );
    
    							foreach ( $options['answers'] as $p_index => $answer ) {
    								$the_answer = isset( $checked[ $p_index ] ) ? $checked[ $p_index ] : false;
    								$student_answer = '';
    
    								if ( isset( $student_response[ $p_index ] ) && $student_response[ $p_index ] ) {
    									$student_answer = $student_response[ $p_index ];
    
    									if ( $the_answer ) {
    										$student_answer = '<span class="chosen-answer correct"></span>';
    									} else {
    										$student_answer = '<span class="chosen-answer incorrect"></span>';
    									}
    									$content .= '<li>' . $student_answer . esc_html( $answer ) . '</li>';
    								}
    							}
    							$content .= '</ul></div>';
    
    						}
    					}
    				} else {
    					$content .= self::quiz_result_content( $student_id, $course_id, $unit_id, $module_id );
    				}
    				break;
    
    			case 'input-form':
    				if ( ! empty( $attributes['questions'] ) ) {
    					$questions = $attributes['questions'];
    
    					foreach ( $questions as $q_index => $question ) {
    						$student_response = ! empty( $response[ $q_index ] ) ? $response[ $q_index ] : '';
    						$format = '<div class="cp-q"><hr /><p class="description cp-question">%s</p>';
    						$content .= sprintf( $format, esc_html( $question['question'] ) );
    						$content .= '<ul>';
    
    						if ( 'selectable' == $question['type'] ) {
    							$options = $question['options']['answers'];
    							$checked = $question['options']['checked'];
    
    							foreach ( $options as $ai => $answer ) {
    								if ( $student_response == $ai ) {
    									$the_answer = ! empty( $checked[ $ai ] );
    
    									if ( $the_answer === $student_response ) {
    										$student_answer = '<span class="chosen-answer correct"></span>';
    									} else {
    										$student_answer = '<span class="chosen-answer incorrect"></span>';
    									}
    									$content .= sprintf( '<li>%s %s</li>', $student_answer, $answer );
    								}
    							}
    						} else {
    							$content .= sprintf( '<li>%s</li>', esc_html( $student_response ) );
    						}
    						$content .= '</ul></div>';
    					}
    				}
    				break;
    		}
    
    		/**
    		 * Filter the student response template.
    		 **/
    		$content = apply_filters( 'coursepress_student_reponse_template', $content, $module_id, $module_type );
    
    		return $content;
    	}
    
    	public static function get_module_status( $module_id, $student_id ) {
    		$attributes = self::attributes( $module_id );
    		$module_type = $attributes['module_type'];
    		$assessables = array( 'input-text', 'input-textarea', 'input-upload', 'input-form' );
    		$response = self::get_response( $module_id, $student_id, true );
    		$grades = (array) CoursePress_Helper_Utility::get_array_val( $response, 'grades' );
    		$grades = array_pop( $grades );
    		$grade = (int) CoursePress_Helper_Utility::get_array_val( $grades, 'grade' );
    		$minimum_grade = (int) $attributes['minimum_grade'];
    		$require_assessment = false;
    		$pass = $grade >= $minimum_grade;
    		$status = '';
    
    		if ( in_array( $module_type, $assessables ) ) {
    			if ( ! empty( $attributes['assessable'] ) ) {
    				$graded_by = CoursePress_Helper_Utility::get_array_val( $grades, 'graded_by' );
    				if ( 'auto' === $graded_by || empty( $grades ) ) {
    					$status = __( 'Pending', 'cp' );
    				} elseif ( $pass ) {
    					$status = __( 'Pass', 'cp' );
    				} else {
    				    $status = __( 'Failed', 'cp' );
    				}
    			} else {
    				$status = __( 'Non Gradable', 'cp' );
    			}
    		} else {
    			$status = $pass ? __( 'Pass', 'cp' ) : __( 'Fail', 'cp' );
    		}
    
    		return $status;
    	}
    
    	/**
    	 *
    	 * @param integer $module_id Modile ID.
    	 * @param boolean $is_focus Is in focus mode?
    	 * @param string $view_type View type, possible values "normal", "preview" @since 2.0.4
    	 */
    	public static function template( $module_id = 0, $is_focus = false, $view_type = 'normal' ) {
    		if ( empty( $module_id ) ) {
    			return ''; // Nothing to process, bail!
    		}
    
    		$attributes = self::attributes( $module_id );
    		$module_type = $attributes['module_type'];
    		$is_required = ! empty( $attributes['mandatory'] );
    		$method = 'render_' . str_replace( '-', '_', $module_type );
    		$module = get_post( $module_id );
    		$unit_id = $module->post_parent;
    		$course_id = get_post_field( 'post_parent', $unit_id );
    		$course_status = CoursePress_Data_Course::get_course_status( $course_id );
    		$is_module_answerable = preg_match( '%input-%', $module_type ) || 'video' === $module_type;
    		$disabled = false;
    		$element_class = array();
    		$student_id = get_current_user_id();
    		$content = '<div class="module-container">';
    
    		/**
    		 * Fire before the module template is printed
    		 *
    		 * @since 2.0
    		 *
    		 * @param (int) $module_id			The WP_Post object ID.
    		 * @param (int) $student_id			Current user ID.
    		 **/
    		do_action( 'coursepress_module_view', $module_id, $student_id );
    
    		// Marked module and page as visited
    		$module_page = get_post_meta( $module_id, 'module_page', true );
    		CoursePress_Data_Student::visited_module( $student_id, $course_id, $unit_id, $module_id );
    		CoursePress_Data_Student::visited_page( $student_id, $course_id, $unit_id, $module_page );
    
    		$content .= sprintf( '<input type="hidden" name="course_id" value="%s" />', $course_id );
    		$content .= sprintf( '<input type="hidden" name="unit_id" value="%s" />', $unit_id );
    		$content .= sprintf( '<input type="hidden" name="student_id" value="%s" />', $student_id );
    		$content .= sprintf( '<input type="hidden" name="module_id[]" value="%s" />', $module_id );
    
    		if ( $is_focus ) {
    			$content .= wp_nonce_field( 'coursepress_submit_modules', '_wpnonce', true, false );
    			$content .= sprintf( '<div class="cp-error">%s</div>', apply_filters( 'coursepress_before_unit_modules', '' ) );
    		}
    
    		// Module header
    		$content .= self::render_module_head( $module, $attributes );
    		// The question or text content
    		$content .= self::_wrap_content( $module->post_content );
    
    		if ( method_exists( __CLASS__, $method ) ) {
    			// Get student progress if it is not retrieve yet
    			if ( empty( self::$student_progress ) ) {
    				$student_progress = self::$student_progress = CoursePress_Data_Student::get_completion_data( $student_id, $course_id );
    			} else {
    				$student_progress = self::$student_progress;
    			}
    
    			// Record module visit
    			CoursePress_Data_Student::visited_module( $student_id, $course_id, $unit_id, $module_id, self::$student_progress );
    
    			$retry = 'TRY';
    			$element_class = array( 'module-elements' );
    			if ( $is_module_answerable ) {
    				$responses = CoursePress_Data_Student::get_responses( $student_id, $course_id, $unit_id, $module_id, true, $student_progress );
    				$last_response = self::get_response( $module_id, $student_id );
    				if ( ! empty( $responses ) ) {
    					$element_class[] = 'hide';
    				}
    
    				// Set value to 1 only if not attempted this module.
    				$is_module_hidden = empty( $responses ) ? 0 : 1;
    				// Add a hidden field to track if student really submitted the form.
    				$content .= sprintf( '<input type="hidden" class="cp-is-hidden-module" name="is_module_hidden[%s]" value="%s" />', $module_id, $is_module_hidden );
    
    				$response_count = ! empty( $responses ) ? count( $responses ) : 0;
    
    				// Get recorded time lapsed
    				$keys = array( $course_id, $unit_id, $module_id, $student_id );
    				$key = 'response_' . implode( '_', $keys );
    				$lapses = (int) get_user_meta( $student_id, $key, true );
    				$response_count += $lapses;
    
    				$try_again_label = __( 'Try Again', 'cp' );
    
    				switch ( $module_type ) {
    					case 'input-upload':
    						$try_again_label = __( 'Upload a different file', 'cp' );
    					break;
    				}
    				$retry = sprintf( '<p class="cp-try-again"><a data-module="%s" onclick="javascript:ShowQuiz(%s);" class="button module-submit-action button-reload-module">%s</a></p>', $module_id,$module_id, $try_again_label );
    
    				// Check if retry is disabled
    				if ( empty( $attributes['allow_retries'] ) ) {
    					$retry = '';
    				} elseif ( ! empty( $attributes['retry_attempts'] ) && 0 < $response_count ) {
    					$attempts = (int) $attributes['retry_attempts'];
    
    					// Retries + 1 normal attempt.
    					if ( $response_count > $attempts ) {
    						$disabled = true;
    						$retry = '';
    					} else {
    						$retry .= sprintf(
    							'<p class="number-of-fails">%s</p>',
    							sprintf( __( 'Number of failed attempts: %d', 'cp' ), $response_count )
    						);
    					}
    				}
    
    				if ( ! empty( $attributes['use_timer'] ) && ! empty( $attributes['duration'] ) ) {
    					$allow_retry = true;
    					$attempts = (int) $attributes['retry_attempts'];
    					$duration = $attributes['duration'];
    					$dur = explode( ':', $duration );
    					/**
    					 * sanitize time format
    					 */
    					switch ( sizeof( $dur ) ) {
    						case 1:
    							$duration = sprintf( '00:%02d', $dur[0] );
    						break;
    						case 2:
    							$duration = sprintf( '%02d:%02d', $dur[0], $dur[1] );
    						break;
    						case 3:
    							$duration = sprintf( '%02d:%02d:%02d', $dur[0], $dur[1], $dur[2] );
    						break;
    					}
    
    					$format = '<span class="quiz_timer" data-limit="%1$s" data-retry="%2$s">%1$s</span><span class="quiz_timer_info">%3$s</span>';
    
    					if ( empty( $retry ) ) {
    						$attempts = 'no';
    						if ( $response_count > 0 ) {
    							$duration = '00:00:00';
    						}
    					}
    
    					$timer_info = __( 'Session Expired', 'cp' ) . $retry;
    					$content .= sprintf( $format, $duration, $attempts, $timer_info );
    				}
    			}
    
    			if ( 'closed' == $course_status ) {
    				$disabled = true;
    				$retry = '';
    			}
    
    			$disabled_attr = $disabled ? 'disabled="disabled"' : '';
    			$module_elements = call_user_func( array( __CLASS__, $method ), $module, $attributes, $student_progress );
    			if ( $is_module_answerable && 'preview' == $view_type  ) {
    				$module_elements = '';
    			}
    
    			switch ( $module_type ) {
    				case 'input-quiz';
    					$module_elements = sprintf( '<div class="module-quiz-questions">%s</div>', $module_elements );
    					break;
    			}
    
    			$element_class[] = sprintf( 'module-type-%s', $module_type );
    
    			$module_elements = sprintf( '<div id="cp-element-%s" class="%s" data-type="%s" data-required="%s">%s</div>', $module_id, implode( ' ', $element_class ), $module_type, $is_required, $module_elements );
    
    			if ( $is_module_answerable && ! empty( $responses ) ) {
    
    				$status = self::get_module_status( $module->ID, $student_id );
    
    				if ( 'Pass' == $status ) {
    					$retry = '';
    				}
    
    				$student_answers = sprintf( '<span class="cp-status status-%s">%s</span>', strtolower( $status ), $status );
    				$student_answers = sprintf( '<div class="cp-student-status">%s</div>', $student_answers );
    				$student_answers .= self::get_student_answer( $module->ID, $student_id );
    				$student_answers .= $retry;
    
    				$module_elements .= sprintf( '<div id="cp-response-%s" class="module-response">%s</div>', $module_id, $student_answers );
    			}
    
    			if ( 'closed' == $course_status ) {
    				$format = '<div class="module-warnings"><p>%s</p></div>';
    				$module_warning = sprintf( $format, esc_html__( 'This course is completed, you can not submit answers anymore.', 'cp' ) );
    
    				/**
    				 * Filter the warning message.
    				 *
    				 * @since 2.0
    				 **/
    				$module_elements .= apply_filters( 'coursepress_course_readonly_message', $module_warning, $module_id, $course_id );
    			}
    
    			/**
    			 * custom wrappers
    			 */
    			switch ( $module_type ) {
    				case 'discussion':
    					$module_elements = sprintf( '<div id="comments" class="comments-area"><div class="comments-list-container">%s</div></div>', $module_elements );
    					break;
    			}
    
    			/**
    			 * Filter the module elements template.
    			 *
    			 * @since 2.0
    			 **/
    			$content .= apply_filters( 'coursepress_module_template', $module_elements, $module_type, $module_id );
    
    			/**
    			 * Filter the module container classes
    			 *
    			 * @since 2.0.6
    			 **/
    			$module_container_classes = apply_filters( 'coursepress_module_container_classes', array( 'cp-module-content' ), $module_type, $module_id );
    
    			$content = sprintf(
    				'<div class="%4$s" data-type="%1$s" data-id="%2$s" id="cp-module-%2$s">%3$s</div>',
    				esc_attr( $module_type ),
    				esc_attr( $module_id ),
    				$content,
    				esc_attr( implode( ' ', $module_container_classes ) )
    			);
    		}
    		/**
    		 * div.module-container
    		 */
    		$content .= '</div>';
    		return $content;
    	}
    
    	/**
    	 * Module header
    	 **/
    	private static function render_module_head( $module, $attributes = false ) {
    		if ( false === $module || empty( $module ) ) {
    			return; // Bail
    		}
    
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$content = '';
    
    		$show_title = ! empty( $attributes['show_title'] );
    		$mandatory = ! empty( $attributes['mandatory'] );
    
    		if ( $show_title ) {
    			$content .= '<h4 class="module-title">';
    			$content .= $module->post_title;
    			if ( $mandatory ) {
    				$content .= sprintf( '<span class="is-mandatory">%s</span>', __( 'Required', 'cp' ) );
    			}
    			$content .= '</h4>';
    		} else if ( $mandatory ) {
    			$content .= sprintf( '<div class="is-mandatory">%s</div>', __( 'Required', 'cp' ) );
    		}
    		$format = '<div class="module-header module %1$s module-%2$s %3$s" data-type="%1$s" data-module="%2$s">%4$s</div>';
    		$content = sprintf( $format, $attributes['module_type'], $module->ID, $attributes['mode'], $content );
    
    		/**
    		 * Filter the module header template.
    		 *
    		 * @since 2.0
    		 **/
    		$content = apply_filters( 'coursepress_module_header', $content, $module );
    
    		return $content;
    	}
    
    	public static function render_image( $module, $attributes = false ) {
    		$content = self::do_caption_media( $attributes );
    
    		return $content;
    	}
    
    	/**
    	 * @param $data
    	 * @param null|WP_Post $module
    	 * @return string
    	 */
    	private static function do_caption_media( $data, $module = null ) {
    		if ( empty( $data['image_url'] ) && empty( $data['video_url'] ) ) {
    			return '';
    		}
    
    		$the_caption = '';
    		$alt_text = '';
    		$media_width = '';
    
    		$type = $data['module_type'];
    		if ( 'video' === $type ) {
    			$url = $data['video_url'];
    		}
    		if ( 'image' === $type ) {
    			$url = $data['image_url'];
    		}
    
    		$caption_source = isset( $data['caption_field'] ) ? $data['caption_field'] : 'media';
    		$attachment = CoursePress_Helper_Utility::attachment_from_url( $url );
    
    		if ( 'media' === $caption_source ) {
    
    			if ( ! empty( $attachment ) ) {
    
    				$alt_text = CoursePress_Helper_Utility::filter_content( get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ) );
    				if ( empty( $alt_text ) ) {
    					$alt_text = isset( $data['caption_custom_text'] ) ? CoursePress_Helper_Utility::filter_content( $data['caption_custom_text'] ) : '';
    				}
    
    				$meta = wp_get_attachment_metadata( $attachment->ID );
    				$media_width = $meta['width'];
    
    				$the_caption = $attachment->post_excerpt;
    
    			} else {
    				$the_caption = '';
    				$alt_text = isset( $data['caption_custom_text'] ) ? CoursePress_Helper_Utility::filter_content( $data['caption_custom_text'] ) : '';
    			}
    		} else {
    
    			$alt_text = isset( $data['caption_custom_text'] ) ? CoursePress_Helper_Utility::filter_content( $data['caption_custom_text'] ) : '';
    
    			global $content_width;
    			if ( ! empty( $content_width ) ) {
    				$media_width = $content_width;
    			} else {
    				$media_width = get_option( 'large_size_w' );
    			}
    
    			// Get the custom caption text
    			$the_caption = isset( $data['caption_custom_text'] ) ? CoursePress_Helper_Utility::filter_content( $data['caption_custom_text'] ) : '';
    		}
    
    		$html = '';
    
    		$show_caption = isset( $data['show_media_caption'] ) ? cp_is_true( $data['show_media_caption'] ) : false;
    
    		if ( ! empty( $attachment ) ) {
    			$attachment_id = ' id="attachment_' . $attachment->ID . '" ';
    		} else {
    			$attachment_id = ' id="attachment_' . time() . '" ';
    		}
    
    		if ( 'image' === $type ) {
    			if ( $show_caption ) {
    				$html .= '<div class="image_holder">';
    				$img = '<img src="' . esc_url( $url ) . '" alt="' . esc_attr( $alt_text ) . '" />';
    				$html .= do_shortcode( '[caption width="' . $media_width . '"' . $attachment_id . ']' . $img . ' ' . $the_caption . '[/caption]' );
    				$html .= '</div>';
    			} else {
    				$html .= '<div class="image_holder">';
    				$html .= '<img src="' . esc_url( $url ) . '" alt="' . esc_attr( $alt_text ) . '" />';
    				$html .= '</div>';
    			}
    		}
    
    		if ( 'video' === $type ) {
    			$player_width = CoursePress_Helper_Utility::get_array_val( $data, 'video_player_width' );
    			$player_width = $player_width ? $player_width : '640';
    			$player_height = CoursePress_Helper_Utility::get_array_val( $data, 'video_player_height' );
    			$player_height = $player_height ? $player_height : '360';
    			$autoplay = CoursePress_Helper_Utility::get_array_val( $data, 'video_autoplay' ) ? 'autoplay' : '';
    			$loop = CoursePress_Helper_Utility::get_array_val( $data, 'video_loop' ) ? 'loop' : '';
    			$controls = CoursePress_Helper_Utility::get_array_val( $data, 'video_hide_controls' ) ? '' : 'controls';
    			$module_video_id = isset( $module->ID ) ? 'module-video-' . $module->ID : '';
    
    			ob_start();
    			?>
    				<video
    					id="<?php echo $module_video_id; ?>"
    					class="video-js vjs-default-skin vjs-big-play-centered"
    					width="<?php echo $player_width; ?>"
    					height="<?php echo $player_height; ?>"
    					src="<?php echo $url; ?>"
    					data-setup='<?php echo CoursePress_Helper_Utility::create_video_js_setup_data( $url, $data ); ?>'
    					<?php echo $controls; ?>
    					<?php echo $autoplay; ?>
    					<?php echo $loop; ?>>
    				</video>
    			<?php
    			$video = ob_get_clean();
    
    			if ( $show_caption ) {
    				$html .= '<div class="video_holder">';
    				$html .= '<figure ' . $attachment_id . ' class="wp-caption" style="width: ' . $media_width . 'px;">';
    				$html .= '<div class="video_player">';
    				$html .= $video;
    				$html .= '</div>';
    				if ( ! empty( $the_caption ) ) {
    					$html .= '<figcaption class="wp-caption-text">' . $the_caption . '</figcaption>';
    				}
    				$html .= '</figure>';
    				$html .= '</div>';
    			} else {
    				$html .= '<div class="video_player">';
    				$html .= $video;
    				$html .= '</div>';
    			}
    		}
    
    		return $html;
    	}
    
    	public static function render_video( $module, $attributes = false ) {
    		$content = self::do_caption_media( $attributes, $module );
    
    		return $content;
    	}
    
    	public static function render_audio( $module, $attributes = false ) {
    		$content = '';
    
    		if ( isset( $attributes['audio_url'] ) ) {
    			$loop = isset( $attributes['loop'] ) ? cp_is_true( $attributes['loop'] ) : false;
    			$autoplay = isset( $attributes['autoplay'] ) ? cp_is_true( $attributes['autoplay'] ) : false;
    			$attr = array(
    				'src' => $attributes['audio_url'],
    				'loop' => $loop,
    				'autoplay' => $autoplay,
    			);
    
    			$content .= '<div class="module-content">
    					<div class="audio_player">
    						' . wp_audio_shortcode( $attr ) . '
    					</div>
    				</div>
    			';
    		}
    
    		return $content;
    	}
    
    	public static function render_download( $module, $attributes = false ) {
    		$content = '';
    
    		if ( isset( $attributes['file_url'] ) ) {
    
    			$url = $attributes['file_url'];
    
    			$file_size = CoursePress_Helper_Utility::get_file_size( $url );
    
    			if ( $file_size > 0 ) {
    				$filesize = '<small>(' . esc_html( $file_size ) . ')</small>';
    			} else {
    				$filesize = '';
    			}
    
    			$url = CoursePress_Helper_Utility::encode( $url );
    			$url = trailingslashit( home_url() ) . '?fdcpf=' . $url;
    
    			$link_text = isset( $attributes['link_text'] ) ? $attributes['link_text'] : $module->post_title;
    			$after_content = sprintf(
    				'<div class="file_holder"><a href="%s">%s <span class="file-size">%s</span></a></div>',
    				esc_url( $url ),
    				esc_html( $link_text ),
    				CoursePress_Helper_Utility::filter_content( $filesize )
    			);
    			$content .= $after_content;
    		}
    
    		return $content;
    	}
    
    	public static function render_zipped( $module, $attributes = false ) {
    		$content = '';
    
    		if ( isset( $attributes['zip_url'] ) && ! empty( $attributes['primary_file'] ) ) {
    
    			$url = $attributes['zip_url'];
    
    			$url = CoursePress_Helper_Utility::encode( $url );
    			$url = trailingslashit( home_url() ) . '?oacpf=' . $url . '&module=' . $module->ID . '&file=' . $attributes['primary_file'];
    
    			$link_text = isset( $attributes['link_text'] ) ? $attributes['link_text'] : $module->post_title;
    			$after_content = sprintf(
    				'<div class="zip_holder"><a href="%s">%s</a></div>',
    				esc_url( $url ),
    				esc_html( $link_text )
    			);
    			$content .= $after_content;
    		} elseif ( empty( $attributes['primary_file'] ) ) {
    			$content .= sprintf(
    				'<div class="zip_holder error">%s</div>',
    				__( 'Primary File not set, please come back later.', 'cp' )
    			);
    		}
    
    		return $content;
    	}
    
    	public static function render_section( $module, $attributes = false ) {
    		return '<hr />';
    	}
    
    	private static function comment_form( $post_id, $attributes = false ) {
    		if ( ! is_user_logged_in() ) {
    			return '';
    		}
    		$enrolled = false;
    		$student_id = get_current_user_id();
    		$course_id = CoursePress_Data_Module::get_course_id_by_module( $post_id );
    		$enrolled = CoursePress_Data_Course::student_enrolled( $student_id, $course_id );
    		/**
    		 * Instructor as enrolled user.
    		 */
    		if ( false == $enrolled ) {
    			$instructors = array_filter( CoursePress_Data_Course::get_instructors( $course_id ) );
    			if ( in_array( $student_id, $instructors ) ) {
    				$enrolled = true;
    			}
    		}
    		/**
    		 * Author as enrolled user.
    		 */
    		if ( false == $enrolled ) {
    			$enrolled = CoursePress_Data_Capabilities::can_update_course( $course_id );
    		}
    		if ( false == $enrolled ) {
    			return '';
    		}
    
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    
    		ob_start();
    
    		$form_class = array( 'comment-form', 'cp-comment-form' );
    		$comment_order = get_option( 'comment_order' );
    		$form_class[] = 'comment-form-' . $comment_order;
    
    		$args = array(
    			'class_form' => implode( ' ', $form_class ),
    			'title_reply' => __( 'Post Here', 'cp' ),
    			'label_submit' => __( 'Post', 'cp' ),
    			'must_log_in' => '',
    			'logged_in_as' => '',
    			'action' => '',
    			'class_submit' => 'submit cp-comment-submit',
    			'comment_field' => '<p class="comment-form-comment"><textarea id="comment" name="comment" cols="45" rows="8" maxlength="65525"></textarea></p>',
    		);
    
    		/**
    		 * Comment form args filter.
    		 *
    		 * @since 2.0.8
    		 */
    		$args = apply_filters( 'coursepress_comment_form_args', false );
    
    		add_filter( 'comment_form_submit_button', array( 'CoursePress_Template_Discussion', 'add_subscribe_button' ) );
    		comment_form( $args, $post_id );
    		$comment_form = ob_get_clean();
    		$comment_form = str_replace(
    			array( '<form', '</form>' ),
    			array( '<div', '</div>' ),
    			$comment_form
    		);
    
    		/**
    		 * remove required="required" from textarea
    		 */
    		$mandatory = false;
    		if ( isset( $attributes['mandatory'] ) ) {
    			$mandatory = cp_is_true( $attributes['mandatory'] );
    		}
    		if ( false === $mandatory ) {
    			$pattern = '/(<textarea[^>]+>)/';
    			preg_match( $pattern, $comment_form, $matches );
    			if ( 2 == sizeof( $matches ) ) {
    				$replacement = $matches[1];
    				$replacement = preg_replace( '/ required(="[^"]+")?/', '', $replacement );
    				$replacement = preg_replace( '/ aria-required="true"/', '', $replacement );
    				$comment_form = preg_replace( $pattern, $replacement, $comment_form );
    			}
    		}
    
    		remove_filter( 'comment_form_submit_button', array( 'CoursePress_Template_Discussion', 'add_subscribe_button' ) );
    		return $comment_form;
    	}
    
    	public static function comment_list( $module_id ) {
    		ob_start();
    
    		$comments = get_comments(
    			array(
    				'post_id' => $module_id,
    			)
    		);
    
    		$args = array(
    			'style'	   => 'ol',
    			'short_ping'  => true,
    			'avatar_size' => 42,
    		);
    		/**
    		 * Comment list arguments filter.
    		 *
    		 * @since 2.0.8
    		 */
    		$args = apply_filters( 'coursepress_comment_list_args', $args );
    
    		?>
    		<ol class="comment-list">
    			<?php
    				wp_list_comments( $args, $comments );
    			?>
    		</ol><!-- .comment-list -->
    
    		<?php
    		$comment_list = ob_get_clean();
    
    		return $comment_list;
    	}
    
    	public static function discussion_url( $post_id ) {
    		$unit_id = get_post_field( 'post_parent', $post_id );
    		$unit_url = CoursePress_Data_Unit::get_unit_url( $unit_id );
    		$page_number = get_post_meta( $post_id, 'page_number', true );
    		$page_number = max( $page_number, 1 );
    
    		$url = sprintf( '%spage/%s/module_id/%s', $unit_url, $page_number, $post_id );
    
    		return $url;
    	}
    
    	public static function comment_reply_link( $link, $args, $comment, $post ) {
    		$discussion_link = self::discussion_url( $post->ID );
    		$discussion_link = add_query_arg( 'replytocom', $comment->comment_ID, $discussion_link );
    		$discussion_link .= '#respond';
    		$link = preg_replace( '%href=([\'"])(.*?)([\'"])%', 'href=$1' . $discussion_link . '$3', $link );
    		$link = sprintf( '<div data-comid="%s" data-parentid="%s">%s</div>', $comment->comment_ID, $post->ID, $link );
    
    		return $link;
    	}
    
    	public static function render_discussion( $module, $attributes = false ) {
    		global $post;
    
    		$post = $module;
    		// Add comment filters
    		add_filter( 'comments_open', '__return_true' );
    		add_filter( 'comment_reply_link', array( __CLASS__, 'comment_reply_link' ), 10, 4 );
    		setup_postdata( $module );
    
    		$content = '';
    
    		$content .= self::comment_form( $module->ID, $attributes );
    		$content .= self::comment_list( $module->ID );
    
    		// Remove comment filters, etc
    		wp_reset_postdata();
    		remove_filter( 'comments_open', '__return_true' );
    		remove_filter( 'comment_reply_link', array( __CLASS__, 'comment_reply_link' ), 10, 4 );
    
    		return $content;
    	}
    
    	public static function render_input_checkbox( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$student_progress = false === $student_progress ? self::$student_progress : $student_progress;
    		$content = '';
    
    		if ( ! empty( $attributes['answers'] ) ) {
    			$disabled_attr = true === $disabled ? 'disabled="disabled"' : '';
    			$oddeven = 'odd';
    			$alt = '';
    			$response = self::get_response( $module->ID, get_current_user_id() );
    
    			$content .= '<ul class="quiz-question quiz-question-checkbox">';
    			foreach ( $attributes['answers'] as $key => $answer ) {
    				$checked = ' ' . checked( 1, is_array( $response ) && in_array( $key, $response ), false );
    
    				$format = '<li class="%1$s %2$s"><input type="checkbox" value="%5$s" name="module[%3$s][]" id="module-%3$s-%5$s" %6$s /> <label for="module-%3$s-%5$s">%4$s</label></li>';
    				$content .= sprintf( $format, $oddeven, $alt, $module->ID, $answer, esc_attr( $key ), $disabled_attr . $checked );
    
    				$oddeven = 'odd' === $oddeven ? 'even' : 'odd';
    			}
    			$content .= '</ul>';
    		}
    
    		return $content;
    	}
    
    	public static function render_input_radio( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$student_progress = false === $student_progress ? self::$student_progress : $student_progress;
    		$content = '';
    
    		if ( ! empty( $attributes['answers'] ) ) {
    
    			$disabled_attr = $disabled ? 'disabled="disabled"' : '';
    			$oddeven = 'odd';
    			$alt = '';
    			$response = self::get_response( $module->ID, get_current_user_id() );
    
    			$content .= '<ul class="quiz-question quiz-question-radio">';
    
    			foreach ( $attributes['answers'] as $key => $answer ) {
    				$checked = '' !== $response ? ' ' . checked( 1, '' != $response && (int) $response === $key, false ) : '';
    				$format = '<li class="%1$s %2$s"><input type="radio" value="%5$s" name="module[%3$s]" id="module-%3$s-%5$s" %6$s /> <label for="module-%3$s-%5$s">%4$s</label> </li>';
    				$content .= sprintf( $format, $oddeven, $alt, $module->ID, $answer, esc_attr( $key ), $disabled_attr . $checked );
    				$oddeven = 'odd' === $oddeven ? 'even' : 'odd';
    				$alt = empty( $alt ) ? 'alt' : '';
    			}
    
    			$content .= '</ul>';
    		}
    
    		return $content;
    	}
    
    	public static function render_input_select( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$student_progress = false === $student_progress ? self::$student_progress : $student_progress;
    		$content = '';
    
    		if ( ! empty( $attributes['answers'] ) ) {
    			$disabled_attr = $disabled ? 'disabled="disabled"' : '';
    			$options = '';
    			$response = self::get_response( $module->ID, get_current_user_id() );
    
    			foreach ( $attributes['answers'] as $key => $answer ) {
    				$options .= sprintf( '<option value="%s" %s>%s</option>', esc_attr( $key ), selected( 1, $response == $key, false ), esc_html( $answer ) );
    			}
    			$content .= sprintf( '<select class="wide" name="module[%s]" %s>%s</select>', $module->ID, $disabled_attr, $options );
    		}
    
    		return $content;
    	}
    
    	public static function render_input_text( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$student_progress = false === $student_progress ? self::$student_progress : $student_progress;
    		$placeholder_text = get_post_meta( $module->ID, 'placeholder_text', true );
    		$placeholder_text = ! empty( $placeholder_text ) ? $placeholder_text : '';
    		$disabled_attr = $disabled ? 'disabled="disabled"' : '';
    		$response = self::get_response( $module->ID, get_current_user_id() );
    		$format = '<input type="text" name="module[%s]" placeholder="%s" value="%s" %s />';
    
    		$content = sprintf( $format, $module->ID, esc_attr( $placeholder_text ), esc_attr( $response ), $disabled_attr );
    
    		return $content;
    	}
    
    	public static function render_input_textarea( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$student_progress = false === $student_progress ? self::$student_progress : $student_progress;
    		$placeholder_text = get_post_meta( $module->ID, 'placeholder_text', true );
    		$placeholder_text = ! empty( $placeholder_text ) ? $placeholder_text : '';
    		$disabled_attr = $disabled ? 'disabled="disabled"' : '';
    
    		$response = self::get_response( $module->ID, get_current_user_id() );
    		$format = '<textarea name="module[%s]" placeholder="%s" %s rows="3">%s</textarea>';
    
    		$content = sprintf( $format, $module->ID, esc_attr( $placeholder_text ), $disabled_attr, esc_textarea( $response ) );
    
    		return $content;
    	}
    
    	public static function render_input_upload( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$student_progress = false === $student_progress ? self::$student_progress : $student_progress;
    		$disabled_attr = $disabled ? 'disabled="disabled"' : '';
    		$response = self::get_response( $module->ID, get_current_user_id() );
    
    		$format = '<label class="file"><input type="file" name="module[%s]" %s /><span class="button" data-change="%s" data-upload="%s">%s <span class="upload-progress"></span></label>';
    		$content = sprintf( $format, $module->ID, $disabled_attr, __( 'Change File', 'cp' ), __( 'Upload File', 'cp' ), __( 'Upload File', 'cp' ) );
    
    		$upload_types = CoursePress_Helper_Utility::allowed_student_mimes();
    		$upload_types = array_map( 'strtoupper', array_keys( $upload_types ) );
    		$format = '<div class="cp-sub"><p>%s %s</p><p>%s %s</p></div>';
    
    		$content .= sprintf( $format,
    			__( 'Accepted File Format: ', 'cp' ),
    			implode( ' ', $upload_types ),
    			__( 'Max File Size:', 'cp' ),
    			ini_get( 'upload_max_filesize' )
    		);
    		return $content;
    	}
    
    	public static function render_input_quiz( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$student_progress = false === $student_progress ? self::$student_progress : $student_progress;
    		$disabled_attr = $disabled ? 'disabled="disabled"' : '';
    		$content = '';
    
    		if ( ! empty( $attributes['questions'] ) ) {
    			$response = self::get_response( $module->ID, get_current_user_id() );
    
    			foreach ( $attributes['questions'] as $qi => $question ) {
    				$questions = '<ul class="quiz-question quiz-question-input">';
    
    				foreach ( $question['options']['answers'] as $ai => $answer ) {
    					$module_name = sprintf( 'module[%s][%s]', $module->ID, $qi );
    					$quiz_id = 'quiz-module-' . $module->ID . '-' . $qi . '-' . $ai;
    					$type = 'radio';
    
    					if ( 'multiple' == $question['type'] ) {
    						$type = 'checkbox';
    						$module_name .= '[]';
    					}
    
    					$checked = ' ';
    					if ( is_array( $response ) && ! empty( $response[ $qi ] ) ) {
    						$checked .= checked( 1, ! empty( $response[ $qi ][ $ai ] ), false );
    					}
    
    					$format = '<li><input type="%3$s" id="%1$s" name="%4$s" value="%5$s" %6$s/> <label for="%1$s">%2$s</label></li>';
    					$questions .= sprintf( $format, $quiz_id, esc_html( $answer ), $type, $module_name, $ai, $disabled_attr . $checked );
    				}
    				$questions .= '</ul>';
    				$questions = sprintf( '<p class="question">%s</p>%s', esc_html( $question['question'] ), $questions );
    				$container_format = '<div class="module-quiz-question question-%s" data-type="%s">%s</div>';
    				$content .= sprintf( $container_format, $qi, $question['type'], $questions );
    			}
    		}
    
    		/**
    		 * Filter allow to cange questions in input quiz.
    		 *
    		 * @since 2.0.6
    		 *
    		 * @param string $questions Quiz module questions.
    		 */
    		$content = apply_filters( 'coursepress_template_module_render_input_quiz_content', $content );
    		return $content;
    	}
    
    	public static function render_input_form( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		$attributes = false === $attributes ? self::attributes( $module->ID ) : $attributes;
    		$student_progress = false === $student_progress ? self::$student_progress : $student_progress;
    		$disabled_attr = $disabled ? 'disabled="disabled"' : '';
    		$content = '';
    		$response = self::get_response( $module->ID, get_current_user_id() );
    
    		foreach ( $attributes['questions'] as $qi => $question ) {
    			$field_id = 'form-module-' . $module->ID . '-' . $qi;
    			$label = sprintf( '<label for="%s">%s</label>', $field_id, esc_html( $question['question'] ) );
    
    			switch ( $question['type'] ) {
    				case 'short':
    					$value = ! empty( $response[ $qi ] ) ? $response[ $qi ] : '';
    					$field = '<input type="text" name="module[%s][%s]" placeholder="%s" id="%s" value="%s" %s />';
    					$field = sprintf( $field, $module->ID, $qi, esc_attr( $question['placeholder'] ), $field_id, esc_attr( $value ), $disabled_attr );
    					break;
    
    				case 'long':
    					$value = ! empty( $response[ $qi ] ) ? $response[ $qi ] : '';
    					$field = '<textarea name="module[%s][%s]" placeholder="%s" id="%s" %s>%s</textarea>';
    					$field = sprintf( $field, $module->ID, $qi, esc_attr( $question['placeholder'] ), $field_id, $disabled_attr, esc_textarea( $value ) );
    					break;
    
    				case 'selectable':
    					$options = '';
    					foreach ( $question['options']['answers'] as $ai => $answer ) {
    						$selected = selected( 1, isset( $response[ $qi ] ) && $response[ $qi ] == $ai, false );
    						$options .= sprintf( '<option value="%s" %s>%s</option>', esc_attr( $ai ), $selected, $answer );
    					}
    					$field = '<select class="wide" name="module[%s][%s]" id="%s" %s>%s</select>';
    					$field = sprintf( $field, $module->ID, $qi, $field_id, $disabled_attr, $options );
    					break;
    			}
    
    			$container_format = '<div class="module-quiz-question question-%s" data-type="%s">%s</div>';
    			$content .= sprintf( $container_format, $qi, $question['type'], $label . $field );
    		}
    
    		return $content;
    	}
    
    	/**
    	 * Chat Module
    	 **/
    	public static function render_chat( $module, $attributes = false, $student_progress = false, $disabled = false ) {
    		if ( cp_is_chat_plugin_active() ) {
    			$content = sprintf( '<div class="cp-chat-module">[chat id="%s"]</div>', $module->ID );
    			$content = do_shortcode( $content );
    
    			return $content;
    		}
    		return '';
    	}
    
    	/**
    	 * Wrap Content by div, apply filter and shortcodes.
    	 *
    	 * @access private
    	 *
    	 * @since 2.0.0
    	 *
    	 * @param string $content Content to wrap.
    	 * @param string $after_content String to paste after content, but before * wrapper.
    	 * @return string Wrapped and processed content.
    	 */
    	private static function _wrap_content( $content, $after_content = '' ) {
    		return sprintf(
    			'<div class="module-content">%s%s</div>',
    			do_shortcode( apply_filters( 'the_content', $content ) ),
    			$after_content
    		);
    	}
    
    	public static function quiz_result_content( $student_id, $course_id, $unit_id, $module_id, $quiz_result = false ) {
    
    		// Get last submitted result
    		if ( empty( $quiz_result ) ) {
    			$quiz_result = CoursePress_Data_Module::get_quiz_results( $student_id, $course_id, $unit_id, $module_id );
    		}
    		$quiz_passed = ! empty( $quiz_result['passed'] );
    
    		$passed_class = $quiz_passed ? 'passed' : 'not-passed';
    		$passed_message = ! empty( $quiz_result['passed'] ) ? __( 'You have successfully passed the quiz. Here are your results.', 'cp' ) : __( 'You did not pass the quiz this time. Here are your results.', 'cp' );
    
    		$template = '<div class="module-quiz-questions">
    			<div class="coursepress-quiz-results ' . esc_attr( $passed_class ) . '">
    				<div class="quiz-message"><p class="result-message">' . $passed_message . '</p></div>
    				<div class="quiz-results">
    					<table>
    					<tr><th>' . esc_html__( 'Total Questions', 'cp' ) . '</th><td>' . esc_html( $quiz_result['total_questions'] ) . '</td></tr>
    					<tr><th>' . esc_html__( 'Correct', 'cp' ) . '</th><td>' . esc_html( $quiz_result['correct'] ) . '</td></tr>
    					<tr><th>' . esc_html__( 'Incorrect', 'cp' ) . '</th><td>' . esc_html( $quiz_result['wrong'] ) . '</td></tr>
    					<tr><th>' . esc_html__( 'Grade', 'cp' ) . '</th><td>' . esc_html( $quiz_result['grade'] ) . '%</td></tr>
    					</table>
    				</div>
    			</div>
    		</div>
    		<script>
    		function ShowQuiz(id){
    		document.getElementById("cp-element-"+id).classList.remove("hide");
    		}
    		</script>';
    
    		$attributes = array(
    			'course_id' => $course_id,
    			'unit_id' => $unit_id,
    			'module_id' => $module_id,
    			'student_id' => $student_id,
    			'quiz_result' => $quiz_result,
    		);
    
    		// Can't use shortcodes this time as this also loads via AJAX
    		$template = apply_filters( 'coursepress_template_quiz_results', $template, $attributes );
    
    		return $template;
    	}
    
    	public static function oembed_result_add_autoplay( $html, $url, $attr ) {
    		wp_parse_str( $url, $attr );
    		if ( isset( $attr['autoplay'] ) && $attr['autoplay'] ) {
    			preg_match( '/src="([^"]+)"/', $html, $matches );
    			if ( 1 < sizeof( $matches ) ) {
    				$url = add_query_arg(
    					array(
    						'autoplay' => 1,
    					),
    					$matches[1]
    				);
    				$src = sprintf( 'src="%s"', esc_url( $url ) );
    				$html = preg_replace( '/src="[^"]+"/', $src, $html );
    			}
    		}
    		return $html;
    	}
    
    	/**
    	 * Check and show form input results.
    	 *
    	 * @since 2.0.6
    	 *
    	 * @param integer $student_id student ID.
    	 * @param integer $course_id Course ID.
    	 * @param integer $unit_id Unit ID.
    	 * @param integer $module_id Modue ID.
    	 * @param array $form_result Result of rorm input.
    	 *
    	 * @return array
    	 */
    	public static function form_result_content( $student_id, $course_id, $unit_id, $module_id, $form_result = false ) {
    		// Get last submitted result
    		if ( empty( $form_result ) ) {
    			$form_result = CoursePress_Data_Module::get_form_results( $student_id, $course_id, $unit_id, $module_id );
    		}
    
    		if ( ! empty( $form_result['pending'] ) ) {
    			$template = sprintf( '<div class="module-form-message">%s</div>', $form_result['message'] );
    		} else {
    
    		    /*
                $form_passed = !empty($form_result['passed']);
                $passed_class = $form_passed ? 'passed' : 'not-passed';
                $passed_message = !empty($form_result['passed']) ? __('You have successfully passed the form. Here are your results.', 'cp') : __('You did not pass the form this time. Here are your results.', 'cp');
                $template = '<div class="module-form-questions">
                    <div class="coursepress-form-results ' . esc_attr($passed_class) . '">
                        <div class="form-message"><p class="result-message">' . $passed_message . '</p></div>
                        <div class="form-results">
                            <table>
                            <tr><th>' . esc_html__('Total Questions', 'cp') . '</th><td>' . esc_html($form_result['total_questions']) . '</td></tr>
                            <tr><th>' . esc_html__('Correct', 'cp') . '</th><td>' . esc_html($form_result['correct']) . '</td></tr>
                            <tr><th>' . esc_html__('Incorrect', 'cp') . '</th><td>' . esc_html($form_result['wrong']) . '</td></tr>
                            <tr><th>' . esc_html__('Grade', 'cp') . '</th><td>' . esc_html($form_result['grade']) . '%</td></tr>
                            </table>
                        </div>
                    </div>
                </div>';
    		    */
    		}
    
    		$attributes = array(
    			'course_id' => $course_id,
    			'unit_id' => $unit_id,
    			'module_id' => $module_id,
    			'student_id' => $student_id,
    			'form_result' => $form_result,
    		);
    		// Can't use shortcodes this time as this also loads via AJAX
    		$template = apply_filters( 'coursepress_template_form_results', $template, $attributes );
    		return $template;
    	}
    }
    
    
    Thread Starter shiftlessatol

    (@shiftlessatol)

    Thanks for the confirmation; eagerly awaiting the update. I appreciate your response and update.

Viewing 3 replies - 1 through 3 (of 3 total)