<?php
/**
 * Ability to interact with post data.
 */

if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

/**
 * Vc_Post_Admin class.
 *
 * @since 4.4
 */
class Vc_Post_Admin {
	/**
	 * Add hooks required to save, update and manipulate post
	 */
	public function init() {
		// hooks for backend editor.
		add_action( 'save_post', [ $this, 'save' ] );
		// hooks for frontend editor.
		add_action( 'wp_ajax_vc_save', [ $this, 'saveAjaxFe' ] );

		add_filter( 'content_save_pre', 'wpb_remove_custom_html' );
	}

	/**
	 * Update post frontend editor ajax processing.
	 *
	 * @throws Exception
	 */
	public function saveAjaxFe() {
		$post_id = intval( vc_post_param( 'post_id' ) );
		vc_user_access()->checkAdminNonce()->validateDie()->wpAny( 'edit_posts', 'edit_pages' )->validateDie()->canEdit( $post_id )->validateDie();

		if ( 0 === $post_id ) {
			wp_send_json_error();
		}

		$this->update_post_data( $post_id );

		wp_send_json_success();
	}

	/**
	 * Update post_content, title and etc.
	 *
	 * @since 7.4
	 * @param int $post_id
	 * @throws Exception
	 */
	public function update_post_data( $post_id ) {
		ob_start();

		if ( ! vc_post_param( 'content' ) ) {
			return;
		}

		$post = get_post( $post_id );

		/**
		 * Filter post data before we update it with our plugin.
		 *
		 * @since 7.7
		 * @param WP_Post $post
		 */
		$post = apply_filters( 'vc_before_update_post_data', $post );

		$post = $this->set_post_content( $post );

		$post = $this->set_post_title( $post );

		$post = $this->set_post_status( $post );

		if ( vc_user_access()->part( 'unfiltered_html' )->checkStateAny( true, null )->get() ) {
			kses_remove_filters();
		}
		remove_filter( 'content_save_pre', 'balanceTags', 50 );

		wp_update_post( $post );

		$this->setPostMeta( $post_id );

		wp_cache_flush();
		ob_clean();
	}

