widget:
class ynWidgetFormDoctrineChoiceEmpty extends sfWidgetFormDoctrineChoice
{
protected function configure( $options = array(), $attributes = array() )
{
parent::configure( $options, $attributes );
$this->addOption( 'with_empty', false );
$this->addOption( 'empty_label', 'none' );
$this->addOption( 'template', '%select%<div>%empty_checkbox% %empty_label%</div>' );
}
public function render( $name, $value = null, $attributes = array(), $errors = array() )
{
$select = parent::render( $name, $value, $attributes, $errors );
if ( $this->getOption('with_empty') ) {
$values = array_merge(array('text' => '', 'is_empty' => false), is_array($value) ? $value : array());
return strtr($this->getOption('template'), array(
'%select%' => $select,
'%empty_checkbox%' => $this->renderTag('input', array('type' => 'checkbox', 'name' => $name.'[is_empty]', 'checked' => $values['is_empty'] ? 'checked' : '')),
'%empty_label%' => $this->renderContentTag('label', $this->translate($this->getOption('empty_label')), array('for' => $this->generateId($name.'[is_empty]'))),
));
}
else {
return $select;
}
}
}
validator:
class ynValidatorDoctrineChoiceEmpty extends sfValidatorDoctrineChoice
{
public function configure( $options = array(), $messages = array() )
{
parent::configure( $options = array(), $messages = array() );
$this->addMessage('empty_or_not', 'Select either choices or none');
}
protected function doClean( $values )
{
if (
isset( $values['is_empty'] )
&& $values['is_empty'] == 'on'
) {
if ( count( $values ) > 1 ) {
// 'empty' selected alongside subjects
throw new sfValidatorError( $this, 'empty_or_not' );
}
return $values;
}
else {
return parent::doClean( $values );
}
}
}
in FooFormFilter
:
public function addBarListColumnQuery( Doctrine_Query $query, $field, $values )
{
if (!is_array($values))
{
$values = array($values);
}
if (!count($values))
{
return;
}
if (
isset( $values['is_empty'] )
&& $values['is_empty'] == 'on'
) {
$query
->andWhere('NOT EXISTS (SELECT fb.bar_id '
. 'FROM FooBar fb where ' . $query->getRootAlias()
. '.id=fb.foo_id)');
}
else {
$query
->leftJoin($query->getRootAlias().'.FooBar FooBar')
->andWhereIn('FooBar.bar_id', $values)
;
}
}