@@ -32,7 +32,6 @@ function wp_dashboard_setup() {
3232 array ( 'all_link ' => 'edit-comments.php ' , 'notice ' => $ notice , 'width ' => 'half ' )
3333 );
3434
35-
3635 // Incoming Links Widget
3736 if ( !isset ( $ widget_options ['dashboard_incoming_links ' ] ) ) {
3837 $ update = true ;
@@ -44,7 +43,8 @@ function wp_dashboard_setup() {
4443 );
4544 }
4645 wp_register_sidebar_widget ( 'dashboard_incoming_links ' , __ ( 'Incoming Links ' ), 'wp_dashboard_empty ' ,
47- array ( 'all_link ' => $ widget_options ['dashboard_incoming_links ' ]['link ' ], 'feed_link ' => $ widget_options ['dashboard_incoming_links ' ]['url ' ], 'width ' => 'half ' )
46+ array ( 'all_link ' => $ widget_options ['dashboard_incoming_links ' ]['link ' ], 'feed_link ' => $ widget_options ['dashboard_incoming_links ' ]['url ' ], 'width ' => 'half ' ),
47+ 'wp_dashboard_cached_rss_widget ' , 'wp_dashboard_incoming_links_output '
4848 );
4949 wp_register_widget_control ( 'dashboard_incoming_links ' , __ ( 'Incoming Links ' ), 'wp_dashboard_rss_control ' , array (),
5050 array ( 'widget_id ' => 'dashboard_incoming_links ' , 'form_inputs ' => array ( 'title ' => false , 'show_summary ' => false , 'show_author ' => false ) )
@@ -53,13 +53,11 @@ function wp_dashboard_setup() {
5353
5454 // WP Plugins Widget
5555 wp_register_sidebar_widget ( 'dashboard_plugins ' , __ ( 'Plugins ' ), 'wp_dashboard_empty ' ,
56- array ( 'all_link ' => 'http://wordpress.org/extend/plugins/ ' , 'feed_link ' => 'http://wordpress.org/extend/plugins/rss/ ' , 'width ' => 'half ' )
57- );
58- wp_register_widget_control ( 'dashboard_plugins ' , __ ( 'Plugins ' ), 'wp_dashboard_empty ' , array (),
59- array ( 'widget_id ' => 'dashboard_plugins ' )
56+ array ( 'all_link ' => 'http://wordpress.org/extend/plugins/ ' , 'feed_link ' => 'http://wordpress.org/extend/plugins/rss/ ' , 'width ' => 'half ' ),
57+ 'wp_dashboard_cached_rss_widget ' , 'wp_dashboard_plugins_output ' ,
58+ array ( 'http://wordpress.org/extend/plugins/rss/browse/popular/ ' , 'http://wordpress.org/extend/plugins/rss/browse/new/ ' , 'http://wordpress.org/extend/plugins/rss/browse/updated/ ' )
6059 );
6160
62-
6361 // Primary feed (Dev Blog) Widget
6462 if ( !isset ( $ widget_options ['dashboard_primary ' ] ) ) {
6563 $ update = true ;
@@ -74,7 +72,8 @@ function wp_dashboard_setup() {
7472 );
7573 }
7674 wp_register_sidebar_widget ( 'dashboard_primary ' , $ widget_options ['dashboard_primary ' ]['title ' ], 'wp_dashboard_empty ' ,
77- array ( 'all_link ' => $ widget_options ['dashboard_primary ' ]['link ' ], 'feed_link ' => $ widget_options ['dashboard_primary ' ]['url ' ], 'width ' => 'half ' , 'class ' => 'widget_rss ' )
75+ array ( 'all_link ' => $ widget_options ['dashboard_primary ' ]['link ' ], 'feed_link ' => $ widget_options ['dashboard_primary ' ]['url ' ], 'width ' => 'half ' , 'class ' => 'widget_rss ' ),
76+ 'wp_dashboard_cached_rss_widget ' , 'wp_dashboard_rss_output '
7877 );
7978 wp_register_widget_control ( 'dashboard_primary ' , __ ( 'Primary Feed ' ), 'wp_dashboard_rss_control ' , array (),
8079 array ( 'widget_id ' => 'dashboard_primary ' )
@@ -92,13 +91,38 @@ function wp_dashboard_setup() {
9291 );
9392 }
9493 wp_register_sidebar_widget ( 'dashboard_secondary ' , $ widget_options ['dashboard_secondary ' ]['title ' ], 'wp_dashboard_empty ' ,
95- array ( 'all_link ' => $ widget_options ['dashboard_secondary ' ]['link ' ], 'feed_link ' => $ widget_options ['dashboard_secondary ' ]['url ' ], 'width ' => 'full ' )
94+ array ( 'all_link ' => $ widget_options ['dashboard_secondary ' ]['link ' ], 'feed_link ' => $ widget_options ['dashboard_secondary ' ]['url ' ], 'width ' => 'full ' ),
95+ 'wp_dashboard_cached_rss_widget ' , 'wp_dashboard_secondary_output '
9696 );
9797 wp_register_widget_control ( 'dashboard_secondary ' , __ ( 'Secondary Feed ' ), 'wp_dashboard_rss_control ' , array (),
9898 array ( 'widget_id ' => 'dashboard_secondary ' , 'form_inputs ' => array ( 'show_summary ' => false , 'show_author ' => false , 'show_date ' => false ) )
9999 );
100100
101101
102+ /* Dashboard Widget Template
103+ wp_register_sidebar_widget( $widget_id (unique slug) , $widget_title, $output_callback,
104+ array(
105+ 'all_link' => full url for "See All" link,
106+ 'feed_link' => full url for "RSS" link,
107+ 'width' => 'fourth', 'third', 'half', 'full' (defaults to 'half'),
108+ 'height' => 'single', 'double' (defaults to 'single'),
109+ ),
110+ $wp_dashboard_empty_callback (only needed if using 'wp_dashboard_empty' as your $output_callback),
111+ $arg, $arg, $arg... (further args passed to callbacks)
112+ );
113+
114+ // optional: if you want users to be able to edit the settings of your widget, you need to register a widget_control
115+ wp_register_widget_control( $widget_id, $widget_control_title, $control_output_callback,
116+ array(), // leave an empty array here: oddity in widget code
117+ array(
118+ 'widget_id' => $widget_id, // Yes - again. This is required: oddity in widget code
119+ 'arg' => an arg to pass to the $control_output_callback,
120+ 'another' => another arg to pass to the $control_output_callback,
121+ ...
122+ )
123+ );
124+ */
125+
102126 // Hook to register new widgets
103127 do_action ( 'wp_dashboard_setup ' );
104128
@@ -174,7 +198,7 @@ function wp_dashboard_dynamic_sidebar_params( $params ) {
174198 $ content_class .= ' dashboard-widget-control ' ;
175199 $ wp_registered_widgets [$ widget_id ]['callback ' ] = 'wp_dashboard_empty ' ;
176200 $ sidebar_widget_name = $ wp_registered_widget_controls [$ widget_id ]['name ' ];
177- $ params [1 ] = $ widget_id ;
201+ $ params [1 ] = ' wp_dashbaord_trigger_widget_control ' ;
178202 $ sidebar_before_widget .= '<form action=" ' . remove_query_arg ( 'edit ' ) . '" method="post"> ' ;
179203 $ sidebar_after_widget = "<div class='dashboard-widget-submit'><input type='hidden' name='sidebar' value='wp_dashboard' /><input type='hidden' name='widget_id' value=' $ widget_id' /><input type='submit' value=' " . __ ( 'Save ' ) . "' /></div></form> $ sidebar_after_widget " ;
180204 $ links [] = '<a href=" ' . remove_query_arg ( 'edit ' ) . '"> ' . __ ( 'Cancel ' ) . '</a> ' ;
@@ -218,7 +242,6 @@ function wp_dashboard_dynamic_sidebar_params( $params ) {
218242
219243function wp_dashboard_recent_comments ( $ sidebar_args ) {
220244 global $ comment ;
221-
222245 extract ( $ sidebar_args , EXTR_SKIP );
223246
224247 echo $ before_widget ;
@@ -268,8 +291,182 @@ function wp_dashboard_recent_comments( $sidebar_args ) {
268291 echo $ after_widget ;
269292}
270293
271- // Empty widget used for JS/AJAX created output. Also used when widget is in edit mode.
272- function wp_dashboard_empty ( $ sidebar_args , $ widget_control_id = false ) {
294+ // $sidebar_args are handled by wp_dashboard_empty()
295+ function wp_dashboard_incoming_links_output () {
296+ $ widgets = get_option ( 'dashboard_widget_options ' );
297+ @extract ( @$ widgets ['dashboard_incoming_links ' ], EXTR_SKIP );
298+ $ rss = @fetch_rss ( $ url );
299+ if ( isset ($ rss ->items ) && 1 < count ($ rss ->items ) ) {// Technorati returns a 1-item feed when it has no results
300+
301+ echo "<ul> \n" ;
302+
303+ $ rss ->items = array_slice ($ rss ->items , 0 , $ items );
304+ foreach ( $ rss ->items as $ item ) {
305+ $ publisher = '' ;
306+ $ site_link = '' ;
307+ $ link = '' ;
308+ $ content = '' ;
309+ $ date = '' ;
310+ $ link = clean_url ( strip_tags ( $ item ['link ' ] ) );
311+
312+ if ( isset ( $ item ['author_uri ' ] ) )
313+ $ site_link = clean_url ( strip_tags ( $ item ['author_uri ' ] ) );
314+
315+ if ( !$ publisher = wp_specialchars ( strip_tags ( isset ($ item ['dc ' ]['publisher ' ]) ? $ item ['dc ' ]['publisher ' ] : $ item ['author_name ' ] ) ) )
316+ $ publisher = __ ( 'Somebody ' );
317+ if ( $ site_link )
318+ $ publisher = "<a href=' $ site_link'> $ publisher</a> " ;
319+ else
320+ $ publisher = "<strong> $ publisher</strong> " ;
321+
322+ if ( isset ($ item ['description ' ]) )
323+ $ content = $ item ['description ' ];
324+ elseif ( isset ($ item ['summary ' ]) )
325+ $ content = $ item ['summary ' ];
326+ elseif ( isset ($ item ['atom_content ' ]) )
327+ $ content = $ item ['atom_content ' ];
328+ else
329+ $ content = __ ( 'something ' );
330+ $ content = strip_tags ( $ content );
331+ if ( 50 < strlen ($ content ) )
332+ $ content = substr ($ content , 0 , 50 ) . ' ... ' ;
333+ $ content = wp_specialchars ( $ content );
334+ if ( $ link )
335+ $ text = _c ( '%1$s linked here <a href="%2$s">saying</a>, "%3$s"|feed_display ' );
336+ else
337+ $ text = _c ( '%1$s linked here saying, "%3$s"|feed_display ' );
338+
339+ if ( $ show_date ) {
340+ if ( $ show_author || $ show_summary )
341+ $ text .= _c ( ' on %4$s|feed_display ' );
342+ $ date = wp_specialchars ( strip_tags ( isset ($ item ['pubdate ' ]) ? $ item ['pubdate ' ] : $ item ['published ' ] ) );
343+ $ date = strtotime ( $ date );
344+ $ date = gmdate ( get_option ( 'date_format ' ), $ date );
345+ }
346+
347+ echo "\t<li> " . sprintf ( _c ( "$ text|feed_display " ), $ publisher , $ link , $ content , $ date ) . "</li> \n" ;
348+ }
349+
350+ echo "</ul> \n" ;
351+
352+ } else {
353+ echo '<p> ' . __ ('No incoming links found... yet. ' ) . "</p> \n" ;
354+ }
355+ }
356+
357+ // $sidebar_args are handled by wp_dashboard_empty()
358+ function wp_dashboard_rss_output ( $ widget_id ) {
359+ $ widgets = get_option ( 'dashboard_widget_options ' );
360+ wp_widget_rss_output ( $ widgets [$ widget_id ] );
361+ }
362+
363+ // $sidebar_args are handled by wp_dashboard_empty()
364+ function wp_dashboard_secondary_output () {
365+ $ widgets = get_option ( 'dashboard_widget_options ' );
366+ @extract ( @$ widgets ['dashboard_secondary ' ], EXTR_SKIP );
367+ $ rss = @fetch_rss ( $ url );
368+ if ( !isset ($ rss ->items ) || 0 == count ($ rss ->items ) )
369+ return false ;
370+
371+ echo "<ul> \n" ;
372+
373+ $ rss ->items = array_slice ($ rss ->items , 0 , $ items );
374+ foreach ($ rss ->items as $ item ) {
375+ $ title = wp_specialchars ($ item ['title ' ]);
376+ $ author = preg_replace ( '|(.+?):.+|s ' , '$1 ' , $ item ['title ' ] );
377+ $ post = preg_replace ( '|.+?:(.+)|s ' , '$1 ' , $ item ['title ' ] );
378+ $ link = clean_url ($ item ['link ' ]);
379+
380+ echo "\t<li><a href=' $ link'><span class='post'> $ post</span><span class='hidden'> - </span><cite> $ author</cite></a></li> \n" ;
381+ }
382+
383+ echo "</ul> \n<br class='clear' /> \n" ;
384+ }
385+
386+ // $sidebar_args are handled by wp_dashboard_empty()
387+ function wp_dashboard_plugins_output () {
388+ $ popular = @fetch_rss ( 'http://wordpress.org/extend/plugins/rss/browse/popular/ ' );
389+ $ new = @fetch_rss ( 'http://wordpress.org/extend/plugins/rss/browse/new/ ' );
390+ $ updated = @fetch_rss ( 'http://wordpress.org/extend/plugins/rss/browse/updated/ ' );
391+
392+ foreach ( array ( 'popular ' => __ ('Most Popular ' ), 'new ' => __ ('Newest Plugins ' ), 'updated ' => __ ('Recently Updated ' ) ) as $ feed => $ label ) {
393+ if ( !isset ($ $ feed ->items ) || 0 == count ($ $ feed ->items ) )
394+ continue ;
395+
396+ $ $ feed ->items = array_slice ($ $ feed ->items , 0 , 5 );
397+ $ item_key = array_rand ($ $ feed ->items );
398+
399+ // Eliminate some common badly formed plugin descriptions
400+ while ( ( null !== $ item_key = array_rand ($ $ feed ->items ) ) && false !== strpos ( $ $ feed ->items [$ item_key ]['description ' ], 'Plugin Name: ' ) )
401+ unset($ $ feed ->items [$ item_key ]);
402+
403+ if ( !isset ($ $ feed ->items [$ item_key ]) )
404+ continue ;
405+
406+ $ item = $ $ feed ->items [$ item_key ];
407+
408+ // current bbPress feed item titles are: user on "topic title"
409+ if ( preg_match ( '/"(.*)"/s ' , $ item ['title ' ], $ matches ) )
410+ $ title = $ matches [1 ];
411+ else // but let's make it forward compatible if things change
412+ $ title = $ item ['title ' ];
413+ $ title = wp_specialchars ( $ title );
414+
415+ $ description = wp_specialchars ( strip_tags (html_entity_decode ($ item ['description ' ], ENT_QUOTES )) );
416+
417+ list ($ link , $ frag ) = explode ( '# ' , $ item ['link ' ] );
418+
419+ $ link = clean_url ($ link );
420+ $ dlink = rtrim ($ link , '/ ' ) . '/download/ ' ;
421+
422+ echo "<h4> $ label</h4> \n" ;
423+ echo "<h5><a href=' $ link'> $ title</a></h5> <span>(<a href=' $ dlink'> " . __ ( 'Download ' ) . "</a>)</span> \n" ;
424+ echo "<p> $ description</p> \n" ;
425+ }
426+ }
427+
428+ // Checks to see if all of the feed url in $check_urls are cached.
429+ // If $check_urls is empty, look for the rss feed url found in the dashboard widget optios of $widget_id.
430+ // If cached, call $callback, a function that echoes out output for this widget.
431+ // If not cache, echo a "Loading..." stub which is later replaced by AJAX call (see top of /wp-admin/index.php)
432+ function wp_dashboard_cached_rss_widget ( $ widget_id , $ callback , $ check_urls = array () ) {
433+ $ loading = '<p class="widget-loading"> ' . __ ( 'Loading… ' ) . '</p> ' ;
434+
435+ if ( empty ($ check_urls ) ) {
436+ $ widgets = get_option ( 'dashboard_widget_options ' );
437+ if ( empty ($ widgets [$ widget_id ]['url ' ]) ) {
438+ echo $ loading ;
439+ return false ;
440+ }
441+ $ check_urls = array ( $ widgets [$ widget_id ]['url ' ] );
442+ }
443+
444+
445+ require_once ( ABSPATH . WPINC . '/rss.php ' );
446+ init (); // initialize rss constants
447+
448+ $ cache = new RSSCache ( MAGPIE_CACHE_DIR , MAGPIE_CACHE_AGE );
449+
450+ foreach ( $ check_urls as $ check_url ) {
451+ $ status = $ cache ->check_cache ( $ check_url );
452+ if ( 'HIT ' !== $ status ) {
453+ echo $ loading ;
454+ return false ;
455+ }
456+ }
457+
458+ if ( $ callback && is_callable ( $ callback ) ) {
459+ $ args = array_slice ( func_get_args (), 2 );
460+ array_unshift ( $ args , $ widget_id );
461+ call_user_func_array ( $ callback , $ args );
462+ }
463+
464+ return true ;
465+ }
466+
467+ // Empty widget used for JS/AJAX created output.
468+ // Callback inserts content between before_widget and after_widget. Used when widget is in edit mode. Can also be used for custom widgets.
469+ function wp_dashboard_empty ( $ sidebar_args , $ callback = false ) {
273470 extract ( $ sidebar_args , EXTR_SKIP );
274471
275472 echo $ before_widget ;
@@ -278,8 +475,12 @@ function wp_dashboard_empty( $sidebar_args, $widget_control_id = false ) {
278475 echo $ widget_name ;
279476 echo $ after_title ;
280477
281- if ( $ widget_control_id ) // If in edit mode
282- wp_dashbaord_trigger_widget_control ( $ widget_control_id );
478+ // When in edit mode, the callback passed to this function is the widget_control callback
479+ if ( $ callback && is_callable ( $ callback ) ) {
480+ $ args = array_slice ( func_get_args (), 2 );
481+ array_unshift ( $ args , $ widget_id );
482+ call_user_func_array ( $ callback , $ args );
483+ }
283484
284485 echo $ after_widget ;
285486}
0 commit comments