%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /var/www/tif-dev/wp-content/plugins/lazy-blocks/classes/
Upload File :
Create Path :
Current File : //var/www/tif-dev/wp-content/plugins/lazy-blocks/classes/class-blocks.php

<?php
/**
 * LazyBlocks blocks.
 *
 * @package lazyblocks
 */

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


/**
 * LazyBlocks_Blocks class. Class to work with LazyBlocks CPT.
 */
class LazyBlocks_Blocks {
    /**
     * Handlebars engine.
     *
     * @var null|object
     */
    private $handlebars = null;

    /**
     * Rules to sanitize SVG
     *
     * @var array
     */
    private $kses_svg = array(
        'svg'   => array(
            'class'           => true,
            'aria-hidden'     => true,
            'aria-labelledby' => true,
            'role'            => true,
            'xmlns'           => true,
            'width'           => true,
            'height'          => true,
            'viewbox'         => true,   // <= Must be lower case!
        ),
        'g'     => array( 'fill' => true ),
        'title' => array( 'title' => true ),
        'path'  => array(
            'd'    => true,
            'fill' => true,
        ),
        'rect'  => array(
            'fill'      => true,
            'opacity'   => true,
            'width'     => true,
            'height'    => true,
            'rx'        => true,
            'transform' => true,
        ),
    );

    /**
     * LazyBlocks_Blocks constructor.
     */
    public function __construct() {
        add_action( 'init', array( $this, 'prepare_handlebars' ) );

        add_action( 'init', array( $this, 'register_post_type' ) );

        add_action( 'init', array( $this, 'remove_custom_fields_support' ), 150 );

        add_filter( 'allowed_block_types_all', array( $this, 'allowed_block_types_all' ), 10, 2 );

        // custom post roles.
        add_action( 'admin_init', array( $this, 'add_role_caps' ) );

        // additional elements in blocks list table.
        add_filter( 'disable_months_dropdown', array( $this, 'disable_months_dropdown' ), 10, 2 );
        add_filter( 'post_row_actions', array( $this, 'post_row_actions' ), 10, 2 );
        add_filter( 'bulk_actions-edit-lazyblocks', array( $this, 'bulk_actions_edit' ) );
        add_filter( 'handle_bulk_actions-edit-lazyblocks', array( $this, 'handle_bulk_actions_edit' ), 10, 3 );
        add_filter( 'manage_lazyblocks_posts_columns', array( $this, 'manage_posts_columns' ) );
        add_filter( 'manage_lazyblocks_posts_custom_column', array( $this, 'manage_posts_custom_column' ), 10, 2 );

        // add gutenberg blocks assets.
        if ( function_exists( 'register_block_type' ) ) {
            // add custom block categories.
            add_filter( 'block_categories_all', array( $this, 'block_categories_all' ), 100 );

            add_action( 'enqueue_block_editor_assets', array( $this, 'register_block' ) );
            add_action( 'init', array( $this, 'register_block_render' ), 20 );
        }
    }

    /**
     * Handlebars php.
     */
    public function prepare_handlebars() {
        require_once lazyblocks()->plugin_path() . 'vendor/Handlebars/Autoloader.php';

        Handlebars\Autoloader::register();

        $this->handlebars = new Handlebars\Handlebars();

        // phpcs:ignore
        // truncate
        // {{truncate 'string' 2 'true'}}.
        $this->handlebars->registerHelper(
            'truncate',
            function( $str, $len, $ellipsis = 'true' ) {
                if ( $str && $len && mb_strlen( $str, 'UTF-8' ) > $len ) {
                    $new_str = mb_substr( $str, 0, $len + 1, 'UTF-8' );
                    $count   = mb_strlen( $new_str, 'UTF-8' );

                    while ( $count > 0 ) {
                        $ch      = mb_substr( $new_str, -1, null, 'UTF-8' );
                        $new_str = mb_substr( $new_str, 0, -1, 'UTF-8' );

                        $count--;

                        if ( ' ' === $ch ) {
                            break;
                        }
                    }

                    if ( '' === $new_str ) {
                        $new_str = mb_substr( $str, 0, $len, 'UTF-8' );
                    }

                    return new \Handlebars\SafeString( $new_str . ( 'true' === $ellipsis ? '...' : '' ) );
                }
                return $str;
            }
        );

        // compare.
        // {{#compare 1 '===' 2}} Show if true {{/compare}}
        // slightly changed https://gist.github.com/doginthehat/1890659.
        $this->handlebars->registerHelper(
            'compare',
            function( $lvalue, $operator, $rvalue = null, $options = null ) {
                if ( null === $rvalue ) {
                    return $options['inverse']();
                }

                if ( null === $options ) {
                    $options  = $rvalue;
                    $rvalue   = $operator;
                    $operator = '===';
                }

                $result = false;

                switch ( $operator ) {
                    case '==':
                        // phpcs:ignore
                        $result = $lvalue == $rvalue;
                        break;
                    case '===':
                        $result = $lvalue === $rvalue;
                        break;
                    case '!=':
                        // phpcs:ignore
                        $result = $lvalue != $rvalue;
                        break;
                    case '!==':
                        $result = $lvalue !== $rvalue;
                        break;
                    case '<':
                        $result = $lvalue < $rvalue;
                        break;
                    case '>':
                        $result = $lvalue > $rvalue;
                        break;
                    case '<=':
                        $result = $lvalue <= $rvalue;
                        break;
                    case '>=':
                        $result = $lvalue >= $rvalue;
                        break;
                    case '&&':
                        $result = $lvalue && $rvalue;
                        break;
                    case '||':
                        $result = $lvalue || $rvalue;
                        break;
                    case 'typeof':
                        $result = gettype( $lvalue ) === $rvalue;
                        break;
                }

                if ( $result ) {
                    return $options['fn']();
                }

                return $options['inverse']();
            }
        );

        // math.
        // {{math 1 '+' 2}}
        // https://stackoverflow.com/questions/33059203/error-missing-helper-in-handlebars-js/46317662#46317662.
        $this->handlebars->registerHelper(
            'math',
            function( $lvalue, $operator, $rvalue ) {
                $result = '';

                switch ( $operator ) {
                    case '+':
                        $result = $lvalue + $rvalue;
                        break;
                    case '-':
                        $result = $lvalue - $rvalue;
                        break;
                    case '*':
                        $result = $lvalue * $rvalue;
                        break;
                    case '/':
                        $result = $lvalue / $rvalue;
                        break;
                    case '%':
                        $result = $lvalue % $rvalue;
                        break;
                }

                return $result;
            }
        );

        // phpcs:ignore
        // do_shortcode.
        // {{{do_shortcode 'my_shortcode' this}}}.
        $this->handlebars->registerHelper(
            'do_shortcode',
            function( $shortcode_name, $attributes ) {
                $result = '[' . $shortcode_name;

                // prepare attributes.
                if ( isset( $attributes ) && ! empty( $attributes ) ) {
                    foreach ( $attributes as $name => $val ) {
                        if (
                        'content' === $name
                        || 'lazyblock_code_frontend_html' === $name
                        || 'lazyblock_code_backend_html' === $name
                        || 'data' === $name
                        || 'hash' === $name
                        ) {
                            continue;
                        }

                        if ( is_array( $val ) ) {
                            $val = wp_json_encode( $val );
                        }

                        if (
                        ! is_numeric( $val )
                        && ! is_string( $val )
                        && ! is_bool( $val )
                        ) {
                            continue;
                        }

                        if ( is_bool( $val ) ) {
                            $val = $val ? '1' : '0';
                        }

                        $result .= ' ' . esc_attr( $name ) . '="' . esc_attr( $val ) . '"';
                    }

                    // content.
                    if ( isset( $attributes['content'] ) ) {
                        $result .= ']' . $attributes['content'] . '[/' . $shortcode_name;
                    }
                }

                $result .= ']';

                return do_shortcode( $result );
            }
        );

        // phpcs:ignore
        // date_i18n.
        // {{date_i18n 'F j, Y H:i' '2018-09-16 15:35'}}.
        $this->handlebars->registerHelper(
            'date_i18n',
            function( $format, $time ) {
                return date_i18n( $format, strtotime( $time ) );
            }
        );

        // phpcs:ignore
        // var_dump.
        // {{var_dump 'test'}}.
        $this->handlebars->registerHelper(
            'var_dump',
            function( $val ) {
                ob_start();
                // phpcs:ignore
                var_dump( $val );
                return ob_get_clean();
            }
        );

        // custom action for extending default helpers by 3rd-party.
        do_action( 'lzb/handlebars/object', $this->handlebars );
        do_action( 'lzb_handlebars_object', $this->handlebars );
    }

