Plugin Directory

Changeset 3380394


Ignore:
Timestamp:
10/18/2025 06:08:15 AM (5 weeks ago)
Author:
nalam
Message:

update widget and code organize

Location:
magical-posts-display/trunk
Files:
9 added
26 edited

Legend:

Unmodified
Added
Removed
  • magical-posts-display/trunk/README.txt

    r3334686 r3380394  
    33Donate link: https://wpthemespace.com/donation
    44Tags: post display, Page display, custom Post, elementor widget, post slider
    5 Requires at least: 5.0
     5Requires at least: 6.0
    66Tested up to: 6.8
    77Stable tag: trunk
     
    5757    <li><strong>All options show hide features. </strong></li>
    5858    <li><strong>User-friendly Editor.</strong></li>
     59    <li><strong>Ajax Loadmore button.</strong></li>
     60    <li><strong>Ajax Categories filter.</strong></li>
    5961   
    6062</ul>
     
    137139
    138140== Changelog ==
     141
     142= 1.2.54 =
     143 * Enhanced Security: Added comprehensive nonce verification and input sanitization across all AJAX handlers
     144 * Premium Features: Reading Time, View Count, and Social Share Buttons
     145 * Code Quality: Refactored AJAX methods following WordPress coding standards
     146 * Advanced Media Support: Video, Gallery with priority fallback system
     147 * Hover Effects added: Zoom, Lift, Tilt animations for cards
     148 * Categories Filter Buttons Added
     149 * Improved: Better error handling and default values for AJAX requests
     150 * Performance: Optimized category filtering and infinite scroll functionality
    139151
    140152= 1.2.53 =
  • magical-posts-display/trunk/admin/admin-page/admin-info.php

    r3235168 r3380394  
    1616        add_action('admin_notices', [__CLASS__, 'mp_display_admin_info']);
    1717        add_action('init', [__CLASS__, 'mp_display_admin_info_init']);
     18        add_action('admin_notices', [__CLASS__, 'admin_notice_update_info']);
     19        add_action('admin_notices', [__CLASS__, 'admin_notice_minimum_php_version']);
     20        add_action('admin_notices', [__CLASS__, 'admin_notice_missing_main_plugin']);
     21        add_action('init', [__CLASS__, 'elementor_notice_hide_options']);
    1822    }
    1923
     
    2630                <div class="mge-info-hello">
    2731                    <?php
    28                     $addons_name = esc_html__('Magical Addons, ', 'magical-addons-for-elementor');
     32                    $addons_name = esc_html__('Magical Posts Display, ', 'magical-posts-display');
    2933                    $current_user = wp_get_current_user();
    3034
     
    3236                    $pricing_link = esc_url('https://wpthemespace.com/product/magical-posts-display-pro/');
    3337
    34                     esc_html_e('Hello, ', 'magical-addons-for-elementor');
     38                    esc_html_e('Hey there, ', 'magical-posts-display');
    3539                    echo esc_html($current_user->display_name);
    3640                    ?>
    3741
    38                     <?php esc_html_e('👋🏻', 'magical-addons-for-elementor'); ?>
     42                    <?php esc_html_e('�', 'magical-posts-display'); ?>
    3943                </div>
    4044                <div class="mge-info-desc">
    41                     <div><?php printf(esc_html__('Thank you for choosing Magical Posts Display! ✨ We\'re excited to share that our Pro version is now available, with all custom posts display features. Plus, Pagination, QR code, Share button, reading time, wordcount, filters,popup, lightbox and more 🔥', 'magical-addons-for-elementor'), esc_html($addons_name)); ?></div>
    42                     <div class="mge-offer"><?php printf(esc_html__('Upgrade to Magical Posts Display Pro today and Display your posts the way you want just $21! 🚀', 'magical-addons-for-elementor'), esc_html($addons_name)); ?></div>
     45                    <div><?php printf(esc_html__('Ready to SUPERCHARGE your content display? 🚀 Our PRO version transforms your website with advanced post layouts, lightning-fast AJAX filters, social sharing, reading time, and 50+ premium features that drive MORE engagement! ⚡', 'magical-posts-display'), esc_html($addons_name)); ?></div>
     46                    <div class="mge-offer"><?php printf(esc_html__('💥 LIMITED TIME: Get PRO for just $21 and unlock UNLIMITED possibilities! Join 10,000+ happy customers! �', 'magical-posts-display'), esc_html($addons_name)); ?></div>
    4347                </div>
    4448                <div class="mge-info-actions">
    4549                    <a href="<?php echo esc_url($pro_link); ?>" target="_blank" class="button button-primary upgrade-btn">
    46                         <?php esc_html_e('Upgrade Now', 'magical-addons-for-elementor'); ?>
     50                        <?php esc_html_e('🚀 GET PRO NOW - $21', 'magical-posts-display'); ?>
    4751                    </a>
    4852                    <a href="<?php echo esc_url($pricing_link); ?>" target="_blank" class="button button-primary demo-btn">
    49                         <?php esc_html_e('View Details', 'magical-addons-for-elementor'); ?>
     53                        <?php esc_html_e('💎 See All Features', 'magical-posts-display'); ?>
    5054                    </a>
    51                     <button class="button button-info mgad-dismiss mgade-notice-hide"><?php esc_html_e('Dismiss this notice', 'magical-addons-for-elementor') ?></button>
     55                    <button class="button button-info mgad-dismiss mgade-notice-hide"><?php esc_html_e('Maybe Later', 'magical-posts-display') ?></button>
    5256                </div>
    5357            </div>
     
    5862
    5963
    60 
     64    /**
     65     * Show update notice for new features
     66     *
     67     * @since 1.2.53
     68     * @access public
     69     */
     70    public static function admin_notice_update_info()
     71    {
     72        $hide_notice_update = get_option('mgpd_update_notice_1_2_53');
     73        if (!empty($hide_notice_update)) {
     74            return;
     75        }
     76
     77        $dismiss_url = wp_nonce_url(
     78            add_query_arg('mgpd_update_hide', '1'),
     79            'mgpd_update_notice',
     80            '_wpnonce'
     81        );
     82    ?>
     83        <div class="notice notice-info is-dismissible mgpd-update-notice" style="border-left-color: #00a0d2; padding: 15px;">
     84            <h3 style="margin: 0 0 10px 0;"><?php echo esc_html__('🎉 Magical Posts Display v1.2.53 - Major Update!', 'magical-posts-display'); ?></h3>
     85            <p><strong><?php echo esc_html__('What\'s New:', 'magical-posts-display'); ?></strong></p>
     86            <ul style="list-style: disc; margin-left: 20px;">
     87                <li><?php echo esc_html__('✨ Premium Features: Reading Time, View Count, and Social Share Buttons', 'magical-posts-display'); ?></li>
     88                <li><?php echo esc_html__('🎨 Three Display Styles: Default, Image Top, and Image Overlay positions', 'magical-posts-display'); ?></li>
     89                <li><?php echo esc_html__('📹 Advanced Media Support: Video, Gallery with priority fallback system', 'magical-posts-display'); ?></li>
     90                <li><?php echo esc_html__('🎭 Hover Effects: Zoom, Lift, Tilt animations for cards', 'magical-posts-display'); ?></li>
     91                <li><?php echo esc_html__('🔧 AJAX Optimization: Category filtering and infinite scroll improvements', 'magical-posts-display'); ?></li>
     92                <li><?php echo esc_html__('🎯 Filter Buttons: Complete styling controls in Style tab', 'magical-posts-display'); ?></li>
     93                <li><?php echo esc_html__('🔒 Security: Enhanced nonce verification and sanitization', 'magical-posts-display'); ?></li>
     94                <li><?php echo esc_html__('♻️ Code Quality: Refactored for better performance and maintainability', 'magical-posts-display'); ?></li>
     95            </ul>
     96            <p>
     97                <a href="<?php echo esc_url($dismiss_url); ?>" class="button button-primary"><?php echo esc_html__('Got it, thanks!', 'magical-posts-display'); ?></a>
     98                <a href="https://wpthemespace.com/product/magical-posts-display-pro/" target="_blank" class="button button-secondary" style="margin-left: 10px;"><?php echo esc_html__('Upgrade to Pro', 'magical-posts-display'); ?></a>
     99            </p>
     100        </div>
     101    <?php
     102    }
    61103
    62104    public static function mp_display_admin_info()
    63105    {
    64106
    65         $hide_date = get_option('mgpd_info_protext');
     107        $hide_date = get_option('mgpd_pro_infotext');
    66108        if (!empty($hide_date)) {
    67109            $clickhide = round((time() - strtotime($hide_date)) / 24 / 60 / 60);
     
    90132    public static function mp_display_admin_info_init()
    91133    {
    92         if (isset($_GET['mgrecnot']) && $_GET['mgrecnot'] == 1) {
    93             update_option('mgpd_info_protext', current_time('mysql'));
    94         }
     134        if (isset($_GET['mgrecnot']) && absint($_GET['mgrecnot']) === 1) {
     135            update_option('mgpd_pro_infotext', current_time('mysql'));
     136        }
     137
     138        // Hide update notice
     139        if (isset($_GET['mgpd_update_hide']) && absint($_GET['mgpd_update_hide']) === 1 && isset($_GET['_wpnonce']) && wp_verify_nonce($_GET['_wpnonce'], 'mgpd_update_notice')) {
     140            update_option('mgpd_update_notice_1_2_53', 1);
     141        }
     142    }
     143
     144    /**
     145     * Hide Elementor notice options handler
     146     */
     147    public static function elementor_notice_hide_options()
     148    {
     149        // Security check with nonce verification
     150        if (isset($_GET['mgelhide']) && absint($_GET['mgelhide']) === 1 && isset($_GET['_wpnonce']) && wp_verify_nonce($_GET['_wpnonce'], 'mgpd_hide_notice')) {
     151            update_option('mgelhide9', 1);
     152        }
     153    }
     154
     155    /**
     156     * Admin notice for minimum PHP version
     157     * Warning when the site doesn't have a minimum required PHP version.
     158     */
     159    public static function admin_notice_minimum_php_version()
     160    {
     161        // Check if we should show this notice
     162        if (version_compare(PHP_VERSION, '5.6', '>=')) {
     163            return;
     164        }
     165
     166        if (isset($_GET['activate'])) unset($_GET['activate']);
     167
     168        $message = sprintf(
     169            /* translators: 1: Plugin name 2: PHP 3: Required PHP version */
     170            esc_html__('"%1$s" requires "%2$s" version %3$s or greater.', 'magical-posts-display'),
     171            '<strong>' . esc_html__('Magical Posts Display', 'magical-posts-display') . '</strong>',
     172            '<strong>' . esc_html__('PHP', 'magical-posts-display') . '</strong>',
     173            '5.6'
     174        );
     175
     176        printf(
     177            '<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>',
     178            wp_kses_post($message)
     179        );
     180    }
     181
     182    /**
     183     * Admin notice for missing Elementor plugin
     184     * Warning when the site doesn't have Elementor installed or activated.
     185     */
     186    public static function admin_notice_missing_main_plugin()
     187    {
     188        if (get_option('mgelhide9')) {
     189            return;
     190        }
     191
     192        // Only show on specific pages
     193        global $pagenow;
     194        if (!in_array($pagenow, array('plugins.php', 'admin.php'))) {
     195            return;
     196        }
     197
     198        // Don't show if Elementor is loaded
     199        if (did_action('elementor/loaded')) {
     200            return;
     201        }
     202
     203        if (isset($_GET['activate'])) unset($_GET['activate']);
     204
     205        if (file_exists(WP_PLUGIN_DIR . '/elementor/elementor.php')) {
     206            $magial_eactive_url = wp_nonce_url('plugins.php?action=activate&plugin=elementor/elementor.php&plugin_status=all&paged=1', 'activate-plugin_elementor/elementor.php');
     207            $message = sprintf(
     208                /* translators: 1: Plugin name 2: Elementor 3: Elementor installation link */
     209                esc_html__('%1$s Recommended %2$s plugin, which is currently NOT RUNNING  %3$s', 'magical-posts-display'),
     210                '<strong>' . esc_html__('Magical Posts Display', 'magical-posts-display') . '</strong>',
     211                '<strong>' . esc_html__('Elementor', 'magical-posts-display') . '</strong>',
     212                '<a class="button button-primary" style="margin-left:20px" href="' . $magial_eactive_url . '">' . __('Activate Elementor', 'magical-posts-display') . '</a>'
     213            );
     214        } else {
     215            $magial_einstall_url =  wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=elementor'), 'install-plugin_elementor');
     216            $message = sprintf(
     217                /* translators: 1: Plugin name 2: Elementor 3: Elementor installation link */
     218                esc_html__('%1$s Recommended %2$s plugin for use all Elementor addons, which is currently NOT RUNNING  %3$s', 'magical-posts-display'),
     219                '<strong>' . esc_html__('Magical Posts Display', 'magical-posts-display') . '</strong>',
     220                '<strong>' . esc_html__('Elementor', 'magical-posts-display') . '</strong>',
     221                '<a class="button button-primary" style="margin-left:20px" href="' . $magial_einstall_url . '">' . __('Install Elementor', 'magical-posts-display') . '</a>'
     222            );
     223        }
     224
     225        printf('<div class="notice notice-warning is-dismissible mgpd-notice"><p style="padding: 13px 0">%1$s</p></div>', wp_kses_post($message));
    95226    }
    96227}
    97 mgpAdminInfo::init();
     228
     229// Initialize only if we're in admin and not in pro version
     230if (is_admin() && !mpd_check_plugin_active('magical-posts-display-pro/magical-posts-display-pro.php')) {
     231    mgpAdminInfo::init();
     232}
  • magical-posts-display/trunk/admin/admin-page/admin-page.php

    r3116993 r3380394  
    3737            add_menu_page($menu_text, $menu_text, 'manage_options', 'mgpd-page', array($this, 'plugin_page'), 'dashicons-tickets-alt', 20);
    3838
    39             add_submenu_page('mgpd-page', esc_html__("WelCome Page", 'gbox'), esc_html__("WelCome Page", 'gbox'), "manage_options",  'mgpd-page', array($this, 'plugin_page'));
     39            add_submenu_page('mgpd-page', esc_html__("WelCome Page", 'magical-posts-display' ), esc_html__("WelCome Page", 'magical-posts-display' ), "manage_options",  'mgpd-page', array($this, 'plugin_page'));
    4040        }
    4141
     
    4646                array(
    4747                    'id'    => 'magical_ptab_home',
    48                     'title' => __('Home', 'magical-addons-for-elementor')
     48                    'title' => __('Home', 'magical-posts-display')
    4949                ),
    5050                /*array(
    5151                'id'    => 'magical_addons',
    52                 'title' => __( 'Addons', 'magical-addons-for-elementor' )
     52                'title' => __( 'Addons', 'magical-posts-display' )
    5353            )*/
    5454            );
  • magical-posts-display/trunk/admin/admin-page/welcome-page.php

    r3170252 r3380394  
    1010<div id="mgpdp1" class="magical-post-display mgpdp1">
    1111    <div class="mg-cols">
    12         <section class="sec-wel" <?php if (!class_exists('magicalPostDisplayPro')) : ?> style="background-image: url(<?php echo esc_url(MAGICAL_POSTS_DISPLAY_ASSETS . 'img/blue.svg'); ?>);" <?php else : ?>style="background-image: url(<?php echo esc_url(MAGICAL_POSTS_DISPLAY_ASSETS . 'mg/purple.svg'); ?>);" <?php endif; ?>>
     12        <section class="sec-wel" <?php if (!class_exists('magicalPostDisplayPro')) : ?> style="background-image: url(<?php echo esc_url(MAGICAL_POSTS_DISPLAY_ASSETS . 'img/blue.svg'); ?>);" <?php else : ?>style="background-image: url(<?php echo esc_url(MAGICAL_POSTS_DISPLAY_ASSETS . 'img/purple.svg'); ?>);" <?php endif; ?>>
    1313            <div class="wel-center-text">
    1414                <div class="welsec-icon">
     
    2121                        <?php esc_html_e('See Short Video', 'magical-posts-display'); ?>
    2222                    </a>
    23 
    2423                    <?php if (!class_exists('magicalPostDisplayPro')) : ?>
    25                         <a href="https://wpthemespace.com/product/magical-posts-display-pro/" class="button button-mgp1 button-mgp2"><?php esc_html_e('Buy Pro Now', 'magical-posts-display'); ?></a>
     24                        <a href="https://wpthemespace.com/product/magical-posts-display-pro/" class="button button-mgp1 button-mgp2"><?php esc_html_e('View Pro Version', 'magical-posts-display'); ?></a>
    2625                    <?php endif; ?>
    2726                </div>
  • magical-posts-display/trunk/admin/extra-function.php

    r3170252 r3380394  
    6161        $url1 = esc_url('https://wpthemespace.com/product-category/pro-theme/');
    6262
    63         $message = __('<strong><span style="color:red;">Latest WordPress Theme:</span>  <span style="color:green"> If you find a Secure, SEO friendly, full functional premium WordPress theme for your site then </span>  </strong>', 'niso');
     63        $message = __('<strong><span style="color:red;">Latest WordPress Theme:</span>  <span style="color:green"> If you find a Secure, SEO friendly, full functional premium WordPress theme for your site then </span>  </strong>', 'magical-posts-display');
    6464
    6565        printf(
  • magical-posts-display/trunk/admin/src/cmb2/includes/CMB2.php

    r2892423 r3380394  
    11<?php
     2
    23/**
    34 * CMB2 - The core metabox object
     
    1920 * The main CMB2 object for storing box data/properties.
    2021 */
    21 class CMB2 extends CMB2_Base {
     22class CMB2 extends CMB2_Base
     23{
    2224
    2325    /**
     
    194196     * @param integer $object_id Optional object id.
    195197     */
    196     public function __construct( $config, $object_id = 0 ) {
    197 
    198         if ( empty( $config['id'] ) ) {
    199             wp_die( esc_html__( 'Metabox configuration is required to have an ID parameter.', 'cmb2' ) );
     198    public function __construct($config, $object_id = 0)
     199    {
     200
     201        if (empty($config['id'])) {
     202            wp_die(esc_html__('Metabox configuration is required to have an ID parameter.', 'cmb2'));
    200203        }
    201204
    202205        $this->cmb_id = $config['id'];
    203         $this->meta_box = wp_parse_args( $config, $this->mb_defaults );
     206        $this->meta_box = wp_parse_args($config, $this->mb_defaults);
    204207        $this->meta_box['fields'] = array();
    205208
    206209        // Ensures object_types is an array.
    207         $this->set_prop( 'object_types', $this->box_types() );
    208         $this->object_id( $object_id );
    209 
    210         if ( $this->is_options_page_mb() ) {
     210        $this->set_prop('object_types', $this->box_types());
     211        $this->object_id($object_id);
     212
     213        if ($this->is_options_page_mb()) {
    211214            $this->init_options_mb();
    212215        }
     
    214217        $this->mb_object_type();
    215218
    216         if ( ! empty( $config['fields'] ) && is_array( $config['fields'] ) ) {
    217             $this->add_fields( $config['fields'] );
    218         }
    219 
    220         CMB2_Boxes::add( $this );
     219        if (! empty($config['fields']) && is_array($config['fields'])) {
     220            $this->add_fields($config['fields']);
     221        }
     222
     223        CMB2_Boxes::add($this);
    221224
    222225        /**
     
    227230         * @param array $cmb This CMB2 object
    228231         */
    229         do_action( "cmb2_init_{$this->cmb_id}", $this );
     232        do_action("cmb2_init_{$this->cmb_id}", $this);
    230233
    231234        // Hook in the hookup... how meta.
    232         add_action( "cmb2_init_hookup_{$this->cmb_id}", array( 'CMB2_hookup', 'maybe_init_and_hookup' ) );
     235        add_action("cmb2_init_hookup_{$this->cmb_id}", array('CMB2_hookup', 'maybe_init_and_hookup'));
    233236
    234237        // Hook in the rest api functionality.
    235         add_action( "cmb2_init_hookup_{$this->cmb_id}", array( 'CMB2_REST', 'maybe_init_and_hookup' ) );
     238        add_action("cmb2_init_hookup_{$this->cmb_id}", array('CMB2_REST', 'maybe_init_and_hookup'));
    236239    }
    237240
     
    245248     * @return CMB2
    246249     */
    247     public function show_form( $object_id = 0, $object_type = '' ) {
    248         $this->render_form_open( $object_id, $object_type );
    249 
    250         foreach ( $this->prop( 'fields' ) as $field_args ) {
    251             $this->render_field( $field_args );
    252         }
    253 
    254         return $this->render_form_close( $object_id, $object_type );
     250    public function show_form($object_id = 0, $object_type = '')
     251    {
     252        $this->render_form_open($object_id, $object_type);
     253
     254        foreach ($this->prop('fields') as $field_args) {
     255            $this->render_field($field_args);
     256        }
     257
     258        return $this->render_form_close($object_id, $object_type);
    255259    }
    256260
     
    265269     * @return CMB2
    266270     */
    267     public function render_form_open( $object_id = 0, $object_type = '' ) {
    268         $object_type = $this->object_type( $object_type );
    269         $object_id = $this->object_id( $object_id );
     271    public function render_form_open($object_id = 0, $object_type = '')
     272    {
     273        $object_type = $this->object_type($object_type);
     274        $object_id = $this->object_id($object_id);
    270275
    271276        echo "\n<!-- Begin CMB2 Fields -->\n";
     
    283288         * @param array  $cmb         This CMB2 object.
    284289         */
    285         do_action( 'cmb2_before_form', $this->cmb_id, $object_id, $object_type, $this );
     290        do_action('cmb2_before_form', $this->cmb_id, $object_id, $object_type, $this);
    286291
    287292        /**
     
    298303         * @param array  $cmb         This CMB2 object
    299304         */
    300         do_action( "cmb2_before_{$object_type}_form_{$this->cmb_id}", $object_id, $this );
    301 
    302         echo '<div class="', esc_attr( $this->box_classes() ), '"><div id="cmb2-metabox-', sanitize_html_class( $this->cmb_id ), '" class="cmb2-metabox cmb-field-list">';
     305        do_action("cmb2_before_{$object_type}_form_{$this->cmb_id}", $object_id, $this);
     306
     307        echo '<div class="', esc_attr($this->box_classes()), '"><div id="cmb2-metabox-', sanitize_html_class($this->cmb_id), '" class="cmb2-metabox cmb-field-list">';
    303308
    304309        return $this;
     
    311316     * @return string Space concatenated list of classes
    312317     */
    313     public function box_classes() {
    314 
    315         $classes = array( 'cmb2-wrap', 'form-table' );
     318    public function box_classes()
     319    {
     320
     321        $classes = array('cmb2-wrap', 'form-table');
    316322
    317323        // Use the callback to fetch classes.
    318         if ( $added_classes = $this->get_param_callback_result( 'classes_cb' ) ) {
    319             $added_classes = is_array( $added_classes ) ? $added_classes : array( $added_classes );
    320             $classes = array_merge( $classes, $added_classes );
    321         }
    322 
    323         if ( $added_classes = $this->prop( 'classes' ) ) {
    324             $added_classes = is_array( $added_classes ) ? $added_classes : array( $added_classes );
    325             $classes = array_merge( $classes, $added_classes );
     324        if ($added_classes = $this->get_param_callback_result('classes_cb')) {
     325            $added_classes = is_array($added_classes) ? $added_classes : array($added_classes);
     326            $classes = array_merge($classes, $added_classes);
     327        }
     328
     329        if ($added_classes = $this->prop('classes')) {
     330            $added_classes = is_array($added_classes) ? $added_classes : array($added_classes);
     331            $classes = array_merge($classes, $added_classes);
    326332        }
    327333
     
    331337         * @since 2.2.4
    332338         */
    333         if ( $this->is_alternate_context_box() ) {
     339        if ($this->is_alternate_context_box()) {
    334340            $context = array();
    335341
    336342            // Include custom class if requesting no title.
    337             if ( ! $this->prop( 'title' ) && ! $this->prop( 'remove_box_wrap' ) ) {
     343            if (! $this->prop('title') && ! $this->prop('remove_box_wrap')) {
    338344                $context[] = 'cmb2-context-wrap-no-title';
    339345            }
     
    343349
    344350            // Include a context-type based context wrapper.
    345             $context[] = 'cmb2-context-wrap-' . $this->prop( 'context' );
     351            $context[] = 'cmb2-context-wrap-' . $this->prop('context');
    346352
    347353            // Include an ID based context wrapper as well.
    348             $context[] = 'cmb2-context-wrap-' . $this->prop( 'id' );
     354            $context[] = 'cmb2-context-wrap-' . $this->prop('id');
    349355
    350356            // And merge all the classes back into the array.
    351             $classes = array_merge( $classes, $context );
     357            $classes = array_merge($classes, $context);
    352358        }
    353359
     
    360366         * @param CMB2   $cmb     This CMB2 object.
    361367         */
    362         $classes = apply_filters( 'cmb2_wrap_classes', $classes, $this );
     368        $classes = apply_filters('cmb2_wrap_classes', $classes, $this);
    363369
    364370        // Clean up.
    365         $classes = array_map( 'strip_tags', array_filter( $classes ) );
     371        $classes = array_map('wp_strip_all_tags', array_filter($classes));
    366372
    367373        // Remove any duplicates.
    368         $classes = array_unique( $classes );
     374        $classes = array_unique($classes);
    369375
    370376        // Make a string.
    371         return implode( ' ', $classes );
     377        return implode(' ', $classes);
    372378    }
    373379
     
    382388     * @return CMB2
    383389     */
    384     public function render_form_close( $object_id = 0, $object_type = '' ) {
    385         $object_type = $this->object_type( $object_type );
    386         $object_id = $this->object_id( $object_id );
     390    public function render_form_close($object_id = 0, $object_type = '')
     391    {
     392        $object_type = $this->object_type($object_type);
     393        $object_id = $this->object_id($object_id);
    387394
    388395        echo '</div></div>';
     
    402409         * @param array  $cmb         This CMB2 object
    403410         */
    404         do_action( "cmb2_after_{$object_type}_form_{$this->cmb_id}", $object_id, $this );
     411        do_action("cmb2_after_{$object_type}_form_{$this->cmb_id}", $object_id, $this);
    405412
    406413        /**
     
    414421         * @param array  $cmb         This CMB2 object.
    415422         */
    416         do_action( 'cmb2_after_form', $this->cmb_id, $object_id, $object_type, $this );
     423        do_action('cmb2_after_form', $this->cmb_id, $object_id, $object_type, $this);
    417424
    418425        echo "\n<!-- End CMB2 Fields -->\n";
     
    428435     * @return mixed CMB2_Field object if successful.
    429436     */
    430     public function render_field( $field_args ) {
    431         $field_args['context'] = $this->prop( 'context' );
    432 
    433         if ( 'group' === $field_args['type'] ) {
    434 
    435             if ( ! isset( $field_args['show_names'] ) ) {
    436                 $field_args['show_names'] = $this->prop( 'show_names' );
     437    public function render_field($field_args)
     438    {
     439        $field_args['context'] = $this->prop('context');
     440
     441        if ('group' === $field_args['type']) {
     442
     443            if (! isset($field_args['show_names'])) {
     444                $field_args['show_names'] = $this->prop('show_names');
    437445            }
    438             $field = $this->render_group( $field_args );
    439 
    440         } elseif ( 'hidden' === $field_args['type'] && $this->get_field( $field_args )->should_show() ) {
     446            $field = $this->render_group($field_args);
     447        } elseif ('hidden' === $field_args['type'] && $this->get_field($field_args)->should_show()) {
    441448            // Save rendering for after the metabox.
    442             $field = $this->add_hidden_field( $field_args );
    443 
     449            $field = $this->add_hidden_field($field_args);
    444450        } else {
    445451
    446             $field_args['show_names'] = $this->prop( 'show_names' );
     452            $field_args['show_names'] = $this->prop('show_names');
    447453
    448454            // Render default fields.
    449             $field = $this->get_field( $field_args )->render_field();
     455            $field = $this->get_field($field_args)->render_field();
    450456        }
    451457
     
    459465     * @return CMB2_Field|null Group field object.
    460466     */
    461     public function render_group( $args ) {
     467    public function render_group($args)
     468    {
    462469        $field_group = false;
    463470
    464         if ( $args instanceof CMB2_Field ) {
     471        if ($args instanceof CMB2_Field) {
    465472            $field_group = 'group' === $args->type() ? $args : false;
    466         } elseif ( isset( $args['id'], $args['fields'] ) && is_array( $args['fields'] ) ) {
    467             $field_group = $this->get_field( $args );
    468         }
    469 
    470         if ( ! $field_group ) {
     473        } elseif (isset($args['id'], $args['fields']) && is_array($args['fields'])) {
     474            $field_group = $this->get_field($args);
     475        }
     476
     477        if (! $field_group) {
    471478            return;
    472479        }
    473480
    474481        $field_group->render_context = 'edit';
    475         $field_group->peform_param_callback( 'render_row_cb' );
     482        $field_group->peform_param_callback('render_row_cb');
    476483
    477484        return $field_group;
     
    488495     * @return CMB2_Field|null Group field object.
    489496     */
    490     public function render_group_callback( $field_args, $field_group ) {
     497    public function render_group_callback($field_args, $field_group)
     498    {
    491499
    492500        // If field is requesting to be conditionally shown.
    493         if ( ! $field_group || ! $field_group->should_show() ) {
     501        if (! $field_group || ! $field_group->should_show()) {
    494502            return;
    495503        }
     
    497505        $field_group->index = 0;
    498506
    499         $field_group->peform_param_callback( 'before_group' );
    500 
    501         $desc      = $field_group->args( 'description' );
    502         $label     = $field_group->args( 'name' );
     507        $field_group->peform_param_callback('before_group');
     508
     509        $desc      = $field_group->args('description');
     510        $label     = $field_group->args('name');
    503511        $group_val = (array) $field_group->value();
    504512
    505         echo '<div class="cmb-row cmb-repeat-group-wrap ', esc_attr( $field_group->row_classes() ), '" data-fieldtype="group"><div class="cmb-td"><div data-groupid="', esc_attr( $field_group->id() ), '" id="', esc_attr( $field_group->id() ), '_repeat" ', $this->group_wrap_attributes( $field_group ), '>';
    506 
    507         if ( $desc || $label ) {
     513        echo '<div class="cmb-row cmb-repeat-group-wrap ', esc_attr($field_group->row_classes()), '" data-fieldtype="group"><div class="cmb-td"><div data-groupid="', esc_attr($field_group->id()), '" id="', esc_attr($field_group->id()), '_repeat" ', $this->group_wrap_attributes($field_group), '>';
     514
     515        if ($desc || $label) {
    508516            $class = $desc ? ' cmb-group-description' : '';
    509517            echo '<div class="cmb-row', $class, '"><div class="cmb-th">';
    510             if ( $label ) {
     518            if ($label) {
    511519                echo '<h2 class="cmb-group-name">', $label, '</h2>';
    512520            }
    513             if ( $desc ) {
     521            if ($desc) {
    514522                echo '<p class="cmb2-metabox-description">', $desc, '</p>';
    515523            }
     
    517525        }
    518526
    519         if ( ! empty( $group_val ) ) {
    520             foreach ( $group_val as $group_key => $field_id ) {
    521                 $this->render_group_row( $field_group );
     527        if (! empty($group_val)) {
     528            foreach ($group_val as $group_key => $field_id) {
     529                $this->render_group_row($field_group);
    522530                $field_group->index++;
    523531            }
    524532        } else {
    525             $this->render_group_row( $field_group );
    526         }
    527 
    528         if ( $field_group->args( 'repeatable' ) ) {
    529             echo '<div class="cmb-row"><div class="cmb-td"><p class="cmb-add-row"><button type="button" data-selector="', esc_attr( $field_group->id() ), '_repeat" data-grouptitle="', esc_attr( $field_group->options( 'group_title' ) ), '" class="cmb-add-group-row button-secondary">', $field_group->options( 'add_button' ), '</button></p></div></div>';
     533            $this->render_group_row($field_group);
     534        }
     535
     536        if ($field_group->args('repeatable')) {
     537            echo '<div class="cmb-row"><div class="cmb-td"><p class="cmb-add-row"><button type="button" data-selector="', esc_attr($field_group->id()), '_repeat" data-grouptitle="', esc_attr($field_group->options('group_title')), '" class="cmb-add-group-row button-secondary">', $field_group->options('add_button'), '</button></p></div></div>';
    530538        }
    531539
    532540        echo '</div></div></div>';
    533541
    534         $field_group->peform_param_callback( 'after_group' );
     542        $field_group->peform_param_callback('after_group');
    535543
    536544        return $field_group;
     
    544552     * @return string                  The attributes string.
    545553     */
    546     public function group_wrap_attributes( $field_group ) {
     554    public function group_wrap_attributes($field_group)
     555    {
    547556        $classes = 'cmb-nested cmb-field-list cmb-repeatable-group';
    548         $classes .= $field_group->options( 'sortable' ) ? ' sortable' : ' non-sortable';
    549         $classes .= $field_group->args( 'repeatable' ) ? ' repeatable' : ' non-repeatable';
     557        $classes .= $field_group->options('sortable') ? ' sortable' : ' non-sortable';
     558        $classes .= $field_group->args('repeatable') ? ' repeatable' : ' non-repeatable';
    550559
    551560        $group_wrap_attributes = array(
     
    564573         * @param CMB2_Field $field_group           The group CMB2_Field object.
    565574         */
    566         $group_wrap_attributes = apply_filters( 'cmb2_group_wrap_attributes', $group_wrap_attributes, $field_group );
     575        $group_wrap_attributes = apply_filters('cmb2_group_wrap_attributes', $group_wrap_attributes, $field_group);
    567576
    568577        $atts = array();
    569         foreach ( $group_wrap_attributes as $att => $att_value ) {
    570             if ( ! CMB2_Utils::is_data_attribute( $att ) ) {
    571                 $att_value = htmlspecialchars( $att_value );
     578        foreach ($group_wrap_attributes as $att => $att_value) {
     579            if (! CMB2_Utils::is_data_attribute($att)) {
     580                $att_value = htmlspecialchars($att_value);
    572581            }
    573582
    574             $atts[ sanitize_html_class( $att ) ] = sanitize_text_field( strip_tags( $att_value ) );
    575         }
    576 
    577         return CMB2_Utils::concat_attrs( $atts );
     583            $atts[sanitize_html_class($att)] = sanitize_text_field(wp_strip_all_tags($att_value));
     584        }
     585
     586        return CMB2_Utils::concat_attrs($atts);
    578587    }
    579588
     
    586595     * @return CMB2
    587596     */
    588     public function render_group_row( $field_group ) {
    589 
    590         $field_group->peform_param_callback( 'before_group_row' );
    591         $closed_class     = $field_group->options( 'closed' ) ? ' closed' : '';
    592         $confirm_deletion = $field_group->options( 'remove_confirm' );
    593         $confirm_deletion = ! empty( $confirm_deletion ) ? $confirm_deletion : '';
     597    public function render_group_row($field_group)
     598    {
     599
     600        $field_group->peform_param_callback('before_group_row');
     601        $closed_class     = $field_group->options('closed') ? ' closed' : '';
     602        $confirm_deletion = $field_group->options('remove_confirm');
     603        $confirm_deletion = ! empty($confirm_deletion) ? $confirm_deletion : '';
    594604
    595605        echo '
    596606        <div id="cmb-group-', $field_group->id(), '-', $field_group->index, '" class="postbox cmb-row cmb-repeatable-grouping', $closed_class, '" data-iterator="', $field_group->index, '">';
    597607
    598         if ( $field_group->args( 'repeatable' ) ) {
    599             echo '<button type="button" data-selector="', $field_group->id(), '_repeat" data-confirm="', esc_attr( $confirm_deletion ), '" class="dashicons-before dashicons-no-alt cmb-remove-group-row" title="', esc_attr( $field_group->options( 'remove_button' ) ), '"></button>';
    600         }
    601 
    602             echo '
    603             <div class="cmbhandle" title="' , esc_attr__( 'Click to toggle', 'cmb2' ), '"><br></div>
    604             <h3 class="cmb-group-title cmbhandle-title"><span>', $field_group->replace_hash( $field_group->options( 'group_title' ) ), '</span></h3>
     608        if ($field_group->args('repeatable')) {
     609            echo '<button type="button" data-selector="', $field_group->id(), '_repeat" data-confirm="', esc_attr($confirm_deletion), '" class="dashicons-before dashicons-no-alt cmb-remove-group-row" title="', esc_attr($field_group->options('remove_button')), '"></button>';
     610        }
     611
     612        echo '
     613            <div class="cmbhandle" title="', esc_attr__('Click to toggle', 'cmb2'), '"><br></div>
     614            <h3 class="cmb-group-title cmbhandle-title"><span>', $field_group->replace_hash($field_group->options('group_title')), '</span></h3>
    605615
    606616            <div class="inside cmb-td cmb-nested cmb-field-list">';
    607                 // Loop and render repeatable group fields.
    608         foreach ( array_values( $field_group->args( 'fields' ) ) as $field_args ) {
    609             if ( 'hidden' === $field_args['type'] ) {
     617        // Loop and render repeatable group fields.
     618        foreach (array_values($field_group->args('fields')) as $field_args) {
     619            if ('hidden' === $field_args['type']) {
    610620
    611621                // Save rendering for after the metabox.
    612                 $this->add_hidden_field( $field_args, $field_group );
    613 
     622                $this->add_hidden_field($field_args, $field_group);
    614623            } else {
    615624
    616                 $field_args['show_names'] = $field_group->args( 'show_names' );
    617                 $field_args['context']    = $field_group->args( 'context' );
    618 
    619                 $this->get_field( $field_args, $field_group )->render_field();
     625                $field_args['show_names'] = $field_group->args('show_names');
     626                $field_args['context']    = $field_group->args('context');
     627
     628                $this->get_field($field_args, $field_group)->render_field();
    620629            }
    621630        }
    622631
    623         if ( $field_group->args( 'repeatable' ) ) {
     632        if ($field_group->args('repeatable')) {
    624633            echo '
    625634                    <div class="cmb-row cmb-remove-field-row">
    626635                        <div class="cmb-remove-row">
    627                             <button type="button" data-selector="', $field_group->id(), '_repeat" data-confirm="', esc_attr( $confirm_deletion ), '" class="cmb-remove-group-row cmb-remove-group-row-button alignright button-secondary">', $field_group->options( 'remove_button' ), '</button>
     636                            <button type="button" data-selector="', $field_group->id(), '_repeat" data-confirm="', esc_attr($confirm_deletion), '" class="cmb-remove-group-row cmb-remove-group-row-button alignright button-secondary">', $field_group->options('remove_button'), '</button>
    628637                        </div>
    629638                    </div>
    630639                    ';
    631640        }
    632             echo '
     641        echo '
    633642            </div>
    634643        </div>
    635644        ';
    636645
    637         $field_group->peform_param_callback( 'after_group_row' );
     646        $field_group->peform_param_callback('after_group_row');
    638647
    639648        return $this;
     
    649658     * @return CMB2_Field
    650659     */
    651     public function add_hidden_field( $field_args, $field_group = null ) {
    652         if ( isset( $field_args['field_args'] ) ) {
     660    public function add_hidden_field($field_args, $field_group = null)
     661    {
     662        if (isset($field_args['field_args'])) {
    653663            // For back-compatibility.
    654             $field = new CMB2_Field( $field_args );
     664            $field = new CMB2_Field($field_args);
    655665        } else {
    656             $field = $this->get_new_field( $field_args, $field_group );
    657         }
    658 
    659         $types = new CMB2_Types( $field );
    660 
    661         if ( $field_group ) {
     666            $field = $this->get_new_field($field_args, $field_group);
     667        }
     668
     669        $types = new CMB2_Types($field);
     670
     671        if ($field_group) {
    662672            $types->iterator = $field_group->index;
    663673        }
     
    675685     * @return CMB2
    676686     */
    677     public function render_hidden_fields() {
    678         if ( ! empty( $this->hidden_fields ) ) {
    679             foreach ( $this->hidden_fields as $hidden ) {
     687    public function render_hidden_fields()
     688    {
     689        if (! empty($this->hidden_fields)) {
     690            foreach ($this->hidden_fields as $hidden) {
    680691                $hidden->render();
    681692            }
     
    692703     * @return mixed
    693704     */
    694     public function get_sanitized_values( array $data_to_sanitize ) {
     705    public function get_sanitized_values(array $data_to_sanitize)
     706    {
    695707        $this->data_to_save = $data_to_sanitize;
    696708        $stored_id          = $this->object_id();
    697709
    698710        // We do this So CMB will sanitize our data for us, but not save it.
    699         $this->object_id( '_' );
     711        $this->object_id('_');
    700712
    701713        // Ensure temp. data store is empty.
    702         cmb2_options( 0 )->set();
     714        cmb2_options(0)->set();
    703715
    704716        // We want to get any taxonomy values back.
    705         add_filter( "cmb2_return_taxonomy_values_{$this->cmb_id}", '__return_true' );
     717        add_filter("cmb2_return_taxonomy_values_{$this->cmb_id}", '__return_true');
    706718
    707719        // Process/save fields.
     
    709721
    710722        // Put things back the way they were.
    711         remove_filter( "cmb2_return_taxonomy_values_{$this->cmb_id}", '__return_true' );
     723        remove_filter("cmb2_return_taxonomy_values_{$this->cmb_id}", '__return_true');
    712724
    713725        // Get data from temp. data store.
    714         $sanitized_values = cmb2_options( 0 )->get_options();
     726        $sanitized_values = cmb2_options(0)->get_options();
    715727
    716728        // Empty out temp. data store again.
    717         cmb2_options( 0 )->set();
     729        cmb2_options(0)->set();
    718730
    719731        // Reset the object id.
    720         $this->object_id( $stored_id );
     732        $this->object_id($stored_id);
    721733
    722734        return $sanitized_values;
     
    733745     * @return CMB2
    734746     */
    735     public function save_fields( $object_id = 0, $object_type = '', $data_to_save = array() ) {
     747    public function save_fields($object_id = 0, $object_type = '', $data_to_save = array())
     748    {
    736749
    737750        // Fall-back to $_POST data.
    738         $this->data_to_save = ! empty( $data_to_save ) ? $data_to_save : $_POST;
    739         $object_id = $this->object_id( $object_id );
    740         $object_type = $this->object_type( $object_type );
     751        $this->data_to_save = ! empty($data_to_save) ? $data_to_save : $_POST;
     752        $object_id = $this->object_id($object_id);
     753        $object_type = $this->object_type($object_type);
    741754
    742755        $this->process_fields();
    743756
    744757        // If options page, save the updated options.
    745         if ( 'options-page' === $object_type ) {
    746             cmb2_options( $object_id )->set();
     758        if ('options-page' === $object_type) {
     759            cmb2_options($object_id)->set();
    747760        }
    748761
     
    757770     * @return CMB2
    758771     */
    759     public function process_fields() {
     772    public function process_fields()
     773    {
    760774
    761775        $this->pre_process();
    762776
    763777        // Remove the show_on properties so saving works.
    764         $this->prop( 'show_on', array() );
     778        $this->prop('show_on', array());
    765779
    766780        // save field ids of those that are updated.
    767781        $this->updated = array();
    768782
    769         foreach ( $this->prop( 'fields' ) as $field_args ) {
    770             $this->process_field( $field_args );
     783        foreach ($this->prop('fields') as $field_args) {
     784            $this->process_field($field_args);
    771785        }
    772786
     
    782796     * @return CMB2
    783797     */
    784     public function process_field( $field_args ) {
    785 
    786         switch ( $field_args['type'] ) {
     798    public function process_field($field_args)
     799    {
     800
     801        switch ($field_args['type']) {
    787802
    788803            case 'group':
    789                 if ( $this->save_group( $field_args ) ) {
     804                if ($this->save_group($field_args)) {
    790805                    $this->updated[] = $field_args['id'];
    791806                }
     
    798813
    799814            default:
    800                 $field = $this->get_new_field( $field_args );
    801 
    802                 if ( $field->save_field_from_data( $this->data_to_save ) ) {
     815                $field = $this->get_new_field($field_args);
     816
     817                if ($field->save_field_from_data($this->data_to_save)) {
    803818                    $this->updated[] = $field->id();
    804819                }
     
    817832     * @return CMB2
    818833     */
    819     public function pre_process() {
     834    public function pre_process()
     835    {
    820836        $object_type = $this->object_type();
    821837
     
    833849         * @param int   $object_id The ID of the current object
    834850         */
    835         do_action( "cmb2_{$object_type}_process_fields_{$this->cmb_id}", $this, $this->object_id() );
     851        do_action("cmb2_{$object_type}_process_fields_{$this->cmb_id}", $this, $this->object_id());
    836852
    837853        return $this;
     
    846862     * @return CMB2
    847863     */
    848     public function after_save() {
     864    public function after_save()
     865    {
    849866        $object_type = $this->object_type();
    850867        $object_id   = $this->object_id();
     
    863880         * @param array  $cmb         This CMB2 object
    864881         */
    865         do_action( "cmb2_save_{$object_type}_fields", $object_id, $this->cmb_id, $this->updated, $this );
     882        do_action("cmb2_save_{$object_type}_fields", $object_id, $this->cmb_id, $this->updated, $this);
    866883
    867884        /**
     
    879896         * @param array  $cmb         This CMB2 object
    880897         */
    881         do_action( "cmb2_save_{$object_type}_fields_{$this->cmb_id}", $object_id, $this->updated, $this );
     898        do_action("cmb2_save_{$object_type}_fields_{$this->cmb_id}", $object_id, $this->updated, $this);
    882899
    883900        return $this;
     
    891908     * @return mixed        Return of CMB2_Field::update_data().
    892909     */
    893     public function save_group( $args ) {
    894         if ( ! isset( $args['id'], $args['fields'] ) || ! is_array( $args['fields'] ) ) {
     910    public function save_group($args)
     911    {
     912        if (! isset($args['id'], $args['fields']) || ! is_array($args['fields'])) {
    895913            return;
    896914        }
    897915
    898         return $this->save_group_field( $this->get_new_field( $args ) );
     916        return $this->save_group_field($this->get_new_field($args));
    899917    }
    900918
     
    906924     * @return mixed                   Return of CMB2_Field::update_data().
    907925     */
    908     public function save_group_field( $field_group ) {
     926    public function save_group_field($field_group)
     927    {
    909928        $base_id = $field_group->id();
    910929
    911         if ( ! isset( $this->data_to_save[ $base_id ] ) ) {
     930        if (! isset($this->data_to_save[$base_id])) {
    912931            return;
    913932        }
     
    915934        $old        = $field_group->get_data();
    916935        // Check if group field has sanitization_cb.
    917         $group_vals = $field_group->sanitization_cb( $this->data_to_save[ $base_id ] );
     936        $group_vals = $field_group->sanitization_cb($this->data_to_save[$base_id]);
    918937        $saved      = array();
    919938
     
    921940        $field_group->data_to_save = $this->data_to_save;
    922941
    923         foreach ( array_values( $field_group->fields() ) as $field_args ) {
    924             if ( 'title' === $field_args['type'] ) {
     942        foreach (array_values($field_group->fields()) as $field_args) {
     943            if ('title' === $field_args['type']) {
    925944                // Don't process title fields.
    926945                continue;
    927946            }
    928947
    929             $field  = $this->get_new_field( $field_args, $field_group );
    930             $sub_id = $field->id( true );
    931             if ( empty( $saved[ $field_group->index ] ) ) {
    932                 $saved[ $field_group->index ] = array();
     948            $field  = $this->get_new_field($field_args, $field_group);
     949            $sub_id = $field->id(true);
     950            if (empty($saved[$field_group->index])) {
     951                $saved[$field_group->index] = array();
    933952            }
    934953
    935             foreach ( (array) $group_vals as $field_group->index => $post_vals ) {
     954            foreach ((array) $group_vals as $field_group->index => $post_vals) {
    936955
    937956                // Get value.
    938                 $new_val = isset( $group_vals[ $field_group->index ][ $sub_id ] )
    939                     ? $group_vals[ $field_group->index ][ $sub_id ]
     957                $new_val = isset($group_vals[$field_group->index][$sub_id])
     958                    ? $group_vals[$field_group->index][$sub_id]
    940959                    : false;
    941960
    942961                // Sanitize.
    943                 $new_val = $field->sanitization_cb( $new_val );
    944 
    945                 if ( is_array( $new_val ) && $field->args( 'has_supporting_data' ) ) {
    946                     if ( $field->args( 'repeatable' ) ) {
     962                $new_val = $field->sanitization_cb($new_val);
     963
     964                if (is_array($new_val) && $field->args('has_supporting_data')) {
     965                    if ($field->args('repeatable')) {
    947966                        $_new_val = array();
    948                         foreach ( $new_val as $group_index => $grouped_data ) {
     967                        foreach ($new_val as $group_index => $grouped_data) {
    949968                            // Add the supporting data to the $saved array stack.
    950                             $saved[ $field_group->index ][ $grouped_data['supporting_field_id'] ][] = $grouped_data['supporting_field_value'];
     969                            $saved[$field_group->index][$grouped_data['supporting_field_id']][] = $grouped_data['supporting_field_value'];
    951970                            // Reset var to the actual value.
    952                             $_new_val[ $group_index ] = $grouped_data['value'];
     971                            $_new_val[$group_index] = $grouped_data['value'];
    953972                        }
    954973                        $new_val = $_new_val;
    955974                    } else {
    956975                        // Add the supporting data to the $saved array stack.
    957                         $saved[ $field_group->index ][ $new_val['supporting_field_id'] ] = $new_val['supporting_field_value'];
     976                        $saved[$field_group->index][$new_val['supporting_field_id']] = $new_val['supporting_field_value'];
    958977                        // Reset var to the actual value.
    959978                        $new_val = $new_val['value'];
     
    962981
    963982                // Get old value.
    964                 $old_val = is_array( $old ) && isset( $old[ $field_group->index ][ $sub_id ] )
    965                     ? $old[ $field_group->index ][ $sub_id ]
     983                $old_val = is_array($old) && isset($old[$field_group->index][$sub_id])
     984                    ? $old[$field_group->index][$sub_id]
    966985                    : false;
    967986
    968                 $is_updated = ( ! CMB2_Utils::isempty( $new_val ) && $new_val !== $old_val );
    969                 $is_removed = ( CMB2_Utils::isempty( $new_val ) && ! CMB2_Utils::isempty( $old_val ) );
     987                $is_updated = (! CMB2_Utils::isempty($new_val) && $new_val !== $old_val);
     988                $is_removed = (CMB2_Utils::isempty($new_val) && ! CMB2_Utils::isempty($old_val));
    970989
    971990                // Compare values and add to `$updated` array.
    972                 if ( $is_updated || $is_removed ) {
     991                if ($is_updated || $is_removed) {
    973992                    $this->updated[] = $base_id . '::' . $field_group->index . '::' . $sub_id;
    974993                }
    975994
    976995                // Add to `$saved` array.
    977                 $saved[ $field_group->index ][ $sub_id ] = $new_val;
    978 
    979             }// End foreach.
    980 
    981             $saved[ $field_group->index ] = CMB2_Utils::filter_empty( $saved[ $field_group->index ] );
    982         }// End foreach.
    983 
    984         $saved = CMB2_Utils::filter_empty( $saved );
    985 
    986         return $field_group->update_data( $saved, true );
     996                $saved[$field_group->index][$sub_id] = $new_val;
     997            } // End foreach.
     998
     999            $saved[$field_group->index] = CMB2_Utils::filter_empty($saved[$field_group->index]);
     1000        } // End foreach.
     1001
     1002        $saved = CMB2_Utils::filter_empty($saved);
     1003
     1004        return $field_group->update_data($saved, true);
    9871005    }
    9881006
     
    9941012     * @return integer|string $object_id Object ID.
    9951013     */
    996     public function object_id( $object_id = 0 ) {
     1014    public function object_id($object_id = 0)
     1015    {
    9971016        global $pagenow;
    9981017
    999         if ( $object_id ) {
     1018        if ($object_id) {
    10001019            $this->object_id = $object_id;
    10011020            return $this->object_id;
    10021021        }
    10031022
    1004         if ( $this->object_id ) {
     1023        if ($this->object_id) {
    10051024            return $this->object_id;
    10061025        }
    10071026
    10081027        // Try to get our object ID from the global space.
    1009         switch ( $this->object_type() ) {
     1028        switch ($this->object_type()) {
    10101029            case 'user':
    1011                 $object_id = isset( $_REQUEST['user_id'] ) ? wp_unslash( $_REQUEST['user_id'] ) : $object_id;
    1012                 $object_id = ! $object_id && 'user-new.php' !== $pagenow && isset( $GLOBALS['user_ID'] ) ? $GLOBALS['user_ID'] : $object_id;
     1030                $object_id = isset($_REQUEST['user_id']) ? wp_unslash($_REQUEST['user_id']) : $object_id;
     1031                $object_id = ! $object_id && 'user-new.php' !== $pagenow && isset($GLOBALS['user_ID']) ? $GLOBALS['user_ID'] : $object_id;
    10131032                break;
    10141033
    10151034            case 'comment':
    1016                 $object_id = isset( $_REQUEST['c'] ) ? wp_unslash( $_REQUEST['c'] ) : $object_id;
    1017                 $object_id = ! $object_id && isset( $GLOBALS['comments']->comment_ID ) ? $GLOBALS['comments']->comment_ID : $object_id;
     1035                $object_id = isset($_REQUEST['c']) ? wp_unslash($_REQUEST['c']) : $object_id;
     1036                $object_id = ! $object_id && isset($GLOBALS['comments']->comment_ID) ? $GLOBALS['comments']->comment_ID : $object_id;
    10181037                break;
    10191038
    10201039            case 'term':
    1021                 $object_id = isset( $_REQUEST['tag_ID'] ) ? wp_unslash( $_REQUEST['tag_ID'] ) : $object_id;
     1040                $object_id = isset($_REQUEST['tag_ID']) ? wp_unslash($_REQUEST['tag_ID']) : $object_id;
    10221041                break;
    10231042
    10241043            case 'options-page':
    10251044                $key = $this->doing_options_page();
    1026                 if ( ! empty( $key ) ) {
     1045                if (! empty($key)) {
    10271046                    $object_id = $key;
    10281047                }
     
    10301049
    10311050            default:
    1032                 $object_id = isset( $GLOBALS['post']->ID ) ? $GLOBALS['post']->ID : $object_id;
    1033                 $object_id = isset( $_REQUEST['post'] ) ? wp_unslash( $_REQUEST['post'] ) : $object_id;
     1051                $object_id = isset($GLOBALS['post']->ID) ? $GLOBALS['post']->ID : $object_id;
     1052                $object_id = isset($_REQUEST['post']) ? wp_unslash($_REQUEST['post']) : $object_id;
    10341053                break;
    10351054        }
     
    10471066     * @return string Object type.
    10481067     */
    1049     public function mb_object_type() {
    1050         if ( null !== $this->mb_object_type ) {
     1068    public function mb_object_type()
     1069    {
     1070        if (null !== $this->mb_object_type) {
    10511071            return $this->mb_object_type;
    10521072        }
    10531073
    1054         if ( $this->is_options_page_mb() ) {
     1074        if ($this->is_options_page_mb()) {
    10551075            $this->mb_object_type = 'options-page';
    10561076            return $this->mb_object_type;
     
    10621082
    10631083        // if it's an array of one, extract it.
    1064         if ( 1 === count( $registered_types ) ) {
    1065             $last = end( $registered_types );
    1066             if ( is_string( $last ) ) {
     1084        if (1 === count($registered_types)) {
     1085            $last = end($registered_types);
     1086            if (is_string($last)) {
    10671087                $type = $last;
    10681088            }
    1069         } elseif ( ( $curr_type = $this->current_object_type() ) && in_array( $curr_type, $registered_types, true ) ) {
     1089        } elseif (($curr_type = $this->current_object_type()) && in_array($curr_type, $registered_types, true)) {
    10701090            $type = $curr_type;
    10711091        }
    10721092
    10731093        // Get our object type.
    1074         switch ( $type ) {
     1094        switch ($type) {
    10751095
    10761096            case 'user':
     
    10961116     * @return array Object types.
    10971117     */
    1098     public function box_types( $fallback = array() ) {
    1099         return CMB2_Utils::ensure_array( $this->prop( 'object_types' ), $fallback );
     1118    public function box_types($fallback = array())
     1119    {
     1120        return CMB2_Utils::ensure_array($this->prop('object_types'), $fallback);
    11001121    }
    11011122
     
    11071128     * @return void
    11081129     */
    1109     public function init_options_mb() {
     1130    public function init_options_mb()
     1131    {
    11101132        $keys  = $this->options_page_keys();
    11111133        $types = $this->box_types();
    11121134
    1113         if ( empty( $keys ) ) {
     1135        if (empty($keys)) {
    11141136            $keys = '';
    1115             $types = $this->deinit_options_mb( $types );
     1137            $types = $this->deinit_options_mb($types);
    11161138        } else {
    11171139
     
    11211143
    11221144        // Set/Reset the option_key property.
    1123         $this->set_prop( 'option_key', $keys );
     1145        $this->set_prop('option_key', $keys);
    11241146
    11251147        // Reset the object types.
    1126         $this->set_prop( 'object_types', array_unique( $types ) );
     1148        $this->set_prop('object_types', array_unique($types));
    11271149    }
    11281150
     
    11351157     * @return array
    11361158     */
    1137     protected function deinit_options_mb( $types ) {
    1138         if ( isset( $this->meta_box['show_on']['key'] ) && 'options-page' === $this->meta_box['show_on']['key'] ) {
    1139             unset( $this->meta_box['show_on']['key'] );
    1140         }
    1141 
    1142         if ( array_key_exists( 'options-page', $this->meta_box['show_on'] ) ) {
    1143             unset( $this->meta_box['show_on']['options-page'] );
    1144         }
    1145 
    1146         $index = array_search( 'options-page', $types );
    1147 
    1148         if ( false !== $index ) {
    1149             unset( $types[ $index ] );
     1159    protected function deinit_options_mb($types)
     1160    {
     1161        if (isset($this->meta_box['show_on']['key']) && 'options-page' === $this->meta_box['show_on']['key']) {
     1162            unset($this->meta_box['show_on']['key']);
     1163        }
     1164
     1165        if (array_key_exists('options-page', $this->meta_box['show_on'])) {
     1166            unset($this->meta_box['show_on']['options-page']);
     1167        }
     1168
     1169        $index = array_search('options-page', $types);
     1170
     1171        if (false !== $index) {
     1172            unset($types[$index]);
    11501173        }
    11511174
     
    11591182     * @return boolean True/False.
    11601183     */
    1161     public function is_options_page_mb() {
     1184    public function is_options_page_mb()
     1185    {
    11621186        return (
    11631187            // 'show_on' values checked for back-compatibility.
    11641188            $this->is_old_school_options_page_mb()
    1165             || in_array( 'options-page', $this->box_types() )
     1189            || in_array('options-page', $this->box_types())
    11661190        );
    11671191    }
     
    11731197     * @return boolean True/False.
    11741198     */
    1175     public function is_old_school_options_page_mb() {
     1199    public function is_old_school_options_page_mb()
     1200    {
    11761201        return (
    11771202            // 'show_on' values checked for back-compatibility.
    1178             isset( $this->meta_box['show_on']['key'] ) && 'options-page' === $this->meta_box['show_on']['key']
    1179             || array_key_exists( 'options-page', $this->meta_box['show_on'] )
     1203            isset($this->meta_box['show_on']['key']) && 'options-page' === $this->meta_box['show_on']['key']
     1204            || array_key_exists('options-page', $this->meta_box['show_on'])
    11801205        );
    11811206    }
     
    11881213     * @return bool
    11891214     */
    1190     public function doing_options_page() {
     1215    public function doing_options_page()
     1216    {
    11911217        $found_key = false;
    11921218        $keys = $this->options_page_keys();
    11931219
    1194         if ( empty( $keys ) ) {
     1220        if (empty($keys)) {
    11951221            return $found_key;
    11961222        }
    11971223
    1198         if ( ! empty( $_GET['page'] ) && in_array( $_GET['page'], $keys ) ) {
     1224        if (! empty($_GET['page']) && in_array($_GET['page'], $keys)) {
    11991225            $found_key = $_GET['page'];
    12001226        }
    12011227
    1202         if ( ! empty( $_POST['action'] ) && in_array( $_POST['action'], $keys ) ) {
     1228        if (! empty($_POST['action']) && in_array($_POST['action'], $keys)) {
    12031229            $found_key = $_POST['action'];
    12041230        }
     
    12131239     * @return string|array
    12141240     */
    1215     public function options_page_keys() {
     1241    public function options_page_keys()
     1242    {
    12161243        $key = '';
    1217         if ( ! $this->is_options_page_mb() ) {
     1244        if (! $this->is_options_page_mb()) {
    12181245            return $key;
    12191246        }
    12201247
    12211248        $values = null;
    1222         if ( ! empty( $this->meta_box['show_on']['value'] ) ) {
     1249        if (! empty($this->meta_box['show_on']['value'])) {
    12231250            $values = $this->meta_box['show_on']['value'];
    1224         } elseif ( ! empty( $this->meta_box['show_on']['options-page'] ) ) {
     1251        } elseif (! empty($this->meta_box['show_on']['options-page'])) {
    12251252            $values = $this->meta_box['show_on']['options-page'];
    1226         } elseif ( $this->prop( 'option_key' ) ) {
    1227             $values = $this->prop( 'option_key' );
    1228         }
    1229 
    1230         if ( $values ) {
     1253        } elseif ($this->prop('option_key')) {
     1254            $values = $this->prop('option_key');
     1255        }
     1256
     1257        if ($values) {
    12311258            $key = $values;
    12321259        }
    12331260
    1234         if ( ! is_array( $key ) ) {
    1235             $key = array( $key );
     1261        if (! is_array($key)) {
     1262            $key = array($key);
    12361263        }
    12371264
     
    12461273     * @return string Object type.
    12471274     */
    1248     public function object_type( $object_type = '' ) {
    1249         if ( $object_type ) {
     1275    public function object_type($object_type = '')
     1276    {
     1277        if ($object_type) {
    12501278            $this->object_type = $object_type;
    12511279            return $this->object_type;
    12521280        }
    12531281
    1254         if ( $this->object_type ) {
     1282        if ($this->object_type) {
    12551283            return $this->object_type;
    12561284        }
     
    12671295     * @return string  Page object type name.
    12681296     */
    1269     public function current_object_type() {
     1297    public function current_object_type()
     1298    {
    12701299        global $pagenow;
    12711300        $type = 'post';
    12721301
    1273         if ( in_array( $pagenow, array( 'user-edit.php', 'profile.php', 'user-new.php' ), true ) ) {
     1302        if (in_array($pagenow, array('user-edit.php', 'profile.php', 'user-new.php'), true)) {
    12741303            $type = 'user';
    12751304        }
    12761305
    1277         if ( in_array( $pagenow, array( 'edit-comments.php', 'comment.php' ), true ) ) {
     1306        if (in_array($pagenow, array('edit-comments.php', 'comment.php'), true)) {
    12781307            $type = 'comment';
    12791308        }
    12801309
    1281         if ( in_array( $pagenow, array( 'edit-tags.php', 'term.php' ), true ) ) {
     1310        if (in_array($pagenow, array('edit-tags.php', 'term.php'), true)) {
    12821311            $type = 'term';
    12831312        }
    12841313
    1285         if ( defined( 'DOING_AJAX' ) && isset( $_POST['action'] ) && 'add-tag' === $_POST['action'] ) {
     1314        if (defined('DOING_AJAX') && isset($_POST['action']) && 'add-tag' === $_POST['action']) {
    12861315            $type = 'term';
    12871316        }
    12881317
    12891318        if (
    1290             in_array( $pagenow, array( 'admin.php', 'admin-post.php' ), true )
     1319            in_array($pagenow, array('admin.php', 'admin-post.php'), true)
    12911320            && $this->doing_options_page()
    12921321        ) {
     
    13051334     * @return mixed            Metabox config property value or false.
    13061335     */
    1307     public function set_prop( $property, $value ) {
    1308         $this->meta_box[ $property ] = $value;
    1309 
    1310         return $this->prop( $property );
     1336    public function set_prop($property, $value)
     1337    {
     1338        $this->meta_box[$property] = $value;
     1339
     1340        return $this->prop($property);
    13111341    }
    13121342
     
    13191349     * @return mixed            Metabox config property value or false.
    13201350     */
    1321     public function prop( $property, $fallback = null ) {
    1322         if ( array_key_exists( $property, $this->meta_box ) ) {
    1323             return $this->meta_box[ $property ];
    1324         } elseif ( $fallback ) {
    1325             return $this->meta_box[ $property ] = $fallback;
     1351    public function prop($property, $fallback = null)
     1352    {
     1353        if (array_key_exists($property, $this->meta_box)) {
     1354            return $this->meta_box[$property];
     1355        } elseif ($fallback) {
     1356            return $this->meta_box[$property] = $fallback;
    13261357        }
    13271358    }
     
    13381369     * @return CMB2_Field|false                     CMB2_Field object (or false).
    13391370     */
    1340     public function get_field( $field, $field_group = null, $reset_cached = false ) {
    1341         if ( $field instanceof CMB2_Field ) {
     1371    public function get_field($field, $field_group = null, $reset_cached = false)
     1372    {
     1373        if ($field instanceof CMB2_Field) {
    13421374            return $field;
    13431375        }
    13441376
    1345         $field_id = is_string( $field ) ? $field : $field['id'];
    1346 
    1347         $parent_field_id = ! empty( $field_group ) ? $field_group->id() : '';
    1348         $ids = $this->get_field_ids( $field_id, $parent_field_id );
    1349 
    1350         if ( ! $ids ) {
     1377        $field_id = is_string($field) ? $field : $field['id'];
     1378
     1379        $parent_field_id = ! empty($field_group) ? $field_group->id() : '';
     1380        $ids = $this->get_field_ids($field_id, $parent_field_id);
     1381
     1382        if (! $ids) {
    13511383            return false;
    13521384        }
    13531385
    1354         list( $field_id, $sub_field_id ) = $ids;
    1355 
    1356         $index = implode( '', $ids ) . ( $field_group ? $field_group->index : '' );
    1357 
    1358         if ( array_key_exists( $index, $this->fields ) && ! $reset_cached ) {
    1359             return $this->fields[ $index ];
    1360         }
    1361 
    1362         $this->fields[ $index ] = new CMB2_Field( $this->get_field_args( $field_id, $field, $sub_field_id, $field_group ) );
    1363 
    1364         return $this->fields[ $index ];
     1386        list($field_id, $sub_field_id) = $ids;
     1387
     1388        $index = implode('', $ids) . ($field_group ? $field_group->index : '');
     1389
     1390        if (array_key_exists($index, $this->fields) && ! $reset_cached) {
     1391            return $this->fields[$index];
     1392        }
     1393
     1394        $this->fields[$index] = new CMB2_Field($this->get_field_args($field_id, $field, $sub_field_id, $field_group));
     1395
     1396        return $this->fields[$index];
    13651397    }
    13661398
     
    13751407     * @return array                         Array of CMB2_Field arguments.
    13761408     */
    1377     public function get_field_args( $field_id, $field_args, $sub_field_id, $field_group ) {
     1409    public function get_field_args($field_id, $field_args, $sub_field_id, $field_group)
     1410    {
    13781411
    13791412        // Check if group is passed and if fields were added in the old-school fields array.
    1380         if ( $field_group && ( $sub_field_id || 0 === $sub_field_id ) ) {
     1413        if ($field_group && ($sub_field_id || 0 === $sub_field_id)) {
    13811414
    13821415            // Update the fields array w/ any modified properties inherited from the group field.
    1383             $this->meta_box['fields'][ $field_id ]['fields'][ $sub_field_id ] = $field_args;
    1384 
    1385             return $this->get_default_args( $field_args, $field_group );
    1386         }
    1387 
    1388         if ( is_array( $field_args ) ) {
    1389             $this->meta_box['fields'][ $field_id ] = array_merge( $field_args, $this->meta_box['fields'][ $field_id ] );
    1390         }
    1391 
    1392         return $this->get_default_args( $this->meta_box['fields'][ $field_id ] );
     1416            $this->meta_box['fields'][$field_id]['fields'][$sub_field_id] = $field_args;
     1417
     1418            return $this->get_default_args($field_args, $field_group);
     1419        }
     1420
     1421        if (is_array($field_args)) {
     1422            $this->meta_box['fields'][$field_id] = array_merge($field_args, $this->meta_box['fields'][$field_id]);
     1423        }
     1424
     1425        return $this->get_default_args($this->meta_box['fields'][$field_id]);
    13931426    }
    13941427
     
    14011434     * @return array                   Array of field arguments.
    14021435     */
    1403     protected function get_default_args( $field_args, $field_group = null ) {
    1404         if ( $field_group ) {
     1436    protected function get_default_args($field_args, $field_group = null)
     1437    {
     1438        if ($field_group) {
    14051439            $args = array(
    14061440                'field_args'  => $field_args,
     
    14281462     * @return CMB2
    14291463     */
    1430     protected function add_fields( $fields, $parent_field_id = null ) {
    1431         foreach ( $fields as $field ) {
     1464    protected function add_fields($fields, $parent_field_id = null)
     1465    {
     1466        foreach ($fields as $field) {
    14321467
    14331468            $sub_fields = false;
    1434             if ( array_key_exists( 'fields', $field ) ) {
     1469            if (array_key_exists('fields', $field)) {
    14351470                $sub_fields = $field['fields'];
    1436                 unset( $field['fields'] );
     1471                unset($field['fields']);
    14371472            }
    14381473
    14391474            $field_id = $parent_field_id
    1440                 ? $this->add_group_field( $parent_field_id, $field )
    1441                 : $this->add_field( $field );
    1442 
    1443             if ( $sub_fields ) {
    1444                 $this->add_fields( $sub_fields, $field_id );
     1475                ? $this->add_group_field($parent_field_id, $field)
     1476                : $this->add_field($field);
     1477
     1478            if ($sub_fields) {
     1479                $this->add_fields($sub_fields, $field_id);
    14451480            }
    14461481        }
     
    14571492     * @return string|false    Field id or false.
    14581493     */
    1459     public function add_field( array $field, $position = 0 ) {
    1460         if ( ! array_key_exists( 'id', $field ) ) {
     1494    public function add_field(array $field, $position = 0)
     1495    {
     1496        if (! array_key_exists('id', $field)) {
    14611497            return false;
    14621498        }
    14631499
    14641500        // Perform some field-type-specific initiation actions.
    1465         switch ( $field['type'] ) {
     1501        switch ($field['type']) {
    14661502            case 'file':
    14671503            case 'file_list':
    14681504                // Initiate attachment JS hooks.
    1469                 add_filter( 'wp_prepare_attachment_for_js', array( 'CMB2_Type_File_Base', 'prepare_image_sizes_for_js' ), 10, 3 );
     1505                add_filter('wp_prepare_attachment_for_js', array('CMB2_Type_File_Base', 'prepare_image_sizes_for_js'), 10, 3);
    14701506                break;
    14711507
     
    14761512
    14771513            case 'group':
    1478                 if ( empty( $field['render_row_cb'] ) ) {
    1479                     $field['render_row_cb'] = array( $this, 'render_group_callback' );
     1514                if (empty($field['render_row_cb'])) {
     1515                    $field['render_row_cb'] = array($this, 'render_group_callback');
    14801516                }
    14811517                break;
     
    14841520                // Dequeue the rgba_colorpicker custom field script if it is used,
    14851521                // since we now enqueue our own more current version.
    1486                 add_action( 'admin_enqueue_scripts', array( 'CMB2_Type_Colorpicker', 'dequeue_rgba_colorpicker_script' ), 99 );
     1522                add_action('admin_enqueue_scripts', array('CMB2_Type_Colorpicker', 'dequeue_rgba_colorpicker_script'), 99);
    14871523                break;
    14881524        }
    14891525
    1490         if ( isset( $field['column'] ) && false !== $field['column'] ) {
    1491             $field = $this->define_field_column( $field );
    1492         }
    1493 
    1494         if ( isset( $field['taxonomy'] ) && ! empty( $field['remove_default'] ) ) {
    1495             $this->tax_metaboxes_to_remove[ $field['taxonomy'] ] = $field['taxonomy'];
     1526        if (isset($field['column']) && false !== $field['column']) {
     1527            $field = $this->define_field_column($field);
     1528        }
     1529
     1530        if (isset($field['taxonomy']) && ! empty($field['remove_default'])) {
     1531            $this->tax_metaboxes_to_remove[$field['taxonomy']] = $field['taxonomy'];
    14961532        }
    14971533
     
    15121548     * @return array         Modified metabox field config array.
    15131549     */
    1514     protected function define_field_column( array $field ) {
     1550    protected function define_field_column(array $field)
     1551    {
    15151552        $this->has_columns = true;
    15161553
    1517         $column = is_array( $field['column'] ) ? $field['column'] : array();
    1518 
    1519         $field['column'] = wp_parse_args( $column, array(
    1520             'name'     => isset( $field['name'] ) ? $field['name'] : '',
     1554        $column = is_array($field['column']) ? $field['column'] : array();
     1555
     1556        $field['column'] = wp_parse_args($column, array(
     1557            'name'     => isset($field['name']) ? $field['name'] : '',
    15211558            'position' => false,
    1522         ) );
     1559        ));
    15231560
    15241561        return $field;
     
    15341571     * @return mixed                   Array of parent/field ids or false.
    15351572     */
    1536     public function add_group_field( $parent_field_id, array $field, $position = 0 ) {
    1537         if ( ! array_key_exists( $parent_field_id, $this->meta_box['fields'] ) ) {
     1573    public function add_group_field($parent_field_id, array $field, $position = 0)
     1574    {
     1575        if (! array_key_exists($parent_field_id, $this->meta_box['fields'])) {
    15381576            return false;
    15391577        }
    15401578
    1541         $parent_field = $this->meta_box['fields'][ $parent_field_id ];
    1542 
    1543         if ( 'group' !== $parent_field['type'] ) {
     1579        $parent_field = $this->meta_box['fields'][$parent_field_id];
     1580
     1581        if ('group' !== $parent_field['type']) {
    15441582            return false;
    15451583        }
    15461584
    1547         if ( ! isset( $parent_field['fields'] ) ) {
    1548             $this->meta_box['fields'][ $parent_field_id ]['fields'] = array();
     1585        if (! isset($parent_field['fields'])) {
     1586            $this->meta_box['fields'][$parent_field_id]['fields'] = array();
    15491587        }
    15501588
    15511589        $this->_add_field_to_array(
    15521590            $field,
    1553             $this->meta_box['fields'][ $parent_field_id ]['fields'],
     1591            $this->meta_box['fields'][$parent_field_id]['fields'],
    15541592            $position
    15551593        );
    15561594
    1557         return array( $parent_field_id, $field['id'] );
     1595        return array($parent_field_id, $field['id']);
    15581596    }
    15591597
     
    15661604     * @param integer $position Optionally specify a position in the array to be inserted.
    15671605     */
    1568     protected function _add_field_to_array( $field, &$fields, $position = 0 ) {
    1569         if ( $position ) {
    1570             CMB2_Utils::array_insert( $fields, array( $field['id'] => $field ), $position );
     1606    protected function _add_field_to_array($field, &$fields, $position = 0)
     1607    {
     1608        if ($position) {
     1609            CMB2_Utils::array_insert($fields, array($field['id'] => $field), $position);
    15711610        } else {
    1572             $fields[ $field['id'] ] = $field;
     1611            $fields[$field['id']] = $field;
    15731612        }
    15741613    }
     
    15821621     * @return bool                    True if field was removed.
    15831622     */
    1584     public function remove_field( $field_id, $parent_field_id = '' ) {
    1585         $ids = $this->get_field_ids( $field_id, $parent_field_id );
    1586 
    1587         if ( ! $ids ) {
     1623    public function remove_field($field_id, $parent_field_id = '')
     1624    {
     1625        $ids = $this->get_field_ids($field_id, $parent_field_id);
     1626
     1627        if (! $ids) {
    15881628            return false;
    15891629        }
    15901630
    1591         list( $field_id, $sub_field_id ) = $ids;
    1592 
    1593         unset( $this->fields[ implode( '', $ids ) ] );
    1594 
    1595         if ( ! $sub_field_id ) {
    1596             unset( $this->meta_box['fields'][ $field_id ] );
     1631        list($field_id, $sub_field_id) = $ids;
     1632
     1633        unset($this->fields[implode('', $ids)]);
     1634
     1635        if (! $sub_field_id) {
     1636            unset($this->meta_box['fields'][$field_id]);
    15971637            return true;
    15981638        }
    15991639
    1600         if ( isset( $this->fields[ $field_id ]->args['fields'][ $sub_field_id ] ) ) {
    1601             unset( $this->fields[ $field_id ]->args['fields'][ $sub_field_id ] );
    1602         }
    1603         if ( isset( $this->meta_box['fields'][ $field_id ]['fields'][ $sub_field_id ] ) ) {
    1604             unset( $this->meta_box['fields'][ $field_id ]['fields'][ $sub_field_id ] );
     1640        if (isset($this->fields[$field_id]->args['fields'][$sub_field_id])) {
     1641            unset($this->fields[$field_id]->args['fields'][$sub_field_id]);
     1642        }
     1643        if (isset($this->meta_box['fields'][$field_id]['fields'][$sub_field_id])) {
     1644            unset($this->meta_box['fields'][$field_id]['fields'][$sub_field_id]);
    16051645        }
    16061646
     
    16181658     * @return mixed                   Field id. Strict compare to false, as success can return a falsey value (like 0).
    16191659     */
    1620     public function update_field_property( $field_id, $property, $value, $parent_field_id = '' ) {
    1621         $ids = $this->get_field_ids( $field_id, $parent_field_id );
    1622 
    1623         if ( ! $ids ) {
     1660    public function update_field_property($field_id, $property, $value, $parent_field_id = '')
     1661    {
     1662        $ids = $this->get_field_ids($field_id, $parent_field_id);
     1663
     1664        if (! $ids) {
    16241665            return false;
    16251666        }
    16261667
    1627         list( $field_id, $sub_field_id ) = $ids;
    1628 
    1629         if ( ! $sub_field_id ) {
    1630             $this->meta_box['fields'][ $field_id ][ $property ] = $value;
     1668        list($field_id, $sub_field_id) = $ids;
     1669
     1670        if (! $sub_field_id) {
     1671            $this->meta_box['fields'][$field_id][$property] = $value;
    16311672            return $field_id;
    16321673        }
    16331674
    1634         $this->meta_box['fields'][ $field_id ]['fields'][ $sub_field_id ][ $property ] = $value;
     1675        $this->meta_box['fields'][$field_id]['fields'][$sub_field_id][$property] = $value;
    16351676        return $field_id;
    16361677    }
     
    16441685     * @return mixed                    Array of field/parent ids, or false.
    16451686     */
    1646     public function get_field_ids( $field_id, $parent_field_id = '' ) {
     1687    public function get_field_ids($field_id, $parent_field_id = '')
     1688    {
    16471689        $sub_field_id = $parent_field_id ? $field_id : '';
    16481690        $field_id     = $parent_field_id ? $parent_field_id : $field_id;
    1649         $fields       =& $this->meta_box['fields'];
    1650 
    1651         if ( ! array_key_exists( $field_id, $fields ) ) {
    1652             $field_id = $this->search_old_school_array( $field_id, $fields );
    1653         }
    1654 
    1655         if ( false === $field_id ) {
     1691        $fields       = &$this->meta_box['fields'];
     1692
     1693        if (! array_key_exists($field_id, $fields)) {
     1694            $field_id = $this->search_old_school_array($field_id, $fields);
     1695        }
     1696
     1697        if (false === $field_id) {
    16561698            return false;
    16571699        }
    16581700
    1659         if ( ! $sub_field_id ) {
    1660             return array( $field_id, $sub_field_id );
    1661         }
    1662 
    1663         if ( 'group' !== $fields[ $field_id ]['type'] ) {
     1701        if (! $sub_field_id) {
     1702            return array($field_id, $sub_field_id);
     1703        }
     1704
     1705        if ('group' !== $fields[$field_id]['type']) {
    16641706            return false;
    16651707        }
    16661708
    1667         if ( ! array_key_exists( $sub_field_id, $fields[ $field_id ]['fields'] ) ) {
    1668             $sub_field_id = $this->search_old_school_array( $sub_field_id, $fields[ $field_id ]['fields'] );
    1669         }
    1670 
    1671         return false === $sub_field_id ? false : array( $field_id, $sub_field_id );
     1709        if (! array_key_exists($sub_field_id, $fields[$field_id]['fields'])) {
     1710            $sub_field_id = $this->search_old_school_array($sub_field_id, $fields[$field_id]['fields']);
     1711        }
     1712
     1713        return false === $sub_field_id ? false : array($field_id, $sub_field_id);
    16721714    }
    16731715
     
    16801722     * @return mixed            Field index or false.
    16811723     */
    1682     public function search_old_school_array( $field_id, $fields ) {
    1683         $ids = wp_list_pluck( $fields, 'id' );
    1684         $index = array_search( $field_id, $ids );
     1724    public function search_old_school_array($field_id, $fields)
     1725    {
     1726        $ids = wp_list_pluck($fields, 'id');
     1727        $index = array_search($field_id, $ids);
    16851728        return false !== $index ? $index : false;
    16861729    }
     
    16941737     * @return mixed                       Return of the callback function.
    16951738     */
    1696     public function do_callback( $cb, $additional_params = null ) {
    1697         return call_user_func( $cb, $this, $additional_params );
     1739    public function do_callback($cb, $additional_params = null)
     1740    {
     1741        return call_user_func($cb, $this, $additional_params);
    16981742    }
    16991743
     
    17041748     * @return void
    17051749     */
    1706     public function nonce_field() {
    1707         wp_nonce_field( $this->nonce(), $this->nonce(), false, true );
     1750    public function nonce_field()
     1751    {
     1752        wp_nonce_field($this->nonce(), $this->nonce(), false, true);
    17081753    }
    17091754
     
    17141759     * @return string unique nonce string.
    17151760     */
    1716     public function nonce() {
    1717         if ( ! $this->generated_nonce ) {
    1718             $this->generated_nonce = sanitize_html_class( 'nonce_' . basename( __FILE__ ) . $this->cmb_id );
     1761    public function nonce()
     1762    {
     1763        if (! $this->generated_nonce) {
     1764            $this->generated_nonce = sanitize_html_class('nonce_' . basename(__FILE__) . $this->cmb_id);
    17191765        }
    17201766
     
    17291775     * @return bool
    17301776     */
    1731     public function was_updated() {
    1732         return ! empty( $this->updated );
     1777    public function was_updated()
     1778    {
     1779        return ! empty($this->updated);
    17331780    }
    17341781
     
    17401787     * @return bool
    17411788     */
    1742     public function is_alternate_context_box() {
    1743         return $this->prop( 'context' ) && in_array( $this->prop( 'context' ), array( 'form_top', 'before_permalink', 'after_title', 'after_editor' ), true );
     1789    public function is_alternate_context_box()
     1790    {
     1791        return $this->prop('context') && in_array($this->prop('context'), array('form_top', 'before_permalink', 'after_title', 'after_editor'), true);
    17441792    }
    17451793
     
    17511799     * @return mixed
    17521800     */
    1753     public function __get( $property ) {
    1754         switch ( $property ) {
     1801    public function __get($property)
     1802    {
     1803        switch ($property) {
    17551804            case 'updated':
    17561805            case 'has_columns':
     
    17581807                return $this->{$property};
    17591808            default:
    1760                 return parent::__get( $property );
    1761         }
    1762     }
    1763 
     1809                return parent::__get($property);
     1810        }
     1811    }
    17641812}
  • magical-posts-display/trunk/assets/css/admin-style.css

    r3235168 r3380394  
    5353}
    5454
    55 
     55/* Enhanced Admin Notice Styles with Animation */
    5656.mgadin-hero {
    57     padding: 20px 10px;
     57    background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
     58    border: 2px solid #e3f2fd;
     59    border-radius: 12px;
     60    padding: 25px;
     61    margin: 20px 0;
    5862    display: flex;
    5963    align-items: center;
     64    box-shadow: 0 8px 25px rgba(0, 123, 255, 0.1);
     65    position: relative;
     66    overflow: hidden;
     67    animation: slideInFromTop 0.6s ease-out;
     68    transition: all 0.3s ease;
     69}
     70
     71.mgadin-hero:hover {
     72    box-shadow: 0 12px 35px rgba(0, 123, 255, 0.15);
     73    transform: translateY(-2px);
     74}
     75
     76/* Animated Background Gradient */
     77.mgadin-hero::before {
     78    content: '';
     79    position: absolute;
     80    top: 0;
     81    left: -100%;
     82    width: 100%;
     83    height: 100%;
     84    background: linear-gradient(90deg, transparent, rgba(0, 123, 255, 0.05), transparent);
     85    animation: shimmer 3s infinite;
     86}
     87
     88/* Content Container */
     89.mge-info-content {
     90    flex: 1;
     91    z-index: 2;
     92    position: relative;
    6093}
    6194
    6295.mge-info-hello {
    6396    font-weight: 700;
    64     font-size: 16px;
     97    font-size: 18px;
     98    color: #2c3e50;
     99    margin-bottom: 8px;
     100    animation: fadeInUp 0.8s ease-out 0.2s both;
    65101}
    66102
    67103.mge-info-title {
    68     font-size: 22px;
     104    font-size: 24px;
    69105    display: block;
    70     line-height: 1.5;
    71     font-weight: 500;
    72 }
    73 
    74 .mge-info-desc div {
    75     margin-bottom: 10px;
     106    line-height: 1.4;
     107    font-weight: 600;
     108    color: #1a202c;
     109    animation: fadeInUp 0.8s ease-out 0.3s both;
    76110}
    77111
    78112.mge-info-desc {
    79113    font-size: 16px;
    80     line-height: 1.3;
    81     margin: 10px 0 20px;
     114    line-height: 1.5;
     115    margin: 15px 0 25px;
     116    color: #4a5568;
     117}
     118
     119.mge-info-desc div {
     120    margin-bottom: 12px;
     121    animation: fadeInUp 0.8s ease-out 0.4s both;
     122}
     123
     124.mge-info-desc div.mge-offer {
     125    background: linear-gradient(45deg, #ff6b6b, #ff8e53);
     126    background-clip: text;
     127    -webkit-background-clip: text;
     128    -webkit-text-fill-color: transparent;
     129    font-weight: 700;
     130    font-size: 17px;
     131    padding: 10px 15px;
     132    border-left: 4px solid #ff6b6b;
     133    background-color: rgba(255, 107, 107, 0.1);
     134    border-radius: 6px;
     135    animation: pulse 2s infinite, fadeInUp 0.8s ease-out 0.5s both;
    82136}
    83137
     
    85139    display: flex;
    86140    align-items: center;
     141    gap: 15px;
     142    animation: fadeInUp 0.8s ease-out 0.6s both;
    87143}
    88144
     
    90146    display: inline-flex;
    91147    align-items: center;
    92     padding: 5px 20px;
     148    padding: 12px 24px;
    93149    font-size: 16px;
    94     margin-right: 15px;
     150    font-weight: 600;
     151    border-radius: 8px;
     152    text-decoration: none;
     153    transition: all 0.3s ease;
     154    position: relative;
     155    overflow: hidden;
     156}
     157
     158.mge-info-actions a.button::before {
     159    content: '';
     160    position: absolute;
     161    top: 50%;
     162    left: 50%;
     163    width: 0;
     164    height: 0;
     165    background: rgba(255, 255, 255, 0.2);
     166    border-radius: 50%;
     167    transform: translate(-50%, -50%);
     168    transition: width 0.3s ease, height 0.3s ease;
     169}
     170
     171.mge-info-actions a.button:hover::before {
     172    width: 300px;
     173    height: 300px;
     174}
     175
     176.mge-info-actions .upgrade-btn {
     177    background: linear-gradient(45deg, #007cba, #0096dc);
     178    color: white;
     179    border: none;
     180    box-shadow: 0 4px 15px rgba(0, 124, 186, 0.3);
     181    animation: buttonBounce 2s infinite;
     182}
     183
     184.mge-info-actions .upgrade-btn:hover {
     185    background: linear-gradient(45deg, #005a87, #007bb5);
     186    box-shadow: 0 6px 20px rgba(0, 124, 186, 0.4);
     187    transform: translateY(-2px);
     188}
     189
     190.mge-info-actions .demo-btn {
     191    background: linear-gradient(45deg, #28a745, #20c997);
     192    color: white;
     193    border: none;
     194    box-shadow: 0 4px 15px rgba(40, 167, 69, 0.3);
     195}
     196
     197.mge-info-actions .demo-btn:hover {
     198    background: linear-gradient(45deg, #218838, #1ea379);
     199    box-shadow: 0 6px 20px rgba(40, 167, 69, 0.4);
     200    transform: translateY(-2px);
     201}
     202
     203.mge-info-actions .mgad-dismiss {
     204    background: transparent;
     205    border: 2px solid #6c757d;
     206    color: #6c757d;
     207    padding: 10px 20px;
     208    border-radius: 6px;
     209    font-size: 14px;
     210    transition: all 0.3s ease;
     211}
     212
     213.mge-info-actions .mgad-dismiss:hover {
     214    background: #6c757d;
     215    color: white;
     216    transform: translateY(-1px);
    95217}
    96218
     
    99221}
    100222
     223/* Keyframe Animations */
     224@keyframes slideInFromTop {
     225    0% {
     226        opacity: 0;
     227        transform: translateY(-30px);
     228    }
     229    100% {
     230        opacity: 1;
     231        transform: translateY(0);
     232    }
     233}
     234
     235@keyframes fadeInUp {
     236    0% {
     237        opacity: 0;
     238        transform: translateY(20px);
     239    }
     240    100% {
     241        opacity: 1;
     242        transform: translateY(0);
     243    }
     244}
     245
     246@keyframes shimmer {
     247    0% {
     248        left: -100%;
     249    }
     250    100% {
     251        left: 100%;
     252    }
     253}
     254
     255@keyframes pulse {
     256    0%, 100% {
     257        transform: scale(1);
     258    }
     259    50% {
     260        transform: scale(1.02);
     261    }
     262}
     263
     264@keyframes buttonBounce {
     265    0%, 20%, 50%, 80%, 100% {
     266        transform: translateY(0);
     267    }
     268    40% {
     269        transform: translateY(-3px);
     270    }
     271    60% {
     272        transform: translateY(-2px);
     273    }
     274}
     275
     276/* Responsive Design */
     277@media (max-width: 768px) {
     278    .mgadin-hero {
     279        flex-direction: column;
     280        text-align: center;
     281        padding: 20px;
     282    }
     283   
     284    .mge-info-actions {
     285        flex-direction: column;
     286        width: 100%;
     287        gap: 10px;
     288    }
     289   
     290    .mge-info-actions a.button {
     291        width: 100%;
     292        justify-content: center;
     293    }
     294}
     295
     296/* Additional Enhancement Elements */
     297.mgadin-hero::after {
     298    content: '🚀';
     299    position: absolute;
     300    top: 20px;
     301    right: 20px;
     302    font-size: 24px;
     303    animation: float 3s ease-in-out infinite;
     304}
     305
     306@keyframes float {
     307    0%, 100% {
     308        transform: translateY(0);
     309    }
     310    50% {
     311        transform: translateY(-10px);
     312    }
     313}
     314
     315/* Enhanced Image and Review Styles */
    101316.mge-info-image {
    102317    flex: 0 0 400px;
    103318    overflow: hidden;
     319    border-radius: 8px;
     320    animation: fadeInUp 0.8s ease-out 0.7s both;
    104321}
    105322
     
    107324    max-width: 100%;
    108325    min-width: 200px;
     326    border-radius: 8px;
     327    transition: transform 0.3s ease;
     328}
     329
     330.mge-info-image img:hover {
     331    transform: scale(1.05);
    109332}
    110333
     
    113336    display: block;
    114337    font-size: 15px;
     338    color: #2c3e50;
     339    font-weight: 600;
    115340}
    116341
     
    118343    display: flex;
    119344    align-items: center;
    120 }
    121 
    122 .mge-info-desc div.mge-offer {
    123     color: #a30000;
    124     font-weight: 700;
     345    gap: 15px;
    125346}
    126347
    127348.mge-info-rev .button {
    128     padding: 5px 20px !important;
     349    padding: 8px 20px !important;
    129350    display: inline-flex;
    130351    justify-content: center;
    131352    align-items: center;
    132353    height: 100%;
    133     margin-right: 10px;
    134354    font-size: 15px !important;
    135 }
     355    border-radius: 6px;
     356    transition: all 0.3s ease;
     357}
  • magical-posts-display/trunk/assets/css/mgadmin-page.css

    r2608250 r3380394  
    8484}
    8585a.button.button-mgp1 {
    86     background: #000;
    87     color: #fff;
    88     padding: 5px 25px;
    89     margin-top: 10px;
     86    background: #000000;
     87    color: #fff;
     88    padding: 12px 45px;
     89    margin: 10px;
    9090    font-size: 1rem;
    9191    min-height: 38px;
    9292    display: inline-block;
     93    border-radius: 5px;
     94    transition: 0.5s;
     95    border: none;
     96    font-weight: 600;
     97}
     98a.button.button-mgp1.btnprohas {
     99    background: #700000;
     100    color: #fff;
     101}
     102a.button.button-mgp1.btnprohas:hover {
     103    background: #460000;
     104    color: #fff;
    93105}
    94106.mgftext {
  • magical-posts-display/trunk/assets/css/mp-style.css

    r3324281 r3380394  
    884884  font-size: 18px;
    885885  color: #fff;
    886   line-height: 20px;
     886  line-height: 1.5;
    887887}
    888888.mgs-btn {
     
    920920  padding: 3px 0px 4px;
    921921  font-size: 14px;
    922   margin-bottom: 10px;
     922  margin-bottom: 20px;
     923  display: inline-block;
    923924}
    924925.mgs-content a.mp-post-btn.link1 {
     
    16571658  }
    16581659}
     1660
     1661/* Enhanced Masonry Layout Styles */
     1662.mgpd-masonry-container {
     1663  position: relative;
     1664  margin-bottom: 30px;
     1665  overflow: hidden;
     1666}
     1667
     1668.mgpd-masonry {
     1669  align-items: flex-start;
     1670  position: relative !important;
     1671  height: auto !important;
     1672  min-height: 400px;
     1673}
     1674
     1675.mgpd-masonry-item {
     1676  margin-bottom: 1.5rem;
     1677  width: 100%;
     1678  position: relative;
     1679}
     1680
     1681/* Prevent layout jumping during load */
     1682.mgpd-masonry-container:not(.masonry-loaded) .mgpd-masonry {
     1683  opacity: 0;
     1684  transition: opacity 0.3s ease;
     1685}
     1686
     1687.mgpd-masonry-container.masonry-loaded .mgpd-masonry {
     1688  opacity: 1;
     1689}
     1690
     1691/* Fix for items overlapping footer */
     1692.mgpd-masonry::after {
     1693  content: '';
     1694  display: block;
     1695  clear: both;
     1696  height: 0;
     1697}
     1698
     1699/* Ensure proper container bounds */
     1700.mgpd {
     1701  position: relative;
     1702  z-index: 1;
     1703  margin-bottom: 40px;
     1704}
     1705
     1706/* Specific column widths for masonry */
     1707.mgpd-masonry .mgpd-masonry-item.col-lg-4 {
     1708  width: 33.333333%;
     1709}
     1710
     1711.mgpd-masonry .mgpd-masonry-item.col-lg-3 {
     1712  width: 25%;
     1713}
     1714
     1715.mgpd-masonry .mgpd-masonry-item.col-lg-6 {
     1716  width: 50%;
     1717}
     1718
     1719.mgpd-masonry .mgpd-masonry-item.col-lg-12 {
     1720  width: 100%;
     1721}
     1722
     1723.mgpd-masonry .mgpd-masonry-item.col-lg-2 {
     1724  width: 16.666667%;
     1725}
     1726
     1727/* Ensure images are responsive in masonry layout */
     1728.mgpd-masonry .mg-card img {
     1729  width: 100%;
     1730  height: auto;
     1731  display: block;
     1732}
     1733
     1734/* Masonry item transition effects */
     1735.mgpd-masonry-item {
     1736  transition: transform 0.3s ease;
     1737}
     1738
     1739.mgpd-masonry-item:hover {
     1740  transform: translateY(-2px);
     1741}
     1742
     1743/* Responsive masonry adjustments */
     1744@media (max-width: 991.98px) {
     1745  .mgpd-masonry .mgpd-masonry-item.col-lg-4,
     1746  .mgpd-masonry .mgpd-masonry-item.col-lg-3,
     1747  .mgpd-masonry .mgpd-masonry-item.col-lg-2 {
     1748    width: 50%;
     1749  }
     1750 
     1751  .mgpd-masonry-item {
     1752    margin-bottom: 1rem;
     1753  }
     1754}
     1755
     1756@media (max-width: 767.98px) {
     1757  .mgpd-masonry .mgpd-masonry-item {
     1758    width: 100% !important;
     1759    margin-bottom: 1rem;
     1760  }
     1761}
     1762
     1763/* Loading state for masonry */
     1764.mgpd-masonry-container:not(.masonry-loaded) .mgpd-masonry-item {
     1765  opacity: 0;
     1766  transform: translateY(20px);
     1767}
     1768
     1769.mgpd-masonry-container.masonry-loaded .mgpd-masonry-item {
     1770  opacity: 1;
     1771  transform: translateY(0);
     1772  transition: opacity 0.3s ease, transform 0.3s ease;
     1773}
     1774
     1775/* Elementor Editor Mode Fix - Ensure items always visible in editor */
     1776.elementor-editor-active .mgpd-masonry-container .mgpd-masonry-item {
     1777  opacity: 1 !important;
     1778  transform: none !important;
     1779  visibility: visible !important;
     1780  position: relative !important;
     1781}
     1782
     1783/* Force masonry container to show properly in editor */
     1784.elementor-editor-active .mgpd-masonry {
     1785  display: flex !important;
     1786  flex-wrap: wrap !important;
     1787  height: auto !important;
     1788}
     1789
     1790/* Masonry Style Variations */
     1791
     1792/* Style 1 - Default Heights (all images same height) */
     1793.mgpd-masonry-style1 .mgpd-masonry-item .mg-card .mp-post-img figure {
     1794  height: 200px;
     1795}
     1796
     1797/* Style 2 - Alternating Heights (big then small pattern) */
     1798.mgpd-masonry-style2 .mgpd-masonry-item:nth-child(odd) .mg-card .mp-post-img figure {
     1799  height: 300px;
     1800}
     1801
     1802.mgpd-masonry-style2 .mgpd-masonry-item:nth-child(even) .mg-card .mp-post-img figure {
     1803  height: 180px;
     1804}
     1805
     1806/* Style 3 - Pattern Heights (two big, one small repeating pattern) */
     1807.mgpd-masonry-style3 .mgpd-masonry-item:nth-child(3n+1) .mg-card .mp-post-img figure,
     1808.mgpd-masonry-style3 .mgpd-masonry-item:nth-child(3n+2) .mg-card .mp-post-img figure {
     1809  height: 280px;
     1810}
     1811
     1812.mgpd-masonry-style3 .mgpd-masonry-item:nth-child(3n) .mg-card .mp-post-img figure {
     1813  height: 160px;
     1814}
     1815
     1816/* Ensure images cover the full height */
     1817.mgpd-masonry-container .mg-card .mp-post-img figure img {
     1818  width: 100%;
     1819  height: 100%;
     1820  object-fit: cover;
     1821  object-position: center;
     1822}
     1823
     1824/* Responsive adjustments for masonry styles */
     1825@media (max-width: 991.98px) {
     1826  .mgpd-masonry-style1 .mgpd-masonry-item .mg-card .mp-post-img figure,
     1827  .mgpd-masonry-style2 .mgpd-masonry-item .mg-card .mp-post-img figure,
     1828  .mgpd-masonry-style3 .mgpd-masonry-item .mg-card .mp-post-img figure {
     1829    height: 200px;
     1830  }
     1831}
     1832
     1833@media (max-width: 767.98px) {
     1834  .mgpd-masonry-style1 .mgpd-masonry-item .mg-card .mp-post-img figure,
     1835  .mgpd-masonry-style2 .mgpd-masonry-item .mg-card .mp-post-img figure,
     1836  .mgpd-masonry-style3 .mgpd-masonry-item .mg-card .mp-post-img figure {
     1837    height: 180px;
     1838  }
     1839}
     1840
     1841/* Premium Features Styles (Pro Only) */
     1842
     1843/* AJAX Filter Buttons */
     1844.mgpd-ajax-filter-container {
     1845  margin-bottom: 30px;
     1846  text-align: center;
     1847}
     1848
     1849.mgpd-filter-buttons {
     1850  display: flex;
     1851  flex-wrap: wrap;
     1852  justify-content: center;
     1853  gap: 10px;
     1854}
     1855
     1856.mgpd-filter-btn {
     1857  background: #f8f9fa;
     1858  border: 2px solid #dee2e6;
     1859  color: #495057;
     1860  padding: 8px 16px;
     1861  border-radius: 25px;
     1862  cursor: pointer;
     1863  transition: all 0.3s ease;
     1864  font-weight: 500;
     1865  text-transform: capitalize;
     1866}
     1867
     1868.mgpd-filter-btn:hover,
     1869.mgpd-filter-btn.active {
     1870  background: #007cba;
     1871  border-color: #007cba;
     1872  color: #ffffff;
     1873  transform: translateY(-2px);
     1874  box-shadow: 0 4px 12px rgba(0, 124, 186, 0.3);
     1875}
     1876
     1877/* Loading State */
     1878.mgpd-loading .mg-card {
     1879  opacity: 0.5;
     1880  transition: opacity 0.3s ease;
     1881}
     1882
     1883.mgpd-loading-spinner {
     1884  color: #007cba;
     1885  font-size: 16px;
     1886  display: flex;
     1887  align-items: center;
     1888  justify-content: center;
     1889  gap: 10px;
     1890}
     1891
     1892.mgpd-loading-spinner .mgpd-spinner {
     1893  animation: mgpd-spin 1s linear infinite;
     1894}
     1895
     1896@keyframes mgpd-spin {
     1897  0% { transform: rotate(0deg); }
     1898  100% { transform: rotate(360deg); }
     1899}
     1900
     1901/* Reading Time */
     1902.mgpd-reading-time {
     1903  display: inline-flex;
     1904  align-items: center;
     1905  gap: 5px;
     1906  background: #e7f3ff;
     1907  color: #0066cc;
     1908  padding: 4px 10px;
     1909  border-radius: 15px;
     1910  font-size: 12px;
     1911  margin: 8px 8px 8px 0;
     1912  font-weight: 500;
     1913}
     1914
     1915.mgpd-reading-time svg {
     1916  width: 14px;
     1917  height: 14px;
     1918  flex-shrink: 0;
     1919}
     1920
     1921/* View Count */
     1922.mgpd-view-count {
     1923  display: inline-flex;
     1924  align-items: center;
     1925  gap: 5px;
     1926  background: #f0f8f0;
     1927  color: #28a745;
     1928  padding: 4px 10px;
     1929  border-radius: 15px;
     1930  font-size: 12px;
     1931  margin: 8px 8px 8px 0;
     1932  font-weight: 500;
     1933}
     1934
     1935.mgpd-view-count svg {
     1936  width: 14px;
     1937  height: 14px;
     1938  flex-shrink: 0;
     1939}
     1940
     1941/* Social Share Buttons */
     1942.mgpd-social-share {
     1943  display: flex;
     1944  gap: 8px;
     1945  margin: 12px 0;
     1946}
     1947
     1948.mgpd-social-share a {
     1949  display: flex;
     1950  align-items: center;
     1951  justify-content: center;
     1952  width: 32px;
     1953  height: 32px;
     1954  border-radius: 50%;
     1955  text-decoration: none;
     1956  transition: all 0.3s ease;
     1957  font-size: 14px;
     1958}
     1959
     1960.mgpd-share-facebook {
     1961  background: #3b5998;
     1962  color: #ffffff;
     1963}
     1964
     1965.mgpd-share-facebook:hover {
     1966  background: #2d4373;
     1967  transform: translateY(-2px);
     1968  box-shadow: 0 4px 12px rgba(59, 89, 152, 0.4);
     1969}
     1970
     1971.mgpd-share-twitter {
     1972  background: #000000;
     1973  color: #ffffff;
     1974}
     1975
     1976.mgpd-share-twitter:hover {
     1977  background: #333333;
     1978  transform: translateY(-2px);
     1979  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
     1980}
     1981
     1982.mgpd-share-linkedin {
     1983  background: #0077b5;
     1984  color: #ffffff;
     1985}
     1986
     1987.mgpd-share-linkedin:hover {
     1988  background: #005885;
     1989  transform: translateY(-2px);
     1990  box-shadow: 0 4px 12px rgba(0, 119, 181, 0.4);
     1991}
     1992
     1993.mgpd-share-pinterest {
     1994  background: #bd081c;
     1995  color: #ffffff;
     1996}
     1997
     1998.mgpd-share-pinterest:hover {
     1999  background: #8c0613;
     2000  transform: translateY(-2px);
     2001  box-shadow: 0 4px 12px rgba(189, 8, 28, 0.4);
     2002}
     2003
     2004.mgpd-share-instagram {
     2005  background: linear-gradient(45deg, #f09433 0%, #e6683c 25%, #dc2743 50%, #cc2366 75%, #bc1888 100%);
     2006  color: #ffffff;
     2007}
     2008
     2009.mgpd-share-instagram:hover {
     2010  opacity: 0.8;
     2011  transform: translateY(-2px);
     2012  box-shadow: 0 4px 12px rgba(188, 24, 136, 0.4);
     2013}
     2014
     2015/* Premium Features Display Styles */
     2016/* Image Top Style */
     2017.mgpd-premium-image-top .mp-post-img {
     2018  position: relative;
     2019}
     2020
     2021.mgpd-premium-image-top .mgpd-premium-features {
     2022    position: absolute;
     2023    bottom: 10px;
     2024    left: 0;
     2025    right: 10px;
     2026    z-index: 2;
     2027    display: flex;
     2028    flex-wrap: wrap;
     2029    gap: 8px;
     2030    align-items: center;
     2031    width: 100%;
     2032    justify-content: center;
     2033}
     2034
     2035.mgpd-premium-image-top .mgpd-reading-time,
     2036.mgpd-premium-image-top .mgpd-view-count {
     2037  background: rgba(255, 255, 255, 0.95);
     2038  backdrop-filter: blur(10px);
     2039  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
     2040}
     2041
     2042.mgpd-premium-image-top .mgpd-social-share {
     2043  margin: 0;
     2044  background: rgba(255, 255, 255, 0.95);
     2045  backdrop-filter: blur(10px);
     2046  padding: 6px;
     2047  border-radius: 20px;
     2048  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
     2049}
     2050
     2051/* Image Overlay Style */
     2052.mgpd-premium-image-overlay .mp-post-img {
     2053  position: relative;
     2054}
     2055.mp-post-img .mgpd-time-count-wrap {
     2056    display: flex;
     2057    justify-content: space-between;
     2058    align-items: center;
     2059    width: 100%;
     2060    padding: 0 20px;
     2061}
     2062.mgpd-premium-image-overlay .mgpd-premium-features {
     2063  position: absolute;
     2064  bottom: 0;
     2065  left: 0;
     2066  right: 0;
     2067  background: linear-gradient(to top, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.6) 60%, transparent 100%);
     2068  padding: 15px;
     2069  opacity: 0;
     2070  transform: translateY(10px);
     2071  transition: all 0.3s ease;
     2072  z-index: 2;
     2073}
     2074
     2075.mgpd-premium-image-overlay .mg-card:hover .mgpd-premium-features {
     2076  opacity: 1;
     2077  transform: translateY(0);
     2078}
     2079
     2080.mgpd-premium-image-overlay .mgpd-reading-time,
     2081.mgpd-premium-image-overlay .mgpd-view-count {
     2082  background: rgba(255, 255, 255, 0.2);
     2083  backdrop-filter: blur(10px);
     2084  color: #ffffff;
     2085  border: 1px solid rgba(255, 255, 255, 0.3);
     2086}
     2087
     2088.mgpd-premium-image-overlay .mgpd-reading-time svg,
     2089.mgpd-premium-image-overlay .mgpd-view-count svg {
     2090  fill: #ffffff;
     2091}
     2092
     2093.mgpd-premium-image-overlay .mgpd-social-share {
     2094  margin: 10px 0 0 0;
     2095  justify-content: center;
     2096}
     2097
     2098.mgpd-premium-image-overlay .mgpd-social-share a {
     2099  border: 1px solid rgba(255, 255, 255, 0.3);
     2100  backdrop-filter: blur(10px);
     2101}
     2102
     2103/* Video Wrapper */
     2104.mgpd-video-wrapper {
     2105  position: relative;
     2106  display: block;
     2107  width: 100%;
     2108  text-decoration: none;
     2109}
     2110
     2111.mgpd-video-wrapper img {
     2112  width: 100%;
     2113  height: auto;
     2114  display: block;
     2115}
     2116
     2117.mgpd-video-wrapper .mgpd-video-play-icon {
     2118  position: absolute;
     2119  top: 50%;
     2120  left: 50%;
     2121  transform: translate(-50%, -50%);
     2122  width: 60px;
     2123  height: 60px;
     2124  background: rgba(255, 0, 0, 0.9);
     2125  border-radius: 50%;
     2126  display: flex;
     2127  align-items: center;
     2128  justify-content: center;
     2129  z-index: 2;
     2130  transition: all 0.3s ease;
     2131  pointer-events: none;
     2132}
     2133
     2134.mgpd-video-wrapper:hover .mgpd-video-play-icon {
     2135  background: rgba(255, 0, 0, 1);
     2136  transform: translate(-50%, -50%) scale(1.15);
     2137}
     2138
     2139.mgpd-video-wrapper .mgpd-video-play-icon::before {
     2140  content: '';
     2141  width: 0;
     2142  height: 0;
     2143  border-style: solid;
     2144  border-width: 12px 0 12px 20px;
     2145  border-color: transparent transparent transparent #ffffff;
     2146  margin-left: 3px;
     2147}
     2148
     2149/* Hide premium features when video is present */
     2150.mgpd-video-wrapper ~ .mgpd-premium-features,
     2151.mp-post-img:has(.mgpd-video-wrapper) .mgpd-premium-features {
     2152  display: none !important;
     2153}
     2154
     2155/* Placeholder Image */
     2156.mgpd-placeholder-img {
     2157  width: 100%;
     2158  min-height: 250px;
     2159  background: #ddd;
     2160  display: flex;
     2161  align-items: center;
     2162  justify-content: center;
     2163  position: relative;
     2164}
     2165
     2166.mgpd-placeholder-img::before {
     2167  content: 'No Image';
     2168  color: #999;
     2169  font-size: 18px;
     2170  font-weight: 500;
     2171  text-transform: uppercase;
     2172  letter-spacing: 2px;
     2173}
     2174
     2175/* Advanced Hover Effects */
     2176.mgpd-hover-zoom .mg-card {
     2177  transition: transform 0.3s ease;
     2178  overflow: hidden;
     2179}
     2180
     2181.mgpd-hover-zoom .mg-card.mgpd-hover-active {
     2182  transform: scale(1.05);
     2183  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
     2184}
     2185
     2186.mgpd-hover-zoom .mg-card .mp-post-img img {
     2187  transition: transform 0.3s ease;
     2188}
     2189
     2190.mgpd-hover-zoom .mg-card.mgpd-hover-active .mp-post-img img {
     2191  transform: scale(1.1);
     2192}
     2193
     2194.mgpd-hover-slide .mg-card {
     2195  transition: transform 0.3s ease;
     2196}
     2197
     2198.mgpd-hover-slide .mg-card.mgpd-hover-active {
     2199  transform: translateY(-10px);
     2200  box-shadow: 0 15px 35px rgba(0, 0, 0, 0.15);
     2201}
     2202
     2203.mgpd-hover-fade .mg-card {
     2204  transition: opacity 0.3s ease;
     2205}
     2206
     2207.mgpd-hover-fade .mg-card.mgpd-hover-active {
     2208  opacity: 0.9;
     2209  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
     2210}
     2211
     2212.mgpd-hover-rotate .mg-card {
     2213  transition: transform 0.3s ease;
     2214}
     2215
     2216.mgpd-hover-rotate .mg-card.mgpd-hover-active {
     2217  transform: rotate(2deg) scale(1.02);
     2218  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.15);
     2219}
     2220
     2221/* Infinite Scroll Enhancements */
     2222.mgpd-infinite-scroll-enabled {
     2223  position: relative;
     2224}
     2225
     2226.mgpd-infinite-scroll-trigger {
     2227  visibility: hidden;
     2228}
     2229
     2230/* Responsive Design for Premium Features */
     2231@media (max-width: 768px) {
     2232  .mgpd-filter-buttons {
     2233    gap: 5px;
     2234  }
     2235 
     2236  .mgpd-filter-btn {
     2237    padding: 6px 12px;
     2238    font-size: 14px;
     2239  }
     2240 
     2241  .mgpd-social-share a {
     2242    width: 28px;
     2243    height: 28px;
     2244    font-size: 12px;
     2245  }
     2246 
     2247  .mgpd-reading-time,
     2248  .mgpd-view-count {
     2249    font-size: 11px;
     2250    padding: 3px 8px;
     2251  }
     2252}
     2253
     2254@media (max-width: 576px) {
     2255  .mgpd-ajax-filter-container {
     2256    margin-bottom: 20px;
     2257  }
     2258 
     2259  .mgpd-social-share {
     2260    justify-content: center;
     2261    gap: 6px;
     2262  }
     2263 
     2264  /* Disable complex hover effects on mobile */
     2265  .mgpd-hover-zoom .mg-card.mgpd-hover-active,
     2266  .mgpd-hover-slide .mg-card.mgpd-hover-active,
     2267  .mgpd-hover-rotate .mg-card.mgpd-hover-active {
     2268    transform: none;
     2269  }
     2270}
  • magical-posts-display/trunk/assets/js/main.js

    r2328226 r3380394  
    22    "use strict";
    33   
    4     //document ready function
     4    // Document ready function
    55    jQuery(document).ready(function($){
    6 /*-----
    7 Bootstrap carousel active
    8 ----------------------*/
    9         /*var mobileSlider = $('.carousel');
    10         mobileSlider.carousel({
    11           interval: 8000,
     6        // Show sticker lists
     7        $('.mgpd-sticker ul').show();
     8    });
     9   
     10// Enhanced masonry initialization for multiple containers
     11$(window).on('load', function() {
     12    $('.mgpd-masonry').each(function() {
     13        var $container = $(this);
     14        var $wrapper = $container.closest('.mgpd-masonry-container');
     15        var container = this;
     16       
     17        // Wait for images to load before initializing masonry
     18        imagesLoaded(container, function() {
     19            try {
     20                var masonryInstance = new Masonry(container, {
     21                    itemSelector: '.mgpd-masonry-item',
     22                    percentPosition: true,
     23                    gutter: 0,
     24                    horizontalOrder: true,
     25                    fitWidth: false,
     26                    transitionDuration: 0 // Disable animation for initial load
     27                });
     28               
     29                // Store masonry instance for later use
     30                $container.data('masonry', masonryInstance);
     31               
     32                // Force layout calculation after initialization
     33                setTimeout(function() {
     34                    masonryInstance.layout();
     35                    $container.css('height', 'auto');
     36                }, 100);
     37               
     38                // Add loaded class for smooth appearance
     39                $wrapper.addClass('masonry-loaded');
     40               
     41            } catch (error) {
     42                console.error('MGPD: Error initializing masonry:', error);
     43            }
    1244        });
     45    });
     46   
     47    // Initialize Premium Features if available
     48    if (typeof initMGPDPremiumFeatures === 'function') {
     49        initMGPDPremiumFeatures();
     50    }
     51});
    1352
    14         $('.awesome-carousel .carousel-inner .item:first-child').addClass('active');*/
    15      
    16         $('.mgpd-sticker ul').show();
     53// Also initialize on DOM ready for faster loading
     54$(document).ready(function() {
     55    // Pre-initialize masonry containers
     56    $('.mgpd-masonry').each(function() {
     57        var $container = $(this);
     58        $container.css('min-height', '600px'); // Temporary min-height
     59    });
     60});
    1761
    18     });//End document ready function
    19 // masonry active
    20        
    21             var container = document.querySelector('.mgpd-masonry');
    22             //create empty var msnry
    23             var msnry;
    24             // initialize Masonry after all images have loaded
    25          if ( $(container).length > 0 ){
    26             imagesLoaded( container, function() {
    27                 msnry = new Masonry( container, {
    28                     itemSelector: '.mgpd-masonry-item'
    29                 });
    30             });
     62// Global function to reinitialize masonry (can be called by premium features)
     63// Add throttling to prevent excessive calls
     64var mgpdMasonryThrottle = false;
    3165
    32         }
     66window.mgpdReinitializeMasonry = function() {
     67    if (mgpdMasonryThrottle) {
     68        return; // Silent throttle
     69    }
     70   
     71    mgpdMasonryThrottle = true;
     72   
     73    setTimeout(function() {
     74        mgpdMasonryThrottle = false;
     75    }, 500); // Throttle for 500ms
     76   
     77    $('.mgpd-masonry').each(function() {
     78        var $container = $(this);
     79        var container = this;
     80        var masonryInstance = $container.data('masonry');
     81       
     82        // Check if masonry is already initialized on this container
     83        if (masonryInstance) {
     84            // Masonry is initialized, reload items
     85            imagesLoaded(container, function() {
     86                try {
     87                    // Use direct instance methods instead of jQuery plugin
     88                    masonryInstance.reloadItems();
     89                    masonryInstance.layout();
     90                   
     91                    // Reset height to auto to allow proper calculation
     92                    $container.css('height', 'auto');
     93                   
     94                } catch (error) {
     95                    console.error('MGPD: Error reloading masonry:', error);
     96                }
     97            });
     98        } else {
     99            // Masonry not initialized, initialize it first
     100            imagesLoaded(container, function() {
     101                try {
     102                    var newMasonryInstance = new Masonry(container, {
     103                        itemSelector: '.mgpd-masonry-item',
     104                        percentPosition: true,
     105                        gutter: 0,
     106                        horizontalOrder: true,
     107                        fitWidth: false
     108                    });
     109                   
     110                    // Store masonry instance
     111                    $container.data('masonry', newMasonryInstance);
     112                   
     113                    // Add loaded class for smooth appearance
     114                    $container.closest('.mgpd-masonry-container').addClass('masonry-loaded');
     115                   
     116                } catch (error) {
     117                    console.error('MGPD: Error initializing masonry:', error);
     118                }
     119            });
     120        }
     121    });
     122};
     123
     124}(jQuery));
    33125
    34126
    35 }(jQuery));
    36 
    37 
  • magical-posts-display/trunk/composer.json

    r3196996 r3380394  
    11{
     2    "name": "magical-posts-display/wordpress-plugin",
     3    "description": "Magical Posts Display - Elementor Advanced Posts widgets",
     4    "type": "wordpress-plugin",
     5    "license": "GPL-2.0-or-later",
    26    "require": {
     7        "php": ">=7.4",
    38        "appsero/client": "^2.0.4",
    49        "htmlburger/carbon-fields": "^3.6"
     10    },
     11    "require-dev": {
     12        "phpstan/phpstan": "^1.0"
     13    },
     14    "autoload": {
     15        "psr-4": {
     16            "MagicalPostsDisplay\\": "includes/"
     17        }
    518    }
    619}
  • magical-posts-display/trunk/file-include.php

    r3235168 r3380394  
    11<?php
    2 /*
    3 *
    4 * Magical posts display
    5 * All files includes
    6 *
    7 *
    8 *
    9 */
    102
     3/**
     4 * File Include Manager
     5 *
     6 * Manages all file inclusions for the plugin
     7 * Organized by functionality and context
     8 *
     9 * REORGANIZATION SUMMARY:
     10 * - Admin notices moved to admin/admin-page/admin-info.php
     11 * - Assets (CSS/JS) handling moved to includes/class-assets-manager.php
     12 * - AJAX handlers moved to includes/class-ajax-handler.php
     13 * - WordPress hooks moved to includes/class-hooks-handler.php
     14 * - Main plugin class cleaned up to focus on core initialization
     15 *
     16 * @package Magical Posts Display
     17 * @since 1.2.54
     18 */
     19
     20if (!defined('ABSPATH')) {
     21    exit; // Exit if accessed directly.
     22}
     23
     24// Initialize plugin data
    1125$mg_args = array(
    1226    'posts_per_page' => -1,
    1327    'ignore_sticky_posts' => 1,
    1428    'post_type' => 'mp-display',
    15 
    1629);
    1730
     
    1932$install_date = gmdate("Y-m-d", strtotime(get_option('mgposte_install_date')));
    2033$compare_date = '2023-03-07';
     34
     35// Include core classes
     36require_once(MAGICAL_POSTS_DISPLAY_DIR . 'includes/class-assets-manager.php');
     37require_once(MAGICAL_POSTS_DISPLAY_DIR . 'includes/class-ajax-handler.php');
     38require_once(MAGICAL_POSTS_DISPLAY_DIR . 'includes/class-hooks-handler.php');
     39
     40// Initialize core handlers
     41if (class_exists('MPD_Assets_Manager')) {
     42    MPD_Assets_Manager::init();
     43}
     44
     45if (class_exists('MPD_Ajax_Handler')) {
     46    MPD_Ajax_Handler::init();
     47}
     48
     49if (class_exists('MPD_Hooks_Handler')) {
     50    MPD_Hooks_Handler::init();
     51}
    2152
    2253if (is_admin()) {
     
    5384require_once(MAGICAL_POSTS_DISPLAY_DIR . 'includes/mp-posts-function.php');
    5485
    55 //admin info
    56 if (!mpd_check_plugin_active('magical-posts-display-pro/magical-posts-display-pro.php')) {
     86// Load traits
     87if (file_exists(MAGICAL_POSTS_DISPLAY_DIR . 'includes/traits/SVG_Icons_Trait.php')) {
     88    require_once(MAGICAL_POSTS_DISPLAY_DIR . 'includes/traits/SVG_Icons_Trait.php');
     89}
     90if (file_exists(MAGICAL_POSTS_DISPLAY_DIR . 'includes/traits/Advanced_Media_Trait.php')) {
     91    require_once(MAGICAL_POSTS_DISPLAY_DIR . 'includes/traits/Advanced_Media_Trait.php');
     92}
     93if (file_exists(MAGICAL_POSTS_DISPLAY_DIR . 'includes/traits/Premium_Features_Trait.php')) {
     94    require_once(MAGICAL_POSTS_DISPLAY_DIR . 'includes/traits/Premium_Features_Trait.php');
     95}
     96
     97// Admin info (moved to conditional include based on context)
     98if (is_admin() && !mpd_check_plugin_active('magical-posts-display-pro/magical-posts-display-pro.php')) {
    5799    require_once(MAGICAL_POSTS_DISPLAY_DIR . 'admin/admin-page/admin-info.php');
    58100}
     
    84126
    85127
    86 /*
    87     *
    88     * Plugin activation hook
    89     *
    90     */
    91 function mp_display_activation_setup()
    92 {
    93     // Trigger our function that registers the custom post type
    94     mp_display_post_type();
    95 
    96     // Clear the permalinks after the post type has been registered
    97     flush_rewrite_rules();
    98     // Add new administrator role
    99     mp_display_admin_role();
    100 }
    101 
    102 /*
    103     *
    104     * Plugin deactivation hook
    105     *
    106     */
    107 
    108 function mp_display_deactivation_setup()
    109 {
    110 
    111     // Clear the permalinks to remove our post type's rules
    112     flush_rewrite_rules();
    113 
    114     // gets the administrator role remove
    115     mp_display_admin_role_remove();
    116 }
    117 
    118 register_activation_hook(__FILE__, 'mp_display_activation_setup');
    119 register_deactivation_hook(__FILE__, 'mp_display_deactivation_setup');
     128// Plugin activation and deactivation hooks are now handled by MPD_Hooks_Handler class
    120129
    121130
     
    177186}
    178187
    179 if (!function_exists('mpd_count_post_visits')) {
    180     function mpd_count_post_visits()
    181     {
    182         if (is_single()) {
    183             global $post;
    184             $views = get_post_meta($post->ID, 'mpd_my_post_viewed', true);
    185             if ($views == '') {
    186                 update_post_meta($post->ID, 'mpd_my_post_viewed', '1');
    187             } else {
    188                 $views_no = intval($views);
    189                 update_post_meta($post->ID, 'mpd_my_post_viewed', ++$views_no);
    190             }
    191         }
    192     }
    193     add_action('wp_head', 'mpd_count_post_visits');
    194 }
     188// Post visit counting is now handled by MPD_Hooks_Handler class
  • magical-posts-display/trunk/includes/blocks/posts-tab.php

    r3116993 r3380394  
    477477                                                endwhile;
    478478
    479                                                 wp_reset_query();
     479                                                wp_reset_postdata();
    480480                                                wp_reset_postdata();
    481481                                            else :
  • magical-posts-display/trunk/includes/elementor/elementor-main.php

    r3325763 r3380394  
    6666        require_once(MAGICAL_POSTS_DISPLAY_DIR . '/includes/elementor/widgets/news-magazine-grid.php');
    6767        $widgets_manager->register(new \mgpdNewsMagazineGrid());
    68        
     68
    6969        // News Magazine Image Grid
    7070        require_once(MAGICAL_POSTS_DISPLAY_DIR . '/includes/elementor/widgets/news-magazine-img-grid.php');
     
    7676
    7777        $category_prefix = 'mgp-';
    78             $category_slug   = $category_prefix . 'mgposts';
     78        $category_slug   = $category_prefix . 'mgposts';
    7979
    80             $elements_manager->add_category( $category_slug, [
    81                 'title' => esc_html__( 'Magical Posts Display', 'magical-posts-display' ),
    82                 'icon'  => 'fa fa-magic',
    83             ] );
     80        $elements_manager->add_category($category_slug, [
     81            'title' => esc_html__('Magical Posts Display', 'magical-posts-display'),
     82            'icon'  => 'fa fa-magic',
     83        ]);
    8484
    85             // Get all existing categories
    86             $categories = $elements_manager->get_categories();
     85        // Get all existing categories
     86        $categories = $elements_manager->get_categories();
    8787
    88             // Remove your custom category from the list to reposition it
    89             $magical_category = $categories[ $category_slug ] ?? null;
    90             unset( $categories[ $category_slug ] );
     88        // Remove your custom category from the list to reposition it
     89        $magical_category = $categories[$category_slug] ?? null;
     90        unset($categories[$category_slug]);
    9191
    92             if ( ! $magical_category ) {
    93                 return; // Stop if not found
    94             }
     92        if (! $magical_category) {
     93            return; // Stop if not found
     94        }
    9595
    96             // Insert at index 3 (4th position)
    97             $before    = array_slice( $categories, 0, 3, true );
    98             $after     = array_slice( $categories, 3, null, true );
    99             $reordered = $before + [ $category_slug => $magical_category ] + $after;
     96        // Insert at index 3 (4th position)
     97        $before    = array_slice($categories, 0, 4, true);
     98        $after     = array_slice($categories, 4, null, true);
     99        $reordered = $before + [$category_slug => $magical_category] + $after;
    100100
    101             // Use reflection to inject reordered categories
    102             $reflection = new \ReflectionClass( $elements_manager );
    103             $property   = $reflection->getProperty( 'categories' );
    104             $property->setAccessible( true );
    105             $property->setValue( $elements_manager, $reordered );
    106 
     101        // Use reflection to inject reordered categories
     102        $reflection = new \ReflectionClass($elements_manager);
     103        $property   = $reflection->getProperty('categories');
     104        $property->setAccessible(true);
     105        $property->setValue($elements_manager, $reordered);
    107106    }
    108107
     
    125124
    126125        wp_enqueue_style("mp-tab-style", MAGICAL_POSTS_DISPLAY_ASSETS . 'css/widget-style/mp-tabs.css', array(), MAGICAL_POSTS_DISPLAY_VERSION, 'all');
    127        
     126
    128127        // Register News Magazine Grid styles
    129128        wp_register_style('magical-news-magazine-grid', MAGICAL_POSTS_DISPLAY_ASSETS . 'css/news-magazine-grid.css', array(), MAGICAL_POSTS_DISPLAY_VERSION, 'all');
    130        
     129
    131130        // Register News Magazine Image Grid styles
    132131        wp_register_style('magical-news-magazine-img-grid', MAGICAL_POSTS_DISPLAY_ASSETS . 'css/news-magazine-img-grid.css', array(), MAGICAL_POSTS_DISPLAY_VERSION, 'all');
  • magical-posts-display/trunk/includes/elementor/widgets/advanced-posts-grid1.php

    r3116993 r3380394  
    19251925                        endif;
    19261926                    endwhile;
    1927                     wp_reset_query();
     1927                    wp_reset_postdata();
    19281928                    wp_reset_postdata();
    19291929                    ?>
  • magical-posts-display/trunk/includes/elementor/widgets/advanced-posts-grid2.php

    r3116993 r3380394  
    19951995                        endif;
    19961996                    endwhile;
    1997                     wp_reset_query();
     1997                    wp_reset_postdata();
    19981998                    wp_reset_postdata();
    19991999                    ?>
  • magical-posts-display/trunk/includes/elementor/widgets/advanced-posts-img-grid.php

    r3214174 r3380394  
    13331333            ]
    13341334        );
    1335        
     1335
    13361336        $this->add_responsive_control(
    13371337            'mgpg_description_padding',
     
    13451345            ]
    13461346        );
    1347        
     1347
    13481348        $this->add_responsive_control(
    13491349            'mgpg_description_margin',
     
    13571357            ]
    13581358        );
    1359        
     1359
    13601360        $this->add_control(
    13611361            'mgpg_description_color',
     
    13681368            ]
    13691369        );
    1370        
     1370
    13711371        $this->add_control(
    13721372            'mgpg_description_bgcolor',
     
    13791379            ]
    13801380        );
    1381        
     1381
    13821382        $this->add_control(
    13831383            'mgpg_description_radius',
     
    13911391            ]
    13921392        );
    1393        
     1393
    13941394        $this->end_controls_tab(); // End of Normal Tab
    1395        
     1395
    13961396        // Hover Tab
    13971397        $this->start_controls_tab(
     
    14011401            ]
    14021402        );
    1403        
     1403
    14041404        $this->add_control(
    14051405            'mgpg_description_hover_color',
     
    14121412            ]
    14131413        );
    1414        
     1414
    14151415        $this->add_control(
    14161416            'mgpg_description_hover_bgcolor',
     
    14231423            ]
    14241424        );
    1425        
     1425
    14261426        $this->add_control(
    14271427            'mgpg_des_hover_transition',
     
    14411441            ]
    14421442        );
    1443        
     1443
    14441444        $this->end_controls_tab(); // End of Hover Tab
    1445        
     1445
    14461446        $this->end_controls_tabs();
    1447        
     1447
    14481448        $this->add_group_control(
    14491449            \Elementor\Group_Control_Typography::get_type(),
     
    14541454            ]
    14551455        );
    1456        
     1456
    14571457        $this->end_controls_section();
    14581458        $this->start_controls_section(
     
    14781478
    14791479
    1480  $this->start_controls_tabs('mgpg_meta_cat_tabs');
    1481        
     1480        $this->start_controls_tabs('mgpg_meta_cat_tabs');
     1481
    14821482        // Normal Tab
    14831483        $this->start_controls_tab(
     
    14871487            ]
    14881488        );
    1489        
     1489
    14901490        $this->add_control(
    14911491            'mgpg_meta_cat_text_color',
     
    14981498            ]
    14991499        );
    1500        
     1500
    15011501        $this->add_control(
    15021502            'mgpg_meta_cat_bg_color',
     
    15091509            ]
    15101510        );
    1511        
     1511
    15121512        $this->add_responsive_control(
    15131513            'mgpg_meta_cat_margin',
     
    15201520            ]
    15211521        );
    1522        
     1522
    15231523        $this->add_responsive_control(
    15241524            'mgpg_meta_cat_padding',
     
    15311531            ]
    15321532        );
    1533                
     1533
    15341534        $this->add_control(
    15351535            'mgpg_meta_cat_border_radius',
     
    15431543            ]
    15441544        );
    1545        
     1545
    15461546        $this->add_group_control(
    15471547            \Elementor\Group_Control_Border::get_type(),
     
    15521552            ]
    15531553        );
    1554        
     1554
    15551555        $this->add_group_control(
    15561556            \Elementor\Group_Control_Box_Shadow::get_type(),
     
    15611561            ]
    15621562        );
    1563        
     1563
    15641564        $this->end_controls_tab(); // End Normal Tab
    1565        
     1565
    15661566        // Hover Tab
    15671567        $this->start_controls_tab(
     
    15711571            ]
    15721572        );
    1573        
     1573
    15741574        $this->add_control(
    15751575            'mgpg_meta_cat_text_color_hover',
     
    15821582            ]
    15831583        );
    1584        
     1584
    15851585        $this->add_control(
    15861586            'mgpg_meta_cat_bg_color_hover',
     
    15931593            ]
    15941594        );
    1595        
     1595
    15961596        $this->add_group_control(
    15971597            \Elementor\Group_Control_Border::get_type(),
     
    16021602            ]
    16031603        );
    1604        
     1604
    16051605        $this->add_group_control(
    16061606            \Elementor\Group_Control_Box_Shadow::get_type(),
     
    16111611            ]
    16121612        );
    1613        
     1613
    16141614        $this->end_controls_tab(); // End Hover Tab
    1615        
     1615
    16161616        $this->end_controls_tabs(); // End Tabs
    1617        
     1617
    16181618        $this->add_group_control(
    16191619            \Elementor\Group_Control_Typography::get_type(),
     
    16431643            ]
    16441644        );
    1645        
     1645
    16461646        $this->add_control(
    16471647            'mgpg_author_style_section',
     
    16531653        );
    16541654
    1655        
     1655
    16561656        $this->start_controls_tabs('mgpg_author_tabs');
    1657        
     1657
    16581658        // Normal Tab
    16591659        $this->start_controls_tab(
     
    16631663            ]
    16641664        );
    1665        
     1665
    16661666        $this->add_group_control(
    16671667            \Elementor\Group_Control_Typography::get_type(),
     
    17021702            ]
    17031703        );
    1704        
     1704
    17051705        $this->add_control(
    17061706            'mgpg_author_background_color',
     
    17131713            ]
    17141714        );
    1715        
     1715
    17161716        $this->add_group_control(
    17171717            \Elementor\Group_Control_Border::get_type(),
     
    17221722            ]
    17231723        );
    1724        
     1724
    17251725        $this->add_responsive_control(
    17261726            'mgpg_author_margin',
     
    17331733            ]
    17341734        );
    1735        
     1735
    17361736        $this->add_responsive_control(
    17371737            'mgpg_author_padding',
     
    17441744            ]
    17451745        );
    1746        
     1746
    17471747        $this->end_controls_tab();
    1748        
     1748
    17491749        // Hover Tab
    17501750        $this->start_controls_tab(
     
    17541754            ]
    17551755        );
    1756        
     1756
    17571757        $this->add_control(
    17581758            'mgpg_author_hover_text_color',
     
    17651765            ]
    17661766        );
    1767        
     1767
    17681768        $this->add_control(
    17691769            'mgpg_author_hover_background_color',
     
    17761776            ]
    17771777        );
    1778        
     1778
    17791779        $this->add_group_control(
    17801780            \Elementor\Group_Control_Box_Shadow::get_type(),
     
    17851785            ]
    17861786        );
    1787        
     1787
    17881788        $this->add_control(
    17891789            'mgpg_author_transition_duration',
     
    18031803            ]
    18041804        );
    1805        
     1805
    18061806        $this->end_controls_tab();
    1807        
     1807
    18081808        $this->end_controls_tabs();
    1809        
     1809
    18101810
    18111811
     
    19901990                            }
    19911991                        endwhile;
    1992                         wp_reset_query();
     1992                        wp_reset_postdata();
    19931993                        wp_reset_postdata();
    19941994                        ?>
  • magical-posts-display/trunk/includes/elementor/widgets/posts-carousel.php

    r3116993 r3380394  
    22902290                            <?php
    22912291                            endwhile;
    2292                             wp_reset_query();
     2292                            wp_reset_postdata();
    22932293                            wp_reset_postdata();
    22942294                            ?>
  • magical-posts-display/trunk/includes/elementor/widgets/posts-cat.php

    r2961712 r3380394  
    421421            'content_grid_boxshadow',
    422422            [
    423                 'label' => __('Use Box shadow?', 'magical-addons-for-elementor'),
     423                'label' => __('Use Box shadow?', 'magical-posts-display'),
    424424                'type' => \Elementor\Controls_Manager::SWITCHER,
    425                 'yes' => __('Yes', 'magical-addons-for-elementor'),
    426                 'no' => __('No', 'magical-addons-for-elementor'),
     425                'yes' => __('Yes', 'magical-posts-display'),
     426                'no' => __('No', 'magical-posts-display'),
    427427                'default' => 'yes',
    428428            ]
  • magical-posts-display/trunk/includes/elementor/widgets/posts-grid.php

    r3214174 r3380394  
    11<?php
    2 
    32
    43class mgpdEPostsGrid extends \Elementor\Widget_Base
    54{
     5    use SVG_Icons_Trait;
     6    use Advanced_Media_Trait;
    67
    78    /**
     
    126127                    'show_byid' => esc_html__('Show By Id (Post Only)', 'magical-posts-display'),
    127128                    'show_byid_manually' => esc_html__('Add ID Manually', 'magical-posts-display'),
     129                    'advanced_query' => esc_html__('Advanced Query Builder (Pro Only)', 'magical-posts-display'),
     130                    'custom_fields' => esc_html__('Custom Fields Filter (Pro Only)', 'magical-posts-display'),
     131                    'exclude_current' => esc_html__('Exclude Current Post (Pro Only)', 'magical-posts-display'),
    128132                ],
    129133            ]
     
    239243        );
    240244        $this->add_control(
     245            'mgpg_layout_type',
     246            [
     247                'label'   => __('Layout Type', 'magical-posts-display'),
     248                'type'    => \Elementor\Controls_Manager::SELECT,
     249                'default' => 'static',
     250                'options' => [
     251                    'static'   => __('Static', 'magical-posts-display'),
     252                    'masonry'  => __('Masonry', 'magical-posts-display'),
     253                ],
     254                'description' => __('Choose between static grid layout or masonry layout. Masonry creates a dynamic, Pinterest-style layout. <strong>Note: Masonry only works on frontend, not in editor preview.</strong>', 'magical-posts-display'),
     255            ]
     256        );
     257        $this->add_control(
     258            'mgpg_masonry_style',
     259            [
     260                'label'   => __('Masonry Style', 'magical-posts-display'),
     261                'type'    => \Elementor\Controls_Manager::SELECT,
     262                'default' => 'style1',
     263                'options' => [
     264                    'style1'   => __('Style 1 - Default Heights', 'magical-posts-display'),
     265                    'style2'   => __('Style 2 - Alternating Heights', 'magical-posts-display'),
     266                    'style3'   => __('Style 3 - Pattern Heights', 'magical-posts-display'),
     267                ],
     268                'condition' => [
     269                    'mgpg_layout_type' => 'masonry',
     270                ],
     271                'description' => __('Choose different image height patterns for masonry layout. <strong>Note: Masonry preview only works on frontend.</strong>', 'magical-posts-display'),
     272            ]
     273        );
     274        $this->add_control(
    241275            'mgpg_post_style',
    242276            [
     
    284318            ]
    285319        );
     320
     321        $this->add_control(
     322            'mgpg_media_source',
     323            [
     324                'label' => __('Advanced Media Source (Pro Only)', 'magical-posts-display'),
     325                'type' => \Elementor\Controls_Manager::SELECT,
     326                'options' => [
     327                    'featured' => __('Featured Image Only', 'magical-posts-display'),
     328                    'content' => __('First Content Image (Pro Only)', 'magical-posts-display'),
     329                    'video' => __('Video Embed (YouTube/Vimeo) (Pro Only)', 'magical-posts-display'),
     330                    'priority' => __('Priority Fallback (Pro Only)', 'magical-posts-display'),
     331                ],
     332                'default' => 'featured',
     333                'description' => __('Choose media source with priority fallback system (Pro Only)', 'magical-posts-display'),
     334                'classes' => 'mpd-pro-control',
     335                'condition' => [
     336                    'mgpg_post_img_show' => 'yes',
     337                ],
     338            ]
     339        );
     340
     341        $this->add_control(
     342            'mgpg_media_priority',
     343            [
     344                'label' => __('Priority Order (Pro Only)', 'magical-posts-display'),
     345                'type' => \Elementor\Controls_Manager::SELECT2,
     346                'multiple' => true,
     347                'options' => [
     348                    'video' => __('Video Embed', 'magical-posts-display'),
     349                    'featured' => __('Featured Image', 'magical-posts-display'),
     350                    'content' => __('First Content Image', 'magical-posts-display'),
     351                    'placeholder' => __('Placeholder Image', 'magical-posts-display'),
     352                ],
     353                'default' => ['video', 'featured', 'content', 'placeholder'],
     354                'description' => __('Set priority order for media fallback. First available source will be used (Pro Only)', 'magical-posts-display'),
     355                'classes' => 'mpd-pro-control',
     356                'condition' => [
     357                    'mgpg_post_img_show' => 'yes',
     358                    'mgpg_media_source' => 'priority',
     359                ],
     360            ]
     361        );
     362
     363        $this->add_control(
     364            'mgpg_video_play_icon',
     365            [
     366                'label' => __('Show Video Play Icon', 'magical-posts-display'),
     367                'type' => \Elementor\Controls_Manager::SWITCHER,
     368                'default' => 'yes',
     369                'description' => __('Display play icon overlay on video thumbnails (Pro Only)', 'magical-posts-display'),
     370                'classes' => 'mpd-pro-control',
     371                'condition' => [
     372                    'mgpg_post_img_show' => 'yes',
     373                    'mgpg_media_source' => ['video', 'priority'],
     374                ],
     375                'condition_type' => 'or',
     376            ]
     377        );
     378
    286379        $this->add_control(
    287380            'mgpg_show_title',
     
    590683        );
    591684        $this->end_controls_section();
     685
     686        // Premium Features Section
     687        $this->start_controls_section(
     688            'mgpg_premium_features',
     689            [
     690                'label' => sprintf('%s %s', __('Premium Features', 'magical-posts-display'), mp_display__pro_only_text()),
     691                'tab'   => \Elementor\Controls_Manager::TAB_CONTENT,
     692            ]
     693        );
     694        if (empty(mp_display_check_main_ok())) {
     695            $this->add_control(
     696                'mgpg_premium_info',
     697                [
     698                    'type' => \Elementor\Controls_Manager::RAW_HTML,
     699                    'raw' => sprintf('<span style="color:red">%s</span>', __('These advanced features are only available in the Pro version.', 'magical-posts-display')),
     700                ]
     701            );
     702        }
     703        $this->add_control(
     704            'mgpg_ajax_filter',
     705            [
     706                'label' => __('AJAX Category Filter', 'magical-posts-display'),
     707                'type' => \Elementor\Controls_Manager::SWITCHER,
     708                'description' => __('Enable dynamic category filtering without page reload (Pro Only)', 'magical-posts-display'),
     709                'classes' => 'mpd-pro-control',
     710            ]
     711        );
     712
     713        $this->add_control(
     714            'mgpg_infinite_scroll',
     715            [
     716                'label' => __('Infinite Scroll', 'magical-posts-display'),
     717                'type' => \Elementor\Controls_Manager::SWITCHER,
     718                'description' => __('Load more posts automatically when scrolling (Pro Only)', 'magical-posts-display'),
     719                'classes' => 'mpd-pro-control',
     720            ]
     721        );
     722
     723        $this->add_control(
     724            'mgpg_reading_time',
     725            [
     726                'label' => __('Reading Time Display', 'magical-posts-display'),
     727                'type' => \Elementor\Controls_Manager::SWITCHER,
     728                'description' => __('Show estimated reading time for each post (Pro Only)', 'magical-posts-display'),
     729                'classes' => 'mpd-pro-control',
     730            ]
     731        );
     732
     733        $this->add_control(
     734            'mgpg_view_count',
     735            [
     736                'label' => __('Post Views Counter', 'magical-posts-display'),
     737                'type' => \Elementor\Controls_Manager::SWITCHER,
     738                'description' => __('Display post view counts with analytics (Pro Only)', 'magical-posts-display'),
     739                'classes' => 'mpd-pro-control',
     740            ]
     741        );
     742
     743        $this->add_control(
     744            'mgpg_social_share',
     745            [
     746                'label' => __('Social Share Buttons', 'magical-posts-display'),
     747                'type' => \Elementor\Controls_Manager::SWITCHER,
     748                'description' => __('Add social sharing buttons to each post card (Pro Only)', 'magical-posts-display'),
     749                'classes' => 'mpd-pro-control',
     750            ]
     751        );
     752
     753        $this->add_control(
     754            'mgpg_premium_features_style',
     755            [
     756                'label' => __('Premium Features Display Style', 'magical-posts-display'),
     757                'type' => \Elementor\Controls_Manager::SELECT,
     758                'options' => [
     759                    'default' => __('Default (Below Content)', 'magical-posts-display'),
     760                    'image-top' => __('Top of Image (Pro Only)', 'magical-posts-display'),
     761                    'image-overlay' => __('Image Overlay on Hover (Pro Only)', 'magical-posts-display'),
     762                ],
     763                'default' => 'default',
     764                'description' => __('Choose where to display reading time, views, and social buttons (Pro Only)', 'magical-posts-display'),
     765                'classes' => 'mpd-pro-control',
     766                'condition' => [
     767                    'mgpg_reading_time' => 'yes',
     768                    'mgpg_view_count' => 'yes',
     769                    'mgpg_social_share' => 'yes',
     770                ],
     771                'condition_type' => 'or',
     772            ]
     773        );
     774
     775        $this->add_control(
     776            'mgpg_hover_effects',
     777            [
     778                'label' => __('Advanced Hover Effects', 'magical-posts-display'),
     779                'type' => \Elementor\Controls_Manager::SELECT,
     780                'options' => [
     781                    'none' => __('None', 'magical-posts-display'),
     782                    'zoom' => __('Zoom Effect (Pro Only)', 'magical-posts-display'),
     783                    'slide' => __('Slide Effect (Pro Only)', 'magical-posts-display'),
     784                    'fade' => __('Fade Effect (Pro Only)', 'magical-posts-display'),
     785                    'rotate' => __('Rotate Effect (Pro Only)', 'magical-posts-display'),
     786                ],
     787                'default' => 'none',
     788                'description' => __('Choose advanced hover animations for post cards (Pro Only)', 'magical-posts-display'),
     789                'classes' => 'mpd-pro-control',
     790            ]
     791        );
     792        if (mp_display_check_main_ok()) {
     793            $this->add_control(
     794                'mgpg_ajax_info',
     795                [
     796                    'type' => \Elementor\Controls_Manager::RAW_HTML,
     797                    'raw' => sprintf('<span style="color:red">%s</span>', __('All Ajax features only work in the frontend', 'magical-posts-display')),
     798                ]
     799            );
     800        }
     801        $this->end_controls_section();
     802
    592803        $this->start_controls_section(
    593804            'mgpg_pagination',
     
    9331144        $this->end_controls_section();
    9341145
     1146        // Filter Buttons Style Section
     1147        $this->start_controls_section(
     1148            'mgpd_filter_buttons_style',
     1149            [
     1150                'label' => __('Filter Buttons', 'magical-posts-display'),
     1151                'tab'   => \Elementor\Controls_Manager::TAB_STYLE,
     1152                'condition' => [
     1153                    'mgpg_ajax_filter' => 'yes',
     1154                ]
     1155            ]
     1156        );
     1157
     1158        $this->add_responsive_control(
     1159            'mgpd_filter_align',
     1160            [
     1161                'label' => __('Alignment', 'magical-posts-display'),
     1162                'type' => \Elementor\Controls_Manager::CHOOSE,
     1163                'options' => [
     1164                    'left' => [
     1165                        'title' => __('Left', 'magical-posts-display'),
     1166                        'icon' => 'eicon-text-align-left',
     1167                    ],
     1168                    'center' => [
     1169                        'title' => __('Center', 'magical-posts-display'),
     1170                        'icon' => 'eicon-text-align-center',
     1171                    ],
     1172                    'right' => [
     1173                        'title' => __('Right', 'magical-posts-display'),
     1174                        'icon' => 'eicon-text-align-right',
     1175                    ],
     1176                ],
     1177                'default' => 'center',
     1178                'selectors' => [
     1179                    '{{WRAPPER}} .mgpd-filter-buttons' => 'text-align: {{VALUE}};',
     1180                ],
     1181            ]
     1182        );
     1183
     1184        $this->add_responsive_control(
     1185            'mgpd_filter_spacing',
     1186            [
     1187                'label' => __('Buttons Spacing', 'magical-posts-display'),
     1188                'type' => \Elementor\Controls_Manager::SLIDER,
     1189                'size_units' => ['px'],
     1190                'range' => [
     1191                    'px' => [
     1192                        'min' => 0,
     1193                        'max' => 50,
     1194                        'step' => 1,
     1195                    ],
     1196                ],
     1197                'selectors' => [
     1198                    '{{WRAPPER}} .mgpd-filter-buttons .mgpd-filter-btn' => 'margin: 0 {{SIZE}}{{UNIT}};',
     1199                ],
     1200            ]
     1201        );
     1202
     1203        $this->add_responsive_control(
     1204            'mgpd_filter_margin',
     1205            [
     1206                'label' => __('Container Margin', 'magical-posts-display'),
     1207                'type' => \Elementor\Controls_Manager::DIMENSIONS,
     1208                'size_units' => ['px', 'em', '%'],
     1209                'selectors' => [
     1210                    '{{WRAPPER}} .mgpd-filter-buttons' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
     1211                ],
     1212            ]
     1213        );
     1214
     1215        $this->add_responsive_control(
     1216            'mgpd_filter_padding',
     1217            [
     1218                'label' => __('Container Padding', 'magical-posts-display'),
     1219                'type' => \Elementor\Controls_Manager::DIMENSIONS,
     1220                'size_units' => ['px', 'em', '%'],
     1221                'selectors' => [
     1222                    '{{WRAPPER}} .mgpd-filter-buttons' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
     1223                ],
     1224            ]
     1225        );
     1226
     1227        // Button Tabs for Normal and Active states
     1228        $this->start_controls_tabs('mgpd_filter_btn_tabs');
     1229
     1230        // Normal State Tab
     1231        $this->start_controls_tab(
     1232            'mgpd_filter_btn_normal',
     1233            [
     1234                'label' => __('Normal', 'magical-posts-display'),
     1235            ]
     1236        );
     1237
     1238        $this->add_group_control(
     1239            \Elementor\Group_Control_Typography::get_type(),
     1240            [
     1241                'name' => 'mgpd_filter_btn_typography',
     1242                'selector' => '{{WRAPPER}} .mgpd-filter-buttons .mgpd-filter-btn',
     1243            ]
     1244        );
     1245
     1246        $this->add_control(
     1247            'mgpd_filter_btn_color',
     1248            [
     1249                'label' => __('Text Color', 'magical-posts-display'),
     1250                'type' => \Elementor\Controls_Manager::COLOR,
     1251                'default' => '#333333',
     1252                'selectors' => [
     1253                    '{{WRAPPER}} .mgpd-filter-buttons .mgpd-filter-btn' => 'color: {{VALUE}};',
     1254                ],
     1255            ]
     1256        );
     1257
     1258        $this->add_group_control(
     1259            \Elementor\Group_Control_Background::get_type(),
     1260            [
     1261                'name' => 'mgpd_filter_btn_bg',
     1262                'label' => __('Background', 'magical-posts-display'),
     1263                'types' => ['classic', 'gradient'],
     1264                'selector' => '{{WRAPPER}} .mgpd-filter-buttons .mgpd-filter-btn',
     1265            ]
     1266        );
     1267
     1268        $this->add_responsive_control(
     1269            'mgpd_filter_btn_padding',
     1270            [
     1271                'label' => __('Padding', 'magical-posts-display'),
     1272                'type' => \Elementor\Controls_Manager::DIMENSIONS,
     1273                'size_units' => ['px', 'em', '%'],
     1274                'default' => [
     1275                    'top' => 10,
     1276                    'right' => 20,
     1277                    'bottom' => 10,
     1278                    'left' => 20,
     1279                    'unit' => 'px',
     1280                ],
     1281                'selectors' => [
     1282                    '{{WRAPPER}} .mgpd-filter-buttons .mgpd-filter-btn' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
     1283                ],
     1284            ]
     1285        );
     1286
     1287        $this->add_control(
     1288            'mgpd_filter_btn_border_radius',
     1289            [
     1290                'label' => __('Border Radius', 'magical-posts-display'),
     1291                'type' => \Elementor\Controls_Manager::DIMENSIONS,
     1292                'size_units' => ['px', '%'],
     1293                'selectors' => [
     1294                    '{{WRAPPER}} .mgpd-filter-buttons .mgpd-filter-btn' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
     1295                ],
     1296            ]
     1297        );
     1298
     1299        $this->add_group_control(
     1300            \Elementor\Group_Control_Border::get_type(),
     1301            [
     1302                'name' => 'mgpd_filter_btn_border',
     1303                'selector' => '{{WRAPPER}} .mgpd-filter-buttons .mgpd-filter-btn',
     1304            ]
     1305        );
     1306
     1307        $this->add_group_control(
     1308            \Elementor\Group_Control_Box_Shadow::get_type(),
     1309            [
     1310                'name' => 'mgpd_filter_btn_shadow',
     1311                'selector' => '{{WRAPPER}} .mgpd-filter-buttons .mgpd-filter-btn',
     1312            ]
     1313        );
     1314
     1315        $this->end_controls_tab();
     1316
     1317        // Active/Hover State Tab
     1318        $this->start_controls_tab(
     1319            'mgpd_filter_btn_active',
     1320            [
     1321                'label' => __('Active/Hover', 'magical-posts-display'),
     1322            ]
     1323        );
     1324
     1325        $this->add_control(
     1326            'mgpd_filter_btn_active_color',
     1327            [
     1328                'label' => __('Text Color', 'magical-posts-display'),
     1329                'type' => \Elementor\Controls_Manager::COLOR,
     1330                'default' => '#ffffff',
     1331                'selectors' => [
     1332                    '{{WRAPPER}} .mgpd-filter-buttons .mgpd-filter-btn.active' => 'color: {{VALUE}};',
     1333                    '{{WRAPPER}} .mgpd-filter-buttons .mgpd-filter-btn:hover' => 'color: {{VALUE}};',
     1334                ],
     1335            ]
     1336        );
     1337
     1338        $this->add_group_control(
     1339            \Elementor\Group_Control_Background::get_type(),
     1340            [
     1341                'name' => 'mgpd_filter_btn_active_bg',
     1342                'label' => __('Background', 'magical-posts-display'),
     1343                'types' => ['classic', 'gradient'],
     1344                'selector' => '{{WRAPPER}} .mgpd-filter-buttons .mgpd-filter-btn.active, {{WRAPPER}} .mgpd-filter-buttons .mgpd-filter-btn:hover',
     1345            ]
     1346        );
     1347
     1348        $this->add_control(
     1349            'mgpd_filter_btn_active_border_color',
     1350            [
     1351                'label' => __('Border Color', 'magical-posts-display'),
     1352                'type' => \Elementor\Controls_Manager::COLOR,
     1353                'selectors' => [
     1354                    '{{WRAPPER}} .mgpd-filter-buttons .mgpd-filter-btn.active' => 'border-color: {{VALUE}};',
     1355                    '{{WRAPPER}} .mgpd-filter-buttons .mgpd-filter-btn:hover' => 'border-color: {{VALUE}};',
     1356                ],
     1357            ]
     1358        );
     1359
     1360        $this->add_group_control(
     1361            \Elementor\Group_Control_Box_Shadow::get_type(),
     1362            [
     1363                'name' => 'mgpd_filter_btn_active_shadow',
     1364                'selector' => '{{WRAPPER}} .mgpd-filter-buttons .mgpd-filter-btn.active, {{WRAPPER}} .mgpd-filter-buttons .mgpd-filter-btn:hover',
     1365            ]
     1366        );
     1367
     1368        $this->end_controls_tab();
     1369
     1370        $this->end_controls_tabs();
     1371
     1372        $this->end_controls_section();
     1373
    9351374        $this->start_controls_section(
    9361375            'mgpg_title_style',
     
    9401379            ]
    9411380        );
    942        
     1381
    9431382        // Adding Tabs for Normal and Hover
    9441383        $this->start_controls_tabs('mgpg_title_tabs');
    945        
     1384
    9461385        // Normal Tab
    9471386        $this->start_controls_tab(
     
    9511390            ]
    9521391        );
    953        
     1392
    9541393        $this->add_responsive_control(
    9551394            'mgpg_title_padding',
     
    9631402            ]
    9641403        );
    965        
     1404
    9661405        $this->add_responsive_control(
    9671406            'mgpg_title_margin',
     
    9751414            ]
    9761415        );
    977        
     1416
    9781417        $this->add_control(
    9791418            'mgpg_title_color',
     
    9861425            ]
    9871426        );
    988        
     1427
    9891428        $this->add_control(
    9901429            'mgpg_title_bgcolor',
     
    9971436            ]
    9981437        );
    999        
     1438
    10001439        $this->add_control(
    10011440            'mgpg_descb_radius',
     
    10091448            ]
    10101449        );
    1011        
     1450
    10121451        $this->add_group_control(
    10131452            \Elementor\Group_Control_Typography::get_type(),
     
    10181457            ]
    10191458        );
    1020        
     1459
    10211460        $this->end_controls_tab();
    1022        
     1461
    10231462        // Hover Tab
    10241463        $this->start_controls_tab(
     
    10281467            ]
    10291468        );
    1030        
     1469
    10311470        $this->add_control(
    10321471            'mgpg_hover_transition',
     
    10571496            ]
    10581497        );
    1059        
     1498
    10601499        $this->add_control(
    10611500            'mgpg_title_hover_bgcolor',
     
    10681507            ]
    10691508        );
    1070        
     1509
    10711510        $this->add_control(
    10721511            'mgpg_descb_hover_radius',
     
    10801519            ]
    10811520        );
    1082        
    1083         $this->end_controls_tab(); 
     1521
     1522        $this->end_controls_tab();
    10841523        $this->end_controls_tabs();
    10851524        $this->end_controls_section();
    1086        
     1525
    10871526
    10881527        $this->start_controls_section(
     
    10931532            ]
    10941533        );
    1095        
     1534
    10961535        $this->start_controls_tabs('mgpg_description_tabs');
    1097        
     1536
    10981537        // Normal Tab
    10991538        $this->start_controls_tab(
     
    11031542            ]
    11041543        );
    1105        
     1544
    11061545        $this->add_responsive_control(
    11071546            'mgpg_description_padding',
     
    11151554            ]
    11161555        );
    1117        
     1556
    11181557        $this->add_responsive_control(
    11191558            'mgpg_description_margin',
     
    11271566            ]
    11281567        );
    1129        
     1568
    11301569        $this->add_control(
    11311570            'mgpg_description_color',
     
    11381577            ]
    11391578        );
    1140        
     1579
    11411580        $this->add_control(
    11421581            'mgpg_description_bgcolor',
     
    11491588            ]
    11501589        );
    1151        
     1590
    11521591        $this->add_control(
    11531592            'mgpg_description_radius',
     
    11611600            ]
    11621601        );
    1163        
     1602
    11641603        $this->end_controls_tab(); // End of Normal Tab
    1165        
     1604
    11661605        // Hover Tab
    11671606        $this->start_controls_tab(
     
    11711610            ]
    11721611        );
    1173        
     1612
    11741613        $this->add_control(
    11751614            'mgpg_description_hover_color',
     
    11821621            ]
    11831622        );
    1184        
     1623
    11851624        $this->add_control(
    11861625            'mgpg_description_hover_bgcolor',
     
    11931632            ]
    11941633        );
    1195        
     1634
    11961635        $this->add_control(
    11971636            'mgpg_des_hover_transition',
     
    12111650            ]
    12121651        );
    1213        
     1652
    12141653        $this->end_controls_tab(); // End of Hover Tab
    1215        
     1654
    12161655        $this->end_controls_tabs();
    1217        
     1656
    12181657        $this->add_group_control(
    12191658            \Elementor\Group_Control_Typography::get_type(),
     
    12241663            ]
    12251664        );
    1226        
     1665
    12271666        $this->end_controls_section();
    1228        
     1667
    12291668        $this->start_controls_section(
    12301669            'mgpg_meta_style',
     
    12461685            ]
    12471686        );
    1248        
     1687
    12491688        $this->start_controls_tabs('mgpg_meta_cat_tabs');
    1250        
     1689
    12511690        // Normal Tab
    12521691        $this->start_controls_tab(
     
    12561695            ]
    12571696        );
    1258        
     1697
    12591698        $this->add_control(
    12601699            'mgpg_meta_cat_text_color',
     
    12671706            ]
    12681707        );
    1269        
     1708
    12701709        $this->add_control(
    12711710            'mgpg_meta_cat_bg_color',
     
    12781717            ]
    12791718        );
    1280        
     1719
    12811720        $this->add_responsive_control(
    12821721            'mgpg_meta_cat_margin',
     
    12891728            ]
    12901729        );
    1291        
     1730
    12921731        $this->add_responsive_control(
    12931732            'mgpg_meta_cat_padding',
     
    13001739            ]
    13011740        );
    1302        
     1741
    13031742        $this->add_control(
    13041743            'mgpg_meta_cat_border_radius',
     
    13211760            ]
    13221761        );
    1323        
     1762
    13241763        $this->add_group_control(
    13251764            \Elementor\Group_Control_Box_Shadow::get_type(),
     
    13301769            ]
    13311770        );
    1332        
     1771
    13331772        $this->end_controls_tab(); // End Normal Tab
    1334        
     1773
    13351774        // Hover Tab
    13361775        $this->start_controls_tab(
     
    13401779            ]
    13411780        );
    1342        
     1781
    13431782        $this->add_control(
    13441783            'mgpg_meta_cat_text_color_hover',
     
    13511790            ]
    13521791        );
    1353        
     1792
    13541793        $this->add_control(
    13551794            'mgpg_meta_cat_bg_color_hover',
     
    13621801            ]
    13631802        );
    1364        
     1803
    13651804        $this->add_group_control(
    13661805            \Elementor\Group_Control_Border::get_type(),
     
    13711810            ]
    13721811        );
    1373        
     1812
    13741813        $this->add_group_control(
    13751814            \Elementor\Group_Control_Box_Shadow::get_type(),
     
    13801819            ]
    13811820        );
    1382        
     1821
    13831822        $this->end_controls_tab(); // End Hover Tab
    1384        
     1823
    13851824        $this->end_controls_tabs(); // End Tabs
    1386        
     1825
    13871826        $this->add_group_control(
    13881827            \Elementor\Group_Control_Typography::get_type(),
     
    14341873            ]
    14351874        );
    1436        
     1875
    14371876        $this->add_control(
    14381877            'mgpg_author_style_section',
     
    14421881                'separator' => 'before',
    14431882                'condition' => [
    1444                             'mgpg_author_show' => 'yes',
    1445                 ],
    1446             ]
    1447         );
    1448 
    1449        
     1883                    'mgpg_author_show' => 'yes',
     1884                ],
     1885            ]
     1886        );
     1887
     1888
    14501889        $this->start_controls_tabs('mgpg_author_tabs');
    1451        
     1890
    14521891        // Normal Tab
    14531892        $this->start_controls_tab(
     
    14571896            ]
    14581897        );
    1459        
     1898
    14601899        $this->add_group_control(
    14611900            \Elementor\Group_Control_Typography::get_type(),
     
    14961935            ]
    14971936        );
    1498        
     1937
    14991938        $this->add_control(
    15001939            'mgpg_author_background_color',
     
    15071946            ]
    15081947        );
    1509        
     1948
    15101949        $this->add_group_control(
    15111950            \Elementor\Group_Control_Border::get_type(),
     
    15161955            ]
    15171956        );
    1518        
     1957
    15191958        $this->add_responsive_control(
    15201959            'mgpg_author_margin',
     
    15271966            ]
    15281967        );
    1529        
     1968
    15301969        $this->add_responsive_control(
    15311970            'mgpg_author_padding',
     
    15381977            ]
    15391978        );
    1540        
     1979
    15411980        $this->end_controls_tab();
    1542        
     1981
    15431982        // Hover Tab
    15441983        $this->start_controls_tab(
     
    15481987            ]
    15491988        );
    1550        
     1989
    15511990        $this->add_control(
    15521991            'mgpg_author_hover_text_color',
     
    15591998            ]
    15601999        );
    1561        
     2000
    15622001        $this->add_control(
    15632002            'mgpg_author_hover_background_color',
     
    15702009            ]
    15712010        );
    1572        
     2011
    15732012        $this->add_group_control(
    15742013            \Elementor\Group_Control_Box_Shadow::get_type(),
     
    15792018            ]
    15802019        );
    1581        
     2020
    15822021        $this->add_control(
    15832022            'mgpg_author_transition_duration',
     
    15972036            ]
    15982037        );
    1599        
     2038
    16002039        $this->end_controls_tab();
    1601        
     2040
    16022041        $this->end_controls_tabs();
    1603        
    1604 
    1605        
     2042
     2043
     2044
    16062045        $this->add_control(
    16072046            'mgpg_meta_date',
     
    16212060            'label' => __('Normal', 'magical-posts-display'),
    16222061        ]);
    1623        
     2062
    16242063        $this->add_control(
    16252064            'mgpg_meta_date_color',
     
    16322071            ]
    16332072        );
    1634        
     2073
    16352074        $this->add_control(
    16362075            'mgpg_meta_date_background_color',
     
    16432082            ]
    16442083        );
    1645        
     2084
    16462085        $this->add_responsive_control(
    16472086            'mgpg_meta_date_margin',
     
    16542093            ]
    16552094        );
    1656        
     2095
    16572096        $this->add_responsive_control(
    16582097            'mgpg_meta_date_padding',
     
    16652104            ]
    16662105        );
    1667        
     2106
    16682107        $this->add_group_control(
    16692108            \Elementor\Group_Control_Border::get_type(),
     
    16732112            ]
    16742113        );
    1675        
     2114
    16762115        $this->add_group_control(
    16772116            \Elementor\Group_Control_Box_Shadow::get_type(),
     
    16812120            ]
    16822121        );
    1683        
     2122
    16842123        $this->end_controls_tab();
    1685        
     2124
    16862125        // Hover Tab
    16872126        $this->start_controls_tab('mgpg_meta_date_hover', [
    16882127            'label' => __('Hover', 'magical-posts-display'),
    16892128        ]);
    1690        
     2129
    16912130        $this->add_control(
    16922131            'mgpg_meta_date_hover_color',
     
    16992138            ]
    17002139        );
    1701        
     2140
    17022141        $this->add_control(
    17032142            'mgpg_meta_date_hover_background_color',
     
    17102149            ]
    17112150        );
    1712        
     2151
    17132152        $this->add_group_control(
    17142153            \Elementor\Group_Control_Border::get_type(),
     
    17182157            ]
    17192158        );
    1720        
     2159
    17212160        $this->add_group_control(
    17222161            \Elementor\Group_Control_Box_Shadow::get_type(),
     
    17262165            ]
    17272166        );
    1728        
     2167
    17292168        $this->add_control(
    17302169            'mgpg_meta_date_transition',
     
    17452184            ]
    17462185        );
    1747        
     2186
    17482187        $this->end_controls_tab();
    17492188        $this->end_controls_tabs();
    1750        
     2189
    17512190        $this->add_group_control(
    17522191            \Elementor\Group_Control_Typography::get_type(),
     
    17572196            ]
    17582197        );
    1759        
    1760        
     2198
     2199
    17612200        $this->add_responsive_control(
    17622201            'mgpg_meta_date_icon_size',
     
    17762215                ],
    17772216            ]
    1778         ); 
     2217        );
    17792218
    17802219        $this->add_control(
     
    17962235            'label' => __('Normal', 'magical-posts-display'),
    17972236        ]);
    1798        
     2237
    17992238        $this->add_control(
    18002239            'mgpg_meta_tag_color',
     
    18082247            ]
    18092248        );
    1810        
     2249
    18112250        $this->add_control(
    18122251            'mgpg_meta_tag_background_color',
     
    18192258            ]
    18202259        );
    1821        
     2260
    18222261        $this->add_responsive_control(
    18232262            'mgpg_meta_tag_margin',
     
    18312270            ]
    18322271        );
    1833        
     2272
    18342273        $this->add_responsive_control(
    18352274            'mgpg_meta_tag_padding',
     
    18432282            ]
    18442283        );
    1845        
     2284
    18462285        $this->add_group_control(
    18472286            \Elementor\Group_Control_Border::get_type(),
     
    18512290            ]
    18522291        );
    1853        
     2292
    18542293        $this->add_group_control(
    18552294            \Elementor\Group_Control_Box_Shadow::get_type(),
     
    18592298            ]
    18602299        );
    1861        
     2300
    18622301        $this->end_controls_tab();
    1863        
     2302
    18642303        // Hover Tab
    18652304        $this->start_controls_tab('mgpg_meta_tag_hover', [
    18662305            'label' => __('Hover', 'magical-posts-display'),
    18672306        ]);
    1868        
     2307
    18692308        $this->add_control(
    18702309            'mgpg_meta_tag_hover_color',
     
    18782317            ]
    18792318        );
    1880        
     2319
    18812320        $this->add_control(
    18822321            'mgpg_meta_tag_hover_background_color',
     
    18892328            ]
    18902329        );
    1891        
     2330
    18922331        $this->add_group_control(
    18932332            \Elementor\Group_Control_Border::get_type(),
     
    18972336            ]
    18982337        );
    1899        
     2338
    19002339        $this->add_group_control(
    19012340            \Elementor\Group_Control_Box_Shadow::get_type(),
     
    19052344            ]
    19062345        );
    1907        
     2346
    19082347        $this->add_control(
    19092348            'mgpg_meta_tag_transition',
     
    19242363            ]
    19252364        );
    1926        
     2365
    19272366        $this->end_controls_tab();
    19282367        $this->end_controls_tabs();
     
    19632402                ],
    19642403            ]
    1965         ); 
     2404        );
    19662405
    19672406        $this->end_controls_section();
     
    20162455            ]
    20172456        );
    2018  
     2457
    20192458        $this->add_group_control(
    20202459            \Elementor\Group_Control_Typography::get_type(),
     
    23782817        $this->end_controls_tabs();
    23792818        $this->end_controls_section();
     2819
     2820        // Premium Features Style Section
     2821        $this->start_controls_section(
     2822            'mgpg_premium_style',
     2823            [
     2824                'label' => sprintf('%s %s', __('✨ Premium Features Style', 'magical-posts-display'), mp_display__pro_only_text()),
     2825                'tab' => \Elementor\Controls_Manager::TAB_STYLE,
     2826            ]
     2827        );
     2828
     2829        if (empty(mp_display_check_main_ok())) {
     2830            $this->add_control(
     2831                'mgpg_premium_style_info',
     2832                [
     2833                    'label' => sprintf('<span style="color:red">%s</span>', __('Premium features styling only works with pro version.', 'magical-posts-display')),
     2834                    'type' => \Elementor\Controls_Manager::HEADING,
     2835                    'separator' => 'before',
     2836                ]
     2837            );
     2838        }
     2839
     2840        // Reading Time Style
     2841        $this->add_control(
     2842            'mgpg_reading_time_heading',
     2843            [
     2844                'label' => __('Reading Time', 'magical-posts-display'),
     2845                'type' => \Elementor\Controls_Manager::HEADING,
     2846                'separator' => 'before',
     2847            ]
     2848        );
     2849
     2850        $this->add_control(
     2851            'mgpg_reading_time_color',
     2852            [
     2853                'label' => __('Text Color', 'magical-posts-display'),
     2854                'type' => \Elementor\Controls_Manager::COLOR,
     2855                'selectors' => [
     2856                    '{{WRAPPER}} .mgpd-reading-time' => 'color: {{VALUE}};',
     2857                ],
     2858            ]
     2859        );
     2860
     2861        $this->add_control(
     2862            'mgpg_reading_time_bg',
     2863            [
     2864                'label' => __('Background Color', 'magical-posts-display'),
     2865                'type' => \Elementor\Controls_Manager::COLOR,
     2866                'selectors' => [
     2867                    '{{WRAPPER}} .mgpd-reading-time' => 'background-color: {{VALUE}};',
     2868                ],
     2869            ]
     2870        );
     2871
     2872        $this->add_group_control(
     2873            \Elementor\Group_Control_Typography::get_type(),
     2874            [
     2875                'name' => 'mgpg_reading_time_typography',
     2876                'label' => __('Typography', 'magical-posts-display'),
     2877                'selector' => '{{WRAPPER}} .mgpd-reading-time',
     2878            ]
     2879        );
     2880
     2881        $this->add_responsive_control(
     2882            'mgpg_reading_time_padding',
     2883            [
     2884                'label' => __('Padding', 'magical-posts-display'),
     2885                'type' => \Elementor\Controls_Manager::DIMENSIONS,
     2886                'size_units' => ['px', 'em', '%'],
     2887                'selectors' => [
     2888                    '{{WRAPPER}} .mgpd-reading-time' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
     2889                ],
     2890            ]
     2891        );
     2892
     2893        $this->add_responsive_control(
     2894            'mgpg_reading_time_margin',
     2895            [
     2896                'label' => __('Margin', 'magical-posts-display'),
     2897                'type' => \Elementor\Controls_Manager::DIMENSIONS,
     2898                'size_units' => ['px', 'em', '%'],
     2899                'selectors' => [
     2900                    '{{WRAPPER}} .mgpd-reading-time' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
     2901                ],
     2902            ]
     2903        );
     2904
     2905        $this->add_responsive_control(
     2906            'mgpg_reading_time_border_radius',
     2907            [
     2908                'label' => __('Border Radius', 'magical-posts-display'),
     2909                'type' => \Elementor\Controls_Manager::DIMENSIONS,
     2910                'size_units' => ['px', '%'],
     2911                'selectors' => [
     2912                    '{{WRAPPER}} .mgpd-reading-time' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
     2913                ],
     2914            ]
     2915        );
     2916
     2917        // View Count Style
     2918        $this->add_control(
     2919            'mgpg_view_count_heading',
     2920            [
     2921                'label' => __('View Count', 'magical-posts-display'),
     2922                'type' => \Elementor\Controls_Manager::HEADING,
     2923                'separator' => 'before',
     2924            ]
     2925        );
     2926
     2927        $this->add_control(
     2928            'mgpg_view_count_color',
     2929            [
     2930                'label' => __('Text Color', 'magical-posts-display'),
     2931                'type' => \Elementor\Controls_Manager::COLOR,
     2932                'selectors' => [
     2933                    '{{WRAPPER}} .mgpd-view-count' => 'color: {{VALUE}};',
     2934                ],
     2935            ]
     2936        );
     2937
     2938        $this->add_control(
     2939            'mgpg_view_count_bg',
     2940            [
     2941                'label' => __('Background Color', 'magical-posts-display'),
     2942                'type' => \Elementor\Controls_Manager::COLOR,
     2943                'selectors' => [
     2944                    '{{WRAPPER}} .mgpd-view-count' => 'background-color: {{VALUE}};',
     2945                ],
     2946            ]
     2947        );
     2948
     2949        $this->add_group_control(
     2950            \Elementor\Group_Control_Typography::get_type(),
     2951            [
     2952                'name' => 'mgpg_view_count_typography',
     2953                'label' => __('Typography', 'magical-posts-display'),
     2954                'selector' => '{{WRAPPER}} .mgpd-view-count',
     2955            ]
     2956        );
     2957
     2958        $this->add_responsive_control(
     2959            'mgpg_view_count_padding',
     2960            [
     2961                'label' => __('Padding', 'magical-posts-display'),
     2962                'type' => \Elementor\Controls_Manager::DIMENSIONS,
     2963                'size_units' => ['px', 'em', '%'],
     2964                'selectors' => [
     2965                    '{{WRAPPER}} .mgpd-view-count' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
     2966                ],
     2967            ]
     2968        );
     2969
     2970        $this->add_responsive_control(
     2971            'mgpg_view_count_margin',
     2972            [
     2973                'label' => __('Margin', 'magical-posts-display'),
     2974                'type' => \Elementor\Controls_Manager::DIMENSIONS,
     2975                'size_units' => ['px', 'em', '%'],
     2976                'selectors' => [
     2977                    '{{WRAPPER}} .mgpd-view-count' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
     2978                ],
     2979            ]
     2980        );
     2981
     2982        $this->add_responsive_control(
     2983            'mgpg_view_count_border_radius',
     2984            [
     2985                'label' => __('Border Radius', 'magical-posts-display'),
     2986                'type' => \Elementor\Controls_Manager::DIMENSIONS,
     2987                'size_units' => ['px', '%'],
     2988                'selectors' => [
     2989                    '{{WRAPPER}} .mgpd-view-count' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
     2990                ],
     2991            ]
     2992        );
     2993
     2994        // Social Share Buttons Style
     2995        $this->add_control(
     2996            'mgpg_social_share_heading',
     2997            [
     2998                'label' => __('Social Share Buttons', 'magical-posts-display'),
     2999                'type' => \Elementor\Controls_Manager::HEADING,
     3000                'separator' => 'before',
     3001            ]
     3002        );
     3003
     3004        $this->add_responsive_control(
     3005            'mgpg_social_share_size',
     3006            [
     3007                'label' => __('Button Size', 'magical-posts-display'),
     3008                'type' => \Elementor\Controls_Manager::SLIDER,
     3009                'size_units' => ['px'],
     3010                'range' => [
     3011                    'px' => [
     3012                        'min' => 20,
     3013                        'max' => 60,
     3014                        'step' => 1,
     3015                    ],
     3016                ],
     3017                'default' => [
     3018                    'unit' => 'px',
     3019                    'size' => 32,
     3020                ],
     3021                'selectors' => [
     3022                    '{{WRAPPER}} .mgpd-social-share a' => 'width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}};',
     3023                ],
     3024            ]
     3025        );
     3026
     3027        $this->add_responsive_control(
     3028            'mgpg_social_share_gap',
     3029            [
     3030                'label' => __('Gap Between Buttons', 'magical-posts-display'),
     3031                'type' => \Elementor\Controls_Manager::SLIDER,
     3032                'size_units' => ['px'],
     3033                'range' => [
     3034                    'px' => [
     3035                        'min' => 0,
     3036                        'max' => 30,
     3037                        'step' => 1,
     3038                    ],
     3039                ],
     3040                'default' => [
     3041                    'unit' => 'px',
     3042                    'size' => 8,
     3043                ],
     3044                'selectors' => [
     3045                    '{{WRAPPER}} .mgpd-social-share' => 'gap: {{SIZE}}{{UNIT}};',
     3046                ],
     3047            ]
     3048        );
     3049
     3050        $this->add_responsive_control(
     3051            'mgpg_social_share_margin',
     3052            [
     3053                'label' => __('Margin', 'magical-posts-display'),
     3054                'type' => \Elementor\Controls_Manager::DIMENSIONS,
     3055                'size_units' => ['px', 'em', '%'],
     3056                'selectors' => [
     3057                    '{{WRAPPER}} .mgpd-social-share' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
     3058                ],
     3059            ]
     3060        );
     3061
     3062        // Social Button Colors with Tabs
     3063        $this->add_control(
     3064            'mgpg_social_colors_heading',
     3065            [
     3066                'label' => __('Individual Button Colors', 'magical-posts-display'),
     3067                'type' => \Elementor\Controls_Manager::HEADING,
     3068                'separator' => 'before',
     3069            ]
     3070        );
     3071
     3072        $this->start_controls_tabs('mgpg_social_colors_tabs');
     3073
     3074        // Normal State Tab
     3075        $this->start_controls_tab(
     3076            'mgpg_social_normal_tab',
     3077            [
     3078                'label' => __('Normal', 'magical-posts-display'),
     3079            ]
     3080        );
     3081
     3082        $this->add_control(
     3083            'mgpg_social_facebook_color',
     3084            [
     3085                'label' => __('Facebook', 'magical-posts-display'),
     3086                'type' => \Elementor\Controls_Manager::COLOR,
     3087                'selectors' => [
     3088                    '{{WRAPPER}} .mgpd-share-facebook' => 'background-color: {{VALUE}};',
     3089                ],
     3090            ]
     3091        );
     3092
     3093        $this->add_control(
     3094            'mgpg_social_twitter_color',
     3095            [
     3096                'label' => __('X (Twitter)', 'magical-posts-display'),
     3097                'type' => \Elementor\Controls_Manager::COLOR,
     3098                'selectors' => [
     3099                    '{{WRAPPER}} .mgpd-share-twitter' => 'background-color: {{VALUE}};',
     3100                ],
     3101            ]
     3102        );
     3103
     3104        $this->add_control(
     3105            'mgpg_social_linkedin_color',
     3106            [
     3107                'label' => __('LinkedIn', 'magical-posts-display'),
     3108                'type' => \Elementor\Controls_Manager::COLOR,
     3109                'selectors' => [
     3110                    '{{WRAPPER}} .mgpd-share-linkedin' => 'background-color: {{VALUE}};',
     3111                ],
     3112            ]
     3113        );
     3114
     3115        $this->add_control(
     3116            'mgpg_social_pinterest_color',
     3117            [
     3118                'label' => __('Pinterest', 'magical-posts-display'),
     3119                'type' => \Elementor\Controls_Manager::COLOR,
     3120                'selectors' => [
     3121                    '{{WRAPPER}} .mgpd-share-pinterest' => 'background-color: {{VALUE}};',
     3122                ],
     3123            ]
     3124        );
     3125
     3126        $this->add_control(
     3127            'mgpg_social_instagram_color',
     3128            [
     3129                'label' => __('Instagram', 'magical-posts-display'),
     3130                'type' => \Elementor\Controls_Manager::COLOR,
     3131                'selectors' => [
     3132                    '{{WRAPPER}} .mgpd-share-instagram' => 'background-color: {{VALUE}};',
     3133                ],
     3134            ]
     3135        );
     3136
     3137        $this->end_controls_tab();
     3138
     3139        // Hover State Tab
     3140        $this->start_controls_tab(
     3141            'mgpg_social_hover_tab',
     3142            [
     3143                'label' => __('Hover', 'magical-posts-display'),
     3144            ]
     3145        );
     3146
     3147        $this->add_control(
     3148            'mgpg_social_facebook_hover_color',
     3149            [
     3150                'label' => __('Facebook', 'magical-posts-display'),
     3151                'type' => \Elementor\Controls_Manager::COLOR,
     3152                'selectors' => [
     3153                    '{{WRAPPER}} .mgpd-share-facebook:hover' => 'background-color: {{VALUE}};',
     3154                ],
     3155            ]
     3156        );
     3157
     3158        $this->add_control(
     3159            'mgpg_social_twitter_hover_color',
     3160            [
     3161                'label' => __('X (Twitter)', 'magical-posts-display'),
     3162                'type' => \Elementor\Controls_Manager::COLOR,
     3163                'selectors' => [
     3164                    '{{WRAPPER}} .mgpd-share-twitter:hover' => 'background-color: {{VALUE}};',
     3165                ],
     3166            ]
     3167        );
     3168
     3169        $this->add_control(
     3170            'mgpg_social_linkedin_hover_color',
     3171            [
     3172                'label' => __('LinkedIn', 'magical-posts-display'),
     3173                'type' => \Elementor\Controls_Manager::COLOR,
     3174                'selectors' => [
     3175                    '{{WRAPPER}} .mgpd-share-linkedin:hover' => 'background-color: {{VALUE}};',
     3176                ],
     3177            ]
     3178        );
     3179
     3180        $this->add_control(
     3181            'mgpg_social_pinterest_hover_color',
     3182            [
     3183                'label' => __('Pinterest', 'magical-posts-display'),
     3184                'type' => \Elementor\Controls_Manager::COLOR,
     3185                'selectors' => [
     3186                    '{{WRAPPER}} .mgpd-share-pinterest:hover' => 'background-color: {{VALUE}};',
     3187                ],
     3188            ]
     3189        );
     3190
     3191        $this->add_control(
     3192            'mgpg_social_instagram_hover_color',
     3193            [
     3194                'label' => __('Instagram', 'magical-posts-display'),
     3195                'type' => \Elementor\Controls_Manager::COLOR,
     3196                'selectors' => [
     3197                    '{{WRAPPER}} .mgpd-share-instagram:hover' => 'background-color: {{VALUE}};',
     3198                ],
     3199            ]
     3200        );
     3201
     3202        $this->end_controls_tab();
     3203        $this->end_controls_tabs();
     3204
     3205        // Hover Effects
     3206        $this->add_control(
     3207            'mgpg_social_hover_heading',
     3208            [
     3209                'label' => __('Hover Effects', 'magical-posts-display'),
     3210                'type' => \Elementor\Controls_Manager::HEADING,
     3211                'separator' => 'before',
     3212            ]
     3213        );
     3214
     3215        $this->add_control(
     3216            'mgpg_social_hover_scale',
     3217            [
     3218                'label' => __('Scale on Hover', 'magical-posts-display'),
     3219                'type' => \Elementor\Controls_Manager::SWITCHER,
     3220                'label_on' => __('Yes', 'magical-posts-display'),
     3221                'label_off' => __('No', 'magical-posts-display'),
     3222                'return_value' => 'yes',
     3223                'default' => 'yes',
     3224                'selectors' => [
     3225                    '{{WRAPPER}} .mgpd-social-share a:hover' => 'transform: scale(1.1);',
     3226                ],
     3227            ]
     3228        );
     3229
     3230        $this->add_control(
     3231            'mgpg_social_transition_speed',
     3232            [
     3233                'label' => __('Transition Speed (ms)', 'magical-posts-display'),
     3234                'type' => \Elementor\Controls_Manager::SLIDER,
     3235                'range' => [
     3236                    'px' => [
     3237                        'min' => 100,
     3238                        'max' => 1000,
     3239                        'step' => 50,
     3240                    ],
     3241                ],
     3242                'default' => [
     3243                    'size' => 300,
     3244                ],
     3245                'selectors' => [
     3246                    '{{WRAPPER}} .mgpd-social-share a' => 'transition: all {{SIZE}}ms ease;',
     3247                ],
     3248            ]
     3249        );
     3250
     3251        $this->end_controls_section();
     3252    }
     3253
     3254    /**
     3255     * Render premium features content
     3256     *
     3257     * @param string $reading_time Show reading time
     3258     * @param string $view_count Show view count
     3259     * @param string $social_share Show social share
     3260     */
     3261    private function render_premium_features_content($reading_time, $view_count, $social_share)
     3262    {
     3263
     3264        if ($reading_time || $view_count) {
     3265            echo '<div class="mgpd-time-count-wrap">';
     3266            // Reading Time Display
     3267            if ($reading_time) {
     3268                $content = get_the_content();
     3269                $word_count = str_word_count(wp_strip_all_tags($content));
     3270                $reading_time_value = ceil($word_count / 200); // Average reading speed: 200 words per minute
     3271                echo '<div class="mgpd-reading-time">' . $this->get_reading_time_icon(16) . ' ' . $reading_time_value . ' min read</div>';
     3272            }
     3273
     3274            // Post Views Counter
     3275            if ($view_count) {
     3276                $post_views = get_post_meta(get_the_ID(), 'mp_post_post_viewed', true);
     3277                $post_views = $post_views ? $post_views : 0;
     3278                echo '<div class="mgpd-view-count">' . $this->get_view_count_icon(16) . ' ' . number_format($post_views) . ' views</div>';
     3279            }
     3280            echo '</div>';
     3281        }
     3282        // Social Share Buttons
     3283        if ($social_share) {
     3284            $post_url = get_permalink();
     3285            $post_title = get_the_title();
     3286            echo '<div class="mgpd-social-share">';
     3287            echo $this->get_all_social_share_buttons($post_url, $post_title, null, 20);
     3288            echo '</div>';
     3289        }
     3290    }
     3291
     3292    /**
     3293     * Render single post item
     3294     * Reusable method for both normal render and AJAX responses
     3295     *
     3296     * @param array $settings Widget settings
     3297     * @param string $item_class CSS classes for the item wrapper
     3298     */
     3299    private function render_single_post_item($settings, $item_class = '')
     3300    {
     3301        $mgpg_post_style = $settings['mgpg_post_style'];
     3302        $mgpg_post_type = $settings['mgpg_post_type'];
     3303        $mgpg_post_img_show = $settings['mgpg_post_img_show'];
     3304        $mgpg_media_source = $settings['mgpg_media_source'] ?? 'featured';
     3305        $mgpg_premium_features_style = $settings['mgpg_premium_features_style'] ?? 'default';
     3306        $mgpg_show_title = $settings['mgpg_show_title'];
     3307        $mgpg_title_tag = $settings['mgpg_title_tag'];
     3308        $mgpg_crop_title = $settings['mgpg_crop_title'];
     3309        $mgpg_desc_show = $settings['mgpg_desc_show'];
     3310        $mgpg_crop_desc = $settings['mgpg_crop_desc'];
     3311        $mgpg_post_btn = $settings['mgpg_post_btn'];
     3312        $mgpg_btn_title = $settings['mgpg_btn_title'];
     3313        $mgpg_usebtn_icon = $settings['mgpg_usebtn_icon'];
     3314        $mgpg_btn_icon_position = $settings['mgpg_btn_icon_position'] ?? 'right';
     3315        $mgpg_btn_target = $settings['mgpg_btn_target'];
     3316        $mgpg_reading_time = $settings['mgpg_reading_time'] ?? false;
     3317        $mgpg_view_count = $settings['mgpg_view_count'] ?? false;
     3318        $mgpg_social_share = $settings['mgpg_social_share'] ?? false;
     3319?>
     3320        <div class="<?php echo esc_attr($item_class); ?>">
     3321            <div class="card mg-card mg-shadow mgp-card mb-4">
     3322                <?php
     3323                if ($mgpg_post_img_show) {
     3324                    echo '<div class="mp-post-img">';
     3325
     3326                    // Check if using advanced media source (Pro Only)
     3327                    if (mp_display_check_main_ok() && $mgpg_media_source && $mgpg_media_source !== 'featured') {
     3328                        $media_settings = array(
     3329                            'mgpg_media_source' => $mgpg_media_source,
     3330                            'mgpg_media_priority' => $settings['mgpg_media_priority'] ?? array('video', 'featured', 'content', 'placeholder'),
     3331                            'mgpg_video_play_icon' => $settings['mgpg_video_play_icon'] ?? 'yes'
     3332                        );
     3333                        echo $this->get_advanced_media(get_the_ID(), $media_settings);
     3334                    } else {
     3335                        // Use default featured image
     3336                        mp_post_thumbnail($mgpg_post_img_show);
     3337                    }
     3338
     3339                    // Premium features - Image Top style
     3340                    if (mp_display_check_main_ok() && $mgpg_premium_features_style === 'image-top') {
     3341                        echo '<div class="mgpd-premium-features">';
     3342                        $this->render_premium_features_content($mgpg_reading_time, $mgpg_view_count, $mgpg_social_share);
     3343                        echo '</div>';
     3344                    }
     3345
     3346                    // Premium features - Image Overlay style
     3347                    if (mp_display_check_main_ok() && $mgpg_premium_features_style === 'image-overlay') {
     3348                        echo '<div class="mgpd-premium-features">';
     3349                        $this->render_premium_features_content($mgpg_reading_time, $mgpg_view_count, $mgpg_social_share);
     3350                        echo '</div>';
     3351                    }
     3352
     3353                    echo '</div>';
     3354                }
     3355                ?>
     3356                <div class="mg-card-text card-body">
     3357                    <?php
     3358                    if ($mgpg_post_style == '3') {
     3359                    ?>
     3360                        <div class="magical-post-authon-category">
     3361                            <?php
     3362                            mpd_posts_meta($settings['mgpg_author_show']);
     3363                            mp_post_cat_display($settings['mgpg_category_show']);
     3364                            ?>
     3365                        </div>
     3366                    <?php
     3367                    }
     3368                    if ($mgpg_post_type == 'post' && ($mgpg_post_style == '1' || $mgpg_post_style == '2')) {
     3369                        mp_post_cat_display($settings['mgpg_category_show'], $settings['mgpg_cat_type'] ?? 'one', ', ');
     3370                    }
     3371                    ?>
     3372                    <?php
     3373                    mp_post_title($mgpg_show_title, $mgpg_title_tag, $mgpg_crop_title);
     3374                    ?>
     3375                    <?php
     3376                    if ($mgpg_post_style == '1') {
     3377                        mpd_posts_meta($settings['mgpg_author_show'], $settings['mgpg_date_show'], $settings['mgpg_comment_icon_show']);
     3378                    }
     3379                    ?>
     3380                    <?php if ($mgpg_desc_show) : ?>
     3381                        <p><?php
     3382                            if (has_excerpt()) {
     3383                                echo esc_html(wp_trim_words(get_the_excerpt(), $mgpg_crop_desc, '...'));
     3384                            } else {
     3385                                echo esc_html(wp_trim_words(get_the_content(), $mgpg_crop_desc, '...'));
     3386                            }
     3387                            ?>
     3388                        </p>
     3389                    <?php endif; ?>
     3390
     3391                    <?php
     3392                    // Premium Features Content (Pro Only) - Only show in default position
     3393                    if (mp_display_check_main_ok() && (!$mgpg_premium_features_style || $mgpg_premium_features_style === 'default')) {
     3394                        $this->render_premium_features_content($mgpg_reading_time, $mgpg_view_count, $mgpg_social_share);
     3395                    }
     3396                    ?>
     3397
     3398                    <?php
     3399                    if ($mgpg_post_style == '3') {
     3400                    ?>
     3401                        <div class="mgp_there_style-time">
     3402                            <span>
     3403                                <i class="fa-regular fa-calendar-days"></i>
     3404                                <?php echo esc_html(get_the_date('d M Y')); ?>
     3405                            </span>
     3406                            <?php
     3407                            if ($mgpg_post_btn && ($mgpg_post_style == '3')) {
     3408                                mp_post_btn(
     3409                                    $text = $mgpg_btn_title,
     3410                                    $icon_show = $mgpg_usebtn_icon,
     3411                                    $icon = $settings['mgpg_btn_icon'],
     3412                                    $icon_position = $mgpg_btn_icon_position,
     3413                                    $target = $mgpg_btn_target,
     3414                                    $class = $settings['mgpg_link_type'] ?? ''
     3415                                );
     3416                            }
     3417                            ?>
     3418                        </div>
     3419                    <?php
     3420                    }
     3421                    if ($mgpg_post_btn && ($mgpg_post_style == '1' || $mgpg_post_style == '2')) {
     3422                        mp_post_btn(
     3423                            $text = $mgpg_btn_title,
     3424                            $icon_show = $mgpg_usebtn_icon,
     3425                            $icon = $settings['mgpg_btn_icon'],
     3426                            $icon_position = $mgpg_btn_icon_position,
     3427                            $target = $mgpg_btn_target,
     3428                            $class = $settings['mgpg_link_type'] ?? ''
     3429                        );
     3430                    }
     3431
     3432                    if ($mgpg_post_style == '2') {
     3433                        mpd_posts_meta_author_date($settings['mgpg_author_show'], $settings['mgpg_date_show']);
     3434                    }
     3435
     3436                    mpd_post_tags($settings['mgpg_tag_show']);
     3437
     3438                    ?>
     3439                </div>
     3440
     3441            </div>
     3442        </div>
     3443        <?php
    23803444    }
    23813445
     
    24813545
    24823546        //grid layout
     3547        $mgpg_layout_type = $this->get_settings('mgpg_layout_type');
     3548        $mgpg_masonry_style = $this->get_settings('mgpg_masonry_style');
    24833549        $mgpg_post_style = $this->get_settings('mgpg_post_style');
    24843550        $mgpg_rownumber = $this->get_settings('mgpg_rownumber');
     
    24963562        $mgpg_btn_target = $this->get_settings('mgpg_btn_target');
    24973563        $mgpg_btn_icon = $this->get_settings('mgpg_btn_icon');
     3564
     3565        // Premium Features Settings (Pro Only)
     3566        $mgpg_ajax_filter = $this->get_settings('mgpg_ajax_filter');
     3567        $mgpg_infinite_scroll = $this->get_settings('mgpg_infinite_scroll');
     3568        $mgpg_reading_time = $this->get_settings('mgpg_reading_time');
     3569        $mgpg_view_count = $this->get_settings('mgpg_view_count');
     3570        $mgpg_social_share = $this->get_settings('mgpg_social_share');
     3571        $mgpg_hover_effects = $this->get_settings('mgpg_hover_effects');
     3572        $mgpg_premium_features_style = $this->get_settings('mgpg_premium_features_style');
     3573        $mgpg_media_source = $this->get_settings('mgpg_media_source');
    24983574        $mgpg_btn_icon_position = $this->get_settings('mgpg_btn_icon_position');
    24993575
     
    25093585                $column_set = 'col-lg-' . $mgpg_rownumber . ' col-md-6';
    25103586            }
    2511 ?>
    2512 <div id="mgp-items" class="mgpd mgp-items style<?php echo esc_attr($mgpg_post_style); ?>">
    2513     <div class="row" data-masonry='{"percentPosition": true }'>
    2514         <?php while ($mgpg_posts->have_posts()) : $mgpg_posts->the_post(); ?>
    2515         <div class="<?php echo esc_attr($column_set); ?>">
    2516             <div class="card mg-card mg-shadow mgp-card mb-4">
    2517                 <?php mp_post_thumbnail($mgpg_post_img_show); ?>
    2518                 <div class="mg-card-text card-body">
     3587
     3588            // Add masonry specific classes
     3589            $container_class = 'mgpd mgp-items style' . esc_attr($mgpg_post_style);
     3590            $row_class = 'row';
     3591            $item_class = $column_set;
     3592
     3593            // Add premium feature classes
     3594            if ($mgpg_ajax_filter && mp_display_check_main_ok()) {
     3595                $container_class .= ' mgpd-ajax-filter-enabled';
     3596            }
     3597            if ($mgpg_infinite_scroll && mp_display_check_main_ok()) {
     3598                $container_class .= ' mgpd-infinite-scroll';
     3599            }
     3600            if ($mgpg_hover_effects && $mgpg_hover_effects !== 'none' && mp_display_check_main_ok()) {
     3601                $container_class .= ' mgpd-hover-' . esc_attr($mgpg_hover_effects);
     3602            }
     3603            // Add premium features style class
     3604            if ($mgpg_premium_features_style && $mgpg_premium_features_style !== 'default' && mp_display_check_main_ok()) {
     3605                $container_class .= ' mgpd-premium-' . esc_attr($mgpg_premium_features_style);
     3606            }
     3607
     3608            if ($mgpg_layout_type === 'masonry') {
     3609                $masonry_style = $mgpg_masonry_style ? $mgpg_masonry_style : 'style1';
     3610                $container_class .= ' mgpd-masonry-container mgpd-masonry-' . esc_attr($masonry_style);
     3611                $row_class .= ' mgpd-masonry';
     3612                $item_class .= ' mgpd-masonry-item';
     3613            }
     3614        ?>
     3615
     3616            <?php
     3617            // Premium Features - Category Filter (Pro Only) - Move to top
     3618            if (mp_display_check_main_ok() && $mgpg_ajax_filter && $mgpg_post_type == 'post') {
     3619                $categories = get_categories(array('hide_empty' => true));
     3620                if (!empty($categories)) {
     3621                    echo '<div class="mgpd-ajax-filter-container">';
     3622                    echo '<div class="mgpd-filter-buttons">';
     3623                    echo '<button class="mgpd-filter-btn active" data-category="all">' . __('All', 'magical-posts-display') . '</button>';
     3624                    foreach ($categories as $category) {
     3625                        echo '<button class="mgpd-filter-btn" data-category="' . esc_attr($category->slug) . '">' . esc_html($category->name) . '</button>';
     3626                    }
     3627                    echo '</div>';
     3628                    echo '</div>';
     3629                }
     3630            }
     3631            ?>
     3632
     3633            <div id="mgp-items" class="<?php echo esc_attr($container_class); ?>">
     3634                <div class="<?php echo esc_attr($row_class); ?>">
     3635                    <?php while ($mgpg_posts->have_posts()) : $mgpg_posts->the_post(); ?>
     3636                        <?php $this->render_single_post_item($settings, $item_class); ?>
    25193637                    <?php
    2520                     if ($mgpg_post_style == '3') {
     3638                    endwhile;
     3639                    wp_reset_postdata();
     3640                    wp_reset_postdata();
    25213641                    ?>
    2522                     <div class="magical-post-authon-category">
    2523                         <?php                                             
    2524                         mpd_posts_meta($settings['mgpg_author_show']);
    2525                         mp_post_cat_display($settings['mgpg_category_show']);
    2526                     ?>
    2527                     </div>
    2528                     <?php
     3642                </div>
     3643            </div>
     3644
     3645            <?php
     3646            // Inline Masonry Initialization Script for better compatibility
     3647            if ($mgpg_layout_type === 'masonry') {
     3648                $widget_id = uniqid('mgpd_masonry_');
     3649            ?>
     3650                <script type="text/javascript">
     3651                    (function() {
     3652                        // Initialize masonry for this specific widget
     3653                        function initMasonry<?php echo $widget_id; ?>() {
     3654                            var container = document.querySelector('.mgpd-masonry-container');
     3655                            if (container && typeof Masonry !== 'undefined' && typeof imagesLoaded !== 'undefined') {
     3656                                var masonryGrid = container.querySelector('.mgpd-masonry');
     3657                                if (masonryGrid) {
     3658                                    // Force all images to load first
     3659                                    imagesLoaded(masonryGrid, function() {
     3660                                        // Clear any existing height to let masonry calculate properly
     3661                                        masonryGrid.style.height = '';
     3662
     3663                                        // Initialize masonry
     3664                                        var masonry = new Masonry(masonryGrid, {
     3665                                            itemSelector: '.mgpd-masonry-item',
     3666                                            columnWidth: '.mgpd-masonry-item',
     3667                                            percentPosition: true,
     3668                                            transitionDuration: 0
     3669                                        });
     3670
     3671                                        // Store instance for global access
     3672                                        window.mgpdMasonryInstance = masonry;
     3673
     3674                                        // Force layout calculation after a brief delay
     3675                                        setTimeout(function() {
     3676                                            masonry.layout();
     3677                                        }, 100);
     3678                                    });
     3679                                }
     3680                            }
    25293681                        }
    2530                             if ($mgpg_post_type == 'post' && ($mgpg_post_style == '1' || $mgpg_post_style == '2')) {
    2531                             mp_post_cat_display($settings['mgpg_category_show'], $settings['mgpg_cat_type'], ', ');
    2532                             }
    2533                         ?>
    2534                     <?php
    2535                         mp_post_title($mgpg_show_title, $mgpg_title_tag, $mgpg_crop_title);
    2536                         ?>
    2537                     <?php
    2538                         if ($mgpg_post_style == '1') {
    2539                             mpd_posts_meta($settings['mgpg_author_show'], $settings['mgpg_date_show'], $settings['mgpg_comment_icon_show']);
     3682
     3683                        // Initialize when DOM is ready
     3684                        if (document.readyState === 'loading') {
     3685                            document.addEventListener('DOMContentLoaded', initMasonry<?php echo $widget_id; ?>);
     3686                        } else {
     3687                            initMasonry<?php echo $widget_id; ?>();
    25403688                        }
    2541                     ?>
    2542                     <?php if ($mgpg_desc_show) : ?>
    2543                     <p><?php
    2544                         if (has_excerpt()) {
    2545                             echo esc_html(wp_trim_words(get_the_excerpt(), $mgpg_crop_desc, '...'));
    2546                         } else {
    2547                             echo esc_html(wp_trim_words(get_the_content(), $mgpg_crop_desc, '...'));
    2548                         }
    2549                         ?>
    2550                     </p>
    2551                     <?php endif; ?>
    2552                     <?php
    2553                         if ($mgpg_post_style == '3') {
    2554                         ?>
    2555                     <div class="mgp_there_style-time">
    2556                         <span>
    2557                             <i class="fa-regular fa-calendar-days"></i>
    2558                             <?php echo esc_html(get_the_date('d M Y')); ?>
    2559                         </span>
    2560                         <?php
    2561                                 if ($mgpg_post_btn && ($mgpg_post_style == '3')) {
    2562                                 mp_post_btn(
    2563                                     $text = $mgpg_btn_title,
    2564                                     $icon_show = $mgpg_usebtn_icon,
    2565                                     $icon = $settings['mgpg_btn_icon'],
    2566                                     $icon_position = $mgpg_btn_icon_position,
    2567                                     $target = $mgpg_btn_target,
    2568                                     $class = $settings['mgpg_link_type']
    2569                                 );
    2570                             }
    2571                             ?>
    2572                     </div>
    2573                     <?php
    2574                             }
    2575                             if ($mgpg_post_btn && ($mgpg_post_style == '1' || $mgpg_post_style == '2')) {
    2576                                 mp_post_btn(
    2577                                     $text = $mgpg_btn_title,
    2578                                     $icon_show = $mgpg_usebtn_icon,
    2579                                     $icon = $settings['mgpg_btn_icon'],
    2580                                     $icon_position = $mgpg_btn_icon_position,
    2581                                     $target = $mgpg_btn_target,
    2582                                     $class = $settings['mgpg_link_type']
    2583                                 );
    2584                             }
    2585 
    2586                         if ($mgpg_post_style == '2') {
    2587                             mpd_posts_meta_author_date($settings['mgpg_author_show'], $settings['mgpg_date_show']);
    2588                         }
    2589 
    2590                         mpd_post_tags($settings['mgpg_tag_show']);
    2591 
    2592                         ?>
    2593                 </div>
    2594 
    2595             </div>
    2596         </div>
    2597         <?php
    2598             endwhile;
    2599             wp_reset_query();
    2600             wp_reset_postdata();
     3689
     3690                        // Also initialize on window load as fallback
     3691                        window.addEventListener('load', initMasonry<?php echo $widget_id; ?>);
     3692                    })();
     3693                </script>
     3694            <?php
     3695            }
    26013696            ?>
    2602     </div>
    2603 </div>
    2604 
    2605 <?php
     3697
     3698            <?php
    26063699            if ($mgpg_pagination_show) {
    26073700                mp_display_pagination($paged, $mgpg_posts, $settings['mgpg_pagination_style']);
    26083701            }
    26093702            ?>
     3703
     3704            <?php
     3705            // Premium Features JavaScript & HTML (Pro Only)
     3706            if (mp_display_check_main_ok()) {
     3707
     3708                // Infinite Scroll Trigger
     3709                if ($mgpg_infinite_scroll) {
     3710                    echo '<div class="mgpd-infinite-scroll-trigger" style="height: 1px; margin-top: 50px;"></div>';
     3711                    echo '<div class="mgpd-loading-spinner" style="display: none; text-align: center; padding: 20px;">';
     3712                    echo $this->get_loading_spinner_icon(40);
     3713                    echo '<span>' . __('Loading more posts...', 'magical-posts-display') . '</span>';
     3714                    echo '</div>';
     3715                }
     3716
     3717                // Only localize script if any premium features are enabled
     3718                if ($mgpg_ajax_filter || $mgpg_infinite_scroll || ($mgpg_hover_effects && $mgpg_hover_effects !== 'none')) {
     3719                    // Localize script data for JavaScript
     3720                    wp_localize_script('mgpd-premium-features', 'mgpd_ajax', array(
     3721                        'ajaxurl' => admin_url('admin-ajax.php'),
     3722                        'nonce' => wp_create_nonce('mgpd_ajax_nonce'),
     3723                        'settings' => $settings,
     3724                        'layout_type' => $mgpg_layout_type,
     3725                        'ajax_filter_enabled' => $mgpg_ajax_filter && $mgpg_post_type == 'post',
     3726                        'infinite_scroll_enabled' => $mgpg_infinite_scroll,
     3727                        'hover_effects_enabled' => $mgpg_hover_effects && $mgpg_hover_effects !== 'none',
     3728                        'current_page' => $paged,
     3729                        'max_pages' => $mgpg_posts->max_num_pages,
     3730                        'post_type' => $mgpg_post_type,
     3731                        'texts' => array(
     3732                            'error_loading' => __('Error loading posts. Please try again.', 'magical-posts-display'),
     3733                            'loading_more' => __('Loading more posts...', 'magical-posts-display')
     3734                        )
     3735                    ));
     3736                }
     3737            }
     3738            ?>
     3739
    26103740<?php else :
    26113741            mp_display_posts_not_found($settings['mgpg_post_type']);
    26123742        endif;
    26133743    }
     3744
     3745    /**
     3746     * AJAX handler for category filtering
     3747     * Static method to be called from WordPress AJAX hooks
     3748     */
     3749    public static function ajax_filter_posts()
     3750    {
     3751        // Check nonce for security
     3752        if (!isset($_POST['nonce']) || !wp_verify_nonce(wp_unslash($_POST['nonce']), 'mgpd_ajax_nonce')) {
     3753            wp_die(__('Security check failed', 'magical-posts-display'));
     3754        }
     3755
     3756        // Check if pro version is active
     3757        if (!mp_display_check_main_ok()) {
     3758            wp_send_json_error(__('Premium feature requires pro version', 'magical-posts-display'));
     3759        }
     3760
     3761        $category = isset($_POST['category']) ? sanitize_text_field(wp_unslash($_POST['category'])) : '';
     3762        $settings = isset($_POST['settings']) ? wp_unslash($_POST['settings']) : array();
     3763        $post_type = isset($_POST['post_type']) ? sanitize_text_field(wp_unslash($_POST['post_type'])) : 'post';
     3764
     3765        // Build query args
     3766        $args = array(
     3767            'post_type' => $post_type,
     3768            'post_status' => 'publish',
     3769            'posts_per_page' => isset($settings['mgpg_posts_count']) ? absint($settings['mgpg_posts_count']) : 6,
     3770            'ignore_sticky_posts' => 1
     3771        );
     3772
     3773        // Add category filter if not "all"
     3774        if ($category !== 'all' && $post_type === 'post') {
     3775            $args['tax_query'] = array(
     3776                array(
     3777                    'taxonomy' => 'category',
     3778                    'field' => 'slug',
     3779                    'terms' => $category
     3780                )
     3781            );
     3782        }
     3783
     3784        $query = new WP_Query($args);
     3785        $output = '';
     3786
     3787        if ($query->have_posts()) {
     3788            // Instantiate widget to reuse render method
     3789            $widget = new self();
     3790
     3791            // Calculate item class - consistent with render() method
     3792            $mgpg_rownumber = isset($settings['mgpg_rownumber']) ? $settings['mgpg_rownumber'] : '4';
     3793            $mgpg_layout_type = isset($settings['mgpg_layout_type']) ? $settings['mgpg_layout_type'] : 'grid';
     3794
     3795            if ($mgpg_rownumber == '12') {
     3796                $item_class = 'col-lg-12';
     3797            } else {
     3798                $item_class = 'col-lg-' . $mgpg_rownumber . ' col-md-6';
     3799            }
     3800
     3801            if ($mgpg_layout_type === 'masonry') {
     3802                $item_class .= ' mgpd-masonry-item';
     3803            }
     3804
     3805            while ($query->have_posts()) {
     3806                $query->the_post();
     3807                ob_start();
     3808                $widget->render_single_post_item($settings, $item_class);
     3809                $output .= ob_get_clean();
     3810            }
     3811            wp_reset_postdata();
     3812        }
     3813
     3814        wp_send_json_success($output);
     3815    }
     3816
     3817    /**
     3818     * AJAX handler for infinite scroll
     3819     * Static method to be called from WordPress AJAX hooks
     3820     */
     3821    public static function ajax_infinite_scroll()
     3822    {
     3823        // Check nonce for security
     3824        if (!isset($_POST['nonce']) || !wp_verify_nonce(wp_unslash($_POST['nonce']), 'mgpd_ajax_nonce')) {
     3825            wp_die(__('Security check failed', 'magical-posts-display'));
     3826        }
     3827
     3828        // Check if pro version is active
     3829        if (!mp_display_check_main_ok()) {
     3830            wp_send_json_error(__('Premium feature requires pro version', 'magical-posts-display'));
     3831        }
     3832
     3833        $page = isset($_POST['page']) ? absint($_POST['page']) : 1;
     3834        $settings = isset($_POST['settings']) ? wp_unslash($_POST['settings']) : array();
     3835        $post_type = isset($_POST['post_type']) ? sanitize_text_field(wp_unslash($_POST['post_type'])) : 'post';
     3836
     3837        // Build query args
     3838        $args = array(
     3839            'post_type' => $post_type,
     3840            'post_status' => 'publish',
     3841            'posts_per_page' => isset($settings['mgpg_posts_count']) ? absint($settings['mgpg_posts_count']) : 6,
     3842            'paged' => $page,
     3843            'ignore_sticky_posts' => 1
     3844        );
     3845
     3846        $query = new WP_Query($args);
     3847        $output = '';
     3848
     3849        if ($query->have_posts()) {
     3850            // Instantiate widget
     3851            $widget = new self();
     3852
     3853            // Calculate item class - consistent with render() method
     3854            $mgpg_rownumber = isset($settings['mgpg_rownumber']) ? $settings['mgpg_rownumber'] : '4';
     3855            $mgpg_layout_type = isset($settings['mgpg_layout_type']) ? $settings['mgpg_layout_type'] : 'grid';
     3856
     3857            if ($mgpg_rownumber == '12') {
     3858                $item_class = 'col-lg-12';
     3859            } else {
     3860                $item_class = 'col-lg-' . $mgpg_rownumber . ' col-md-6';
     3861            }
     3862
     3863            if ($mgpg_layout_type === 'masonry') {
     3864                $item_class .= ' mgpd-masonry-item';
     3865            }
     3866
     3867            while ($query->have_posts()) {
     3868                $query->the_post();
     3869                ob_start();
     3870                $widget->render_single_post_item($settings, $item_class);
     3871                $output .= ob_get_clean();
     3872            }
     3873            wp_reset_postdata();
     3874        }
     3875        wp_send_json_success($output);
     3876    }
    26143877}
  • magical-posts-display/trunk/includes/elementor/widgets/posts-list.php

    r3116993 r3380394  
    18781878                    <?php
    18791879                    endwhile;
    1880                     wp_reset_query();
     1880                    wp_reset_postdata();
    18811881                    wp_reset_postdata();
    18821882                    ?>
  • magical-posts-display/trunk/includes/elementor/widgets/posts-slider.php

    r3324281 r3380394  
    17001700
    17011701                    endwhile;
    1702                     wp_reset_query();
     1702                    wp_reset_postdata();
    17031703                    wp_reset_postdata();
    17041704                    ?>
     
    17421742        $mgps_btn_target = $settings['mgps_btn_target'];
    17431743        $mgps_layout_style = $settings['mgps_layout_style'];
    1744        
     1744
    17451745        if ($mgps_layout_style === 'style_two') {
    17461746            $this->render_style_two($settings, $mgpslide_category, $mgps_post_btn, $mgps_btn_title, $mgps_usebtn_icon, $mgps_btn_icon_position, $mgps_btn_target);
     
    18001800            ?>
    18011801        </div>
    1802         <?php
     1802    <?php
    18031803    }
    18041804
    18051805    private function render_style_two($settings, $mgpslide_category, $mgps_post_btn, $mgps_btn_title, $mgps_usebtn_icon, $mgps_btn_icon_position, $mgps_btn_target)
    18061806    {
    1807         ?>
     1807    ?>
    18081808        <!-- Slides Style Two -->
    18091809        <div class="swiper-slide mgs-item mgs-item-style-two">
     
    18551855            </div>
    18561856        </div>
    1857         <?php
     1857<?php
    18581858    }
    18591859}
  • magical-posts-display/trunk/includes/elementor/widgets/posts-tab.php

    r3116993 r3380394  
    20942094                                                <?php
    20952095                                                endwhile;
    2096                                                 wp_reset_query();
     2096                                                wp_reset_postdata();
    20972097                                                wp_reset_postdata();
    20982098                                                ?>
  • magical-posts-display/trunk/includes/elementor/widgets/posts-ticker.php

    r3235168 r3380394  
    686686                        <?php
    687687                        endwhile;
    688                         wp_reset_query();
     688                        wp_reset_postdata();
    689689                        wp_reset_postdata();
    690690                        ?>
  • magical-posts-display/trunk/includes/mp-posts-function.php

    r3334686 r3380394  
    7878                <?php
    7979                // translators: %s: list of categories
    80                 $categories_text = sprintf(esc_html__('%s', 'magical-addons-for-elementor'), $mpg_cat_list);
     80                $categories_text = sprintf(esc_html__('%s', 'magical-posts-display'), $mpg_cat_list);
    8181                printf('<span class="mgp-post-cats">%s</span>', wp_kses_post($categories_text));
    8282                ?>
     
    154154
    155155
    156 function mpd_validate_html_tag($tag, $default_tag = 'h2', $allowed_tags = array()) {
     156function mpd_validate_html_tag($tag, $default_tag = 'h2', $allowed_tags = array())
     157{
    157158    // Use the provided whitelist or fall back to a predefined set of safe tags
    158159    $safe_tags = !empty($allowed_tags) ? $allowed_tags : array(
    159         'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'span', 'p'
     160        'h1',
     161        'h2',
     162        'h3',
     163        'h4',
     164        'h5',
     165        'h6',
     166        'div',
     167        'span',
     168        'p'
    160169    );
    161170
  • magical-posts-display/trunk/magical-posts-display.php

    r3334686 r3380394  
    11<?php
    2 /*
    3  * @link              http://wpthemespace.com
    4  * @since             1.0.0
    5  * @package           Magical Posts Display
     2
     3/**
     4 * Plugin Name: Magical Posts Display
     5 * Plugin URI: http://wpthemespace.com/magical-posts-display
     6 * Description: Show your site posts, Pages and Custom Post Types with many different styles by Elementor Widgets.
     7 * Version: 1.2.54
     8 * Author: Noor Alam
     9 * Author URI: http://wpthemespace.com
     10 * Text Domain: magical-posts-display
     11 * Domain Path: /languages
     12 * Requires at least: 6.0
     13 * Requires PHP: 7.4
     14 * License: GPL-2.0+
     15 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
    616 *
    7  * @wordpress-plugin
    8  * Plugin Name:       Magical Posts Display
    9  * Plugin URI:        http://wpthemespace.com
    10  * Description:       Show your site posts, Pages and Custom Post Types with many different styles by Elementor Widgets.
    11  * Version:           1.2.53
    12  * Author:            Noor alam
    13  * Author URI:        https://profiles.wordpress.org/nalam-1
    14  * License:           GPL-2.0+
    15  * License URI:       http://www.gnu.org/licenses/gpl-2.0.txt
    16  * Text Domain:       magical-posts-display
    17  * Domain Path:       /languages
     17 * @package magical-posts-display
    1818 */
    1919
     
    2121    exit; // Exit if accessed directly.
    2222}
     23
    2324
    2425/**
     
    3738         * @var string The plugin version.
    3839         */
    39         const version = '1.2.53';
     40        const version = '1.2.54';
    4041
    4142        /**
     
    4647         * @var string Minimum PHP version required to run the plugin.
    4748         */
    48         const MINIMUM_PHP_VERSION = '5.6';
    49 
    50 
     49        const MINIMUM_PHP_VERSION = '7.4';
    5150        /**
    5251         * Instance
     
    9695            add_action('plugins_loaded', [$this, 'init']);
    9796            add_filter('plugin_action_links_' . plugin_basename(__FILE__), [$this, 'admin_adminpro_link']);
    98             add_action('init', [$this, 'elementor_notice_hide_options']);
    9997            require_once('lib/custom-template/pagetemplater.php');
    10098            require_once('includes/elementor/extra.php');
    10199        }
    102100
    103         // After active go homepage
    104         /*
    105     public function mgpd_plugin_homego($plugin)
    106     {
    107         if (plugin_basename(__FILE__) == $plugin) {
    108             wp_redirect(admin_url('admin.php?page=mgpd-page'));
    109             die();
    110         }
    111     }
    112     */
     101        // After active go homepage - functionality removed
     102        // Was: mgpd_plugin_homego method for redirect after activation
    113103
    114104        public  function admin_adminpro_link($links)
    115105        {
    116             $newlink = sprintf("<a target='_blank' href='%s'><span style='color:red;font-weight:bold'>%s</span></a>", esc_url('https://wpthemespace.com/product/magical-posts-display-pro/?add-to-cart=8239'), __('Get Pro', 'optionsdemo'));
     106            $newlink = sprintf("<a target='_blank' href='%s'><span style='color:red;font-weight:bold'>%s</span></a>", esc_url('https://wpthemespace.com/product/magical-posts-display-pro/?add-to-cart=8239'), __('Get Pro', 'magical-posts-display'));
    117107            if (empty(mp_display_check_main_ok())) {
    118108                $links[] = $newlink;
     
    147137        public function init()
    148138        {
    149 
     139            // Include all plugin files
    150140            require_once('file-include.php');
    151141
    152             //  require_once( 'lib/carbon-fields/vendor/autoload.php' );
     142            // Initialize new user settings
    153143            $this->mgposts_new_user();
    154144
     145            // Handle Carbon Fields loading for older installations
    155146            $install_date = gmdate("Y-m-d", strtotime(get_option('mgposte_install_date', current_time('mysql', true))));
    156147            $compare_date = '2023-03-07';
     
    162153            }
    163154
    164 
    165 
    166155            // Check for required PHP version
    167156            if (version_compare(PHP_VERSION, self::MINIMUM_PHP_VERSION, '<')) {
    168                 add_action('admin_notices', [$this, 'admin_notice_minimum_php_version']);
    169                 return;
    170             }
    171             //
    172             add_action('admin_enqueue_scripts', [$this, 'mgpost_display_editor_scripts']);
    173             add_action('enqueue_block_assets', [$this, 'mgpblock_style']);
    174             add_action('enqueue_block_assets', [$this, 'mgpblock_scripts']);
    175             add_action('enqueue_block_editor_assets', [$this, 'mgpblock_editor_scripts']);
    176 
    177             // Add image size
    178             add_image_size('slider-bg', 1600, 600, true);
    179             add_image_size('card-grid', 600, 900, true);
    180             add_image_size('card-list', 600, 700, true);
    181 
    182             // Check if Elementor installed and activated
     157                return; // Admin notice is now handled by admin-info.php
     158            }
     159
     160            // Load Elementor integration if available
    183161            if (did_action('elementor/loaded')) {
    184162                require_once('includes/elementor/elementor-main.php');
    185             } else {
    186                 global $pagenow;
    187                 if (in_array($pagenow, array('plugins.php', 'admin.php')) && !(get_option('mgelhide9'))) {
    188                     add_action('admin_notices', [$this, 'admin_notice_missing_main_plugin']);
     163            }
     164
     165            // Track plugin activation and installation
     166            $this->track_plugin_usage();
     167
     168            // Initialize Appsero tracking after 2 days
     169            $mgposte_install_date = get_option('mgposte_install_date');
     170            if (!empty($mgposte_install_date)) {
     171                $install_day = round((time() - strtotime($mgposte_install_date)) / 24 / 60 / 60);
     172                if ($install_day > 2) {
     173                    //$this->appsero_init_tracker_magical_posts_display();
    189174                }
    190175            }
     176        }
     177
     178        /**
     179         * Track plugin usage
     180         */
     181        public function track_plugin_usage()
     182        {
    191183            $is_plugin_activated = get_option('mgposte_plugin_activated');
    192184            if ('yes' !== $is_plugin_activated) {
    193185                update_option('mgposte_plugin_activated', 'yes');
    194186            }
     187
    195188            $mgposte_install_date = get_option('mgposte_install_date');
    196189            if (empty($mgposte_install_date)) {
    197190                update_option('mgposte_install_date', current_time('mysql'));
    198191            }
    199             if (!empty($mgposte_install_date)) {
    200                 $install_day = round((time() - strtotime($mgposte_install_date)) / 24 / 60 / 60);
    201                 if ($install_day > 2) {
    202                     $this->appsero_init_tracker_magical_posts_display();
    203                 }
    204             }
    205         }
    206 
    207         public function elementor_notice_hide_options()
    208         {
    209             if (isset($_GET['mgelhide']) && $_GET['mgelhide'] == 1) {
    210                 //  delete_option( 'mgelhide');
    211                 update_option('mgelhide9', 1);
    212             }
    213         }
    214 
    215 
    216         /**
    217          * Admin notice
    218          *
    219          * Warning when the site doesn't have Elementor installed or activated.
    220          *
    221          * @since 1.0.0
    222          *
    223          * @access public
    224          */
    225         public function admin_notice_missing_main_plugin()
    226         {
    227             if (get_option('mgelhide9')) {
    228                 return;
    229             }
    230             if (isset($_GET['activate'])) unset($_GET['activate']);
    231 
    232 
    233             if (file_exists(WP_PLUGIN_DIR . '/elementor/elementor.php')) {
    234                 $magial_eactive_url = wp_nonce_url('plugins.php?action=activate&plugin=elementor/elementor.php&plugin_status=all&paged=1', 'activate-plugin_elementor/elementor.php');
    235                 $message = sprintf(
    236                     /* translators: 1: Plugin name 2: Elementor 3: Elementor installation link */
    237                     esc_html__('%1$s Recommended %2$s plugin, which is currently NOT RUNNING  %3$s', 'magical-posts-display'),
    238                     '<strong>' . esc_html__('Magical Posts Display', 'magical-posts-display') . '</strong>',
    239                     '<strong>' . esc_html__('Elementor', 'magical-posts-display') . '</strong>',
    240                     '<a class="button button-primary" style="margin-left:20px" href="' . $magial_eactive_url . '">' . __('Activate Elementor', 'magical-posts-display') . '</a>'
    241 
    242                 );
    243             } else {
    244                 $magial_einstall_url =  wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=elementor'), 'install-plugin_elementor');
    245                 $message = sprintf(
    246                     /* translators: 1: Plugin name 2: Elementor 3: Elementor installation link */
    247                     esc_html__('%1$s Recommended %2$s plugin for use all Elementor addons, which is currently NOT RUNNING  %3$s', 'magical-posts-display'),
    248                     '<strong>' . esc_html__('Magical Posts Display', 'magical-posts-display') . '</strong>',
    249                     '<strong>' . esc_html__('Elementor', 'magical-posts-display') . '</strong>',
    250                     '<a class="button button-primary" style="margin-left:20px" href="' . $magial_einstall_url . '">' . __('Install Elementor', 'magical-posts-display') . '</a>'
    251                     /* '<a class="button skipelementor" style="margin-left:20px" href="#">' . __('Skip it for only use Gutenberg addons', 'magical-posts-display') . '</a>' */
    252 
    253                 );
    254             }
    255 
    256             printf('<div class="notice notice-warning is-dismissible mgpd-notice"><p style="padding: 13px 0">%1$s</p></div>', wp_kses_post($message));
    257         }
    258 
    259 
    260 
    261         /**
    262          * Add style and scripts
    263          *
    264          * Add the plugin style and scripts for this
    265          *
    266          * @since 1.0.0
    267          *
    268          * @access public
    269          */
    270         public function mgpblock_style()
    271         {
    272             wp_register_style(
    273                 'swiper',
    274                 plugins_url('/assets/css/swiper.min.css', __FILE__),
    275                 [],
    276                 '8.4.5',
    277                 'all'
    278             );
    279 
    280             wp_enqueue_style('venobox.min', plugins_url('/assets/css/venobox.min.css', __FILE__), array(), '1.0.0', 'all');
    281             wp_enqueue_style('bootstrap', plugins_url('/assets/css/bootstrap.min.css', __FILE__), array(), '5.1.1', 'all');
    282             wp_enqueue_style('mpd-fonts', plugins_url('/assets/css/fontello.css', __FILE__), array(), MAGICAL_POSTS_DISPLAY_VERSION, 'all');
    283             //  wp_enqueue_style('swiper.min', plugins_url('/assets/css/swiper.min.css', __FILE__), array(), '5.3.8', 'all');
    284             wp_enqueue_style('mpd-style', plugins_url('/assets/css/mp-style.css', __FILE__), array(), MAGICAL_POSTS_DISPLAY_VERSION, 'all');
    285         }
    286 
    287         public function mgpblock_scripts()
    288         {
    289 
    290             wp_register_script(
    291                 'mg-swiper',
    292                 plugins_url('/assets/js/swiper.min.js', __FILE__),
    293                 ['jquery'],
    294                 '8.4.5',
    295                 true
    296             );
    297             wp_register_script(
    298                 'jquery.easy-ticker',
    299                 plugins_url('/assets/js/jquery.easy-ticker.min.js', __FILE__),
    300                 ['jquery'],
    301                 '3.1.0',
    302                 true
    303             );
    304 
    305             wp_enqueue_script('masonry');
    306             wp_enqueue_script('venobox-js', plugins_url('/assets/js/venobox.min.js', __FILE__), array('jquery'), '1.0.0', true);
    307             wp_enqueue_script('bootstrap.bundle.min', plugins_url('/assets/js/bootstrap.bundle.min.js', __FILE__), array('jquery'), '5.1.1', false);
    308             wp_enqueue_script('mpd-main', plugins_url('/assets/js/main.js', __FILE__), array('jquery'), MAGICAL_POSTS_DISPLAY_VERSION, true);
    309         }
    310 
    311         /**
    312          * Add style and scripts for gutenburg editor
    313          *
    314          * Add the plugin style and scripts for gutenburg editor
    315          *
    316          * @since 1.0.4
    317          *
    318          * @access public
    319          */
    320         public function mgpblock_editor_scripts()
    321         {
    322             wp_enqueue_style('mp-admin-block', plugins_url('/assets/css/mgblock-admin.css', __FILE__), array(), '1.0.0', 'all');
    323         }
    324 
    325 
    326         /**
    327          * Add style and scripts for editor
    328          *
    329          * Add the plugin style and scripts for editor only
    330          *
    331          * @since 1.0.0
    332          *
    333          * @access public
    334          */
    335         public function mgpost_display_editor_scripts()
    336         {
    337             global $pagenow;
    338 
    339 
    340             wp_enqueue_style('mp-admin-style', plugins_url('/assets/css/admin-style.css', __FILE__), array(), MAGICAL_POSTS_DISPLAY_VERSION, 'all');
    341             if (in_array($pagenow, array('post-new.php', 'post.php'))) {
    342                 wp_enqueue_script('cmb2-conditional-logic', plugins_url('/assets/js/cmb2-conditional-logic.js', __FILE__), array('jquery'), '2.5.1', true);
    343             }
    344             if (isset($_GET['page']) && $_GET['page'] == 'mgpd-page') {
    345                 wp_enqueue_style('mp-admin-page', plugins_url('/assets/css/mgadmin-page.css', __FILE__), array(), MAGICAL_POSTS_DISPLAY_VERSION, 'all');
    346                 wp_enqueue_style('venobox.min', plugins_url('/assets/css/venobox.min.css', __FILE__), array(), MAGICAL_POSTS_DISPLAY_VERSION, 'all');
    347                 wp_enqueue_script('venobox-js', plugins_url('/assets/js/venobox.min.js', __FILE__), array('jquery'), MAGICAL_POSTS_DISPLAY_VERSION, true);
    348             }
    349             wp_enqueue_script('mgntc-js', plugins_url('/assets/js/mgntc.js', __FILE__), array('jquery'), '1.0.0', true);
    350192        }
    351193
     
    363205
    364206
    365 
    366 
    367         /**
    368          * Admin notice
    369          *
    370          * Warning when the site doesn't have a minimum required PHP version.
    371          *
    372          * @since 1.0.0
    373          *
    374          * @access public
    375          */
    376         public function admin_notice_minimum_php_version()
    377         {
    378 
    379             if (isset($_GET['activate'])) unset($_GET['activate']);
    380 
    381             $message = sprintf(
    382                 /* translators: 1: Plugin name 2: PHP 3: Required PHP version */
    383                 esc_html__('"%1$s" requires "%2$s" version %3$s or greater.', 'magical-posts-display'),
    384                 '<strong>' . esc_html__('Magical Posts Display', 'magical-posts-display') . '</strong>',
    385                 '<strong>' . esc_html__('PHP', 'magical-posts-display') . '</strong>',
    386                 self::MINIMUM_PHP_VERSION
    387             );
    388 
    389             printf(
    390                 '<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>',
    391                 wp_kses_post($message)
    392             );
    393         }
    394207
    395208
Note: See TracChangeset for help on using the changeset viewer.