WordPress.org

Make WordPress Core

Opened 8 years ago

Closed 8 years ago

Last modified 7 years ago

#9701 closed feature request (fixed)

Add a the_widget() function to output a generic widget anywhere in a template

Reported by: Viper007Bond Owned by: azaozz
Milestone: 2.8 Priority: low
Severity: minor Version: 2.8
Component: Widgets Keywords: has-patch tested dev-feedback
Focuses: Cc:

Description

For those of us who don't use widgets (for whatever reason), it'd be nice if we could display the recent comments without having to do a bit of hacking to get the widget to work.

I propose the code be moved to a function that's called by the widget.

Attachments (4)

9701-plugin.php (4.4 KB) - added by hakre 8 years ago.
Plugin for Demonstration of a the_widget() Prototype
9701-plugin.2.php (4.6 KB) - added by hakre 8 years ago.
Corrected Demonstration / Test Plugin. Widget now instantiates correctly.
9701.diff (1.4 KB) - added by Denis-de-Bernardy 8 years ago.
9701.2.diff (911 bytes) - added by Denis-de-Bernardy 8 years ago.
fix the sprintf when $args[before_widget] is passed

Download all attachments as: .zip

Change History (28)

#1 @Denis-de-Bernardy
8 years ago

  • Milestone changed from Unassigned to Future Release

#2 @hakre
8 years ago

Wouldn't it be nice to have a function in the global namespace to display any widget with it's options passed by an array? like so

$name    = 'Recent Comments';
$options = array('title' => 'The 20 most Recent Comments', 'number' => 20);
display_widget($name, $options);

#3 @Denis-de-Bernardy
8 years ago

+1. Plus, the new widgets class makes that a lot simpler.

#4 @azaozz
8 years ago

Yes, this should be quite easy. All default widgets can be run as template tags with preset values, even no need to save options (no UI for that anyways).

#5 @hakre
8 years ago

I'm just writing a patch for that. It looks really easy.

@hakre
8 years ago

Plugin for Demonstration of a the_widget() Prototype

#6 @hakre
8 years ago

Install the attached Plugin and you will see the output of a the_widget() test-implementation that does exactly what it is intended for:

the_widget('WP_Widget_Recent_Posts'); // Widget by Classname
the_widget('Recent Comments'); // Widget by Name

#7 @Denis-de-Bernardy
8 years ago

seems extraordinarily complex. in my own plugins, I usually have a function around that goes:

function my_widget($instance = array()) {
  $args = array('before_widget' => '<div>', 'after_widget' => '</div>', etc.);
  my_widget::widget($args, $instance);
}

#8 @hakre
8 years ago

well your code is a static function call with hardcoded values. You want to code that fragment multiple times to mimic every widget? even the ones you do not know the classnames or widget names from? and what about configuring $args?

if you take that into account, i doub you would name the code "extraordinarily complex".

with my suggestion i wanted to ensure that the widget works as it should, like an instance of a widget, in it's own sidebar environment, fully configureable and callable by widget-name, not only by class.

this is done sothat it works with _any_ registered widget. and it is possible to configure the sidebar args. your example uses hardcoded values therefore. next to this, the standard filter that can decide wether or not a widget should be displayed has been implemented to better mimic the stand widget display procedure.

the rest in the attachment is just plugin and test-widget code. so basically, this one function is how it looks like, and I do not think it is that complex:

/** widget template tag
 * 
 * get a configured widgets output without the need of a sidebar and backend administration. 
 * 
 * NOTE: this is development code
 * 
 * @global WP_Widget_Factory $wp_widget_factory 
 * @global array $wp_registered_sidebars
 * 
 * @param string $widget   widget identifier
 * @param array  $settings optional widget settings
 * @param array  $args     optional sidebar options  
 * @return void
 */
