Component/module/plugin Managment ?

Hello community.

As the topic says, is there a module managment tool in Yii2 ?

I found this one for yii1 : github . com/antonCPU/app-manager

I need something to manage modules/components on the fly for my project.

Big Thanks

Mafi

I implementation about that





<?php


namespace app\components\base;


use app\models\Modules;

use yii\base\component;

use yii\base\BootstrapInterface;

use yii\base\InvalidParamException;

use yii\helpers\Json;


class ModuleLoader extends Component implements BootstrapInterface

{

    private $_enabledModules = [];


    public function bootstrap($application)

    {

        //Load Enabled Modules Form storage

        $this->_enabledModules = Modules::find()->enabled()->asArray()->indexBy('module')->all();

        foreach ($this->_enabledModules as $module) {

            //TODO Add config for each modules from DB

            \Yii::trace('Load Module:' . $module['module'], 'application.ModuleLoader');

            $config = Json::decode($module['config']);

            if (json_last_error() && !isset($config['configure'])) {

                throw new InvalidParamException($module['module'] . ' config is not valid json ');

            }

            $application->setModule($module['module'], $config['configure']);

        }

    }




    public function getEnabledModules()

    {

        return $this->_enabledModules;

    }


    /**

     * Load Modules Dir Name From Modules Path(@app/modules)

     *

     * @return array

     */

    public function getModuleDirs()

    {

        $modulePath = $this->getModulePath();

        $dirs = (array)glob($modulePath . '*');

        $moduleDirs = array();

        foreach ($dirs as $dir) {

            if (is_dir($dir)) {

                $d = basename($dir);

                $moduleDirs[] = $d;

            }

        }

        return $moduleDirs;

    }


    /**

     * Get the Modules List which in modules Dir that not in db

     *

     * @return array

     */

    public function unInstallModules()

    {

        $unInstall = [];

        $install = $this->installedModules();

        $allModules = $this->getModuleDirs();


        if (!$install) {

            return $this->loadModuleConfig($allModules);

        }


        foreach ($allModules as $module) {

            if (!isset($install[$module])) {

                $unInstall[] = $module;

            }

        }

        return $this->loadModuleConfig($unInstall);

    }


    /**

     * Get All Modules From DB

     *

     * @return array|\yii\db\ActiveRecord[]

     */

    public function installedModules()

    {

        return Modules::find()->asArray()->indexBy('module')->all();

    }


    private function loadModuleConfig($modules)

    {

        $return = [];

        if (!$modules) {

            return [];

        }

        foreach ($modules as $module) {

            $return[$module] = $this->getModuleConfig($module);

        }

        return $return;

    }


    public function getModulePath()

    {

        return \Yii::getAlias('@app/modules') . DIRECTORY_SEPARATOR;

    }


    public function getModuleClass($module)

    {

        $class = "\\app\\modules\\" . $module . "\\Module";

        if (class_exists($class)) {

            return $class;

        }

        \Yii::trace(

            'Load Module Config : The module class not exist:' . $module['module'] . '',

            'application.ModuleLoader'

        );

        return false;

    }


    public function getModuleConfig($module)

    {

        if (!$module) {

            return [];

        }

        $class = $this->getModuleClass($module);

        if ($class && method_exists($class, 'moduleConfig')) {

            return $class::moduleConfig();

        }

        return [];

    }


    public function install($module)

    {

        $class = $this->getModuleClass($module);

        if (!$class) {

            throw new InvalidParamException($module . "'s Modules.php not exist");

        }

        return $class::install();

    }


    public function uninstall($module)

    {

        $class = $this->getModuleClass($module);

        if (!$class) {

            throw new \HttpInvalidParamException($module . "'s Modules.php not exist");

        }

        return $class::uninstall();

    }


}



if you config in your config file like this:




[

  'bootstrap' => ['log', 'moduleLoader'],

  

  'components' => [

     ......

      'moduleLoader' => [

            'class' => 'app\components\base\ModuleLoader'

        ]

     ......

  ]

]



the database modules:




