From 0be3b1bae21bb52c4aa0aab614a59fec72b9fbc4 Mon Sep 17 00:00:00 2001 From: Andrey Kutejko Date: Sun, 7 Sep 2014 23:46:32 +0300 Subject: [PATCH] move legacy admin parts to legacy app --- ipf/legacy_orm/adminmodel.php | 610 ++++++++++++++++++++++++++++ ipf/legacy_orm/adminmodelinline.php | 110 +++++ 2 files changed, 720 insertions(+) create mode 100644 ipf/legacy_orm/adminmodel.php create mode 100644 ipf/legacy_orm/adminmodelinline.php diff --git a/ipf/legacy_orm/adminmodel.php b/ipf/legacy_orm/adminmodel.php new file mode 100644 index 0000000..5b50270 --- /dev/null +++ b/ipf/legacy_orm/adminmodel.php @@ -0,0 +1,610 @@ +modelName = $modelName; + } + + public function verbose_name() + { + return IPF_Utils::humanTitle($this->modelName); + } + + public function slug() + { + return strtolower($this->modelName); + } + + private function table() + { + return IPF_ORM::getTable($this->modelName); + } + + protected function query($searchValue, $filters) + { + if (method_exists($this->modelName, 'ordering')) { + $m = new $this->modelName; + $ord = $m->ordering(); + } elseif ($this->table()->getOrdering()) { + $ord = implode(', ', $this->table()->getOrdering()); + } elseif ($this->table()->hasTemplate('IPF_ORM_Template_Orderable')) { + $ord = $this->table()->getTemplate('IPF_ORM_Template_Orderable')->getColumnName(); + } else { + $ord = '1 desc'; + } + + $q = IPF_ORM_Query::create()->from($this->modelName)->orderby($ord); + + if ($searchValue) { + $wh = array(); + $whv = array(); + foreach ($this->_searchFields() as $f) { + $wh[] = $f.' like ?'; + $whv[] = '%'.$searchValue.'%'; + } + $q->addWhere($wh, $whv); + } + + foreach ($filters as $f) + $f->applyToQuery($q); + + return $q; + } + + protected function getItems($searchValue, $filters, $page, $pageSize) + { + $idColumn = $this->table()->getIdentifier(); + + $result = array(); + foreach ($this->query($searchValue, $filters)->limit($pageSize)->offset(($page - 1) * $pageSize)->execute() as $o) { + $id = $o->__get($idColumn); + $result[$id] = $o; + } + return $result; + } + + protected function itemsCount($searchValue, $filters) + { + return $this->query($searchValue, $filters)->count(); + } + + public function getObjectByID($id) + { + return $this->table()->find($id); + } + + public function searcheable() + { + return count($this->_searchFields()) > 0; + } + + protected function _searchFields() + { + return array(); + } + + public function list_display() + { + return $this->table()->getColumnNames(); + } + + public function renderCell($object, $column) + { + $value = $object->$column; + switch ($object->getTable()->getTypeOf($column)) { + case 'boolean': + return $value + ? '' + : ''; + case 'timestamp': + return Text::escape(IPF_Utils::formatDate($value)); + default: + return Text::escape($value); + } + } + + protected function columnTitle($column) + { + $columns = $this->table()->getColumns(); + if (array_key_exists($column, $columns) && array_key_exists('verbose', $columns[$column])) + return $columns[$column]['verbose']; + else + return parent::columnTitle($column); + } + + public function _orderable() + { + return $this->_orderableColumn() !== null; + } + + public function _orderableColumn() + { + if (method_exists($this, 'list_order')) + return $this->list_order(); + elseif ($this->table()->hasTemplate('IPF_ORM_Template_Orderable')) + return $this->table()->getTemplate('IPF_ORM_Template_Orderable')->getColumnName(); + else + return null; + } + + /* filters */ + + protected function _listFilters() + { + return array(); + } + + public function listFilters() + { + $filters = array(); + foreach ($this->_listFilters() as $f) { + if (is_string($f)) + $f = new IPF_Admin_Model_RelationFilter($this->modelName, $f); + + $filters[] = $f; + } + return $filters; + } + + public function reorder($ids) + { + if (!$this->_orderable()) + return false; + + $ord_field = $this->_orderableColumn(); + + $table = IPF_ORM::getTable($this->modelName); + $conn = $table->getConnection(); + + $idColumn = $table->getIdentifier(); + if (is_array($idColumn)) + $idColumn = $idColumn[0]; + + $questions = str_repeat('?,', count($ids)-1) . '?'; + $query = 'SELECT ' . $conn->quoteIdentifier($ord_field) . + ' FROM ' . $conn->quoteIdentifier($table->getTableName()) . + ' WHERE ' . $conn->quoteIdentifier($idColumn) . ' IN (' . $questions . ')' . + ' ORDER BY ' . $conn->quoteIdentifier($ord_field); + $ords = $conn->fetchColumn($query, $ids); + + $i = 0; + foreach ($ids as $id) { + $item = $table->find($id); + $item[$ord_field] = $ords[$i]; + $item->save(); + $i++; + } + + return true; + } + + /* edit */ + + protected function _getForm($model, $data) + { + $extra = array( + 'user_fields' => $this->fields(), + 'inlines' => $this->inlines(), + ); + return new IPF_Admin_ModelForm($data, $model, $this->modelName, $extra); + } + + public function inlines() + { + return array(); + } + + public function saveObject($form, $model) + { + $model = $form->save(); + $idColumn = $this->table()->getIdentifier(); + return array($model->$idColumn, $model); + } + + public function deleteObject($model) + { + $model->delete(); + } + + public function fields() + { + return null; + } +} + +class IPF_Admin_ModelForm extends IPF_Form_Model +{ + private $inlines = array(); + + 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) { + $fields = $this->fields(); + if (!$fields || in_array($rname, $fields)) { + if ($rel->getType() == IPF_ORM_Relation::MANY_AGGREGATE) { + $data[$rname] = array(); + foreach ($rel->fetchRelatedFor($o) as $ri) { + $data[$rname][] = $ri->pk(); + } + } + } + } + + 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 +{ + abstract function applyToQuery($q); + + protected $title, $paramName; + + function title() + { + return $this->title; + } + + protected function link($params, $value, $title) + { + if ($value !== null) + $params[$this->paramName] = $value; + else + unset($params[$this->paramName]); + + return Tag::a() + ->attr('href', '?'.IPF_HTTP_URL::generateParams($params, false)) + ->append($title); + } +} + +class IPF_Admin_Model_RelationFilter extends IPF_Admin_Model_Filter +{ + private $relation, $selected = null; + + function __construct($modelName, $relName) + { + $this->relation = IPF_ORM::getTable($modelName)->getRelation($relName); + $this->title = 'By '.IPF_Utils::humanTitle($relName); + + $this->paramName = 'filter_'.$this->relation['local']; + } + + function setParams($params) + { + $this->selected = \PFF\Arr::get($params, $this->paramName); + } + + function applyToQuery($q) + { + // check ??? + if ($this->selected) + $q->addWhere($this->relation['local'].' = ?', array($this->selected)); + } + + function render($extraParams) + { + $ul = Tag::ul(); + + // reset filter + $ul->append(Tag::li() + ->toggleClass('selected', !$this->selected) + ->append($this->link($extraParams, null, __('All')))); + + // query related + $table = IPF_ORM::getTable($this->relation['class']); + + $query = $table->createQuery(); + if ($table->getOrdering()) { + $query->orderBy(implode(', ', $table->getOrdering())); + } elseif ($table->hasTemplate('IPF_ORM_Template_Orderable')) { + $query->orderBy($table->getTemplate('IPF_ORM_Template_Orderable')->getColumnName()); + } + + $foreign = $this->relation['foreign']; + foreach ($query->execute() as $val) { + $id = $val[$foreign]; + $name = (string)$val; + + $ul->append(Tag::li() + ->toggleClass('selected', $this->selected == $id) + ->append($this->link($extraParams, $id, $name))); + } + + return $ul->html(); + } +} + +class IPF_Admin_Model_OwnedFilter extends IPF_Admin_Model_Filter +{ + private $column, $selected = null; + + function __construct($modelName, $column, $title) + { + $this->column = $column; + $this->title = $title; + $this->paramName = 'filter_'.$this->column; + } + + function setParams($params) + { + $this->selected = \PFF\Arr::get($params, $this->paramName); + } + + function applyToQuery($q) + { + // check ??? + if ($this->selected) + $q->addWhere($this->column.' = ?', array($this->selected)); + } + + function render($extraParams) + { + $ul = Tag::ul(); + + // reset filter + $ul->append(Tag::li() + ->toggleClass('selected', !$this->selected) + ->append($this->link($extraParams, null, __('All')))); + + foreach (User::query()->fetchAll() as $val) { + $id = $val->id; + $name = (string)$val; + + $ul->append(Tag::li() + ->toggleClass('selected', $this->selected == $id) + ->append($this->link($extraParams, $id, $name))); + } + + return $ul->html(); + } +} + +class BooleanFilter extends IPF_Admin_Model_Filter +{ + private $column, $trueTitle, $falseTitle, $selected; + + public function __construct($column, $title, $trueTitle='Yes', $falseTitle='No') + { + $this->column = $column; + $this->title = $title; + $this->trueTitle = $trueTitle; + $this->falseTitle = $falseTitle; + + $this->paramName = 'filter_'.$column; + } + + function setParams($params) + { + $this->selected = \PFF\Arr::get($params, $this->paramName); + } + + function render($extraParams) + { + return Tag::ul(null, + Tag::li() + ->toggleClass('selected', $this->selected !== 'y' && $this->selected !== 'n') + ->append($this->link($extraParams, null, __('All'))), + Tag::li() + ->toggleClass('selected', $this->selected === 'y') + ->append($this->link($extraParams, 'y', $this->trueTitle)), + Tag::li() + ->toggleClass('selected', $this->selected === 'n') + ->append($this->link($extraParams, 'n', $this->falseTitle))); + } + + function applyToQuery($q) + { + switch ($this->selected) { + case 'y': + $query->addWhere($this->column); + break; + case 'n': + $query->addWhere('NOT '.$this->column); + break; + } + } +} + +class DateHierarchyListFilter extends IPF_Admin_Model_Filter +{ + private $model, $name; + private $day, $month, $year; + + function __construct($title, $modelName, $fieldName) + { + $this->title = $title; + $this->modelName = $modelName; + $this->name = $fieldName; + + $this->paramName = $fieldName; + } + + function setParams($params) + { + $date = \PFF\Arr::get($params, $this->paramName, ''); + $matches = array(); + if (preg_match('/(\d{4})-(\d{2})-(\d{2})/', $date, $matches)) { + $this->year = intval($matches[1]); + $this->month = intval($matches[2]); + $this->day = intval($matches[3]); + } + } + + function render($extraParams) + { + $ul = Tag::ul(); + + $ul->append(Tag::li() + ->toggleClass('selected', !$this->year) + ->append($this->link($extraParams, null, __('All')))); + + if ($this->year) + $ul->append($this->renderChoice($extraParams, $this->year, 0, 0, $this->year)->addClass('selected')); + + if ($this->month) + $ul->append($this->renderChoice($extraParams, $this->year, $this->month, 0, $this->monthName($this->month))->addClass('selected')); + + if ($this->day) + $ul->append($this->renderChoice($extraParams, $this->year, $this->month, $this->day, $this->day)->addClass('selected')); + + if ($this->day) { + } elseif ($this->month) { + $days = $this->choices('DAY(' . $this->name . ')', + 'YEAR(' . $this->name . ')', $this->year, + 'MONTH(' . $this->name . ')', $this->month); + foreach ($days as $day) { + $ul->append($this->renderChoice($extraParams, $this->year, $this->month, $day, $day)); + } + } elseif ($this->year) { + $months = $this->choices('MONTH(' . $this->name . ')', + 'YEAR(' . $this->name . ')', $this->year); + foreach ($months as $month) { + $ul->append($this->renderChoice($extraParams, $this->year, $month, 0, $this->monthName($month))); + } + } else { + $years = $this->choices('YEAR(' . $this->name . ')'); + foreach ($years as $year) { + $ul->append($this->renderChoice($extraParams, $year, 0, 0, $year)); + } + } + + return $ul->html(); + } + + function applyToQuery($q) + { + if ($this->day) + $q->addWhere('DAY(' . $this->name . ') = ?', array($this->day)); + if ($this->month) + $q->addWhere('MONTH(' . $this->name . ') = ?', array($this->month)); + if ($this->year) + $q->addWhere('YEAR(' . $this->name . ') = ?', array($this->year)); + } + + private function choices(/* $what, [$expr, $value, ...]*/) + { + $args = func_get_args(); + $what = array_shift($args); + + $q = IPF_ORM_Query::create() + ->from($this->modelName) + ->select($what . ' AS value') + ->groupBy('1') + ->orderBy('1'); + + while ($args) { + $expr = array_shift($args); + $value = array_shift($args); + + $q->addWhere($expr . ' = ?', array($value)); + } + return \PFF\Arr::create($q->fetchArray())->pluck('value')->arr(); + } + + private function renderChoice($extraParams, $year, $month, $day, $label) + { + return Tag::li(null, + $this->link($extraParams, sprintf('%04d-%02d-%02d', $year, $month, $day), $label)); + } + + protected function monthName($month) + { + return date('F', mktime(0, 0, 0, $month, 1)); + } +} + diff --git a/ipf/legacy_orm/adminmodelinline.php b/ipf/legacy_orm/adminmodelinline.php new file mode 100644 index 0000000..bb5e4dd --- /dev/null +++ b/ipf/legacy_orm/adminmodelinline.php @@ -0,0 +1,110 @@ +parentModel = $parentModel; + } + + abstract function getModelName(); + + public function getApplication() + { + foreach (IPF_Project::getInstance()->appList() as $app) + foreach (IPF_Legacy_ORM_App::appModelList($app) as $model) + if ($model == $this->getModelName()) + return $app; + return null; + } + + function getAddNum() + { + return 4; + } + + function getLegend() + { + return $this->getModelName(); + } + + function getFkName() + { + foreach($this->getTable()->getRelations() as $rel) { + if ($rel->getClass()==get_class($this->parentModel)) + return $rel->getAlias(); + } + throw new IPF_Exception(__('Cannot get fkName for '.$this->getModelName())); + } + + function getFkLocal() + { + 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 getObjects() + { + if (!$this->parentModel->exists()) + return array(); + + $query = IPF_ORM_Query::create() + ->from($this->getModelName()) + ->where($this->getFkLocal().'='.$this->parentModel->id); + + $o = $this->_orderableColumn(); + if ($o) + $query->orderby($o); + else + $query->orderby($this->orderby); + + return $query->execute(); + } + + public function _orderable() + { + return $this->_orderableColumn() !== null; + } + + public function _orderableColumn() + { + if ($this->getTable()->hasTemplate('IPF_ORM_Template_Orderable')) + return $this->getTable()->getTemplate('IPF_ORM_Template_Orderable')->getColumnName(); + else + return null; + } + + private function getTable() + { + return IPF_ORM::getTable($this->getModelName()); + } + + public function createField() + { + $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(), + )); + } +} + -- 2.49.0