Skip to content

Instantly share code, notes, and snippets.

@mhulse
Last active December 18, 2015 23:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mhulse/5860561 to your computer and use it in GitHub Desktop.
Save mhulse/5860561 to your computer and use it in GitHub Desktop.
What's wrong with my WP_Widget wrapper class? See PHP warning in markdown file below.
<?php
/**
* Generic sidebar widget that contains a title and text field.
*
* See "Text widget class" in `/wp-includes/default-widgets.php`.
*
* @todo Option to make this a single-instance widget.
* @todo Need constant that allows user to pick template base location.
* @todo Make more like WPAlchemy.
*
* @see http://wordpress.stackexchange.com/questions/32103
* @see http://wordpress.stackexchange.com/a/1834/32387
* @see http://wordpress.stackexchange.com/questions/104077
* @see https://github.com/farinspace/wpalchemy
*/
class Foo_Widget extends WP_Widget
{
private $template = '';
private $style_admin = array();
private $script_admin = array();
private $style = array();
private $script = array();
public function __construct($arr = array()) {
if (is_array($arr)) {
# http://stackoverflow.com/a/8329005/922323
$arr = array_filter($arr);
if ( ! empty($arr)) {
$args = wp_parse_args(
$arr,
array(
'id_base' => '',
'name' => '',
'template' => '',
'description' => '',
'width' => '',
'height' => '',
'style_admin' => array(),
'script_admin' => array(),
'style' => array(),
'script' => array(),
)
);
if (( ! empty($args['id_base'])) && ( ! is_numeric($args['id_base']))) {
if ( ! empty($args['template'])) {
parent::__construct(
$args['id_base'],
$args['name'],
array(
'classname' => __CLASS__,
'description' => $args['description'],
),
array(
'width' => $args['width'],
'height' => $args['height'],
)
);
$this->template = $args['template'];
if ( ! empty($args['style_admin'])) {
$this->style_admin = $args['style_admin'];
add_action('admin_enqueue_scripts', array($this, 'add_styles'));
}
if ( ! empty($args['script_admin'])) {
$this->script_admin = $args['script_admin'];
add_action('admin_enqueue_scripts', array($this, 'add_scripts'));
}
if ( ! empty($args['style'])) {
$this->style = $args['style'];
add_action('wp_enqueue_scripts', array($this, 'add_styles'));
}
if ( ! empty($args['script'])) {
$this->script = $args['script'];
add_action('wp_enqueue_scripts', array($this, 'add_styles'));
}
add_action(
'widgets_init',
function() {
register_widget(__CLASS__);
}
);
} else {
//die('Widget template file required.');
}
} else {
//die('Widget ID required and must be a string.');
}
}
}
}
public function update($new_instance, $old_instance) {
$instance = $old_instance;
$instance['title'] = strip_tags($new_instance['title']);
$instance['text'] = $new_instance['text']; // Unfiltered HTML.
return $instance;
}
public function form($instance) {
$instance = wp_parse_args((array) $instance, array('title' => '', 'text' => '',));
$title = strip_tags($instance['title']);
$text = esc_textarea($instance['text']);
?>
<p>
<label for="<?=$this->get_field_id('title')?>">Title:</label>
<input type="text" name="<?=$this->get_field_name('title')?>" id="<?=$this->get_field_id('title')?>" class="widefat" value="<?=esc_attr($title)?>">
</p>
<textarea rows="16" cols="20" name="<?=$this->get_field_name('text')?>" id="<?=$this->get_field_id('text')?>" class="widefat"><?=$text?></textarea>
<?php
}
/**
* @see http://wordpress.stackexchange.com/a/4471/32387
*/
public function widget($args, $instance) {
extract($args);
$title = apply_filters(
'widget_title', // The name (`$tag`) of the filter hook.
(empty($instance['title']) ? '' : $instance['title']), // The value which the filters hooked to `$tag` may modify.
$instance, // Additional variable passed to the filter functions.
$this->id_base // IBID.
);
$text = apply_filters(
'widget_text',
(empty($instance['text']) ? '' : $instance['text']),
$instance
);
if ($text != '') {
echo $text;
} else {
# Remember: Arguments will be available to included template.
include($this->template);
}
}
public function add_styles() {
$defaults = array(
'handle' => '',
'src' => '',
'deps' => array(),
'version' => false,
'media' => 'all',
);
return $this->add_files('style', $defaults);
}
public function add_scripts() {
$defaults = array(
'handle' => '',
'src' => '',
'deps' => array(),
'version' => false,
'in_footer' => false,
);
return $this->add_files('script', $defaults);
}
private function add_files($kind = '', $defaults = array()) {
$return = FALSE;
if ($kind) {
$files = (is_admin()) ? $this->{ $kind . '_admin' } : $this->{ $kind };
if ( ! empty($files)) {
foreach($files as $file) {
$args = wp_parse_args($file, $defaults);
call_user_func_array(
('wp_enqueue_' . $kind),
array(
$args['handle'],
$args['src'],
$args['deps'],
$args['version'],
((array_key_exists('media', $args)) ? $args['media'] : $args['in_footer']),
)
);
}
$return = TRUE;
}
}
return $return;
}
}
<?php
include_once('class.foo_widget.php');
$medium_rectangle_1 = new Foo_Widget(
array(
'id_base' => 'medium_rectangle_1',
'name' => 'Medium Rectangle 1',
'description' => 'Standard Advertising Unit',
'template' => STYLESHEETPATH . '/includes/widgets/medium-rectangle-1.php',
)
);
<!-- //////////////////// MEDIUM RECTANGLE 1 \\\\\\\\\\\\\\\\\\\\ -->
<div class="medium_rectangle advert Aon Bon"><div id="medium_rectangle_1-mobile"></div></div>
<div class="medium_rectangle advert Con Don"><div id="medium_rectangle_1-desktop"></div></div>
<!-- \\\\\\\\\\\\\\\\\\\\ MEDIUM RECTANGLE 1 //////////////////// -->
<hr>

This is the PHP warning I get back:

Notice: Undefined property: Foo_Widget::$option_name in /.../wp-includes/widgets.php on line 291 Warning: array_merge(): Argument #2 is not an array in /.../wp-includes/widgets.php on line 777

From there, I just see a blank widget placeholder in the admin.

@DrewAPicture
Copy link

Well, the undefined property notice is pretty straightforward. You need to define it in foo_Widget {}. Hint: Look at line 89 in wp-includes/widgets.php.

@mhulse
Copy link
Author

mhulse commented Jun 25, 2013

Hi @DrewAPicture, thanks for your feedback!

I wonder what I would define $option_name as? I'll take a closer look at line 89 in widgets.php. Thank you for the tip!

Actually, I've simplified by code here: https://gist.github.com/mhulse/5861847

By simplifying my code, I think I've found other problems that might be the root of the problems that were not obvious in this Gist. If I can fix the problems I'm having in my simplified code, I'm hoping that will fix the problems that I'm having with this code/gist.

@DrewAPicture
Copy link

On this (first) revision, I cleared the notice by doing protected option_name = ''; and adding $this->option_name = 'widget_' . $args['id_base']; to the constructor, although defining it in the constructor was probably moot since the parent handled it from passed args.

It was an interesting idea, if only kind of a "Yo dawg, I heard you like using widget factories with yo widget factories" :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment