NodeController.php 10.3 KB
<?php
/**
 * @property string[] $pathIds
 * @property Node[] $pathNodes
 * @property Node $currentNode
 */
class NodeController extends AdminController
{
    public $layout = 'node';

    private $_pathIds = null;
    private $_pathNodes = null;
    private $_currentNode = null;


    public function getCurrentNodeId()
    {
        return isset($_GET['nodeId']) ? $_GET['nodeId'] : null;
    }

    public function getPathIds()
    {
        if ($this->_pathIds === null) {
            $path = $this->currentNode->getPathIds();
            $this->_pathIds = $path;
        }
        return $this->_pathIds;
    }

    public function getPathNodes()
    {
        if ($this->_pathNodes === null) {
            $this->_pathNodes = $this->currentNode->getPath();
        }
        return $this->_pathNodes;
    }



    /**
     * @param string|null $name
     * @return string[]
     */
    public function getNestedNodeTypes($name = null)
    {
        $res = array();
        if ($name === null) {
            foreach (NodeTypeHelper::getNodeTypes() as $typeName => $type)
                if ($type->isRootNode()) {
                    $res[$typeName] = $type->getName();
                }
        } else {
            foreach (NodeTypeHelper::getNodeType($name)->getNestedTypes() as $typeName) {
                $res[$typeName] = NodeTypeHelper::getNodeType($typeName)->getName();
            }
        }
        return $res;
    }

    public function createAction($actionID)
    {
        if ($actionID == 'type') {
            $typeActionName = $_GET['action'];
            $typeName = $this->getCurrentNode()->data_type;
            $type = NodeTypeHelper::getNodeType($typeName);
            $action = $type->createAction($typeActionName, $this, $actionID);
            $action->node = $this->currentNode;
            $action->nodeType = $this->getCurrentType();
            return $action;
        } else
            return parent::createAction($actionID);
    }


    private function nodeTree($rootNode)
    {
        $tree = array();
        foreach ($rootNode->nodes as $childNode) {
            $url = array('type', 'action' => NodeTypeHelper::getNodeType($childNode->data_type)->getDefaultAction(), 'nodeId' => $childNode->id);
            $item = array(
                'text' => CHtml::link($childNode->i18n->label, $url),
            );
            $children = $this->nodeTree($childNode);
            if (count($children) > 0) $item['children'] = $children;
            $tree[] = $item;
        }
        if (count(NodeTypeHelper::getNodeType($rootNode->data_type)->getNestedTypes()))
            $tree[] = array(
                'text' => CHtml::link('<i class="icon-plus"></i>' . 'Добавить',
                    $this->createUrl('create', array('nodeId' => $rootNode->id)))
            );
        if(count($tree)>2){
            $tree[] = array(
                'text' => CHtml::link('<i class="icon-resize-vertical"></i>' . 'Упорядочить', $this->createUrl('order', array('nodeId' => $rootNode->id))),
            );
        }
        return $tree;
    }

    public function getSidebarTree()
    {
        $data = array();
        /** @var $rootNode Node */
        foreach (Node::model()->findAll('node_id is null') as $rootNode) {
            $url = array('type', 'action' => NodeTypeHelper::getNodeType($rootNode->data_type)->getDefaultAction(), 'nodeId' => $rootNode->id);
            $item = array(
                'text' => CHtml::link($rootNode->i18n->label, $url),
            );
            $children = $this->nodeTree($rootNode);
            if (count($children) > 0) $item['children'] = $children;
            $data[] = $item;
        }
        $data[] = array(
            'text' => CHtml::link('<i class="icon-plus"></i>' . 'Добавить', $this->createUrl('create')),
        );

        return $data;
    }


    public function  actionIndex()
    {
        $first = Node::model()->find('node_id is null');
        if ($first != null)
            $url = $this->createUrl('type', array('action' => NodeTypeHelper::getNodeType($first->data_type)->getDefaultAction(), 'nodeId' => $first->id));
        else
            $url = $this->createUrl('create');
        $this->redirect($url);
    }

    public function actionCreate()
    {
        $this->layout = 'tree';
        $model = new Node;
        if (isset($this->currentNode)) {
            $model->nodeTypes = $this->getNestedNodeTypes($this->currentNode->data_type);
            $model->node_id = $this->currentNode->id;
        } else
            $model->nodeTypes = $this->getNestedNodeTypes();
        /** @var $i18nModels NodeI18n[] */
        $i18nModels = array();
        foreach (Yii::app()->params['languages'] as $lang) {
            $i18nModel = new NodeI18n();
            $i18nModel->lang = $lang;
            $i18nModels[$lang] = $i18nModel;
        }

        if (isset($_POST['Node']) || isset($_POST['NodeI18n'])) {

            if (isset($_POST['Node']))
                $model->attributes = $_POST['Node'];
            $i18nValidation = true;
            if (isset($_POST['NodeI18n'])) {
                foreach ($_POST['NodeI18n'] as $lang => $post) {
                    $i18nModels[$lang]->attributes = $post;
                    $i18nValidation = $i18nValidation && $i18nModels[$lang]->validate();
                }
            }
            if ($model->validate() && $i18nValidation) {
                $model->i18ns = $i18nModels;
                $model->save(false);
                foreach ($i18nModels as $i18nModel) {
                    $i18nModel->id = $model->id;
                    $i18nModel->save();
                }
                $this->redirect(array('type', 'action' => NodeTypeHelper::getNodeType($model->data_type)->getDefaultAction(), 'nodeId' => $model->id));
            }

        }

        $this->render('create', array(
            'model' => $model,
            'i18nModels' => $i18nModels,
        ));
    }

