<?php
/**
 * Register custom post type and taxonomies.
 *
 * @package wpcode
 */

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

add_action( 'init', 'wpcode_register_post_type', - 5 );
add_action( 'init', 'wpcode_register_taxonomies', - 5 );
add_filter( 'update_post_term_count_statuses', 'wpcode_taxonomies_count_drafts', 10, 2 );
add_action( 'wpcode_before_snippet_save', 'wpcode_maybe_remove_core_content_filters' );
add_action( 'wpcode_snippet_after_update', 'wpcode_restore_core_content_filters' );
add_filter( 'wp_import_post_data_raw', 'wpcode_prevent_wp_importer_import' );
add_filter( 'wp_insert_post_empty_content', 'wpcode_block_unauthorized_snippet_writes', 10, 2 );

/**
 * Register the post type for snippets.
 *
 * @return void
 */
function wpcode_register_post_type() {
	register_post_type(
		'wpcode',
		array(
			'public'          => false,
			'show_ui'         => false,
			'can_export'      => false,
			'capability_type' => array( 'wpcode_snippet', 'wpcode_snippets' ),
			'map_meta_cap'    => true,
			'capabilities'    => array(
				'edit_posts'             => 'wpcode_edit_snippets',
				'edit_others_posts'      => 'wpcode_edit_snippets',
				'delete_posts'           => 'wpcode_edit_snippets',
				'publish_posts'          => 'wpcode_activate_snippets',
				'read_private_posts'     => 'wpcode_edit_snippets',
				'read'                   => 'read',
				'create_posts'           => 'wpcode_edit_snippets',
				'delete_private_posts'   => 'wpcode_edit_snippets',
				'delete_published_posts' => 'wpcode_edit_snippets',
				'delete_others_posts'    => 'wpcode_edit_snippets',
				'edit_private_posts'     => 'wpcode_edit_snippets',
				'edit_published_posts'   => 'wpcode_edit_snippets',
			),
		)
	);
}

/**
 * Block wp_insert_post writes to the wpcode post type from unauthorized users and XML-RPC.
 *
 * @param bool  $maybe_empty Whether to treat the post as empty (abort save).
 * @param array $postarr     The post data being inserted.
 *
 * @return bool
 */
function wpcode_block_unauthorized_snippet_writes( $maybe_empty, $postarr ) {
	if ( empty( $postarr['post_type'] ) || 'wpcode' !== $postarr['post_type'] ) {
		return $maybe_empty;
	}

	if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
		return true;
	}

	if ( ! current_user_can( 'wpcode_edit_snippets' ) ) {
		return true;
	}

	return $maybe_empty;
}

/**
 * Register the custom taxonomies used for snippets.
 *
 * @return void
 */
function wpcode_register_taxonomies() {
	register_taxonomy(
		'wpcode_type',
		'wpcode',
		array(
			'public' => false,
		)
	);
	register_taxonomy(
		'wpcode_location',
		'wpcode',
		array(
			'public' => false,
		)
	);
	register_taxonomy(
		'wpcode_tags',
		'wpcode',
		array(
			'public' => false,
		)
	);
}

/**
 * Count draft (inactive) snippets as part of our custom taxonomies count.
 *
 * @param array       $statuses The statuses to include in the count.
 * @param WP_Taxonomy $taxonomy The taxonomy object.
 *
 * @return array
 */
function wpcode_taxonomies_count_drafts( $statuses, $taxonomy ) {
	$taxonomies = array(
		'wpcode_type',
		'wpcode_location',
		'wpcode_tags',
	);
	if ( in_array( $taxonomy->name, $taxonomies, true ) ) {
		$statuses[] = 'draft';
	}

	return $statuses;
}

/**
 * Remove core filters that may interfere with snippet saving.
 *
 * @param WPCode_Snippet $snippet The snippet being saved.
 *
 * @return void
 */
function wpcode_maybe_remove_core_content_filters( $snippet ) {
	// Prevent content_save_pre from modifying the snippet content.
	remove_all_filters( 'content_save_pre' );

	if ( ! function_exists( 'wp_remove_targeted_link_rel_filters' ) || version_compare( get_bloginfo( 'version' ), '6.7', '>=' ) ) {
		// This function is only available in WP 5.1+.
		return;
	}
	/**
	 * Filters the code types that should keep the core filters.
	 *
	 * @param array $code_types_to_keep_filters The code types that should keep the core filters.
	 */
	$code_types_to_keep_filters = apply_filters(
		'wpcode_code_types_to_keep_core_content_filters',
		array(
			'text',
			'html',
		)
	);
	if ( ! in_array( $snippet->get_code_type(), $code_types_to_keep_filters, true ) ) {
		wp_remove_targeted_link_rel_filters();
	}
}

/**
 * Add back the core filters that were removed when saving a snippet.
 *
 * @return void
 */
function wpcode_restore_core_content_filters() {
	if ( ! function_exists( 'wp_init_targeted_link_rel_filters' ) || version_compare( get_bloginfo( 'version' ), '6.7', '>=' ) ) {
		// This function is only available in WP 5.1+.
		return;
	}
	wp_init_targeted_link_rel_filters();
}

/**
 * Prevent the WP Importer plugin from importing snippets.
 *
 * @param array $post_data The post data.
 *
 * @return array
 */
function wpcode_prevent_wp_importer_import( $post_data ) {
	if ( 'wpcode' === $post_data['post_type'] ) {
		$post_data['post_type']    = '';
		$post_data['post_content'] = '';
	}

	return $post_data;
}
