controllerNamespace = 'rss\\' . $this->id . '\commands'; $this->defaultRoute = 'init'; } // Set alias of module base path $this->alias = '@'.$this->vendor.'/'.$this->id; $this->setAliases([ $this->alias => $this->basePath ]); // Set version of current module $this->setVersion($this->version); // Set priority of current module $this->setPriority($this->priority); // Register translations $this->registerTranslations(); // Normalize route prefix $this->routePrefixNormalize(); // Set meta data of current module $this->setMetaData(); } /** * Get module vendor * @return string of current module vendor */ public function getVendor() { return $this->vendor; } /** * Get module version * @return string of current module version */ public function getVersion() { $this->version = parent::getVersion(); return $this->version; } /** * Set current module version * @param $version string */ public function setVersion($version) { parent::setVersion($version); $this->version = $version; } /** * Get module priority * @return integer of current module priority */ public function getPriority() { return $this->priority; } /** * Set current module priority * @param $priority integer */ public function setPriority($priority) { $this->priority = $priority; } /** * Get alias * @return string of current module alias */ public function getBaseAlias() { return $this->alias; } /** * Set meta data * @return array of current module meta data */ public function setMetaData() { $data = []; $module = $this; if (isset($module->id)) { $data['id'] = $module->id; $data['uniqueId'] = $module->getUniqueId(); $data['name'] = str_replace(Yii::getAlias('@vendor').'/',"", $module->getBasePath()); $data['label'] = (isset($module->name)) ? $module->name : null; $data['version'] = $module->getVersion(); $data['vendor'] = (isset($module->vendor)) ? $module->vendor : null; $data['alias'] = $module->getBaseAlias(); $data['paths']['basePath'] = $module->getBasePath(); $data['paths']['controllerPath'] = $module->getControllerPath(); $data['paths']['layoutPath'] = $module->getLayoutPath(); $data['paths']['viewPath'] = $module->getViewPath(); $data['components'] = $module->getComponents(); $data['parent']['id'] = (isset($module->module->id)) ? $module->module->id : null; $data['parent']['uniqueId'] = $module->module->getUniqueId(); $data['parent']['version'] = $module->module->getVersion(); $data['parent']['paths']['basePath'] = $module->module->getBasePath(); $data['parent']['paths']['controllerPath'] = $module->module->getControllerPath(); $data['parent']['paths']['layoutPath'] = $module->module->getLayoutPath(); $data['parent']['paths']['viewPath'] = $module->module->getViewPath(); $data['extensions'] = Yii::$app->extensions; } $this->meta = $data; } /** * Get meta data * @return array of current module meta data */ public function getMetaData() { return $this->meta; } /** * Get option from DB, params or module public properties * @return mixed of params or current module properties */ public function getOption($option) { $value = null; if (isset(Yii::$app->options)) { if (!$value = Yii::$app->options->get($option)) { if (preg_match('/\./', $option)) { $split = explode('.', $option, 2); if (count($split) > 1) { if (!empty($split[0]) && !empty($split[1])) { $option = $split[1]; } } } if (isset(Yii::$app->params[$option])) $value = Yii::$app->params[$option]; elseif (isset($this->$option)) $value = $this->$option; } } else { if (preg_match('/\./', $option)) { $split = explode('.', $option, 2); if (count($split) > 1) { if (!empty($split[0]) && !empty($split[1])) { $section = $split[0]; $option = $split[1]; } } } if (isset(Yii::$app->params[$option])) $value = Yii::$app->params[$option]; elseif (isset($this->$option)) $value = $this->$option; } if (YII_ENV_DEV) { if (isset(Yii::$app->options)) Yii::debug('Option from options`'.$option.'` is ' . gettype(Yii::$app->options->get('admin.checkForUpdates')) .' and value: '. var_export(Yii::$app->options->get('admin.checkForUpdates'), true)); if (isset(Yii::$app->params['admin.checkForUpdates'])) Yii::debug('Option from params`'.$option.'` is ' . gettype(Yii::$app->params['admin.checkForUpdates']) .' and value: '. var_export(Yii::$app->params['admin.checkForUpdates'], true)); Yii::debug('`'.$option.'` is ' . gettype($value) .' and value: '. var_export($value, true)); } return $value; } /** * {@inheritdoc} */ public function afterAction($action, $result) { // Log missing translations if (is_array($this->missingTranslation) && YII_ENV == 'dev') Yii::warning('Missing translations: ' . var_export($this->missingTranslation, true), 'i18n'); $result = parent::afterAction($action, $result); return $result; } /** * Registers translations for module */ public function registerTranslations() { $moduleId = 'base'; if (!is_null($this->id)) $moduleId = $this->id; Yii::$app->i18n->translations['app/modules/' . $moduleId] = [ 'class' => 'yii\i18n\PhpMessageSource', 'sourceLanguage' => 'en-US', 'basePath' => '@rss/messages', 'on missingTranslation' => function ($event) { if (YII_ENV == 'dev') $this->missingTranslation[] = $event->message; } ]; // Name and description translation of module // $this->name = Yii::t('app/modules/' . $moduleId, $this->name); // $this->description = Yii::t('app/modules/' . $moduleId, $this->description); } /** * Public translation function, Module::t('app/modules/admin', 'Dashboard'); * @return string of current message translation */ public static function t($category, $message, $params = [], $language = null) { return Yii::t('app/modules/' . self::id .'/'. $category, $message, $params, $language); } /** * Normalize route * @return string of current route */ public function normalizeRoute($route) { $route = ltrim($route, '/'); $route = rtrim($route, '/'); $route = '/'.$route; $route = str_replace('//', '/', $route); return $route; } /** * Normalize route prefix * @return string of current route prefix */ public function routePrefixNormalize() { if(!empty($this->routePrefix)) $this->routePrefix = self::normalizeRoute($this->routePrefix); return $this->routePrefix; } /** * Build dashboard navigation items for NavBar * @param $options array, if you need to add a custom menu routes, like create, update, etc. item * @return array of current module nav items */ public function dashboardNavItems($options = false) { $items = [ 'label' => $this->name, 'url' => [$this->routePrefix . '/'. $this->id . ((isset($this->defaultRoute)) ? '/' . $this->defaultRoute : '')], 'active' => (\Yii::$app->controller->module->id == $this->id) ? true : false ]; if (is_array($options)) { foreach ($options as $route => $option) { if (is_string($route)) { $items['items'] = [ [ 'label' => (isset($option['label'])) ? $option['label'] : $route, 'icon' => (isset($option['icon'])) ? $option['icon'] : null, 'url' => [$this->routePrefix . '/' . $this->id . '/' . ltrim($route, '/')], 'active' => ((\Yii::$app->controller->module->id == $this->id) && (\Yii::$app->controller->action->id == ltrim($route, '/'))) ? true : false ], ]; } } } return $items; } /** * Check if module exist * * @param $id * @param bool $returnId * @return string */ public function moduleExist($id, $returnId = false) { // If module configured without parent module, like `admin/...` if (!(preg_match('/\/[^\s]+/', $id))) { $parent = $this->module->id; if ($parent) $id = $parent . '/' . $id; } $isExist = (Yii::$app->hasModule($id)); if ($returnId && $isExist) return $id; return $isExist; } /** * Check if module exist and return instance * * @param $id string, the module name (if the module name does not contain the parent module, * it will be assigned from the launch module) * @param $returnInstance boolean, the return instance of module * @return boolean, null or intance */ public function moduleLoaded($id, $returnInstance = false, $autoLoad = false) { // If module configured without parent module, like `admin/...` if (!(preg_match('/\/[^\s]+/', $id))) { $parent = $this->module->id; if ($parent) $id = $parent . '/' . $id; } if ($id = $this->moduleExist($id, true)) { if ($returnInstance) return Yii::$app->getModule($id, $autoLoad); else return true; } else { return false; } return null; } /** * Returns a value indicating whether the current request is made via command line (console). * * @return bool */ public function isConsole() { return Yii::$app->request->isConsoleRequest; } /** * Returns a value indicating whether the current request made for admin dashboard. * * @return bool * @throws \yii\base\InvalidConfigException */ public function isBackend($onlyAuth = true) { if ($this->isConsole()) return true; $isBackend = false; if (substr(Yii::$app->request->getUrl(), 0, 6) == '/admin') return true; if ($onlyAuth && Yii::$app->getUser()->getIsGuest()) return false; return false; } public function isRestAPI() { if ($this->isConsole()) return false; if (Yii::$app->controller instanceof \yii\rest\Controller) return true; return false; } /** * Bootstrap interface, to be called during application loaded module. * @param $app object, the application currently running */ public function bootstrap($app) { // Get URL path prefix if exist if (isset($this->routePrefix)) $prefix = $this->routePrefix . '/'; else $prefix = ''; // Add module URL rules if ($urlManager = $app->getUrlManager()) { $urlManager->addRules([ $prefix . 'id . '>///' => '//', $prefix . 'id . '>//' => '//', $prefix . 'id . '>/' => '//index', ], true); } // Add short module alias, like `@sitemap` instead of long `@wdmg/sitemap` if ($this->id !== 'base') { Yii::setAlias('@' . $this->id, Yii::getAlias($this->getBaseAlias())); } // Get missing translations $missingTranslation = $this->missingTranslation; // Log missing translations if (!($app instanceof \yii\console\Application) && $this->module) { \yii\base\Event::on(\yii\base\Controller::class, \yii\base\Controller::EVENT_AFTER_ACTION, function ($event) use ($missingTranslation) { // Log missing translations if (is_array($missingTranslation) && YII_ENV == 'dev') Yii::warning('Missing translations: ' . var_export($missingTranslation, true), 'i18n'); }); } } public function install() { if (!($options = Yii::$app->getModule('admin/options'))) $options = Yii::$app->getModule('options'); if (!is_null($options) && isset(Yii::$app->options)) { $props = get_class_vars(get_class($this)); foreach ($props as $prop => $value) { // Skip private properties of modules if (in_array($prop, $this->privateProperties)) continue; if (is_array($value)) Yii::$app->options->set($this->id .'.'. $prop, $value, 'array', null, true, false); elseif (is_object($value)) Yii::$app->options->set($this->id .'.'. $prop, $value, 'object', null, true, false); elseif (is_bool($value)) Yii::$app->options->set($this->id .'.'. $prop, ($value) ? 1 : 0, 'boolean', null, true, false); else Yii::$app->options->set($this->id .'.'. $prop, $value, null, null, true, false); } return true; } return false; } /** * Main method of uninstallation module * @return boolean, false if uninstall failure */ public function uninstall() { return true; } /** * Runs command in console (CLI) from web-request * * @param string $command, cli command, like `php yii hello/index` * @param bool $await, flag if need wait the return execution output * @param bool $cli, flag if need execute system comands * @param bool $escape, flag if need to escape shell metacharacters * @return null|array */ public function runConsole($command, $await = true, $cli = false, $escape = true) { ignore_user_abort(true); set_time_limit(0); $status = null; $output = null; $cmd = ""; if (!$cli) { $script = Yii::getAlias('@app/yii'); $cmd = "php " . $script . " " . $command; } else { $cmd = $command; } if (!$await) { header('Connection: close'); @ob_end_flush(); @ob_flush(); @flush(); if (session_id()) session_write_close(); } if ($escape) $cmd = escapeshellcmd($cmd); if (mb_strtolower(mb_substr(php_uname(), 0, 7)) == "windows" || $cli) { $status = popen($cmd . ' 2>&1', 'r'); $output = ''; while (!feof($status)) { $output .= fgets($status); } return [pclose($status), trim($output)]; } else { $output = exec($cmd . " > /dev/null 2>&1 &", $status); return [$status, trim($output)]; } } }