    public function actionUpdate($nodeId)
    {
        /** @var $model Node */
        $model = Node::model()->findByPk($nodeId);
        /** @var $i18nModels NodeI18n[] */
        $i18nModels = array();
        foreach (Yii::app()->params['languages'] as $lang) {
            if (!isset($model->i18ns[$lang])) {
                $i18nModel = new NodeI18n();
                $i18nModel->id = $model->id;
                $i18nModel->lang = $lang;
                $i18nModels[$lang] = $i18nModel;
            } else {
                $i18nModels[$lang] = $model->i18ns[$lang];
            }
        }


        if (isset($_POST['Node']) || isset($_POST['NodeI18n'])) {
            if (isset($_POST['Node'])) $model->attributes = $_POST['Node'];
            $i18nValidation = $model->validate();
            if (isset($_POST['NodeI18n'])) {
                foreach ($_POST['NodeI18n'] as $lang => $post) {
                    $i18nModels[$lang]->attributes = $post;
                    $i18nValidation = $i18nModels[$lang]->validate() && $i18nValidation;
                }
            }
            if ($i18nValidation) {
                $model->i18ns = $i18nModels;
                $model->save(false);
                foreach ($i18nModels as $i18nModel) {
                    $i18nModel->save();
                }
                $this->refresh();
            }
        }

        $this->render('update', array(
            'model' => $model,
            'i18nModels' => $i18nModels,
        ));
    }

    public function actionOrder()
    {
        if (Yii::app()->request->isPostRequest && isset($_POST['Order'])) {
            if ($_POST['Order'] != 'none') {
                $models = explode(',', $_POST['Order']);
                for ($i = 0; $i < sizeof($models); $i++) {
                    if ($model = Node::model()->findByPk($models[$i])) {
                        $model->rank = $i;
                        $model->save();
                    }
                }
            }
            $url = array('type', 'action' => NodeTypeHelper::getNodeType($this->currentNode->data_type)->getDefaultAction(), 'nodeId' => $this->currentNode->id);
            $this->redirect($url);
        } else {
            $dataProvider = new CActiveDataProvider(
                'Node',
                array(
                    'pagination' => false,
                    'criteria' => array(
                        'order' => '`rank` ASC, id DESC',
                        'condition'=>"node_id = {$this->getCurrentNodeId()}",
                    ),
                ));
            $this->render(
                'order',
                array(
                    'dataProvider' => $dataProvider,
                ));
        }
    }


    /**
     * Deletes a particular model.
     * If deletion is successful, the browser will be redirected to the 'admin' page.
     * @param integer $id the ID of the model to be deleted
     */
    public function actionDelete()
    {
        if (Yii::app()->request->isPostRequest) {
            $this->currentNode->delete();
            $this->redirect('index');
        } else
            $this->render('delete');
    }

    /**
     * @return Node
     */
    public function getCurrentNode()
    {
        if ($this->_currentNode === null)
            $this->_currentNode = isset($_GET['nodeId']) ? Node::model()->with('i18n')->findByPk($_GET['nodeId']) : null;
        return $this->_currentNode;
    }

    public function getNodeMenu()
    {
        $menu = array(
            array(
                'label' => 'Параметры страницы',
                'url' => array('update', 'nodeId' => $this->currentNode->id),
                'active' => $this->action->id == 'update',
            ),
        );
        $currentAction = isset($_GET['action']) ? $_GET['action'] : null;
        foreach ($this->currentType->actionLabels() as $action => $label) {
            $menu[] = array(
                'label' => $label,
                'url' => array('type', 'action' => $action, 'nodeId' => $this->currentNode->id),
                'active' => $currentAction == $action,
            );
        }
        $menu[] = array(
            'label' => 'Удалить',
            'url' => array('delete', 'nodeId' => $this->currentNode->id),
            'active' => $this->action->id == 'delete',
        );
        return $menu;
    }

    /**
     * @return INodeType
     */
    public function getCurrentType()
    {
        return NodeTypeHelper::getNodeType($this->getCurrentNode()->data_type);
    }
}