Plugin Directory

Changeset 3478936


Ignore:
Timestamp:
03/10/2026 09:44:19 AM (3 weeks ago)
Author:
msuekdeveloper
Message:

add new form widget and logo slider fixed

Location:
moonstack-ultimate-elementor-kit/trunk
Files:
11 added
14 edited

Legend:

Unmodified
Added
Removed
  • moonstack-ultimate-elementor-kit/trunk/README.txt

    r3427568 r3478936  
    44Requires at least: 5.0
    55Tested up to: 6.9
    6 Stable tag: 1.0.2
     6Stable tag: 1.1.0
    77Requires PHP: 7.4
    88License: GPLv2 or later
     
    4242* Logo Slider - Customer logo slider with hover effects and linking
    4343
     44**Form Widgets**
     45
     46* Form - Advanced form builder with AJAX submission, email notifications, and Google reCAPTCHA (v2/v3) integration
     47
    4448== External Services ==
    4549
     
    7377Terms of Service: https://www.youtube.com/t/terms 
    7478
     79Google reCAPTCHA 
     80Service: Spam protection and security 
     81Website: https://www.google.com/recaptcha/about/ 
     82Privacy Policy: https://policies.google.com/privacy 
     83Terms of Service: https://policies.google.com/terms 
     84
    7585**Basic Widgets**
    7686
     
    91101* moonulel_card_slider_slides
    92102* moonulel_logo_slider_logos
     103* moonulel_form_submitted_data
     104* moonulel_form_before_send_emails
     105* moonulel_form_after_save_db
    93106
    94107== Installation ==
     
    114127== Changelog ==
    115128
     129= 1.1.0 =
     130* Added powerful Form Widget with multiple field types and AJAX submission handling
     131* Integrated Google reCAPTCHA v2 and v3 APIs for form spam protection
     132* Added global plugin dashboard settings panel for handling external API integrations
     133* Fixed RTL (Right-to-Left) behavior in the Customer Logo Slider widget
     134* Fixed responsive layout and behavior in the Card Slider widget
     135
    116136= 1.0.2 =
    117137* Removed Custom CSS option from widgets to improve security
     
    134154
    135155== Upgrade Notice ==
     156
     157= 1.1.0 =
     158This update introduces a new Form Widget with Google reCAPTCHA v2 & v3 support, along with a new global settings dashboard.
    136159
    137160= 1.0.2 =
     
    158181    echo '<div class="custom-slider-navigation">Custom Nav</div>';
    159182}, 10, 3);
     183
     184// Filter form widget submitted data before sending email or saving
     185add_filter('moonulel_form_submitted_data', function($submitted_data, $form_id, $post_id, $settings) {
     186    // Add custom hidden data
     187    $submitted_data['Source'] = 'Facebook Ads';
     188    return $submitted_data;
     189}, 10, 4);
    160190</pre>
  • moonstack-ultimate-elementor-kit/trunk/admin/class-moonstack-ultimate-elementor-kit-admin.php

    r3427568 r3478936  
    6464        add_action('wp_ajax_moonulel_admin_save_options', array($this, 'moonulel_admin_save_options'));
    6565        add_action('init', array($this, 'moonulel_documents_register'), 20);
     66        add_action('admin_init', array($this, 'moonulel_handle_form_export'));
    6667        add_filter('plugin_action_links_' . $moonulel_main_file, array($this, 'moonulel_add_settings_link'));
    6768    }
     
    164165            $elementor_icon,
    165166            25
     167        );
     168        add_submenu_page(
     169            'ms-ultimate-elementor-kit',
     170            esc_html__('Form Submissions', 'moonstack-ultimate-elementor-kit'),
     171            esc_html__('Form Submissions', 'moonstack-ultimate-elementor-kit'),
     172            'manage_options',
     173            'ms-ultimate-elementor-kit-forms',
     174            array($this, 'moonulel_form_submissions_page')
     175        );
     176        add_submenu_page(
     177            'ms-ultimate-elementor-kit',
     178            esc_html__('Export Data', 'moonstack-ultimate-elementor-kit'),
     179            esc_html__('Export Data', 'moonstack-ultimate-elementor-kit'),
     180            'manage_options',
     181            'ms-ultimate-elementor-kit-import-export',
     182            array($this, 'moonulel_form_import_export_page')
    166183        );
    167184    }
     
    235252
    236253    /**
     254     * Handle CSV Export
     255     */
     256    public function moonulel_handle_form_export()
     257    {
     258        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     259        if (isset($_GET['moonulel_export_forms']) && $_GET['moonulel_export_forms'] == '1' && current_user_can('manage_options')) {
     260            global $wpdb;
     261            $table_name_forms = $wpdb->prefix . 'moonulel_forms';
     262            $table_name_meta = $wpdb->prefix . 'moonulel_form_meta';
     263
     264            $where = "WHERE 1=1";
     265            if (!empty($_GET['export_form_name'])) {
     266                $where .= $wpdb->prepare(" AND form_name = %s", sanitize_text_field(wp_unslash($_GET['export_form_name'])));
     267            }
     268            if (!empty($_GET['export_date_from'])) {
     269                $where .= $wpdb->prepare(" AND DATE(created_at) >= %s", sanitize_text_field(wp_unslash($_GET['export_date_from'])));
     270            }
     271            if (!empty($_GET['export_date_to'])) {
     272                $where .= $wpdb->prepare(" AND DATE(created_at) <= %s", sanitize_text_field(wp_unslash($_GET['export_date_to'])));
     273            }
     274
     275            $forms = $wpdb->get_results("SELECT * FROM $table_name_forms $where ORDER BY id DESC");
     276            if (!$forms) {
     277                wp_die(esc_html__('No data found for export.', 'moonstack-ultimate-elementor-kit'));
     278            }
     279
     280            header('Content-Type: text/csv; charset=utf-8');
     281            header('Content-Disposition: attachment; filename=moonulel-form-submissions.csv');
     282            $output = fopen('php://output', 'w');
     283
     284            // Get all possible meta keys across all elements to create the header
     285            $meta_keys = $wpdb->get_col("SELECT DISTINCT meta_key FROM $table_name_meta");
     286            $headers = array('ID', 'Form Name', 'Created At');
     287            foreach ($meta_keys as $key) {
     288                $headers[] = $key;
     289            }
     290            fputcsv($output, $headers);
     291
     292            foreach ($forms as $form) {
     293                $row = array($form->id, $form->form_name, $form->created_at);
     294                // To fix the undefined constant warning, use 'OBJECT_K' as a string instead of OBJECT_K directly if it causes issues, but standard WP uses OBJECT_K.
     295                // Let's use OBJECT_K without quotes as WP defines it, but ignore the linter warning or use string 'OBJECT_K' if needed. WP defines OBJECT_K. Or just loop normally without OBJECT_K.
     296                $metas = $wpdb->get_results($wpdb->prepare("SELECT meta_key, meta_value FROM $table_name_meta WHERE form_id = %d", $form->id));
     297                $metas_assoc = array();
     298                foreach ($metas as $m) {
     299                    $metas_assoc[$m->meta_key] = $m->meta_value;
     300                }
     301
     302                foreach ($meta_keys as $key) {
     303                    $row[] = isset($metas_assoc[$key]) ? $metas_assoc[$key] : '';
     304                }
     305                fputcsv($output, $row);
     306            }
     307
     308            fclose($output);
     309            exit();
     310        }
     311    }
     312
     313
     314
     315    /**
     316     * Output Form Submissions page content
     317     */
     318    public function moonulel_form_submissions_page()
     319    {
     320        if (!current_user_can('manage_options')) {
     321            return;
     322        }
     323
     324        $template_file = plugin_dir_path(__FILE__) . 'partials/moonstack-ultimate-elementor-kit-admin-submissions.php';
     325
     326        if (file_exists($template_file)) {
     327            include $template_file;
     328        } else {
     329            echo '<div class="wrap"><div class="notice notice-error"><p>' . esc_html__('Template file not found.', 'moonstack-ultimate-elementor-kit') . '</p></div></div>';
     330        }
     331    }
     332
     333    /**
     334     * Output Export Data page content
     335     */
     336    public function moonulel_form_import_export_page()
     337    {
     338        if (!current_user_can('manage_options')) {
     339            return;
     340        }
     341
     342        $template_file = plugin_dir_path(__FILE__) . 'partials/moonstack-ultimate-elementor-kit-admin-import-export.php';
     343
     344        if (file_exists($template_file)) {
     345            include $template_file;
     346        } else {
     347            echo '<div class="wrap"><div class="notice notice-error"><p>' . esc_html__('Template file not found.', 'moonstack-ultimate-elementor-kit') . '</p></div></div>';
     348        }
     349    }
     350
     351    /**
    237352     * Handle AJAX request to save admin options.
    238353     *
     
    290405        do_action('moonulel_before_save_options', $sanitized_post);
    291406
     407        // Save reCAPTCHA options
     408        if (isset($sanitized_post['moonulel_recaptcha_version'])) {
     409            update_option('moonulel_recaptcha_version', $sanitized_post['moonulel_recaptcha_version']);
     410        }
     411        // Get from post directly and sanitize properly to preserve base64 / underscores if any in keys, although sanitize_text_field usually allows them.
     412        if (isset($_POST['moonulel_recaptcha_site_key'])) {
     413            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
     414            update_option('moonulel_recaptcha_site_key', sanitize_text_field(wp_unslash($_POST['moonulel_recaptcha_site_key'])));
     415        }
     416        if (isset($_POST['moonulel_recaptcha_secret_key'])) {
     417            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
     418            update_option('moonulel_recaptcha_secret_key', sanitize_text_field(wp_unslash($_POST['moonulel_recaptcha_secret_key'])));
     419        }
    292420
    293421
     
    405533                /* translators: %s: comma-separated list of setting names that failed */
    406534                $message .= ' ' . sprintf(
    407                 /* translators: %s: comma-separated list of setting names that failed */
     535                    /* translators: %s: comma-separated list of setting names that failed */
    408536                    esc_html__('Failed to save: %s', 'moonstack-ultimate-elementor-kit'),
    409537                    esc_html(implode(', ', $errors))
  • moonstack-ultimate-elementor-kit/trunk/admin/css/moonstack-ultimate-elementor-kit-admin.css

    r3427537 r3478936  
    1 
    21.moonulelFormGrid {
    32    display: flex;
     
    54    flex-wrap: wrap;
    65}
    7 .toplevel_page_ms-ultimate-elementor-kit .wp-menu-image.svg{
     6
     7.toplevel_page_ms-ultimate-elementor-kit .wp-menu-image.svg {
    88    filter: contrast(0.3);
    99}
     
    3030    margin: -5px 10px 0 0;
    3131}
    32 .moonulelFormFooter{
     32
     33.moonulelFormFooter {
    3334    padding: 50px 0;
    3435}
     36
    3537.moonulelFormGrid .moonulelFormElement .moonulelToggleWrapper {
    3638    display: flex;
     
    99101    border-radius: 50%;
    100102}
     103
     104.moonulel-pagination-container {
     105    display: flex;
     106    justify-content: flex-end;
     107    align-items: center;
     108    gap: 20px;
     109    padding: 15px 0;
     110    margin-top: 10px;
     111}
     112
     113.moonulel-pagination-container .displaying-num {
     114    font-weight: 500;
     115    color: #3c434a;
     116}
     117
     118.moonulel-pagination-container .pagination-links {
     119    display: flex;
     120    gap: 6px;
     121    align-items: center;
     122}
     123
     124.moonulel-pagination-container .pagination-links a,
     125.moonulel-pagination-container .pagination-links span.current,
     126.moonulel-pagination-container .pagination-links span.dots {
     127    display: inline-flex;
     128    align-items: center;
     129    justify-content: center;
     130    min-width: 32px;
     131    height: 32px;
     132    padding: 0 8px;
     133    font-size: 14px;
     134    border: 1px solid #c3c4c7;
     135    border-radius: 4px;
     136    background: #fff;
     137    color: #2271b1;
     138    text-decoration: none;
     139    box-sizing: border-box;
     140}
     141
     142.moonulel-pagination-container .pagination-links a:hover {
     143    background: #f6f7f7;
     144    border-color: #8c8f94;
     145    color: #135e96;
     146}
     147
     148.moonulel-pagination-container .pagination-links span.current {
     149    background: #2271b1;
     150    border-color: #2271b1;
     151    color: #fff;
     152    font-weight: 600;
     153}
     154
     155.moonulel-pagination-container .pagination-links span.dots {
     156    border: none;
     157    background: transparent;
     158    color: #3c434a;
     159}
  • moonstack-ultimate-elementor-kit/trunk/admin/css/moonstack-ultimate-elementor-kit-admin.min.css

    r3427537 r3478936  
    1 .moonulelFormGrid{display:flex;gap:30px;flex-wrap:wrap}.toplevel_page_ms-ultimate-elementor-kit .wp-menu-image.svg{filter:contrast(.3)}.moonulelFormGrid .moonulelFormElement{width:calc(25% - 24px);padding:27px;background:#fff;box-shadow:0 0 5px 2px #0001;border-radius:10px;box-sizing:border-box}.moonulelFormElement .moonulelWidgetName{color:#000;font-size:16px;font-weight:500}.moonulelFormElement .moonulelWidgetIcon{font-size:30px;width:30px;color:#000;margin:-5px 10px 0 0}.moonulelFormFooter{padding:50px 0}.moonulelFormGrid .moonulelFormElement .moonulelToggleWrapper{display:flex;flex-direction:column;align-items:center;gap:15px}.moonulelToggleSwitch{position:relative;display:inline-block;width:60px;height:34px}.moonulelToggleSwitch input{opacity:0;width:0;height:0}.moonulelSlider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.4s;transition:.4s}.moonulelSlider:before{position:absolute;content:"";height:26px;width:26px;left:4px;bottom:4px;background:#fff;-webkit-transition:.4s;transition:.4s}.moonulelToggleSwitch input:checked+.moonulelSlider{background:#2196f3}.moonulelToggleSwitch input:focus+.moonulelSlider{box-shadow:0 0 1px #2196f3}.moonulelToggleSwitch input:checked+.moonulelSlider:before{-webkit-transform:translateX(26px);-ms-transform:translateX(26px);transform:translateX(26px)}.moonulelSlider.moonulelRound{border-radius:34px}.moonulelSlider.moonulelRound:before{border-radius:50%}
     1.moonulelFormGrid {
     2    display: flex;
     3    gap: 30px;
     4    flex-wrap: wrap
     5}
     6
     7.toplevel_page_ms-ultimate-elementor-kit .wp-menu-image.svg {
     8    filter: contrast(.3)
     9}
     10
     11.moonulelFormGrid .moonulelFormElement {
     12    width: calc(25% - 24px);
     13    padding: 27px;
     14    background: #fff;
     15    box-shadow: 0 0 5px 2px #0001;
     16    border-radius: 10px;
     17    box-sizing: border-box
     18}
     19
     20.moonulelFormElement .moonulelWidgetName {
     21    color: #000;
     22    font-size: 16px;
     23    font-weight: 500
     24}
     25
     26.moonulelFormElement .moonulelWidgetIcon {
     27    font-size: 30px;
     28    width: 30px;
     29    color: #000;
     30    margin: -5px 10px 0 0
     31}
     32
     33.moonulelFormFooter {
     34    padding: 50px 0
     35}
     36
     37.moonulelFormGrid .moonulelFormElement .moonulelToggleWrapper {
     38    display: flex;
     39    flex-direction: column;
     40    align-items: center;
     41    gap: 15px
     42}
     43
     44.moonulelToggleSwitch {
     45    position: relative;
     46    display: inline-block;
     47    width: 60px;
     48    height: 34px
     49}
     50
     51.moonulelToggleSwitch input {
     52    opacity: 0;
     53    width: 0;
     54    height: 0
     55}
     56
     57.moonulelSlider {
     58    position: absolute;
     59    cursor: pointer;
     60    top: 0;
     61    left: 0;
     62    right: 0;
     63    bottom: 0;
     64    background-color: #ccc;
     65    -webkit-transition: .4s;
     66    transition: .4s
     67}
     68
     69.moonulelSlider:before {
     70    position: absolute;
     71    content: "";
     72    height: 26px;
     73    width: 26px;
     74    left: 4px;
     75    bottom: 4px;
     76    background: #fff;
     77    -webkit-transition: .4s;
     78    transition: .4s
     79}
     80
     81.moonulelToggleSwitch input:checked+.moonulelSlider {
     82    background: #2196f3
     83}
     84
     85.moonulelToggleSwitch input:focus+.moonulelSlider {
     86    box-shadow: 0 0 1px #2196f3
     87}
     88
     89.moonulelToggleSwitch input:checked+.moonulelSlider:before {
     90    -webkit-transform: translateX(26px);
     91    -ms-transform: translateX(26px);
     92    transform: translateX(26px)
     93}
     94
     95.moonulelSlider.moonulelRound {
     96    border-radius: 34px
     97}
     98
     99.moonulelSlider.moonulelRound:before {
     100    border-radius: 50%
     101}
     102
     103.moonulel-pagination-container {
     104    display: flex;
     105    justify-content: flex-end;
     106    align-items: center;
     107    gap: 20px;
     108    padding: 15px 0;
     109    margin-top: 10px
     110}
     111
     112.moonulel-pagination-container .displaying-num {
     113    font-weight: 500;
     114    color: #3c434a
     115}
     116
     117.moonulel-pagination-container .pagination-links {
     118    display: flex;
     119    gap: 6px;
     120    align-items: center
     121}
     122
     123.moonulel-pagination-container .pagination-links a,
     124.moonulel-pagination-container .pagination-links span.current,
     125.moonulel-pagination-container .pagination-links span.dots {
     126    display: inline-flex;
     127    align-items: center;
     128    justify-content: center;
     129    min-width: 32px;
     130    height: 32px;
     131    padding: 0 8px;
     132    font-size: 14px;
     133    border: 1px solid #c3c4c7;
     134    border-radius: 4px;
     135    background: #fff;
     136    color: #2271b1;
     137    text-decoration: none;
     138    box-sizing: border-box
     139}
     140
     141.moonulel-pagination-container .pagination-links a:hover {
     142    background: #f6f7f7;
     143    border-color: #8c8f94;
     144    color: #135e96
     145}
     146
     147.moonulel-pagination-container .pagination-links span.current {
     148    background: #2271b1;
     149    border-color: #2271b1;
     150    color: #fff;
     151    font-weight: 600
     152}
     153
     154.moonulel-pagination-container .pagination-links span.dots {
     155    border: none;
     156    background: #fff0;
     157    color: #3c434a
     158}
  • moonstack-ultimate-elementor-kit/trunk/admin/partials/moonstack-ultimate-elementor-kit-admin-display.php

    r3427537 r3478936  
    114114                            <?php endforeach; ?>
    115115
     116                            <div class="moonulelWidgetCategory">
     117                                <h3 class="moonulelCategoryTitle"><?php echo esc_html__( 'Google reCAPTCHA API Settings', 'moonstack-ultimate-elementor-kit' ); ?></h3>
     118                                <div class="moonulelFormSectionItems" style="background: #fff; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.05); padding: 20px; border: 1px solid #e2e8f0; margin-bottom: 24px;">
     119                                    <table class="form-table">
     120                                        <tr>
     121                                            <th scope="row"><label for="moonulel_recaptcha_version" style="font-weight: 500; font-size: 15px;">reCAPTCHA Version</label></th>
     122                                            <td>
     123                                                <select name="moonulel_recaptcha_version" id="moonulel_recaptcha_version" style="width: 100%; max-width: 400px; padding: 6px 12px; border-radius: 4px; border: 1px solid #cbd5e1;">
     124                                                    <option value="v2" <?php selected( get_option('moonulel_recaptcha_version'), 'v2' ); ?>>v2 Checkbox</option>
     125                                                    <option value="v3" <?php selected( get_option('moonulel_recaptcha_version'), 'v3' ); ?>>v3</option>
     126                                                </select>
     127                                                <p class="description">Select which version of reCAPTCHA to use.</p>
     128                                            </td>
     129                                        </tr>
     130                                        <tr>
     131                                            <th scope="row"><label for="moonulel_recaptcha_site_key" style="font-weight: 500; font-size: 15px;">Site Key</label></th>
     132                                            <td>
     133                                                <input type="text" name="moonulel_recaptcha_site_key" id="moonulel_recaptcha_site_key" value="<?php echo esc_attr( get_option('moonulel_recaptcha_site_key') ); ?>" class="regular-text" style="width: 100%; max-width: 400px; padding: 6px 12px; border-radius: 4px; border: 1px solid #cbd5e1;">
     134                                            </td>
     135                                        </tr>
     136                                        <tr>
     137                                            <th scope="row"><label for="moonulel_recaptcha_secret_key" style="font-weight: 500; font-size: 15px;">Secret Key</label></th>
     138                                            <td>
     139                                                <input type="text" name="moonulel_recaptcha_secret_key" id="moonulel_recaptcha_secret_key" value="<?php echo esc_attr( get_option('moonulel_recaptcha_secret_key') ); ?>" class="regular-text" style="width: 100%; max-width: 400px; padding: 6px 12px; border-radius: 4px; border: 1px solid #cbd5e1;">
     140                                            </td>
     141                                        </tr>
     142
     143                                    </table>
     144                                </div>
     145                            </div>
     146
    116147                            <div class="moonulelFormFooter">
    117148                                <button type="submit" class="moonulelFormSaveButton button button-primary button-large">
  • moonstack-ultimate-elementor-kit/trunk/includes/class-moonstack-ultimate-elementor-kit-activator.php

    r3427537 r3478936  
    2121 * @author     Moonstack Team <[email protected]>
    2222 */
    23 class Moonstack_Ultimate_Elementor_Kit_Activator {
     23class Moonstack_Ultimate_Elementor_Kit_Activator
     24{
    2425
    25     /**
    26     * Short Description. (use period)
    27     *
    28     * Long Description.
    29     *
    30     * @since    1.0.0
    31     */
     26    /**
     27    * Short Description. (use period)
     28    *
     29    * Long Description.
     30    *
     31    * @since    1.0.0
     32    */
    3233
    33     public static function activate() {
     34    public static function activate()
     35    {
    3436
    35      
     37
    3638        if (!class_exists('Moonulel_Widget_Options_Manager')) {
    3739            $options_file = MOONULEL_PLUGIN_DIR . '/includes/class-moonulel-widgets.php';
    38              require_once $options_file;
     40            require_once $options_file;
    3941        }
    4042
     
    4244        $widget_options = $widget_manager->moonulel_get_widget_options();
    4345
     46        self::create_custom_tables();
     47
    4448        $current_version = get_option('moonstack_ultimate_elementor_kit_version');
    45         $plugin_version  = MOONULEL_VERSION;
     49        $plugin_version = MOONULEL_VERSION;
    4650
    4751        if (!$current_version) {
     
    5761        }
    5862    }
     63
     64    /**
     65     * Create custom database tables for forms.
     66     */
     67    private static function create_custom_tables()
     68    {
     69        global $wpdb;
     70        $charset_collate = $wpdb->get_charset_collate();
     71
     72        $table_name_forms = $wpdb->prefix . 'moonulel_forms';
     73        $sql_forms = "CREATE TABLE IF NOT EXISTS $table_name_forms (
     74            id bigint(20) NOT NULL AUTO_INCREMENT,
     75            form_name varchar(255) NOT NULL,
     76            created_at datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
     77            updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL,
     78            PRIMARY KEY  (id)
     79        ) $charset_collate;";
     80
     81        $table_name_meta = $wpdb->prefix . 'moonulel_form_meta';
     82        $sql_meta = "CREATE TABLE IF NOT EXISTS $table_name_meta (
     83            id bigint(20) NOT NULL AUTO_INCREMENT,
     84            form_id bigint(20) NOT NULL,
     85            meta_key varchar(255),
     86            meta_value longtext,
     87            PRIMARY KEY  (id),
     88            KEY form_id (form_id),
     89            KEY meta_key (meta_key(191))
     90        ) $charset_collate;";
     91
     92        $wpdb->query($sql_forms);
     93        $wpdb->query($sql_meta);
     94    }
    5995}
    6096
  • moonstack-ultimate-elementor-kit/trunk/includes/class-moonstack-ultimate-elementor-kit.php

    r3427537 r3478936  
    337337            add_action('wp_ajax_moonulel_post_template_load_more', [$this, 'moonulel_post_template_load_more']);
    338338            add_action('wp_ajax_nopriv_moonulel_post_template_load_more', [$this, 'moonulel_post_template_load_more']);
     339            add_action('wp_ajax_moonulel_submit_form', [$this, 'moonulel_submit_form']);
     340            add_action('wp_ajax_nopriv_moonulel_submit_form', [$this, 'moonulel_submit_form']);
    339341
    340342            // Register Elementor widgets
     
    607609    }
    608610
     611    public function moonulel_submit_form()
     612    {
     613
     614        if (!class_exists('MOONULEL_Form_Widget')) {
     615            require_once plugin_dir_path(__FILE__) . 'widgets/form/class-form.php';
     616        }
     617        \MOONULEL_Form_Widget::ajax_submit();
     618    }
     619
    609620    private function register_autoloader()
    610621    {
  • moonstack-ultimate-elementor-kit/trunk/includes/class-moonulel-widgets.php

    r3427537 r3478936  
    3333            'moonulel-post-excerpt',
    3434            'moonulel-post-featured-img',
    35             'moonulel-banner-sleder',
     35            'moonulel-banner-slider',
    3636            'moonulel-logo-slider',
    3737            'moonulel-card-slider',
     38            'moonulel-form',
    3839        ]);
    3940    }
     
    9798                [
    9899                    'label' => 'Banner Slider',
    99                     'name' => 'moonulel-banner-sleder',
     100                    'name' => 'moonulel-banner-slider',
    100101                    'icon' => 'dashicons-cover-image'
    101102                ],
     
    111112                ],
    112113            ],
     114            'Form Widgets' => [
     115                [
     116                    'label' => 'Form',
     117                    'name' => 'moonulel-form',
     118                    'icon' => 'dashicons-email'
     119                ],
     120            ],
    113121            'Basic Widgets' => [
    114122                [
     
    117125                    'icon' => 'dashicons-button'
    118126                ],
    119              
     127
    120128            ],
    121129        ]);
  • moonstack-ultimate-elementor-kit/trunk/includes/widgets/class-moonulel-elementor-element-widgets.php

    r3427537 r3478936  
    55 *
    66 * @since      1.0.0
    7 * @package    Moonstack_Ultimate_Elementor_Kit
     7 * @package    Moonstack_Ultimate_Elementor_Kit
    88 * @subpackage Moonstack_Ultimate_Elementor_Kit/includes
    99 * @author     Moonstack Team <[email protected]>
     
    1111
    1212// If this file is called directly, abort.
    13 if (! defined('ABSPATH')) {
     13if (!defined('ABSPATH')) {
    1414    exit;
    1515}
     
    5555    {
    5656        $this->plugin_name = $plugin_name;
    57         $this->version     = $version;
    58         if(!class_exists('Moonulel_Widget_Options_Manager')){
     57        $this->version = $version;
     58        if (!class_exists('Moonulel_Widget_Options_Manager')) {
    5959            require_once MOONULEL_PLUGIN_DIR . 'includes/class-moonulel-widgets.php';
    6060        }
     
    8787    }
    8888
    89  
     89
    9090
    9191    public function moonulel_enqueue_custom_button_styles()
    9292    {
    9393
    94         if (! wp_style_is('moonulel-custom-button-animations', 'enqueued')) {
     94        if (!wp_style_is('moonulel-custom-button-animations', 'enqueued')) {
    9595            wp_enqueue_style(
    9696                'moonulel-custom-button-animations',
     
    100100            );
    101101        }
    102         if (! wp_style_is('moonulel-featured-image', 'enqueued')) {
     102        if (!wp_style_is('moonulel-featured-image', 'enqueued')) {
    103103            wp_enqueue_style(
    104104                'moonulel-featured-image',
     
    120120            true
    121121        );
    122         if (! wp_style_is($this->plugin_name . '-posts-style', 'enqueued')) {
     122        if (!wp_style_is($this->plugin_name . '-posts-style', 'enqueued')) {
    123123            wp_enqueue_style(
    124124                $this->plugin_name . '-posts-style',
     
    130130        }
    131131        // Check and enqueue moonulel-post-slider.css
    132         if (! wp_style_is($this->plugin_name . '-posts-slider', 'enqueued')) {
     132        if (!wp_style_is($this->plugin_name . '-posts-slider', 'enqueued')) {
    133133            wp_enqueue_style(
    134134                $this->plugin_name . '-posts-slider',
     
    140140
    141141        // Check and enqueue moonulel-card-slider.css
    142         if (! wp_style_is($this->plugin_name . '-posts-card', 'enqueued')) {
     142        if (!wp_style_is($this->plugin_name . '-posts-card', 'enqueued')) {
    143143            wp_enqueue_style(
    144144                $this->plugin_name . '-posts-card',
     
    150150
    151151        // Check and enqueue moonulel-customer-logo-slider.css
    152         if (! wp_style_is($this->plugin_name . '-posts-customer-logo', 'enqueued')) {
     152        if (!wp_style_is($this->plugin_name . '-posts-customer-logo', 'enqueued')) {
    153153            wp_enqueue_style(
    154154                $this->plugin_name . '-posts-customer-logo',
     
    165165        if ($widget_manager->moonulel_is_widget_enabled('moonulel-banner-slider')) {
    166166
    167             if (! wp_script_is('moonulel-banner-slider', 'enqueued')) {
     167            if (!wp_script_is('moonulel-banner-slider', 'enqueued')) {
    168168                wp_enqueue_script(
    169169                    'moonulel-banner-slider',
     
    174174            }
    175175
    176             if (! wp_style_is('moonulel-banner-slider', 'enqueued')) {
     176            if (!wp_style_is('moonulel-banner-slider', 'enqueued')) {
    177177                wp_enqueue_style(
    178178                    'moonulel-banner-slider',
     
    187187        // Check and enqueue card slider
    188188        if ($widget_manager->moonulel_is_widget_enabled('moonulel-card-slider')) {
    189             if (! wp_script_is($this->plugin_name . '-card-slider', 'enqueued')) {
     189            if (!wp_script_is($this->plugin_name . '-card-slider', 'enqueued')) {
    190190                wp_enqueue_script(
    191191                    $this->plugin_name . '-card-slider',
     
    202202            $widget_manager->moonulel_is_widget_enabled('moonulel-logo-slider')
    203203        ) {
    204             if (! wp_script_is($this->plugin_name . '-customer-logo-slider', 'enqueued')) {
     204            if (!wp_script_is($this->plugin_name . '-customer-logo-slider', 'enqueued')) {
    205205                wp_enqueue_script(
    206206                    $this->plugin_name . '-customer-logo-slider',
     
    213213        }
    214214        if (
    215             $widget_manager->moonulel_is_widget_enabled('moonulel-post-slider')) {
     215            $widget_manager->moonulel_is_widget_enabled('moonulel-post-slider')
     216        ) {
    216217
    217218            // Check and enqueue post slider
    218             if (! wp_script_is($this->plugin_name . '-post-slider', 'enqueued')) {
     219            if (!wp_script_is($this->plugin_name . '-post-slider', 'enqueued')) {
    219220                wp_enqueue_script(
    220221                    $this->plugin_name . '-post-slider',
     
    227228        }
    228229
     230
     231        if ($widget_manager->moonulel_is_widget_enabled('moonulel-form')) {
     232            if (!wp_script_is('moonulel-form-script', 'enqueued')) {
     233                wp_enqueue_script(
     234                    'moonulel-form-script',
     235                    plugin_dir_url(dirname(dirname(__FILE__))) . 'includes/widgets/form/assets/js/moonulel-form.min.js',
     236                    ['jquery'],
     237                    time(),
     238                    true
     239                );
     240
     241                $recaptcha_site_key = get_option('moonulel_recaptcha_site_key', '');
     242                if (!empty($recaptcha_site_key)) {
     243                    $recaptcha_version = get_option('moonulel_recaptcha_version', 'v2');
     244                    if ($recaptcha_version === 'v2') {
     245                        wp_enqueue_script('google-recaptcha', 'https://www.google.com/recaptcha/api.js', [], null, true);
     246                    } else {
     247                        wp_enqueue_script('google-recaptcha-v3', 'https://www.google.com/recaptcha/api.js?render=' . esc_attr($recaptcha_site_key), [], null, true);
     248                    }
     249                }
     250
     251                wp_localize_script(
     252                    'moonulel-form-script',
     253                    'moonulel_ajax_object',
     254                    ['ajax_url' => admin_url('admin-ajax.php')]
     255                );
     256            }
     257
     258
     259            if (!wp_style_is('moonulel-form-style', 'enqueued')) {
     260                wp_enqueue_style(
     261                    'moonulel-form-style',
     262                    plugin_dir_url(dirname(dirname(__FILE__))) . 'includes/widgets/form/assets/css/moonulel-form.min.css',
     263                    [],
     264                    time()
     265                );
     266            }
     267        }
     268
    229269    }
    230270
     
    238278    private function has_slider_widget_in_data($elements_data)
    239279    {
    240         if (! is_array($elements_data)) {
     280        if (!is_array($elements_data)) {
    241281            return false;
    242282        }
     
    254294                return true;
    255295            }
    256             if (isset($element['elements']) && ! empty($element['elements'])) {
     296            if (isset($element['elements']) && !empty($element['elements'])) {
    257297                if ($this->has_slider_widget_in_data($element['elements'])) {
    258298                    return true;
     
    283323        ];
    284324
    285         if (in_array($widget_name, $slider_widgets) && ! self::$slick_loaded) {
     325        if (in_array($widget_name, $slider_widgets) && !self::$slick_loaded) {
    286326            $this->enqueue_slick_assets();
    287327            self::$slick_loaded = true;
     
    302342        }
    303343
    304      
     344
    305345        // Local fallback paths (minified versions)
    306         $slick_js_local    = plugin_dir_url(dirname(dirname(__FILE__))) . 'includes/widgets/assets/js/slick.min.js';
    307         $slick_css_local   = plugin_dir_url(dirname(dirname(__FILE__))) . 'includes/widgets/assets/css/slick.min.css';
     346        $slick_js_local = plugin_dir_url(dirname(dirname(__FILE__))) . 'includes/widgets/assets/js/slick.min.js';
     347        $slick_css_local = plugin_dir_url(dirname(dirname(__FILE__))) . 'includes/widgets/assets/css/slick.min.css';
    308348        $slick_theme_local = plugin_dir_url(dirname(dirname(__FILE__))) . 'includes/widgets/assets/css/slick-theme.min.css';
    309349
    310        
    311             wp_enqueue_style('slick-css', $slick_css_local, [], '1.9.0');
    312             wp_enqueue_style('slick-theme-css', $slick_theme_local, ['slick-css'], '1.9.0');
    313             wp_enqueue_script('slick', $slick_js_local, ['jquery'], '1.9.0', true);
    314    
     350
     351        wp_enqueue_style('slick-css', $slick_css_local, [], '1.9.0');
     352        wp_enqueue_style('slick-theme-css', $slick_theme_local, ['slick-css'], '1.9.0');
     353        wp_enqueue_script('slick', $slick_js_local, ['jquery'], '1.9.0', true);
     354
    315355
    316356        // Mark as loaded
     
    328368    public function register_widgets($widgets_manager)
    329369    {
    330  
     370
    331371        $widget_manager = new Moonulel_Widget_Options_Manager();
    332372
    333         if ($widget_manager->moonulel_is_widget_enabled('moonulel-banner-sleder')) {
     373        if ($widget_manager->moonulel_is_widget_enabled('moonulel-banner-slider')) {
    334374            require_once plugin_dir_path(dirname(__FILE__)) . 'widgets/slider/banner-slider/class-banner-slider.php';
    335375            $widgets_manager->register(new \MOONULEL_Banner_Slider_Widget());
     
    383423            $widgets_manager->register(new \MOONULEL_Posts_Template_Widget());
    384424        }
    385        
     425        if ($widget_manager->moonulel_is_widget_enabled('moonulel-form')) {
     426            require_once plugin_dir_path(dirname(__FILE__)) . 'widgets/form/class-form.php';
     427            $widgets_manager->register(new \MOONULEL_Form_Widget());
     428        }
     429
    386430    }
    387431
     
    411455        wp_localize_script($this->plugin_name . '-elementor-frontend', 'Moonulel_frontend', [
    412456            'ajaxurl' => admin_url('admin-ajax.php'),
    413             'nonce'   => wp_create_nonce('moonulel_elementor_nonce'),
    414             'i18n'    => [
     457            'nonce' => wp_create_nonce('moonulel_elementor_nonce'),
     458            'i18n' => [
    415459                'loading' => __('Loading...', 'moonstack-ultimate-elementor-kit'),
    416                 'error'   => __('Error occurred', 'moonstack-ultimate-elementor-kit'),
     460                'error' => __('Error occurred', 'moonstack-ultimate-elementor-kit'),
    417461            ],
    418462        ]);
     
    457501        wp_localize_script($this->plugin_name . '-elementor-editor', 'Moonulel_frontendEditor', [
    458502            'ajaxurl' => admin_url('admin-ajax.php'),
    459             'nonce'   => wp_create_nonce('moonulel_elementor_editor_nonce'),
     503            'nonce' => wp_create_nonce('moonulel_elementor_editor_nonce'),
    460504        ]);
    461505    }
     
    472516            'moonulel-elementor-elements' => [
    473517                'title' => __('Moonstack Ultimate Elementor Kit', 'moonstack-ultimate-elementor-kit'),
    474                 'icon'  => 'fa fa-plug',
     518                'icon' => 'fa fa-plug',
    475519            ],
    476520        ];
     
    531575                [
    532576                    'title' => $category_data['title'],
    533                     'icon'  => $category_data['icon'],
     577                    'icon' => $category_data['icon'],
    534578                ]
    535579            );
     
    552596        add_action('elementor/frontend/after_enqueue_styles', [$this, 'register_frontend_styles']);
    553597        add_action('elementor/editor/after_enqueue_scripts', [$this, 'register_editor_scripts']);
    554        
     598
    555599    }
    556600}
  • moonstack-ultimate-elementor-kit/trunk/includes/widgets/slider/assets/js/moonulel-card-slider.js

    r3427537 r3478936  
    1 (function($) {
     1(function ($) {
    22    'use strict';
    33
     
    88        if (!$sliders.length) return;
    99
    10         $sliders.each(function() {
     10        $sliders.each(function () {
    1111            var $slider = $(this);
    1212
     
    4040                lazyLoad: settings.lazyLoad || 'ondemand',
    4141                speed: settings.speed || 300,
    42                 cssEase: settings.cssEase || 'ease'
     42                cssEase: settings.cssEase || 'ease',
     43                responsive: settings.responsive || []
    4344            };
    4445
    4546            try {
    4647                $slider.slick(sliderSettings);
    47 //                 console.log('Card Slider initialized:', $slider.attr('id') || $slider);
     48                //                 console.log('Card Slider initialized:', $slider.attr('id') || $slider);
    4849            } catch (error) {
    4950                console.error('Card Slider: Error initializing Slick Slider for #' + $slider.attr('id'), error);
     
    5354
    5455    // Run on normal page load
    55     $(document).ready(function() {
     56    $(document).ready(function () {
    5657        initMsuekCardSlider($(document));
    5758    });
    5859
    5960    // Run inside Elementor editor (live preview)
    60     $(window).on('elementor/frontend/init', function() {
     61    $(window).on('elementor/frontend/init', function () {
    6162        elementorFrontend.hooks.addAction(
    6263            'frontend/element_ready/moonulel_card_slider.default',
    63             function($scope) {
     64            function ($scope) {
    6465                initMsuekCardSlider($scope);
    6566            }
  • moonstack-ultimate-elementor-kit/trunk/includes/widgets/slider/assets/js/moonulel-card-slider.min.js

    r3427537 r3478936  
    1 !function(e){"use strict";function i(i){var a=i.find(".moonulel-card-slider");a.length&&a.each(function(){var i=e(this);if(!(i.length&&i.hasClass("slick-initialized"))){var a=i.data("settings")||{},s={accessibility:void 0===a.accessibility||a.accessibility,adaptiveHeight:a.adaptiveHeight||!1,slidesToShow:a.slidesToShow||3,slidesToScroll:a.slidesToScroll||1,autoplay:a.autoplay||!1,autoplaySpeed:a.autoplaySpeed||3e3,infinite:void 0===a.infinite||a.infinite,arrows:void 0===a.arrows||a.arrows,dots:void 0===a.dots||a.dots,pauseOnHover:void 0===a.pauseOnHover||a.pauseOnHover,pauseOnFocus:void 0===a.pauseOnFocus||a.pauseOnFocus,pauseOnDotsHover:a.pauseOnDotsHover||!1,centerMode:a.centerMode||!1,centerPadding:a.centerPadding||"50px",draggable:void 0===a.draggable||a.draggable,fade:a.fade||!1,focusOnSelect:a.focusOnSelect||!1,initialSlide:a.initialSlide||0,lazyLoad:a.lazyLoad||"ondemand",speed:a.speed||300,cssEase:a.cssEase||"ease"};try{i.slick(s)}catch(o){console.error("Card Slider: Error initializing Slick Slider for #"+i.attr("id"),o)}}})}e(document).ready(function(){i(e(document))}),e(window).on("elementor/frontend/init",function(){elementorFrontend.hooks.addAction("frontend/element_ready/moonulel_card_slider.default",function(e){i(e)})})}(jQuery);
     1!function (e) { "use strict"; function i(i) { var a = i.find(".moonulel-card-slider"); a.length && a.each(function () { var i = e(this); if (!(i.length && i.hasClass("slick-initialized"))) { var a = i.data("settings") || {}, s = { accessibility: void 0 === a.accessibility || a.accessibility, adaptiveHeight: a.adaptiveHeight || !1, slidesToShow: a.slidesToShow || 3, slidesToScroll: a.slidesToScroll || 1, autoplay: a.autoplay || !1, autoplaySpeed: a.autoplaySpeed || 3e3, infinite: void 0 === a.infinite || a.infinite, arrows: void 0 === a.arrows || a.arrows, dots: void 0 === a.dots || a.dots, pauseOnHover: void 0 === a.pauseOnHover || a.pauseOnHover, pauseOnFocus: void 0 === a.pauseOnFocus || a.pauseOnFocus, pauseOnDotsHover: a.pauseOnDotsHover || !1, centerMode: a.centerMode || !1, centerPadding: a.centerPadding || "50px", draggable: void 0 === a.draggable || a.draggable, fade: a.fade || !1, focusOnSelect: a.focusOnSelect || !1, initialSlide: a.initialSlide || 0, lazyLoad: a.lazyLoad || "ondemand", speed: a.speed || 300, cssEase: a.cssEase || "ease", responsive: a.responsive || [] }; try { i.slick(s) } catch (o) { console.error("Card Slider: Error initializing Slick Slider for #" + i.attr("id"), o) } } }) } e(document).ready(function () { i(e(document)) }), e(window).on("elementor/frontend/init", function () { elementorFrontend.hooks.addAction("frontend/element_ready/moonulel_card_slider.default", function (e) { i(e) }) }) }(jQuery);
  • moonstack-ultimate-elementor-kit/trunk/includes/widgets/slider/card-slider/class-card-slider.php

    r3427537 r3478936  
    248248        );
    249249
    250         $this->add_control(
     250        $this->add_responsive_control(
    251251            'slides_to_show',
    252252            [
     
    255255                'default' => 3,
    256256                'min' => 1,
    257             ]
    258         );
    259 
    260         $this->add_control(
     257                'tablet_default' => 2,
     258                'mobile_default' => 1,
     259
     260            ]
     261        );
     262
     263        $this->add_responsive_control(
    261264            'slides_to_scroll',
    262265            [
     
    325328            ]
    326329        );
     330        // $this->add_control(
     331        //     'rtl',
     332        //     [
     333        //         'label' => __('RTL Mode', 'moonstack-ultimate-elementor-kit'),
     334        //         'type' => \Elementor\Controls_Manager::SWITCHER,
     335        //         'default' => 'no',
     336        //         'label_on' => __('Yes', 'moonstack-ultimate-elementor-kit'),
     337        //         'label_off' => __('No', 'moonstack-ultimate-elementor-kit'),
     338        //         'return_value' => 'yes',
     339        //     ]
     340        // );
    327341
    328342        $this->add_control(
     
    14011415
    14021416        // Prepare slider settings for JSON
    1403         $center_padding = preg_match('/^\d+(px|%)$/', $settings['center_padding']) ? $settings['center_padding'] : '50px';
     1417        $center_padding = preg_match('/^\d+(px|%)$/', (string) ($settings['center_padding'] ?? '')) ? $settings['center_padding'] : '50px';
     1418
     1419        $slides_to_show = !empty($settings['slides_to_show']) ? (int) $settings['slides_to_show'] : 3;
     1420        $slides_to_scroll = !empty($settings['slides_to_scroll']) ? (int) $settings['slides_to_scroll'] : 1;
     1421       
     1422        $slides_to_show_tablet = !empty($settings['slides_to_show_tablet']) ? (int) $settings['slides_to_show_tablet'] : $slides_to_show;
     1423        $slides_to_scroll_tablet = !empty($settings['slides_to_scroll_tablet']) ? (int) $settings['slides_to_scroll_tablet'] : $slides_to_scroll;
     1424       
     1425        $slides_to_show_mobile = !empty($settings['slides_to_show_mobile']) ? (int) $settings['slides_to_show_mobile'] : $slides_to_show_tablet;
     1426        $slides_to_scroll_mobile = !empty($settings['slides_to_scroll_mobile']) ? (int) $settings['slides_to_scroll_mobile'] : $slides_to_scroll_tablet;
    14041427
    14051428        $slider_settings = [
    14061429            'accessibility' => $settings['accessibility'] === 'yes',
    14071430            'adaptiveHeight' => $settings['adaptive_height'] === 'yes',
    1408             'slidesToShow' => (int) $settings['slides_to_show'],
    1409             'slidesToScroll' => (int) $settings['slides_to_scroll'],
     1431            'slidesToShow' => $slides_to_show,
     1432            'slidesToScroll' => $slides_to_scroll,
    14101433            'autoplay' => $settings['autoplay'] === 'yes',
    14111434            'autoplaySpeed' => (int) $settings['autoplay_speed'],
     
    14251448            'speed' => (int) $settings['speed'],
    14261449            'cssEase' => $settings['css_ease'],
     1450            'responsive' => [
     1451                [
     1452                    'breakpoint' => 1025,
     1453                    'settings' => [
     1454                        'slidesToShow' => $slides_to_show_tablet,
     1455                        'slidesToScroll' => $slides_to_scroll_tablet,
     1456                    ]
     1457                ],
     1458                [
     1459                    'breakpoint' => 768,
     1460                    'settings' => [
     1461                        'slidesToShow' => $slides_to_show_mobile,
     1462                        'slidesToScroll' => $slides_to_scroll_mobile,
     1463                    ]
     1464                ]
     1465            ]
    14271466        ];
    14281467
     
    14601499        $slider_settings_json = apply_filters('moonulel_card_slider_settings_json', $slider_settings_json, $slider_settings, $settings, $this);
    14611500        ?>
    1462         <div class="moonulel-card-slider moonulel_elementor_slider"
     1501        <div class="moonulel-card-slider moonulel_elementor_slider "
    14631502            id="moonulel-card-slider-<?php echo esc_attr($widget_id); ?>"
    14641503            data-settings="<?php echo esc_attr($slider_settings_json); ?>">
     
    15611600                            <?php
    15621601                            echo wp_kses(\Elementor\Plugin::instance()->frontend->get_builder_content_for_display(absint($slide['card_template'])), MOONULEL_HTML_Sanitizer::allowed_html());
    1563                            ?>
     1602                            ?>
    15641603                        </div>
    15651604                    <?php else: ?>
     
    16211660                                <div class="moonulel-card-button-wrapper elementor-widget-button">
    16221661                                    <?php
    1623                                  
     1662
    16241663                                    echo wp_kses($button_link_open, MOONULEL_HTML_Sanitizer::allowed_html());
    1625                                     echo  esc_html($slide['card_button_text']);
     1664                                    echo "<span class='elementor-button-content-wrapper'>";
     1665                                    echo esc_html($slide['card_button_text']);
     1666                                    echo "</span>";
    16261667                                    echo wp_kses($button_link_close, MOONULEL_HTML_Sanitizer::allowed_html()); ?>
    16271668                                </div>
     
    16301671                    <?php endif; ?>
    16311672                    <?php
    1632                      echo wp_kses($card_link_close, MOONULEL_HTML_Sanitizer::allowed_html()); ?>
     1673                    echo wp_kses($card_link_close, MOONULEL_HTML_Sanitizer::allowed_html()); ?>
    16331674                </div>
    16341675                <?php
  • moonstack-ultimate-elementor-kit/trunk/includes/widgets/slider/logo-slider/class-logo-slider.php

    r3427537 r3478936  
    710710            ]
    711711        );
     712        $this->add_group_control(
     713            \Elementor\Group_Control_Border::get_type(),
     714            [
     715                'name' => 'image_border',
     716                'selector' => '{{WRAPPER}} .moonulel-logo-img',
     717            ]
     718        );
     719
     720        $this->add_control(
     721            'image_border_radius',
     722            [
     723                'label' => __('Border Radius', 'moonstack-ultimate-elementor-kit'),
     724                'type' => \Elementor\Controls_Manager::DIMENSIONS,
     725                'size_units' => ['px', '%', 'em', 'rem'],
     726                'default' => [
     727                    'top' => '',
     728                    'right' => '',
     729                    'bottom' => '',
     730                    'left' => '',
     731                    'unit' => 'px',
     732                ],
     733                'selectors' => [
     734                    '{{WRAPPER}} .moonulel-logo-img' =>
     735                        'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
     736                ],
     737            ]
     738        );
    712739
    713740        $this->add_responsive_control(
     
    748775        );
    749776
     777
     778
    750779        $this->end_controls_section();
    751780    }
     
    922951    }
    923952
    924   protected function render()
    925 {
    926     $settings = $this->get_settings_for_display();
    927 
    928     /**
    929      * Filter: Modify widget settings before processing
    930      *
    931      * Allows developers to modify the widget settings array before any processing begins.
    932      * Useful for dynamically changing logo slider behavior based on conditions.
    933      *
    934      * @param array $settings The widget settings array
    935      * @param object $this The widget instance
    936      */
    937     $settings = apply_filters('moonulel_logo_slider_settings', $settings, $this);
    938 
    939     if (empty($settings['logos'])) {
     953    protected function render()
     954    {
     955        $settings = $this->get_settings_for_display();
     956
    940957        /**
    941          * Action: When no logos available
     958         * Filter: Modify widget settings before processing
    942959         *
    943          * Allows developers to add custom content when no logos are configured.
    944          * Useful for displaying placeholder content or fallback messages.
     960         * Allows developers to modify the widget settings array before any processing begins.
     961         * Useful for dynamically changing logo slider behavior based on conditions.
    945962         *
    946963         * @param array $settings The widget settings array
    947964         * @param object $this The widget instance
    948965         */
    949         do_action('moonulel_logo_slider_no_logos', $settings, $this);
    950         return;
    951     }
    952 
    953     wp_enqueue_script('slick-js');
    954     wp_enqueue_script($this->plugin_name . '-customer-logo-slider');
    955     wp_enqueue_style('slick-css');
    956     wp_enqueue_style('slick-theme-css');
    957 
    958     $slider_id = 'moonulel-logo-slider-' . $this->get_id();
    959     $global_title_position = $settings['title_position'] ?? 'below';
    960 
    961     /**
    962      * Filter: Modify slider ID
    963      *
    964      * Allows developers to customize the unique identifier for the logo slider.
    965      * Useful for integrating with external scripts or creating predictable IDs.
    966      *
    967      * @param string $slider_id The slider ID
    968      * @param array $settings The widget settings array
    969      * @param object $this The widget instance
    970      */
    971     $slider_id = apply_filters('moonulel_logo_slider_id', $slider_id, $settings, $this);
    972 
    973     // Prepare slider settings for data attribute
    974     $slider_settings = [
    975         'slidesToShow' => (int) ($settings['slides_to_show'] ?? 5),
    976         'slidesToScroll' => (int) ($settings['slides_to_scroll'] ?? 1),
    977         'autoplay' => $settings['autoplay'] === 'yes',
    978         'autoplaySpeed' => (int) ($settings['autoplay_speed'] ?? 1),
    979         'speed' => (int) ($settings['slider_speed'] ?? 4000),
    980         'infinite' => $settings['infinite'] === 'yes',
    981         'pauseOnHover' => $settings['pause_on_hover'] === 'yes',
    982         'centerMode' => $settings['center_mode'] === 'yes',
    983         'centerPadding' => $settings['center_mode'] === 'yes' ? (int) ($settings['center_padding'] ?? 50) . 'px' : '0px',
    984         'adaptiveHeight' => $settings['adaptive_height'] === 'yes',
    985         'arrows' => $settings['arrows'] === 'yes',
    986         'dots' => $settings['dots'] === 'yes',
    987         'rtl' => $settings['rtl'] === 'yes',
    988         'cssEase' => $settings['autoplay_ease'] ?? 'linear',
    989         'responsive' => [
    990             [
    991                 'breakpoint' => 1024,
    992                 'settings' => [
    993                     'slidesToShow' => (int) ($settings['slides_to_show_tablet'] ?? 3)
    994                 ]
    995             ],
    996             [
    997                 'breakpoint' => 768,
    998                 'settings' => [
    999                     'slidesToShow' => (int) ($settings['slides_to_show_mobile'] ?? 2)
    1000                 ]
    1001             ]
    1002         ]
    1003     ];
    1004 
    1005     /**
    1006      * Filter: Modify slider configuration options
    1007      *
    1008      * Allows developers to customize the slider JavaScript configuration.
    1009      * Useful for adding custom slider behaviors or modifying existing options.
    1010      *
    1011      * @param array $slider_settings The slider configuration array
    1012      * @param array $settings The widget settings array
    1013      * @param object $this The widget instance
    1014      */
    1015     $slider_settings = apply_filters('moonulel_logo_slider_options', $slider_settings, $settings, $this);
    1016 
    1017     /**
    1018      * Filter: Modify slider settings JSON
    1019      *
    1020      * Allows developers to customize the JSON-encoded slider settings string.
    1021      * Useful for adding custom data attributes or modifying the JSON output.
    1022      *
    1023      * @param string $slider_settings_json The JSON-encoded slider settings
    1024      * @param array $slider_settings The slider configuration array
    1025      * @param array $settings The widget settings array
    1026      * @param object $this The widget instance
    1027      */
    1028     $slider_settings_json = apply_filters('moonulel_logo_slider_settings_json', wp_json_encode($slider_settings), $slider_settings, $settings, $this);
    1029 
    1030     /**
    1031      * Filter: Modify hover scale value
    1032      *
    1033      * Allows developers to customize the hover scale effect value.
    1034      * Useful for conditional scaling or dynamic hover effects.
    1035      *
    1036      * @param float $hover_scale The hover scale value
    1037      * @param array $settings The widget settings array
    1038      * @param object $this The widget instance
    1039      */
    1040     $hover_scale = apply_filters('moonulel_logo_slider_hover_scale', $settings['hover_scale']['size'] ?? 1.1, $settings, $this);
    1041     ?>
    1042     <div id="<?php echo esc_attr($slider_id); ?>" class="moonulel-customer-logo-slider moonulel_elementor_slider"
    1043         data-settings='<?php
    1044         // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    1045          echo esc_attr($slider_settings_json); ?>'
    1046         data-hover-scale="<?php echo esc_attr($hover_scale); ?>">
    1047         <?php
     966        $settings = apply_filters('moonulel_logo_slider_settings', $settings, $this);
     967
     968        if (empty($settings['logos'])) {
     969            /**
     970             * Action: When no logos available
     971             *
     972             * Allows developers to add custom content when no logos are configured.
     973             * Useful for displaying placeholder content or fallback messages.
     974             *
     975             * @param array $settings The widget settings array
     976             * @param object $this The widget instance
     977             */
     978            do_action('moonulel_logo_slider_no_logos', $settings, $this);
     979            return;
     980        }
     981
     982        wp_enqueue_script('slick-js');
     983        wp_enqueue_script($this->plugin_name . '-customer-logo-slider');
     984        wp_enqueue_style('slick-css');
     985        wp_enqueue_style('slick-theme-css');
     986
     987        $slider_id = 'moonulel-logo-slider-' . $this->get_id();
     988        $global_title_position = $settings['title_position'] ?? 'below';
     989
    1048990        /**
    1049          * Filter: Modify logos array before rendering
     991         * Filter: Modify slider ID
    1050992         *
    1051          * Allows developers to modify the logos array before rendering.
    1052          * Useful for filtering logos, adding dynamic logos, or reordering.
     993         * Allows developers to customize the unique identifier for the logo slider.
     994         * Useful for integrating with external scripts or creating predictable IDs.
    1053995         *
    1054          * @param array $logos The logos array
     996         * @param string $slider_id The slider ID
    1055997         * @param array $settings The widget settings array
    1056998         * @param object $this The widget instance
    1057999         */
    1058         $logos = apply_filters('moonulel_logo_slider_logos', $settings['logos'], $settings, $this);
     1000        $slider_id = apply_filters('moonulel_logo_slider_id', $slider_id, $settings, $this);
     1001
     1002        // Prepare slider settings for data attribute
     1003        $slides_to_show = !empty($settings['slides_to_show']) ? (int) $settings['slides_to_show'] : 5;
     1004        $slides_to_scroll = !empty($settings['slides_to_scroll']) ? (int) $settings['slides_to_scroll'] : 1;
    10591005       
    1060         foreach ($logos as $index => $logo):
     1006        $slides_to_show_tablet = !empty($settings['slides_to_show_tablet']) ? (int) $settings['slides_to_show_tablet'] : $slides_to_show;
     1007       
     1008        $slides_to_show_mobile = !empty($settings['slides_to_show_mobile']) ? (int) $settings['slides_to_show_mobile'] : $slides_to_show_tablet;
     1009
     1010        $slider_settings = [
     1011            'slidesToShow' => $slides_to_show,
     1012            'slidesToScroll' => $slides_to_scroll,
     1013            'autoplay' => $settings['autoplay'] === 'yes',
     1014            'autoplaySpeed' => (int) ($settings['autoplay_speed'] ?? 1),
     1015            'speed' => (int) ($settings['slider_speed'] ?? 4000),
     1016            'infinite' => $settings['infinite'] === 'yes',
     1017            'pauseOnHover' => $settings['pause_on_hover'] === 'yes',
     1018            'centerMode' => $settings['center_mode'] === 'yes',
     1019            'centerPadding' => $settings['center_mode'] === 'yes' ? (int) ($settings['center_padding'] ?? 50) . 'px' : '0px',
     1020            'adaptiveHeight' => $settings['adaptive_height'] === 'yes',
     1021            'arrows' => $settings['arrows'] === 'yes',
     1022            'dots' => $settings['dots'] === 'yes',
     1023            'rtl' => $settings['rtl'] === 'yes',
     1024            'cssEase' => $settings['autoplay_ease'] ?? 'linear',
     1025            'responsive' => [
     1026                [
     1027                    'breakpoint' => 1024,
     1028                    'settings' => [
     1029                        'slidesToShow' => $slides_to_show_tablet
     1030                    ]
     1031                ],
     1032                [
     1033                    'breakpoint' => 768,
     1034                    'settings' => [
     1035                        'slidesToShow' => $slides_to_show_mobile
     1036                    ]
     1037                ]
     1038            ]
     1039        ];
     1040
     1041        /**
     1042         * Filter: Modify slider configuration options
     1043         *
     1044         * Allows developers to customize the slider JavaScript configuration.
     1045         * Useful for adding custom slider behaviors or modifying existing options.
     1046         *
     1047         * @param array $slider_settings The slider configuration array
     1048         * @param array $settings The widget settings array
     1049         * @param object $this The widget instance
     1050         */
     1051        $slider_settings = apply_filters('moonulel_logo_slider_options', $slider_settings, $settings, $this);
     1052
     1053        /**
     1054         * Filter: Modify slider settings JSON
     1055         *
     1056         * Allows developers to customize the JSON-encoded slider settings string.
     1057         * Useful for adding custom data attributes or modifying the JSON output.
     1058         *
     1059         * @param string $slider_settings_json The JSON-encoded slider settings
     1060         * @param array $slider_settings The slider configuration array
     1061         * @param array $settings The widget settings array
     1062         * @param object $this The widget instance
     1063         */
     1064        $slider_settings_json = apply_filters('moonulel_logo_slider_settings_json', wp_json_encode($slider_settings), $slider_settings, $settings, $this);
     1065
     1066        /**
     1067         * Filter: Modify hover scale value
     1068         *
     1069         * Allows developers to customize the hover scale effect value.
     1070         * Useful for conditional scaling or dynamic hover effects.
     1071         *
     1072         * @param float $hover_scale The hover scale value
     1073         * @param array $settings The widget settings array
     1074         * @param object $this The widget instance
     1075         */
     1076        $hover_scale = apply_filters('moonulel_logo_slider_hover_scale', $settings['hover_scale']['size'] ?? 1.1, $settings, $this);
     1077        ?>
     1078        <div id="<?php echo esc_attr($slider_id); ?>" dir="<?php echo esc_attr($settings['rtl'] === 'yes' ? 'rtl' : 'ltr'); ?>"
     1079            rtl="<?php echo esc_attr($settings['rtl'] === 'yes' ? 'true' : 'false'); ?>"
     1080            class="moonulel-customer-logo-slider moonulel_elementor_slider" data-settings='<?php
     1081            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
     1082            echo esc_attr($slider_settings_json); ?>' data-hover-scale="<?php echo esc_attr($hover_scale); ?>">
     1083            <?php
    10611084            /**
    1062              * Filter: Modify individual logo data
     1085             * Filter: Modify logos array before rendering
    10631086             *
    1064              * Allows developers to modify individual logo data before rendering.
    1065              * Useful for dynamic logo content or conditional modifications.
     1087             * Allows developers to modify the logos array before rendering.
     1088             * Useful for filtering logos, adding dynamic logos, or reordering.
    10661089             *
    1067              * @param array $logo The logo data array
    1068              * @param int $index The logo index
     1090             * @param array $logos The logos array
    10691091             * @param array $settings The widget settings array
    10701092             * @param object $this The widget instance
    10711093             */
    1072             $logo = apply_filters('moonulel_logo_slider_logo_data', $logo, $index, $settings, $this);
    1073 
    1074             $item_class = 'elementor-repeater-item-' . $logo['_id'];
    1075             $link_attrs = [];
    1076 
    1077             if (!empty($logo['logo_link']['url'])) {
    1078                 $link_attrs['href'] = esc_url($logo['logo_link']['url']);
    1079                 if ($logo['logo_link']['is_external']) {
    1080                     $link_attrs['target'] = '_blank';
     1094            $logos = apply_filters('moonulel_logo_slider_logos', $settings['logos'], $settings, $this);
     1095
     1096            foreach ($logos as $index => $logo):
     1097                /**
     1098                 * Filter: Modify individual logo data
     1099                 *
     1100                 * Allows developers to modify individual logo data before rendering.
     1101                 * Useful for dynamic logo content or conditional modifications.
     1102                 *
     1103                 * @param array $logo The logo data array
     1104                 * @param int $index The logo index
     1105                 * @param array $settings The widget settings array
     1106                 * @param object $this The widget instance
     1107                 */
     1108                $logo = apply_filters('moonulel_logo_slider_logo_data', $logo, $index, $settings, $this);
     1109
     1110                $item_class = 'elementor-repeater-item-' . $logo['_id'];
     1111                $link_attrs = [];
     1112
     1113                if (!empty($logo['logo_link']['url'])) {
     1114                    $link_attrs['href'] = esc_url($logo['logo_link']['url']);
     1115                    if ($logo['logo_link']['is_external']) {
     1116                        $link_attrs['target'] = '_blank';
     1117                    }
     1118                    if ($logo['logo_link']['nofollow']) {
     1119                        $link_attrs['rel'] = 'nofollow';
     1120                    }
     1121                    $link_attrs['class'] = 'moonulel-logo-link';
    10811122                }
    1082                 if ($logo['logo_link']['nofollow']) {
    1083                     $link_attrs['rel'] = 'nofollow';
    1084                 }
    1085                 $link_attrs['class'] = 'moonulel-logo-link';
    1086             }
    1087 
    1088             // Determine title position for this logo
    1089             $title_position = ($logo['title_position'] === 'default') ? $global_title_position : $logo['title_position'];
    1090             $show_title = $settings['show_title'] === 'yes' && !empty($logo['logo_title']) && $title_position !== 'hidden';
    1091 
    1092             // Title above image
    1093             $title_above = $show_title && $title_position === 'above';
    1094 
    1095             // Title below image (default)
    1096             $title_below = $show_title && $title_position === 'below';
    1097 
    1098             // Title as overlay
    1099             $title_overlay = $show_title && $title_position === 'overlay';
    1100 
    1101             // Title as tooltip
    1102             $title_tooltip = $show_title && $title_position === 'tooltip';
    1103 
    1104             /**
    1105              * Action: Before logo item output
    1106              *
    1107              * Allows developers to add content before each logo item.
    1108              * Useful for adding custom wrappers or additional elements.
    1109              *
    1110              * @param array $logo The logo data array
    1111              * @param int $index The logo index
    1112              * @param array $settings The widget settings array
    1113              * @param object $this The widget instance
    1114              */
    1115             do_action('moonulel_logo_slider_before_logo_item', $logo, $index, $settings, $this);
     1123
     1124                // Determine title position for this logo
     1125                $title_position = ($logo['title_position'] === 'default') ? $global_title_position : $logo['title_position'];
     1126                $show_title = $settings['show_title'] === 'yes' && !empty($logo['logo_title']) && $title_position !== 'hidden';
     1127
     1128                // Title above image
     1129                $title_above = $show_title && $title_position === 'above';
     1130
     1131                // Title below image (default)
     1132                $title_below = $show_title && $title_position === 'below';
     1133
     1134                // Title as overlay
     1135                $title_overlay = $show_title && $title_position === 'overlay';
     1136
     1137                // Title as tooltip
     1138                $title_tooltip = $show_title && $title_position === 'tooltip';
     1139
     1140                /**
     1141                 * Action: Before logo item output
     1142                 *
     1143                 * Allows developers to add content before each logo item.
     1144                 * Useful for adding custom wrappers or additional elements.
     1145                 *
     1146                 * @param array $logo The logo data array
     1147                 * @param int $index The logo index
     1148                 * @param array $settings The widget settings array
     1149                 * @param object $this The widget instance
     1150                 */
     1151                do_action('moonulel_logo_slider_before_logo_item', $logo, $index, $settings, $this);
     1152                ?>
     1153
     1154                <div class="moonulel-logo-item <?php echo esc_attr($item_class); ?>">
     1155                    <div class="moonulel-logo-inner">
     1156                        <?php if ($title_above): ?>
     1157                            <div class="moonulel-logo-title"><?php echo esc_html($logo['logo_title']); ?></div>
     1158                        <?php endif; ?>
     1159
     1160                        <?php if (!empty($link_attrs)): ?>
     1161                            <a <?php
     1162                            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
     1163                            echo $this->render_attributes($link_attrs); ?>>
     1164                            <?php endif; ?>
     1165
     1166                            <div class="moonulel-logo-media-wrap">
     1167                                <img class="moonulel-logo-img" src="<?php echo esc_url($logo['logo_image']['url']); ?>"
     1168                                    alt="<?php echo esc_attr($logo['logo_title'] ?: 'logo'); ?>"
     1169                                    loading="<?php echo esc_attr($settings['lazy_load'] === 'yes' ? 'lazy' : 'eager'); ?>" />
     1170
     1171                                <?php if ($settings['show_overlay'] === 'yes'): ?>
     1172                                    <div class="moonulel-logo-overlay"></div>
     1173                                <?php endif; ?>
     1174
     1175                                <?php if ($title_overlay): ?>
     1176                                    <div class="moonulel-logo-overlay-title"><?php echo esc_html($logo['logo_title']); ?></div>
     1177                                <?php endif; ?>
     1178
     1179                                <?php if ($title_tooltip): ?>
     1180                                    <div class="moonulel-logo-tooltip"><?php echo esc_html($logo['logo_title']); ?></div>
     1181                                <?php endif; ?>
     1182                            </div>
     1183
     1184                            <?php if (!empty($link_attrs)): ?>
     1185                            </a>
     1186                        <?php endif; ?>
     1187
     1188                        <?php if ($title_below): ?>
     1189                            <div class="moonulel-logo-title"><?php echo esc_html($logo['logo_title']); ?></div>
     1190                        <?php endif; ?>
     1191                    </div>
     1192                </div>
     1193
     1194                <?php
     1195                /**
     1196                 * Action: After logo item output
     1197                 *
     1198                 * Allows developers to add content after each logo item.
     1199                 * Useful for adding custom footers or additional elements.
     1200                 *
     1201                 * @param array $logo The logo data array
     1202                 * @param int $index The logo index
     1203                 * @param array $settings The widget settings array
     1204                 * @param object $this The widget instance
     1205                 */
     1206                do_action('moonulel_logo_slider_after_logo_item', $logo, $index, $settings, $this);
     1207            endforeach;
    11161208            ?>
    1117 
    1118             <div class="moonulel-logo-item <?php echo esc_attr($item_class); ?>">
    1119                 <div class="moonulel-logo-inner">
    1120                     <?php if ($title_above): ?>
    1121                         <div class="moonulel-logo-title"><?php echo esc_html($logo['logo_title']); ?></div>
    1122                     <?php endif; ?>
    1123 
    1124                     <?php if (!empty($link_attrs)): ?>
    1125                         <a <?php
    1126                          // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    1127                             echo $this->render_attributes($link_attrs); ?>>
    1128                         <?php endif; ?>
    1129 
    1130                         <div class="moonulel-logo-media-wrap">
    1131                             <img class="moonulel-logo-img" src="<?php echo esc_url($logo['logo_image']['url']); ?>"
    1132                                 alt="<?php echo esc_attr($logo['logo_title'] ?: 'logo'); ?>"
    1133                                 loading="<?php echo esc_attr($settings['lazy_load'] === 'yes' ? 'lazy' : 'eager'); ?>" />
    1134 
    1135                             <?php if ($settings['show_overlay'] === 'yes'): ?>
    1136                                 <div class="moonulel-logo-overlay"></div>
    1137                             <?php endif; ?>
    1138 
    1139                             <?php if ($title_overlay): ?>
    1140                                 <div class="moonulel-logo-overlay-title"><?php echo esc_html($logo['logo_title']); ?></div>
    1141                             <?php endif; ?>
    1142 
    1143                             <?php if ($title_tooltip): ?>
    1144                                 <div class="moonulel-logo-tooltip"><?php echo esc_html($logo['logo_title']); ?></div>
    1145                             <?php endif; ?>
    1146                         </div>
    1147 
    1148                         <?php if (!empty($link_attrs)): ?>
    1149                         </a>
    1150                     <?php endif; ?>
    1151 
    1152                     <?php if ($title_below): ?>
    1153                         <div class="moonulel-logo-title"><?php echo esc_html($logo['logo_title']); ?></div>
    1154                     <?php endif; ?>
    1155                 </div>
    1156             </div>
    1157 
    1158             <?php
    1159             /**
    1160              * Action: After logo item output
    1161              *
    1162              * Allows developers to add content after each logo item.
    1163              * Useful for adding custom footers or additional elements.
    1164              *
    1165              * @param array $logo The logo data array
    1166              * @param int $index The logo index
    1167              * @param array $settings The widget settings array
    1168              * @param object $this The widget instance
    1169              */
    1170             do_action('moonulel_logo_slider_after_logo_item', $logo, $index, $settings, $this);
    1171         endforeach;
    1172         ?>
    1173     </div>
    1174     <?php
    1175    
    1176 
    1177 }
    1178 
    1179   protected function moonulel_sanitize_hook_name($hook_name)
    1180     {
    1181      
     1209        </div>
     1210        <?php
     1211
     1212
     1213    }
     1214
     1215    protected function moonulel_sanitize_hook_name($hook_name)
     1216    {
     1217
    11821218        return MOONULEL_HTML_Sanitizer::sanitize_html($hook_name);
    11831219        // Allow only letters, numbers, and underscores
    11841220    }
    1185  
     1221
    11861222    protected function render_attributes($attributes)
    11871223    {
  • moonstack-ultimate-elementor-kit/trunk/moonstack-ultimate-elementor-kit.php

    r3427537 r3478936  
    1717 * Plugin URI:        https://moonstack.co
    1818 * Description:       Moonstack Ultimate Elementor Kit is a powerful all-in-one addon pack designed to supercharge your Elementor website building experience.
    19  * Version:           1.0.2
     19 * Version:           1.1.0
    2020 * Author:            Moonstack Team
    2121 * Author URI:        https://moonstack.co/
     
    3737 * Start at version 1.0.0 and update as you release new versions.
    3838 */
    39 define('MOONULEL_VERSION', '1.0.2');
     39define('MOONULEL_VERSION', '1.1.0');
    4040
    4141define('MOONULEL_PLUGIN_DIR', plugin_dir_path(__FILE__));
Note: See TracChangeset for help on using the changeset viewer.