Home / Widgets / Add Custom Post Selector Avada
Duplicate Snippet

Embed Snippet on Your Site

Add Custom Post Selector Avada

Code Preview
php
<?php
/**
 * Curated Post Grid for Avada Builder
 * Version 1.3
 *
 * WPCode: PHP Snippet > Auto Insert > Run Everywhere
 * No opening PHP tag required.
 */
if (!defined('ABSPATH')) {
    return;
}
/**
 * Published posts for the Avada multi-select dropdown.
 */
if (!function_exists('cpg_get_post_choices')) {
    function cpg_get_post_choices() {
        $posts = get_posts([
            'post_type'           => 'post',
            'post_status'         => 'publish',
            'posts_per_page'      => 500,
            'orderby'             => 'title',
            'order'               => 'ASC',
            'suppress_filters'    => false,
        ]);
        $choices = [];
        foreach ($posts as $post) {
            $choices[(string) $post->ID] = $post->post_title;
        }
        return $choices;
    }
}
/**
 * Validate a CSS dimension, with a fallback.
 * Supports px, rem, em, and unitless values if allowed.
 */
if (!function_exists('cpg_validate_dimension')) {
    function cpg_validate_dimension($input, $fallback, $unitless = false) {
        if (!is_scalar($input)) {
            return $fallback;
        }
        $input = trim((string) $input);
        if (
            preg_match(
                '/^(\d+(?:\.\d+)?)(px|rem|em)$/i',
                $input,
                $matches
            )
        ) {
            $value = (float) $matches[1];
            if ($value > 0 && $value <= 200) {
                return $value . strtolower($matches[2]);
            }
        }
        if (
            $unitless &&
            preg_match('/^\d+(?:\.\d+)?$/', $input)
        ) {
            $value = (float) $input;
            if ($value >= 0.8 && $value <= 3) {
                return (string) $value;
            }
        }
        return $fallback;
    }
}
/**
 * Render Curated Post Grid.
 */
if (!function_exists('cpg_wpcode_render')) {
    function cpg_wpcode_render($atts) {
        $a = shortcode_atts([
            'post_ids'          => '',
            'columns'           => 3,
            'tablet_columns'    => 2,
            'mobile_columns'    => 1,
            'gap'               => 24,
            'ratio'             => '16/10',
            'limit'             => 0,
            // Typography.
            'title_font_family' => 'inherit',
            'title_color'       => '#171714',
            'title_font_size'   => '22px',
            'title_line_height' => '1.4',
        ], $atts, 'curated_post_grid');
        // Normalize selected post IDs.
        $raw = is_array($a['post_ids'])
            ? $a['post_ids']
            : explode(',', (string) $a['post_ids']);
        $ids = array_values(array_unique(
            array_filter(array_map('absint', $raw))
        ));
        if (!$ids) {
            return current_user_can('edit_posts')
                ? '<p>Select posts in Curated Post Grid settings.</p>'
                : '';
        }
        // Validate post limit.
        $limit = min(100, absint($a['limit']));
        $ids = array_slice($ids, 0, $limit ?: 100);
        // Validate grid values.
        $columns = max(1, min(6, absint($a['columns'])));
        $tablet  = max(1, min(4, absint($a['tablet_columns'])));
        $mobile  = max(1, min(2, absint($a['mobile_columns'])));
        $gap     = max(0, min(120, absint($a['gap'])));
        $allowed_ratios = [
            '1/1',
            '4/3',
            '16/9',
            '16/10',
            '3/2',
            'auto',
        ];
        $ratio = in_array($a['ratio'], $allowed_ratios, true)
            ? $a['ratio']
            : '16/10';
        /**
         * Typography validation.
         */
        $allowed_fonts = [
            'inherit',
            'Arial',
            'Georgia',
            'Helvetica',
            'DM Sans',
            'Cormorant Garamond',
            'Roboto',
            'Open Sans',
            'Montserrat',
            'Poppins',
        ];
        $title_font = in_array(
            $a['title_font_family'],
            $allowed_fonts,
            true
        ) ? $a['title_font_family'] : 'inherit';
        $title_color = sanitize_hex_color(
            (string) $a['title_color']
        );
        if (!$title_color) {
            $title_color = '#171714';
        }
        $title_size = cpg_validate_dimension(
            $a['title_font_size'],
            '22px'
        );
        $title_line_height = cpg_validate_dimension(
            $a['title_line_height'],
            '1.4',
            true
        );
        /**
         * Query selected posts in the selected order.
         */
        $query = new WP_Query([
            'post_type'           => 'post',
            'post_status'         => 'publish',
            'post__in'            => $ids,
            'orderby'             => 'post__in',
            'posts_per_page'      => count($ids),
            'ignore_sticky_posts' => true,
            'no_found_rows'       => true,
        ]);
        if (!$query->have_posts()) {
            return '';
        }
        /**
         * CSS variables for this element instance.
         */
        $style = sprintf(
            '--cpg-cols:%d;--cpg-tablet:%d;--cpg-mobile:%d;--cpg-gap:%dpx;--cpg-ratio:%s;',
            $columns,
            $tablet,
            $mobile,
            $gap,
            $ratio
        );
        $style .= '--cpg-title-size:' . $title_size . ';';
        $style .= '--cpg-title-line-height:' . $title_line_height . ';';
        $style .= '--cpg-title-color:' . $title_color . ';';
        if ($title_font !== 'inherit') {
            $style .= '--cpg-title-font:"' . $title_font . '";';
        }
        /**
         * Output grid.
         */
        ob_start();
        echo '<div class="cpg-grid" style="' .
            esc_attr($style) . '">';
        while ($query->have_posts()) {
            $query->the_post();
            $url   = get_permalink();
            $title = get_the_title();
            echo '<article class="cpg-card">';
            // Featured image.
            if (has_post_thumbnail()) {
                echo '<a class="cpg-image-link" href="' .
                    esc_url($url) . '">';
                echo get_the_post_thumbnail(
                    get_the_ID(),
                    'large',
                    [
                        'class'   => 'cpg-image',
                        'loading' => 'lazy',
                        'alt'     => esc_attr($title),
                    ]
                );
                echo '</a>';
            }
            // Linked post title.
            echo '<h3 class="cpg-title">';
            echo '<a href="' . esc_url($url) . '">';
            echo esc_html($title);
            echo '</a>';
            echo '</h3>';
            echo '</article>';
        }
        echo '</div>';
        wp_reset_postdata();
        return ob_get_clean();
    }
}
add_shortcode('curated_post_grid', 'cpg_wpcode_render');
/**
 * Register custom Avada Builder element.
 */
