* @copyright Copyright (c) 2021, Phi Phan */ namespace BoldBlocks; // Exit if accessed directly. defined( 'ABSPATH' ) || exit; if ( ! class_exists( 'Variations' ) ) : /** * Manage custom block variations */ class Variations { /** * A dummy constructor */ public function __construct() {} /** * Run main hooks * * @return void */ public function run() { // Register custom post type. add_action( 'init', [ $this, 'register_custom_post_type' ], 5 ); // Custom variation columns. add_filter( 'manage_edit-boldblocks_variation_columns', [ $this, 'add_variation_custom_columns' ] ); add_action( 'manage_boldblocks_variation_posts_custom_column', [ $this, 'manage_variation_columns' ], 10, 2 ); add_filter( 'manage_edit-boldblocks_variation_sortable_columns', [ $this, 'variation_sortable_columns' ] ); add_action( 'pre_get_posts', [ $this, 'pre_get_posts_order_variation_custom_columns' ], 1 ); // Only do customization on 'edit.php' page for variation. add_action( 'load-edit.php', [ $this, 'admin_listing_variation_page' ] ); // Load data for js. add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_block_editor_assets' ] ); // Update template on the fly for variation post type. add_action( 'admin_init', [ $this, 'update_template_for_variation' ] ); // Add rest api endpoint to create variations. add_action( 'rest_api_init', [ $this, 'build_create_variation_endpoint' ] ); } /** * Register custom post type * * @return void */ public function register_custom_post_type() { // Block variations. $variation_labels = array( 'name' => _x( 'Block Variations', 'post type general name', 'boldblocks' ), 'singular_name' => _x( 'Block Variation', 'post type singular name', 'boldblocks' ), 'menu_name' => _x( 'Block Variations', 'admin menu', 'boldblocks' ), 'name_admin_bar' => _x( 'Block Variations', 'add new on admin bar', 'boldblocks' ), 'add_new' => _x( 'Add New', 'item', 'boldblocks' ), 'add_new_item' => __( 'Add New Block Variation', 'boldblocks' ), 'new_item' => __( 'New Block Variation', 'boldblocks' ), 'edit_item' => __( 'Edit Block Variation', 'boldblocks' ), 'view_item' => __( 'View Block Variation', 'boldblocks' ), 'all_items' => __( 'All Block Variations', 'boldblocks' ), 'search_items' => __( 'Search Block Variations', 'boldblocks' ), 'parent_item_colon' => __( 'Parent Block Variation:', 'boldblocks' ), 'not_found' => __( 'No items found.', 'boldblocks' ), 'not_found_in_trash' => __( 'No items found in trash.', 'boldblocks' ), ); $variation_args = array( 'labels' => $variation_labels, 'description' => __( 'All custom block variations', 'boldblocks' ), 'public' => true, 'publicly_queryable' => false, 'exclude_from_search' => true, 'show_ui' => true, 'show_in_menu' => true, 'show_in_nav_menus' => false, 'show_in_admin_bar' => false, 'rewrite' => array( 'slug' => 'variation' ), 'capability_type' => 'post', 'capabilities' => array( 'create_posts' => 'do_not_allow', ), 'map_meta_cap' => true, 'has_archive' => false, 'hierarchical' => false, 'menu_position' => 5, 'supports' => array( 'title', 'editor', 'excerpt', 'author', 'custom-fields', 'revisions' ), 'show_in_rest' => true, 'template_lock' => 'insert', ); register_post_type( 'boldblocks_variation', $variation_args ); // Meta fields. register_meta( 'post', 'boldblocks_variation_block_name', array( 'object_subtype' => 'boldblocks_variation', 'show_in_rest' => true, 'type' => 'string', 'default' => '', 'single' => true, ) ); register_meta( 'post', 'boldblocks_variation_name', array( 'object_subtype' => 'boldblocks_variation', 'show_in_rest' => true, 'type' => 'string', 'default' => '', 'single' => true, ) ); register_meta( 'post', 'boldblocks_variation_data', array( 'object_subtype' => 'boldblocks_variation', 'show_in_rest' => true, 'type' => 'string', 'default' => '{}', 'single' => true, ) ); } /** * Enqueue editor assets * * @return void */ public function enqueue_block_editor_assets() { global $boldblocks_cbb; // Custom blocks access file. $variations_asset = $boldblocks_cbb->include_file( 'build/variations.asset.php' ); // Scripts. wp_enqueue_script( 'boldblocks-variations', BOLDBLOCKS_CBB_URL . '/build/variations.js', $variations_asset['dependencies'], $variations_asset['version'], true ); // Load all variations for registration. wp_localize_script( 'boldblocks-variations', 'BoldblocksVariations', $this->get_all_variations() ); } /** * Update template for variation * * @return void */ public function update_template_for_variation() { // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( isset( $_GET['post'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $post_id = absint( $_GET['post'] ); $current_post = get_post( $post_id ); if ( 'boldblocks_variation' !== $current_post->post_type ) { return; } $block_name = get_post_meta( $post_id, 'boldblocks_variation_block_name', true ); if ( $block_name ) { $post_type_object = get_post_type_object( 'boldblocks_variation' ); $post_type_object->template = array( array( $block_name ), ); } } } /** * Get all variations * * @return array */ public function get_all_variations() { $variation_posts = get_posts( [ 'post_type' => 'boldblocks_variation', 'posts_per_page' => -1, 'post_status' => 'publish', ] ); return array_map( function( $item ) { return [ 'blockName' => get_post_meta( $item->ID, 'boldblocks_variation_block_name', true ), 'variationName' => get_post_meta( $item->ID, 'boldblocks_variation_name', true ), 'title' => $item->post_title, 'postContent' => $item->post_content, 'description' => $item->post_excerpt, 'variationData' => get_post_meta( $item->ID, 'boldblocks_variation_data', true ), ]; }, $variation_posts ); } /** * Build a custom endpoint to create variation * * @return void */ public function build_create_variation_endpoint() { register_rest_route( 'boldblocks/v1', '/createVariation/', array( 'methods' => 'POST', 'callback' => [ $this, 'create_variation' ], 'permission_callback' => function () { return current_user_can( 'publish_posts' ); }, ) ); } /** * Create variation * * @param WP_REST_Request $request The request object. * @return void */ public function create_variation( $request ) { $args = $request->get_params(); if ( empty( $args['blockName'] ) || empty( $args['variationName'] ) || empty( $args['content'] ) || empty( $args['data'] ) ) { wp_send_json_error( __( 'Invalid request!', 'boldblocks' ), 400 ); } // Build post array. $post_array = [ 'post_type' => 'boldblocks_variation', 'post_title' => $args['title'] ?? __( 'No Title', 'boldblocks' ), 'post_content' => $args['content'] ?? '', 'post_status' => 'publish', 'meta_input' => [ 'boldblocks_variation_block_name' => $args['blockName'] ?? '', 'boldblocks_variation_name' => $args['variationName'] ?? '', 'boldblocks_variation_data' => $args['data'], ], ]; // Parse JSON object from JSON.stringify. // $data = json_decode(html_entity_decode( stripslashes ($args['data'] ) ), 1);. // Insert new boldblocks_block post item. $post_id = wp_insert_post( $post_array ); // Send the error if any. if ( is_wp_error( $post_id ) ) { wp_send_json_error( $post_id, 500 ); } wp_send_json( [ 'data' => __( 'The new variation has been created!', 'boldblocks' ), 'success' => true, 'post' => [ 'id' => $post_id ], ] ); } /** * Add custom columns to custom post type * * @param array $columns The array of columns. * @return array */ public function add_variation_custom_columns( $columns ) { $custom_columns = array( 'block_name' => esc_html__( 'Block name', 'boldblocks' ), 'variation_name' => esc_html__( 'Variation name', 'boldblocks' ), ); // Add after title column. $return = array_slice( $columns, 0, 2, true ) + $custom_columns + array_slice( $columns, 2, count( $columns ) - 2, true ); return $return; } /** * Manage custom columns. * * @param string $column the column name. * @param int $post_id the post id. */ public function manage_variation_columns( $column, $post_id ) { switch ( $column ) { case 'block_name': echo esc_html( get_post_meta( $post_id, 'boldblocks_variation_block_name', true ) ); break; case 'variation_name': echo esc_html( get_post_meta( $post_id, 'boldblocks_variation_name', true ) ); break; // Just break out of the switch statement for everything else. default: break; } } /** * Make custom columns sortable. * * @param array $columns The array of columns. * @return array */ public function variation_sortable_columns( $columns ) { $columns['block_name'] = 'block_name'; $columns['variation_name'] = 'variation_name'; return $columns; } /** * Alter the main query for sorting. * * @param WP_Query $query The main query. * @return void */ public function pre_get_posts_order_variation_custom_columns( $query ) { // Do nothing on front end side. if ( ! is_admin() ) { return; } // Only for main query with orderby parameter. if ( $query->is_main_query() && 'boldblocks_variation' === $query->post_type && $query->get( 'orderby' ) ) { $orderby = $query->get( 'orderby' ); switch ( $orderby ) { case 'block_name': // set our query's meta_key, which is used for custom fields. $query->set( 'meta_key', 'boldblocks_variation_block_name' ); break; case 'variation_name': // set our query's meta_key, which is used for custom fields. $query->set( 'meta_key', 'boldblocks_variation_name' ); break; default: break; } } } /** * Add filters for custom variation columns * * @return void */ public function admin_listing_variation_page() { // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( isset( $_GET['post_type'] ) && 'boldblocks_variation' === $_GET['post_type'] ) { add_filter( 'request', [ $this, 'add_custom_columns_to_query_vars' ] ); add_filter( 'restrict_manage_posts', [ $this, 'add_filter_select_control' ] ); } } /** * Add custom vars to query vars * * @param array $query_vars The array of query vars. * @return array */ public function add_custom_columns_to_query_vars( $query_vars ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( isset( $_GET['boldblocks_variation_filter_block'] ) ) { // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key $query_vars['meta_key'] = 'boldblocks_variation_block_name'; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value, WordPress.Security.NonceVerification.Recommended $query_vars['meta_value'] = sanitize_text_field( wp_unslash( $_GET['boldblocks_variation_filter_block'] ) ); } return $query_vars; } /** * Add a filter select control to filter variation by block name * * @return void */ public function add_filter_select_control() { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $block_names = $wpdb->get_col( 'SELECT DISTINCT meta_value FROM ' . $wpdb->postmeta . ' WHERE meta_key = "boldblocks_variation_block_name" ORDER BY meta_value' ); $boldblocks_variation_filter_block = false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( isset( $_GET['boldblocks_variation_filter_block'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $boldblocks_variation_filter_block = sanitize_text_field( wp_unslash( $_GET['boldblocks_variation_filter_block'] ) ); } ?>