<?php
/**
 * Sets up a class that contains the properties and functions that each
 * LearnDash custom post type will have
 *
 * @since 2.1.0
 *
 * @package LearnDash\CPT
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! class_exists( 'SFWD_CPT' ) ) {
	/**
	 * Abstract class to setup LearnDash CPTs
	 */
	abstract class SFWD_CPT extends Semper_Fi_Module {

		/**
		 * Post type name
		 *
		 * @var string
		 */
		protected $post_name;

		/**
		 * Post type
		 *
		 * @var string
		 */
		protected $post_type;

		/**
		 * Post type options
		 *
		 * @var array
		 */
		protected $post_options;

		/**
		 * Post type slug
		 *
		 * @var string
		 */
		protected $slug_name;

		/**
		 * Post type taxonomies
		 *
		 * @var object
		 */
		protected $taxonomies = null;

		/**
		 * Set up post type and taxonomy to be registered
		 */
		public function __construct() {
			parent::__construct();

			$this->post_options = array(
				'label'             => $this->post_name,
				'labels'            => array(
					'name'                     => $this->post_name,
					'singular_name'            => $this->post_name,
					'add_new'                  => esc_html__( 'Add New', 'learndash' ),
					'all_items'                => $this->post_name,
					// translators: placeholder: Post Name.
					'add_new_item'             => sprintf( esc_html_x( 'Add New %s', 'placeholder: Post Name', 'learndash' ), $this->post_name ),
					// translators: placeholder: Post Name.
					'edit_item'                => sprintf( esc_html_x( 'Edit %s', 'placeholder: Post Name', 'learndash' ), $this->post_name ),
					// translators: placeholder: Post Name.
					'new_item'                 => sprintf( esc_html_x( 'New %s', 'placeholder: Post Name', 'learndash' ), $this->post_name ),
					// translators: placeholder: Post Name.
					'view_item'                => sprintf( esc_html_x( 'View %s', 'placeholder: Post Name', 'learndash' ), $this->post_name ),
					// translators: placeholder: Post Name.
					'search_items'             => sprintf( esc_html_x( 'Search %s', 'placeholder: Post Name', 'learndash' ), $this->post_name ),
					// translators: placeholder: Post Name.
					'not_found'                => sprintf( esc_html_x( 'No %s found', 'placeholder: Post Name', 'learndash' ), $this->post_name ),
					// translators: placeholder: Post Name.
					'not_found_in_trash'       => sprintf( esc_html_x( 'No %s found in Trash', 'placeholder: Post Name', 'learndash' ), $this->post_name ),
					// translators: placeholder: Post Name.
					'parent_item_colon'        => sprintf( esc_html_x( 'Parent %s', 'placeholder: Post Name', 'learndash' ), $this->post_name ),
					'menu_name'                => $this->post_name,
					// translators: placeholder: Post Name.
					'item_published'           => sprintf( esc_html_x( '%s Published', 'placeholder: Post Name', 'learndash' ), $this->post_name ),
					// translators: placeholder: Post Name.
					'item_published_privately' => sprintf( esc_html_x( '%s Published Privately', 'placeholder: Post Name', 'learndash' ), $this->post_name ),
					// translators: placeholder: Post Name.
					'item_reverted_to_draft'   => sprintf( esc_html_x( '%s Reverted to Draft', 'placeholder: Post Name', 'learndash' ), $this->post_name ),
					// translators: placeholder: Post Name.
					'item_scheduled'           => sprintf( esc_html_x( '%s Scheduled', 'placeholder: Post Name', 'learndash' ), $this->post_name ),
					// translators: placeholder: Post Name.
					'item_updated'             => sprintf( esc_html_x( '%s Updated', 'placeholder: Post Name', 'learndash' ), $this->post_name ),
				),
				'public'            => true,
				'hierarchical'      => false,
				'rewrite'           => array(
					'slug'       => $this->slug_name,
					'with_front' => false,
				),
				'show_ui'           => true,
				'has_archive'       => false,
				'show_in_nav_menus' => true,
				'supports'          => array(
					'title',
					'editor',
				),
			);
		}

		/**
		 * Activate
		 *
		 * @todo  consider for removal, this never gets fired
		 *        add_post_type is fired elsewhere
		 *
		 * @since 2.1.0
		 */
		public function activate() {
			remove_action( 'init', array( $this, 'add_post_type' ) );
			$this->add_post_type();
		}

		/**
		 * Deactivate
		 *
		 *  @todo  consider for removal, this never gets fired
		 *
		 * @since 2.1.0
		 */
		public function deactivate() {
			remove_action( 'init', array( $this, 'add_post_type' ) );
		}

		/**
		 * Sets up admin menu item for post type
		 *
		 * @since 2.1.0
		 */
		public function admin_menu() {
			$this->add_menu( "edit.php?post_type={$this->post_type}" );
		}

		/**
		 * Registers the custom post type, adds filter to register taxonomy
		 * and flushes rewrite rules after registration
		 *
		 * @since 2.1.0
		 */
		public function add_post_type() {
			static $rewrite_flushed = false;

			/**
			 * Filters the custom post type registration options.
			 *
			 * @since 2.1.0
			 *
			 * @param array  $post_options An array of post options.
			 * @param string $post_type    Post type slug.
			 */
			$this->post_options = apply_filters( 'sfwd_cpt_options', $this->post_options, $this->post_type );

			register_post_type( $this->post_type, $this->post_options );
			add_filter( 'sfwd_cpt_register_tax', array( $this, 'register_tax' ), 10 );

			$flush = false;

			// If this is an AJAX call then abort.
			if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
				return;
			}

			// If for some reason we have already flushed rewrites. abort.
			if ( $rewrite_flushed ) {
				return;
			}

			/**
			 * Filters whether to flush the rewrite rules.
			 *
			 * @since 2.1.0
			 *
			 * @param boolean $should_flush  Whether to flush rewrite rules. The value should be true if the rules should be flushed otherwise false.
			 * @param array   $post_options Array of post options.
			 */
			$learndash_flush_rewrite_rules = apply_filters( 'learndash_flush_rewrite_rules', $flush, $this->post_options );

			if ( $learndash_flush_rewrite_rules ) {

				// Set our flag so we know we have already been here.
				$rewrite_flushed = true;

				// We set a transient. This is checked during the 'shutdown' action where the rewrites will then be flushed.
				learndash_setup_rewrite_flush();
			}
		}


		/**
		 * Sets up taxonomy to be registered, does not actually register the taxonomy
		 *
		 * Filter callback for 'sfwd_cpt_register_tax'
		 *
		 * @since 2.1.0
		 *
		 * @param  array $tax_data Taxonomy data.
		 * @return array $tax_data
		 */
		public function register_tax( $tax_data ) {
			if ( ! is_array( $tax_data ) ) {
				$tax_data = array();
			}

			if ( is_array( $this->taxonomies ) ) {
				foreach ( $this->taxonomies as $k_tax_slug => $t_tax_options ) {
					if ( $k_tax_slug !== $t_tax_options ) {

						/**
						 * Filters taxonomy registration options.
						 *
						 * @since 2.1.0
						 *
						 * @param array  $taxonomy_options An array of taxonomy options.
						 * @param string $post_type        Post type slug.
						 * @param string $taxonomy_slug    Taxonomy slug.
						 */
						$t_tax_options = apply_filters( 'sfwd_cpt_tax', $t_tax_options, $this->post_type, $k_tax_slug );
					}

					if ( ! empty( $t_tax_options ) ) {
						if ( ! isset( $tax_data[ $k_tax_slug ] ) ) {
							$tax_data[ $k_tax_slug ] = array(
								'post_types' => array( $this->post_type ),
								'tax_args'   => $t_tax_options,
							);
						} elseif ( isset( $tax_data[ $k_tax_slug ]['post_types'] ) ) {
							$tax_data[ $k_tax_slug ]['post_types'] = array_merge( $tax_data[ $k_tax_slug ]['post_types'], array( $this->post_type ) );
						}
					}
				}
			}

			return $tax_data;
		}

		/**
		 * Shortcode that generates a list of items in this post type
		 *
		 * @since 2.1.0
		 *
		 * @param  array  $atts    shortcode attributes.
		 * @param  string $content short content.
		 * @return string            shortcode output
		 */
		public static function loop_shortcode( $atts, $content = null ) {
			global $learndash_shortcode_used;

			$args = array(
				'pagination'      => '',
				'paged'           => 1,
				'pager_context'   => '',
				'posts_per_page'  => '',
				'query'           => '',
				'category'        => '',
				'post_type'       => '',
				'order'           => '',
				'orderby'         => '',
				'post__in'        => '',
				'include'         => '',
				'meta_key'        => '',
				'meta_value'      => '',
				'taxonomy'        => '',
				'tax_field'       => '',
				'tax_terms'       => '',
				'user_id'         => null,
				'course_id'       => 0,
				'topic_list_type' => '',
				'return'          => 'text', /* text or array */
			);

			if ( ! empty( $atts ) ) {
				foreach ( $atts as $k => $v ) {
					if ( '' === $v ) {
						unset( $atts[ $k ] );
					}
				}
			}

			$filter = shortcode_atts( $args, $atts );
			extract( shortcode_atts( $args, $atts ) ); // phpcs:ignore WordPress.PHP.DontExtract.extract_extract -- Bad idea, but better keep it for now.
			$sno = 1;

			if ( ( 'true' === $pagination ) && ( isset( $posts_per_page ) ) && ( ! empty( $posts_per_page ) ) ) {
				if ( ! isset( $atts['paged'] ) ) {
					global $paged;
				}

				$query   .= '&paged=' . $paged;
				$start_no = intval( $posts_per_page ) * ( intval( $paged ) - 1 ) + 1;
				$sno      = $start_no;
			}

			if ( ! empty( $category ) ) {
				$query .= '&category_name=' . $category;
			}

			foreach ( array( 'post_type', 'order', 'orderby', 'meta_key', 'meta_value', 'query' ) as $field ) {
				if ( ! empty( $$field ) ) {
					$query .= "&$field=" . $$field;
				}
			}

			if ( ( isset( $include ) ) && ( ! empty( $include ) ) ) {
				$query .= '&include=' . $include;
			}

			$query = wp_parse_args( $query, $filter );

			if ( ! empty( $taxonomy ) && ! empty( $tax_field ) && ! empty( $tax_terms ) ) {
				$query['tax_query'] = array(
					array(
						'taxonomy' => $taxonomy,
						'field'    => $tax_field,
						'terms'    => explode( ',', $tax_terms ),
					),
				);
			}

			if ( ( isset( $query['post__in'] ) ) && ( ! empty( $query['post__in'] ) ) ) {
				if ( is_string( $query['post__in'] ) ) {
					$query['post__in'] = explode( ',', $query['post__in'] );
				}
			} elseif ( ( isset( $query['include'] ) ) && ( ! empty( $query['include'] ) ) ) {
				$query['post__in'] = explode( ',', $query['include'] );
				$query['post__in'] = array_map( 'trim', $query['post__in'] );
				unset( $query['include'] );
			}

			$query_posts = new WP_Query( $query );
			if ( $query_posts->have_posts() ) {
				$posts = $query_posts->posts;
			} else {
				$posts = array();
			}

			if ( 'array' === $return ) {
				$buf = array();
			} else {
				$buf = '';
			}

			if ( empty( $user_id ) ) {
				$user_id = get_current_user_id();
			}

			foreach ( $posts as $post ) {
				$id                    = $post->ID; // allow use of id variable in template.
				$class                 = '';
				$status                = '';
				$sample                = '';
				$sub_title             = '';
				$ld_lesson_access_from = '';

				if ( 'sfwd-quiz' === $post->post_type ) {

					$sample = ( learndash_is_sample( $post ) ) ? 'is_sample' : 'is_not_sample';
					$id    .= ' class="' . $sample . '"';
					$status = ( learndash_is_quiz_notcomplete( $user_id, array( $post->ID => 1 ), false, $course_id ) ) ? 'notcompleted' : 'completed';

				} elseif ( 'sfwd-lessons' === $post->post_type ) {

					$sample = ( learndash_is_sample( $post ) ) ? 'is_sample' : 'is_not_sample';
					$id    .= ' class="' . $sample . '"';

					if ( ! learndash_is_lesson_notcomplete( $user_id, array( $post->ID => 1 ), $course_id ) ) {
						$status = 'completed';
					} else {
						$ld_lesson_access_from = ld_lesson_access_from( $post->ID, $user_id, $course_id );

						if ( empty( $ld_lesson_access_from ) ) {
							$status = 'notcompleted';
						} else {
							$status        = 'notavailable';
								$sub_title = SFWD_LMS::get_template(
									'learndash_course_lesson_not_available',
									array(
										'user_id'   => $user_id,
										'course_id' => learndash_get_course_id( $post->ID ),
										'lesson_id' => $post->ID,
										'lesson_access_from_int' => $ld_lesson_access_from,
										'lesson_access_from_date' => learndash_adjust_date_time_display( $ld_lesson_access_from ),
										'context'   => 'loop_content_shortcode',
									),
									false
								);
						}
					}

					if ( empty( $sub_title ) && ! empty( $topic_list_type ) ) {
						$sub_title .= learndash_topic_dots( $post->ID, false, $topic_list_type, $user_id, $course_id );
					}
				}

				if ( 'course_id' !== $meta_key ) {
					$show_content = true;
				} else {
					$show_content = self::show_content( $post );
				}

				if ( $show_content ) {
					$permalink = get_permalink( $post->ID );

					if ( 'array' === $return ) {
						$buf[ $sno ] = array(
							'sno'                => $sno,
							'post'               => $post,
							'sub_title'          => $sub_title,
							'status'             => $status,
							'sample'             => $sample,
							'lesson_access_from' => $ld_lesson_access_from,
						);

						if ( ( isset( $course_id ) ) && ( ! empty( $course_id ) ) && ( LearnDash_Settings_Section::get_section_setting( 'LearnDash_Settings_Section_Permalinks', 'nested_urls' ) == 'yes' ) ) {
							$buf[ $sno ]['permalink'] = learndash_get_step_permalink( $post->ID, $course_id );
						} else {
							$buf[ $sno ]['permalink'] = get_permalink( $post->ID );
						}
					} else {
						$show_content = str_replace( '{learndash_completed_class}', 'class="' . $status . '"', $content );
						$show_content = str_replace( '{the_title}', $post->post_title, $show_content );
						if ( ( isset( $course_id ) ) && ( ! empty( $course_id ) ) && ( LearnDash_Settings_Section::get_section_setting( 'LearnDash_Settings_Section_Permalinks', 'nested_urls' ) == 'yes' ) ) {
							$show_content = str_replace( '{the_permalink}', learndash_get_step_permalink( $post->ID, $course_id ), $show_content );
						} else {
							$show_content = str_replace( '{the_permalink}', get_permalink( $post->ID ), $show_content );
						}

						$show_content = str_replace( '{sub_title}', $sub_title, $show_content );
						$show_content = str_replace( '$id', "$id", $show_content );
						$show_content = str_replace( '{sno}', $sno, $show_content );
						$buf         .= do_shortcode( $show_content );
					}
				}

				if ( ! empty( $show_content ) ) {
					$sno++;
				}
			}

			if ( 'true' === $pagination ) {

				/**
				 * Fires after the course lesson list pagination.
				 *
				 * @param WP_Query $query_posts   Course lesson list WP_Query object.
				 * @param string   $pager_context The context where pagination is shown.
				 */
				do_action( 'learndash_course_lessons_list_pager', $query_posts, $pager_context );
			}
			$learndash_shortcode_used = true;

			return $buf;
		}

		/**
		 * To show content or not
		 *
		 * @since 2.1.0
		 *
		 * @param  object $post WP_Post.
		 * @return bool
		 */
		public static function show_content( $post ) {
			if ( 'sfwd-quiz' === $post->post_type ) {
				if ( learndash_is_course_builder_enabled() ) {
					$course_id = learndash_get_course_id( $post );
					$lesson_id = learndash_course_get_single_parent_step( $course_id, $post->ID );
				} else {
					$lesson_id = learndash_get_setting( $post, 'lesson' );
				}
				return empty( $lesson_id );
			} else {
				return true;
			}
		}

		/**
		 * Set up shortcode for custom post type
		 *
		 * @todo  evaluate if this shortcode is still being used
		 *        called from sfwd_lms.php
		 *        accepts $code as an argument, but $code doesn't exist
		 *
		 * @since 2.1.0
		 *
		 * @param  array  $atts    shortcode attributes.
		 * @param  string $content short content.
		 * @param  string $code    post type.
		 * @return string            shortcode output
		 */
		public function shortcode( $atts, $content = null, $code = '' ) {
			global $learndash_shortcode_used;

			extract( // phpcs:ignore WordPress.PHP.DontExtract.extract_extract -- Bad idea, but better keep it for now.
				shortcode_atts(
					array(
						'post_type'       => $code,
						'posts_per_page'  => -1,
						'taxonomy'        => '',
						'tax_field'       => '',
						'tax_terms'       => '',
						'meta_key'        => '',
						'meta_value'      => '',
						'order'           => 'DESC',
						'orderby'         => 'date',
						'wrapper'         => 'div',
						'title'           => 'h4',
						'topic_list_type' => 'dots',
						'post__in'        => '',
					),
					$atts
				)
			);

			global $shortcode_tags;
			$save_tags = $shortcode_tags;

			add_shortcode( 'loop', array( $this, 'loop_shortcode' ) );

			$template = "[loop post_type='$post_type' posts_per_page='$posts_per_page' meta_key='{$meta_key}' meta_value='{$meta_value}' order='$order' orderby='$orderby' taxonomy='$taxonomy' tax_field='$tax_field' tax_terms='$tax_terms' post__in='" . $post__in . "' topic_list_type='" . $topic_list_type . "']"
			. "<$wrapper id=post-\$id><$title><a {learndash_completed_class} href='{the_permalink}'>{the_title}</a>{sub_title}</$title>"
			. "</$wrapper>[/loop]";

			/**
			 * Filters custom post type shortcode content.
			 *
			 * @param string $template Shortcode template content.
			 */
			$template = apply_filters( 'sfwd_cpt_template', $template );
			$buf      = do_shortcode( $template );

			$shortcode_tags = $save_tags; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- I suppose it's what they wanted.

			$learndash_shortcode_used = true;

			return $buf;
		}



		/**
		 * Get settings for post type
		 *
		 * @since 2.1.0
		 *
		 * @param  string $location post type.
		 * @return array  $setting  post type setting
		 */
		public function get_settings_values( $location = null ) {
			$settings = $this->setting_options( $location );
			$values   = $this->get_current_options( array(), $location );

			foreach ( $settings as $k => $v ) {
				if ( isset( $values[ $k ] ) ) {
					$settings[ $k ]['value'] = $values[ $k ];
				}
			}

			return $settings;
		}



		/**
		 * Output the settings for post type
		 *
		 * @since 2.1.0
		 *
		 * @param  string $location post type.
		 */
		public function display_settings_values( $location = null ) {
			$meta = $this->get_settings_values( $location );

			if ( ! empty( $meta ) ) {
				?>
					<ul class='post-meta'>
						<?php
						foreach ( $meta as $m ) {
							echo "<li><span class='post-meta-key'>" . esc_html( $m['name'] ) . '</span> ' . esc_html( $m['value'] ) . "</li>\n";
						}
						?>
					</ul>
				<?php
			}
		}
	}
}