    /**
     * Register CPT.
     */
    public function register_post_type() {
        register_post_type(
            'lazyblocks',
            array(
                'labels'            => array(
                    'menu_name'     => __( 'Lazy Blocks', 'lazy-blocks' ),
                    'name'          => __( 'Blocks', 'lazy-blocks' ),
                    'all_items'     => __( 'Blocks', 'lazy-blocks' ),
                    'singular_name' => __( 'Block', 'lazy-blocks' ),
                ),
                'public'            => false,
                'has_archive'       => false,
                'show_ui'           => true,

                // adding to custom menu manually.
                'show_in_menu'      => true,
                'show_in_admin_bar' => true,
                'show_in_rest'      => true,
                // phpcs:ignore
                'menu_icon'         => 'data:image/svg+xml;base64,' . base64_encode( file_get_contents( lazyblocks()->plugin_path() . 'assets/svg/icon-lazyblocks.svg' ) ),
                'menu_position'     => 80,
                'capabilities'      => array(
                    'edit_post'          => 'edit_lazyblock',
                    'edit_posts'         => 'edit_lazyblocks',
                    'edit_others_posts'  => 'edit_other_lazyblocks',
                    'publish_posts'      => 'publish_lazyblocks',
                    'read_post'          => 'read_lazyblock',
                    'read_private_posts' => 'read_private_lazyblocks',
                    'delete_posts'       => 'delete_lazyblocks',
                    'delete_post'        => 'delete_lazyblock',
                ),
                'rewrite'           => true,
                'supports'          => array(
                    'title',
                    'editor',
                    'revisions',
                ),
                'template'          => array(
                    array(
                        'lzb-constructor/main',
                    ),
                ),
                // we can't use it since blocks didn't inserted in some posts.
                // 'template_lock' => 'all',.
            )
        );
    }

    /**
     * Remove custom fields support from lazy blocks constructor page.
     * Some plugins adds support for custom fields to all post types, but we don't need it in our constructor.
     *
     * @link https://github.com/nk-crew/lazy-blocks/issues/141
     */
    public function remove_custom_fields_support() {
        remove_post_type_support( 'lazyblocks', 'custom-fields' );
    }

    /**
     * Allowed blocks for lazyblocks post type.
     *
     * @param array  $allowed_block_types - blocks.
     * @param object $editor_context - editor context.
     * @return array
     */
    public function allowed_block_types_all( $allowed_block_types, $editor_context ) {
        if ( empty( $editor_context->post ) || 'lazyblocks' !== $editor_context->post->post_type ) {
            return $allowed_block_types;
        }
        return array( 'lzb-constructor/main' );
    }

    /**
     * Add Roles
     */
    public function add_role_caps() {
        global $wp_roles;

        if ( isset( $wp_roles ) ) {
            $wp_roles->add_cap( 'administrator', 'edit_lazyblock' );
            $wp_roles->add_cap( 'administrator', 'edit_lazyblocks' );
            $wp_roles->add_cap( 'administrator', 'edit_other_lazyblocks' );
            $wp_roles->add_cap( 'administrator', 'publish_lazyblocks' );
            $wp_roles->add_cap( 'administrator', 'read_lazyblock' );
            $wp_roles->add_cap( 'administrator', 'read_private_lazyblocks' );
            $wp_roles->add_cap( 'administrator', 'delete_lazyblocks' );
            $wp_roles->add_cap( 'administrator', 'delete_lazyblock' );

            $wp_roles->add_cap( 'editor', 'read_lazyblock' );
            $wp_roles->add_cap( 'editor', 'read_private_lazyblocks' );

            $wp_roles->add_cap( 'author', 'read_lazyblock' );
            $wp_roles->add_cap( 'author', 'read_private_lazyblocks' );

            $wp_roles->add_cap( 'contributor', 'read_lazyblock' );
            $wp_roles->add_cap( 'contributor', 'read_private_lazyblocks' );
        }
    }

