Limit the number of inactive widgets

I’m trying to restrict the number of widgets from the “wp_inactive_widgets” sidebar to maximum 10, because the widgets admin page is incredibly slow:

add_filter('pre_update_option_sidebars_widgets', 'cleanup_inactive_widgets', 10, 2);

function cleanup_inactive_widgets($new, $old){
  if(!empty($new['wp_inactive_widgets']) && count($new['wp_inactive_widgets']) > 10)
    $new['wp_inactive_widgets'] = array_slice($new['wp_inactive_widgets'], -10, 10);

  return $new;
}

This works apparently, but the problem is that the widget instance options still remain in the database, regardless if the widget instance exists or not inside a sidebar…

Read More

Does anyone know a way to remove the widget options too?


I found out a solution:

Edit: in certain situations it seems to remove widgets from other sidebars too, I’m not sure what’s causing this…

if(!empty($new['wp_inactive_widgets']) && count($new['wp_inactive_widgets']) > 10){

  // find out which widget instances to remove
  $removed_widgets = array_slice($new['wp_inactive_widgets'], 0, -10);

  // remove instance options
  foreach($removed_widgets as $widget_id)
    if(isset($GLOBALS['wp_registered_widgets'][$widget_id])){

      $instance = $GLOBALS['wp_registered_widgets'][$widget_id]['callback'][0]->number;
      $option_name = $GLOBALS['wp_registered_widgets'][$widget_id]['callback'][0]->option_name;

      $options = get_option($option_name);   // get options of all instances
      unset($options[$instance]);            // remove this instance's options
      update_option($option_name, $options);
    }

  // keep only the last 10 records from the inactive widgets area
  $new['wp_inactive_widgets'] = array_slice($new['wp_inactive_widgets'], -10, 10);

}
return $new;

Related posts

Leave a Reply

1 comment

  1. Tested under v3.2.1:

    $sidebars = wp_get_sidebars_widgets();
    if(count($sidebars['wp_inactive_widgets']) > 10){
        $new_inactive = array_slice($sidebars['wp_inactive_widgets'],-10,10);
    
        // remove the dead widget options
        $dead_inactive = array_slice($sidebars['wp_inactive_widgets'],0,count($sidebars['wp_inactive_widgets'])-10);
        foreach($dead_inactive as $dead){
            $pos = strpos($dead,'-');
            $widget_name = substr($dead,0,$pos);
            $widget_number = substr($dead,$pos+1);
            $option = get_option('widget_'.$widget_name);
            unset($option[$widget_number]);
            update_option('widget_'.$widget_name,$option);
        }
    
        // save our new widget setup
        $sidebars['wp_inactive_widgets'] = $new_inactive;
        wp_set_sidebars_widgets($sidebars);
    }
    

    The above code limits the inactive sidebar to the last 10 widgets, and only the inactive sidebar. It also removes the options for the widgets that have been deleted.