	/**
	 * Save plugin post meta and post fields.
	 *
	 * @param int $post_id
	 *
	 * @since 4.4
	 */
	public function save( $post_id ) {
		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE || vc_is_inline() ) {
			return;
		}
		$this->setPostMeta( $post_id );
	}

	/**
	 * Saves VC Backend editor meta box visibility status.
	 *
	 * If post param 'wpb_vc_js_status' set to true, then methods adds/updated post
	 * meta option with tag '_wpb_vc_js_status'.
	 *
	 * @param int $post_id
	 * @since 4.4
	 */
	public function setJsStatus( $post_id ) {
		$value = vc_post_param( 'wpb_vc_js_status' );
		if ( null === $value ) {
			delete_post_meta( $post_id, '_wpb_vc_js_status', get_post_meta( $post_id, '_wpb_vc_js_status', true ) );
		} elseif ( '' === get_post_meta( $post_id, '_wpb_vc_js_status' ) ) {
				add_post_meta( $post_id, '_wpb_vc_js_status', $value, true );
		} elseif ( get_post_meta( $post_id, '_wpb_vc_js_status', true ) !== $value ) {
			update_post_meta( $post_id, '_wpb_vc_js_status', $value );
		} elseif ( '' === $value ) {
			delete_post_meta( $post_id, '_wpb_vc_js_status', get_post_meta( $post_id, '_wpb_vc_js_status', true ) );
		}
	}

	/**
	 * Saves VC interface version which is used for building post content.
	 *
	 * @param int $post_id
	 * @since 4.4
	 * @todo check is it used everywhere and is it needed?!
	 * @deprecated not needed anywhere
	 */
	public function setInterfaceVersion( $post_id ) { // phpcs:ignore:Generic.CodeAnalysis.UnusedFunctionParameter.Found
		_deprecated_function( '\Vc_Post_Admin::setInterfaceVersion', '4.4', '' );
	}

	/**
	 * Set Post Settings for VC.
	 *
	 * It is possible to add any data to post settings by adding filter with tag 'vc_hooks_vc_post_settings'.
	 *
	 * @param int $post_id
	 * @since 4.4
	 * vc_filter: vc_hooks_vc_post_settings - hook to override
	 * post meta settings for WPBakery Page Builder (used in grid for example)
	 */
	public function setSettings( $post_id ) {
		$settings = array();
		$settings = apply_filters( 'vc_hooks_vc_post_settings', $settings, $post_id, get_post( $post_id ) );
		if ( is_array( $settings ) && ! empty( $settings ) ) {
			update_post_meta( $post_id, '_vc_post_settings', $settings );
		} else {
			delete_post_meta( $post_id, '_vc_post_settings' );
		}
	}

	/**
	 * Set post content.
	 *
	 * @since 7.4
	 * @param WP_Post $post
	 * @return WP_Post $post
	 */
	public function set_post_content( $post ) {
		$post->post_content = stripslashes( vc_post_param( 'content' ) );

		return $post;
	}

	/**
	 * Set post title.
	 *
	 * @since 7.4
	 * @param WP_Post $post
	 * @return WP_Post $post
	 */
	public function set_post_title( $post ) {
		$post_title = vc_post_param( 'post_title' );
		if ( null !== $post_title ) {
			$post->post_title = $post_title;
		}

		return $post;
	}

	/**
	 * Set post status.
	 *
	 * @since 7.4
	 * @param WP_Post $post
	 * @return WP_Post $post
	 */
	public function set_post_status( $post ) {
		$post_status = vc_post_param( 'post_status' );
		if ( $post_status && 'publish' === $post_status ) {
			if ( vc_user_access()->wpAll( [
				get_post_type_object( $post->post_type )->cap->publish_posts,
				$post->ID,
			] )->get() ) {
				if ( 'private' !== $post->post_status && 'future' !== $post->post_status ) {
					$post->post_status = 'publish';
				}
			} else {
				$post->post_status = 'pending';
			}
		}

		return $post;
	}

	/**
	 * Set plugin meta to specific post.
	 *
	 * @param int $id
	 * @throws Exception
	 */
	protected function setPostMeta( $id ) {
		if ( ! vc_user_access()->wpAny( array(
			'edit_post',
			$id,
		) )->get() ) {
			return;
		}

		$this->setJsStatus( $id );
		if ( 'dopreview' === vc_post_param( 'wp-preview' ) && wp_revisions_enabled( get_post( $id ) ) ) {
			$latest_revision = wp_get_post_revisions( $id );
			if ( ! empty( $latest_revision ) ) {
				$array_values = array_values( $latest_revision );
				$id = $array_values[0]->ID;
			}
		}

		if ( 'dopreview' !== vc_post_param( 'wp-preview' ) ) {
			$this->setSettings( $id );
		}

		$meta_list = $this->get_post_meta_list();

		$this->setPostMetaByList( $id, $meta_list );

		$types = [
			'default',
			'custom',
		];
		foreach ( $types as $type ) {
			wpbakery()->buildShortcodesCss( $id, $type );
		}
	}

	/**
	 * Get post meta list.
	 *
	 * @since 7.0
	 *
	 * @return array
	 */
	public function get_post_meta_list() {
		// we add value to it in our modules.
		return apply_filters( 'vc_post_meta_list', [] );
	}

	/**
	 * Set post meta by meta list.
	 *
	 * @note we keep this data for meta in regular $_POST
	 * @see include/templates/editors/partials/vc_post_custom_meta.tpl.php
	 * @note we also additionally save data for frontend editor in ajax request to push it in $_POST
	 * and save it than in that method
	 * @see assets/js/frontend_editor/shortcodes_builder.js ShortcodesBuilder::save()
	 * @since 7.0
	 *
	 * @param int $id
	 * @param array $meta_list
	 */
	public function setPostMetaByList( $id, $meta_list ) {
		foreach ( $meta_list as $meta_name ) {
			$post_param = vc_post_param( 'vc_post_' . $meta_name );
			$value = apply_filters( 'vc_base_save_post_' . $meta_name, $post_param, $id );
			if ( null !== $value && empty( $value ) ) {
				delete_metadata( 'post', $id, '_wpb_post_' . $meta_name );
			} elseif ( null !== $value ) {
				$value = wp_strip_all_tags( $value );
				update_metadata( 'post', $id, '_wpb_post_' . $meta_name, $value );
			}
		}
	}
}