    /**
     * Disable month dropdown.
     *
     * @param array  $return disabled dropdown or no.
     * @param object $post_type current post type name.
     *
     * @return array
     */
    public function disable_months_dropdown( $return, $post_type ) {
        return 'lazyblocks' === $post_type ? true : $return;
    }

    /**
     * Add featured image in lazyblocks list
     *
     * @param array  $actions actions for posts.
     * @param object $post current post data.
     *
     * @return array
     */
    public function post_row_actions( $actions = array(), $post = null ) {
        if ( ! $post || 'lazyblocks' !== $post->post_type ) {
            return $actions;
        }

        // remove quick edit link.
        if ( isset( $actions['inline hide-if-no-js'] ) ) {
            unset( $actions['inline hide-if-no-js'] );
        }

        // add duplicate and export link.
        $actions = array_merge(
            array_slice( $actions, 0, 1 ),
            array(
                'duplicate' => sprintf(
                    '<a href="%1$s" aria-label="%2$s">%3$s</a>',
                    add_query_arg(
                        array(
                            'lazyblocks_duplicate_block' => $post->ID,
                            'lazyblocks_duplicate_block_nonce' => wp_create_nonce( 'lzb-duplicate-block-nonce' ),
                        )
                    ),
                    sprintf(
                        // translators: %1$ - post title.
                        esc_html__( 'Duplicate ā€œ%1$sā€', 'lazy-blocks' ),
                        get_the_title( $post->ID )
                    ),
                    esc_html__( 'Duplicate', 'lazy-blocks' )
                ),
                'export' => sprintf(
                    '<a href="%1$s" aria-label="%2$s">%3$s</a>',
                    add_query_arg(
                        array(
                            'lazyblocks_export_block' => $post->ID,
                        )
                    ),
                    sprintf(
                        // translators: %1$ - post title.
                        esc_html__( 'Export ā€œ%1$sā€', 'lazy-blocks' ),
                        get_the_title( $post->ID )
                    ),
                    esc_html__( 'Export', 'lazy-blocks' )
                ),
            ),
            array_slice( $actions, 1 )
        );

        return $actions;
    }

    /**
     * Bulk actions.
     *
     * @param array $actions bulk actions for posts.
     *
     * @return array
     */
    public function bulk_actions_edit( $actions = array() ) {
        unset( $actions['edit'] );

        $actions['export'] = esc_html__( 'Export', 'lazy-blocks' );

        return $actions;
    }

    /**
     * Prepare to bulk export blocks.
     *
     * @param string $redirect redirect url after export.
     * @param string $action action name.
     * @param array  $post_ids post ids to export.
     *
     * @return string
     */
    public function handle_bulk_actions_edit( $redirect, $action, $post_ids ) {
        if ( 'export' !== $action ) {
            return $redirect;
        }

        lazyblocks()->tools()->export_json( $post_ids, 'blocks' );

        return $redirect;
    }

    /**
     * Add featured image in lazyblocks list
     *
     * @param array $columns columns of the table.
     *
     * @return array
     */
    public function manage_posts_columns( $columns = array() ) {
        $columns = array(
            'cb'                          => $columns['cb'],
            'lazyblocks_post_icon'        => esc_html__( 'Icon', 'lazy-blocks' ),
            'title'                       => $columns['title'],
            'lazyblocks_post_category'    => esc_html__( 'Category', 'lazy-blocks' ),
            'lazyblocks_post_description' => esc_html__( 'Description', 'lazy-blocks' ),
        );

        return $columns;
    }

    /**
     * Add thumb to the column
     *
     * @param bool $column_name column name.
     */
    public function manage_posts_custom_column( $column_name = false ) {
        global $post;

        if ( 'lazyblocks_post_icon' === $column_name ) {
            $icon      = $this->get_meta_value_by_id( 'lazyblocks_icon' );
            $admin_url = get_edit_post_link( $post->ID );

            if ( $icon && strpos( $icon, 'dashicons' ) === 0 ) {
                echo '<a class="lzb-admin-block-icon" href="' . esc_url( $admin_url ) . '"><span class="dashicons ' . esc_attr( $icon ) . '"></span></a>';
            } elseif ( $icon ) {
                echo '<a class="lzb-admin-block-icon" href="' . esc_url( $admin_url ) . '">' . wp_kses( $icon, $this->kses_svg ) . '</a>';
            }
        }

        if ( 'lazyblocks_post_category' === $column_name ) {
            $category = $this->get_meta_value_by_id( 'lazyblocks_category' );
            if ( $category ) {
                $gutenberg_categories = array();
                if ( function_exists( 'get_block_categories' ) ) {
                    $gutenberg_categories = get_block_categories( $post );
                } elseif ( function_exists( 'gutenberg_get_block_categories' ) ) {
                    $gutenberg_categories = gutenberg_get_block_categories( $post );
                }

                foreach ( $gutenberg_categories as $cat ) {
                    if ( $cat['slug'] === $category ) {
                        $category = $cat['title'];
                        break;
                    }
                }

                echo esc_html( $category );
            }
        }

        if ( 'lazyblocks_post_description' === $column_name ) {
            $description = $this->get_meta_value_by_id( 'lazyblocks_description' );
            echo esc_html( $description );
        }
    }

