From 3d3fe43d54e4adee76c37a0b9fc31e65353b56d9 Mon Sep 17 00:00:00 2001 From: Antonio Ramirez Date: Sat, 3 Dec 2016 19:20:12 +0100 Subject: [PATCH] added Bootstrap + Module + model class map helper + message translation config --- composer.json | 21 ++- lib/User/Bootstrap.php | 218 +++++++++++++++++++++++++---- lib/User/Helper/ClassMapHelper.php | 49 +++++++ lib/User/Module.php | 19 +-- lib/i18n/message.php | 46 ++++++ 5 files changed, 308 insertions(+), 45 deletions(-) create mode 100644 lib/User/Helper/ClassMapHelper.php create mode 100644 lib/i18n/message.php diff --git a/composer.json b/composer.json index f2574da..e620502 100644 --- a/composer.json +++ b/composer.json @@ -8,24 +8,31 @@ "email": "email@example.com" } ], + "require": { + "php": ">=5.5" + }, "require-dev": { "squizlabs/php_codesniffer": "^2.7", "fabpot/php-cs-fixer": "^1.12", - "phpmd/phpmd": "^2.4" + "phpmd/phpmd": "^2.4", + "dektrium/yii2-user": "^0.9.9", + "dektrium/yii2-rbac": "^0.3.0" }, "autoload": { "psr-4": { - "Da\\" : ["./lib", "./tests/lib"] + "Da\\": [ + "./lib", + "./tests/lib" + ] } }, "autoload-dev": { "psr-4": { - "Da\\": ["./lib", "./tests/lib"] + "Da\\": [ + "./lib", + "./tests/lib" + ] } }, - "require": { - "dektrium/yii2-user": "^0.9.9", - "dektrium/yii2-rbac": "^0.3.0" - }, "minimum-stability": "dev" } diff --git a/lib/User/Bootstrap.php b/lib/User/Bootstrap.php index c9e8369..589f886 100644 --- a/lib/User/Bootstrap.php +++ b/lib/User/Bootstrap.php @@ -1,49 +1,217 @@ - */ class Bootstrap implements BootstrapInterface { + /** + * @inheritdoc + */ public function bootstrap($app) { - if($app->hasModule('user') && $app->getModule('user') instanceof Module) { + if ($app->hasModule('user') && $app->getModule('user') instanceof Module) { + $classMap = $this->buildClassMap(); + $this->initContainer($classMap); + $this->initTranslations($app); - // configure yii's container - $this->setContainer(); + if ($app instanceof WebApplication) { + $this->initUrlRoutes($app); + $this->initAuthCollection($app); + } else { + /** @var $app ConsoleApplication */ + $this->initConsoleCommands($app); + } } } - protected function setContainer() + /** + * Initialize container with module classes + * + * @param array $map the previously built class map list + */ + protected function initContainer($map) { $di = Yii::$container; - // helpers - $di->set('Da\User\Helper\AuthHelper'); // email change strategy $di->set('Da\User\Strategy\DefaultEmailChangeStrategy'); $di->set('Da\User\Strategy\InsecureEmailChangeStrategy'); $di->set('Da\User\Strategy\SecureEmailChangeStrategy'); - // active query classes - Yii::$container->set('Da\User\Query\AccountQuery'); - Yii::$container->set('Da\User\Query\ProfileQuery'); - Yii::$container->set('Da\User\Query\TokenQuery'); - Yii::$container->set('Da\User\Query\UserQuery'); + // models + active query classes + $modelClassMap = []; + foreach ($map as $class => $definition) { + + $di->set($class, $definition); + $model = is_array($definition) ? $definition['class'] : $definition; + $name = (substr($class, strrpos($class, '\\') + 1)); + $modelClassMap[$name] = $model; + + if (in_array($name, ['User', 'Profile', 'Token', 'Account'])) { + $di->set( + $name . 'Query', + function () use ($model) { + return $model->find(); + } + ); + } + } + + // helpers + $di->set('Da\User\Helper\AuthHelper'); + $di->setSingleton(ClassMapHelper::class, 'Da\User\Helper\ModelClassMapHelper', [$modelClassMap]); + + if (php_sapi_name() !== 'cli') { + // override Yii + $di->set( + 'yii\web\User', + [ + 'enableAutoLogin' => true, + 'loginUrl' => ['/user/auth/login'], + 'identityClass' => $di->get(ClassMapHelper::class)->get('User') + ] + ); + } } + + /** + * Registers module translation messages + * + * @param Application $app + */ + protected function initTranslations(Application $app) + { + if (!isset($app->get('i18n')->translations['user*'])) { + $app->get('i18n')->translations['user*'] = [ + 'class' => PhpMessageSource::class, + 'basePath' => __DIR__ . '/../i18n', + 'sourceLanguage' => 'en-US' + ]; + } + } + + /** + * Initializes web url routes (rules in Yii2) + * + * @param WebApplication $app + */ + protected function initUrlRoutes(WebApplication $app) + { + /** @var $module Module */ + $module = $app->getModule('user'); + $config = [ + 'class' => 'yii\web\GroupUrlRule', + 'prefix' => $module->prefix, + 'rules' => $module->routes, + ]; + + if ($module->prefix !== 'user') { + $config['routePrefix'] = 'user'; + } + + $rule = Yii::createObject($config); + $app->getUrlManager()->addRules([$rule], false); + } + + /** + * Ensures the authCollection component is configured. + * + * @param WebApplication $app + */ + protected function initAuthCollection(WebApplication $app) + { + if (!$app->has('authClientCollection')) { + $app->set('authClientCollection', Collection::class); + } + } + + /** + * Registers console commands to main app. + * + * @param ConsoleApplication $app + */ + protected function initConsoleCommands(ConsoleApplication $app) + { + $app->getModule('user')->controllerNamespace = 'Da\User\Command'; + } + + /** + * Builds class map according to use configuration + * + * @return array + */ + protected function buildClassMap() + { + $map = []; + + $defaults = [ + 'User' => 'Da\User\Model\User', + 'Account' => 'Da\User\Model\Account', + 'Profile' => 'Da\User\Model\Profile', + 'Token' => 'Da\User\Model\Token', + // --- + 'UserSearch' => 'Da\User\Search\UserSearch', + // --- + 'RegistrationForm' => 'Da\User\Form\RegistrationForm', + 'ResendForm' => 'Da\User\Form\ResendForm', + 'LoginForm' => 'Da\User\Form\LoginForm', + 'SettingsForm' => 'Da\User\Form\SettingsForm', + 'RecoveryForm' => 'Da\User\Form\RecoveryForm', + ]; + + $routes = [ + 'Da\User\Model' => [ + 'User', + 'Account', + 'Profile', + 'Token' + ], + 'Da\User\Search' => [ + 'UserSearch' + ], + 'Da\UserForm' => [ + 'RegistrationForm', + 'ResendForm', + 'LoginForm', + 'SettingsForm', + 'RecoveryForm', + ] + ]; + + foreach ($defaults as $name => $definition) { + $map[$this->getRoute($routes, $name) . "\\$name"] = $definition; + } + + return $map; + } + + /** + * Returns the parent class name route of a short class name + * + * @param array $routes class name routes + * @param string $name + * + * @return int|string + * @throws Exception + */ + protected function getRoute(array $routes, $name) + { + foreach ($routes as $route => $names) { + if (in_array($name, $names)) { + return $route; + } + } + throw new Exception('Unknown configuration class name'); + } + } diff --git a/lib/User/Helper/ClassMapHelper.php b/lib/User/Helper/ClassMapHelper.php new file mode 100644 index 0000000..3c4988f --- /dev/null +++ b/lib/User/Helper/ClassMapHelper.php @@ -0,0 +1,49 @@ + + */ +class ClassMapHelper +{ + protected $map = []; + + /** + * ModelClassMapHelper constructor. + * + * @param array $map + */ + public function __construct($map = []) + { + $this->map = $map; + } + + /** + * @param $key + * @param $class + */ + public function set($key, $class) + { + $this->map[$key] = $class; + } + + /** + * @param $key + * + * @return mixed + * @throws \Exception + */ + public function get($key) + { + if (array_key_exists($key, $this->map)) { + return $this->map[$key]; + }; + throw new \Exception('Unknown model map key: ' . $key); + } +} diff --git a/lib/User/Module.php b/lib/User/Module.php index a155780..d78c5ef 100644 --- a/lib/User/Module.php +++ b/lib/User/Module.php @@ -1,16 +1,9 @@ - */ class Module extends \yii\base\Module { /** @@ -64,12 +57,12 @@ class Module extends \yii\base\Module * @var array the url rules (routes) */ public $routes = [ - '' => 'profile/show', - '' => 'security/', - '' => 'registration/', + '' => 'profile/show', + '' => 'auth/', + '' => 'registration/', 'confirm//' => 'registration/confirm', - 'forgot' => 'recovery/request', + 'forgot' => 'recovery/request', 'recover//' => 'recovery/reset', - 'settings/' => 'settings/' + 'settings/' => 'settings/' ]; } diff --git a/lib/i18n/message.php b/lib/i18n/message.php new file mode 100644 index 0000000..63f6077 --- /dev/null +++ b/lib/i18n/message.php @@ -0,0 +1,46 @@ + __DIR__ . '/../User', + 'messagePath' => __DIR__, + 'languages' => [ + 'ca', + 'da', + 'de', + 'de-DU', + 'es', + 'fa-IR', + 'fi', + 'fr', + 'hr', + 'hu', + 'it', + 'kz', + 'lt', + 'nl', + 'pl', + 'pt-BR', + 'pt-PT', + 'ro', + 'ru', + 'th', + 'tr_TR', + 'uk', + 'vi', + 'zh-CN', + ], + 'translator' => 'Yii::t', + 'sort' => false, + 'overwrite' => true, + 'removeUnused' => false, + 'only' => ['*.php'], + 'except' => [ + '.svn', + '.git', + '.gitignore', + '.gitkeep', + '.hgignore', + '.hgkeep' + ], + 'format' => 'php', +];