Browse Source

Modules manifest

Modules Manager
Modules management
Start banners module
master
Egorka 6 years ago
parent
commit
54113ff93f
  1. 92
      backend/controllers/ModuleController.php
  2. 4
      backend/messages/ru/main.php
  3. 2
      backend/tests/functional/LoginCest.php
  4. 7
      backend/views/layouts/left.php
  5. 70
      backend/views/module/list.php
  6. 12
      common/config/main.php
  7. 63
      common/modules/banners/BannersModule.php
  8. 8
      common/modules/banners/manifest.php
  9. 4
      common/modules/blog/BlogModule.php
  10. 2
      common/modules/blog/forms/BlogPostForm.php
  11. 2
      common/modules/blog/forms/BlogTagSingleForm.php
  12. 8
      common/modules/blog/manifest.php
  13. 2
      common/modules/blog/messages/ru/blog.php
  14. 13
      common/modules/forms/FormsModule.php
  15. 2
      common/modules/forms/controllers/manage/FormMessageController.php
  16. 20
      common/modules/forms/entities/Form.php
  17. 4
      common/modules/forms/entities/FormMessage.php
  18. 20
      common/modules/forms/forms/FormForm.php
  19. 4
      common/modules/forms/helpers/FormHelper.php
  20. 2
      common/modules/forms/mail/form-html.php
  21. 2
      common/modules/forms/mail/form-text.php
  22. 8
      common/modules/forms/manifest.php
  23. 2
      common/modules/forms/messages/ru/forms.php
  24. 16
      common/modules/forms/views/manage/form-message/index.php
  25. 6
      common/modules/forms/views/manage/form-message/view.php
  26. 8
      common/modules/forms/views/manage/form/_form.php
  27. 2
      common/modules/forms/views/manage/form/_form/_form-items.php
  28. 4
      common/modules/forms/views/manage/form/create.php
  29. 4
      common/modules/forms/views/manage/form/index.php
  30. 4
      common/modules/forms/views/manage/form/update.php
  31. 12
      common/modules/forms/views/manage/form/view.php
  32. 4
      common/modules/links/LinksModule.php
  33. 8
      common/modules/links/manifest.php
  34. 4
      common/modules/links/messages/ru/link.php
  35. 6
      common/modules/links/messages/ru/links.php
  36. 2
      common/modules/links/widgets/MenuItemCreatorWidget.php
  37. 9
      common/modules/pages/PagesModule.php
  38. 8
      common/modules/pages/entities/Page.php
  39. 12
      common/modules/pages/forms/PageForm.php
  40. 8
      common/modules/pages/manifest.php
  41. 2
      common/modules/pages/messages/ru/pages.php
  42. 8
      common/modules/pages/views/manage/page/_form.php
  43. 4
      common/modules/pages/views/manage/page/create.php
  44. 4
      common/modules/pages/views/manage/page/index.php
  45. 4
      common/modules/pages/views/manage/page/update.php
  46. 24
      common/modules/pages/views/manage/page/view.php
  47. 6
      common/modules/pages/widgets/MenuItemCreatorWidget.php
  48. 6
      common/modules/pages/widgets/views/menu-item/creator.php
  49. 90
      core/components/modules/ModuleManager.php
  50. 15
      core/entities/ModuleRecord.php
  51. 6
      core/entities/user/User.php
  52. 25
      core/helpers/ModuleHelper.php
  53. 30
      core/repositories/ModuleRepository.php
  54. 109
      core/services/ModuleService.php
  55. 13
      frontend/tests/_data/login_data.php
  56. 23
      frontend/tests/_data/user.php
  57. 20
      frontend/tests/acceptance/HomeCest.php
  58. 15
      frontend/tests/fixtures/UserFixture.php
  59. 43
      frontend/tests/fixtures/data/user.php
  60. 13
      frontend/tests/functional/AboutCest.php
  61. 59
      frontend/tests/functional/ContactCest.php
  62. 17
      frontend/tests/functional/HomeCest.php
  63. 60
      frontend/tests/functional/LoginCest.php
  64. 57
      frontend/tests/functional/SignupCest.php
  65. 41
      frontend/tests/unit/UserTest.php
  66. 32
      frontend/tests/unit/models/ContactFormTest.php
  67. 59
      frontend/tests/unit/models/PasswordResetRequestFormTest.php
  68. 44
      frontend/tests/unit/models/ResetPasswordFormTest.php
  69. 59
      frontend/tests/unit/models/SignupFormTest.php

92
backend/controllers/ModuleController.php

@ -0,0 +1,92 @@
<?php
/**
* Created by Error202
* Date: 17.08.2018
*/
namespace backend\controllers;
use core\entities\ModuleRecord;
use core\services\ModuleService;
use yii\web\Controller;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use yii\web\NotFoundHttpException;
class ModuleController extends Controller
{
private $service;
public function __construct( string $id, $module, ModuleService $service, array $config = [] ) {
parent::__construct( $id, $module, $config );
$this->service = $service;
}
public function behaviors(): array
{
return [
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'actions' => ['list', 'disable', 'enable', 'delete'],
'allow' => true,
'roles' => ['ModuleManagement'],
],
[ // all the action are accessible to admin
'allow' => true,
'roles' => ['admin'],
],
],
],
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'delete' => ['POST'],
'disable' => ['POST'],
'enable' => ['POST'],
],
],
];
}
public function actionList()
{
//$modules = ModuleRecord::find()->all();
$modules = \Yii::$app->moduleManager->getModules();
return $this->render('list', [
'modules' => $modules,
]);
}
public function actionDelete($id)
{
$module = $this->findModel($id);
$this->service->delete($module);
return $this->redirect(['module/list']);
}
public function actionDisable($id)
{
$module = $this->findModel($id);
$this->service->disable($module);
return $this->redirect(['module/list']);
}
public function actionEnable($id)
{
$module = $this->findModel($id);
$this->service->enable($module);
return $this->redirect(['module/list']);
}
protected function findModel($id): ModuleRecord
{
if (($model = ModuleRecord::findOne($id)) !== null) {
return $model;
}
throw new NotFoundHttpException('The requested module does not exist.');
}
}

4
backend/messages/ru/main.php

@ -32,4 +32,8 @@ return [
'Url' => 'Ссылка',
'Sign in to start your session' => 'Вход в панель управления',
'You have {count} notifications' => 'Новых уведомлений: {count}',
'Modules' => 'Модули',
'Find modules' => 'Поиск модулей',
'Enable' => 'Включить',
'Disable' => 'Отключить'
];

2
backend/tests/functional/LoginCest.php

@ -22,7 +22,7 @@ class LoginCest
{
return [
'user' => [
'class' => UserFixture::className(),
'class' => UserFixture::class,
'dataFile' => codecept_data_dir() . 'login_data.php'
]
];

7
backend/views/layouts/left.php

@ -83,8 +83,13 @@ $model = new SearchForm();
'visible' => \Yii::$app->user->can('admin') || \Yii::$app->user->can('MenuManagement'),
],
['label' => Yii::t('main', 'Modules'), 'icon' => 'cubes', 'items' => [
['label' => Yii::t('main', 'Modules'), 'icon' => 'caret-right', 'url' => ['/module/list'], 'active' => \Yii::$app->controller->action->getUniqueId() == 'module/list'],
['label' => Yii::t('main', 'Find modules'), 'icon' => 'caret-right', 'url' => ['/module/search'], 'active' => \Yii::$app->controller->action->getUniqueId() == 'module/search'],
], 'visible' => \Yii::$app->user->can('admin') || \Yii::$app->user->can('ModuleManagement')],
/*[
'label' => Yii::t('page', 'Pages'),
'label' => Yii::t('pages', 'Pages'),
'icon' => 'file-o', 'url' => ['/page/index'],
'active' => $this->context->id == 'page',
'visible' => \Yii::$app->user->can('admin') || \Yii::$app->user->can('PagesManagement'),

70
backend/views/module/list.php

@ -0,0 +1,70 @@
<?php
/**
* Created by Error202
* Date: 17.08.2018
*/
use core\entities\ModuleRecord;
use yii\helpers\Html;
use core\helpers\ModuleHelper;
/**
* @var $this \yii\web\View
* @var $modules \core\entities\ModuleRecord[]
*/
$this->title = Yii::t('main', 'Modules');
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="row">
<?php foreach ($modules as $module): ?>
<?php
$color = $module->isEnabled() ? '#00aced' : '#cccccc';
if ($module->isDisabled()) {
ModuleHelper::addModuleAdminTranslation($module->name);
}
?>
<div class="col-md-4">
<div class="box">
<div class="box-header with-border">
<h3 class="box-title"><i class="fa fa-power-off" aria-hidden="true" style="color: <?= $color ?>"></i> <?= Yii::t($module->name, $module->name) ?></h3>
</div>
<div class="box-body">
<?= Yii::t($module->name, $module->description) ?>
</div>
<div class="box-footer" style="text-align: right">
<?php if ($module->isEnabled()): ?>
<?= Html::a(Yii::t('main', 'Disable'), ['module/disable', 'id' => $module->id], [
'class' => 'btn btn-default btn-sm',
'data' => [
'method' => 'post',
],
]) ?>
<?php else: ?>
<?= Html::a(Yii::t('main', 'Enable'), ['module/enable', 'id' => $module->id], [
'class' => 'btn btn-default btn-sm',
'data' => [
'method' => 'post',
],
]) ?>
<?php endif; ?>
<?= Html::a(Yii::t('buttons', 'Delete'), ['module/delete', 'id' => $module->id], [
'class' => 'btn btn-danger btn-sm',
'data' => [
'confirm' => Yii::t('buttons', 'Are you sure you want to delete this item?'),
'method' => 'post',
],
]) ?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>