    /**
     * Default values of controls.
     *
     * @var array
     */
    private $defaults = array(
        'lazyblocks_controls'                        => array(),

        'lazyblocks_slug'                            => '',
        'lazyblocks_icon'                            => '',
        'lazyblocks_description'                     => '',
        'lazyblocks_keywords'                        => '',
        'lazyblocks_category'                        => 'text',

        'lazyblocks_code_show_preview'               => 'always',
        'lazyblocks_code_single_output'              => 'false',
        'lazyblocks_code_output_method'              => 'html',

        'lazyblocks_code_editor_html'                => '',
        'lazyblocks_code_editor_callback'            => '',
        'lazyblocks_code_editor_css'                 => '',
        'lazyblocks_code_frontend_html'              => '',
        'lazyblocks_code_frontend_callback'          => '',
        'lazyblocks_code_frontend_css'               => '',

        'lazyblocks_supports_multiple'               => 'true',
        'lazyblocks_supports_classname'              => 'true',
        'lazyblocks_supports_anchor'                 => 'false',
        'lazyblocks_supports_html'                   => 'false',
        'lazyblocks_supports_inserter'               => 'true',
        'lazyblocks_supports_align'                  => array( 'wide', 'full' ),

        // Ghost Kit Extensions.
        'lazyblocks_supports_ghostkit_spacings'      => 'false',
        'lazyblocks_supports_ghostkit_display'       => 'false',
        'lazyblocks_supports_ghostkit_scroll_reveal' => 'false',
        'lazyblocks_supports_ghostkit_frame'         => 'false',
        'lazyblocks_supports_ghostkit_custom_css'    => 'false',

        'lazyblocks_condition_post_types'            => '',
    );

    /**
     * Get metabox value by name.
     *
     * @param string $name - meta name.
     * @param mixed  $result - result of stored attribute.
     *
     * @return mixed
     */
    private function get_meta_value( $name, $result ) {
        $default = null;
        if ( isset( $this->defaults[ $name ] ) ) {
            $default = $this->defaults[ $name ];
        }

        if ( '' === $result && null !== $default ) {
            $result = $default;
        }

        if ( 'true' === $result ) {
            $result = true;
        } elseif ( 'false' === $result ) {
            $result = false;
        }

        return $result;
    }

    /**
     * Get metabox value by name and post id.
     *
     * @param string      $name - meta name.
     * @param int|boolean $id - post id.
     * @return mixed
     */
    private function get_meta_value_by_id( $name, $id = false ) {
        if ( ! $id ) {
            global $post;
            $id = $post->ID;
        }

        $result = get_post_meta( $id, $name, true );

        return $this->get_meta_value( $name, $result );
    }

    /**
     * Get metabox value by name and block data.
     *
     * @param string $name - meta name.
     * @param array  $block_data - supplied block data.
     *
     * @return mixed
     */
    private function get_meta_value_by_block( $name, $block_data ) {
        $result = $block_data[ $name ];

        return $this->get_meta_value( $name, $result );
    }

    /**
     * Sanitize block slug name.
     * Keep only alpha and numbers.
     * Make it lowercase.
     *
     * @param string $slug - slug name.
     *
     * @return string
     */
    public function sanitize_slug( $slug ) {
        return strtolower( preg_replace( '/[^a-zA-Z0-9\-]+/', '', $slug ) );
    }

    /**
     * Recursive sanitation for an array
     * Thanks: https://wordpress.stackexchange.com/questions/24736/wordpress-sanitize-array/26465
     *
     * @param array $array - array for sanitize.
     * @param array $textarea_items - sanitize as textarea fields by name.
     *
     * @return array
     */
    private function sanitize_array( $array, $textarea_items = array() ) {
        foreach ( $array as $key => &$value ) {
            if ( is_array( $value ) ) {
                $value = $this->sanitize_array( $value, $textarea_items );
            } else {
                if ( in_array( $key, $textarea_items, true ) ) {
                    $value = sanitize_textarea_field( $value );
                } else {
                    $value = sanitize_text_field( $value );
                }
            }
        }

        return $array;
    }

    /**
     * Save Format metabox
     *
     * @param int   $post_id The post ID.
     * @param array $data Metaboxes data for save.
     */
    public function save_meta_boxes( $post_id, $data ) {
        foreach ( $this->defaults as $meta => $default ) {
            $new_meta_value = '';

            if ( isset( $data[ $meta ] ) ) {
                // convert boolean to string.
                if ( is_bool( $data[ $meta ] ) ) {
                    $data[ $meta ] = $data[ $meta ] ? 'true' : 'false';
                }

                // icon and editors.
                if (
                    'lazyblocks_icon' === $meta ||
                    'lazyblocks_code_editor_html' === $meta ||
                    'lazyblocks_code_editor_css' === $meta ||
                    'lazyblocks_code_frontend_html' === $meta ||
                    'lazyblocks_code_frontend_css' === $meta
                ) {
                    // phpcs:ignore
                    $new_meta_value = wp_slash( $data[ $meta ] );
                } else {
                    // Get the posted data and sanitize it for use as an HTML class.
                    if ( is_array( $data[ $meta ] ) ) {
                        $block_data_array_textarea = array( 'choices', 'help' );
                        $block_data_array_textarea = apply_filters( 'lzb/block_save/array_attributes/textarea_items', $block_data_array_textarea, $data[ $meta ], $meta );

                        // phpcs:ignore
                        $new_meta_value = $this->sanitize_array( wp_slash( $data[ $meta ] ), $block_data_array_textarea );
                    } else {
                        $new_meta_value = sanitize_text_field( wp_slash( $data[ $meta ] ) );
                    }
                }
            }

            // keep only alpha and numbers in slug.
            if ( 'lazyblocks_slug' === $meta ) {
                $new_meta_value = $this->sanitize_slug( $new_meta_value );

                // generate slug from title.
                if ( ! $new_meta_value ) {
                    $new_meta_value = get_the_title();
                    $new_meta_value = $this->sanitize_slug( $new_meta_value );
                }

                // if no slug available.
                if ( ! $new_meta_value ) {
                    $new_meta_value = 'no-slug';
                }
            }

            /* Get the meta value of the custom field key. */
            $meta_value = get_post_meta( $post_id, $meta, true );

            $meta_value_to_check     = $meta_value;
            $new_meta_value_to_check = $new_meta_value;

            if ( is_array( $meta_value_to_check ) ) {
                $meta_value_to_check = wp_json_encode( $meta_value_to_check );
            }
            if ( is_array( $new_meta_value_to_check ) ) {
                $new_meta_value_to_check = wp_json_encode( $new_meta_value_to_check );
            }

            /* If a new meta value was added and there was no previous value, add it. */
            if ( $new_meta_value_to_check && '' === $meta_value_to_check ) {
                add_post_meta( $post_id, $meta, $new_meta_value, true );

                /* If the new meta value does not match the old value, update it. */
            } elseif ( $new_meta_value_to_check && $new_meta_value_to_check !== $meta_value_to_check ) {
                update_post_meta( $post_id, $meta, $new_meta_value );

                /* If there is no new meta value but an old value exists, delete it. */
            } elseif ( '' === $new_meta_value_to_check && $meta_value_to_check ) {
                delete_post_meta( $post_id, $meta, $meta_value );
            }
        }
    }

