]> git.andy128k.dev Git - ipf-legacy-orm.git/commitdiff
move legacy admin parts to legacy app
authorAndrey Kutejko <andy128k@gmail.com>
Sun, 7 Sep 2014 20:46:32 +0000 (23:46 +0300)
committerAndrey Kutejko <andy128k@gmail.com>
Sun, 7 Sep 2014 20:46:32 +0000 (23:46 +0300)
ipf/legacy_orm/adminmodel.php [new file with mode: 0644]
ipf/legacy_orm/adminmodelinline.php [new file with mode: 0644]

diff --git a/ipf/legacy_orm/adminmodel.php b/ipf/legacy_orm/adminmodel.php
new file mode 100644 (file)
index 0000000..5b50270
--- /dev/null
@@ -0,0 +1,610 @@
+<?php
+
+use \PFF\HtmlBuilder\Text as Text;
+use \PFF\HtmlBuilder\Tag as Tag;
+
+class IPF_Admin_Model extends IPF_Admin_Component
+{
+    public $modelName;
+
+    public function __construct($modelName)
+    {
+        $this->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
+                    ? '<span class="positive">&#x2714;</span>'
+                    : '<span class="negative">&#x2718;</span>';
+            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 (file)
index 0000000..bb5e4dd
--- /dev/null
@@ -0,0 +1,110 @@
+<?php
+
+abstract class IPF_Admin_ModelInline
+{
+    public $parentModel = null;
+    public $orderby = 'id';
+
+    function __construct($parentModel)
+    {
+        $this->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(),
+        ));
+    }
+}
+