MenuItem.php 8.41 KB
<?php

namespace thread\modules\menu\models;

use Yii;
use yii\db\ActiveQuery;
use yii\helpers\ArrayHelper;
use yii\helpers\Url;
//
use thread\app\base\models\ActiveRecord;
use thread\modules\menu\Menu as MenuModule;
use thread\app\helpers\tree\multi\MultiTreeBehavior;

/**
 * Class MenuItem
 *
 * @package thread\modules\menu\models
 * @author FilamentV <vortex.filament@gmail.com>
 * @copyright (c), Thread
 */
class MenuItem extends ActiveRecord
{
    const LINK_TYPE_EXTERNAL = 'external';
    const LINK_TYPE_INTERNAL = 'internal';
    const LINK_TYPE_PERMANENT = 'permanent';

    /**
     * Переопределяем active query
     * @var
     */
    public static $commonQuery = query\ActiveQuery::class;

    /**
     * @var array
     */
    protected static $sources = [];

    /**
     * @var array
     */
    protected static $permanent_link = [];

    /**
     *
     * @return string
     */
    public static function getDb()
    {
        return Menu::getDb();
    }

    /**
     * @return string
     */
    public static function tableName()
    {
        return '{{%menu_item}}';
    }

    public function init()
    {
        parent::init();
        self::getInternalSourcesFromModule();
    }

    /**
     * @return array
     */
    public function rules()
    {
        return [
            [['group_id, type'], 'required'],
            [['created_at', 'updated_at', 'group', 'position', 'group_id', 'parent_id', 'internal_source_id'], 'integer'],
            //
            [['type'], 'in', 'range' => array_keys(static::typeRange())],
            ['type', 'default', 'value' => array_keys(static::typeRange())[0]],
            //
            [['link_type'], 'in', 'range' => array_keys(static::linkTypeRange())],
            ['link_type', 'default', 'value' => array_keys(static::linkTypeRange())[0]],
            //
            [['link_target'], 'in', 'range' => array_keys(static::linkTargetRange())],
            ['link_target', 'default', 'value' => array_keys(static::linkTargetRange())[0]],
            //
            ['internal_source', 'default', 'value' => 'page_page'],
            //
            [['published', 'deleted'], 'in', 'range' => array_keys(static::statusKeyRange())],
            [['link', 'internal_source', 'default_title'], 'string', 'max' => 255],
            //default
            [['type'], 'default', 'value' => 'normal'],
            [['position', 'parent_id', 'internal_source_id'], 'default', 'value' => '0'],
            [['link'], 'default', 'value' => '1'],
            //Tree
            [['position', 'level'], 'default', 'value' => 0],
            [['tree', 'parent', 'position', 'level'], 'integer'],
            [['parent'], 'validateParentPath'],
        ];
    }

    /**
     * @return array
     */
    public function scenarios()
    {
        return [
            'published' => ['published'],
            'deleted' => ['deleted'],
            'position' => ['position'],
            'backend' => [
                'link', 'group_id', 'type', 'published', 'deleted', 'position', 'internal_source', 'internal_source_id',
                'link_target', 'link_type', 'parent_id', 'default_title',
                //Tree
                'parent', 'tree', 'level'
            ],
        ];
    }

    /**
     * @return array
     */
    public function attributeLabels()
    {
        return [
            'id' => Yii::t('app', 'ID'),
            'alias' => Yii::t('app', 'Alias'),
            'group_id' => Yii::t('app', 'Menu'),
            'parent_id' => Yii::t('app', 'Parent'),
            'parent' => Yii::t('app', 'Parent'),
            'type' => Yii::t('app', 'Type'),
            'link' => Yii::t('app', 'Link'),
            'link_type' => Yii::t('menu', 'Link type'),
            'link_target' => Yii::t('menu', 'Link target'),
            'internal_source' => Yii::t('menu', 'Internal source'),
            'internal_source_id' => Yii::t('menu', 'Internal source id'),
            'external_link' => Yii::t('menu', 'External link'),
            'position' => Yii::t('app', 'Position'),
            'created_at' => Yii::t('app', 'Create time'),
            'updated_at' => Yii::t('app', 'Update time'),
            'published' => Yii::t('app', 'Published'),
            'deleted' => Yii::t('app', 'Deleted'),
            'title' => Yii::t('app', 'Title'),
            'default_title' => Yii::t('app', 'Default Title'),
        ];
    }