    /**
     * Get metabox data
     *
     * @param int $post_id The post ID.
     *
     * @return array|null
     */
    public function get_meta_boxes( $post_id ) {
        $result_meta = array();

        foreach ( $this->defaults as $meta => $default ) {
            $result_meta[ $meta ] = $this->get_meta_value_by_id( $meta, $post_id );
        }

        return $result_meta;
    }

    /**
     * Blocks list.
     *
     * @var array|null
     */
    private $blocks = null;

    /**
     * Blocks list added by user using add_blocks method.
     *
     * @var null
     */
    private $user_blocks = null;

    /**
     * Add block.
     *
     * @param array $data - block data.
     */
    public function add_block( $data ) {
        if ( null === $this->user_blocks ) {
            $this->user_blocks = array();
        }

        $this->user_blocks[] = apply_filters( 'lzb/add_user_block', $data );
    }

    /**
     * Convert block format.
     *
     * @param array $block_data - block data.
     */
    public function marshal_block_data( $block_data ) {
        $all_controls = lazyblocks()->controls()->get_controls();
        return $this->marshal_block_data_with_controls( null, null, $block_data, $all_controls );
    }

    /**
     * Convert block format.
     *
     * @param int   $id - registered block id.
     * @param int   $post_title - registered block post title.
     * @param array $block_data - block data.
     * @param array $all_controls - control data.
     */
    public function marshal_block_data_with_controls( $id = null, $post_title = null, $block_data = null, $all_controls = null ) {
        $get_meta_value = function( $name ) use ( $id, $block_data ) {
            if ( $id ) {
                return $this->get_meta_value_by_id( $name, $id );
            } else {
                return $this->get_meta_value_by_block( $name, $block_data );
            }
        };

        $icon = $get_meta_value( 'lazyblocks_icon' );

        // add default icon.
        if ( ! $icon ) {
            // phpcs:ignore
            $icon = file_get_contents( lazyblocks()->plugin_path() . 'assets/svg/icon-lazyblocks.svg' );
            $icon = str_replace( 'fill="white"', 'fill="currentColor"', $icon );
        }

        if ( $icon && strpos( $icon, 'dashicons' ) === 0 ) {
            $icon = esc_attr( str_replace( 'dashicons-', 'dashicons dashicons-', $icon ) );
        } elseif ( $icon ) {
            $icon = wp_kses( $icon, $this->kses_svg );
        }

        $keywords = esc_attr( $get_meta_value( 'lazyblocks_keywords' ) );
        if ( $keywords ) {
            $keywords = explode( ',', $keywords );
        } else {
            $keywords = array();
        }

        $controls = $get_meta_value( 'lazyblocks_controls' );

        // prepare default control data.
        foreach ( $controls as $k => $control ) {
            if ( isset( $control['type'] ) && isset( $all_controls[ $control['type'] ] ) && isset( $all_controls[ $control['type'] ]['attributes'] ) ) {
                $controls[ $k ] = array_merge(
                    $all_controls[ $control['type'] ]['attributes'],
                    $control
                );
            }
        }

        $align          = (array) $get_meta_value( 'lazyblocks_supports_align' );
        $align_none_key = array_search( 'none', $align, true );

        if ( false !== $align_none_key ) {
            unset( $align[ $align_none_key ] );
        }

        return array(
            'id'             => $id,
            'title'          => $post_title,
            'icon'           => $icon,
            'keywords'       => $keywords,
            'slug'           => 'lazyblock/' . esc_html( $get_meta_value( 'lazyblocks_slug' ) ),
            'description'    => esc_html( $get_meta_value( 'lazyblocks_description' ) ),
            'category'       => $this->sanitize_slug( esc_html( $get_meta_value( 'lazyblocks_category' ) ) ),
            'category_label' => esc_html( $get_meta_value( 'lazyblocks_category' ) ),
            'supports'       => array(
                'customClassName' => $get_meta_value( 'lazyblocks_supports_classname' ),
                'anchor'          => $get_meta_value( 'lazyblocks_supports_anchor' ),
                'align'           => $align,
                'html'            => $get_meta_value( 'lazyblocks_supports_html' ),
                'multiple'        => $get_meta_value( 'lazyblocks_supports_multiple' ),
                'inserter'        => $get_meta_value( 'lazyblocks_supports_inserter' ),
            ),
            'ghostkit'       => array(
                'supports' => array(
                    'spacings'     => $get_meta_value( 'lazyblocks_supports_ghostkit_spacings' ),
                    'display'      => $get_meta_value( 'lazyblocks_supports_ghostkit_display' ),
                    'scrollReveal' => $get_meta_value( 'lazyblocks_supports_ghostkit_scroll_reveal' ),
                    'frame'        => $get_meta_value( 'lazyblocks_supports_ghostkit_frame' ),
                    'customCSS'    => $get_meta_value( 'lazyblocks_supports_ghostkit_custom_css' ),
                ),
            ),
            'controls'       => $controls,
            'code'           => array(
                'output_method'     => $get_meta_value( 'lazyblocks_code_output_method' ),
                'editor_html'       => $get_meta_value( 'lazyblocks_code_editor_html' ),
                'editor_callback'   => '',
                'editor_css'        => $get_meta_value( 'lazyblocks_code_editor_css' ),
                'frontend_html'     => $get_meta_value( 'lazyblocks_code_frontend_html' ),
                'frontend_callback' => '',
                'frontend_css'      => $get_meta_value( 'lazyblocks_code_frontend_css' ),
                'show_preview'      => $get_meta_value( 'lazyblocks_code_show_preview' ),
                'single_output'     => $get_meta_value( 'lazyblocks_code_single_output' ),
            ),
            'condition'      => $get_meta_value( 'lazyblocks_condition_post_types' ) ? $get_meta_value( 'lazyblocks_condition_post_types' ) : array(),
            'edit_url'       => get_edit_post_link( $id ),
        );
    }

