Passing values from a widget to a function within a plugin

I have a plugin that is built with many widgets. A widget’s bundle. Each widget creates it’s own custom CSS code.

Instead of having messy source code where I display 15 different sets of inline CSS code I would like to pass the custom generated CSS code from each widget to a main custom CSS file that I created through WordPress AJAX.

Read More

I will display the functions that I have setup to make this possible.

The AJAX created CSS file

The below CSS file is created through WordPress AJAX. It allows me to place custom CSS statements in the file. It also contains a filter where I am hoping to pass the extra generated CSS from the widgets to this function (file).

/**
 * Echo the CSS for the custom widgets style
 */
public function advanced_widget_pack_css() {
    if(empty($_GET['action']) || $_GET['action'] != 'advanced_widget_pack_gen_css') return;
    if(!isset($_GET['ver'])) return;

    $css_text = '';

    /* ============================= */
    /* Archives Widget               */
    /* ============================= */
    $css_text .= ".awp_archives_colour { color:".awp_option('awp_archives_dropdown_inst_colour')." !important }n"; 

    /**
     * Filter for any incoming CSS
     */
    $css_text = apply_filters('advanced_widget_pack_css', $css_text);

    header("Content-type: text/css");
    echo $css_text;
    exit();
}

One of the widget classes with custom genrated CSS code

The below code is a snippet of one of the many widgets used within the plugin. The widget creates custom CSS code and stores it in the variable $sc_css. What I want to do from here is pass the contents of the variable $sc_css or append the contents to the function advanced_widget_pack_css() which I created earlier.

class Advanced_Widget_Pack_Widget_Archives extends WP_Widget {

    public function __construct(){
        // This filter hooks the custom genrated css code to the advanced_widget_pack_css function
        add_filter('advanced_widget_pack_css', array(&$this,'awp_pass_css_code'));
    }

    public function form($instance) {}

    public function widget($args, $instance){

        extract($args);

        // All the widget code is contained here....

        // Styling for the shortcode
        if($is_awp_sc == 'true'){

            /* Generate unique id if shortcode - used for styling */
            $sc_id = mt_rand(1, 100000);

            $sc_css =  ".awp_archive_widget_sc".$sc_id." { border:".$awp_archives_border_width.' '.$awp_archives_border_style.' '.$awp_archives_border_color." !important }n";
            $sc_css .= $awp_archives_border_radius == 'round' ? '.awp_archive_widget_sc'.$sc_id.' { -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px }' : ''.''." n";

            $sc_css .= ".awp_archive_widget_sc".$sc_id." li a, .awp_archive_widget_sc".$sc_id." li { font-size:".$awp_archives_font_size." !important }n";
            $sc_css .= ".awp_archive_widget_sc".$sc_id." li a { color:".$awp_archives_link_std." !important }n";
            $sc_css .= ".awp_archive_widget_sc".$sc_id." li a:hover { color:".$awp_archives_link_hover." !important }n";

            // This should pass the variable
            echo $this->awp_pass_css_code($sc_css);
        }

        // The widget code gets outputted here
    }

    // This function is created to pass the content of the variable $sc_css to the advanced_widget_pack_css function
    function awp_pass_css_code( $sc_css ) {
        return $sc_css;
    }
}

The issues

I tried to achieve this by passing the contents of the $sc_css variable to a function within the widget and then hooking it to the function advanced_widget_pack_css() through a WordPress filter.

The problem that occurs is that the contents of the variable are always blank when passing them to the AJAX generated stylesheet.

Related posts

2 comments

  1. First of all I can say why your code doesn’t work.

    The custom css is created inside the widget function that is called by WordPress in the moment that the widget is displayed.

    I guess, that you on document ready send an ajax request that call advanced_widget_pack_css() function. But every ajax request is a completely new http request that the only scope is running a function, sure not embed widget.

    For this reason, the new request via ajax never call the widget() method in your widget class and so of course no css are added.

    Said that, think one minute for what you are doing.

    Assuming your workflow will work, it fail if user has no js enabled. And even if the the js are enabled, the page is loaded withou custom css, that should be loaded on ajax request (and Ajax in WordPress are not very fast…) so:

    • if no js no css as well
    • even if js page load with no css, so you have unstyled widget for a
      second or more
    • browser are not allowed to cache the css

    So your code does’t work (an I explained yopu why) but even if you find a way to make it works is not a great solution.

    What can be a solution?

    First of all in the widget isolate the function that generates the custom css.

    After that, you should call the function not on the widget() method but on the update method. In this way the css is generated everytime the widget is updated, and you can save the newly generated css to store it in a css file.

    As a good practise is better saving this file in the uploads folder, because you are sure that folder is writable from WP.

    Pseudo code:

    class Advanced_Widget_Pack_Widget_Archives extends WP_Widget {
    
       function generate_css( $instance ) {
         // some code here to generate css from instance arguments...
         return $sc_css;
       }
    
       function update( $new_instance, $old_instance ) {
         // some code here to update the widget instance...
         $css = $this->generate_css( $new_instance );
         $upload_dir = wp_upload_dir();
         $path = $upload_dir['basedir'] . '/myplugin/myplugin-customwidget.css';
         if ( ! file_exists($upload_dir['basedir'] . '/myplugin') )
           mkdir($upload_dir['basedir'] . '/myplugin');
         file_put_contents($path, $css);
       }
    
    }
    

    After that, you can enqueue the file just created using WordPress standard way…

    Alternative to this method is generate the css in the widget() method (as you are already doing) and just output as inline style in the markup.

  2. A quick solution for you is to store all your generated css data in a serialized array into the WordPress database, and get it/set it with get_option/set_option

Comments are closed.