Opened 4 years ago

Closed 4 years ago

Last modified 3 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
Priority: low Milestone: 2.8
Component: Widgets Version: 2.8
Severity: minor Keywords: has-patch tested dev-feedback
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 4 years ago.
Plugin for Demonstration of a the_widget() Prototype
9701-plugin.2.php (4.6 KB) - added by hakre 4 years ago.
Corrected Demonstration / Test Plugin. Widget now instantiates correctly.
9701.diff (1.4 KB) - added by Denis-de-Bernardy 4 years ago.
9701.2.diff (911 bytes) - added by Denis-de-Bernardy 4 years ago.
fix the sprintf when $args[before_widget] is passed

Download all attachments as: .zip

Change History (28)

  • Milestone changed from Unassigned to Future Release

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);

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

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).

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

hakre4 years ago

Plugin for Demonstration of a the_widget() Prototype

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

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);
}

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);
}

hakre4 years ago

Corrected Demonstration / Test Plugin. Widget now instantiates correctly.

  • 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.

  • 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
  • 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
  • Keywords tested dev-feedback added
  • Owner set to azaozz

9701.diff seems good to me. Andrew?

oh wait, patch actually has an issue.

if ( in_the_loop() ) {

should be:

if ( !in_the_loop() ) {

fixing this right away. :-)

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

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.

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

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.

  • 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

Sounds good, removed the in_the_loop() conditional.

fix the sprintf when $args[before_widget] is passed

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>');

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

comment:23 in reply to: ↑ 22   azaozz4 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']);

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.