    /**
     * Get all blocks array.
     *
     * @param bool $db_only - get blocks from database only.
     * @param bool $no_cache - get blocks without cache.
     * @param bool $keep_duplicates - get blocks with same slugs.
     *
     * @return array|null
     */
    public function get_blocks( $db_only = false, $no_cache = false, $keep_duplicates = false ) {
        // fetch blocks.
        if ( null === $this->blocks || $no_cache ) {
            $this->blocks = array();

            // get all lazyblocks post types.
            // Don't use WP_Query on the admin side https://core.trac.wordpress.org/ticket/18408 .
            $all_blocks = get_posts(
                array(
                    'post_type'      => 'lazyblocks',
                    // phpcs:ignore
                    'posts_per_page' => -1,
                    'showposts'      => -1,
                    'paged'          => -1,
                )
            );

            $all_controls = lazyblocks()->controls()->get_controls();

            foreach ( $all_blocks as $block ) {
                $this->blocks[] = $this->marshal_block_data_with_controls( $block->ID, $block->post_title, null, $all_controls );
            }
        }

        $result = $this->blocks;

        if ( ! $db_only && $this->user_blocks ) {
            $result = array_merge( $result, $this->user_blocks );
        }

        // unique only.
        if ( ! $keep_duplicates ) {
            $unique_result = array();
            $slug_array    = array();

            foreach ( $result as $item ) {
                if ( ! in_array( $item['slug'], $slug_array, true ) ) {
                    $slug_array[]    = $item['slug'];
                    $unique_result[] = $item;
                }
            }

            return $unique_result;
        }

        return $result;
    }

    /**
     * Get specific block data by name.
     *
     * @param string $name - block name.
     * @param bool   $db_only - get blocks from database only.
     *
     * @return array|null
     */
    public function get_block( $name, $db_only = false ) {
        $blocks = $this->get_blocks( $db_only );

        foreach ( $blocks as $block ) {
            if ( $name === $block['slug'] ) {
                return $block;
            }
        }

        return false;
    }

    /**
     * Get all custom blocks categories array.
     *
     * @param bool $db_only - get blocks from database only.
     *
     * @return array|null
     */
    public function get_blocks_categories( $db_only = false ) {
        $blocks             = $this->get_blocks( $db_only );
        $default_categories = array(
            'text',
            'media',
            'design',
            'widgets',
            'embed',
            'reusable',
        );

        $custom_categories = array();

        foreach ( $blocks as $block ) {
            if (
                ! isset( $default_categories[ $block['category'] ] ) &&
                ! isset( $custom_categories[ $block['category'] ] ) &&
                ! in_array( $block['category'], $default_categories, true ) &&
                isset( $block['category_label'] )
            ) {
                $custom_categories[ $block['category'] ] = $block['category_label'];
            }
        }

        return $custom_categories;
    }

    /**
     * Register custom categories for blocks
     *
     * @param array $categories - available categories.
     * @return array
     */
    public function block_categories_all( $categories ) {
        // lazyblocks core category.
        $categories[] = array(
            'slug'  => 'lazyblocks',
            'title' => esc_html__( 'Lazy Blocks', 'lazy-blocks' ),
        );

        $new_categories = $this->get_blocks_categories();
        if ( ! empty( $new_categories ) ) {
            foreach ( $new_categories as $slug => $category ) {
                // no duplicates.
                $allow = true;

                foreach ( $categories as $existing_cat ) {
                    if ( isset( $existing_cat['slug'] ) && $slug === $existing_cat['slug'] ) {
                        $allow = false;
                    }
                }

                if ( $allow ) {
                    $categories[] = array(
                        'slug'  => $slug,
                        'title' => $category,
                    );
                }
            }
        }

        return $categories;
    }

    /**
     * Add Gutenberg block assets.
     */
    public function register_block() {
        global $post_type;

        $blocks = $this->get_blocks();

        // enqueue block css.
        wp_enqueue_style(
            'lazyblocks-gutenberg',
            lazyblocks()->plugin_url() . 'assets/css/style.min.css',
            array(),
            '2.5.3'
        );
        wp_style_add_data( 'lazyblocks-gutenberg', 'rtl', 'replace' );
        wp_style_add_data( 'lazyblocks-gutenberg', 'suffix', '.min' );

        // enqueue block js.
        wp_enqueue_script(
            'lazyblocks-gutenberg',
            lazyblocks()->plugin_url() . 'assets/js/index.min.js',
            array( 'wp-blocks', 'wp-block-editor', 'wp-i18n', 'wp-element', 'wp-components' ),
            '2.5.3',
            true
        );

        // additional data for block js.
        wp_localize_script(
            'lazyblocks-gutenberg',
            'lazyblocksGutenberg',
            array(
                'post_type'          => $post_type,
                'blocks'             => $blocks,
                'controls'           => lazyblocks()->controls()->get_controls(),
                'icons'              => lazyblocks()->icons()->get_all(),
                'allowed_mime_types' => get_allowed_mime_types(),
            )
        );
    }