add_action('init', function () {
    if (!function_exists('fusion_builder_map')) {
        return;
    }
    fusion_builder_map([
        'name'            => 'Curated Post Grid',
        'shortcode'       => 'curated_post_grid',
        'icon'            => 'fusiona-blog',
        'allow_generator' => true,
        'params' => [
            // Select blog posts.
            [
                'type'        => 'multiple_select',
                'heading'     => 'Select Blog Posts',
                'param_name'  => 'post_ids',
                'value'       => cpg_get_post_choices(),
                'default'     => '',
                'description' => 'Select multiple published posts.',
            ],
            // Desktop columns.
            [
                'type'       => 'range',
                'heading'    => 'Desktop Columns',
                'param_name' => 'columns',
                'value'      => 3,
                'min'        => 1,
                'max'        => 6,
                'step'       => 1,
            ],
            // Tablet columns.
            [
                'type'       => 'range',
                'heading'    => 'Tablet Columns',
                'param_name' => 'tablet_columns',
                'value'      => 2,
                'min'        => 1,
                'max'        => 4,
                'step'       => 1,
            ],
            // Mobile columns.
            [
                'type'       => 'range',
                'heading'    => 'Mobile Columns',
                'param_name' => 'mobile_columns',
                'value'      => 1,
                'min'        => 1,
                'max'        => 2,
                'step'       => 1,
            ],
            // Grid gap.
            [
                'type'       => 'range',
                'heading'    => 'Grid Gap (px)',
                'param_name' => 'gap',
                'value'      => 24,
                'min'        => 0,
                'max'        => 120,
                'step'       => 1,
            ],
            // Image ratio.
            [
                'type'       => 'select',
                'heading'    => 'Image Ratio',
                'param_name' => 'ratio',
                'value'      => [
                    '16/10' => '16:10',
                    '16/9'  => '16:9',
                    '4/3'   => '4:3',
                    '1/1'   => 'Square',
                    '3/2'   => '3:2',
                    'auto'  => 'Original',
                ],
                'default' => '16/10',
            ],
            // Post limit.
            [
                'type'       => 'range',
                'heading'    => 'Post Limit (0 = All)',
                'param_name' => 'limit',
                'value'      => 0,
                'min'        => 0,
                'max'        => 100,
                'step'       => 1,
            ],
            /**
             * TITLE TYPOGRAPHY
             */
            // Font family dropdown.
            [
                'type'       => 'select',
                'heading'    => 'Title Font Family',
                'param_name' => 'title_font_family',
                'value'      => [
                    'inherit'           => 'Inherit Theme Font',
                    'Arial'             => 'Arial',
                    'Georgia'           => 'Georgia',
                    'Helvetica'         => 'Helvetica',
                    'DM Sans'           => 'DM Sans',
                    'Cormorant Garamond'=> 'Cormorant Garamond',
                    'Roboto'            => 'Roboto',
                    'Open Sans'         => 'Open Sans',
                    'Montserrat'        => 'Montserrat',
                    'Poppins'           => 'Poppins',
                ],
                'default' => 'inherit',
            ],
            // HEX color input.
            [
                'type'        => 'textfield',
                'heading'     => 'Title Color (HEX)',
                'param_name'  => 'title_color',
                'value'       => '#171714',
                'description' => 'Example: #171714 or #FFFFFF',
            ],
            // Font size input.
            [
                'type'        => 'textfield',
                'heading'     => 'Title Font Size',
                'param_name'  => 'title_font_size',
                'value'       => '22px',
                'description' => 'Example: 22px, 1.5rem, 1.25em',
            ],
            // Line height input.
            [
                'type'        => 'textfield',
                'heading'     => 'Title Line Height',
                'param_name'  => 'title_line_height',
                'value'       => '1.4',
                'description' => 'Example: 1.4, 28px, 1.6rem',
            ],
        ],
    ]);
}, 30);

Comments

Add a Comment