From 31a5808240292a986793886c0a76159dca440528 Mon Sep 17 00:00:00 2001 From: Andrey Kutejko Date: Sun, 7 Sep 2014 23:45:08 +0300 Subject: [PATCH] replace inline models with set field and set table widget --- ipf/admin/legacymodel.php | 110 ++++++++++-- ipf/admin/model.php | 36 +--- ipf/admin/modelinline.php | 240 +++++--------------------- ipf/admin/static/admin/css/forms.css | 5 + ipf/admin/templates/admin/change.html | 37 ---- 5 files changed, 150 insertions(+), 278 deletions(-) diff --git a/ipf/admin/legacymodel.php b/ipf/admin/legacymodel.php index d8baa17..5b50270 100644 --- a/ipf/admin/legacymodel.php +++ b/ipf/admin/legacymodel.php @@ -191,18 +191,14 @@ class IPF_Admin_Model extends IPF_Admin_Component { $extra = array( 'user_fields' => $this->fields(), + 'inlines' => $this->inlines(), ); + return new IPF_Admin_ModelForm($data, $model, $this->modelName, $extra); + } - if ($model) { - // edit - $extra['model'] = $model; - $extra['initial'] = $this->getFormData($model); - } else { - // add - $extra['model'] = new $this->modelName; - } - - return new IPF_Form_Model($data, $extra); + public function inlines() + { + return array(); } public function saveObject($form, $model) @@ -221,8 +217,49 @@ class IPF_Admin_Model extends IPF_Admin_Component { return null; } +} + +class IPF_Admin_ModelForm extends IPF_Form_Model +{ + private $inlines = array(); - public function getFormData($o) + function __construct($data=null, $model=null, $modelName='', $extra=array()) + { + if ($model) { + // edit + $extra['model'] = $model; + $extra['initial'] = $this->getFormData($model); + } else { + // add + $extra['model'] = new $modelName; + } + + parent::__construct($data, $extra); + } + + function initFields($extra=array()) + { + parent::initFields($extra); + + if ($extra['inlines']) { + $this->field_groups[] = array('fields' => array_keys($this->fields)); + foreach ($extra['inlines'] as $inlineClassName) { + $this->inlines[] = new $inlineClassName($extra['model']); + } + } + + foreach ($this->inlines as $inline) { + $name = $inline->getModelName(); + $this->fields[$name] = $inline->createField(); + + $this->field_groups[] = array( + 'label' => $inline->getLegend(), + 'fields' => array($name), + ); + } + } + + private function getFormData($o) { $data = $o->getData(); foreach ($o->getTable()->getRelations() as $rname => $rel) { @@ -236,8 +273,59 @@ class IPF_Admin_Model extends IPF_Admin_Component } } } + + foreach ($this->inlines() as $inlineName => $inlineClassName) { + $inlineInstance = new $inlineClassName($o, null); + + $objs = array(); + foreach ($inlineInstance->getObjects() as $io) { + $d = $io->getData(); + $d['id'] = $io->pk(); + $objs[] = $d; + } + $data[$inlineName] = $objs; + } + return $data; } + + function save($commit=true) + { + $model = parent::save($commit); + + foreach ($this->inlines as $inline) { + $this->saveInlineObject($inline, $model); + } + + return $model; + } + + private function saveInlineObject($inline, $model) + { + $objIndex = array(); + foreach ($inline->getObjects() as $obj) + $objIndex[$obj->pk()] = $obj; + + $modelName = $inline->getModelName(); + $fk_local = $inline->getFkLocal(); + + foreach ($this->cleaned_data[$modelName] as $objData) { + if (array_key_exists('id', $objData) && array_key_exists($objData['id'], $objIndex)) { + $obj = $objIndex[$objData['id']]; + if (isset($objData['is_remove'])) { + $obj->delete(); + } else { + $obj->synchronizeWithArray($objData); + $obj->save(); + } + } else { + $objData[$fk_local] = $model->id; + $obj = new $modelName; + $obj->synchronizeWithArray($objData); + $obj->save(); + } + } + } } abstract class IPF_Admin_Model_Filter implements IPF_Admin_ListFilter diff --git a/ipf/admin/model.php b/ipf/admin/model.php index 778f0f4..2ada07f 100644 --- a/ipf/admin/model.php +++ b/ipf/admin/model.php @@ -9,9 +9,7 @@ interface IPF_Admin_ListFilter abstract class IPF_Admin_Component { - var $inlineInstances = array(); - var $perPage = 50; - + public $perPage = 50; public $app = null, $request = null; public function slug() @@ -61,23 +59,6 @@ abstract class IPF_Admin_Component return IPF_Admin_App::RenderToResponse($template, $context, $request); } - protected function setInlines($model, $data=null) - { - $il = $this->inlines(); - if (is_array($il)) { - foreach($il as $inlineName => $inlineClassName) { - $this->inlineInstances[] = new $inlineClassName($model, $data); - } - } - } - - protected function saveInlines($obj) - { - foreach($this->inlineInstances as $inlineInstance) { - $inlineInstance->save($obj); - } - } - protected function _setupEditForm($form) { $this->_setupForm($form); @@ -92,19 +73,6 @@ abstract class IPF_Admin_Component { } - public function inlines() - { - return null; - } - - public function isValidInlines() - { - foreach ($this->inlineInstances as &$il) - if ($il->isValid() === false) - return false; - return true; - } - public abstract function list_display(); public function list_display_links() @@ -204,7 +172,6 @@ abstract class IPF_Admin_Component 'form_html' => $form->renderLayout(new IPF_Admin_Form_Layout), 'extra_js' => $extraMedia['js'], 'extra_css' => $extraMedia['css'], - 'inlineInstances'=>$this->inlineInstances, 'errors' => $errors, 'objecttools' => array(), ); @@ -279,7 +246,6 @@ abstract class IPF_Admin_Component 'form_html' => $form->renderLayout(new IPF_Admin_Form_Layout), 'extra_js' => $extraMedia['js'], 'extra_css' => $extraMedia['css'], - 'inlineInstances'=>$this->inlineInstances, 'errors' => $errors, 'objecttools' => $objecttools, ); diff --git a/ipf/admin/modelinline.php b/ipf/admin/modelinline.php index 0baf64d..bb5e4dd 100644 --- a/ipf/admin/modelinline.php +++ b/ipf/admin/modelinline.php @@ -2,19 +2,12 @@ abstract class IPF_Admin_ModelInline { - var $model = null; - var $parentModel = null; - var $formset = null; + public $parentModel = null; + public $orderby = 'id'; - var $orderby = 'id'; - - function __construct($parentModel, $data=null) + function __construct($parentModel) { $this->parentModel = $parentModel; - - $modelName = $this->getModelName(); - $this->model = new $modelName(); - $this->createFormSet($data); } abstract function getModelName(); @@ -35,65 +28,12 @@ abstract class IPF_Admin_ModelInline function getLegend() { - return get_class($this->model); - } - - public function listColumns() - { - if (!$this->formset || !count($this->formset)) - return array(); - - $header = array(); - foreach ($this->formset[0]->fields as $fieldname => $field) { - $header[] = array( - 'fieldname' => $fieldname, - 'label' => $field->label, - 'is_hidden' => $field->widget->is_hidden, - 'is_del' => (property_exists($field, 'is_del') && $field->is_del), - 'has_display_method' => method_exists($this, 'column_'.$fieldname), - ); - } - return $header; - } - - public function displayField($fieldname, $obj) - { - $method = 'column_'.$fieldname; - if (!method_exists($this, $method)) - throw new IPF_Exception('No method '.$method.' defined.'); - return $this->$method($obj); - } - - function isValid() - { - foreach ($this->formset as $form) { - if (!$form->isValid()) { - $empty = true; - foreach ($form->data as $k => $v) { - if (is_array($v) && \PFF\Arr::get($v, 'error') === 4) { - // empty file - } elseif ($k !== $form->prefix.'is_remove' && $v) { - $empty = false; - break; - } - } - if (!$form->isAdd || !$empty) { - return false; - } - } - } - return true; - } - - protected function _getForm($model, $data, $extra) - { - $extra['model'] = $model; - return new IPF_Form_Model($data, $extra); + return $this->getModelName(); } function getFkName() { - foreach($this->model->getTable()->getRelations() as $rel) { + foreach($this->getTable()->getRelations() as $rel) { if ($rel->getClass()==get_class($this->parentModel)) return $rel->getAlias(); } @@ -102,159 +42,69 @@ abstract class IPF_Admin_ModelInline function getFkLocal() { - foreach($this->model->getTable()->getRelations() as $rel) { + foreach($this->getTable()->getRelations() as $rel) { if ($rel->getClass() == get_class($this->parentModel)) return $rel->getLocal(); } throw new IPF_Exception(__('Cannot get fkLocal for '.$this->getModelName())); } - function createFormSet($data) + function getObjects() { - $this->formset = array(); + if (!$this->parentModel->exists()) + return array(); - $o = $this->_orderableColumn(); + $query = IPF_ORM_Query::create() + ->from($this->getModelName()) + ->where($this->getFkLocal().'='.$this->parentModel->id); - $form_extra = array( - 'exclude' => array( - $this->getFkName(), - $this->getFkLocal(), - ), - ); + $o = $this->_orderableColumn(); if ($o) - $form_extra['exclude'][] = $o; - - if ($this->parentModel->exists()) { - $query = IPF_ORM_Query::create() - ->from(get_class($this->model)) - ->where($this->getFkLocal().'='.$this->parentModel->id); - - if ($o) - $objects = $query->orderby($o)->execute(); - else - $objects = $query->orderby($this->orderby)->execute(); - - foreach ($objects as $obj) { - $prefix = 'edit_'.get_class($this->model).'_'.$obj->id.'_'; - $d = $this->extractFormData($obj, $data, $prefix); - - $form = $this->_getForm($obj, $d, $form_extra); - - $form->prefix = $prefix; - - $del = new IPF_Form_Field_Boolean(array( - 'label' => __('Del'), - 'name' => 'is_remove', - )); - $del->is_del = true; - $form->fields = array_merge(array('is_remove' => $del), $form->fields); - - $form->isAdd = false; - $this->formset[] = $form; - } - } - - $n_addnum = $this->getAddNum(); - for ($i = 0; $i < $n_addnum; $i++) { - $prefix = 'add_'.get_class($this->model).'_'.$i.'_'; - $d = $data !== null ? $this->extractFormData(null, $data, $prefix) : null; - - $form = $this->_getForm($this->model->copy(), $d, $form_extra); - $form->prefix = 'add_'.get_class($this->model).'_'.$i.'_'; - - $del = new IPF_Form_Field_Boolean(array( - 'label' => __('Del'), - 'name' => 'is_remove', - 'widget_attrs' => array('disabled'=>'disabled'), - )); - $del->is_del = true; - - $form->fields = array_merge(array('is_remove' => $del), $form->fields); + $query->orderby($o); + else + $query->orderby($this->orderby); - $form->isAdd = true; - $this->formset[] = $form; - } + return $query->execute(); } - private function extractFormData($obj, $data, $prefix) + public function _orderable() { - $d = array(); - if ($data === null) { - foreach ($obj->getData() as $k => $v) { - $d[$prefix.$k] = $v; - } - } else { - foreach ($data as $k => $v) { - if (strpos($k, $prefix) === 0) - $d[$k] = $v; - } - } - return $d; + return $this->_orderableColumn() !== null; } - function save($parent_obj) + public function _orderableColumn() { - if (!$this->isValid()) - throw new IPF_Exception_Form(__('Cannot save models from an invalid formset.')); - - if ($this->parentModel->exists()) { - $objects = IPF_ORM_Query::create() - ->from(get_class($this->model)) - ->orderby('id') - ->where($this->getFkLocal().'='.$this->parentModel->id) - ->execute(); - foreach ($objects as $obj) { - foreach ($this->formset as $form) { - if ($form->isAdd) - continue; - - @list($x1,$x2,$id,$x3) = @explode('_',$form->prefix); - if ($id == $obj->id) { - if ($form->cleaned_data['is_remove']==true) { - $obj->delete(); - } else { - unset($form->cleaned_data[0]); - foreach($form->fields as $fname=>$f) { - if (is_a($f,'IPF_Form_Field_File')) { - if($form->cleaned_data[$fname]===null) - continue; - if($form->cleaned_data[$fname]=='') - unset($form->cleaned_data[$fname]); - } - - } - $obj->synchronizeWithArray($form->cleaned_data); - $obj->save(); - } - break; - } - } - } - } - - $fk_local = $this->getFkLocal(); - foreach ($this->formset as $form) { - if ($form->isAdd) { - if ($form->isValid()) { - unset($form->cleaned_data[0]); - $form->cleaned_data[$fk_local] = $parent_obj->id; - $form->save(); - } - } - } + if ($this->getTable()->hasTemplate('IPF_ORM_Template_Orderable')) + return $this->getTable()->getTemplate('IPF_ORM_Template_Orderable')->getColumnName(); + else + return null; } - public function _orderable() + private function getTable() { - return $this->_orderableColumn() !== null; + return IPF_ORM::getTable($this->getModelName()); } - public function _orderableColumn() + public function createField() { - if ($this->model->getTable()->hasTemplate('IPF_ORM_Template_Orderable')) - return $this->model->getTable()->getTemplate('IPF_ORM_Template_Orderable')->getColumnName(); - else - return null; + $exclude = array( + $this->getFkName(), + $this->getFkLocal(), + ); + $o = $this->_orderableColumn(); + if ($o) + $exclude[] = $o; + + $fields = array(); + foreach (IPF_Form_Model::suggestFields($this->getTable(), null, $exclude, null) as $field) { + list($n, $f) = $field; + $fields[$n] = $f; + } + + return new IPF_Form_Field_Set(array( + 'fields' => $fields, + 'addCount' => $this->getAddNum(), + )); } } diff --git a/ipf/admin/static/admin/css/forms.css b/ipf/admin/static/admin/css/forms.css index 934da57..ed59a42 100644 --- a/ipf/admin/static/admin/css/forms.css +++ b/ipf/admin/static/admin/css/forms.css @@ -168,6 +168,11 @@ fieldset.monospace textarea { font-family:"Bitstream Vera Sans Mono",Monaco,"Cou /* INLINE */ .inline-related table {width: 100%;} +/* SET WIDGET */ +.set-widget { border-collapse: collapse; width: 100%; } +.set-widget th { background:#eee url(../img/nav-bg.gif) bottom left repeat-x; color:#666; } + + /* INLINE REORDER */ .ItemsDragClass{background-color:#E3F3FE;} diff --git a/ipf/admin/templates/admin/change.html b/ipf/admin/templates/admin/change.html index 05938cf..6cb00a0 100644 --- a/ipf/admin/templates/admin/change.html +++ b/ipf/admin/templates/admin/change.html @@ -40,43 +40,6 @@ {$form_html|safe} {/block} - {if $inlineInstances} - {foreach $inlineInstances as $inline} -
- -
- {/foreach} - {/if}
{if ($mode=='change') && $component->isAccessible(array('delete'))}

{trans 'Delete'}

{/if} {if ($mode=='change') && $component->isAccessible(array('change'))}{/if} -- 2.49.0