    /**
     * Prepare attributes.
     * The same function placed in block JSX file.
     *
     * @param array          $controls - controls list.
     * @param string|boolean $child_of - childOf control name.
     * @param array          $block - block data.
     *
     * @return array.
     */
    public function prepare_block_attributes( $controls, $child_of = '', $block = null ) {
        $all_controls = lazyblocks()->controls()->get_controls();
        $attributes   = array();

        foreach ( $controls as $k => $control ) {
            if (
                isset( $control['child_of'] ) &&
                $control['child_of'] === $child_of &&
                $control['name']
            ) {
                $attribute_data = array(
                    'type'    => 'string',
                    'default' => isset( $control['default'] ) ? $control['default'] : null,
                );

                if ( isset( $control['save_in_meta'] ) && 'true' === $control['save_in_meta'] ) {
                    $attribute_data['source'] = 'meta';
                    $attribute_data['meta']   = isset( $control['save_in_meta_name'] ) && $control['save_in_meta_name'] ? $control['save_in_meta_name'] : $control['name'];
                }

                // get attribute type from control data.
                if ( isset( $control['type'] ) && isset( $all_controls[ $control['type'] ] ) ) {
                    $attribute_data['type'] = $all_controls[ $control['type'] ]['type'];

                    if ( 'number' === $attribute_data['type'] && null !== $attribute_data['default'] ) {
                        $attribute_data['default'] = (float) $attribute_data['default'];
                    }
                }

                $attributes[ $control['name'] ] = apply_filters( 'lzb/prepare_block_attribute', $attribute_data, $control, $controls, $k, $block );
            }
        }

        // reserved attributes.
        $attributes['lazyblock']        = array(
            'type'    => 'object',
            'default' => array(
                'slug' => $block['slug'],
            ),
        );
        $attributes['className']        = array(
            'type'    => 'string',
            'default' => '',
        );
        $attributes['align']            = array(
            'type'    => 'string',
            'default' => '',
        );
        $attributes['anchor']           = array(
            'type'    => 'string',
            'default' => '',
        );
        $attributes['blockId']          = array(
            'type'    => 'string',
            'default' => '',
        );
        $attributes['blockUniqueClass'] = array(
            'type'    => 'string',
            'default' => '',
        );

        // Ghost Kit.
        $attributes['ghostkitSpacings'] = array(
            'type'    => 'object',
            'default' => '',
        );
        $attributes['ghostkitSR']       = array(
            'type'    => 'string',
            'default' => '',
        );

        return $attributes;
    }

    /**
     * Eval custom user code and return as string.
     *
     * @param string $code - user code string.
     * @param array  $attributes - block attributes.
     *
     * @return string
     */
    // phpcs:disable
    public function php_eval( $code, $attributes ) {
        ob_start();

        eval( '?>' . $code );

        return ob_get_clean();
    }
    // phpcs:enable

    /**
     * Register block attributes, meta data, and custom frontend render callback if exists.
     */
    public function register_block_render() {
        $blocks = $this->get_blocks();

        foreach ( $blocks as $block ) {
            // Check if slug valid.
            $name_after_slug = explode( '/', $block['slug'] );
            $name_after_slug = isset( $name_after_slug[1] ) ? $name_after_slug[1] : '';

            if ( ! $block['slug'] || ! $name_after_slug ) {
                continue;
            }

            $attributes = $this->prepare_block_attributes( $block['controls'], '', $block );

            $data = array(
                'attributes'      => $attributes,
                'render_callback' => array( $this, 'render_callback' ),
                'example'         => array(),
            );

            // Register block type.
            register_block_type( $block['slug'], $data );

            // Register meta.
            foreach ( $attributes as $attribute ) {
                if ( isset( $attribute['meta'] ) && $attribute['meta'] ) {
                    register_meta(
                        'post',
                        $attribute['meta'],
                        array(
                            'show_in_rest' => true,
                            'single'       => true,
                            'type'         => $attribute['type'],
                            'default'      => $attribute['default'],
                        )
                    );
                }
            }
        }
    }

