Plugin Directory

Changeset 3463427


Ignore:
Timestamp:
02/17/2026 11:31:19 AM (8 hours ago)
Author:
creatorseo
Message:

2.0.1

  • Improved CSS caching architecture
Location:
cta-button-styler/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • cta-button-styler/trunk/class.cta-button-styler.php

    r3326232 r3463427  
    33
    44namespace ctabtn;
    5 if ( !defined('ABSPATH') ) exit; //Exit if accessed directly
     5if ( ! defined('ABSPATH') ) exit; // Exit if accessed directly
    66
    77class cta_button_styler {
    88    private $cta_name = "cta101";
    99    private $options = array(
    10         'margin-left'=>'5px',
    11         'margin-right'=>'5px',
    12         'margin-top'=>'5px',
    13         'margin-bottom'=>'5px',
    14         'padding-left'=>'15px',
    15         'padding-right'=>'15px',
    16         'padding-top'=>'15px',
    17         'padding-bottom'=>'15px',
    18         'background-color'=>'#ffffff',
    19         'color'=>'#f47721',
    20         'font-weight'=>'bold',
    21         'border-width'=>'3px',
    22         'border-style'=>'solid',
    23         'border-color'=>'#f47721',
    24         'border-radius'=>'20px',
    25         'cursor'=>'hand'
     10        'margin-left'      => '5px',
     11        'margin-right'     => '5px',
     12        'margin-top'       => '5px',
     13        'margin-bottom'    => '5px',
     14        'padding-left'     => '15px',
     15        'padding-right'    => '15px',
     16        'padding-top'      => '15px',
     17        'padding-bottom'   => '15px',
     18        'background-color' => '#ffffff',
     19        'color'            => '#f47721',
     20        'font-weight'      => 'bold',
     21        'border-width'     => '3px',
     22        'border-style'     => 'solid',
     23        'border-color'     => '#f47721',
     24        'border-radius'    => '20px',
     25        'cursor'           => 'hand'
    2626    );
    2727    private $hover_options = array(
    28         'background-color'=>'#f47721',
    29         'color'=>'#ffffff',
    30         'font-weight'=>'bold',
    31         'border-color'=>'#ffffff',
     28        'background-color' => '#f47721',
     29        'color'            => '#ffffff',
     30        'font-weight'      => 'bold',
     31        'border-color'     => '#ffffff',
    3232    );
    3333    private $button_effects = array(
    34         'shake'=>'OFF',
    35         'buzz'=>'OFF',
    36         'blink'=>'OFF',
     34        'shake' => 'OFF',
     35        'buzz'  => 'OFF',
     36        'blink' => 'OFF',
    3737    );
    3838    private $pluginloc = '';
    39 
     39   
    4040    /**
    4141     * Initialise the button styler plugin class
    4242     * @param string $loc the full directory and filename for the plugin
    4343     */
    44     public function __construct($loc){
    45         $this->pluginloc = strlen($loc)? $loc: __FILE__;
     44    public function __construct( $loc ) {
     45       
     46        $this->pluginloc = strlen($loc) ? $loc : __FILE__;
    4647        $basename = plugin_basename($this->pluginloc);
    47 
    48         if (is_admin()){
     48       
     49        if ( is_admin() ) {
    4950            add_action('admin_enqueue_scripts', array($this, 'ctabtn_enqueue_admin_scripts'));
    50             add_action('admin_init',array($this, 'ctabtn_register_settings'));
     51            add_action('admin_init', array($this, 'ctabtn_register_settings'));
    5152            add_action('admin_menu', array($this, 'ctabtn_menu'));
    52             add_filter('plugin_action_links_'.$basename, array($this, 'ctabtn_settings_link'));
    53             register_activation_hook($loc, array($this, 'ctabtn_load_options'));
    54             register_uninstall_hook ($loc, array($this, 'ctabtn_unset_options'));
    55             //register_deactivation_hook($loc, array($this, 'ctabtn_unset_options'));
     53            add_filter('plugin_action_links_' . $basename, array($this, 'ctabtn_settings_link'));
     54           
     55            register_activation_hook($loc, array($this, 'ctabtn_activate'));
     56            register_uninstall_hook($loc, array(__CLASS__, 'ctabtn_uninstall_static'));
     57//          if ( ! has_filter('dashboard_glance_items', array($this, 'ctabtn_filter_glance_items')) ) {
     58//              add_filter('dashboard_glance_items', array($this, 'ctabtn_filter_glance_items'), 20, 1);
     59//          }
     60           
     61            // Regenerate cached CSS file when settings change
     62            add_action('update_option_cta_button_name', array($this, 'ctabtn_write_css_file'), 10, 0);
     63            add_action('update_option_cta_button_options', array($this, 'ctabtn_write_css_file'), 10, 0);
     64            add_action('update_option_cta_button_hover_options', array($this, 'ctabtn_write_css_file'), 10, 0);
     65            add_action('update_option_cta_button_effects', array($this, 'ctabtn_write_css_file'), 10, 0);
     66           
    5667        } else {
    5768            add_action('wp_enqueue_scripts', array($this, 'ctabtn_enqueue_scripts'));
    5869        }
    59         add_action('wp_ajax_ctabtn_fetch_styles', 'ctabtn_fetch_styles');
    60         add_action('wp_ajax_nopriv_ctabtn_fetch_styles', 'ctabtn_fetch_styles');
    61         //add_action('wp_head', 'ctabtn_style_in_header');
    62     }
    63 
    64 // -------------------- Add styles and scripts --------------------
     70       
     71//      add_action('wp_ajax_ctabtn_fetch_styles', 'ctabtn_fetch_styles');
     72//      add_action('wp_ajax_nopriv_ctabtn_fetch_styles', 'ctabtn_fetch_styles');
     73    }
     74   
     75    // -------------------- Add styles and scripts --------------------
    6576    function ctabtn_enqueue_admin_scripts(){
    66         wp_enqueue_style('cta-button-css', plugins_url('css/cta-button-styler.css', __FILE__));
    67         wp_enqueue_style( 'wp-color-picker' );
     77        wp_enqueue_style('cta-button-css', plugins_url('css/cta-button-styler.css', __FILE__), [], CTABTN_VERSION);
     78        //wp_enqueue_style('wp-color-picker');
     79       
     80        $this->ctabtn_enqueue_generated_css('cta-button-generated-css-admin');
     81       
     82        // ✅ CHANGE: make effects libs hard dependencies of your script (load order guaranteed)
    6883        wp_enqueue_script(
    6984            'cta-menu-button-js',
    7085            plugins_url('js/ctabtn-scripts.js', __FILE__),
    71             ['jquery', 'jquery-ui-core', 'wp-color-picker'], false, true
     86            ['jquery', 'jquery-ui-core', 'jquery-effects-core', 'jquery-effects-pulsate', 'wp-color-picker', 'wp-color-picker'],
     87            CTABTN_VERSION,
     88            true
    7289        );
    73         wp_localize_script( 'cta-menu-button-js', 'ctabtn', array('ajax_url' => admin_url('admin-ajax.php')));
    74         wp_enqueue_script("jquery-effects-pulsate");
    75     }
    76 
     90       
     91        $cls = (string) get_option('cta_button_name');
     92        $cls = (strlen($cls) >= 5) ? $cls : 'cta101';
     93        $cls = sanitize_html_class($cls);
     94       
     95        $opt2 = get_option('cta_button_effects');
     96        $opt2 = is_array($opt2) ? $opt2 : [];
     97       
     98        wp_localize_script('cta-menu-button-js', 'ctabtn', [
     99            'ajax_url' => admin_url('admin-ajax.php'),
     100            'class'    => $cls,
     101            'effects'  => [
     102                'shake' => (!empty($opt2['shake']) && $opt2['shake'] === 'ON') ? 1 : 0,
     103                'buzz'  => (!empty($opt2['buzz'])  && $opt2['buzz']  === 'ON') ? 1 : 0,
     104                'blink' => (!empty($opt2['blink']) && $opt2['blink'] === 'ON') ? 1 : 0,
     105            ],
     106        ]);
     107    }
     108   
    77109    function ctabtn_enqueue_scripts(){
    78         wp_enqueue_style('cta-button-css', plugins_url('css/cta-button-styler.css', __FILE__));
     110        wp_enqueue_style('cta-button-css', plugins_url('css/cta-button-styler.css', __FILE__), [], CTABTN_VERSION);
     111       
     112        $this->ctabtn_enqueue_generated_css('cta-button-generated-css');
     113       
     114        //make effects libs hard dependencies of your script (load order guaranteed)
    79115        wp_enqueue_script(
    80116            'cta-menu-button-js',
    81117            plugins_url('js/ctabtn-scripts.js', __FILE__),
    82             ['jquery', 'jquery-ui-core'], false, true
     118            ['jquery', 'jquery-ui-core', 'jquery-effects-core', 'jquery-effects-pulsate'],
     119            CTABTN_VERSION,
     120            true
    83121        );
    84         wp_localize_script( 'cta-menu-button-js', 'ctabtn', array('ajax_url' => admin_url('admin-ajax.php')));
    85         wp_enqueue_script("jquery-effects-pulsate");
    86     }
    87 
    88 // -------------------- Add a menu item to the settings (themes) menu --------------------
     122       
     123        $cls = (string) get_option('cta_button_name');
     124        $cls = (strlen($cls) >= 5) ? $cls : 'cta101';
     125        $cls = sanitize_html_class($cls);
     126       
     127        $opt2 = get_option('cta_button_effects');
     128        $opt2 = is_array($opt2) ? $opt2 : [];
     129       
     130        wp_localize_script('cta-menu-button-js', 'ctabtn', [
     131            'ajax_url' => admin_url('admin-ajax.php'),
     132            'class'    => $cls,
     133            'effects'  => [
     134                'shake' => (!empty($opt2['shake']) && $opt2['shake'] === 'ON') ? 1 : 0,
     135                'buzz'  => (!empty($opt2['buzz'])  && $opt2['buzz']  === 'ON') ? 1 : 0,
     136                'blink' => (!empty($opt2['blink']) && $opt2['blink'] === 'ON') ? 1 : 0,
     137            ],
     138        ]);
     139    }
     140   
     141    private function ctabtn_enqueue_generated_css( $handle ) {
     142        $path = $this->ctabtn_css_abs_path();
     143        $url  = $this->ctabtn_css_url();
     144       
     145        $ver = (file_exists($path) ? (string) filemtime($path) : '');
     146       
     147        // Fallback: generate once if missing
     148        if ( empty($ver) ) {
     149            $this->ctabtn_write_css_file();
     150            $ver = (file_exists($path) ? (string) filemtime($path) : '');
     151        }
     152       
     153        // If still missing, skip enqueue (avoids 404s)
     154        if ( file_exists($path) ) {
     155            wp_enqueue_style($handle, $url, array(), $ver);
     156        }
     157    }
     158   
     159    // -------------------- Add a menu item to the settings (themes) menu --------------------
     160   
    89161    function ctabtn_menu() {
    90         add_theme_page('Call to Action (CTA) button Styler', 'CTA Button Styler',
    91             'edit_theme_options', 'cta_button_styler', array($this,'ctabtn_options_page'));
    92     }
    93 
    94 // -------------------- Add a link to the plugin to point to the settings location --------------------
    95 
    96     /**
    97      * Add links to Settings page
    98      */
    99     function ctabtn_settings_link($links) {
    100         $url = get_admin_url().'themes.php?page=cta_button_styler';
    101         $settings_link = '<a href="'.$url.'">' . __("Settings") . '</a>';
    102         array_unshift( $links, $settings_link );
     162        add_theme_page(
     163            'Call to Action (CTA) button Styler',
     164            'CTA Button Styler',
     165            'edit_theme_options',
     166            'cta_button_styler',
     167            array($this, 'ctabtn_options_page')
     168        );
     169    }
     170   
     171    // -------------------- Add a link to the plugin to point to the settings location --------------------
     172   
     173    function ctabtn_settings_link( $links ) {
     174        $url = get_admin_url() . 'themes.php?page=cta_button_styler';
     175        $settings_link = '<a href="' . $url . '">' . __("Settings", "cta-button-styler") . '</a>';
     176        array_unshift($links, $settings_link);
    103177        return $links;
    104178    }
    105 
    106 // -------------------- Define and create the options update page --------------------
    107 
    108     /**
    109      * Register the plugin settings that will be stored to the option table and displayed on the menu page
    110      */
    111     function ctabtn_register_settings(){
    112         //$this->temp .= 'Settings Registered...';
     179   
     180    // -------------------- Define and create the options update page --------------------
     181   
     182    function ctabtn_register_settings() {
    113183        register_setting('cta_button_template_group', 'cta_button_name', array($this, 'ctabtn_validate'));
    114184        register_setting('cta_button_template_group', 'cta_button_options', array($this, 'ctabtn_validate'));
     
    116186        register_setting('cta_button_template_group', 'cta_button_effects', array($this, 'ctabtn_validate'));
    117187    }
    118 
    119     /**
    120      * Validate and transform the values submitted to the options form
    121      * @param array $input - options results from the form submission
    122      * @return array|false - validated and transformed options results
    123      */
    124     function ctabtn_validate($input){
    125         $output = [];
    126         $checkArr = [
    127             'margin-left'=>['0px', '5px', '10px', '15px', '20px', '40px', '60px', '80px', '110px', '150px'],
    128             'margin-right'=>['0px', '5px', '10px', '15px', '20px', '40px', '60px', '80px', '110px', '150px'],
    129             'margin-top'=>['0px', '5px', '10px', '15px', '20px', '40px', '60px', '80px', '110px', '150px'],
    130             'margin-bottom'=>['0px', '5px', '10px', '15px', '20px', '40px', '60px', '80px', '110px', '150px'],
    131             'padding-left'=>['2px', '5px', '7px', '10px', '15px', '20px', '30px', '40px', '50px'],
    132             'padding-right'=>['2px', '5px', '7px', '10px', '15px', '20px', '30px', '40px', '50px'],
    133             'padding-top'=>['2px', '5px', '7px', '10px', '15px', '20px', '30px', '40px', '50px'],
    134             'padding-bottom'=>['2px', '5px', '7px', '10px', '15px', '20px', '30px', '40px', '50px'],
    135             'background-color'=>[],
    136             'color'=>[],
    137             'font-weight'=>['normal', 'bold', 'bolder', 'lighter'],
    138             'border-width'=>['thin', 'medium', 'thick', '1px', '2px', '10px'],
    139             'border-style'=>['none', 'solid', 'dotted', 'groove', 'ridge', 'inset', 'outset', 'double'],
    140             'border-color'=>[],
    141             'border-radius'=>['0px', '5px', '10px', '15px', '20px', '25px', '30px'],
    142             'cursor'=>['crosshair', 'default', 'hand', 'help', 'pointer'],
    143             'switch'=>['ON', 'OFF']
    144         ];
    145         if ( is_array($input) ){
    146             foreach ($input as $att=>$val) {
    147                 if (in_array($att, ['color','background-color','border-color'])){
    148                     //sanitize color values
    149                     if(preg_match('/^#[a-f0-9]{6}$/i', $val)){
     188   
     189    function ctabtn_validate( $input ) {
     190        $output = array();
     191        $checkArr = array(
     192            'margin-left'      => array('0px', '5px', '10px', '15px', '20px', '40px', '60px', '80px', '110px', '150px'),
     193            'margin-right'     => array('0px', '5px', '10px', '15px', '20px', '40px', '60px', '80px', '110px', '150px'),
     194            'margin-top'       => array('0px', '5px', '10px', '15px', '20px', '40px', '60px', '80px', '110px', '150px'),
     195            'margin-bottom'    => array('0px', '5px', '10px', '15px', '20px', '40px', '60px', '80px', '110px', '150px'),
     196            'padding-left'     => array('2px', '5px', '7px', '10px', '15px', '20px', '30px', '40px', '50px'),
     197            'padding-right'    => array('2px', '5px', '7px', '10px', '15px', '20px', '30px', '40px', '50px'),
     198            'padding-top'      => array('2px', '5px', '7px', '10px', '15px', '20px', '30px', '40px', '50px'),
     199            'padding-bottom'   => array('2px', '5px', '7px', '10px', '15px', '20px', '30px', '40px', '50px'),
     200            'background-color' => array(),
     201            'color'            => array(),
     202            'font-weight'      => array('normal', 'bold', 'bolder', 'lighter'),
     203            'border-width'     => array('thin', 'medium', 'thick', '1px', '2px', '10px'),
     204            'border-style'     => array('none', 'solid', 'dotted', 'groove', 'ridge', 'inset', 'outset', 'double'),
     205            'border-color'     => array(),
     206            'border-radius'    => array('0px', '5px', '10px', '15px', '20px', '25px', '30px'),
     207            'cursor'           => array('crosshair', 'default', 'hand', 'help', 'pointer'),
     208            'switch'           => array('ON', 'OFF')
     209        );
     210       
     211        if ( is_array($input) ) {
     212            foreach ($input as $att => $val) {
     213                if ( in_array($att, array('color','background-color','border-color'), true) ) {
     214                    if ( preg_match('/^#[a-f0-9]{6}$/i', $val) ) {
    150215                        $output[$att] = $val;
    151216                    }
    152                 } elseif ( isset($checkArr[$att]) ){
    153                     if (in_array($val,$checkArr[$att])){
     217                } elseif ( isset($checkArr[$att]) ) {
     218                    if ( in_array($val, $checkArr[$att], true) ) {
    154219                        $output[$att] = sanitize_text_field($val);
    155220                    }
    156221                } else {
    157                     if (in_array($val,$checkArr['switch'])){
     222                    if ( in_array($val, $checkArr['switch'], true) ) {
    158223                        $output[$att] = sanitize_text_field($val);
    159224                    }
     
    163228            $output = preg_replace("/[^A-Za-z0-9 ]/", '', sanitize_text_field($input));
    164229        }
     230       
    165231        return $output;
    166232    }
    167 
    168     /**
    169      * Draw the data (styles) manipulation page
    170      */
     233   
    171234    function ctabtn_options_page() {
    172         $opt = get_option('cta_button_options');
     235        $opt  = get_option('cta_button_options');
    173236        $opt1 = get_option('cta_button_hover_options');
    174237        $opt2 = get_option('cta_button_effects');
    175         $opt = is_array($opt)? array_merge($this->options,$opt): $this->options;
    176         $opt1 = is_array($opt1)? array_merge($this->hover_options,$opt1): $this->hover_options;
    177         $opt2 = is_array($opt2)? array_merge($this->button_effects,$opt2): $this->button_effects;
     238        $opt  = is_array($opt)  ? array_merge($this->options, $opt)  : $this->options;
     239        $opt1 = is_array($opt1) ? array_merge($this->hover_options, $opt1) : $this->hover_options;
     240        $opt2 = is_array($opt2) ? array_merge($this->button_effects, $opt2) : $this->button_effects;
    178241        $name = get_option('cta_button_name');
    179         $name = strlen($name)>=5? $name: "cta101";
    180 
    181         if(current_user_can('manage_options')) {
     242        $name = strlen($name) >= 5 ? $name : "cta101";
     243       
     244        if ( current_user_can('manage_options') ) {
    182245            echo "<div class='wrap'>";
    183                 echo "<h2>Call-To-Action Button Styling</h2>";
    184                 //echo "<h3>Temp</h3><div style='padding: 10px 0'>".$this->temp."</div>";
    185                 echo "<div style='padding: 10px 0'><button class='".$name."'>Sample Call to Action Button</button>";
    186                 echo "<span class='cta_message'><em> <==== Give me a second - watch here</em></span>";
    187                 echo "<p><em>Save changes to the options to see the style changes in the button above.</em></p></div>";
    188                 settings_errors(); //turn on settings notification
    189 
    190                     echo "<form action='options.php' method='post'>";
    191                     settings_fields('cta_button_template_group'); //This line must be inside the form tags
    192                     //do_settings_fields('cta_button_template_group');
    193 
    194                     echo "<table class='cta-form-table'>";
    195                     echo "<tr class='cta-input-hdr'><th colspan='4'>GENERAL SETTINGS</th></tr>";
    196                     $txt = "Use the Button Class Label below (i.e. '".$name."') to style any menus or text buttons on ".
    197                            "your site (case-sensitive). Either wrap the text in a &lt;span clsss='cta101'&gt...&lt;/span&gt ".
    198                            "element to create a button around any text or assign the class to a menu element ".
    199                            "(as described in the help text).";
    200                     echo "<tr><td colspan='4'><em>".$txt."</em></td></tr>";
    201 
    202                     echo "<tr class='cta-hdr'><td colspan='4'>Button Class Label</td></tr>";
    203                     echo "<tr><td colspan='4'>".$name."<input type='hidden' name='cta_button_name' size='17' value='".$name."' /></td></tr>";
    204 
    205                     echo "<tr class='cta-input-hdr'><th colspan='4'>BUTTON SETTINGS</th></tr>";
    206                     echo "<tr class='cta-hdr'><td colspan='4'>Margin Space</td></tr>";
    207                     $ets = array('0px', '5px', '10px', '15px', '20px', '40px', '60px', '80px', '110px', '150px');
    208                     echo "<tr class='cta-bod'><td>Left</td><td>Right</td><td>Top</td><td>Bottom</td></tr>";
    209                     echo "<tr class='cta-bod'><td>".cta_button_dynamic_options($ets,'cta_button_options[margin-left]',esc_attr($opt['margin-left']),'',false)."</td>";
    210                     echo "<td>".cta_button_dynamic_options($ets,'cta_button_options[margin-right]',esc_attr($opt['margin-right']),'',false)."</td>";
    211                     echo "<td>".cta_button_dynamic_options($ets,'cta_button_options[margin-top]',esc_attr($opt['margin-top']),'',false)."</td>";
    212                     echo "<td>".cta_button_dynamic_options($ets,'cta_button_options[margin-bottom]',esc_attr($opt['margin-bottom']),'',false)."</td></tr>";
    213                     //echo "<tr class='cta-bod'><td>".."</td>";
    214 
    215                     echo "<tr class='cta-hdr'><td colspan='4'>Text Padding</td></tr>";
    216                     $ets = array('2px', '5px', '7px', '10px', '15px', '20px', '30px', '40px', '50px');
    217                     echo "<tr class='cta-bod'><td>Left</td><td>Right</td><td>Top</td><td>Bottom</td></tr>";
    218                     echo "<tr class='cta-bod'><td>".cta_button_dynamic_options($ets,'cta_button_options[padding-left]',esc_attr($opt['padding-left']),'',false)."</td>";
    219                     echo "<td>".cta_button_dynamic_options($ets,'cta_button_options[padding-right]',esc_attr($opt['padding-right']),'',false)."</td>";
    220                     echo "<td>".cta_button_dynamic_options($ets,'cta_button_options[padding-top]',esc_attr($opt['padding-top']),'',false)."</td>";
    221                     echo "<td>".cta_button_dynamic_options($ets,'cta_button_options[padding-bottom]',esc_attr($opt['padding-bottom']),'',false)."</td></tr>";
    222 
    223                     echo "<tr class='cta-hdr'><td colspan='4'>Button Colors</td></tr>";
    224                     echo "<tr class='cta-bod'><td>Background</td><td colspan='3'>Label Text</td></tr>";
    225                     $val = esc_attr($opt['background-color']);
    226                     echo "<tr class='cta-bod'><td>".cta_button_color_picker('cta_button_options[background-color]',$val,$val,'',false)."</td>";
    227                     $val = esc_attr($opt['color']);
    228                     echo "<td colspan='2'>".cta_button_color_picker('cta_button_options[color]',$val,$val,'',false)."</td></tr>";
    229 
    230                     echo "<tr class='cta-hdr'><td colspan='4'>Button Border</td></tr>";
    231                     echo "<tr class='cta-bod'><td>Color</td><td>Width</td><td>Style</td><td>Radius</td></tr>";
    232                     $val = esc_attr($opt['border-color']);
    233                     echo "<tr class='cta-bod'><td>".cta_button_color_picker('cta_button_options[border-color]',$val,$val,'',false)."</td>";
    234                     $ets = array('thin', 'medium', 'thick', '1px', '2px', '10px');
    235                     echo "<td>".cta_button_dynamic_options($ets,'cta_button_options[border-width]',esc_attr($opt['border-width']),'',false)."</td>";
    236                     $ets = array('none', 'solid', 'dotted', 'groove', 'ridge', 'inset', 'outset', 'double');
    237                     echo "<td>".cta_button_dynamic_options($ets,'cta_button_options[border-style]',esc_attr($opt['border-style']),'',false)."</td>";
    238                     $ets = array('0px', '5px', '10px', '15px', '20px', '25px', '30px');
    239                     echo "<td>".cta_button_dynamic_options($ets,'cta_button_options[border-radius]',esc_attr($opt['border-radius']),'',false)."</td></tr>";
    240 
    241                     echo "<tr class='cta-hdr'><td colspan='4'>Other</td></tr>";
    242                     echo "<tr class='cta-bod'><td>Font Weight</td><td colspan='3'>Cursor</td></tr>";
    243                     $ets = array('normal', 'bold', 'bolder', 'lighter');
    244                     echo "<tr class='cta-bod'><td>".cta_button_dynamic_options($ets,'cta_button_options[font-weight]',esc_attr($opt['font-weight']),'',false)."</td>";
    245                     $ets = array('crosshair', 'default', 'hand', 'help', 'pointer');
    246                     echo "<td colspan='3'>".cta_button_dynamic_options($ets,'cta_button_options[cursor]',esc_attr($opt['cursor']),'',false)."</td></tr>";
    247 
    248                     //-----------------------------------------------------------------
    249                     echo "<tr class='cta-input-hdr'><th colspan='4'>BUTTON HOVER STYLES</th></tr>";
    250                     $txt = "These are the styles that will display when the mouse is hovered over the button.";
    251                     echo "<tr><td colspan='4'><em>".$txt."</em></td></tr>";
    252 
    253                     echo "<tr class='cta-hdr'><td colspan='4'>Button Styles</td></tr>";
    254                     echo "<tr class='cta-bod'><td>Color</td><td>Label Color</td><td>Font Weight</td><td>Border Color</td></tr>";
    255                     $val = esc_attr($opt1['background-color']);
    256                     echo "<tr class='cta-bod'><td>".cta_button_color_picker('cta_button_hover_options[background-color]',$val,$val,'',false)."</td>";
    257                     $val = esc_attr($opt1['color']);
    258                     echo "<td>".cta_button_color_picker('cta_button_hover_options[color]',$val,$val,'',false)."</td>";
    259                     $ets = array('normal', 'bold', 'bolder', 'lighter');
    260                     echo "<td>".cta_button_dynamic_options($ets,'cta_button_hover_options[font-weight]',esc_attr($opt1['font-weight']),'',false)."</td>";
    261                     $val = esc_attr($opt1['border-color']);
    262                     echo "<td>".cta_button_color_picker('cta_button_hover_options[border-color]',$val,$val,'',false)."</td></tr>";
    263 
    264                     //-----------------------------------------------------------------
    265                     echo "<tr class='cta-input-hdr'><th colspan='4'>BUTTON EFFECTS</th></tr>";
    266                     $txt = "There are 3 different animation effects that can be switched on or off. These are meant to ".
    267                            "highlight the Call To Action (CTA) button. If more than one effect is switched on, the ".
    268                            "effects will run sequentially in the order listed. Usually only one effect is switched on.";
    269                     echo "<tr><td colspan='4'><em>".$txt."</em></td></tr>";
    270 
    271                     echo "<tr class='cta-hdr'><td colspan='4'>Effects</td></tr>";
    272                     $ets = array('ON', 'OFF');
    273                     $choice = cta_button_dynamic_options($ets,'cta_button_effects[shake]',esc_attr($opt2['shake']),'',false);
    274                     echo "<tr class='cta-bod'><td>Shake</td><td colspan='3'>".$choice."</td></tr>";
    275                     $choice = cta_button_dynamic_options($ets,'cta_button_effects[buzz]',esc_attr($opt2['buzz']),'',false);
    276                     echo "<tr class='cta-bod'><td>Buzz</td><td colspan='3'>".$choice."</td></tr>";
    277                     $choice = cta_button_dynamic_options($ets,'cta_button_effects[blink]',esc_attr($opt2['blink']),'',false);
    278                     echo "<tr class='cta-bod'><td>Blink</td><td colspan='3'>".$choice."</td></tr>";
    279 
    280                     echo "</table>";
    281                     submit_button();
    282                 echo "</form>";
     246            echo "<h2>Call-To-Action Button Styling</h2>";
     247            echo "<div style='padding: 10px 0'><button class='" . esc_html($name) . "'>Sample Call to Action Button</button>";
     248            echo "<span class='cta_message'><em> <==== Give me a second - watch here</em></span>";
     249            echo "<p><em>Save changes to the options to see the style changes in the button above.</em></p></div>";
     250            settings_errors();
     251            echo "<form action='options.php' method='post'>";
     252            settings_fields('cta_button_template_group');
     253            echo "<table class='cta-form-table'>";
     254            echo "<tr class='cta-input-hdr'><th colspan='4'>GENERAL SETTINGS</th></tr>";
     255            $txt = "Use the Button Class Label below (i.e. '".$name."') to style any menus or text buttons on " .
     256                   "your site (case-sensitive). Either wrap the text in a &lt;span clsss='cta101'&gt...&lt;/span&gt " .
     257                   "element to create a button around any text or assign the class to a menu element " .
     258                   "(as described in the help text).";
     259            echo "<tr><td colspan='4'><em>" . esc_html($txt) . "</em></td></tr>";
     260            echo "<tr class='cta-hdr'><td colspan='4'>Button Class Label</td></tr>";
     261            echo "<tr><td colspan='4'>" . esc_html($name) . "<input type='hidden' name='cta_button_name' size='17' value='" . esc_html($name) . "' /></td></tr>";
     262            echo "<tr class='cta-input-hdr'><th colspan='4'>BUTTON SETTINGS</th></tr>";
     263            echo "<tr class='cta-hdr'><td colspan='4'>Margin Space</td></tr>";
     264            // Safe: all dynamic values are escaped inside cta_button_dynamic_options() and cta_button_color_picker().
     265            // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
     266            $ets = array('0px', '5px', '10px', '15px', '20px', '40px', '60px', '80px', '110px', '150px');
     267            echo "<tr class='cta-bod'><td>Left</td><td>Right</td><td>Top</td><td>Bottom</td></tr>";
     268            echo "<tr class='cta-bod'><td>" . cta_button_dynamic_options($ets,'cta_button_options[margin-left]',esc_attr($opt['margin-left'])) . "</td>";
     269            echo "<td>" . cta_button_dynamic_options($ets,'cta_button_options[margin-right]',esc_attr($opt['margin-right'])) . "</td>";
     270            echo "<td>" . cta_button_dynamic_options($ets,'cta_button_options[margin-top]',esc_attr($opt['margin-top'])) . "</td>";
     271            echo "<td>" . cta_button_dynamic_options($ets,'cta_button_options[margin-bottom]',esc_attr($opt['margin-bottom'])) . "</td></tr>";
     272            echo "<tr class='cta-hdr'><td colspan='4'>Text Padding</td></tr>";
     273            $ets = array('2px', '5px', '7px', '10px', '15px', '20px', '30px', '40px', '50px');
     274            echo "<tr class='cta-bod'><td>Left</td><td>Right</td><td>Top</td><td>Bottom</td></tr>";
     275            echo "<tr class='cta-bod'><td>" . cta_button_dynamic_options($ets,'cta_button_options[padding-left]',esc_attr($opt['padding-left'])) . "</td>";
     276            echo "<td>" . cta_button_dynamic_options($ets,'cta_button_options[padding-right]',esc_attr($opt['padding-right'])) . "</td>";
     277            echo "<td>" . cta_button_dynamic_options($ets,'cta_button_options[padding-top]',esc_attr($opt['padding-top'])) . "</td>";
     278            echo "<td>" . cta_button_dynamic_options($ets,'cta_button_options[padding-bottom]',esc_attr($opt['padding-bottom'])) . "</td></tr>";
     279            echo "<tr class='cta-hdr'><td colspan='4'>Button Colors</td></tr>";
     280            echo "<tr class='cta-bod'><td>Background</td><td colspan='3'>Label Text</td></tr>";
     281            $val = esc_attr($opt['background-color']);
     282            echo "<tr class='cta-bod'><td>" . cta_button_color_picker('cta_button_options[background-color]',$val,$val) . "</td>";
     283            $val = esc_attr($opt['color']);
     284            echo "<td colspan='2'>" . cta_button_color_picker('cta_button_options[color]',$val,$val) . "</td></tr>";
     285            echo "<tr class='cta-hdr'><td colspan='4'>Button Border</td></tr>";
     286            echo "<tr class='cta-bod'><td>Color</td><td>Width</td><td>Style</td><td>Radius</td></tr>";
     287            $val = esc_attr($opt['border-color']);
     288            echo "<tr class='cta-bod'><td>" . cta_button_color_picker('cta_button_options[border-color]',$val,$val) . "</td>";
     289            $ets = array('thin', 'medium', 'thick', '1px', '2px', '10px');
     290            echo "<td>" . cta_button_dynamic_options($ets,'cta_button_options[border-width]',esc_attr($opt['border-width'])) . "</td>";
     291            $ets = array('none', 'solid', 'dotted', 'groove', 'ridge', 'inset', 'outset', 'double');
     292            echo "<td>" . cta_button_dynamic_options($ets,'cta_button_options[border-style]',esc_attr($opt['border-style'])) . "</td>";
     293            $ets = array('0px', '5px', '10px', '15px', '20px', '25px', '30px');
     294            echo "<td>" . cta_button_dynamic_options($ets,'cta_button_options[border-radius]',esc_attr($opt['border-radius'])) . "</td></tr>";
     295            echo "<tr class='cta-hdr'><td colspan='4'>Other</td></tr>";
     296            echo "<tr class='cta-bod'><td>Font Weight</td><td colspan='3'>Cursor</td></tr>";
     297            $ets = array('normal', 'bold', 'bolder', 'lighter');
     298            echo "<tr class='cta-bod'><td>" . cta_button_dynamic_options($ets,'cta_button_options[font-weight]',esc_attr($opt['font-weight'])) . "</td>";
     299            $ets = array('crosshair', 'default', 'hand', 'help', 'pointer');
     300            echo "<td colspan='3'>" . cta_button_dynamic_options($ets,'cta_button_options[cursor]',esc_attr($opt['cursor'])) . "</td></tr>";
     301            // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
     302            //-----------------------------------------------------------------
     303            echo "<tr class='cta-input-hdr'><th colspan='4'>BUTTON HOVER STYLES</th></tr>";
     304            $txt = "These are the styles that will display when the mouse is hovered over the button.";
     305            echo "<tr><td colspan='4'><em>" . esc_html($txt) . "</em></td></tr>";
     306            // Safe: all dynamic values are escaped inside cta_button_dynamic_options() and cta_button_color_picker().
     307            // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
     308            echo "<tr class='cta-hdr'><td colspan='4'>Button Styles</td></tr>";
     309            echo "<tr class='cta-bod'><td>Color</td><td>Label Color</td><td>Font Weight</td><td>Border Color</td></tr>";
     310            $val = esc_attr($opt1['background-color']);
     311            echo "<tr class='cta-bod'><td>" . cta_button_color_picker('cta_button_hover_options[background-color]',$val,$val) . "</td>";
     312            $val = esc_attr($opt1['color']);
     313            echo "<td>" . cta_button_color_picker('cta_button_hover_options[color]',$val,$val) . "</td>";
     314            $ets = array('normal', 'bold', 'bolder', 'lighter');
     315            echo "<td>" . cta_button_dynamic_options($ets,'cta_button_hover_options[font-weight]',esc_attr($opt1['font-weight'])) . "</td>";
     316            $val = esc_attr($opt1['border-color']);
     317            echo "<td>" . cta_button_color_picker('cta_button_hover_options[border-color]',$val,$val) . "</td></tr>";
     318            // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
     319            //-----------------------------------------------------------------
     320            echo "<tr class='cta-input-hdr'><th colspan='4'>BUTTON EFFECTS</th></tr>";
     321            $txt = "There are 3 different animation effects that can be switched on or off. These are meant to " .
     322                   "highlight the Call To Action (CTA) button. If more than one effect is switched on, the " .
     323                   "effects will run sequentially in the order listed. Usually only one effect is switched on.";
     324            echo "<tr><td colspan='4'><em>" . esc_html($txt) . "</em></td></tr>";
     325            echo "<tr class='cta-hdr'><td colspan='4'>Effects</td></tr>";
     326            // Safe: all dynamic values are escaped inside cta_button_dynamic_options() and cta_button_color_picker().
     327            // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
     328            $ets = array('ON', 'OFF');
     329            $choice = cta_button_dynamic_options($ets,'cta_button_effects[shake]',esc_attr($opt2['shake']));
     330            echo "<tr class='cta-bod'><td>Shake</td><td colspan='3'>" . $choice . "</td></tr>";
     331            $choice = cta_button_dynamic_options($ets,'cta_button_effects[buzz]',esc_attr($opt2['buzz']));
     332            echo "<tr class='cta-bod'><td>Buzz</td><td colspan='3'>" . $choice . "</td></tr>";
     333            $choice = cta_button_dynamic_options($ets,'cta_button_effects[blink]',esc_attr($opt2['blink']));
     334            echo "<tr class='cta-bod'><td>Blink</td><td colspan='3'>" . $choice . "</td></tr>";
     335            // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
     336           
     337            echo "</table>";
     338            submit_button();
     339            echo "</form>";
    283340            echo "</div>";
    284 
     341           
    285342        } else {
    286343            wp_die('You do not have sufficient permissions to access this page.');
    287344        }
    288345    }
     346   
     347    // -------------------- Other functions --------------------
     348   
     349    public function ctabtn_filter_glance_items( $items ) {
     350        $marker = 'data-glance-key="faq-magic-install"';
     351        foreach ( (array) $items as $item ) {
     352            if ( is_string($item) && strpos($item, $marker) !== false ) {
     353                return $items; // already added somewhere
     354            }
     355        }
     356        if ( ! current_user_can('install_plugins') ) {
     357            return $items;
     358        }
     359        $url = add_query_arg(
     360            array('s' => 'FAQ Magic', 'tab' => 'search', 'type' => 'term'),
     361            admin_url('plugin-install.php')
     362        );
     363        $label = __('Discover FAQ Magic', 'cta-button-styler');
     364        $items[] =
     365            '<a ' . $marker . ' href="' . esc_url($url) . '">' .
     366            esc_html($label) .
     367            '</a>';
     368        return $items;
     369    }
     370   
     371    // -------------------- Caching: write generated CSS file to uploads --------------------
     372   
     373    private function ctabtn_css_rel_path() {
     374        return 'cta-button-styler/cta-button-styler.css';
     375    }
     376   
     377    private function ctabtn_css_abs_path() {
     378        $upload = wp_upload_dir();
     379        if ( ! empty($upload['error']) || empty($upload['basedir']) ) {
     380            return '';
     381        }
     382        return trailingslashit($upload['basedir']) . $this->ctabtn_css_rel_path();
     383    }
     384   
     385    private function ctabtn_css_url() {
     386        $upload = wp_upload_dir();
     387        return trailingslashit($upload['baseurl']) . $this->ctabtn_css_rel_path();
     388    }
     389   
     390    private function ctabtn_build_css() {
     391        $keyframes = array('webkit', 'moz', 'ms', '');
     392        $clsname = (string) get_option('cta_button_name');
     393        $clsname = (strlen($clsname) >= 5) ? $clsname : 'cta101';
     394        $clsname = sanitize_html_class($clsname);
     395        $opt  = get_option('cta_button_options');
     396        $opt1 = get_option('cta_button_hover_options');
     397        $opt  = is_array($opt)  ? $opt  : array();
     398        $opt1 = is_array($opt1) ? $opt1 : array();
     399        $color0 = '#000000';
     400        $color1 = '#000000';
     401        //Allowed values - security check
     402        $allowed_props = array(
     403            'margin-left','margin-right','margin-top','margin-bottom',
     404            'padding-left','padding-right','padding-top','padding-bottom',
     405            'background','background-color','color',
     406            'font-weight',
     407            'border','border-color','border-width','border-style','border-radius',
     408            'cursor',
     409            'box-shadow','text-shadow',
     410            'width','height','min-width','min-height','max-width','max-height',
     411            'display','align-items','justify-content','gap',
     412            'transition','opacity',
     413        );
     414       
     415        $css = "/* CTA Button Styler (generated) */\n";
     416        // Base
     417        $css .= "." . $clsname . " {\n";
     418        foreach ( $opt as $att => $value ) {
     419            $att = strtolower(trim((string) $att));
     420            if ( ! in_array($att, $allowed_props, true) ) {
     421                continue;
     422            }
     423            $att = sanitize_key($att);
     424            $value = (string) $value;
     425            $value = wp_strip_all_tags($value);
     426            $value = preg_replace('/[\r\n;]/', '', $value);
     427            $nb = (strpos($att, 'border') !== false || strpos($att, 'padding') !== false) ? ' !important' : '';
     428            $css .= "\t" . $att . ": " . $value . $nb . ";\n";
     429            if ( $att === 'color' ) {
     430                $color0 = $value;
     431            }
     432        }
     433        foreach ( $keyframes as $keyframe ) {
     434            $kf  = (strlen($keyframe) ? ('-' . $keyframe . '-') : '') . 'animation';
     435            $css .= "\t" . $kf . ": pulsing 7s 5 cubic-bezier(0.1, 0.7, 0.1, 1);\n";
     436        }
     437        $css .= "}\n\n";
     438        // Hover
     439        $css .= "." . $clsname . ":hover {\n";
     440        foreach ( $opt1 as $att => $value ) {
     441            $att = strtolower(trim((string) $att));
     442            if ( ! in_array($att, $allowed_props, true) ) {
     443                continue;
     444            }
     445            $att = sanitize_key($att);
     446            $value = (string) $value;
     447            $value = wp_strip_all_tags($value);
     448            $value = preg_replace('/[\r\n;]/', '', $value);
     449            $nb = (strpos($att, 'border') !== false || strpos($att, 'padding') !== false) ? ' !important' : '';
     450            $css .= "\t" . $att . ": " . $value . $nb . ";\n";
     451            if ( $att === 'color' ) {
     452                $color1 = $value;
     453            }
     454        }
     455        foreach ( $keyframes as $keyframe ) {
     456            $kf  = (strlen($keyframe) ? ('-' . $keyframe . '-') : '') . 'animation';
     457            $css .= "\t" . $kf . ": none;\n";
     458        }
     459        $css .= "}\n\n";
     460        $color0_safe = preg_replace('/[\r\n;]/', '', wp_strip_all_tags((string) $color0));
     461        $color1_safe = preg_replace('/[\r\n;]/', '', wp_strip_all_tags((string) $color1));
     462        $css .= "." . $clsname . " > a {padding: 0 !important; background: transparent !important; color: " . $color0_safe . " !important;}\n";
     463        $css .= "." . $clsname . ":hover > a {padding: 0 !important; background: transparent !important; color: " . $color1_safe . " !important;}\n\n";
     464        $css .= "/* Animation */\n";
     465        foreach ( $keyframes as $keyframe ) {
     466            $kf  = "@" . (strlen($keyframe) ? ('-' . $keyframe . '-') : '') . "keyframes";
     467            $css .= $kf . " pulsing {\n";
     468            $css .= "\tto {\n";
     469            $css .= "\t\tbox-shadow: 0 0 0 50px #fea92c00;\n";
     470            $css .= "\t}\n";
     471            $css .= "}\n\n";
     472        }
     473        return $css;
     474    }
     475   
     476    public function ctabtn_write_css_file() {
     477       
     478        $css  = $this->ctabtn_build_css();
     479        $upload = wp_upload_dir();
     480        if ( empty($upload['basedir']) || ! empty($upload['error']) ) {
     481            return;
     482        }
     483        $path = $this->ctabtn_css_abs_path();
     484        $dir  = dirname($path);
     485       
     486        // Ensure target is inside uploads (prevents weird path issues)
     487        $basedir_real = wp_normalize_path( realpath($upload['basedir']) );
     488        $dir_real     = wp_normalize_path( realpath($dir) ?: $dir );
     489        $path_norm    = wp_normalize_path( $path );
     490        if ( $basedir_real && strpos($path_norm, trailingslashit($basedir_real)) !== 0 ) {
     491            return;
     492        }
     493        if ( ! wp_mkdir_p($dir) ) {
     494            return;
     495        }
     496        if ( ! function_exists('WP_Filesystem') ) {
     497            require_once ABSPATH . 'wp-admin/includes/file.php';
     498        }
     499        WP_Filesystem();
     500        global $wp_filesystem;
     501       
     502        if ( ! $wp_filesystem ) {
     503            return;
     504        }
     505        // Write atomically: write temp then move into place
     506        $tmp = $path . '.tmp';
     507        $ok = $wp_filesystem->put_contents($tmp, $css, FS_CHMOD_FILE);
     508        if ( $ok ) {
     509            $wp_filesystem->move($tmp, $path, true);
     510        }
     511    }
    289512
    290 // -------------------- Other functions --------------------
    291 
    292 // -------------------- Define actions to be taken when installing and uninstalling the Plugin --------------------
     513   
     514    private function ctabtn_delete_css_file() {
     515        $path = $this->ctabtn_css_abs_path();
     516        // Delete file using WordPress wrapper
     517        if ( file_exists( $path ) ) {
     518            wp_delete_file( $path );
     519        }
     520        // Remove directory if empty using WP_Filesystem
     521        $dir = dirname( $path );
     522        if ( is_dir( $dir ) ) {
     523            if ( ! function_exists( 'WP_Filesystem' ) ) {
     524                require_once ABSPATH . 'wp-admin/includes/file.php';
     525            }
     526            WP_Filesystem();
     527            global $wp_filesystem;
     528            if ( $wp_filesystem && $wp_filesystem->is_dir( $dir ) ) {
     529                // Only remove if empty
     530                $files = $wp_filesystem->dirlist( $dir );
     531                if ( empty( $files ) ) {
     532                    $wp_filesystem->rmdir( $dir );
     533                }
     534            }
     535        }
     536    }
     537   
     538    // -------------------- Define actions to be taken when installing and uninstalling the Plugin --------------------
     539   
     540    public function ctabtn_activate() {
     541        $this->ctabtn_load_options();
     542        $this->ctabtn_write_css_file();
     543    }
     544   
    293545    function ctabtn_load_options() {
    294         //$value = serialize($options);
    295546        add_option('cta_button_name', $this->cta_name);
    296547        add_option('cta_button_options', $this->options);
    297548        add_option('cta_button_hover_options', $this->hover_options);
    298549        add_option('cta_button_effects', $this->button_effects);
    299     }
    300 
     550       
     551        // Ensure cached CSS exists on fresh install
     552        $this->ctabtn_write_css_file();
     553    }
     554   
    301555    function ctabtn_unset_options() {
    302556        delete_option('cta_button_name');
     
    304558        delete_option('cta_button_hover_options');
    305559        delete_option('cta_button_effects');
    306     }
    307 
     560       
     561        $this->ctabtn_delete_css_file();
     562    }
     563   
     564    /**
     565     * Uninstall hook must be static
     566     */
     567    public static function ctabtn_uninstall_static() {
     568        delete_option('cta_button_name');
     569        delete_option('cta_button_options');
     570        delete_option('cta_button_hover_options');
     571        delete_option('cta_button_effects');
     572        $upload = wp_upload_dir();
     573        $path   = trailingslashit($upload['basedir']) . 'cta-button-styler/cta-button-styler.css';
     574        $dir    = dirname($path);
     575        // Delete file using WordPress wrapper
     576        if ( file_exists($path) ) {
     577            wp_delete_file($path);
     578        }
     579        // Remove directory if empty using WP_Filesystem
     580        if ( is_dir($dir) ) {
     581            if ( ! function_exists('WP_Filesystem') ) {
     582                require_once ABSPATH . 'wp-admin/includes/file.php';
     583            }
     584            WP_Filesystem();
     585            global $wp_filesystem;
     586            if ( $wp_filesystem && $wp_filesystem->is_dir($dir) ) {
     587               
     588                $files = $wp_filesystem->dirlist($dir);
     589               
     590                if ( empty($files) ) {
     591                    $wp_filesystem->rmdir($dir);
     592                }
     593            }
     594        }
     595    }
     596   
    308597}
  • cta-button-styler/trunk/cta-button-styler.php

    r3326232 r3463427  
    44 * Plugin URI:  http://www.creatorseo.com/cta-button-styler-plugin/
    55 * Description: Style and customise your Call To Action (CTA) buttons and links to improve click-through rates
    6  * Version:     1.1.6
     6 * Version:     2.0.1
    77 * Author:      Clinton CreatorSEO
    88 * Author URI:  http://www.creatorseo.com
    99 * License:     GPLv2
    10  * Last change: 2025-07-11
     10 * Last change: 2026-02-13
    1111 *
    12  * Copyright 2016-2025 CreatorSEO (email : [email protected])
     12 * Copyright 2016-2026 CreatorSEO (email : [email protected])
    1313 *
    1414 * This program is free software; you can redistribute it and/or modify
     
    3131}
    3232
     33if ( ! defined('CTABTN_VERSION') ) define('CTABTN_VERSION', '1.2.1');
     34
    3335require_once(plugin_dir_path( __FILE__ ) . 'class.cta-button-styler.php');
    3436require_once(plugin_dir_path( __FILE__ ) . 'inc/ctabtn-lib.php');
  • cta-button-styler/trunk/inc/ctabtn-lib.php

    r3326232 r3463427  
    88 * @param string $default - default color
    99 * @param string $class optional class name for the option field
    10  * @param string $display - echo or return the html
    11  * @return string - return sting if $display is false
     10 * @return string - return string
    1211 */
    13 function cta_button_color_picker($name,$color,$default='#efefef',$class='',$display=true){
     12function cta_button_color_picker($name,$color,$default='#efefef',$class=''){
    1413    $out = "";
    1514    $cls = $class? " ".$class."": "";
     
    1817    if ($color){
    1918        $out .= "<div class='cta-color-picker'>";
    20         $out .= "<input type='text' class='cta-button-color-pick".$cls."' name='".esc_attr($name)."' value='".esc_attr($color)."' data-default-color='".$default."'>";
     19        $out .= "<input type='text' class='cta-button-color-pick".esc_attr($cls)."' name='".esc_attr($name)."' value='".esc_attr($color)."' data-default-color='".esc_attr($default)."'>";
    2120        $out .= "</div>";
    2221    } else {
    2322        $out = "<p>ERROR: Color not recognized</p>";
    2423    }
    25     if ($display) echo  wp_kses_post($out);
    26     else return $out;
     24    return $out;
    2725}
    2826
     
    3331 * @param string $selected default or selected option
    3432 * @param string $class optional class name for the option field
    35  * @param string $display - echo or return the html
    36  * @return string - return sting if $display is false
     33 * @return string - return string
    3734 */
    38 function cta_button_dynamic_options($elements,$name,$selected,$class='',$display=true){
     35function cta_button_dynamic_options($elements,$name,$selected,$class=''){
    3936    $out = "";
    4037    $cls = $class? " class='".esc_attr($class)."'": "";
     
    5047        $out = "<p>ERROR: Elements not defined for list</p>";
    5148    }
    52     if ($display) echo  wp_kses_post($out);
    53     else return $out;
     49    return $out;
    5450}
    55 
    56 
    57 /**
    58  * Fetch the styles defined by the plugin and prepare these for a call from JS
    59  * - Called by ctabtn-scripts via AJAX
    60  * @return void
    61  */
    62 function ctabtn_fetch_styles(){
    63     $opt = []; $opt1 = []; $opt2 = [];
    64     $def = array(
    65         'margin-left'=>'5px',
    66         'margin-right'=>'5px',
    67         'margin-top'=>'5px',
    68         'margin-bottom'=>'5px',
    69         'padding-left'=>'15px',
    70         'padding-right'=>'15px',
    71         'padding-top'=>'15px',
    72         'padding-bottom'=>'15px',
    73         'background-color'=>'#ffffff',
    74         'color'=>'#f47721',
    75         'font-weight'=>'bold',
    76         'border-width'=>'3px',
    77         'border-style'=>'solid',
    78         'border-color'=>'#f47721',
    79         'border-radius'=>'20px',
    80         'cursor'=>'hand'
    81     );
    82     $def1 = array(
    83         'background-color'=>'#f47721',
    84         'color'=>'#ffffff',
    85         'font-weight'=>'bold',
    86         'border-color'=>'#ffffff',
    87     );
    88     $def2 = array(
    89         'shake'=>'ON',
    90         'buzz'=>'OFF',
    91         'blink'=>'OFF',
    92     );
    93     $styles = [];
    94 //  $clsname = get_option('cta_button_name');
    95     $opt = get_option('cta_button_options');
    96     $opt1 = get_option('cta_button_hover_options');
    97     $opt2 = get_option('cta_button_effects');
    98     $opt = is_array($opt)? array_merge($def,$opt): $def;
    99     $opt1 = is_array($opt1)? array_merge($def1,$opt1): $def1;
    100     $opt2 = is_array($opt2)? array_merge($def2,$opt2): $def2;
    101     foreach ( $opt as $att => $val ) {
    102         $val1 = isset($opt1[$att])? $opt1[$att]: $val;
    103         $styles[$att] = [$val, $val1];
    104     }
    105     foreach ( $opt2 as $att => $val ) {
    106         $styles['zz_'.$att] = ($val=='ON'? 1: 0);
    107     }
    108     echo json_encode($styles);
    109     wp_die(); //NB!! to prevent the whitespace error
    110 }
    111 
    112 /**
    113  * Generate the styles as part of the header for use with the wp_head hook.
    114  * This approach is not used as it is too inefficient as the code is loaded on every page and not
    115  * only when the styling is needed on a particular page.
    116  *
    117  * @return void
    118  */
    119 function ctabtn_style_in_header(){
    120     $keyframes = ["webkit", "moz", "ms", ""];
    121     $clsname = get_option('cta_button_name');
    122     $clsname = strlen($clsname)>=5? $clsname: "cta101";
    123     $opt = get_option('cta_button_options');
    124     $opt1 = get_option('cta_button_hover_options');
    125     $color0 = "#000000";
    126     $color1 = "#000000";
    127     $css = "<style>\r\n";
    128     $css .= ".".$clsname." {\r\n";
    129     foreach ($opt as $att => $value) {
    130         $nb = stristr($att,'border')? " !important": (stristr($att,'padding')? " !important": "");
    131         $css .= "\t".$att.": ".$value.$nb.";\r\n";
    132         $color0 = $att=='color'? $value: $color0;
    133     }
    134     foreach ( $keyframes as $keyframe ) {
    135         $kf = (strlen($keyframe)? ("-".$keyframe."-"): "")."animation";
    136         $css .= "\t".$kf.": pulsing 7s 5 cubic-bezier(0.1, 0.7, 0.1, 1);\r\n";
    137     }
    138     $css .= "}\r\n\r\n";
    139     $css .= ".".$clsname.":hover {\r\n";
    140     foreach ($opt1 as $att => $value) {
    141         $nb = stristr($att,'border')? " !important": "";
    142         $css .= "\t".$att.": ".$value.$nb.";\r\n";
    143         $color1 = $att=='color'? $value: $color1;
    144     }
    145     foreach ( $keyframes as $keyframe ) {
    146         $kf = (strlen($keyframe)? ("-".$keyframe."-"): "")."animation";
    147         $css .= "\t".$kf.": none;\r\n";
    148     }
    149     $css .= "}\r\n\r\n";
    150     $css .= ".".$clsname.">a {padding: 0 !important; background: transparent !important; color: ".$color0." !important;}\r\n\r\n";
    151     $css .= ".".$clsname.":hover>a {padding: 0 !important; background: transparent !important; color: ".$color1." !important;}\r\n\r\n";
    152     $css .= "/* Animation */\r\n";
    153     foreach ( $keyframes as $keyframe ) {
    154         $kf = "@".(strlen($keyframe)? ("-".$keyframe."-"): "")."keyframes";
    155         $css .= $kf." pulsing {\r\n";
    156         $css .= "\tto {\r\n";
    157         $css .= "\t\tbox-shadow: 0 0 0 50px #fea92c00;\r\n";
    158         $css .= "\t}\r\n";
    159         $css .= "}\r\n";
    160         $css .= "\r\n";
    161     }
    162     $css .= "</style>\r\n";
    163     echo $css;
    164 }
  • cta-button-styler/trunk/inc/ctabtn-shortcodes.php

    r3261574 r3463427  
    22/**
    33 * Description: Shortcodes for CTA button Styler
    4  * @package  ${NAMESPACE}
    54 */
    65if ( !defined('ABSPATH') ) exit; //Exit if accessed directly
     
    1716 * @return string
    1817 */
    19 function ctatbn_test_button($atts){
     18function ctabtn_test_button($atts){
    2019    $atts = shortcode_atts(
    2120        array(
     
    5251}
    5352
    54 add_shortcode('ctatbn_test_button', 'ctatbn_test_button');
     53add_shortcode('ctabtn_test_button', 'ctabtn_test_button');
  • cta-button-styler/trunk/js/ctabtn-scripts.js

    r3326232 r3463427  
    22
    33(function($) {
    4     // $.noConflict();
    5     let emtz = {};
    6     // Add Color Picker to all inputs that have 'color-field' class
    7     if ($('.cta-button-color-pick').length > 0) {
    8         $('.cta-button-color-pick').wpColorPicker();
     4
     5    // Admin: init WP color picker
     6    const $colorPickers = $('.cta-button-color-pick');
     7    if ($colorPickers.length && typeof $.fn.wpColorPicker === 'function') {
     8        $colorPickers.wpColorPicker();
    99    }
    1010
    11     if ($('.cta101').length > 0) {
    12         //clear any potentially destructive styles
    13         if ($('.cta101>a').length > 0) {
    14             const emt = $('.cta101>a');
    15             // emt.css('padding','0');
    16             // emt.css('background','transparent');
    17             // emt.css('color','#000');
    18             emt.removeAttr("color")
     11    const cls = (typeof ctabtn !== 'undefined' && ctabtn.class) ? ctabtn.class : 'cta101';
     12    const fx  = (typeof ctabtn !== 'undefined' && ctabtn.effects) ? ctabtn.effects : { shake:0, buzz:0, blink:0 };
     13
     14    const $cta = $('.' + cls);
     15    if (!$cta.length) return;
     16
     17    // Clean up inline styles that may override CSS
     18    $cta.each(function () {
     19        const $btn  = $(this);
     20        const $link = $btn.children('a:first-child');
     21
     22        $btn.removeAttr('style');
     23
     24        if ($link.length) {
     25            $link.css({ padding: '0', background: 'transparent' });
    1926        }
    20         $('.cta101').each(function () {
    21             const emt = $(this);
    22             const emt1 = $(this).children('a:first-child')
    23             emt.removeAttr('style');
    24             emt1.css('padding', '0');
    25             emt1.css('background', 'transparent');
    26             //console.log('ELEMENT', emt1);
    27             let aj = $.ajax({
    28                 url: ctabtn.ajax_url,
    29                 type: 'post',
    30                 data: {action: 'ctabtn_fetch_styles', my_class: 'cta101'},
    31                 dataType: 'json',
    32                 success : function(data,status){
    33                     emtz=data;
    34                     //console.log('ARR', emtz)
    35                     if (typeof data === 'object' && data !== null) {
    36                         Object.keys(data).forEach(key => {
    37                             //console.log("\n" + key + ": " + data[key][0] + " | " + data[key][1]);
    38                             imp0 = (data[key][0]!=null && key == 'color')? ' !important': '';
    39                             imp1 =(data[key][0]!=null && key == 'color')? ' !important': '';
    40                             emt.css(key, data[key][0] + imp0);
    41                             emt.hover(
    42                                 function() {
    43                                     $( this ).css(key,data[key][1] + imp1);
    44                                 }, function() {
    45                                     $( this ).css(key,data[key][0] + imp0); //to remove property set it to ''
    46                                 }
    47                             );
    48                             if (typeof emt1 !== null){
    49                                 if (key == 'color'){
    50                                     emt1.css(key, data[key][0] + imp0);
    51                                     emt1.hover(
    52                                         function() {
    53                                             $( this ).css(key,data[key][1] + imp1);
    54                                         }, function() {
    55                                             $( this ).css(key,data[key][0] + imp0); //to remove property set it to ''
    56                                         }
    57                                     );
    58                                 }
    59                             }
    60                         });
    61                     } else {
    62                         console.log('ERROR', 'No CTA style data to show');
    63                     }
    64                 },
    65                 error: function (xhr, status, errorThrown) {
    66                     let mytxt = '<h3>ERROR</h3><p>' + status + ' [' + errorThrown + ']<br />' + xhr.responseText + '</p>';
    67                     console.log(mytxt);
    68                 }
    69             });
    70             aj.then(function(){
    71                 $(".cta_message").hide();
    72                 if ( emtz.zz_shake == 1 ) dampshake('cta101',100,15,23);
    73                 if ( emtz.zz_buzz == 1 ) buzzkit('cta101',700,15);
    74                 if ( emtz.zz_blink == 1 ) blinkin('cta101',5000,3)
    75             })
    76         });
    77         //remove drop-arrow in Divi
    78         if ($('.cta101').hasClass('menu-item-has-children')){
    79             $('.cta101').removeClass('menu-item-has-children');
    80         }
     27    });
     28
     29    $(".cta_message").hide();
     30
     31    // Run effects
     32    if (fx.shake == 1) dampshake(cls, 100, 15, 23);
     33    if (fx.buzz  == 1) buzzkit(cls, 700, 15);
     34    if (fx.blink == 1) blinkin(cls, 500, 12); // shorter + more visible
     35
     36    // Divi: remove dropdown arrow class if present
     37    if ($cta.hasClass('menu-item-has-children')) {
     38        $cta.removeClass('menu-item-has-children');
    8139    }
    8240
    83     function callback() {
    84         // setTimeout(function() {
    85         //     $( ".cta101" ).removeAttr( "style" ).hide().fadeIn();
    86         // }, 1000 );
    87     };
     41    function dampshake(clsName, interval=300, distance=10, times=20) {
     42        const $el = $('.' + clsName);
     43        $el.stop(true, true).css('position', 'relative');
    8844
    89     function dampshake(cls='cta101', interval=300, distance=10,times=20) {
    90         $("."+cls).css('position', 'relative');
    91         for (var iter = 0; iter < times ; iter++) {
    92             let x = parseInt(distance *-(times-iter)/times);
    93             $("."+cls).animate({
    94                 left: ((iter % 2 == 0 ? distance : x))
    95             }, (interval*(1.5-(times-iter)/times)));
     45        for (let i = 0; i < times; i++) {
     46            const x = parseInt(distance * -(times - i) / times, 10);
     47            $el.animate({ left: (i % 2 === 0 ? distance : x) }, (interval * (1.5 - (times - i) / times)));
    9648        }
    97         $("."+cls).animate({ left: 0 }, interval);
     49        $el.animate({ left: 0 }, interval);
    9850    }
    9951
    100     function blinkin(cls='cta101', interval=1000, times=20) {
    101         for (var iter = 0; iter < times ; iter++) {
    102             $("."+cls).fadeOut(interval);
    103             $("."+cls).fadeIn(interval);
    104         }
     52    // Reliable blink: toggles visibility on a timer (no queue issues)
     53    function blinkin(clsName, interval=500, toggles=12) {
     54        const $el = $('.' + clsName);
     55        $el.stop(true, true);
     56
     57        let count = 0;
     58        const timer = setInterval(function() {
     59            $el.fadeToggle(interval);
     60            count++;
     61            if (count >= toggles) {
     62                clearInterval(timer);
     63                $el.stop(true, true).show();
     64            }
     65        }, interval);
    10566    }
    10667
    107     function buzzkit(cls='cta101', interval=1000, times=20) {
    108         $( ".cta101" ).effect( 'pulsate', {times:times}, interval, callback );
    109         //$( ".cta101" ).effect( "highlight", {color:"#669966"}, 3000 );
    110         //$( ".cta101" ).toggle("pulsate",1000);
     68    // Buzz: use jQuery UI pulsate if available, otherwise fallback to fadeToggle
     69    function buzzkit(clsName, interval=700, times=15) {
     70        const $el = $('.' + clsName);
     71        $el.stop(true, true);
     72
     73        if (typeof $el.effect === 'function') {
     74            $el.effect('pulsate', { times: times }, interval);
     75            return;
     76        }
     77
     78        // Fallback (no jQuery UI effects loaded)
     79        let count = 0;
     80        const step = Math.max(100, Math.floor(interval / (times * 2)));
     81        const timer = setInterval(function() {
     82            $el.fadeToggle(step);
     83            count++;
     84            if (count >= (times * 2)) {
     85                clearInterval(timer);
     86                $el.stop(true, true).show();
     87            }
     88        }, step);
    11189    }
    11290
    113 })( jQuery );
    114 
     91})(jQuery);
  • cta-button-styler/trunk/readme.txt

    r3326240 r3463427  
    1 === CTA Button Styles ===
     1=== CTA Button Styler ===
    22Contributors: creatorseo
    33Donate link: http://www.creatorseo.com/cta-button-styler-plugin/
    44Tags: Call to Action, CTA Button, styling, click-through rate, CTR
    55Requires at least: 6.1
    6 Tested up to: 6.8.1
    7 Stable tag: 1.1.6
    8 Requires PHP: 7.3
     6Tested up to: 6.9
     7Stable tag: 2.0.1
     8Requires PHP: 7.4
    99License: GPLv2 or later
    1010License URI: http://www.gnu.org/licenses/gpl-2.0.html
    1111
    12 Call to Action (CTA) button and link styler to highlight buttons, links and menu items in WordPress as call to actions.
     12Create and style reusable Call-To-Action buttons with configurable CSS, hover effects, and optional animations. Clean, cache-friendly, and lightweight.
    1313
    1414== Description ==
     
    1616CTA Button Styler is a plugin for WordPress that allows easy styling of existing buttons in WordPress. Buttons labelled with the *cta101* class can be easily turned into effective **Call To Action buttons** which will encourage visitors to stay on the site and click through to the desired page.
    1717
    18 Reducing your bounce-rate (i.e. getting visitors to look at more than one page on your site) is important for your site ranking. Using effective call-to-action buttons encourages visitors to click through and visit other pages thereby reducing your overall bounce rate and potentially increasing your ranking.
     18Reducing your bounce-rate (i.e. get visitors to look at more than one page on your site) is important for your site ranking. Using effective call-to-action buttons encourages visitors to click through and visit other pages thereby reducing your overall bounce rate and potentially increasing your ranking.
    1919
    2020CTA button styler is designed with flexibility and ease of use in mind. It is easy to install. Does not consume any unnecessary resources and simply does what it needs to do to keep visitors on the site.
     
    2525
    2626For more information, check out plugin page at [Help](http://myinfo.ie/CTA-Button-Styling/) or see the [Working demo on CreatorSEO](http://www.creatorseo.com/) on our site.
     27
     28= Key Features =
     29
     30* Ultra easy to apply using a defined button class
     31* Configure margins and padding
     32* Set background and text colors
     33* Customize borders and border radius
     34* Configure hover styles
     35* Optional animation effects (Shake, Buzz, Blink)
     36* Automatically generated and cached CSS file
     37* Clean uninstall (removes settings and generated files)
     38* No inline CSS injection
     39* No runtime CSS generation
    2740
    2841== Installation ==
     
    32453. Click on 'CTA Button Styler' in the Appearance menu to configure the button
    33464. Add the class **cta101** to any link on your site to convert the link to a button
     47
     48== Usage ==
     49
     50After saving your settings, use the configured CSS class in your theme:
     51
     52Example:
     53
     54`<a class="cta101" href="#">Click Here</a>`
     55
     56Or apply it to a menu item using the WordPress menu class field.
    3457
    3558== Frequently Asked Questions ==
     
    85108
    86109== Changelog ==
     110= 2.0.1 =
     111* Improved CSS caching architecture
     112* Implemented atomic file write strategy
     113* Enhanced filesystem security checks
     114* Improved WordPress coding standards compliance
     115* Refined validation and sanitization logic
     116* Removed dynamic AJAX CSS generation
     117* Improved animation loading dependencies
     118
     119= 2.0.0 =
     120* Major refactor of CSS generation engine
     121* Introduced uploads-based CSS caching
     122* Added hover style configuration improvements
     123* Performance optimizations
     124
    87125= 1.1.6 =
    88126* Version checks and minor updates
Note: See TracChangeset for help on using the changeset viewer.