protected function doPreSave(Doctrine_Record $record, sfForm $form) { // loop through relations if ($relations = $form->getOption('dynamic_relations')) { foreach ($relations as $field => $config) { $collection = $record->get($config['relation']->getAlias()); // collect form objects for comparison $search = array(); foreach ($form->getEmbeddedForm($field)->getEmbeddedForms() as $i => $embed) { $search[] = $embed->getObject(); } foreach ($collection as $i => $object) { if (false === ($pos = array_search($object, $search, true))) { // if a related object exists in the record but isn't represented // in the form, the reference has been removed $collection->remove($i); // if the foreign column is a notnull columns, delete the object $column = $config['relation']->getTable()->getColumnDefinition($config['relation']->getForeignColumnName()); if ($object->exists() && isset($column['notnull']) && $column['notnull']) { $object->delete(); } } } } } }
protected function doPreSave(Doctrine_Record $record, sfForm $form) { // loop through relations if ($relations = $form->getOption('dynamic_relations')) { foreach ($relations as $field => $config) { $collection = $record->get($config['relation']->getAlias()); // collect form objects for comparison $search = array(); try { foreach ($form->getEmbeddedForm($field)->getEmbeddedForms() as $i => $embed) { $search[] = $embed->getObject(); } } catch (InvalidArgumentException $e) { // previously embedded form was removed at the end of form.filter_values as there were no values for it. // @see sfDoctrineDynamicFormRelations::correctValidators() } foreach ($collection as $i => $object) { $pos = array_search($object, $search, true); if (false === $pos && $this->filterObject($object, $config['arguments'])) { // if a related object exists in the record but isn't represented // in the form, the reference has been removed $collection->remove($i); // if the foreign column is a notnull columns, delete the object $column = $config['relation']->getTable()->getColumnDefinition($config['relation']->getForeignColumnName()); if ($object->exists() && isset($column['notnull']) && $column['notnull']) { $object->delete(); } } } } } }
/** * Does the actual embedding. * * This method is called when a relation is dynamically embedded during form * configuration and again just before input values are validated. * * @param sfForm $form A form * @param string $field A field name to use for embedding * @param Doctrine_Collection|array $values An collection of values (objects or arrays) to use for embedding */ protected function doEmbed(sfForm $form, $field, $values) { $relations = $form->getOption('dynamic_relations'); $config = $relations[$field]; $r = new ReflectionClass($config['class']); $parent = new BaseForm(); foreach ($values as $i => $value) { if (is_object($value)) { $child = $r->newInstanceArgs(array_merge(array($value), array($config['arguments']))); } elseif (!empty($value['id'])) { $child = $this->findEmbeddedFormById($form, $field, $value['id']); if (!$child) { throw new InvalidArgumentException(sprintf('Could not find a previously embedded form with id "%s".', $value['id'])); } } else { $object = $config['relation']->getTable()->create(); $object->fromArray($value); $form->getObject()->get($config['relation']->getAlias())->add($object); $child = $r->newInstanceArgs(array_merge(array($object), array($config['arguments']))); } // form must include PK widget if (!isset($child['id'])) { throw new LogicException(sprintf('The %s form must include an "id" field to be embedded as dynamic relation.', get_class($child))); } $parent->embedForm($i, $child); } // workaround embedding despite being bound // this is why this class extends sfForm $wasBound = $form->isBound; $form->isBound = false; $form->embedForm($field, $parent); $form->isBound = $wasBound; }
/** * Returns the embedder form if any, false otherwise. * So we can use this static method for basic sfForms * * @param sfForm $form */ public static function getFormEmbedder(sfForm $form) { return $form->getOption('embedder', false); }