12
common/config/main.php

@ -5,6 +5,15 @@ return [
'@npm' => '@vendor/npm-asset',
],
'vendorPath' => dirname(dirname(__DIR__)) . '/vendor',
'controllerMap' => [
// Common migrations for the whole application
'migrate' => [
'class' => 'yii\console\controllers\MigrateController',
'migrationPath' => [
'@console/migrations',
],
],
],
'components' => [
'cache' => [
'class' => 'yii\caching\FileCache',
@ -35,5 +44,8 @@ return [
'texture_over_image' => false,
'text_over_image' => false,
],
'moduleManager' => [
'class' => \core\components\modules\ModuleManager::class,
],
],
];

63
common/modules/banners/BannersModule.php

@ -0,0 +1,63 @@
<?php
namespace common\modules\banners;
use core\components\modules\ModuleInterface;
use yii\helpers\ArrayHelper;
/**
* blog module definition class
*/
class BannersModule extends \yii\base\Module implements ModuleInterface
{
/**
* @inheritdoc
*/
public $controllerNamespace = 'common\modules\banners\controllers';
/**
* @inheritdoc
*/
public function init()
{
parent::init();
// custom initialization code goes here
}
public function bootstrap($app)
{
// add migration path
$app->controllerMap['migrate']['migrationPath'][] = '@common/modules/banners/migrations';
// add search rules
$app->params['search_rules'][] = "SELECT title, CONCAT('/banners/manage/banner/view/', id) AS url FROM {{banners}}";
$app->getUrlManager()->addRules([
'banners/manage/banner/view/<id:\d+>' => 'banners/manage/banner/view',
]);
// add languages
$app->getI18n()->translations = ArrayHelper::merge($app->getI18n()->translations, [
'banners' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@common/modules/banners/messages',
],
'banners_public' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@common/modules/banners/messages',
],
]);
// add menu items
if (basename($app->getBasePath()) === 'backend') {
$app->params['adminMenu'][] = [
'label' => \Yii::t( 'banners', 'Banners' ),
'icon' => 'flag',
'url' => [ '/banners/manage/banner/index' ],
'visible' => \Yii::$app->user->can( 'admin' ) || \Yii::$app->user->can( 'BannersManagement' )
];
}
}
}

8
common/modules/banners/manifest.php

@ -0,0 +1,8 @@
<?php
return [
'version' => '1.0.1',
'name' => 'banners',
'description' => 'Banners widget for site',
'module' => 'BannersModule',
];

4
common/modules/blog/BlogModule.php

@ -22,12 +22,14 @@ class BlogModule extends \yii\base\Module implements ModuleInterface
public function init()
{
parent::init();
// custom initialization code goes here
}
public function bootstrap($app)
{
// add migration path
$app->controllerMap['migrate']['migrationPath'][] = '@common/modules/blog/migrations';
// add search rules
$app->params['search_rules'][] = "SELECT title, content, CONCAT('/blog/manage/post/view/', id) AS url FROM {{blog_posts}}";

2
common/modules/blog/forms/BlogPostForm.php

@ -108,7 +108,7 @@ class BlogPostForm extends CompositeForm
public function attributeHints() {
return [
'published_at' => Yii::t('blog', 'The article will be published after the specified date if its status is not a draft'),
'slug' => Yii::t('page', 'SEO link will be generated automatically if not specified'),
'slug' => Yii::t('pages', 'SEO link will be generated automatically if not specified'),
];
}

2
common/modules/blog/forms/BlogTagSingleForm.php

@ -45,7 +45,7 @@ class BlogTagSingleForm extends Model
public function attributeHints() {
return [
'slug' => Yii::t('page', 'SEO link will be generated automatically if not specified'),
'slug' => Yii::t('pages', 'SEO link will be generated automatically if not specified'),
];
}
}

8
common/modules/blog/manifest.php

@ -0,0 +1,8 @@
<?php
return [
'version' => '1.0.1',
'name' => 'blog',
'description' => 'Blog system for site with comments and slug',
'module' => 'BlogModule',
];

2
common/modules/blog/messages/ru/blog.php

