Resolví esto en Javascript. Si quieres evitarlo por completo, también deberías hacerlo desde el lado del servidor, ya que puedes editar los widgets con Javascript desactivado (¡pruébalo!).
Las diferentes barras laterales se verifican cuando coloca los widgets en ellos o se aleja de ellos. Si se llenan, el color de fondo cambia y ya no puede colocar elementos en ellos. Si, en el inicio, la barra lateral ya está más que llena (porque ajustó la restricción), el color de fondo se vuelve rojo. Aún puedes arrastrar los widgets lejos de los widgets completos para hacerlos vacíos nuevamente.

Pruebeestecódigoparaencontrarformasdeagregaroeliminarwidgetsquenoencontré.La"magia" en el código jQuery proviene de Aman , quien respondió a una pregunta de desbordamiento de pila que publiqué al respecto .
Javascript:
jQuery( function( $ ) {
var sidebarLimits = {
'sidebar-1': 2,
'sidebar-2': 2,
};
var realSidebars = $( '#widgets-right div.widgets-sortables' );
var availableWidgets = $( '#widget-list' ).children( '.widget' );
var checkLength = function( sidebar, delta ) {
var sidebarId = sidebar.id;
if ( undefined === sidebarLimits[sidebarId] ) {
return;
}
// This is a limited sidebar
// Find out how many widgets it already has
var widgets = $( sidebar ).sortable( 'toArray' );
$( sidebar ).toggleClass( 'sidebar-full', sidebarLimits[sidebarId] <= widgets.length + (delta || 0) );
$( sidebar ).toggleClass( 'sidebar-morethanfull', sidebarLimits[sidebarId] < widgets.length + (delta || 0) );
var notFullSidebars = $( 'div.widgets-sortables' ).not( '.sidebar-full' );
availableWidgets.draggable( 'option', 'connectToSortable', notFullSidebars );
realSidebars.sortable( 'option', 'connectWith', notFullSidebars );
}
// Check existing sidebars on startup
realSidebars.map( function() {
checkLength( this );
} );
// Update when dragging to this (sort-receive)
// and away to another sortable (sort-remove)
realSidebars.bind( 'sortreceive sortremove', function( event, ui ) {
checkLength( this );
} );
// Update when dragging back to the "Available widgets" stack
realSidebars.bind( 'sortstop', function( event, ui ) {
if ( ui.item.hasClass( 'deleting' ) ) {
checkLength( this, -1 );
}
} );
// Update when the "Delete" link is clicked
$( 'a.widget-control-remove' ).live( 'click', function() {
checkLength( $( this ).closest( 'div.widgets-sortables' )[0], -1 );
} );
} );
CSS:
.sidebar-full
{
background-color: #cfe1ef !important;
}
.sidebar-morethanfull
{
background-color: #c43 !important;
}
PHP para cargarlos:
$wpse19907_file = $plugin;
add_action( 'admin_enqueue_scripts', 'wpse19907_admin_enqueue_scripts' );
function wpse19907_admin_enqueue_scripts( $hook_suffix )
{
if ( 'widgets.php' == $hook_suffix ) {
wp_enqueue_script( 'wpse-19907', plugins_url( 'wpse-19907.js', $GLOBALS['wpse19907_file'] ), array(), false, true );
wp_enqueue_style( 'wpse-19907', plugins_url( 'wpse-19907.css', $GLOBALS['wpse19907_file'] ) );
}
}
Un intento de verificación del lado del servidor (probablemente aún no esté completo):
$wpse19907_sidebars_max_widgets = array(
'sidebar-1' => 2,
);
add_action( 'sidebar_admin_setup', 'wpse19907_sidebar_admin_setup' );
function wpse19907_sidebar_admin_setup()
{
if ( ! isset( $_POST['action'] ) || 'save-widget' != $_POST['action'] || empty( $_POST['add_new'] ) ) {
return;
}
// We're adding a new widget to a sidebar
global $wpse19907_sidebars_max_widgets;
$sidebar_id = $_POST['sidebar'];
if ( ! array_key_exists( $sidebar_id, $wpse19907_sidebars_max_widgets ) ) {
return;
}
$sidebar = wp_get_sidebars_widgets();
$sidebar = isset( $sidebars[$sidebar_id] ) ? $sidebars[$sidebar_id] : array();
if ( count( $sidebar ) <= $wpse19907_sidebars_max_widgets[$sidebar_id] ) {
die( 'mx' ); // Length must be shorter than 2, and unique
}
}