    /**
     * Render block custom frontend HTML.
     *
     * @param array  $attributes - The block attributes.
     * @param string $content - The block content.
     * @param string $context - block context [frontend, editor].
     * @param array  $block - Data containing the block's specifications (mostly used for live block preview in the block's constructor).
     *
     * @return string Returns the post content with latest posts added.
     */
    public function render_callback( $attributes, $content = null, $context = 'frontend', $block = null ) {
        if ( ! $block && ( ! isset( $attributes['lazyblock'] ) || ! isset( $attributes['lazyblock']['slug'] ) ) ) {
            return null;
        }
        if ( ! $block ) {
            $block = $this->get_block( $attributes['lazyblock']['slug'] );
        }

        $context = 'editor' === $context ? 'editor' : 'frontend';
        $result  = null;

        // phpcs:disable

        // apply filter for block attributes.
        $attributes = apply_filters( 'lzb/block_render/attributes', $attributes, $content, $block, $context );
        $attributes = apply_filters( $block['slug'] . '/' . $context . '_attributes', $attributes, $content, $block );
        $attributes = apply_filters( $block['slug'] . '/attributes', $attributes, $content, $block, $context );

        // apply filter for custom output callback.
        $result = apply_filters( 'lzb/block_render/callback', $result, $attributes, $context );
        $result = apply_filters( $block['slug'] . '/' . $context . '_callback', $result, $attributes );
        $result = apply_filters( $block['slug'] . '/callback', $result, $attributes, $context );

        // phpcs:enable

        // Custom render name.
        $custom_render_name = $context . '_html';
        if ( isset( $block['code']['output_method'] ) && isset( $block['code']['single_output'] ) && $block['code']['single_output'] ) {
            $custom_render_name = 'frontend_html';
        }

        // Custom output.
        if ( ! $result && isset( $block['code'] ) ) {
            $code = $block['code'];

            // Theme template file.
            if ( isset( $code['output_method'] ) && 'template' === $code['output_method'] ) {
                ob_start();
                $template_slug        = str_replace( '/', '-', $block ? $block['slug'] : $attributes['lazyblock']['slug'] );
                $template_path_editor = '/blocks/' . $template_slug . '/editor.php';
                $template_path        = '/blocks/' . $template_slug . '/block.php';
                $template_args        = array(
                    'attributes' => $attributes,
                    'block'      => $block,
                    'context'    => $context,
                );

                // Editor template.
                if ( 'editor' === $context && $this->template_exists( $template_path_editor, $template_args ) ) {
                    $this->include_template( $template_path_editor, $template_args );

                    // Frontend template.
                } elseif ( $this->template_exists( $template_path, $template_args ) ) {
                    $this->include_template( $template_path, $template_args );

                    // Template not found.
                } else {
                    $this->include_template( lazyblocks()->plugin_path . 'templates/template-not-found.php', $template_args );
                }

                $result = ob_get_clean();
                // Callback function.
            } elseif ( isset( $code[ $context . '_callback' ] ) && ! empty( $code[ $context . '_callback' ] ) && is_callable( $code[ $context . '_callback' ] ) ) {
                ob_start();
                call_user_func( $code[ $context . '_callback' ], $attributes );
                $result = ob_get_clean();

                // Custom code.
            } elseif ( isset( $code[ $custom_render_name ] ) && ! empty( $code[ $custom_render_name ] ) ) {
                // PHP output.
                if ( isset( $code['output_method'] ) && 'php' === $code['output_method'] ) {
                    $result = $this->php_eval( $code[ $custom_render_name ], $attributes );

                    // Handlebars.
                } else {
                    $result = $this->handlebars->render( $code[ $custom_render_name ], $attributes );
                }
            }
        }

        // add wrapper.
        $allow_wrapper = apply_filters( 'lzb/block_render/allow_wrapper', $result && 'frontend' === $context, $attributes, $context );
        // phpcs:ignore
        $allow_wrapper = apply_filters( $block['slug'] . '/' . $context . '_allow_wrapper', $allow_wrapper, $attributes );
        // phpcs:ignore
        $allow_wrapper = apply_filters( $block['slug'] . '/allow_wrapper', $allow_wrapper, $attributes, $context );

        if ( $allow_wrapper ) {
            $html_atts = '';

            if ( ! isset( $attributes['className'] ) ) {
                $attributes['className'] = '';
            }

            $attributes['className'] .= ' wp-block-' . str_replace( '/', '-', $attributes['lazyblock']['slug'] );

            if ( $attributes['blockUniqueClass'] ) {
                $attributes['className'] .= ' ' . $attributes['blockUniqueClass'];
            }

            if ( $attributes['align'] ) {
                $attributes['className'] .= ' align' . $attributes['align'];
            }

            if ( $attributes['className'] ) {
                $attributes['className'] = trim( $attributes['className'] );
                $html_atts              .= ' class="' . esc_attr( $attributes['className'] ) . '"';
            }
            if ( $attributes['anchor'] ) {
                $html_atts .= ' id="' . esc_attr( $attributes['anchor'] ) . '"';
            }

            if ( isset( $attributes['ghostkitSR'] ) && $attributes['ghostkitSR'] ) {
                $html_atts .= ' data-ghostkit-sr="' . esc_attr( $attributes['ghostkitSR'] ) . '"';
            }

            $result = '<div' . $html_atts . '>' . $result . '</div>';
        }

        // add filter for block output.
        $result = apply_filters( 'lzb/block_render/output', $result, $attributes, $context );
        // phpcs:ignore
        $result = apply_filters( $block['slug'] . '/' . $context . '_output', $result, $attributes );
        // phpcs:ignore
        $result = apply_filters( $block['slug'] . '/output', $result, $attributes, $context );

        return $result;
    }

    /**
     * Check if template exists.
     *
     * @param string $template_name file name.
     * @param array  $args args for template.
     */
    public function template_exists( $template_name, $args = array() ) {
        if ( ! empty( $args ) && is_array( $args ) ) {
	        // phpcs:ignore
            extract( $args );
        }

        // template in theme folder.
        $template = locate_template( array( $template_name ) );

        // Allow 3rd party plugin filter template file from their plugin.
        $template = apply_filters( 'lzb/block_render/template_exists', $template, $template_name, $args['attributes'], $args['block'], $args['context'] );
        // phpcs:ignore
        $template = apply_filters( $args['block']['slug'] . '/' . $args['context'] . '_template_exists', $template, $template_name, $args['attributes'], $args['block'] );
        // phpcs:ignore
        $template = apply_filters( $args['block']['slug'] . '/template_exists', $template, $template_name, $args['attributes'], $args['block'], $args['context'] );

        // DEPRECATED.
        $template = apply_filters( 'lzb/template_exists', $template, $template_name, $args );

        return file_exists( $template );
    }

    /**
     * Include template
     *
     * @param string $template_name file name.
     * @param array  $args args for template.
     */
    public function include_template( $template_name, $args = array() ) {
        if ( ! empty( $args ) && is_array( $args ) ) {
	        // phpcs:ignore
            extract( $args );
        }

        // template in theme folder.
        $template = locate_template( array( $template_name ) );

        // Allow 3rd party plugin filter template file from their plugin.
        $template = apply_filters( 'lzb/block_render/include_template', $template, $args['attributes'], $args['block'], $args['context'] );
        // phpcs:ignore
        $template = apply_filters( $args['block']['slug'] . '/' . $args['context'] . '_include_template', $template, $args['attributes'], $args['block'] );
        // phpcs:ignore
        $template = apply_filters( $args['block']['slug'] . '/include_template', $template, $args['attributes'], $args['block'], $args['context'] );

        // DEPRECATED.
        $template = apply_filters( 'lzb/include_template', $template, $template_name, $args );

        if ( file_exists( $template ) ) {
            include $template;
        }
    }
}

Zerion Mini Shell 1.0