    /**
     * @return ActiveQuery
     */
    public function getMenu()
    {
        return $this->hasOne(Menu::class, ['id' => 'group_id'])->undeleted();
    }

    /**
     * @return ActiveQuery
     */
    public function getLang()
    {
        return $this->hasOne(MenuItemLang::class, ['rid' => 'id']);
    }

    /**
     * @return string
     */
    public function getTitle()
    {
        return (isset($this->lang->title)) ? $this->lang->title : "{{$this->default_title}}";
    }

    /**
     * @return ActiveQuery
     */
    public function getItems()
    {
        return $this->hasMany(self::class, ['parent_id' => 'id'])->undeleted();
    }

    /**
     * @return ActiveQuery
     */
    public function getSource()
    {
        if (!isset(self::$sources[$this->internal_source])) {
            return null;
        }
        return $this->hasOne(self::$sources[$this->internal_source]['class'], ['id' => 'internal_source_id']);
    }

    /**
     * @return array
     */
    public static function getInternalSourcesFromModule()
    {
        /** @var MenuModule $module */
        $module = Yii::$app->getModule('menu');
        $module->setInternalSource();
        self::$sources = $module->internal_sources_list;
    }

    /**
     * @return array
     */
    public static function getPermanentLink()
    {
        /** @var MenuModule $module */
        $module = Yii::$app->getModule('menu');
        return $module->permanent_link;
    }


    /**
     * @return array
     */
    public static function getTypeSources()
    {
        return ArrayHelper::map(self::$sources, 'key', 'label');
    }

    /**
     * @return array
     */
    public static function getSourcesList()
    {
        return self::$sources;
    }

    /**
     * Варіанти типів елементів меню
     * Значення параметра type
     * @return array
     */
    public static function typeRange()
    {
        return [
            'normal' => Yii::t('menu', 'Default'),
            'divider' => Yii::t('menu', 'Divider'),
            'header' => Yii::t('menu', 'Header'),
        ];
    }

    /**
     * Варіанти типів посилань елементів
     * Значення параметра link_type
     * @return array
     */
    public static function linkTypeRange()
    {
        return [
            'external' => Yii::t('menu', 'External'),
            'internal' => Yii::t('menu', 'Internal'),
            'permanent' => Yii::t('menu', 'Permanent'),
        ];
    }

    /**
     * Варіанти типів відкриття посилань посилань елементів
     * Значення параметра link_type
     * @return array
     */
    public static function linkTargetRange()
    {
        return [
            '_blank' => Yii::t('menu', '_blank'),
            '_self' => Yii::t('menu', '_self'),
        ];
    }

    /**
     * @return string
     */
    public function getTarget()
    {
        return (self::LINK_TYPE_EXTERNAL == $this['link_type']) ? $this['link_target'] : '_self';
    }

    /**
     * @param bool $scheme
     * @return mixed|string
     */
    public function getLink($scheme = false)
    {
        $link = '';
        switch ($this['link_type']) {
            case self::LINK_TYPE_EXTERNAL:
                $link = $this['lang']['link']??'';
                break;
            case self::LINK_TYPE_INTERNAL:
                $link = (isset($this->source)) ? $this->source->getUrl($scheme) : '';
                break;
            case self::LINK_TYPE_PERMANENT:
                $link = Url::toRoute($this['link'], $scheme);
                break;
        }
        return $link;
    }

    /**
     * @param $id
     * @return mixed
     */
    public static function getById($id)
    {
        return self::find()->byID($id)->one();
    }

    use \thread\app\helpers\tree\multi\MultiTreeModelTrait;

    /**
     * @return array
     */
    public function behaviors()
    {
        return ArrayHelper::merge(parent::behaviors(), [
            'multitree' => [
                'class' => MultiTreeBehavior::class,
            ],
        ]);
    }
}