CREATE TABLE `modules` (

  `id` int(10) NOT NULL AUTO_INCREMENT,

  `module` varchar(30) NOT NULL DEFAULT '' COMMENT 'module id',

  `name` varchar(20) NOT NULL DEFAULT '' COMMENT 'module name',

  `url` varchar(100) NOT NULL DEFAULT '' COMMENT '',

  `version` varchar(50) NOT NULL DEFAULT '' COMMENT 'version',

  `icon` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT 'icon for the module',

  `category` varchar(30) NOT NULL DEFAULT '' COMMENT '',

  `description` varchar(255) NOT NULL DEFAULT '' COMMENT '',

  `config` text COMMENT '模块配置,数组形式',

  `sort` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT ' ',

  `disabled` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT 'status for module',

  `created_at` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '',

  `updated_at` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '',

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;



now create the model:




  <?php


namespace app\models;


use app\models\query\ModulesQuery;

use Yii;

use yii\base\InvalidParamException;

use yii\behaviors\TimestampBehavior;

use yii\helpers\Json;


/**

 * This is the model class for table "phpci_modules".

 *

 * @property integer $id

 * @property string $module

 * @property string $name

 * @property string $url

 * @property string $version

 * @property integer $icon

 * @property string $category

 * @property string $description

 * @property string $config

 * @property integer $sort

 * @property integer $disabled

 * @property string $created_at

 * @property string $updated_at

 */

class Modules extends \yii\db\ActiveRecord

{

    /**

     * @inheritdoc

     */

    public static function tableName()

    {

        return '{{%modules}}';

    }


    /**

     * @inheritdoc

     */

    public function rules()

    {

        return [

            [['module', 'name', 'description'], 'required'],

            [['icon', 'sort', 'disabled', 'created_at', 'updated_at'], 'integer'],

            [['module', 'category'], 'string', 'max' => 30],

            [['name'], 'string', 'max' => 20],

            [['url'], 'string', 'max' => 100],

            [['version'], 'string', 'max' => 50],

            [['description'], 'string', 'max' => 255],

            [['config'], 'safe']

        ];

    }


    /**

     * @inheritdoc

     */

    public function attributeLabels()

    {

        return [

            'id' => 'ID',

            'module' => 'module id',

            'name' => 'module name',

            'url' => 'url',

            'version' => 'version',

            'icon' => 'icon for module',

            'category' => 'category',

            'description' => 'desc',

            'config' => 'config',

            'sort' => 'sort',

            'disabled' => 'status',

            'created_at' => 'created',

            'updated_at' => 'updated',

        ];

    }


    public function behaviors()

    {

        return [

            TimestampBehavior::className(),

        ];

    }


    public static function find()

    {

        return new ModulesQuery(get_called_class());

    }


    public function beforeSave($insert)

    {

        if (parent::beforeSave($insert)) {

            if (is_array($this->config) || !$this->config) {

                $this->config = $this->config ? Json::encode($this->config) : Json::encode([]);

            }


            if ($insert) {

                $this->disabled = 1;

            }

            return true;

        }

        return false;

    }


    public function getConfig($configKey = null)

    {

        if (!$this->config) {

            return false;

        }


        $config = Json::decode($this->config);

        if ($configKey === null) {

            return $config;

        }


        if (isset($config[$configKey])) {

            return $config[$configKey];

        }


        return [];

    }


    public function install()

    {

        //TODO uninstall 和 install 合并冗代码

        $transaction = self::getDb()->beginTransaction();

        try {

            if ($this->save(false) && Yii::$app->moduleLoader->install($this->module)) {

                Yii::trace($this->module . '安装成功', 'application.ModuleInstall');

                $transaction->commit();

                return true;

            } else {

                $transaction->rollBack();

                return '安装失败()';

            }

        } catch (InvalidParamException $e) {

            $transaction->rollBack();

            Yii::error($e->getMessage(), 'application.ModuleInstall');

            return $e->getMessage();

        } catch (\Exception $e) {

            $transaction->rollBack();

            Yii::error($e->getMessage(), 'application.ModuleInstall');

            return $e->getMessage();

        }

    }


    public function uninstall()

    {

        //TODO uninstall 和 install 合并冗代码

        $transaction = self::getDb()->beginTransaction();

        try {

            if ($this->delete() && Yii::$app->moduleLoader->uninstall($this->module)) {

                Yii::trace($this->module . '卸载成功', 'application.ModuleInstall');

                $transaction->commit();

                return true;

            } else {

                $transaction->rollBack();

                return '卸载失败';

            }

        } catch (InvalidParamException $e) {

            $transaction->rollBack();

            Yii::error($e->getMessage(), 'application.ModuleInstall');

            return $e->getMessage();

        } catch (\Exception $e) {

            $transaction->rollBack();

            Yii::error($e->getMessage(), 'application.ModuleInstall');

            return $e->getMessage();

        }


    }

}




last you must crate a config file named config.php in your module dir :




<?php


return [

    //module basic info

    'module' => 'phploc',

    'name' => 'PHPLoc',

    'description' => 'phploc is a tool for quickly measuring the size and analyzing the structure of a PHP project.',

    'version' => '1.0',

    'category' => '',

    'url' => '',

    //module config info

    'config' => [

        'configure' => [

            'class' => 'app\modules\phploc\Module',

        ],

        'setting' => [

            'route' => 'phploc/default/index',

        ]


    ],


];




now you can set config your module like this in module.php




 <?php


namespace app\modules\phploc;


class Module extends \yii\base\Module

{

    public $controllerNamespace = 'app\modules\phploc\controllers';




    public function init()

    {

        parent::init();


        // custom initialization code goes here

    }




    public static function install()

    {

        return true;

    }


    public static function uninstall()

    {

        return true;

    }


    public static function moduleConfig()

    {

        if (is_file(__DIR__ . DIRECTORY_SEPARATOR . 'config.php')) {

            return require(__DIR__ . DIRECTORY_SEPARATOR . 'config.php');

        }

        return [];

    }

}




Big thanks, i will try it!