Code snippets for symfony 1.x

Navigation

Snippets by user Svyatoslav Mankovski

Tha django-multilingual style for I18n forms (ability to remove selected translations)

This snippet was created under the inspiration of using the django-multilingual package. Also an additional code is used to solve the problem of saving the many-to-many relations in embedded forms (http://trac.symfony-project.org/ticket/5867#comment:21).

The idea is that in all embedded I18n forms appears checkbox "delete" for each translation. When creating a new object this checkbox is checked for all translation form. To use the translation it's necessary to clear the checkbox in this translation form. When you save a form such I18n embedded form is also being validated and saved, and the forms with checkboxes checked are not validated and not saved. Also the objects of I18n embedded forms with checked checkbox are removed.

Probably it's not ideal solution but it works good for me. If you have any idea how to improve it you're always welcome.

The changes in code are only in one file /lib/forms/doctrine/BaseFormDoctrine.class.php:

<?php
 
/**
 * Project form base class.
 *
 * @package    symfony
 * @subpackage form
 * @author     Svyatoslav Mankovski <slawka@slawka.net>
 * @version    SVN: $Id: sfDoctrineFormBaseTemplate.php 23810 2009-11-12 11:07:44Z Kris.Wallsmith $
 */
abstract class BaseFormDoctrine extends sfFormDoctrine {
 
  protected static $I18nDeleteFieldName = '_i18n_delete';
 
  public function __construct($object = null, $options = array(), $CSRFSecret = null) {
 
    parent::__construct($object, $options, $CSRFSecret);
 
    $this->addI18nDeleteField();
 
    $this->resetFormFields();
  }
 
  public function addI18nDeleteField() {
 
    if ($this->getObject()->getTable()->getParentGenerator() instanceof Doctrine_I18n) {
      $this->widgetSchema[self::$I18nDeleteFieldName] = new sfWidgetFormInputCheckbox(array(
                'label' => sfContext::getInstance()->getI18N()->__('Remove'),
              ));
      $this->setDefault(self::$I18nDeleteFieldName, $this->isNew());
      $this->widgetSchema->moveField(self::$I18nDeleteFieldName, sfWidgetFormSchema::FIRST);
      $this->validatorSchema[self::$I18nDeleteFieldName] = new sfValidatorPass();
    }
 
    return $this;
  }
 
  public function bind(array $taintedValues = null, array $taintedFiles = null) {
 
    if ($this->getObject()->getTable()->hasGenerator('Doctrine_I18n')) {
      $forms = 0;
      $deletes = 0;
      $first_form = '';
      foreach ($taintedValues as $name => $field) {
        if (is_array($field)) {
          $first_form = $first_form == '' ? $name : $first_form;
          $forms++;
          if (isset($field[self::$I18nDeleteFieldName])) {
            $deletes++;
          }
        }
      }
      foreach ($taintedValues as $name => $field) {
        if (is_array($field) && isset($field[self::$I18nDeleteFieldName])) {
          if ($forms > $deletes || $forms == $deletes && $first_form != $name) {
            unset($this->validatorSchema[$name]);
            $this->validatorSchema[$name] = new sfValidatorPass();
          } else {
            unset($taintedValues[$name][self::$I18nDeleteFieldName]);
          }
        }
      }
    }
 
    parent::bind($taintedValues, $taintedFiles);
  }
 
  public function bindAndSave($taintedValues, $taintedFiles = null, $con = null) {
 
    if ($this->getObject()->getTable()->getParentGenerator() instanceof Doctrine_I18n) {
      if (isset($taintedValues[self::$I18nDeleteFieldName])) {
        unset($taintedValues[self::$I18nDeleteFieldName]);
 
        $object = clone $this->getObject();
 
        $object->delete($con);
 
        return true;
      }
    }
 
    return parent::bindAndSave($taintedValues, $taintedFiles, $con);
  }
 
  public function saveEmbeddedForms($con = null, $forms = null, $taintedValues = null) {
    if (null === $con) {
      $con = $this->getConnection();
    }
 
    if (null === $forms) {
      $forms = $this->embeddedForms;
    }
 
    if (null === $taintedValues) {
      $taintedValues = $this->taintedValues;
    }
 
    foreach ($forms as $name => $form) {
      $values = isset($taintedValues[$name]) ? $taintedValues[$name] : array();
      if ($form instanceof sfFormObject) {
        unset($form[self::$CSRFFieldName]);
 
        $form->bindAndSave($values, $this->taintedFiles, $con);
        $form->saveEmbeddedForms($con, null, $values);
      } else {
        $this->saveEmbeddedForms($con, $form->getEmbeddedForms(), $values);
      }
    }
  }
 
}
 
by Svyatoslav Mankovski on 2010-12-10, tagged form  i18n