function the_widget($widget, $settings = array(), $args = array()) {
	
	/* sanitize input */
	$widget = (string) $widget;
	if (!strlen($widget))
		return;
	if (!is_array($settings))
		return;
	if (!is_array($args))
		return;

	/* globals */	
	global $wp_widget_factory, $wp_registered_sidebars;	
	
	/* pull default (def) sidebar options (args) */	
	$sidebar_id = register_sidebar( array('name' => uniqid('temp-')) );	
	$def  = $wp_registered_sidebars[$sidebar_id];
	$args = array_merge($def, $args);
							
	/* get widget ($instance) */
 	$instance = null;
	if (isset($wp_widget_factory->widgets[$widget])) {
		$instance = $wp_widget_factory->widgets[$widget];
	} else {
		foreach($wp_widget_factory->widgets as $value)
			if (isset($value->name))
				if ($value->name == $widget) {
					$instance = $value;
					break;
				}
	}
	
	/*  display widget */
	if (is_a($instance, 'WP_Widget')) {
		$settings = apply_filters('widget_display_callback', $settings, $instance);   
		if ( false !== $settings )
			$instance->widget($args, $settings);
	}	
	
	unregister_sidebar($sidebar_id);
}

@hakre
8 years ago

Corrected Demonstration / Test Plugin. Widget now instantiates correctly.

#9 @Denis-de-Bernardy
8 years ago

  • Keywords has-patch added; needs-patch removed
  • Milestone changed from Future Release to 2.8

I still fail to see the point in registering a fake sidebar. :-)

Suggested alternative patch attached.

#10 @Denis-de-Bernardy
8 years ago

  • Summary changed from Pull the "Recent Comments" code out of the widget and into it's own function to Add a the_widget() to output a generic widget anywhere in a template

#11 @Denis-de-Bernardy
8 years ago

  • Priority changed from normal to low
  • Severity changed from normal to minor
  • Summary changed from Add a the_widget() to output a generic widget anywhere in a template to Add a the_widget() function to output a generic widget anywhere in a template
  • Type changed from enhancement to feature request

#12 @Denis-de-Bernardy
8 years ago

  • Keywords tested dev-feedback added

#13 @ryan
8 years ago

  • Owner set to azaozz

9701.diff seems good to me. Andrew?

#14 @Denis-de-Bernardy
8 years ago

oh wait, patch actually has an issue.

if ( in_the_loop() ) {

should be:

if ( !in_the_loop() ) {

fixing this right away. :-)

#15 @Denis-de-Bernardy
8 years ago

err, nevermind that. it's just getting late.

#16 @azaozz
8 years ago

It has actually a typo too and the default tag when in the sidebar should preferably be <li>, otherwise <div> in or out of the loop. Looking at it now.

#17 @Denis-de-Bernardy
8 years ago

lol. make that *very* late. :-)

#18 @Denis-de-Bernardy
8 years ago

the div tag might be the best one to use at all times, on second thoughts. it's reasonably safe to assume that sidebars are using sidebar widgets nowadays.

#19 @azaozz
8 years ago

  • Resolution set to fixed
  • Status changed from new to closed

(In [11317]) Add a function to output a generic widget anywhere in a template, props Denis-de-Bernardy, fixes #9701

#20 @azaozz
8 years ago

Sounds good, removed the in_the_loop() conditional.

@Denis-de-Bernardy
8 years ago

fix the sprintf when $args[before_widget] is passed

#21 @Denis-de-Bernardy
8 years ago

mm... the sprintf() call might be wrongly placed. I attached a patch to make this work:

the_widget('foo', $instance, array('before_widget' => '<li class="foo %s">', 'after_widget' => '</li>');

or then, you're assuming that this syntax will be used (in which case nevermind, and not re-opening for this reason):

the_widget('foo', $instance, array('before_widget' => '<li>', 'after_widget' => '</li>');

#22 follow-up: @Denis-de-Bernardy
8 years ago

both options are valid I think. it can safely be assumed that, if the user wants a specific class, he'll add it.

#23 in reply to: ↑ 22 @azaozz
8 years ago

Replying to Denis-de-Bernardy:

both options are valid I think. it can safely be assumed that, if the user wants a specific class, he'll add it.

Yes, exactly. No need to

sprintf('<div class="my-custom-class">', $widget_obj->widget_options['classname']);

#24 @Denis-de-Bernardy
8 years ago

ok, then it's good to know I'm starting to get a feel of your mindset. :-)

Note: See TracTickets for help on using tickets.