<commit_before><?php
/**
 * AMP Story Templates handler.
 *
 * @package AMP
 * @since 1.?
 */

/**
 * Class AMP_Story_Templates
 */
class AMP_Story_Templates {

	/**
	 * Current version of the templates.
	 *
	 * @var string
	 */
	const STORY_TEMPLATES_VERSION = '0.1';

	/**
	 * Slug for templates' taxonomy.
	 */
	const TEMPLATES_TAXONOMY = 'amp_template';

	/**
	 * Slug for templates term.
	 */
	const TEMPLATES_TERM = 'story-template';

	/**
	 * Init.
	 */
	public function init() {
		if ( ! post_type_exists( 'amp_story' ) ) {
			return;
		}

		add_filter( 'rest_wp_block_query', array( $this, 'filter_rest_wp_block_query' ), 10, 2 );
		add_action( 'save_post_wp_block', array( $this, 'flag_template_as_modified' ) );

		// Temporary filters for disallowing the users to edit any templates until the feature has been implemented.
		add_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ), 10, 3 );
		add_filter( 'pre_get_posts', array( $this, 'filter_pre_get_posts' ) );

		$this->register_taxonomy();
		$this->maybe_import_story_templates();
	}

	/**
	 * Temporarily hide editing option for Templates.
	 *
	 * @param  array  $allcaps Existing capabilities for the user.
	 * @param  string $caps    Capabilities provided by map_meta_cap().
	 * @param  array  $args    Arguments for current_user_can().
	 * @return array Modified capabilities.
	 */
	public function filter_user_has_cap( $allcaps, $caps, $args ) {
		if ( 'edit_post' === $args[0] && isset( $args[2] ) ) {
			if ( has_term( self::TEMPLATES_TERM, self::TEMPLATES_TAXONOMY, $args[2] ) ) {
				unset( $allcaps['edit_others_posts'] );
				unset( $allcaps['edit_published_posts'] );
			}
		}
		return $allcaps;
	}

	/**
	 * Temporarily filter pre_get_posts to not display templates in the list of reusable blocks.
	 *
	 * @param object $query WP_Query object.
	 * @return object WP Query modified object.
	 */
	public function filter_pre_get_posts( $query ) {
		global $pagenow;

		if ( 'edit.php' !== $pagenow || ! $query->is_admin ) {
			return $query;
		}

		if ( 'wp_block' !== $query->get( 'post_type' ) ) {
			return $query;
		}

		$tax_query = $query->get( 'tax_query' );
		if ( empty( $tax_query ) ) {
			$tax_query = array();
		}

		$tax_query[] = array(
			'taxonomy' => self::TEMPLATES_TAXONOMY,
			'field'    => 'slug',
			'terms'    => array( self::TEMPLATES_TERM ),
			'operator' => 'NOT IN',
		);

		$query->set( 'tax_query', $tax_query );
		return $query;
	}

	/**
	 * Import story templates if they haven't been imported previously.
	 */
	private function maybe_import_story_templates() {
		if ( self::STORY_TEMPLATES_VERSION === AMP_Options_Manager::get_option( 'story_templates_version' ) ) {
			return;
		}
		$this->import_story_templates();
		// @todo This is commented out for testing purposes until the PR gets ready.
		// AMP_Options_Manager::update_option( 'story_templates_version', self::STORY_TEMPLATES_VERSION );
	}

	/**
	 * Import logic for story templates.
	 */
	public function import_story_templates() {
		$templates = self::get_story_templates();
		foreach ( $templates as $template ) {
			$existing_template = $this->template_exists( $template['name'] );
			if ( $existing_template > 0 ) {
				continue;
			}
			$post_content = file_get_contents( AMP__DIR__ . '/includes/templates/story-templates/' . $template['name'] . '.html' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
			if ( ! empty( $post_content ) ) {
				$post_id = wp_insert_post(
					wp_slash(
						array(
							'post_title'   => $template['title'],
							'post_type'    => 'wp_block',
							'post_status'  => 'publish',
							'post_content' => $post_content,
							'post_name'    => $template['name'],
						)
					)
				);
				if ( ! $post_id ) {
					continue;
				}
				wp_set_object_terms( $post_id, self::TEMPLATES_TERM, self::TEMPLATES_TAXONOMY );
				add_post_meta( $post_id, 'amp_template_unmodified', true );
			}
		}
	}

	/**
	 * Get the static list of templates, including temlate name and content.
	 *
	 * @return array Story templates.
	 */
	public static function get_story_templates() {
		return array(
			array(
				'title' => __( 'Template: Travel Tip', 'amp' ),
				'name'  => 'travel-tip',
			),
		);
	}

	/**
	 * Determine if a post exists based on slug.
	 *
	 * @param string $slug Post slug.
	 * @return int Post ID if post exists, 0 otherwise.
	 */
	private function template_exists( $slug ) {
		if ( empty( $slug ) ) {
			return 0;
		}

		$args      = array(
			'name'           => $slug,
			'post_type'      => 'wp_block',
			'post_status'    => 'publish',
			'posts_per_page' => 1,
		);
		$templates = get_posts( $args );
		if ( ! empty( $templates ) ) {
			return $templates[0]->ID;
		}

		return 0;
	}

	/**
	 * Register taxonomy for differentiating AMP Story Templates.
	 */
	private function register_taxonomy() {
		register_taxonomy(
			self::TEMPLATES_TAXONOMY,
			'wp_block',
			array(
				'query_var'             => self::TEMPLATES_TAXONOMY,
				'show_admin_column'     => false,
				'show_in_rest'          => true,
				'rest_base'             => self::TEMPLATES_TAXONOMY . 's',
				'rest_controller_class' => 'WP_REST_Terms_Controller',
				'public'                => false,
				'show_ui'               => false,
				'show_tagcloud'         => false,
				'show_in_quick_edit'    => false,
				'hierarchical'          => false,
				'show_in_menu'          => false,
				'meta_box_cb'           => false,
			)
		);

		if ( ! term_exists( self::TEMPLATES_TERM, self::TEMPLATES_TAXONOMY ) ) {
			wp_insert_term(
				__( 'Story Template', 'amp' ),
				self::TEMPLATES_TAXONOMY,
				array(
					'description' => __( 'Story Template', 'amp' ),
					'slug'        => self::TEMPLATES_TERM,
				)
			);
		}
	}

	/**
	 * Filter REST request for reusable blocks to not display templates under Reusable Blocks within other posts.
	 *
	 * @param array           $args Original args.
	 * @param WP_REST_Request $request WP REST Request object.
	 * @return array Args.
	 */
	public function filter_rest_wp_block_query( $args, $request ) {
		$headers = $request->get_headers();
		if ( ! isset( $headers['referer'][0] ) ) {
			return $args;
		}

		$parts = wp_parse_url( $headers['referer'][0] );
		if ( ! isset( $parts['query'] ) ) {
			return $args;
		}
		parse_str( $parts['query'], $params );
		if ( ! isset( $params['post'] ) || ! isset( $params['action'] ) ) {
			return $args;
		}

		$edited_post = get_post( absint( $params['post'] ) );
		if ( AMP_Story_Post_Type::POST_TYPE_SLUG !== $edited_post->post_type ) {
			if ( ! isset( $args['tax_query'] ) ) {
				$args['tax_query'] = array();
			}
			$args['tax_query'][] = array(
				'taxonomy' => self::TEMPLATES_TAXONOMY,
				'field'    => 'slug',
				'terms'    => array( self::TEMPLATES_TERM ),
				'operator' => 'NOT IN',
			);
		}

		return $args;
	}

	/**
	 * Flag template as modified when it's being saved.
	 *
	 * @param int $post_id Post ID.
	 */
	public function flag_template_as_modified( $post_id ) {
		if ( ! has_term( self::TEMPLATES_TERM, self::TEMPLATES_TAXONOMY, $post_id ) ) {
			return;
		}

		if ( true === (bool) get_post_meta( $post_id, 'amp_template_unmodified', true ) ) {
			update_post_meta( $post_id, 'amp_template_unmodified', false );
		}
	}
}
<commit_msg>Add new templates.<commit_after><?php
/**
 * AMP Story Templates handler.
 *
 * @package AMP
 * @since 1.?
 */

/**
 * Class AMP_Story_Templates
 */
class AMP_Story_Templates {

	/**
	 * Current version of the templates.
	 *
	 * @var string
	 */
	const STORY_TEMPLATES_VERSION = '0.1';

	/**
	 * Slug for templates' taxonomy.
	 */
	const TEMPLATES_TAXONOMY = 'amp_template';

	/**
	 * Slug for templates term.
	 */
	const TEMPLATES_TERM = 'story-template';

	/**
	 * Init.
	 */
	public function init() {
		if ( ! post_type_exists( 'amp_story' ) ) {
			return;
		}

		add_filter( 'rest_wp_block_query', array( $this, 'filter_rest_wp_block_query' ), 10, 2 );
		add_action( 'save_post_wp_block', array( $this, 'flag_template_as_modified' ) );

		// Temporary filters for disallowing the users to edit any templates until the feature has been implemented.
		add_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ), 10, 3 );
		add_filter( 'pre_get_posts', array( $this, 'filter_pre_get_posts' ) );

		$this->register_taxonomy();
		$this->maybe_import_story_templates();
	}

	/**
	 * Temporarily hide editing option for Templates.
	 *
	 * @param  array  $allcaps Existing capabilities for the user.
	 * @param  string $caps    Capabilities provided by map_meta_cap().
	 * @param  array  $args    Arguments for current_user_can().
	 * @return array Modified capabilities.
	 */
	public function filter_user_has_cap( $allcaps, $caps, $args ) {
		if ( 'edit_post' === $args[0] && isset( $args[2] ) ) {
			if ( has_term( self::TEMPLATES_TERM, self::TEMPLATES_TAXONOMY, $args[2] ) ) {
				unset( $allcaps['edit_others_posts'] );
				unset( $allcaps['edit_published_posts'] );
			}
		}
		return $allcaps;
	}

	/**
	 * Temporarily filter pre_get_posts to not display templates in the list of reusable blocks.
	 *
	 * @param object $query WP_Query object.
	 * @return object WP Query modified object.
	 */
	public function filter_pre_get_posts( $query ) {
		global $pagenow;

		if ( 'edit.php' !== $pagenow || ! $query->is_admin ) {
			return $query;
		}

		if ( 'wp_block' !== $query->get( 'post_type' ) ) {
			return $query;
		}

		$tax_query = $query->get( 'tax_query' );
		if ( empty( $tax_query ) ) {
			$tax_query = array();
		}

		$tax_query[] = array(
			'taxonomy' => self::TEMPLATES_TAXONOMY,
			'field'    => 'slug',
			'terms'    => array( self::TEMPLATES_TERM ),
			'operator' => 'NOT IN',
		);

		$query->set( 'tax_query', $tax_query );
		return $query;
	}

	/**
	 * Import story templates if they haven't been imported previously.
	 */
	private function maybe_import_story_templates() {
		if ( self::STORY_TEMPLATES_VERSION === AMP_Options_Manager::get_option( 'story_templates_version' ) ) {
			return;
		}
		$this->import_story_templates();
		// @todo This is commented out for testing purposes until the PR gets ready.
		// AMP_Options_Manager::update_option( 'story_templates_version', self::STORY_TEMPLATES_VERSION );
	}

	/**
	 * Import logic for story templates.
	 */
	public function import_story_templates() {
		$templates = self::get_story_templates();
		foreach ( $templates as $template ) {
			$existing_template = $this->template_exists( $template['name'] );
			if ( $existing_template > 0 ) {
				continue;
			}
			$post_content = @file_get_contents( AMP__DIR__ . '/includes/templates/story-templates/' . $template['name'] . '.html' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
			if ( ! empty( $post_content ) ) {
				$post_id = wp_insert_post(
					wp_slash(
						array(
							'post_title'   => $template['title'],
							'post_type'    => 'wp_block',
							'post_status'  => 'publish',
							'post_content' => $post_content,
							'post_name'    => $template['name'],
						)
					)
				);
				if ( ! $post_id ) {
					continue;
				}
				wp_set_object_terms( $post_id, self::TEMPLATES_TERM, self::TEMPLATES_TAXONOMY );
				add_post_meta( $post_id, 'amp_template_unmodified', true );
			}
		}
	}

	/**
	 * Get the static list of templates, including temlate name and content.
	 *
	 * @return array Story templates.
	 */
	public static function get_story_templates() {
		return array(
			array(
				'title' => __( 'Template: Travel Tip', 'amp' ),
				'name'  => 'travel-tip',
			),
			array(
				'title' => __( 'Template: Quote', 'amp' ),
				'name'  => 'quote',
			),
			array(
				'title' => __( 'Template: Travel CTA', 'amp' ),
				'name'  => 'travel-cta',
			),
			// @todo This needs redoing once we have automated blocks for post data.
			array(
				'title' => __( 'Template: Title Page', 'amp' ),
				'name'  => 'title-page',
			),

		);
	}

	/**
	 * Determine if a post exists based on slug.
	 *
	 * @param string $slug Post slug.
	 * @return int Post ID if post exists, 0 otherwise.
	 */
	private function template_exists( $slug ) {
		if ( empty( $slug ) ) {
			return 0;
		}

		$args      = array(
			'name'           => $slug,
			'post_type'      => 'wp_block',
			'post_status'    => 'publish',
			'posts_per_page' => 1,
		);
		$templates = get_posts( $args );
		if ( ! empty( $templates ) ) {
			return $templates[0]->ID;
		}

		return 0;
	}

	/**
	 * Register taxonomy for differentiating AMP Story Templates.
	 */
	private function register_taxonomy() {
		register_taxonomy(
			self::TEMPLATES_TAXONOMY,
			'wp_block',
			array(
				'query_var'             => self::TEMPLATES_TAXONOMY,
				'show_admin_column'     => false,
				'show_in_rest'          => true,
				'rest_base'             => self::TEMPLATES_TAXONOMY . 's',
				'rest_controller_class' => 'WP_REST_Terms_Controller',
				'public'                => false,
				'show_ui'               => false,
				'show_tagcloud'         => false,
				'show_in_quick_edit'    => false,
				'hierarchical'          => false,
				'show_in_menu'          => false,
				'meta_box_cb'           => false,
			)
		);

		if ( ! term_exists( self::TEMPLATES_TERM, self::TEMPLATES_TAXONOMY ) ) {
			wp_insert_term(
				__( 'Story Template', 'amp' ),
				self::TEMPLATES_TAXONOMY,
				array(
					'description' => __( 'Story Template', 'amp' ),
					'slug'        => self::TEMPLATES_TERM,
				)
			);
		}
	}

	/**
	 * Filter REST request for reusable blocks to not display templates under Reusable Blocks within other posts.
	 *
	 * @param array           $args Original args.
	 * @param WP_REST_Request $request WP REST Request object.
	 * @return array Args.
	 */
	public function filter_rest_wp_block_query( $args, $request ) {
		$headers = $request->get_headers();
		if ( ! isset( $headers['referer'][0] ) ) {
			return $args;
		}

		$parts = wp_parse_url( $headers['referer'][0] );
		if ( ! isset( $parts['query'] ) ) {
			return $args;
		}
		parse_str( $parts['query'], $params );
		if ( ! isset( $params['post'] ) || ! isset( $params['action'] ) ) {
			return $args;
		}

		$edited_post = get_post( absint( $params['post'] ) );
		if ( AMP_Story_Post_Type::POST_TYPE_SLUG !== $edited_post->post_type ) {
			if ( ! isset( $args['tax_query'] ) ) {
				$args['tax_query'] = array();
			}
			$args['tax_query'][] = array(
				'taxonomy' => self::TEMPLATES_TAXONOMY,
				'field'    => 'slug',
				'terms'    => array( self::TEMPLATES_TERM ),
				'operator' => 'NOT IN',
			);
		}

		return $args;
	}

	/**
	 * Flag template as modified when it's being saved.
	 *
	 * @param int $post_id Post ID.
	 */
	public function flag_template_as_modified( $post_id ) {
		if ( ! has_term( self::TEMPLATES_TERM, self::TEMPLATES_TAXONOMY, $post_id ) ) {
			return;
		}

		if ( true === (bool) get_post_meta( $post_id, 'amp_template_unmodified', true ) ) {
			update_post_meta( $post_id, 'amp_template_unmodified', false );
		}
	}
}

{'fraction_non_alphanumeric': 0.15157401205626256, 'fraction_numerical': 0.0026791694574681848, 'mean_word_length': 3.1143565720584183, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 99, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2756740', 'n_tokens_mistral': 6092, 'n_tokens_neox': 5210, 'n_words': 1145}