From e1dc2dadafeac1bf0f11f1f767a4628cf55ba2d0 Mon Sep 17 00:00:00 2001 From: avl Date: Sun, 5 Oct 2008 20:48:23 +0300 Subject: [PATCH] Support ManyToMany relations in forms --- ipf/admin/model.php | 9 +++++++ ipf/admin/templates/admin/base.html | 1 + ipf/form/db/manytomany.php | 21 ++++++++++++++++ ipf/form/field/modelchoice.php | 6 ++--- ipf/form/field/modelmultiplechoice.php | 12 ++++++++++ ipf/form/field/multiplechoice.php | 32 +++++++++++++++++++++++++ ipf/form/model.php | 19 +++++++++++++++ ipf/form/widget/selectmultipleinput.php | 7 +++--- ipf/orm/connection/unitofwork.php | 7 +++--- ipf/orm/exception/orm.php | 7 +++--- ipf/orm/record.php | 4 +++- 11 files changed, 110 insertions(+), 15 deletions(-) create mode 100644 ipf/form/db/manytomany.php create mode 100644 ipf/form/field/modelmultiplechoice.php create mode 100644 ipf/form/field/multiplechoice.php diff --git a/ipf/admin/model.php b/ipf/admin/model.php index 673299f..73db6b4 100644 --- a/ipf/admin/model.php +++ b/ipf/admin/model.php @@ -216,6 +216,15 @@ class IPF_Admin_Model{ } else{ $data = $o->getData(); + foreach($o->getTable()->getRelations() as $rname=>$rel){ + if (array_search($rname,$this->fields())){ + if ($rel->getType()==IPF_ORM_Relation::MANY_AGGREGATE){ + $data[$rname] = array(); + foreach($rel->fetchRelatedFor($o) as $ri) + $data[$rname][] = $ri->id; + } + } + } $form = $this->_getEditForm($o,&$data,array('user_fields'=>$this->fields())); $this->_setupEditForm($form); $this->setInlines($o, &$data); diff --git a/ipf/admin/templates/admin/base.html b/ipf/admin/templates/admin/base.html index 476d8ec..047adf5 100644 --- a/ipf/admin/templates/admin/base.html +++ b/ipf/admin/templates/admin/base.html @@ -32,5 +32,6 @@ {block scripts}{/block} + diff --git a/ipf/form/db/manytomany.php b/ipf/form/db/manytomany.php new file mode 100644 index 0000000..2188498 --- /dev/null +++ b/ipf/form/db/manytomany.php @@ -0,0 +1,21 @@ +findAll(); + $choices = array(); + foreach($list_objects as $o){ + $choices[$o->__toString()] = $o->id; + } + $def['choices'] = $choices; + if (!isset($def['widget'])) { + $def['widget'] = 'IPF_Form_Widget_SelectMultipleInput'; + } + return parent::formField($def, $form_field); + } +} diff --git a/ipf/form/field/modelchoice.php b/ipf/form/field/modelchoice.php index 1ce1ce5..47d8325 100644 --- a/ipf/form/field/modelchoice.php +++ b/ipf/form/field/modelchoice.php @@ -6,7 +6,7 @@ class IPF_Form_Field_ModelChoice extends IPF_Form_Field_Choice{ function __construct($params=array()){ parent::__construct($params); - $this->model = $params['model']; + $this->_model = $params['model']; if (isset($params['queryset'])){ $choices = array('--------'=>''); foreach ($params['queryset'] as $item) { @@ -15,7 +15,7 @@ class IPF_Form_Field_ModelChoice extends IPF_Form_Field_Choice{ $this->setChoices($choices); } } - + public function clean($value){ parent::clean($value); if (in_array($value, $this->empty_values)) { @@ -24,7 +24,7 @@ class IPF_Form_Field_ModelChoice extends IPF_Form_Field_Choice{ //print_r($this->model); //print $value; //$this->model->get($value); - $o = $this->model->getTable()->find($value); + $o = $this->_model->getTable()->find($value); return $o; } } diff --git a/ipf/form/field/modelmultiplechoice.php b/ipf/form/field/modelmultiplechoice.php new file mode 100644 index 0000000..644ac1d --- /dev/null +++ b/ipf/form/field/modelmultiplechoice.php @@ -0,0 +1,12 @@ +_model = $params['model']; + } +} + diff --git a/ipf/form/field/multiplechoice.php b/ipf/form/field/multiplechoice.php new file mode 100644 index 0000000..b6da5b8 --- /dev/null +++ b/ipf/form/field/multiplechoice.php @@ -0,0 +1,32 @@ +_choices as $name=>$val){ + if ($v==$val){ + $find = true; + break; + } + } + if (!$find) + return false; + } + return true; + } + + public function clean($value){ + parent::clean($value); + if (in_array($value, $this->empty_values)) { + return ''; + } + if (!$this->validValue($value)) + throw new IPF_Exception_Form(__('Invalid choice')); + return $value; + } + +} + diff --git a/ipf/form/model.php b/ipf/form/model.php index 40d5164..994d4d2 100644 --- a/ipf/form/model.php +++ b/ipf/form/model.php @@ -94,6 +94,14 @@ class IPF_Form_Model extends IPF_Form $defaults = array('blank' => true, 'verbose' => $name, 'help_text' => '', 'editable' => true, 'model'=>$relation->getClass()); $form_field = $db_field->formField($defaults); $this->fields[$name] = $form_field; + return; + } + if ($relation->getType()==IPF_ORM_Relation::MANY_AGGREGATE){ + $db_field = new IPF_Form_DB_ManyToMany('',$name); + $defaults = array('blank' => true, 'verbose' => $name, 'help_text' => '', 'editable' => true, 'model'=>$relation->getClass()); + $form_field = $db_field->formField($defaults); + $this->fields[$name] = $form_field; + return; } } @@ -105,6 +113,17 @@ class IPF_Form_Model extends IPF_Form $this->model->SetFromFormData($this->cleaned_data); try{ $this->model->save(); + $rels = $this->model->getTable()->getRelations(); + + foreach($rels as $rname=>$rel){ + //print "$rname
"; + if (isset($this->cleaned_data[$rname])){ + //print $rel->getAlias(); + $this->model->unlink($rel->getAlias()); + if (is_array($this->cleaned_data[$rname])) + $this->model->link($rel->getAlias(),$this->cleaned_data[$rname]); + } + } return $this->model; } catch(IPF_ORM_Exception_Validator $e) { $erecords = $e->getInvalidRecords(); diff --git a/ipf/form/widget/selectmultipleinput.php b/ipf/form/widget/selectmultipleinput.php index e3526e5..92d9bf2 100644 --- a/ipf/form/widget/selectmultipleinput.php +++ b/ipf/form/widget/selectmultipleinput.php @@ -11,23 +11,24 @@ class IPF_Form_Widget_SelectMultipleInput extends IPF_Form_Widget parent::__construct($attrs); } - public function render($name, $value, $extra_attrs=array(), + public function render($name, $value, $extra_attrs=array(), $choices=array()) { $output = array(); if ($value === null) { $value = array(); } - $final_attrs = $this->buildAttrs(array('name' => $name.'[]'), + $final_attrs = $this->buildAttrs(array('name' => $name.'[]'), $extra_attrs); $output[] = '