@ -1,5 +1,7 @@
<?php
return [
'blog' => 'Блог',
'Blog system for site with comments and slug' => 'Публикация статей на сайте в виде ленты. Статьи разделены по категориям',
'All Posts' => 'Все статьи',
'Posts' => 'Статьи',
'Categories' => 'Категории',

13
common/modules/forms/FormsModule.php

@ -31,6 +31,9 @@ class FormsModule extends \yii\base\Module implements ModuleInterface
public function bootstrap($app)
{
// add migration path
$app->controllerMap['migrate']['migrationPath'][] = '@common/modules/forms/migrations';
// prepare rules
$app->getUrlManager()->addRules([
'forms/manage/form/view/<id:\d+>' => 'forms/manage/form/view',
@ -38,7 +41,7 @@ class FormsModule extends \yii\base\Module implements ModuleInterface
// add languages
$app->getI18n()->translations = ArrayHelper::merge($app->getI18n()->translations, [
'form' => [
'forms' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@common/modules/forms/messages',
],
@ -47,16 +50,16 @@ class FormsModule extends \yii\base\Module implements ModuleInterface
// add menu items
if (basename($app->getBasePath()) === 'backend') {
$app->params['adminMenu'][] = [
'label' => \Yii::t( 'form', 'Forms' ),
'label' => \Yii::t( 'forms', 'Forms' ),
'icon' => 'address-card-o',
'items' => [
[
'label' => \Yii::t( 'form', 'Forms' ),
'label' => \Yii::t( 'forms', 'Forms' ),
'icon' => 'caret-right',
'url' => [ '/forms/manage/form/index' ]
],
[
'label' => \Yii::t( 'form', 'Messages' ),
'label' => \Yii::t( 'forms', 'Messages' ),
'icon' => 'caret-right',
'url' => [ '/forms/manage/form-message/index' ]
],
@ -72,7 +75,7 @@ class FormsModule extends \yii\base\Module implements ModuleInterface
'icon' => 'address-card-o',
'color' => 'yellow',
'message' => 'New forms messages: {count}',
'message_file' => 'form',
'message_file' => 'forms',
'url' => '/forms/manage/form-message/index',
'count' => $new_messages_count,
];

2
common/modules/forms/controllers/manage/FormMessageController.php

@ -115,7 +115,7 @@ class FormMessageController extends Controller
];
}
}
Yii::$app->session->setFlash('success', Yii::t('form', 'Selected messages deleted'));
Yii::$app->session->setFlash('success', Yii::t('forms', 'Selected messages deleted'));
return [
'result' => 'success',
];

20
common/modules/forms/entities/Form.php

@ -97,16 +97,16 @@ class Form extends ActiveRecord
public function attributeLabels() {
return [
'name' => Yii::t('form', 'Name'),
'data' => Yii::t('form', 'Form'),
'subject' => Yii::t('form', 'Subject'),
'from' => Yii::t('form', 'From E-mail'),
'reply' => Yii::t('form', 'Reply E-mail'),
'return' => Yii::t('form', 'Return E-mail'),
'complete_text' => Yii::t('form', 'Complete Text'),
'complete_page_id' => Yii::t('form', 'Complete Page'),
'status' => Yii::t('form', 'Status'),
'captcha' => Yii::t('form', 'Use Captcha'),
'name' => Yii::t('forms', 'Name'),
'data' => Yii::t('forms', 'Form'),
'subject' => Yii::t('forms', 'Subject'),
'from' => Yii::t('forms', 'From E-mail'),
'reply' => Yii::t('forms', 'Reply E-mail'),
'return' => Yii::t('forms', 'Return E-mail'),
'complete_text' => Yii::t('forms', 'Complete Text'),
'complete_page_id' => Yii::t('forms', 'Complete Page'),
'status' => Yii::t('forms', 'Status'),
'captcha' => Yii::t('forms', 'Use Captcha'),
];
}

4
common/modules/forms/entities/FormMessage.php

@ -64,8 +64,8 @@ class FormMessage extends ActiveRecord
public function attributeLabels() {
return [
'form_id' => Yii::t('form', 'Form'),
'data' => Yii::t('form', 'Form Data'),
'form_id' => Yii::t('forms', 'Form'),
'data' => Yii::t('forms', 'Form Data'),
];
}

20
common/modules/forms/forms/FormForm.php

@ -58,16 +58,16 @@ class FormForm extends Model
public function attributeLabels() {
return [
'name' => Yii::t('form', 'Name'),
'data' => Yii::t('form', 'Form'),
'subject' => Yii::t('form', 'Subject'),
'from' => Yii::t('form', 'From E-mail'),
'reply' => Yii::t('form', 'Reply E-mail'),
'return' => Yii::t('form', 'Return E-mail'),
'complete_text' => Yii::t('form', 'Complete Text'),
'complete_page_id' => Yii::t('form', 'Complete Page'),
'status' => Yii::t('form', 'Status'),
'captcha' => Yii::t('form', 'Use Captcha'),
'name' => Yii::t('forms', 'Name'),
'data' => Yii::t('forms', 'Form'),
'subject' => Yii::t('forms', 'Subject'),
'from' => Yii::t('forms', 'From E-mail'),
'reply' => Yii::t('forms', 'Reply E-mail'),
'return' => Yii::t('forms', 'Return E-mail'),
'complete_text' => Yii::t('forms', 'Complete Text'),
'complete_page_id' => Yii::t('forms', 'Complete Page'),
'status' => Yii::t('forms', 'Status'),
'captcha' => Yii::t('forms', 'Use Captcha'),
];
}
}

4
common/modules/forms/helpers/FormHelper.php

@ -16,8 +16,8 @@ class FormHelper {
public static function statusList(): array
{
return [
Form::STATUS_DRAFT => Yii::t('form', 'Draft'),
Form::STATUS_ACTIVE => Yii::t('form', 'Active'),
Form::STATUS_DRAFT => Yii::t('forms', 'Draft'),
Form::STATUS_ACTIVE => Yii::t('forms', 'Active'),
];
}

2
common/modules/forms/mail/form-html.php

@ -10,7 +10,7 @@
*/
?>
<h3><?= Yii::t('form', 'Message from site') ?></h3>
<h3><?= Yii::t('forms', 'Message from site') ?></h3>
<?php foreach ($items as $item): ?>
<?= $item['key'] ?>: <?= $item['value'] ?><br>

2
common/modules/forms/mail/form-text.php

@ -10,7 +10,7 @@
*/
?>
<?= Yii::t('form', 'Message from site') ?>
<?= Yii::t('forms', 'Message from site') ?>
-------
<?php foreach ($items as $item): ?>

8
common/modules/forms/manifest.php

@ -0,0 +1,8 @@
<?php
return [
'version' => '1.0.1',
'name' => 'forms',
'description' => 'Form widget generator for site',
'module' => 'FormsModule',
];

2
common/modules/forms/messages/ru/form.php → common/modules/forms/messages/ru/forms.php

@ -1,5 +1,7 @@
<?php
return [
'forms' => 'Формы',
'Form widget generator for site' => 'Создание различных форм для сайта с отправкой на e-mail и уведомлениями',
'Form' => 'Форма',
'Forms' => 'Формы',
'Messages' => 'Сообщения',

16
common/modules/forms/views/manage/form-message/index.php

@ -13,7 +13,7 @@ use backend\widgets\grid\CheckBoxColumn;
/* @var $searchModel \common\modules\forms\forms\FormMessageSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */
$this->title = Yii::t('form', 'Messages');
$this->title = Yii::t('forms', 'Messages');
$this->params['breadcrumbs'][] = $this->title;
$js = <<<JS
@ -34,7 +34,7 @@ $js = <<<JS
JS;
$this->registerJs($js, $this::POS_READY);
$deleteConfirmMessage = Yii::t('form', 'Are you sure you want to delete selected messages?');
$deleteConfirmMessage = Yii::t('forms', 'Are you sure you want to delete selected messages?');
$deleteSelectedUrl = Url::to(['delete-selected']);
$unreadSelectedUrl = Url::to(['unread-selected']);
$readSelectedUrl = Url::to(['read-selected']);
@ -89,7 +89,7 @@ $this->registerJs($js2, $this::POS_HEAD);
<div style="margin-bottom: 10px;">
<div class="btn-group">
<?= Html::a(Yii::t('form', 'Group actions {caret}', ['caret' => '<span class="caret">']), '#', [
<?= Html::a(Yii::t('forms', 'Group actions {caret}', ['caret' => '<span class="caret">']), '#', [
'class' => 'btn btn-default dropdown-toggle disabled',
'id' => 'groupActions',
'disabled' => 'disabled',
@ -99,14 +99,14 @@ $this->registerJs($js2, $this::POS_HEAD);
]) ?>
<ul class="dropdown-menu">
<li><?= Html::a(Yii::t('form', 'Mark as read'), '#', [
<li><?= Html::a(Yii::t('forms', 'Mark as read'), '#', [
'onclick' => new \yii\web\JsExpression('readSelected()'),
]) ?></li>
<li><?= Html::a(Yii::t('form', 'Mark as unread'), '#', [
<li><?= Html::a(Yii::t('forms', 'Mark as unread'), '#', [
'onclick' => new \yii\web\JsExpression('unreadSelected()'),
]) ?></li>
<li role="separator" class="divider"></li>
<li><?= Html::a(Yii::t('form', 'Delete selected'), '#', [
<li><?= Html::a(Yii::t('forms', 'Delete selected'), '#', [
'onclick' => new \yii\web\JsExpression('deleteSelected()'),
]) ?></li>
</ul>
@ -128,7 +128,7 @@ $this->registerJs($js2, $this::POS_HEAD);
'contentOptions' => ['class' => 'text-center'],
],
[
'label' => Yii::t('form', 'Date'),
'label' => Yii::t('forms', 'Date'),
'attribute' => 'created_at',
'value' => function(FormMessage $model) {
return date('d.m.Y H:i', $model->created_at);
@ -136,7 +136,7 @@ $this->registerJs($js2, $this::POS_HEAD);
'options' => ['style' => 'width: 100px;'],
],
[
'label' => Yii::t('form', 'Form'),
'label' => Yii::t('forms', 'Form'),
'filter' => ArrayHelper::map(Form::find()->all(), 'id', 'name'),
'attribute' => 'form_id',
'value' => function (FormMessage $model) {

6
common/modules/forms/views/manage/form-message/view.php

@ -9,7 +9,7 @@ use yii\helpers\Json;
/* @var $message FormMessage */
$this->title = $message->form->name . ': ' . date('d.m.Y H:i', $message->created_at);
$this->params['breadcrumbs'][] = ['label' => Yii::t('form', 'Messages'), 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => Yii::t('forms', 'Messages'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
$data = Json::decode($message->data, true);
@ -17,7 +17,7 @@ $data = Json::decode($message->data, true);
<div class="message-view">
<p>
<?= Html::a(Yii::t('form','Messages'), ['index'], ['class' => 'btn btn-default']) ?>
<?= Html::a(Yii::t('forms','Messages'), ['index'], ['class' => 'btn btn-default']) ?>
<?= Html::a(Yii::t('buttons', 'Delete'), ['delete', 'id' => $message->id], [
'class' => 'btn btn-danger',
'data' => [
@ -50,7 +50,7 @@ $data = Json::decode($message->data, true);
</div>
<!-- <div class="box">
<div class="box-header with-border">< ?= Yii::t('page', 'Complete Message') ?></div>
<div class="box-header with-border">< ?= Yii::t('pages', 'Complete Message') ?></div>
<div class="box-body">
< ?= Yii::$app->formatter->asHtml($form->complete_text, [
'Attr.AllowedRel' => array('nofollow'),

8
common/modules/forms/views/manage/form/_form.php

@ -35,18 +35,18 @@ $this->registerJs($js2);
<div class="col-md-10">
<div class="box box-default">
<div class="box-header with-border"><?= Yii::t('form', 'Common') ?></div>
<div class="box-header with-border"><?= Yii::t('forms', 'Common') ?></div>
<div class="box-body">
<?= \yii\bootstrap\Tabs::widget([
'items' => [
[
'label' => Yii::t('form', 'Common'),
'label' => Yii::t('forms', 'Common'),
'content' => $this->render('_form/_form-items', ['model' => $model, 'form' => $form]),
'active' => true,
],
[
'label' => Yii::t('form', 'Form'),
'label' => Yii::t('forms', 'Form'),
'content' => $this->render('_form/_form-builder', ['model' => $model]),
]
],
@ -63,7 +63,7 @@ $this->registerJs($js2);
<div class="col-md-2">
<div class="box box-default">
<div class="box-header with-border"><?= Yii::t('form', 'Publish') ?></div>
<div class="box-header with-border"><?= Yii::t('forms', 'Publish') ?></div>
<div class="box-body">
<?= $form->field($model, 'status')->radioList(FormHelper::statusList()) ?>

2
common/modules/forms/views/manage/form/_form/_form-items.php

@ -40,7 +40,7 @@ $fetchUrl = Url::to( [ '/forms/manage/form/page-search' ] );
<?= $form->field($model, 'complete_page_id')->widget(\kartik\widgets\Select2::class, [
'options' => [
'placeholder' => Yii::t('form', 'Select page...'),
'placeholder' => Yii::t('forms', 'Select page...'),
'id' => 'page_select',
],
'pluginOptions' => [

4
common/modules/forms/views/manage/form/create.php

@ -3,8 +3,8 @@
/* @var $this yii\web\View */
/* @var $model \common\modules\forms\forms\FormForm */
$this->title = Yii::t('form', 'Create Form');
$this->params['breadcrumbs'][] = ['label' => Yii::t('form', 'Forms'), 'url' => ['index']];
$this->title = Yii::t('forms', 'Create Form');
$this->params['breadcrumbs'][] = ['label' => Yii::t('forms', 'Forms'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="form-create">

4
common/modules/forms/views/manage/form/index.php

@ -9,13 +9,13 @@ use yii\grid\GridView;
/* @var $searchModel \common\modules\forms\forms\FormSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */
$this->title = Yii::t('form', 'Forms');
$this->title = Yii::t('forms', 'Forms');
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="forms-index">
<p>
<?= Html::a(Yii::t('form','Create Form'), ['create'], ['class' => 'btn btn-success']) ?>
<?= Html::a(Yii::t('forms','Create Form'), ['create'], ['class' => 'btn btn-success']) ?>
</p>
<div class="box">

4
common/modules/forms/views/manage/form/update.php

@ -4,8 +4,8 @@
/* @var $form_model \common\modules\forms\entities\Form */
/* @var $model \common\modules\forms\forms\FormForm */
$this->title = Yii::t('form', 'Update Form: {name}', ['name' => $form_model->name]);
$this->params['breadcrumbs'][] = ['label' => Yii::t('page', 'Pages'), 'url' => ['index']];
$this->title = Yii::t('forms', 'Update Form: {name}', ['name' => $form_model->name]);
$this->params['breadcrumbs'][] = ['label' => Yii::t('pages', 'Pages'), 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => $form_model->name, 'url' => ['view', 'id' => $form_model->id]];
$this->params['breadcrumbs'][] = Yii::t('buttons', 'Editing');
?>

12
common/modules/forms/views/manage/form/view.php

@ -9,13 +9,13 @@ use common\modules\forms\helpers\FormHelper;
/* @var $form Form */
$this->title = $form->name;
$this->params['breadcrumbs'][] = ['label' => Yii::t('form', 'Forms'), 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => Yii::t('forms', 'Forms'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="form-view">
<p>
<?= Html::a(Yii::t('form','Forms'), ['index'], ['class' => 'btn btn-default']) ?>
<?= Html::a(Yii::t('forms','Forms'), ['index'], ['class' => 'btn btn-default']) ?>
<?= Html::a(Yii::t('buttons', 'Edit'), ['update', 'id' => $form->id], ['class' => 'btn btn-primary']) ?>
<?= Html::a(Yii::t('buttons', 'Delete'), ['delete', 'id' => $form->id], [
'class' => 'btn btn-danger',
@ -30,7 +30,7 @@ $this->params['breadcrumbs'][] = $this->title;
<div class="col-md-9">
<div class="box">
<div class="box-header with-border"><?= Yii::t('form', 'Common') ?></div>
<div class="box-header with-border"><?= Yii::t('forms', 'Common') ?></div>
<div class="box-body">
<?= DetailView::widget([
'model' => $form,
@ -56,7 +56,7 @@ $this->params['breadcrumbs'][] = $this->title;
</div>
<div class="box">
<div class="box-header with-border"><?= Yii::t('form', 'Complete Message') ?></div>
<div class="box-header with-border"><?= Yii::t('forms', 'Complete Message') ?></div>
<div class="box-body">
<?= Yii::$app->formatter->asHtml($form->complete_text, [
'Attr.AllowedRel' => array('nofollow'),
@ -72,14 +72,14 @@ $this->params['breadcrumbs'][] = $this->title;
<div class="col-md-3">
<div class="box box-default">
<div class="box-header with-border"><?= Yii::t('form', 'Insert Code') ?></div>
<div class="box-header with-border"><?= Yii::t('forms', 'Insert Code') ?></div>
<div class="box-body">
<?php
$code = Html::encode(
"<?= \common\modules\\forms\widgets\FormWidget::widget(['id' => ".$form->id."]) ?>");
?>
<p><?= Yii::t('form', 'For template') ?></p>
<p><?= Yii::t('forms', 'For template') ?></p>
<pre><?= $code ?></pre>
<?php

4
common/modules/links/LinksModule.php

@ -31,7 +31,7 @@ class LinksModule extends \yii\base\Module implements ModuleInterface
{
// add languages
$app->getI18n()->translations = ArrayHelper::merge($app->getI18n()->translations, [
'link' => [
'links' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@common/modules/links/messages',
],
@ -47,7 +47,7 @@ class LinksModule extends \yii\base\Module implements ModuleInterface
$widgets = [];
$widgets[] = [
'id' => 'links',
'title' => \Yii::t('link', 'Links'),
'title' => \Yii::t('links', 'Links'),
'content' => MenuItemCreatorWidget::widget([
'menu_id' => $menu_id,
]),

8
common/modules/links/manifest.php

@ -0,0 +1,8 @@
<?php
return [
'version' => '1.0.1',
'name' => 'links',
'description' => 'Custom links in web site menu',
'module' => 'LinksModule',
];

4
common/modules/links/messages/ru/link.php

@ -1,4 +0,0 @@
<?php
return [
'Links' => 'Ссылки',
];

6
common/modules/links/messages/ru/links.php

@ -0,0 +1,6 @@
<?php
return [
'links' => 'Ссылки',
'Custom links in web site menu' => 'Создание пунктов меню сайта, содержащих ссылки, указанные вручную',
'Links' => 'Ссылки',
];

2
common/modules/links/widgets/MenuItemCreatorWidget.php

@ -16,7 +16,7 @@ class MenuItemCreatorWidget extends Widget
public function run()
{
$form = new MenuItemForm();
$form->module = \Yii::t('link', 'Links');
$form->module = \Yii::t('links', 'Links');
$form->menu_id = $this->menu_id;
return $this->render('menu-item/creator', [

9
common/modules/pages/PagesModule.php

@ -29,6 +29,9 @@ class PagesModule extends \yii\base\Module implements ModuleInterface
public function bootstrap($app)
{
// add migration path
$app->controllerMap['migrate']['migrationPath'][] = '@common/modules/pages/migrations';
// add search rules
$app->params['search_rules'][] = "SELECT title, content, CONCAT('/pages/manage/page/view/', id) AS url FROM {{pages}}";
@ -42,7 +45,7 @@ class PagesModule extends \yii\base\Module implements ModuleInterface
// add languages
$app->getI18n()->translations = ArrayHelper::merge($app->getI18n()->translations, [
'page' => [
'pages' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@common/modules/pages/messages',
],
@ -55,7 +58,7 @@ class PagesModule extends \yii\base\Module implements ModuleInterface
// add menu items
if (basename($app->getBasePath()) === 'backend') {
$app->params['adminMenu'][] = [
'label' => \Yii::t( 'page', 'Pages' ),
'label' => \Yii::t( 'pages', 'Pages' ),
'icon' => 'file-o',
'url' => [ '/pages/manage/page/index' ],
'visible' => \Yii::$app->user->can( 'admin' ) || \Yii::$app->user->can( 'PagesManagement' )
@ -68,7 +71,7 @@ class PagesModule extends \yii\base\Module implements ModuleInterface
$widgets = [];
$widgets[] = [
'id' => 'pages',
'title' => \Yii::t('page', 'Pages'),
'title' => \Yii::t('pages', 'Pages'),
'content' => MenuItemCreatorWidget::widget([
'menu_id' => $menu_id,
]),

8
common/modules/pages/entities/Page.php

@ -103,10 +103,10 @@ class Page extends ActiveRecord
public function attributeLabels() {
return [
'title' => Yii::t('page', 'Title'),
'slug' => Yii::t('page', 'Slug'),
'id' => Yii::t('page', 'ID'),
'content' => Yii::t('page', 'Content'),
'title' => Yii::t('pages', 'Title'),
'slug' => Yii::t('pages', 'Slug'),
'id' => Yii::t('pages', 'ID'),
'content' => Yii::t('pages', 'Content'),
];
}

12
common/modules/pages/forms/PageForm.php

@ -63,17 +63,17 @@ class PageForm extends CompositeForm
public function attributeLabels() {
return [
'title' => Yii::t('page', 'Title'),
'slug' => Yii::t('page', 'Slug'),
'id' => Yii::t('page', 'ID'),
'content' => Yii::t('page', 'Content'),
'parentId' => Yii::t('page', 'Parent Page'),
'title' => Yii::t('pages', 'Title'),
'slug' => Yii::t('pages', 'Slug'),
'id' => Yii::t('pages', 'ID'),
'content' => Yii::t('pages', 'Content'),
'parentId' => Yii::t('pages', 'Parent Page'),
];
}
public function attributeHints() {
return [
'slug' => Yii::t('page', 'SEO link will be generated automatically if not specified'),
'slug' => Yii::t('pages', 'SEO link will be generated automatically if not specified'),
];
}

8
common/modules/pages/manifest.php

@ -0,0 +1,8 @@
<?php
return [
'version' => '1.0.1',
'name' => 'pages',
'description' => 'Custom pages on site with slug',
'module' => 'PagesModule',
];

2
common/modules/pages/messages/ru/page.php → common/modules/pages/messages/ru/pages.php

@ -1,5 +1,7 @@
<?php
return [
'pages' => 'Страницы',
'Custom pages on site with slug' => 'Публикация информации в виде отдельных самостоятельных страниц сайта',
'Create Page' => 'Новая страница',
'Pages' => 'Страницы',
'Common' => 'Основное',

8
common/modules/pages/views/manage/page/_form.php

@ -33,7 +33,7 @@ $this->registerJs($js2);
<div class="col-md-10">
<div class="box box-default">
<div class="box-header with-border"><?= Yii::t('page', 'Common') ?></div>
<div class="box-header with-border"><?= Yii::t('pages', 'Common') ?></div>
<div class="box-body">
<?= $form->field($model, 'parentId')->dropDownList($model->parentsList()) ?>
<?= $form->field($model, 'title')->textInput(['maxlength' => true]) ?>
@ -43,7 +43,7 @@ $this->registerJs($js2);
</div>
<div class="box box-default">
<div class="box-header with-border"><?= Yii::t('page', 'SEO') ?></div>
<div class="box-header with-border"><?= Yii::t('pages', 'SEO') ?></div>
<div class="box-body">
<?= $form->field($model->meta, 'title')->textInput() ?>
<?= $form->field($model->meta, 'description')->textarea(['rows' => 2]) ?>
@ -59,9 +59,9 @@ $this->registerJs($js2);
<div class="col-md-2">
<div class="box box-default">
<div class="box-header with-border"><?= Yii::t('page', 'Publish') ?></div>
<div class="box-header with-border"><?= Yii::t('pages', 'Publish') ?></div>
<div class="box-body">
<?= Html::submitButton(Yii::t('page', 'Preview on site'), [
<?= Html::submitButton(Yii::t('pages', 'Preview on site'), [
'class' => 'btn btn-info',
'value'=>'preview',
'name'=>'submit_preview',

4
common/modules/pages/views/manage/page/create.php

@ -3,8 +3,8 @@
/* @var $this yii\web\View */
/* @var $model \common\modules\pages\forms\PageForm */
$this->title = Yii::t('page', 'Create Page');
$this->params['breadcrumbs'][] = ['label' => Yii::t('page', 'Pages'), 'url' => ['index']];
$this->title = Yii::t('pages', 'Create Page');
$this->params['breadcrumbs'][] = ['label' => Yii::t('pages', 'Pages'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="page-create">

4
common/modules/pages/views/manage/page/index.php

@ -9,13 +9,13 @@ use yii\grid\GridView;
/* @var $searchModel \common\modules\pages\forms\PageSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */
$this->title = Yii::t('page', 'Pages');
$this->title = Yii::t('pages', 'Pages');
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="user-index">
<p>
<?= Html::a(Yii::t('page','Create Page'), ['create'], ['class' => 'btn btn-success']) ?>
<?= Html::a(Yii::t('pages','Create Page'), ['create'], ['class' => 'btn btn-success']) ?>
</p>
<div class="box">

4
common/modules/pages/views/manage/page/update.php

@ -4,8 +4,8 @@
/* @var $page \common\modules\pages\entities\Page */
/* @var $model \common\modules\pages\forms\PageForm */
$this->title = Yii::t('page', 'Update Page: {name}', ['name' => $page->title]);
$this->params['breadcrumbs'][] = ['label' => Yii::t('page', 'Pages'), 'url' => ['index']];
$this->title = Yii::t('pages', 'Update Page: {name}', ['name' => $page->title]);
$this->params['breadcrumbs'][] = ['label' => Yii::t('pages', 'Pages'), 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => $page->title, 'url' => ['view', 'id' => $page->id]];
$this->params['breadcrumbs'][] = Yii::t('buttons', 'Editing');
?>

24
common/modules/pages/views/manage/page/view.php

@ -8,13 +8,13 @@ use yii\widgets\DetailView;
/* @var $history \common\modules\pages\entities\Page[] */
$this->title = $page->title;
$this->params['breadcrumbs'][] = ['label' => Yii::t('page', 'Pages'), 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => Yii::t('pages', 'Pages'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="user-view">
<p>
<?= Html::a(Yii::t('page','Pages'), ['index'], ['class' => 'btn btn-default']) ?>
<?= Html::a(Yii::t('pages','Pages'), ['index'], ['class' => 'btn btn-default']) ?>
<?= Html::a(Yii::t('buttons', 'Edit'), ['update', 'id' => $page->id], ['class' => 'btn btn-primary']) ?>
<?= Html::a(Yii::t('buttons', 'Delete'), ['delete', 'id' => $page->id], [
'class' => 'btn btn-danger',
@ -29,7 +29,7 @@ $this->params['breadcrumbs'][] = $this->title;
<div class="col-md-9">
<div class="box">
<div class="box-header with-border"><?= Yii::t('page', 'Common') ?></div>
<div class="box-header with-border"><?= Yii::t('pages', 'Common') ?></div>
<div class="box-body">
<?= DetailView::widget([
'model' => $page,
@ -43,7 +43,7 @@ $this->params['breadcrumbs'][] = $this->title;
</div>
<div class="box">
<div class="box-header with-border"><?= Yii::t('page', 'Content') ?></div>
<div class="box-header with-border"><?= Yii::t('pages', 'Content') ?></div>
<div class="box-body">
<?= Yii::$app->formatter->asHtml($page->content, [
'Attr.AllowedRel' => array('nofollow'),
@ -56,7 +56,7 @@ $this->params['breadcrumbs'][] = $this->title;
</div>
<div class="box">
<div class="box-header with-border"><?= Yii::t('page', 'SEO') ?></div>
<div class="box-header with-border"><?= Yii::t('pages', 'SEO') ?></div>
<div class="box-body">
<?= DetailView::widget([
'model' => $page,
@ -82,7 +82,7 @@ $this->params['breadcrumbs'][] = $this->title;
<div class="col-md-3">
<div class="box">
<div class="box-header with-border"><?= Yii::t('page', 'History') ?></div>
<div class="box-header with-border"><?= Yii::t('pages', 'History') ?></div>
<div class="box-body">
<?php if ($history): ?>
@ -100,30 +100,30 @@ $this->params['breadcrumbs'][] = $this->title;
|
<?= Html::a(Yii::t('page', 'Restore'), ['/pages/manage/page/restore-history', 'id' => $item->id], [
<?= Html::a(Yii::t('pages', 'Restore'), ['/pages/manage/page/restore-history', 'id' => $item->id], [
'style' => 'font-size:11px; color: red',
'data' => [
'confirm' => Yii::t('page', 'Are you sure you want to restore this history item?'),
'confirm' => Yii::t('pages', 'Are you sure you want to restore this history item?'),
'method' => 'post',
],
]) ?>
<?php else: ?>
<strong><?= Yii::t('page', 'Current Edition') ?></strong>
<strong><?= Yii::t('pages', 'Current Edition') ?></strong>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
<?= Html::a(Yii::t('page', 'Clear History'), ['/pages/manage/page/clear-history', 'id' => $page->id], [
<?= Html::a(Yii::t('pages', 'Clear History'), ['/pages/manage/page/clear-history', 'id' => $page->id], [
'class' => 'btn btn-danger btn-sm pull-right',
'data' => [
'confirm' => Yii::t('page', 'Are you sure you want to remove this history?'),
'confirm' => Yii::t('pages', 'Are you sure you want to remove this history?'),
'method' => 'post',
],
]) ?>
<?php else: ?>
<div style="padding: 20px 0; text-align: center"><?= Yii::t('page', 'History is empty') ?></div>
<div style="padding: 20px 0; text-align: center"><?= Yii::t('pages', 'History is empty') ?></div>
<?php endif; ?>
</div>

6
common/modules/pages/widgets/MenuItemCreatorWidget.php

@ -16,9 +16,9 @@ class MenuItemCreatorWidget extends Widget
public function run()
{
$form = new MenuItemForm();
$form->module = \Yii::t('page', 'Pages');
$form->name = \Yii::t('page', 'Pages');
$form->title_attr = \Yii::t('page', 'Pages');
$form->module = \Yii::t('pages', 'Pages');
$form->name = \Yii::t('pages', 'Pages');
$form->title_attr = \Yii::t('pages', 'Pages');
$form->menu_id = $this->menu_id;
$form->url = '/pages/page/index';

6
common/modules/pages/widgets/views/menu-item/creator.php

@ -14,8 +14,8 @@ use yii\helpers\Html;
use yii\web\JsExpression;
use yii\helpers\Url;
$block_name = Yii::t('page', 'Pages');
$block_title_attr = Yii::t('page', 'Pages');
$block_name = Yii::t('pages', 'Pages');
$block_title_attr = Yii::t('pages', 'Pages');
$js = <<<JS
function updatePagesUrl() {
@ -41,7 +41,7 @@ $fetchUrl = Url::to( [ '/pages/manage/page/page-search' ] );
'name' => 'page_select',
'value' => '',
'options' => [
'placeholder' => Yii::t('page', 'Select page...'),
'placeholder' => Yii::t('pages', 'Select page...'),
'id' => 'page_select',
'onchange' => new JsExpression("updatePagesUrl()"),
],

90
core/components/modules/ModuleManager.php

@ -0,0 +1,90 @@
<?php
/**
* Created by Error202
* Date: 20.08.2018
*/
namespace core\components\modules;
use core\entities\ModuleRecord;
use core\services\ModuleService;
use Yii;
use yii\helpers\FileHelper;
class ModuleManager
{
public $moduleNames = [];
public $modules = [];
private $service;
public function __construct(ModuleService $service)
{
$this->service = $service;
}
public function appendToMigrationTable($name) {
$time = time();
$connection = Yii::$app->getDb();
$command = $connection->createCommand("INSERT INTO migration (version, apply_time) VALUE ('$name', '$time')");
$command->execute();
}
public function removeFromMigrationTable($name) {
$connection = Yii::$app->getDb();
$command = $connection->createCommand("DELETE FROM migration WHERE version = '$name'");
$command->execute();
}
public function getModules()
{
$modules = [];
$localModules = $this->getLocalModules();
foreach ($localModules as $local_module) {
if (!$db_module = ModuleRecord::find()->andWhere(['name' => $local_module['name']])->one()) {
$db_module = $this->service->create($local_module['name'], "common\\modules\\".$local_module['name']."\\" . $local_module['module']);
$db_module->description = $local_module['description'];
$modules[] = $db_module;
}
else {
$db_module->description = $local_module['description'];
$modules[] = $db_module;
}
}
return $modules;
}
public function getLocalModules()
{
$this->_getLocalModulesNames();
if (empty($this->modules)) {
foreach ( $this->moduleNames as $module_name ) {
$manifest = Yii::getAlias( '@common/modules/' . $module_name . '/manifest.php' );
if ( file_exists( $manifest ) ) {
$this->modules[] = require $manifest;
}
}
}
return $this->modules;
}
private function _getLocalModulesNames(): void
{
if (!empty($this->moduleNames)) {
return;
}
$names = [];
$modulePath = Yii::getAlias('@common/modules');
$modules = file_exists($modulePath) ? FileHelper::findDirectories($modulePath, [
'recursive' => false,
]) : [];
foreach ($modules as $module) {
$module = basename($module);
$names[] = $module;
}
$this->moduleNames = $names;
}
}

15
core/entities/ModuleRecord.php

@ -16,6 +16,11 @@ use core\entities\queries\ModuleRecordQuery;
*/
class ModuleRecord extends \yii\db\ActiveRecord
{
const STATUS_ENABLED = 1;
const STATUS_DISABLED = 0;
public $description;
/**
* @inheritdoc
*/
@ -50,6 +55,16 @@ class ModuleRecord extends \yii\db\ActiveRecord
];
}
public function isEnabled(): bool
{
return $this->active == $this::STATUS_ENABLED;
}
public function isDisabled(): bool
{
return $this->active == $this::STATUS_DISABLED;
}
public static function find(): ModuleRecordQuery
{
return new ModuleRecordQuery(static::class);

6
core/entities/user/User.php

@ -181,7 +181,7 @@ class User extends ActiveRecord implements AggregateRoot
public function getNetworks(): ActiveQuery
{
return $this->hasMany(Network::className(), ['user_id' => 'id']);
return $this->hasMany(Network::class, ['user_id' => 'id']);
}
/**
@ -198,9 +198,9 @@ class User extends ActiveRecord implements AggregateRoot
public function behaviors()
{
return [
TimestampBehavior::className(),
TimestampBehavior::class,
[
'class' => SaveRelationsBehavior::className(),
'class' => SaveRelationsBehavior::class,
'relations' => ['networks'],
],
];

25
core/helpers/ModuleHelper.php

@ -0,0 +1,25 @@
<?php
/**
* Created by Error202
* Date: 18.08.2018
*/
namespace core\helpers;
use yii\helpers\ArrayHelper;
use Yii;
class ModuleHelper
{
// add module translation without load module
public static function addModuleAdminTranslation($module_name)
{
Yii::$app->getI18n()->translations = ArrayHelper::merge(Yii::$app->getI18n()->translations, [
$module_name => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@common/modules/' . $module_name . '/messages',
],
]);
}
}

30
core/repositories/ModuleRepository.php

@ -0,0 +1,30 @@
<?php
namespace core\repositories;
use core\entities\ModuleRecord;
class ModuleRepository
{
public function get($id): ModuleRecord
{
if (!$module = ModuleRecord::findOne($id)) {
throw new NotFoundException('Module is not found.');
}
return $module;
}
public function save(ModuleRecord $module): void
{
if (!$module->save()) {
throw new \RuntimeException('Saving error.');
}
}
public function remove(ModuleRecord $module): void
{
if (!$module->delete()) {
throw new \RuntimeException('Removing error.');
}
}
}

109
core/services/ModuleService.php

@ -0,0 +1,109 @@
<?php
namespace core\services;
use core\entities\ModuleRecord;
use core\repositories\ModuleRepository;
use yii\helpers\FileHelper;
use Yii;
class ModuleService
{
private $modules;
public function __construct(ModuleRepository $modules)
{
$this->modules = $modules;
}
public function create($name, $class, $type = 'common', $active = ModuleRecord::STATUS_DISABLED): ModuleRecord
{
$module = new ModuleRecord();
$module->name = $name;
$module->class = $class;
$module->type = $type;
$module->active = $active;
$this->modules->save($module);
return $module;
}
public function delete(ModuleRecord $module)
{
$migrations = $this->getMigrationFiles($module->name);
$migrations = array_reverse($migrations);
foreach ($migrations as $migrationPath) {
$migrationFile = basename($migrationPath);
$migration = str_replace('.php', '', $migrationFile);
if ($this->migrationExists($migration)) {
require $migrationPath;
$obj = new $migration;
if (method_exists($obj, 'safeDown')) {
$obj->safeDown();
Yii::$app->moduleManager->removeFromMigrationTable($migration);
}
elseif (method_exists($obj, 'down')) {
$obj->down();
Yii::$app->moduleManager->removeFromMigrationTable($migration);
}
}
}
// delete files
$modulePath = Yii::getAlias('@common/modules/' . $module->name);
if (file_exists($modulePath)) {
FileHelper::removeDirectory($modulePath);
}
// delete module record
$this->modules->remove($module);
}
public function disable(ModuleRecord $module)
{
$module->active = ModuleRecord::STATUS_DISABLED;
$this->modules->save($module);
}
public function enable(ModuleRecord $module)
{
$module->active = ModuleRecord::STATUS_ENABLED;
// migration if not exists
$migrations = $this->getMigrationFiles($module->name);
foreach ($migrations as $migrationPath) {
$migrationFile = basename($migrationPath);
$migration = str_replace('.php', '', $migrationFile);
if (!$this->migrationExists($migration)) {
// run migration
require $migrationPath;
$obj = new $migration;
if (method_exists($obj, 'safeUp')) {
$obj->safeUp();
Yii::$app->moduleManager->appendToMigrationTable($migration);
}
elseif (method_exists($obj, 'up')) {
$obj->up();
Yii::$app->moduleManager->appendToMigrationTable($migration);
}
}
}
$this->modules->save($module);
}
private function getMigrationFiles($module)
{
// migration if not exists
$migrationPath = Yii::getAlias('@common/modules/' . $module . '/migrations');
return file_exists($migrationPath) ? FileHelper::findFiles($migrationPath) : [];
}
private function migrationExists($name): bool
{
// check record exists
$connection = Yii::$app->getDb();
$command = $connection->createCommand("SELECT * FROM migration WHERE version = '$name'");
$result = $command->queryAll();
return $result ? true : false;
}
}

13
frontend/tests/_data/login_data.php

@ -1,13 +0,0 @@
<?php
return [
[
'username' => 'erau',
'auth_key' => 'tUu1qHcde0diwUol3xeI-18MuHkkprQI',
// password_0
'password_hash' => '$2y$13$nJ1WDlBaGcbCdbNC5.5l4.sgy.OMEKCqtDQOdQ2OWpgiKRWYyzzne',
'password_reset_token' => 'RkD_Jw0_8HEedzLk7MM-ZKEFfYR7VbMr_1392559490',
'created_at' => '1392559490',
'updated_at' => '1392559490',
'email' => 'sfriesen@jenkins.info',
],
];

23
frontend/tests/_data/user.php

@ -1,23 +0,0 @@
<?php
return [
[
'username' => 'okirlin',
'auth_key' => 'iwTNae9t34OmnK6l4vT4IeaTk-YWI2Rv',
'password_hash' => '$2y$13$CXT0Rkle1EMJ/c1l5bylL.EylfmQ39O5JlHJVFpNn618OUS1HwaIi',
'password_reset_token' => 't5GU9NwpuGYSfb7FEZMAxqtuz2PkEvv_' . time(),
'created_at' => '1391885313',
'updated_at' => '1391885313',
'email' => 'brady.renner@rutherford.com',
],
[
'username' => 'troy.becker',
'auth_key' => 'EdKfXrx88weFMV0vIxuTMWKgfK2tS3Lp',
'password_hash' => '$2y$13$g5nv41Px7VBqhS3hVsVN2.MKfgT3jFdkXEsMC4rQJLfaMa7VaJqL2',
'password_reset_token' => '4BSNyiZNAuxjs5Mty990c47sVrgllIi_' . time(),
'created_at' => '1391885313',
'updated_at' => '1391885313',
'email' => 'nicolas.dianna@hotmail.com',
'status' => '0',
],
];

20
frontend/tests/acceptance/HomeCest.php

@ -1,20 +0,0 @@
<?php
namespace frontend\tests\acceptance;
use frontend\tests\AcceptanceTester;
use yii\helpers\Url;
class HomeCest
{
public function checkHome(AcceptanceTester $I)
{
$I->amOnPage(Url::toRoute('/site/index'));
$I->see('My Application');
$I->seeLink('About');
$I->click('About');
$I->wait(2); // wait for page to be opened
$I->see('This is the About page.');
}
}

15
frontend/tests/fixtures/UserFixture.php vendored

@ -0,0 +1,15 @@
<?php
/**
* Created by Error202
* Date: 13.08.2018
*/
namespace frontend\tests\fixtures;
use yii\test\ActiveFixture;
class UserFixture extends ActiveFixture
{
public $modelClass = 'core\entites\user\User';
}

43
frontend/tests/fixtures/data/user.php vendored

@ -0,0 +1,43 @@
<?php
return [
'user1' => [
"id" => 1,
"username" => "Error202",
"auth_key" => "I4MJAUm8ZZ4rennRmwhjfeZ7xV2-FpYn",
"password_hash" => "$2y$13$53Y5IhwZyUkvLirp.qq.o.J0XRDOPRFVCbkHSzYXKVb6.DbdM9uYy",
"password_reset_token" => null,
"email" => "error-202@mail.ru",
"email_confirm_token" => null,
"status" => 10,
"created_at" => 1516021751,
"updated_at" => 1530816306,
"user_pic" => "avatar_e188db6330ceab81865b3996f7bbb3d6_300.png"
],
'user2' => [
"id" => 17,
"username" => "Error203",
"auth_key" => "wW7PWDP0yUvGVzEqy3dZepb0tj19ejv6",
"password_hash" => '$2y$13$Spf7/iHOj3aJARSORST4s.blouBXtUPLzMf7sD4AX9akSK1URGkfe',
"password_reset_token" => null,
"email" => "error-202@yandex.ru",
"email_confirm_token" => null,
"status" => 10,
"created_at" => 1518122129,
"updated_at" => 1518127758,
"user_pic" => null
],
'user3' => [
"id" => 18,
"username" => "zz",
"auth_key" => "JbLkAlfA7jQ0XxbaWxUEPWQCzsVZ9gn8",
"password_hash" => '$2y$13$gyDo.ax9O962rq9pfh6sX.ZHrZ05cTZNAaX8VEMBL7n6UPsMr/vHa',
"password_reset_token" => null,
"email" => "zz@morework.ru",
"email_confirm_token" => "AcNTOgIMhefCq5tQaOyUqEIeIPLFqFdY",
"status" => 0,
"created_at" => 1518157352,
"updated_at" => 1518157352,
"user_pic" => null
],
];

13
frontend/tests/functional/AboutCest.php

@ -1,13 +0,0 @@
<?php
namespace frontend\tests\functional;
use frontend\tests\FunctionalTester;
class AboutCest
{
public function checkAbout(FunctionalTester $I)
{
$I->amOnRoute('site/about');
$I->see('About', 'h1');
}
}

59
frontend/tests/functional/ContactCest.php

@ -1,59 +0,0 @@
<?php
namespace frontend\tests\functional;
use frontend\tests\FunctionalTester;
/* @var $scenario \Codeception\Scenario */
class ContactCest
{
public function _before(FunctionalTester $I)
{
$I->amOnPage(['site/contact']);
}
public function checkContact(FunctionalTester $I)
{
$I->see('Contact', 'h1');
}
public function checkContactSubmitNoData(FunctionalTester $I)
{
$I->submitForm('#contact-form', []);
$I->see('Contact', 'h1');
$I->seeValidationError('Name cannot be blank');
$I->seeValidationError('Email cannot be blank');
$I->seeValidationError('Subject cannot be blank');
$I->seeValidationError('Body cannot be blank');
$I->seeValidationError('The verification code is incorrect');
}
public function checkContactSubmitNotCorrectEmail(FunctionalTester $I)
{
$I->submitForm('#contact-form', [
'ContactForm[name]' => 'tester',
'ContactForm[email]' => 'tester.email',
'ContactForm[subject]' => 'test subject',
'ContactForm[body]' => 'test content',
'ContactForm[verifyCode]' => 'testme',
]);
$I->seeValidationError('Email is not a valid email address.');
$I->dontSeeValidationError('Name cannot be blank');
$I->dontSeeValidationError('Subject cannot be blank');
$I->dontSeeValidationError('Body cannot be blank');
$I->dontSeeValidationError('The verification code is incorrect');
}
public function checkContactSubmitCorrectData(FunctionalTester $I)
{
$I->submitForm('#contact-form', [
'ContactForm[name]' => 'tester',
'ContactForm[email]' => 'tester@example.com',
'ContactForm[subject]' => 'test subject',
'ContactForm[body]' => 'test content',
'ContactForm[verifyCode]' => 'testme',
]);
$I->seeEmailIsSent();
$I->see('Thank you for contacting us. We will respond to you as soon as possible.');
}
}

17
frontend/tests/functional/HomeCest.php

@ -1,17 +0,0 @@
<?php
namespace frontend\tests\functional;
use frontend\tests\FunctionalTester;
class HomeCest
{
public function checkOpen(FunctionalTester $I)
{
$I->amOnPage(\Yii::$app->homeUrl);
$I->see('My Application');
$I->seeLink('About');
$I->click('About');
$I->see('This is the About page.');
}
}

60
frontend/tests/functional/LoginCest.php

@ -1,60 +0,0 @@
<?php
namespace frontend\tests\functional;
use frontend\tests\FunctionalTester;
use common\fixtures\UserFixture;
class LoginCest
{
/**
* Load fixtures before db transaction begin
* Called in _before()
* @see \Codeception\Module\Yii2::_before()
* @see \Codeception\Module\Yii2::loadFixtures()
* @return array
*/
public function _fixtures()
{
return [
'user' => [
'class' => UserFixture::className(),
'dataFile' => codecept_data_dir() . 'login_data.php'
]
];
}
public function _before(FunctionalTester $I)
{
$I->amOnRoute('site/login');
}
protected function formParams($login, $password)
{
return [
'LoginForm[username]' => $login,
'LoginForm[password]' => $password,
];
}
public function checkEmpty(FunctionalTester $I)
{
$I->submitForm('#login-form', $this->formParams('', ''));
$I->seeValidationError('Username cannot be blank.');
$I->seeValidationError('Password cannot be blank.');
}
public function checkWrongPassword(FunctionalTester $I)
{
$I->submitForm('#login-form', $this->formParams('admin', 'wrong'));
$I->seeValidationError('Incorrect username or password.');
}
public function checkValidLogin(FunctionalTester $I)
{
$I->submitForm('#login-form', $this->formParams('erau', 'password_0'));
$I->see('Logout (erau)', 'form button[type=submit]');
$I->dontSeeLink('Login');
$I->dontSeeLink('Signup');
}
}

57
frontend/tests/functional/SignupCest.php

@ -1,57 +0,0 @@
<?php
namespace frontend\tests\functional;
use frontend\tests\FunctionalTester;
class SignupCest
{
protected $formId = '#form-signup';
public function _before(FunctionalTester $I)
{
$I->amOnRoute('site/signup');
}
public function signupWithEmptyFields(FunctionalTester $I)
{
$I->see('Signup', 'h1');
$I->see('Please fill out the following fields to signup:');
$I->submitForm($this->formId, []);
$I->seeValidationError('Username cannot be blank.');
$I->seeValidationError('Email cannot be blank.');
$I->seeValidationError('Password cannot be blank.');
}
public function signupWithWrongEmail(FunctionalTester $I)
{
$I->submitForm(
$this->formId, [
'SignupForm[username]' => 'tester',
'SignupForm[email]' => 'ttttt',
'SignupForm[password]' => 'tester_password',
]
);
$I->dontSee('Username cannot be blank.', '.help-block');
$I->dontSee('Password cannot be blank.', '.help-block');
$I->see('Email is not a valid email address.', '.help-block');
}
public function signupSuccessfully(FunctionalTester $I)
{
$I->submitForm($this->formId, [
'SignupForm[username]' => 'tester',
'SignupForm[email]' => 'tester.email@example.com',
'SignupForm[password]' => 'tester_password',
]);
$I->seeRecord('common\models\User', [
'username' => 'tester',
'email' => 'tester.email@example.com',
]);
$I->see('Logout (tester)', 'form button[type=submit]');
}
}

41
frontend/tests/unit/UserTest.php

@ -0,0 +1,41 @@
<?php
/**
* Created by Error202
* Date: 13.08.2018
*/
namespace frontend\tests\unit;
use Codeception\Test\Unit;
use frontend\tests\UnitTester;
use frontend\tests\fixtures\UserFixture;
class UserTest extends Unit
{
/**
* @var UnitTester
*/
protected $tester;
public function _fixtures()
{
return [
'users' => UserFixture::class,
];
}
protected function _before() {
}
protected function _after() {
}
// test
public function testTest()
{
$user = $this->tester->grabFixture('users', 'user1');
}
}

32
frontend/tests/unit/models/ContactFormTest.php

@ -1,32 +0,0 @@
<?php
namespace frontend\tests\unit\models;
use Yii;
use frontend\models\ContactForm;
class ContactFormTest extends \Codeception\Test\Unit
{
public function testSendEmail()
{
$model = new ContactForm();
$model->attributes = [
'name' => 'Tester',
'email' => 'tester@example.com',
'subject' => 'very important letter subject',
'body' => 'body of current message',
];
expect_that($model->sendEmail('admin@example.com'));
// using Yii2 module actions to check email was sent
$this->tester->seeEmailIsSent();
$emailMessage = $this->tester->grabLastSentEmail();
expect('valid email is sent', $emailMessage)->isInstanceOf('yii\mail\MessageInterface');
expect($emailMessage->getTo())->hasKey('admin@example.com');
expect($emailMessage->getFrom())->hasKey('tester@example.com');
expect($emailMessage->getSubject())->equals('very important letter subject');
expect($emailMessage->toString())->contains('body of current message');
}
}

59
frontend/tests/unit/models/PasswordResetRequestFormTest.php

@ -1,59 +0,0 @@
<?php
namespace frontend\tests\unit\models;
use Yii;
use frontend\models\PasswordResetRequestForm;
use common\fixtures\UserFixture as UserFixture;
use common\models\User;
class PasswordResetRequestFormTest extends \Codeception\Test\Unit
{
/**
* @var \frontend\tests\UnitTester
*/
protected $tester;
public function _before()
{
$this->tester->haveFixtures([
'user' => [
'class' => UserFixture::className(),
'dataFile' => codecept_data_dir() . 'user.php'
]
]);
}
public function testSendMessageWithWrongEmailAddress()
{
$model = new PasswordResetRequestForm();
$model->email = 'not-existing-email@example.com';
expect_not($model->sendEmail());
}
public function testNotSendEmailsToInactiveUser()
{
$user = $this->tester->grabFixture('user', 1);
$model = new PasswordResetRequestForm();
$model->email = $user['email'];
expect_not($model->sendEmail());
}
public function testSendEmailSuccessfully()
{
$userFixture = $this->tester->grabFixture('user', 0);
$model = new PasswordResetRequestForm();
$model->email = $userFixture['email'];
$user = User::findOne(['password_reset_token' => $userFixture['password_reset_token']]);
expect_that($model->sendEmail());
expect_that($user->password_reset_token);
$emailMessage = $this->tester->grabLastSentEmail();
expect('valid email is sent', $emailMessage)->isInstanceOf('yii\mail\MessageInterface');
expect($emailMessage->getTo())->hasKey($model->email);
expect($emailMessage->getFrom())->hasKey(Yii::$app->params['supportEmail']);
}
}

44
frontend/tests/unit/models/ResetPasswordFormTest.php

@ -1,44 +0,0 @@
<?php
namespace frontend\tests\unit\models;
use common\fixtures\UserFixture;
use frontend\models\ResetPasswordForm;
class ResetPasswordFormTest extends \Codeception\Test\Unit
{
/**
* @var \frontend\tests\UnitTester
*/
protected $tester;
public function _before()
{
$this->tester->haveFixtures([
'user' => [
'class' => UserFixture::className(),
'dataFile' => codecept_data_dir() . 'user.php'
],
]);
}
public function testResetWrongToken()
{
$this->tester->expectException('yii\base\InvalidParamException', function() {
new ResetPasswordForm('');
});
$this->tester->expectException('yii\base\InvalidParamException', function() {
new ResetPasswordForm('notexistingtoken_1391882543');
});
}
public function testResetCorrectToken()
{
$user = $this->tester->grabFixture('user', 0);
$form = new ResetPasswordForm($user['password_reset_token']);
expect_that($form->resetPassword());
}
}

59
frontend/tests/unit/models/SignupFormTest.php

@ -1,59 +0,0 @@
<?php
namespace frontend\tests\unit\models;
use common\fixtures\UserFixture;
use frontend\models\SignupForm;
class SignupFormTest extends \Codeception\Test\Unit
{
/**
* @var \frontend\tests\UnitTester
*/
protected $tester;
public function _before()
{
$this->tester->haveFixtures([
'user' => [
'class' => UserFixture::className(),
'dataFile' => codecept_data_dir() . 'user.php'
]
]);
}
public function testCorrectSignup()
{
$model = new SignupForm([
'username' => 'some_username',
'email' => 'some_email@example.com',
'password' => 'some_password',
]);
$user = $model->signup();
expect($user)->isInstanceOf('common\models\User');
expect($user->username)->equals('some_username');
expect($user->email)->equals('some_email@example.com');
expect($user->validatePassword('some_password'))->true();
}
public function testNotCorrectSignup()
{
$model = new SignupForm([
'username' => 'troy.becker',
'email' => 'nicolas.dianna@hotmail.com',
'password' => 'some_password',
]);
expect_not($model->signup());
expect_that($model->getErrors('username'));
expect_that($model->getErrors('email'));
expect($model->getFirstError('username'))
->equals(\Yii::t('auth', 'This username has already been taken.'));
expect($model->getFirstError('email'))
->equals(\Yii::t('auth', 'This email address has already been taken.'));
}
}
Loading…
Cancel
Save