diff --git a/backend/bootstrap/SetUp.php b/backend/bootstrap/SetUp.php index 52a5c5a..7d75215 100644 --- a/backend/bootstrap/SetUp.php +++ b/backend/bootstrap/SetUp.php @@ -39,6 +39,7 @@ class SetUp implements BootstrapInterface 'editorOptions' => ElFinder::ckeditorOptions('elfinder', [ 'toolbar' => $app->params['ckeditor']['editor']['toolbar'], 'extraPlugins' => $app->params['ckeditor']['editor']['plugins'], + 'language' => $app->language, ]), ]); diff --git a/backend/controllers/AuthController.php b/backend/controllers/AuthController.php index fd79029..67bf23b 100644 --- a/backend/controllers/AuthController.php +++ b/backend/controllers/AuthController.php @@ -26,7 +26,7 @@ class AuthController extends Controller { return [ 'access' => [ - 'class' => AccessControl::className(), + 'class' => AccessControl::class, 'rules' => [ [ 'actions' => ['login'], @@ -45,7 +45,7 @@ class AuthController extends Controller ], ], 'verbs' => [ - 'class' => VerbFilter::className(), + 'class' => VerbFilter::class, 'actions' => [ 'logout' => ['post'], ], diff --git a/backend/controllers/MenuController.php b/backend/controllers/MenuController.php index 74f3cf2..66a4d2a 100644 --- a/backend/controllers/MenuController.php +++ b/backend/controllers/MenuController.php @@ -40,11 +40,6 @@ class MenuController extends Controller 'class' => AccessControl::class, 'rules' => [ [ - 'actions' => [ - 'create', 'update', 'delete', 'index', 'save-menu-items', - 'delete-menu-item', - 'save-item' - ], 'allow' => true, 'roles' => ['MenuManagement'], ], diff --git a/backend/controllers/SliderController.php b/backend/controllers/SliderController.php index a2df221..9321d2b 100644 --- a/backend/controllers/SliderController.php +++ b/backend/controllers/SliderController.php @@ -44,7 +44,7 @@ class SliderController extends Controller ], ], 'verbs' => [ - 'class' => VerbFilter::className(), + 'class' => VerbFilter::class, 'actions' => [ 'delete' => ['POST'], ], diff --git a/common/bootstrap/SetUp.php b/common/bootstrap/SetUp.php index ef7e85e..2492bb1 100644 --- a/common/bootstrap/SetUp.php +++ b/common/bootstrap/SetUp.php @@ -138,8 +138,25 @@ class SetUp implements BootstrapInterface $container->set(ImageUploadBehavior::class, FlySystemImageUploadBehavior::class); */ + // Set frontend languages + if (\Yii::$app->moduleManager->isTableExist('{{%languages}}') && file_exists(Yii::getAlias('@common/modules/languages/LanguagesModule.php'))) { + $language = Language::find()->active()->default()->one(); + Yii::$app->params['defaultLanguage'] = $language ? $language->name : 'ru'; + Yii::$app->params['translatedLanguages'] = ArrayHelper::map( Language::find()->active()->all(), 'name', 'title' ); + } + else { + Yii::$app->params['defaultLanguage'] = 'en'; + Yii::$app->params['translatedLanguages'] = ['en']; + } + + // Set backend languages + if (basename($app->getBasePath()) === 'backend') { + $app->language = ! $app->user->isGuest && $app->user->identity->user->backend_language ? $app->user->identity->user->backend_language : Yii::$app->params['defaultLanguage']; + $app->params['frontendLanguage'] = Yii::$app->session->get('frontendLanguage', Yii::$app->params['defaultLanguage']); + } + // Connect common modules - if (Yii::$app->db->schema->getTableSchema('{{%modules}}') !== null) { + if (\Yii::$app->moduleManager->isTableExist('{{%modules}}')) { $modules = ModuleRecord::find()->andWhere(['type' => 'common'])->andWhere(['active' => 1])->all(); foreach ($modules as $module) { Yii::$app->setModule($module->name, [ @@ -148,16 +165,20 @@ class SetUp implements BootstrapInterface Yii::$app->getModule($module->name)->bootstrap(Yii::$app); } } - - // Set frontend languages - $language = Language::find()->active()->default()->one(); - Yii::$app->params['defaultLanguage'] = $language ? $language->name : 'ru'; - Yii::$app->params['translatedLanguages'] = ArrayHelper::map(Language::find()->active()->all(), 'name', 'title'); - - // Set backend languages - if (basename($app->getBasePath()) === 'backend') { - $app->language = ! $app->user->isGuest && $app->user->identity->user->backend_language ? $app->user->identity->user->backend_language : $app->language; - $app->params['frontendLanguage'] = Yii::$app->session->get('frontendLanguage', Yii::$app->params['defaultLanguage']); + else { // connect all existing modules + $this->connectExistingModules(); } } + + private function connectExistingModules(): void + { + $modules = Yii::$app->moduleManager->getLocalModules(); + //print_r($modules); die; + foreach ($modules as $module) { + Yii::$app->setModule($module['name'], [ + 'class' => 'common\modules\\' . $module['name'] . '\\' . $module['module'], + ]); + Yii::$app->getModule( $module['name'] )->bootstrap( Yii::$app ); + } + } } \ No newline at end of file diff --git a/common/codeception.yml b/common/codeception.yml index de5d76a..ce69f48 100644 --- a/common/codeception.yml +++ b/common/codeception.yml @@ -13,3 +13,8 @@ modules: config: Yii2: configFile: 'config/test-local.php' +coverage: + enabled: true + include: + - ../models/pages/entites/* + - ../modules/pages/controllers/* diff --git a/common/modules/blog/BlogModule.php b/common/modules/blog/BlogModule.php index 0ca7c56..10197cd 100644 --- a/common/modules/blog/BlogModule.php +++ b/common/modules/blog/BlogModule.php @@ -31,7 +31,7 @@ class BlogModule extends \yii\base\Module implements ModuleInterface $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}}"; + $app->params['search_rules'][] = "SELECT title, content, CONCAT('/blog/manage/post/view/', blog_post_id) AS url FROM {{blog_posts_lng}}"; // add rules $app->getUrlManager()->addRules([ diff --git a/common/modules/blog/controllers/PostController.php b/common/modules/blog/controllers/PostController.php index c4e3f39..fd226ce 100644 --- a/common/modules/blog/controllers/PostController.php +++ b/common/modules/blog/controllers/PostController.php @@ -233,12 +233,15 @@ class PostController extends FrontendController return ''; }*/ - public function actionPreview($id) + public function actionPreview($id, $language = '') { - if (!$post = $this->posts->findPreview($id)) { + if (!$post = $this->posts->findPreview($id, $language)) { throw new NotFoundHttpException('The requested page does not exist.'); } + /*if ($language) { + Yii::$app->language = $language; + }*/ return $this->render('post', [ 'post' => $post, ]); diff --git a/common/modules/blog/controllers/manage/CategoryController.php b/common/modules/blog/controllers/manage/CategoryController.php index e813c4b..ac22b18 100644 --- a/common/modules/blog/controllers/manage/CategoryController.php +++ b/common/modules/blog/controllers/manage/CategoryController.php @@ -7,6 +7,7 @@ use common\modules\blog\forms\BlogCategoryForm; use common\modules\blog\forms\search\BlogCategorySearch; use common\modules\blog\services\BlogCategoryManageService; use Yii; +use yii\data\ActiveDataProvider; use yii\web\Controller; use yii\web\NotFoundHttpException; use yii\filters\VerbFilter; @@ -26,7 +27,7 @@ class CategoryController extends Controller { return [ 'access' => [ - 'class' => AccessControl::className(), + 'class' => AccessControl::class, 'rules' => [ [ 'allow' => true, @@ -39,7 +40,7 @@ class CategoryController extends Controller ], ], 'verbs' => [ - 'class' => VerbFilter::className(), + 'class' => VerbFilter::class, 'actions' => [ 'delete' => ['POST'], ], diff --git a/common/modules/blog/controllers/manage/CommentController.php b/common/modules/blog/controllers/manage/CommentController.php index 28f7651..90264b6 100644 --- a/common/modules/blog/controllers/manage/CommentController.php +++ b/common/modules/blog/controllers/manage/CommentController.php @@ -26,7 +26,7 @@ class CommentController extends Controller { return [ 'access' => [ - 'class' => AccessControl::className(), + 'class' => AccessControl::class, 'rules' => [ [ 'allow' => true, @@ -39,7 +39,7 @@ class CommentController extends Controller ], ], 'verbs' => [ - 'class' => VerbFilter::className(), + 'class' => VerbFilter::class, 'actions' => [ 'delete' => ['POST'], ], diff --git a/common/modules/blog/controllers/manage/PostController.php b/common/modules/blog/controllers/manage/PostController.php index 91b073c..5035491 100644 --- a/common/modules/blog/controllers/manage/PostController.php +++ b/common/modules/blog/controllers/manage/PostController.php @@ -92,7 +92,7 @@ class PostController extends Controller ]); } - public function actionCreatePreview($id = null) + public function actionCreatePreview($id = null, $language = '') { $this->service->removePreviews(); @@ -111,7 +111,7 @@ class PostController extends Controller copy($path . '/' . $real_post->id . '.' . $parts['extension'], $path . '/' . $post->id . '.' . $parts['extension']); } } - return $this->redirect(Url::to(Yii::$app->get('frontendUrlManager')->createAbsoluteUrl(['/blog/post/preview', 'id' => $post->id]))); + return $this->redirect(Url::to(Yii::$app->get('frontendUrlManager')->createAbsoluteUrl(['/blog/post/preview', 'id' => $post->id, 'language' => $language]))); } catch (\DomainException $e) { Yii::$app->errorHandler->logException($e); Yii::$app->session->setFlash('error', $e->getMessage()); @@ -151,6 +151,7 @@ class PostController extends Controller { $post = $this->findModel($id); $form = new BlogPostForm($post); + $form->published_at = date('d.m.Y H:i:s', $form->published_at); if ($form->load(Yii::$app->request->post()) && $form->validate()) { try { @@ -230,15 +231,40 @@ class PostController extends Controller \Yii::$app->response->format = Response::FORMAT_JSON; $out = ['results' => ['id' => '', 'text' => '']]; if (!is_null($q)) { - $data = BlogPost::find()->select('id, title as text')->andWhere(['like', 'title', $q])->limit(20)->asArray()->all(); + //$data = BlogPost::find()->select('id, title as text')->andWhere(['like', 'title', $q])->limit(20)->asArray()->all(); + //$out['results'] = array_values($data); + $data = []; + $posts = BlogPost::find() + ->with('translation') + ->leftJoin('{{%blog_posts_lng}}', '`blog_posts_lng`.`blog_post_id` = `blog_posts`.`id`') + ->andWhere(['like', 'blog_posts_lng.title', $q]) + ->limit(20) + ->all(); + + foreach ($posts as $post) { + $data[] = [ + 'id' => $post->id, + 'text' => isset($post->translation) ? $post->translation->title : null, + ]; + } $out['results'] = array_values($data); } elseif ($id > 0) { - $tag_name = BlogPost::findOne($id)->title; + $tag_name = BlogPost::findOne($id)->translation->title; $out['results'] = ['id' => $tag_name, 'text' => $tag_name]; } else { - $data = BlogPost::find()->select('id, title as text')->orderBy(['created_at' => SORT_DESC])->limit(20)->asArray()->all(); + //$data = BlogPost::find()->select('id, title as text')->orderBy(['created_at' => SORT_DESC])->limit(20)->asArray()->all(); + //$out['results'] = array_values($data); + $data = []; + $posts = BlogPost::find()->orderBy(['id' => SORT_DESC])->limit(20)->all(); + + foreach ($posts as $post) { + $data[] = [ + 'id' => $post->id, + 'text' => isset($post->translation) ? $post->translation->title : null, + ]; + } $out['results'] = array_values($data); } return $out; @@ -248,8 +274,8 @@ class PostController extends Controller { $post = $this->findModel($id); if ($post_id = $post->revision_id) { - $this->service->restoreHistory($id, $post->revision_id); - return $this->redirect(['/blog/manage/post/view', 'id' => $post_id]); + $new_id = $this->service->restoreHistory($id, $post->revision_id); + return $this->redirect(['/blog/manage/post/view', 'id' => $new_id]); } return $this->redirect(['/blog/manage/post/index']); } @@ -274,4 +300,12 @@ class PostController extends Controller } throw new NotFoundHttpException('The requested page does not exist.'); } + + protected function findLanguageModel($id) + { + if (($model = BlogPost::find()->multilingual()->andWhere(['id' => $id])->one()) !== null) { + return $model; + } + throw new NotFoundHttpException('The requested page does not exist.'); + } } diff --git a/common/modules/blog/controllers/manage/TagController.php b/common/modules/blog/controllers/manage/TagController.php index 780f276..d2dc23b 100644 --- a/common/modules/blog/controllers/manage/TagController.php +++ b/common/modules/blog/controllers/manage/TagController.php @@ -26,7 +26,7 @@ class TagController extends Controller { return [ 'access' => [ - 'class' => AccessControl::className(), + 'class' => AccessControl::class, 'rules' => [ [ 'allow' => true, @@ -39,7 +39,7 @@ class TagController extends Controller ], ], 'verbs' => [ - 'class' => VerbFilter::className(), + 'class' => VerbFilter::class, 'actions' => [ 'delete' => ['POST'], ], diff --git a/common/modules/blog/entities/BlogCategory.php b/common/modules/blog/entities/BlogCategory.php index 56189ca..08b59d5 100644 --- a/common/modules/blog/entities/BlogCategory.php +++ b/common/modules/blog/entities/BlogCategory.php @@ -2,47 +2,43 @@ namespace common\modules\blog\entities; -use core\behaviors\MetaBehavior; -use yii\behaviors\SluggableBehavior; -use core\entities\Meta; +use common\modules\blog\entities\queries\BlogCategoryQuery; +use core\behaviors\LanguageBehavior; +use core\behaviors\SluggableRelationBehavior; use yii\db\ActiveRecord; use Yii; /** * @property integer $id - * @property string $name * @property string $slug - * @property string $title - * @property string $description * @property integer $sort - * @property string $meta_json - * @property Meta $meta + * + * + * @method ActiveRecord findTranslation(string $language) + * @method void saveTranslations($translations) + * + * @property ActiveRecord[] translations + * @property ActiveRecord[] translation */ class BlogCategory extends ActiveRecord { - public $meta; + public $_form; - public static function create($name, $slug, $title, $description, $sort, Meta $meta): self + public static function create($form, $slug, $sort): self { $category = new static(); - $category->name = $name; $category->slug = $slug; - $category->title = $title; - $category->description = $description; $category->sort = $sort; - $category->meta = $meta; + $category->_form = $form; return $category; } - public function edit($name, $slug, $title, $description, $sort, Meta $meta): void + public function edit($form, $slug, $sort): void { - $this->name = $name; $this->slug = $slug; - $this->title = $title; - $this->description = $description; $this->sort = $sort; - $this->meta = $meta; + $this->_form = $form; } public function attributeLabels() @@ -54,20 +50,20 @@ class BlogCategory extends ActiveRecord 'sort' => Yii::t('blog', 'Sort'), 'title' => Yii::t('blog', 'Title'), 'description' => Yii::t('blog', 'Description'), - 'meta.title' => Yii::t('blog', 'Meta Title'), - 'meta.description' => Yii::t('blog', 'Meta Description'), - 'meta.keywords' => Yii::t('blog', 'Meta Keywords'), + 'meta_title' => Yii::t('blog', 'META Title'), + 'meta_description' => Yii::t('blog', 'META Description'), + 'meta_keywords' => Yii::t('blog', 'META Keywords'), ]; } public function getSeoTitle(): string { - return $this->meta->title ?: $this->getHeadingTile(); + return $this->translation->meta_title ?: $this->getHeadingTile(); } public function getHeadingTile(): string { - return $this->title ?: $this->name; + return $this->translation->title ?: $this->translation->name; } public function getPostsCount(): int @@ -83,13 +79,32 @@ class BlogCategory extends ActiveRecord public function behaviors(): array { return [ - MetaBehavior::class, - [ + /*[ 'class' => SluggableBehavior::class, 'attribute' => 'title', 'ensureUnique' => true, 'preserveNonEmptyValues' => true, + ],*/ + [ + 'class' => LanguageBehavior::class, + 'virtualClassName' => 'BlogCategoryVirtualTranslate', + 'translatedLanguages' => \Yii::$app->params['translatedLanguages'], + 'relativeField' => 'blog_category_id', + 'tableName' => "{{%blog_categories_lng}}", + 'attributes' => ['title', 'description', 'name', 'meta_title', 'meta_description', 'meta_keywords'], + //'defaultLanguage' => basename(Yii::$app->getBasePath()) === 'backend' ? Yii::$app->language : Yii::$app->params['defaultLanguage'], + 'defaultLanguage' => \Yii::$app->params['defaultLanguage'], + ], + [ + 'class' => SluggableRelationBehavior::class, + 'attribute' => 'name', + 'relation' => 'translation', ], ]; } + + public static function find(): BlogCategoryQuery + { + return new BlogCategoryQuery(static::class); + } } \ No newline at end of file diff --git a/common/modules/blog/entities/BlogPost.php b/common/modules/blog/entities/BlogPost.php index 4f2efc7..f6140d4 100644 --- a/common/modules/blog/entities/BlogPost.php +++ b/common/modules/blog/entities/BlogPost.php @@ -3,15 +3,14 @@ namespace common\modules\blog\entities; use common\modules\blog\entities\queries\BlogPostQuery; -use core\behaviors\MetaBehavior; -use core\entities\Meta; +use core\behaviors\LanguageBehavior; +use core\behaviors\SluggableRelationBehavior; use lhs\Yii2SaveRelationsBehavior\SaveRelationsBehavior; use yii\behaviors\TimestampBehavior; use yii\db\ActiveQuery; use yii\db\ActiveRecord; use yii\web\UploadedFile; use yiidreamteam\upload\ImageUploadBehavior; -use yii\behaviors\SluggableBehavior; use Yii; @@ -23,13 +22,9 @@ use Yii; * @property int $published_at * @property int $created_at * @property int $updated_at - * @property string $title - * @property string $description - * @property string $content * @property string $image * @property string $video * @property int $status - * @property string $meta_json * @property int $comments_count * @property int $views * @property string $slug @@ -37,6 +32,12 @@ use Yii; * @property int $revision_at * @property int $revision_id * + * @method ActiveRecord findTranslation(string $language) + * @method void saveTranslations($translations) + * + * @property ActiveRecord[] translations + * @property ActiveRecord[] translation + * * @property BlogComment[] $blogComments * @property BlogTagAssignment[] $blogTagAssignments * @property BlogTag[] $tags @@ -55,17 +56,13 @@ class BlogPost extends ActiveRecord const FILE_ORIGINAL_PATH = '@staticRoot/origin/posts'; - public $meta; + public $_form; - public static function create($categoryId, $title, $slug, $description, $content, $published_at, $video, $type = BlogPost::TYPE_PUBLIC, Meta $meta): self + public static function create($form, $categoryId, $slug, $published_at, $video, $type = BlogPost::TYPE_PUBLIC): self { $post = new static(); $post->category_id = $categoryId; - $post->title = $title; $post->slug = $slug; - $post->description = $description; - $post->content = $content; - $post->meta = $meta; $post->status = self::STATUS_DRAFT; $post->created_at = time(); $post->comments_count = 0; @@ -73,6 +70,7 @@ class BlogPost extends ActiveRecord $post->video = $video; $post->type = $type; $post->revision_at = time(); + $post->_form = $form; return $post; } @@ -82,18 +80,15 @@ class BlogPost extends ActiveRecord } - public function edit($categoryId, $title, $slug, $description, $content, $published_at, $video, $type = BlogPost::TYPE_PUBLIC, Meta $meta): void + public function edit($form, $categoryId, $slug, $published_at, $video, $type = BlogPost::TYPE_PUBLIC): void { $this->category_id = $categoryId; - $this->title = $title; $this->slug = $slug; - $this->description = $description; - $this->content = $content; - $this->meta = $meta; $this->published_at = $published_at; $this->video = $video; $this->type = $type; $this->revision_at = time(); + $this->_form = $form; } /** @@ -127,9 +122,9 @@ class BlogPost extends ActiveRecord 'comments_count' => Yii::t('blog', 'Comments Count'), 'views' => Yii::t('blog', 'Views'), 'slug' => Yii::t('blog', 'Slug'), - 'meta.title' => Yii::t('blog', 'Meta Title'), - 'meta.description' => Yii::t('blog', 'Meta Description'), - 'meta.keywords' => Yii::t('blog', 'Meta Keywords'), + 'meta_title' => Yii::t('blog', 'META Title'), + 'meta_description' => Yii::t('blog', 'META Description'), + 'meta_keywords' => Yii::t('blog', 'META Keywords'), ]; } @@ -162,7 +157,7 @@ class BlogPost extends ActiveRecord public function getSeoTitle(): string { - return $this->meta->title ?: $this->title; + return $this->translation->meta_title ?: $this->translation->title; } // Tags @@ -311,16 +306,30 @@ class BlogPost extends ActiveRecord { return [ TimestampBehavior::class, - MetaBehavior::class, [ 'class' => SaveRelationsBehavior::class, 'relations' => ['blogTagAssignments', 'blogComments'], ], - [ + /*[ 'class' => SluggableBehavior::class, 'attribute' => 'title', 'ensureUnique' => true, 'preserveNonEmptyValues' => true, + ],*/ + [ + 'class' => LanguageBehavior::class, + 'virtualClassName' => 'BlogVirtualTranslate', + 'translatedLanguages' => \Yii::$app->params['translatedLanguages'], + 'relativeField' => 'blog_post_id', + 'tableName' => "{{%blog_posts_lng}}", + 'attributes' => ['title', 'description', 'content', 'meta_title', 'meta_description', 'meta_keywords'], + //'defaultLanguage' => basename(Yii::$app->getBasePath()) === 'backend' ? Yii::$app->language : Yii::$app->params['defaultLanguage'], + 'defaultLanguage' => \Yii::$app->params['defaultLanguage'], + ], + [ + 'class' => SluggableRelationBehavior::class, + 'attribute' => 'title', + 'relation' => 'translation', ], [ // todo Image Sizes to settings or theme settings diff --git a/common/modules/blog/entities/BlogTagAssignment.php b/common/modules/blog/entities/BlogTagAssignment.php index bb9b4a1..adb6aee 100644 --- a/common/modules/blog/entities/BlogTagAssignment.php +++ b/common/modules/blog/entities/BlogTagAssignment.php @@ -32,6 +32,6 @@ class BlogTagAssignment extends ActiveRecord public function getTag(): ActiveQuery { - return $this->hasOne(BlogTag::className(), ['id' => 'tag_id']); + return $this->hasOne(BlogTag::class, ['id' => 'tag_id']); } } \ No newline at end of file diff --git a/common/modules/blog/entities/queries/BlogCategoryQuery.php b/common/modules/blog/entities/queries/BlogCategoryQuery.php new file mode 100644 index 0000000..a8d58c4 --- /dev/null +++ b/common/modules/blog/entities/queries/BlogCategoryQuery.php @@ -0,0 +1,15 @@ +name = $category->name; $this->slug = $category->slug; - $this->title = $category->title; - $this->description = $category->description; $this->sort = $category->sort; - $this->meta = new MetaForm($category->meta); $this->_category = $category; } else { - $this->meta = new MetaForm(); $this->sort = BlogCategory::find()->max('sort') + 1; } - parent::__construct($config); + parent::__construct($category, $attributes, $config); } public function rules(): array { - return [ - [['name'], 'required'], - [['name', 'slug', 'title'], 'string', 'max' => 255], - [['description'], 'string'], - ['slug', SlugValidator::class], - [['name', 'slug'], 'unique', 'targetClass' => BlogCategory::class, 'filter' => $this->_category ? ['<>', 'id', $this->_category->id] : null] - ]; + return array_merge( + parent::rules(), + [ + [['name'], 'required'], + [['name', 'slug', 'title', 'meta_title', 'meta_keywords'], 'string', 'max' => 255], + [['description', 'meta_description'], 'string'], + ['slug', SlugValidator::class], + [['slug'], 'unique', 'targetClass' => BlogCategory::class, 'filter' => $this->_category ? ['<>', 'id', $this->_category->id] : null] + ] + ); } public function attributeLabels() { - return [ - 'name' => Yii::t('blog', 'Name'), - 'slug' => Yii::t('blog', 'SEO link'), - 'sort' => Yii::t('blog', 'Sort'), - 'title' => Yii::t('blog', 'Title'), - 'description' => Yii::t('blog', 'Description'), - ]; + return array_merge( + parent::attributeLabels(), + [ + 'name' => Yii::t('blog', 'Name'), + 'slug' => Yii::t('blog', 'SEO link'), + 'sort' => Yii::t('blog', 'Sort'), + 'title' => Yii::t('blog', 'Title'), + 'description' => Yii::t('blog', 'Description'), + 'meta_title' => Yii::t('blog', 'META Title'), + 'meta_description' => Yii::t('blog', 'META Description'), + 'meta_keywords' => Yii::t('blog', 'META Keywords'), + ] + ); } public function attributeHints() { - return [ - 'slug' => Yii::t('blog', 'SEO link will be generated automatically if not specified'), - ]; + return array_merge( + parent::attributeHints(), + [ + 'slug' => Yii::t('blog', 'SEO link will be generated automatically if not specified'), + ] + ); } public function updateSort() { $this->sort = BlogCategory::find()->max('sort') + 1; } - - public function internalForms(): array - { - return ['meta']; - } } \ No newline at end of file diff --git a/common/modules/blog/forms/BlogPostForm.php b/common/modules/blog/forms/BlogPostForm.php index ea265bd..5dd66ec 100644 --- a/common/modules/blog/forms/BlogPostForm.php +++ b/common/modules/blog/forms/BlogPostForm.php @@ -5,9 +5,11 @@ namespace common\modules\blog\forms; use common\modules\blog\entities\BlogCategory; use common\modules\blog\entities\BlogPost; use core\forms\CompositeForm; +use core\forms\CompositeLanguageForm; use core\forms\MetaForm; use core\validators\SlugValidator; use yii\db\ActiveQuery; +use yii\db\ActiveRecord; use yii\helpers\ArrayHelper; use yii\web\UploadedFile; use Yii; @@ -16,7 +18,7 @@ use Yii; * @property MetaForm $meta * @property BlogTagForm $tags */ -class BlogPostForm extends CompositeForm +class BlogPostForm extends CompositeLanguageForm { public $type; @@ -30,96 +32,104 @@ class BlogPostForm extends CompositeForm public $slug; public $reset_image; public $status; + public $meta_title; + public $meta_description; + public $meta_keywords; public $_post; - public function __construct(BlogPost $post = null, $config = []) + public function __construct(BlogPost $post = null, array $attributes = [], $config = []) { if ($post) { $this->category_id = $post->category_id; - $this->title = $post->title; - $this->description = $post->description; - $this->content = $post->content; $this->video = $post->video; $this->published_at = $post->published_at; $this->slug = $post->slug; - $this->meta = new MetaForm($post->meta); $this->tags = new BlogTagForm($post); $this->status = $post->status; $this->_post = $post; } else { - $this->meta = new MetaForm(); $this->tags = new BlogTagForm(); $this->status = 0; } - parent::__construct($config); + parent::__construct($post, $attributes, $config); } public function rules(): array { - return [ - [['category_id', 'title'], 'required'], - [['title', 'video'], 'string', 'max' => 255], - [['category_id', 'status'], 'integer'], - [['description', 'content'], 'string'], - [['image'], 'image'], - ['reset_image', 'boolean'], - ['published_at', 'safe'], - ['slug', SlugValidator::class], - //[['slug'], 'unique', 'targetClass' => BlogPost::class, 'filter' => $this->_post ? ['<>', 'id', $this->_post->id] : null], - //[['slug'], 'unique', 'targetClass' => BlogPost::class, 'filter' => $this->_post ? ['<>', 'id', $this->_post->id] : ['type' => BlogPost::TYPE_PUBLIC]], - //[['slug'], 'unique', 'targetClass' => BlogPost::class, 'filter' => $this->_post ? ['AND', ['<>', 'id', $this->_post->id], ['type' => BlogPost::TYPE_PUBLIC]] : ['type' => BlogPost::TYPE_PUBLIC]], - [['slug'], 'unique', 'targetClass' => BlogPost::class, 'filter' => function (ActiveQuery $query) { - if ($this->type != BlogPost::TYPE_PUBLIC) { - $query->andWhere($this->type . '=' . BlogPost::TYPE_PUBLIC); - } + return array_merge( + parent::rules(), + [ + [['category_id', 'title'], 'required'], + [['title', 'video', 'meta_title', 'meta_keywords'], 'string', 'max' => 255], + [['category_id', 'status'], 'integer'], + [['description', 'content', 'meta_description'], 'string'], + [['image'], 'image'], + ['reset_image', 'boolean'], + ['published_at', 'safe'], + ['slug', SlugValidator::class], + [['slug'], 'unique', 'targetClass' => BlogPost::class, 'filter' => function (ActiveQuery $query) { + if ($this->type != BlogPost::TYPE_PUBLIC) { + $query->andWhere($this->type . '=' . BlogPost::TYPE_PUBLIC); + } - $query->andWhere(['type' => BlogPost::TYPE_PUBLIC]); - if ($this->_post) { - $query->andWhere(['<>', 'id', $this->_post->id]); - } - return $query; - }], - ]; + $query->andWhere(['type' => BlogPost::TYPE_PUBLIC]); + if ($this->_post) { + $query->andWhere(['<>', 'id', $this->_post->id]); + } + return $query; + }], + ] + ); } public function attributeLabels() { - return [ - 'id' => Yii::t('blog', 'ID'), - 'category_id' => Yii::t('blog', 'Category'), - 'published_at' => Yii::t('blog', 'Published At'), - 'created_at' => Yii::t('blog', 'Created At'), - 'updated_at' => Yii::t('blog', 'Updated At'), - 'title' => Yii::t('blog', 'Title'), - 'description' => Yii::t('blog', 'Description'), - 'content' => Yii::t('blog', 'Content'), - 'image' => Yii::t('blog', 'Image'), - 'video' => Yii::t('blog', 'Video'), - 'status' => Yii::t('blog', 'Status'), - 'meta_json' => Yii::t('blog', 'Meta Json'), - 'comments_count' => Yii::t('blog', 'Comments Count'), - 'views' => Yii::t('blog', 'Views'), - 'slug' => Yii::t('blog', 'Slug'), - 'reset_image' => Yii::t('blog', 'Reset Image'), - ]; + return array_merge( + parent::attributeLabels(), + [ + 'id' => Yii::t('blog', 'ID'), + 'category_id' => Yii::t('blog', 'Category'), + 'published_at' => Yii::t('blog', 'Published At'), + 'created_at' => Yii::t('blog', 'Created At'), + 'updated_at' => Yii::t('blog', 'Updated At'), + 'title' => Yii::t('blog', 'Title'), + 'description' => Yii::t('blog', 'Description'), + 'content' => Yii::t('blog', 'Content'), + 'image' => Yii::t('blog', 'Image'), + 'video' => Yii::t('blog', 'Video'), + 'status' => Yii::t('blog', 'Status'), + 'comments_count' => Yii::t('blog', 'Comments Count'), + 'views' => Yii::t('blog', 'Views'), + 'slug' => Yii::t('blog', 'Slug'), + 'reset_image' => Yii::t('blog', 'Reset Image'), + 'meta_title' => Yii::t('blog', 'META Title'), + 'meta_description' => Yii::t('blog', 'META Description'), + 'meta_keywords' => Yii::t('blog', 'META Keywords'), + ] + ); } 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('pages', 'SEO link will be generated automatically if not specified'), - ]; + return array_merge( + parent::attributeHints(), + [ + 'published_at' => Yii::t('blog', 'The article will be published after the specified date if its status is not a draft'), + 'slug' => Yii::t('pages', 'SEO link will be generated automatically if not specified'), + ] + ); } public function categoriesList(): array { - return ArrayHelper::map(BlogCategory::find()->orderBy('sort')->asArray()->all(), 'id', 'name'); + return ArrayHelper::map(BlogCategory::find()->orderBy('sort')->all(), 'id', function (BlogCategory $category) { + return $category->translation->name; + }); } protected function internalForms(): array { - return ['meta', 'tags']; + return ['tags']; } public function beforeValidate(): bool diff --git a/common/modules/blog/forms/search/BlogCategorySearch.php b/common/modules/blog/forms/search/BlogCategorySearch.php index 435cde6..3b2bd99 100644 --- a/common/modules/blog/forms/search/BlogCategorySearch.php +++ b/common/modules/blog/forms/search/BlogCategorySearch.php @@ -17,7 +17,8 @@ class BlogCategorySearch extends Model { return [ [['id'], 'integer'], - [['name', 'slug', 'title'], 'safe'], + [['slug'], 'safe'], + [['name', 'title'], 'safe'], ]; } @@ -35,7 +36,6 @@ class BlogCategorySearch extends Model 'defaultOrder' => ['sort' => SORT_ASC] ] ]); - $this->load($params); if (!$this->validate()) { @@ -51,7 +51,6 @@ class BlogCategorySearch extends Model ->andFilterWhere(['like', 'name', $this->name]) ->andFilterWhere(['like', 'slug', $this->slug]) ->andFilterWhere(['like', 'title', $this->title]); - return $dataProvider; } } diff --git a/common/modules/blog/helpers/BlogPostHelper.php b/common/modules/blog/helpers/BlogPostHelper.php index 58e7ea9..6173836 100644 --- a/common/modules/blog/helpers/BlogPostHelper.php +++ b/common/modules/blog/helpers/BlogPostHelper.php @@ -3,14 +3,20 @@ namespace common\modules\blog\helpers; use common\modules\blog\entities\BlogPost; +use common\modules\blog\forms\BlogPostForm; +use common\modules\blog\repositories\BlogRepository; +use common\modules\blog\repositories\read\BlogPostReadRepository; +use common\modules\blog\services\BlogPostManageService; +use core\dispatchers\DeferredEventDispatcher; use core\entities\post\Post; +use core\services\TransactionManager; use yii\helpers\ArrayHelper; use yii\helpers\Html; use Yii; class BlogPostHelper { - public static function statusList(): array + public static function statusList(): array { return [ Post::STATUS_DRAFT => Yii::t('blog', 'Draft'), @@ -69,6 +75,36 @@ class BlogPostHelper return $id; } + public static function saveRevision1(BlogPost $model) { + if (!$model->revision_id) { + + $blogForm = new BlogPostForm($model); + $blog = BlogPost::create( + $blogForm, + $model->category_id, + $model->slug, + $model->published_at, + $model->video, + $model->type + ); + $blog->type = BlogPost::TYPE_REVISION; + $blog->revision_at = $model->updated_at; + $blog->revision_id = $model->id; + + foreach ($model->tags as $tag) { + $blog->assignTag($tag->id); + } + + $blog->save(); + + if ($model->image) { + $path = Yii::getAlias( '@staticRoot/origin/posts' ); + $parts = pathinfo( $model->image ); + copy( $path . '/' . $model->id . '.' . $parts['extension'], $path . '/' . $blog->id . '.' . $parts['extension'] ); + } + } + } + public static function saveRevision(BlogPost $model) { if (!$model->revision_id) { $revision = clone $model; @@ -77,6 +113,7 @@ class BlogPostHelper $revision->revision_at = $revision->updated_at; $revision->revision_id = $model->id; $revision->type = BlogPost::TYPE_REVISION; + $revision->_form = new BlogPostForm($model); $revision->save(); // tags @@ -85,9 +122,11 @@ class BlogPostHelper } $revision->save(); - $path = Yii::getAlias('@staticRoot/origin/posts'); - $parts = pathinfo($model->image); - copy($path . '/' . $model->id . '.' . $parts['extension'], $path . '/' . $revision->id . '.' . $parts['extension']); + if ($model->image) { + $path = Yii::getAlias( '@staticRoot/origin/posts' ); + $parts = pathinfo( $model->image ); + copy( $path . '/' . $model->id . '.' . $parts['extension'], $path . '/' . $revision->id . '.' . $parts['extension'] ); + } } } } \ No newline at end of file diff --git a/common/modules/blog/messages/ru/blog.php b/common/modules/blog/messages/ru/blog.php index b7e6406..43cade2 100644 --- a/common/modules/blog/messages/ru/blog.php +++ b/common/modules/blog/messages/ru/blog.php @@ -36,9 +36,9 @@ return [ 'Draft' => 'Черновик', 'Active' => 'Опубликовано', 'Activate' => 'Опубликовать', - 'Meta Title' => 'Заголовок', - 'Meta Description' => 'Описание', - 'Meta Keywords' => 'Ключевые слова', + 'META Title' => 'Заголовок', + 'META Description' => 'Описание', + 'META Keywords' => 'Ключевые слова', 'Name' => 'Название', 'Sort' => 'Позиция', 'Update: {name}' => 'Редактирование: {name}', diff --git a/common/modules/blog/migrations/m180828_190314_create_blog_post_lng_table.php b/common/modules/blog/migrations/m180828_190314_create_blog_post_lng_table.php new file mode 100644 index 0000000..9608535 --- /dev/null +++ b/common/modules/blog/migrations/m180828_190314_create_blog_post_lng_table.php @@ -0,0 +1,54 @@ +createTable('{{%blog_posts_lng}}', [ + 'id' => $this->primaryKey(), + 'blog_post_id' => $this->integer()->notNull(), + 'language' => $this->string(6)->notNull(), + 'title' => $this->string()->notNull(), + 'description' => $this->text(), + 'content' => 'MEDIUMTEXT', + 'meta_title' => $this->string(255), + 'meta_description' => $this->text(), + 'meta_keywords' => $this->string(255), + ], $tableOptions); + + $this->createIndex('idx_blog_posts_lng_language', '{{%blog_posts_lng}}', 'language'); + $this->createIndex('idx_blog_posts_lng_blog_post_id', '{{%blog_posts_lng}}', 'blog_post_id'); + $this->addForeignKey('frg_blog_posts_lng_blog_posts_blog_post_id_id', '{{%blog_posts_lng}}', 'blog_post_id', '{{%blog_posts}}', 'id', 'CASCADE', 'CASCADE'); + + $this->dropColumn('{{%blog_posts}}', 'title'); + $this->dropColumn('{{%blog_posts}}', 'description'); + $this->dropColumn('{{%blog_posts}}', 'content'); + $this->dropColumn('{{%blog_posts}}', 'meta_json'); + } + + /** + * {@inheritdoc} + */ + public function safeDown() + { + $this->addColumn('{{%blog_posts}}', 'title', $this->string(255)->notNull()); + $this->addColumn('{{%blog_posts}}', 'description', $this->text()); + $this->addColumn('{{%blog_posts}}', 'description', 'MEDIUMTEXT'); + $this->addColumn('{{%blog_posts}}', 'meta_json', $this->text()); + + $this->dropForeignKey('frg_blog_posts_lng_blog_posts_blog_post_id_id', '{{%blog_posts_lng}}'); + $this->dropIndex('idx_blog_posts_lng_blog_post_id', '{{%blog_posts_lng}}'); + $this->dropIndex('idx_blog_posts_lng_language', '{{%blog_posts_lng}}'); + $this->dropTable('{{%blog_posts_lng}}'); + } +} diff --git a/common/modules/blog/migrations/m180830_163050_create_blog_categories_lng_table.php b/common/modules/blog/migrations/m180830_163050_create_blog_categories_lng_table.php new file mode 100644 index 0000000..95967be --- /dev/null +++ b/common/modules/blog/migrations/m180830_163050_create_blog_categories_lng_table.php @@ -0,0 +1,55 @@ +createTable('{{%blog_categories_lng}}', [ + 'id' => $this->primaryKey(), + 'blog_category_id' => $this->integer()->notNull(), + 'language' => $this->string(6)->notNull(), + 'name' => $this->string()->notNull(), + 'title' => $this->string(), + 'description' => $this->text(), + 'meta_title' => $this->string(255), + 'meta_description' => $this->text(), + 'meta_keywords' => $this->string(255), + ], $tableOptions); + + $this->createIndex('idx_blog_categories_lng_language', '{{%blog_categories_lng}}', 'language'); + $this->createIndex('idx_blog_categories_lng_blog_category_id', '{{%blog_categories_lng}}', 'blog_category_id'); + $this->addForeignKey('frg_blog_categories_lng_blog_categories_blog_category_id_id', '{{%blog_categories_lng}}', 'blog_category_id', '{{%blog_categories}}', 'id', 'CASCADE', 'CASCADE'); + + $this->dropColumn('{{%blog_categories}}', 'title'); + $this->dropColumn('{{%blog_categories}}', 'description'); + $this->dropColumn('{{%blog_categories}}', 'name'); + $this->dropColumn('{{%blog_categories}}', 'meta_json'); + } + + /** + * {@inheritdoc} + */ + public function safeDown() + { + $this->dropForeignKey('frg_blog_categories_lng_blog_categories_blog_category_id_id', '{{%blog_categories_lng}}'); + $this->dropIndex('idx_blog_categories_lng_blog_category_id', '{{%blog_categories_lng}}'); + $this->dropIndex('idx_blog_categories_lng_language', '{{%blog_categories_lng}}'); + + $this->dropTable('{{%blog_categories_lng}}'); + + $this->addColumn('{{%blog_categories}}', 'title', $this->string(255)); + $this->addColumn('{{%blog_categories}}', 'name', $this->string(255)->notNull()); + $this->addColumn('{{%blog_categories}}', 'description', $this->text()); + $this->addColumn('{{%blog_categories}}', 'meta_json', 'LONGTEXT NOT NULL'); + } +} diff --git a/common/modules/blog/repositories/read/BlogPostReadRepository.php b/common/modules/blog/repositories/read/BlogPostReadRepository.php index c589105..f512cf7 100644 --- a/common/modules/blog/repositories/read/BlogPostReadRepository.php +++ b/common/modules/blog/repositories/read/BlogPostReadRepository.php @@ -92,8 +92,8 @@ class BlogPostReadRepository return BlogPost::find()->andWhere(['slug' => $slug])->one(); } - public function findPreview($id): ?BlogPost + public function findPreview($id, $language): ?BlogPost { - return BlogPost::find()->andWhere(['id' => $id])->one(); + return BlogPost::find()->localized($language)->andWhere(['id' => $id])->one(); } } \ No newline at end of file diff --git a/common/modules/blog/services/BlogCategoryManageService.php b/common/modules/blog/services/BlogCategoryManageService.php index 70e869e..8cf9871 100644 --- a/common/modules/blog/services/BlogCategoryManageService.php +++ b/common/modules/blog/services/BlogCategoryManageService.php @@ -22,16 +22,9 @@ class BlogCategoryManageService public function create(BlogCategoryForm $form): BlogCategory { $category = BlogCategory::create( - $form->name, + $form, $form->slug, - $form->title, - $form->description, - $form->sort, - new Meta( - $form->meta->title, - $form->meta->description, - $form->meta->keywords - ) + $form->sort ); $this->categories->save($category); return $category; @@ -41,16 +34,9 @@ class BlogCategoryManageService { $category = $this->categories->get($id); $category->edit( - $form->name, + $form, $form->slug, - $form->title, - $form->description, - $form->sort, - new Meta( - $form->meta->title, - $form->meta->description, - $form->meta->keywords - ) + $form->sort ); $this->categories->save($category); } diff --git a/common/modules/blog/services/BlogPostManageService.php b/common/modules/blog/services/BlogPostManageService.php index 342ae53..d2f0014 100644 --- a/common/modules/blog/services/BlogPostManageService.php +++ b/common/modules/blog/services/BlogPostManageService.php @@ -9,10 +9,10 @@ use common\modules\blog\helpers\BlogPostHelper; use common\modules\blog\repositories\BlogCategoryRepository; use common\modules\blog\repositories\BlogRepository; use common\modules\blog\repositories\BlogTagRepository; -use core\entities\Meta; use core\helpers\VideoHelper; use core\services\TransactionManager; use yii\base\Security; +use yii\db\ActiveRecord; use yii\helpers\Inflector; class BlogPostManageService @@ -40,19 +40,12 @@ class BlogPostManageService $category = $this->categories->get($form->category_id); $post = BlogPost::create( + $form, $category->id, - $form->title, $form->slug, - $form->description, - $form->content, $form->published_at, $form->video, - $type, - new Meta( - $form->meta->title, - $form->meta->description, - $form->meta->keywords - ) + $type ); $this->transaction->wrap(function () use ($post, $form) { @@ -92,24 +85,20 @@ class BlogPostManageService public function edit($id, BlogPostForm $form): void { $post = $this->posts->get($id); - BlogPostHelper::saveRevision($post); + BlogPostHelper::saveRevision(clone $post); + //$this->saveRevision(clone $post); + + //print_r($post->translations); die; $category = $this->categories->get($form->category_id); $post->edit( + $form, $category->id, - $form->title, $form->slug, - $form->description, - $form->content, $form->published_at, $form->video, - $post->type, - new Meta( - $form->meta->title, - $form->meta->description, - $form->meta->keywords - ) + $post->type ); if ($form->image) { @@ -119,14 +108,12 @@ class BlogPostManageService elseif ($form->video && (!$post->image || $form->reset_image)) { $post->cleanFiles(); $src = VideoHelper::getThumb($form->video); - //$src = 'https://i.ytimg.com/vi/' . BlogPostHelper::parseYoutubeUrl($post->video) . '/maxresdefault.jpg'; $filename = (new Security())->generateRandomString(15) . '.jpg'; copy($src, \Yii::getAlias(BlogPost::FILE_ORIGINAL_PATH . '/' . $post->id . '.jpg')); $post->image = $filename; } elseif ($post->image && $form->reset_image) { $post->cleanFiles(); - //Post::updateAll(['image' => null], ['id' => $post->id]); $post->image = null; $post->updateAttributes(['image']); } @@ -165,6 +152,9 @@ class BlogPostManageService public function remove($id): void { $post = $this->posts->get($id); + // Remove revisions + $this->clearHistory($post); + $this->posts->remove($post); } @@ -181,11 +171,54 @@ class BlogPostManageService BlogPost::deleteAll(['revision_id' => $post->id]); } - public function restoreHistory($from_id, $id): void + public function restoreHistory($from_id, $id): int + { + $post = $this->posts->get($id); + $from = $this->posts->get($from_id); + + // update revision id + BlogPost::updateAll(['revision_id' => $from->id], ['revision_id' => $post->id]); + + $this->posts->remove($post); + $from->revision_id = null; + $from->type = BlogPost::TYPE_PUBLIC; + $this->posts->save($from); + + // delete never revisions + BlogPost::deleteAll(['AND', ['revision_id' => $from->id], ['>', 'revision_at', $from->revision_at]]); + + return $from->id; + } + + public function restoreHistory2($from_id, $id): void { $post = $this->posts->get($id); $from = $this->posts->get($from_id); + $post->category_id = $from->category_id; + $post->published_at = $from->published_at; + $post->created_at = $from->created_at; + $post->updated_at = $from->updated_at; + $post->video = $from->video; + $post->revision_at = $from->revision_at; + $post->status = $from->status; + $post->slug = $from->slug; + + $this->posts->save($post); + + // remove distance translation + foreach ( $post->translations as $translate ) { + /* @var $translate ActiveRecord */ + $translate->delete(); + } + + // move source translation + foreach ( $from->translations as $translate ) { + /* @var $translate ActiveRecord */ + $translate->blog_post_id = $post->id; + $translate->save(); + } + // get from tags $from_tags = $from->tags; $new_tags_names = array_map(function ($item){ @@ -205,9 +238,9 @@ class BlogPostManageService copy($path . '/' . $from->id . '.' . $parts['extension'], $path . '/' . $id . '.' . $parts['extension']); $from->createThumbs(); - $from->id = $id; - $from->type = BlogPost::TYPE_PUBLIC; - $from->revision_id = null; + //$from->id = $id; + //$from->type = BlogPost::TYPE_PUBLIC; + //$from->revision_id = null; foreach ($new_tags_names as $tag_name) { if ( ! $tag = $this->tags->findByName( $tag_name ) ) { @@ -221,4 +254,65 @@ class BlogPostManageService // delete never revisions BlogPost::deleteAll(['AND', ['revision_id' => $from->id], ['>', 'revision_at', $from->revision_at]]); } + + /*public function saveRevision2(BlogPost $model) { + if (!$model->revision_id) { + $revision = clone $model; + $revision->id = null; + $revision->isNewRecord = true; + $revision->revision_at = $revision->updated_at; + $revision->revision_id = $model->id; + $revision->type = BlogPost::TYPE_REVISION; + $revision->_form = new BlogPostForm($model); + $revision->save(); + + // tags + foreach ($model->tags as $tag) { + $revision->assignTag($tag->id); + } + $revision->save(); + + if ($model->image) { + $path = Yii::getAlias( '@staticRoot/origin/posts' ); + $parts = pathinfo( $model->image ); + copy( $path . '/' . $model->id . '.' . $parts['extension'], $path . '/' . $revision->id . '.' . $parts['extension'] ); + } + } + }*/ + + /*public function saveRevision(BlogPost $model) { + if (!$model->revision_id) { + + $blogForm = new BlogPostForm($model); + $blog = BlogPost::create( + $blogForm, + $blogForm->category_id, + $blogForm->slug, + $blogForm->published_at, + $blogForm->video, + BlogPost::TYPE_REVISION + ); + //$blog->id = null; + //$blog->isNewRecord = true; + $blog->revision_at = $model->updated_at; + $blog->revision_id = $model->id; + + $this->transaction->wrap(function () use ($blog, $model) { + foreach ( $model->tags as $tag ) { + $blog->assignTag( $tag->id ); + } + + $this->posts->save($blog); + + //print_r($blog->translations); die; + //print_r($model->translations); die; + + if ($model->image) { + $path = Yii::getAlias( '@staticRoot/origin/posts' ); + $parts = pathinfo( $model->image ); + copy( $path . '/' . $model->id . '.' . $parts['extension'], $path . '/' . $blog->id . '.' . $parts['extension'] ); + } + }); + } + }*/ } \ No newline at end of file diff --git a/common/modules/blog/urls/BlogCategoryUrlRule.php b/common/modules/blog/urls/BlogCategoryUrlRule.php index 34ecec2..41f3ca0 100644 --- a/common/modules/blog/urls/BlogCategoryUrlRule.php +++ b/common/modules/blog/urls/BlogCategoryUrlRule.php @@ -5,7 +5,7 @@ namespace common\modules\blog\urls; use yii\caching\TagDependency; use common\modules\blog\repositories\read\BlogCategoryReadRepository; use yii\base\BaseObject; -use yii\base\InvalidParamException; +use core\helpers\LanguageHelper; use yii\caching\Cache; use yii\web\UrlNormalizerRedirectException; use yii\web\UrlRuleInterface; @@ -26,7 +26,8 @@ class BlogCategoryUrlRule extends BaseObject implements UrlRuleInterface public function parseRequest($manager, $request) { - if (preg_match('#^' . $this->prefix . '/(.*[a-z])$#is', $request->pathInfo, $matches)) { + $uri = ltrim(LanguageHelper::processLangInUrl($request->pathInfo), '/'); + if (preg_match('#^' . $this->prefix . '/(.*[a-z])$#is', $uri, $matches)) { $path = $matches['1']; $result = $this->cache->getOrSet( [ 'blog_category_route', 'path' => $path ], function () use ( $path ) { @@ -56,7 +57,7 @@ class BlogCategoryUrlRule extends BaseObject implements UrlRuleInterface { if ($route == 'blog/post/category') { if (empty($params['id'])) { - throw new InvalidParamException('Empty id.'); + throw new \InvalidArgumentException('Empty id.'); } $id = $params['id']; @@ -69,7 +70,7 @@ class BlogCategoryUrlRule extends BaseObject implements UrlRuleInterface }, null, new TagDependency(['tags' => ['blog']])); if (!$url) { - throw new InvalidParamException('Undefined id.'); + throw new \InvalidArgumentException('Undefined id.'); } $url = $this->prefix . '/' . $url; @@ -77,8 +78,8 @@ class BlogCategoryUrlRule extends BaseObject implements UrlRuleInterface if (!empty($params) && ($query = http_build_query($params)) !== '') { $url .= '?' . $query; } - - return $url; + //return $url; + return LanguageHelper::addLangToUrl($url, isset($params['language']) ? $params['language'] : null); } return false; } diff --git a/common/modules/blog/urls/BlogMainUrlRule.php b/common/modules/blog/urls/BlogMainUrlRule.php index c5157d2..a60db6b 100644 --- a/common/modules/blog/urls/BlogMainUrlRule.php +++ b/common/modules/blog/urls/BlogMainUrlRule.php @@ -9,6 +9,7 @@ use yii\caching\TagDependency; use yii\web\UrlNormalizerRedirectException; use yii\web\UrlRuleInterface; use InvalidArgumentException; +use core\helpers\LanguageHelper; class BlogMainUrlRule extends BaseObject implements UrlRuleInterface { @@ -26,7 +27,8 @@ class BlogMainUrlRule extends BaseObject implements UrlRuleInterface public function parseRequest($manager, $request) { - if (preg_match('#^' . $this->prefix . '/(.*[a-z])$#is', $request->pathInfo, $matches)) { + $uri = ltrim(LanguageHelper::processLangInUrl($request->pathInfo), '/'); + if (preg_match('#^' . $this->prefix . '/(.*[a-z])$#is', $uri, $matches)) { $path = $matches['1']; $result = $this->cache->getOrSet( [ 'blog_main_route', 'path' => $path ], function () use ( $path ) { @@ -74,8 +76,8 @@ class BlogMainUrlRule extends BaseObject implements UrlRuleInterface if (!empty($params) && ($query = http_build_query($params)) !== '') { $url .= '?' . $query; } - - return $url; + //return $url; + return LanguageHelper::addLangToUrl($url, isset($params['language']) ? $params['language'] : null); } return false; } diff --git a/common/modules/blog/views/manage/category/_form.php b/common/modules/blog/views/manage/category/_form.php index 246b8e8..ea92762 100644 --- a/common/modules/blog/views/manage/category/_form.php +++ b/common/modules/blog/views/manage/category/_form.php @@ -1,6 +1,5 @@ registerJs($js2);
field($model, 'sort')->textInput(['maxlength' => true]) ?>
-
- field($model, 'name')->textInput(['maxlength' => true]) ?> -
-
+
field($model, 'slug')->textInput(['maxlength' => true]) ?>
+ params['translatedLanguages'] as $language => $language_name) { + $items[] = [ + 'label' => $language_name, + 'content' => $this->render('_form_tab', [ + 'form' => $form, + 'model' => $model, + 'language' => $language, + ]), + ]; + } + ?> - field($model, 'title')->textInput(['maxlength' => true]) ?> - field($model, 'description')->widget(CKEditor::className()) ?> - - - + -
-
-
- field($model->meta, 'title')->textInput() ?> - field($model->meta, 'description')->textarea(['rows' => 2]) ?> - field($model->meta, 'keywords')->textInput() ?>
diff --git a/common/modules/blog/views/manage/category/_form_tab.php b/common/modules/blog/views/manage/category/_form_tab.php new file mode 100644 index 0000000..2a3dffd --- /dev/null +++ b/common/modules/blog/views/manage/category/_form_tab.php @@ -0,0 +1,35 @@ +params['defaultLanguage'] ? '' : '_' . $language; +?> + +
+
+ field($model, 'name' . $postfix)->textInput(['maxlength' => true]) ?> + field($model, 'title' . $postfix)->textInput(['maxlength' => true]) ?> + field($model, 'description' . $postfix)->widget(CKEditor::class) ?> +
+
+ + +
+
+
+ field($model, 'meta_title' . $postfix)->textInput() ?> + field($model, 'meta_description' . $postfix)->textarea(['rows' => 2]) ?> + field($model, 'meta_keywords' . $postfix)->textInput() ?> +
+
diff --git a/common/modules/blog/views/manage/category/_view_tab.php b/common/modules/blog/views/manage/category/_view_tab.php new file mode 100644 index 0000000..eeeed04 --- /dev/null +++ b/common/modules/blog/views/manage/category/_view_tab.php @@ -0,0 +1,77 @@ + + + $category, + 'attributes' => [ + [ + 'label' => Yii::t('blog', 'Name'), + 'value' => function(BlogCategory $entity) use ($language) { + return $entity->findTranslation($language)->name; + } + ], + [ + 'label' => Yii::t('blog', 'Title'), + 'value' => function(BlogCategory $entity) use ($language) { + return $entity->findTranslation($language)->title; + } + ], + ], +]) ?> + +
+
+
+ + $category, + 'attributes' => [ + [ + 'label' => Yii::t('blog', 'META Title'), + 'value' => function(BlogCategory $entity) use ($language) { + return $entity->findTranslation($language)->meta_title; + } + ], + [ + 'label' => Yii::t('blog', 'META Description'), + 'value' => function(BlogCategory $entity) use ($language) { + return $entity->findTranslation($language)->meta_description; + } + ], + [ + 'label' => Yii::t('blog', 'META Keywords'), + 'value' => function(BlogCategory $entity) use ($language) { + return $entity->findTranslation($language)->meta_keywords; + } + ], + ], +]) ?> +
+
+ +
+
+
+ formatter->asHtml($category->findTranslation($language)->description, [ + 'Attr.AllowedRel' => array('nofollow'), + 'HTML.SafeObject' => true, + 'Output.FlashCompat' => true, + 'HTML.SafeIframe' => true, + 'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%', + ]) ?> +
+
\ No newline at end of file diff --git a/common/modules/blog/views/manage/category/index.php b/common/modules/blog/views/manage/category/index.php index cfe8ac8..f6e5420 100644 --- a/common/modules/blog/views/manage/category/index.php +++ b/common/modules/blog/views/manage/category/index.php @@ -13,7 +13,7 @@ $title = Yii::t('blog', 'Categories'); $this->title = $title; $this->params['breadcrumbs'][] = $title; ?> -
+

'btn btn-success']) ?> @@ -32,16 +32,21 @@ $this->params['breadcrumbs'][] = $title; [ 'attribute' => 'name', 'value' => function (BlogCategory $model) { - return Html::a(Html::encode($model->name), ['view', 'id' => $model->id]); + return Html::a(Html::encode($model->translation->name), ['view', 'id' => $model->id]); }, 'format' => 'raw', ], [ 'attribute' => 'slug', ], - [ - 'attribute' => 'title', - ], + [ + 'attribute' => 'title', + 'value' => function (BlogCategory $model) { + $title = isset($model->findTranslation(Yii::$app->language)->title) ? $model->findTranslation(Yii::$app->language)->title : $model->findTranslation(Yii::$app->params['defaultLanguage'])->title; + return Html::a(Html::encode($title), ['view', 'id' => $model->id]); + }, + 'format' => 'raw', + ], [ 'class' => ActionColumn::class, 'options' => ['style' => 'width: 100px;'], diff --git a/common/modules/blog/views/manage/category/update.php b/common/modules/blog/views/manage/category/update.php index f99a078..55b2e49 100644 --- a/common/modules/blog/views/manage/category/update.php +++ b/common/modules/blog/views/manage/category/update.php @@ -4,10 +4,10 @@ /* @var $category \common\modules\blog\entities\BlogCategory */ /* @var $model \common\modules\blog\forms\BlogCategoryForm */ -$title = Yii::t('blog', 'Update: {name}', ['name' => $category->name]); +$title = Yii::t('blog', 'Update: {name}', ['name' => $category->translation->name]); $this->title = $title; $this->params['breadcrumbs'][] = ['label' => Yii::t('blog', 'Categories'), 'url' => ['index']]; -$this->params['breadcrumbs'][] = ['label' => $category->name, 'url' => ['view', 'id' => $category->id]]; +$this->params['breadcrumbs'][] = ['label' => $category->translation->name, 'url' => ['view', 'id' => $category->id]]; $this->params['breadcrumbs'][] = Yii::t('buttons', 'Editing'); ?>

diff --git a/common/modules/blog/views/manage/category/view.php b/common/modules/blog/views/manage/category/view.php index 6870889..9a991aa 100644 --- a/common/modules/blog/views/manage/category/view.php +++ b/common/modules/blog/views/manage/category/view.php @@ -6,12 +6,20 @@ use yii\widgets\DetailView; /* @var $this yii\web\View */ /* @var $category \common\modules\blog\entities\BlogCategory */ -$title = $category->name; +$title = $category->translation->name; $this->title = $title; $this->params['breadcrumbs'][] = ['label' => Yii::t('blog', 'Categories'), 'url' => ['index']]; $this->params['breadcrumbs'][] = $title; + +$css = <<registerCss($css); ?> -
+ +

'btn btn-default']) ?> @@ -32,39 +40,30 @@ $this->params['breadcrumbs'][] = $title; 'model' => $category, 'attributes' => [ 'id', - 'name', 'slug', - 'title', 'sort', ], ]) ?>

-
-
-
- formatter->asHtml($category->description, [ - 'Attr.AllowedRel' => array('nofollow'), - 'HTML.SafeObject' => true, - 'Output.FlashCompat' => true, - 'HTML.SafeIframe' => true, - 'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%', - ]) ?> -
-
+ params['translatedLanguages'] as $language => $language_name) { + $items[] = [ + 'label' => $language_name, + 'content' => $this->render('_view_tab', [ + 'category' => $category, + 'language' => $language, + ]), + ]; + } + ?> + + -
-
-
- $category, - 'attributes' => [ - 'meta.title', - 'meta.description', - 'meta.keywords', - ], - ]) ?> -
-
diff --git a/common/modules/blog/views/manage/post/_form.php b/common/modules/blog/views/manage/post/_form.php index 5b052c0..d57f9ba 100644 --- a/common/modules/blog/views/manage/post/_form.php +++ b/common/modules/blog/views/manage/post/_form.php @@ -63,7 +63,7 @@ $this->registerJs($js2);
- field($model, 'category_id')->dropDownList($model->categoriesList(), ['prompt' => '']) ?> + field($model, 'category_id')->dropDownList($model->categoriesList()) ?>
@@ -94,14 +94,34 @@ $this->registerJs($js2);
-
-
- field($model, 'title')->textInput(['maxlength' => true]) ?> - field($model, 'slug')->textInput(['maxlength' => true]) ?> - field($model, 'description')->textarea(['rows' => 5]) ?> - field($model, 'content')->widget(CKEditor::class) ?> -
-
+
+
+ + field($model, 'slug')->textInput(['maxlength' => true]) ?> + +
+
+ + params['translatedLanguages'] as $language => $language_name) { + $items[] = [ + 'label' => $language_name, + 'content' => $this->render('_form_tab', [ + 'form' => $form, + 'model' => $model, + 'language' => $language, + ]), + ]; + } + ?> + +
@@ -139,15 +159,6 @@ $this->registerJs($js2);
-
-
-
- field($model->meta, 'title')->textInput() ?> - field($model->meta, 'description')->textarea(['rows' => 2]) ?> - field($model->meta, 'keywords')->textInput() ?> -
-
-
'btn btn-success', @@ -171,6 +182,35 @@ $this->registerJs($js2); 'formaction' => Url::to(['/blog/manage/post/create-preview', 'id' => $model->_post ? $model->_post->id : null]), 'formtarget' => '_blank', ]) ?> + + + +
+ + + +
+ + + + +
field($model, 'status')->radioList(BlogPostHelper::statusList()) ?>
diff --git a/common/modules/blog/views/manage/post/_form_tab.php b/common/modules/blog/views/manage/post/_form_tab.php new file mode 100644 index 0000000..cc8e756 --- /dev/null +++ b/common/modules/blog/views/manage/post/_form_tab.php @@ -0,0 +1,35 @@ +params['defaultLanguage'] ? '' : '_' . $language; +?> + +
+
+ field($model, 'title' . $postfix)->textInput(['maxlength' => true]) ?> + field($model, 'description' . $postfix)->textarea(['rows' => 5]) ?> + field($model, 'content' . $postfix)->widget(CKEditor::class) ?> +
+
+ + +
+
+
+ field($model, 'meta_title' . $postfix)->textInput() ?> + field($model, 'meta_description' . $postfix)->textarea(['rows' => 2]) ?> + field($model, 'meta_keywords' . $postfix)->textInput() ?> +
+
diff --git a/common/modules/blog/views/manage/post/_view_tab.php b/common/modules/blog/views/manage/post/_view_tab.php new file mode 100644 index 0000000..b564a19 --- /dev/null +++ b/common/modules/blog/views/manage/post/_view_tab.php @@ -0,0 +1,78 @@ + + + $post, + 'attributes' => [ + [ + 'label' => Yii::t('blog', 'Title'), + 'value' => function(BlogPost $entity) use ($language) { + return $entity->findTranslation($language)->title; + } + ], + ], +]) ?> + +
+
+
+ + $post, + 'attributes' => [ + [ + 'label' => Yii::t('blog', 'META Title'), + 'value' => function(BlogPost $entity) use ($language) { + return $entity->findTranslation($language)->meta_title; + } + ], + [ + 'label' => Yii::t('blog', 'META Description'), + 'value' => function(BlogPost $entity) use ($language) { + return $entity->findTranslation($language)->meta_description; + } + ], + [ + 'label' => Yii::t('blog', 'META Keywords'), + 'value' => function(BlogPost $entity) use ($language) { + return $entity->findTranslation($language)->meta_keywords; + } + ], + ], +]) ?> +
+
+ +
+
+
+ formatter->asNtext($post->findTranslation($language)->description) ?> +
+
+ +
+
+
+ formatter->asHtml($post->findTranslation($language)->content, [ + 'Attr.AllowedRel' => array('nofollow'), + 'HTML.SafeObject' => true, + 'Output.FlashCompat' => true, + 'HTML.SafeIframe' => true, + 'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%', + ]) ?> +
+
\ No newline at end of file diff --git a/common/modules/blog/views/manage/post/index.php b/common/modules/blog/views/manage/post/index.php index 1f60137..e3f9c1e 100644 --- a/common/modules/blog/views/manage/post/index.php +++ b/common/modules/blog/views/manage/post/index.php @@ -34,7 +34,8 @@ $this->params['breadcrumbs'][] = $title; [ 'attribute' => 'title', 'value' => function (BlogPost $model) { - return Html::a(Html::encode($model->title), ['view', 'id' => $model->id]); + $title = isset($model->findTranslation(Yii::$app->language)->title) ? $model->findTranslation(Yii::$app->language)->title : $model->findTranslation(Yii::$app->params['defaultLanguage'])->title; + return Html::a(Html::encode($title), ['view', 'id' => $model->id]); }, 'format' => 'raw', ], diff --git a/common/modules/blog/views/manage/post/update.php b/common/modules/blog/views/manage/post/update.php index 08585b3..9f53453 100644 --- a/common/modules/blog/views/manage/post/update.php +++ b/common/modules/blog/views/manage/post/update.php @@ -6,10 +6,10 @@ use yii\helpers\StringHelper; -$title = Yii::t('blog', 'Update Post: {name}', ['name' => StringHelper::truncateWords($post->title, 6, '...')]); +$title = Yii::t('blog', 'Update Post: {name}', ['name' => StringHelper::truncateWords($post->translation->title, 6, '...')]); $this->title = $title; $this->params['breadcrumbs'][] = ['label' => Yii::t('blog', 'Posts'), 'url' => ['index']]; -$this->params['breadcrumbs'][] = ['label' => StringHelper::truncateWords($post->title, 4, '...'), 'url' => ['view', 'id' => $post->id]]; +$this->params['breadcrumbs'][] = ['label' => StringHelper::truncateWords($post->translation->title, 4, '...'), 'url' => ['view', 'id' => $post->id]]; $this->params['breadcrumbs'][] = Yii::t('buttons', 'Editing'); ?>
diff --git a/common/modules/blog/views/manage/post/view.php b/common/modules/blog/views/manage/post/view.php index acdf7ef..4cde14b 100644 --- a/common/modules/blog/views/manage/post/view.php +++ b/common/modules/blog/views/manage/post/view.php @@ -10,10 +10,17 @@ use yii\widgets\DetailView; /* @var $modificationsProvider yii\data\ActiveDataProvider */ /* @var $history \common\modules\blog\entities\BlogPost[] */ -$title = $post->title; +$title = $post->translation->title; $this->title = $title; $this->params['breadcrumbs'][] = ['label' => Yii::t('blog', 'Posts'), 'url' => ['index']]; $this->params['breadcrumbs'][] = $title; + +$css = <<registerCss($css); ?>
@@ -50,21 +57,40 @@ $this->params['breadcrumbs'][] = $title; 'value' => BlogPostHelper::statusLabel($post->status), 'format' => 'raw', ], - 'title', [ 'attribute' => 'category_id', - 'value' => ArrayHelper::getValue($post, 'category.name'), + 'value' => $post->category->translation->name, //ArrayHelper::getValue($post, 'category.name'), ], [ 'label' => Yii::t('post', 'Tags'), 'format' => 'raw', 'value' => ' ' . implode(' ', ArrayHelper::getColumn($post->tags, 'name')), ], + 'slug' ], ]) ?>
+ params['translatedLanguages'] as $language => $language_name) { + $items[] = [ + 'label' => $language_name, + 'content' => $this->render('_view_tab', [ + 'post' => $post, + 'language' => $language, + ]), + ]; + } + ?> + + + image): ?>
@@ -104,56 +130,11 @@ $this->params['breadcrumbs'][] = $title;
- -
-
-
- formatter->asNtext($post->description) ?> -
-
- -
-
-
- formatter->asHtml($post->content, [ - 'Attr.AllowedRel' => array('nofollow'), - 'HTML.SafeObject' => true, - 'Output.FlashCompat' => true, - 'HTML.SafeIframe' => true, - 'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%', - ]) ?> -
-
- -
-
-
- $post, - 'attributes' => [ - [ - 'attribute' => 'meta.title', - 'value' => $post->meta->title, - ], - [ - 'attribute' => 'meta.description', - 'value' => $post->meta->description, - ], - [ - 'attribute' => 'meta.keywords', - 'value' => $post->meta->keywords, - ], - ], - ]) ?> -
-
-
-
    @@ -161,12 +142,10 @@ $this->params['breadcrumbs'][] = $title; revision_id): ?> revision_at) ?> → - get('frontendUrlManager')->createAbsoluteUrl(['/blog/post/preview', 'id' => $item->id])), [ 'style' => 'font-size:11px;', 'target' => '_blank', ]) ?> - | $item->id], [ @@ -183,7 +162,6 @@ $this->params['breadcrumbs'][] = $title;
- $post->id], [ 'class' => 'btn btn-danger btn-sm pull-right', 'data' => [ @@ -202,4 +180,4 @@ $this->params['breadcrumbs'][] = $title; -
+
\ No newline at end of file diff --git a/common/modules/blog/widgets/MenuItemCreatorWidget.php b/common/modules/blog/widgets/MenuItemCreatorWidget.php index 885c4fb..f554b51 100644 --- a/common/modules/blog/widgets/MenuItemCreatorWidget.php +++ b/common/modules/blog/widgets/MenuItemCreatorWidget.php @@ -17,7 +17,7 @@ class MenuItemCreatorWidget extends Widget public function run() { $form = new MenuItemForm(); - $form->module = \Yii::t('blog', 'Blog'); + $form->module = 'blog'; $form->name = \Yii::t('blog', 'Blog'); $form->title_attr = \Yii::t('blog', 'Blog'); $form->menu_id = $this->menu_id; diff --git a/common/modules/forms/FormsModule.php b/common/modules/forms/FormsModule.php index de0d0cd..c378936 100644 --- a/common/modules/forms/FormsModule.php +++ b/common/modules/forms/FormsModule.php @@ -69,7 +69,7 @@ class FormsModule extends \yii\base\Module implements ModuleInterface } // prepare notifications - $new_messages_count = FormMessage::find()->unread()->count(); + $new_messages_count = \Yii::$app->moduleManager->isTableExist('{{%forms}}') ? FormMessage::find()->unread()->count() : 0; if ($new_messages_count > 0) { $app->params['notifications'][] = [ 'icon' => 'address-card-o', diff --git a/common/modules/languages/views/manage/language/_form.php b/common/modules/languages/views/manage/language/_form.php index ae259f0..1a5abac 100644 --- a/common/modules/languages/views/manage/language/_form.php +++ b/common/modules/languages/views/manage/language/_form.php @@ -58,13 +58,12 @@ $this->registerJs($js2);
- _language->default): ?> - field($model, 'status')->radioList(LanguageHelper::statusList()) ?> - + _language->default) && $model->_language->default): ?>

- + + field($model, 'status')->radioList(LanguageHelper::statusList()) ?>
diff --git a/common/modules/pages/entities/Page.php b/common/modules/pages/entities/Page.php index 7f0320c..06142b7 100644 --- a/common/modules/pages/entities/Page.php +++ b/common/modules/pages/entities/Page.php @@ -6,15 +6,10 @@ use common\modules\pages\entities\queries\PageQuery; use core\behaviors\LanguageBehavior; use core\behaviors\SluggableRelationBehavior; use paulzi\nestedsets\NestedSetsBehavior; -use core\behaviors\MetaBehavior; use yii\behaviors\TimestampBehavior; -use yii\behaviors\SluggableBehavior; use common\behaviors\WidgetContentBehavior; use yii\db\ActiveRecord; -use core\entities\Meta; use Yii; -use yii\helpers\Inflector; -use yii\helpers\Json; /** * @property int $id @@ -48,8 +43,6 @@ class Page extends ActiveRecord const TYPE_REVISION = 1; const TYPE_PREVIEW = 2; - public $meta; - public $_form; public static function create($form, $slug, $type = Page::TYPE_PUBLIC): self @@ -72,10 +65,7 @@ class Page extends ActiveRecord public function getSeoTitle(): string { - return $this->translation->meta_title; - //return $this->meta->title ?: $this->title; - //$meta = Meta::createMeta($this->meta_json); - //return $meta->title; + return $this->translation->meta_title ?: $this->translation->title; } public static function tableName(): string @@ -100,6 +90,7 @@ class Page extends ActiveRecord 'tableName' => "{{%pages_lng}}", 'attributes' => ['title', 'content', 'meta_title', 'meta_description', 'meta_keywords'], 'defaultLanguage' => \Yii::$app->params['defaultLanguage'], + //'defaultLanguage' => basename(Yii::$app->getBasePath()) === 'backend' ? Yii::$app->language : Yii::$app->params['defaultLanguage'], ], [ //'class' => SluggableBehavior::class, diff --git a/common/modules/pages/forms/PageForm.php b/common/modules/pages/forms/PageForm.php index 24ccac7..6370e58 100644 --- a/common/modules/pages/forms/PageForm.php +++ b/common/modules/pages/forms/PageForm.php @@ -23,7 +23,7 @@ class PageForm extends LanguageDynamicModel public $_page; - public function __construct(Page $page = null, $config = []) + public function __construct(Page $page = null, array $attributes = [], $config = []) { if ($page) { $this->slug = $page->slug; @@ -31,29 +31,7 @@ class PageForm extends LanguageDynamicModel $this->_page = $page; } - parent::__construct($config); - // fill translate values - if ($page) { - foreach ( $page->translations as $translate ) { - //$meta_translate = Json::decode($translate->meta_json); // get meta - if ($translate->language == Yii::$app->params['backendDefaultLanguage']) { - $this->{'title'} = $translate->title; - $this->{'content'} = $translate->content; - // fill meta - $this->{'meta_title'} = $translate->meta_title; - $this->{'meta_description'} = $translate->meta_description; - $this->{'meta_keywords'} = $translate->meta_keywords; - } - else { - $this->{'title' . '_' . $translate->language} = $translate->title; - $this->{'content' . '_' . $translate->language} = $translate->content; - // fill meta - $this->{'meta_title' . '_' . $translate->language} = $translate->meta_title; - $this->{'meta_description' . '_' . $translate->language} = $translate->meta_description; - $this->{'meta_keywords' . '_' . $translate->language} = $translate->meta_keywords; - } - }; - }; + parent::__construct( $page, $attributes, $config ); } public function rules(): array @@ -63,8 +41,8 @@ class PageForm extends LanguageDynamicModel [ [['title'], 'required'], [['parentId'], 'integer'], - [['title', 'slug', 'meta_title'], 'string', 'max' => 255], - [['content', 'meta_description', 'meta_keywords'], 'string'], + [['title', 'slug', 'meta_title', 'meta_keywords'], 'string', 'max' => 255], + [['content', 'meta_description'], 'string'], ['slug', SlugValidator::class], [['slug'], 'unique', 'targetClass' => Page::class, 'filter' => function (ActiveQuery $query) { if ($this->type != Page::TYPE_PUBLIC) { diff --git a/common/modules/pages/migrations/m180824_202316_create_pages_lng_table.php b/common/modules/pages/migrations/m180824_202316_create_pages_lng_table.php index 0e7d84f..637ae09 100644 --- a/common/modules/pages/migrations/m180824_202316_create_pages_lng_table.php +++ b/common/modules/pages/migrations/m180824_202316_create_pages_lng_table.php @@ -36,8 +36,8 @@ class m180824_202316_create_pages_lng_table extends Migration public function safeDown() { $this->dropForeignKey('frg_pages_lng_pages_page_id_id', '{{%pages_lng}}'); - $this->dropColumn('idx_pages_lng_page_id', '{{%pages_lng}}'); - $this->dropColumn('idx_pages_lng_language', '{{%pages_lng}}'); + $this->dropIndex('idx_pages_lng_page_id', '{{%pages_lng}}'); + $this->dropIndex('idx_pages_lng_language', '{{%pages_lng}}'); $this->dropTable('{{%pages_lng}}'); } } diff --git a/common/modules/pages/services/PageManageService.php b/common/modules/pages/services/PageManageService.php index 7a4b208..07e693e 100644 --- a/common/modules/pages/services/PageManageService.php +++ b/common/modules/pages/services/PageManageService.php @@ -80,13 +80,7 @@ class PageManageService $page = $this->pages->get($id); // Remove revisions - $revisions = Page::find() - ->andWhere(['revision_id' => $page->id]) - ->all(); - foreach ($revisions as $revision) { - $this->assertIsNotRoot($revision); - $this->pages->remove($revision); - } + $this->clearHistory($page); $this->assertIsNotRoot($page); $this->pages->remove($page); diff --git a/common/modules/pages/views/manage/page/index.php b/common/modules/pages/views/manage/page/index.php index b99c454..ca4cca9 100644 --- a/common/modules/pages/views/manage/page/index.php +++ b/common/modules/pages/views/manage/page/index.php @@ -28,7 +28,8 @@ $this->params['breadcrumbs'][] = $this->title; 'attribute' => 'title', 'value' => function (Page $model) { $indent = ($model->depth > 1 ? str_repeat('  ', $model->depth - 1) . ' ' : ''); - return $indent . Html::a(Html::encode($model->translation->title), ['view', 'id' => $model->id]); + $title = isset($model->findTranslation(Yii::$app->language)->title) ? $model->findTranslation(Yii::$app->language)->title : $model->findTranslation(Yii::$app->params['defaultLanguage'])->title; + return $indent . Html::a(Html::encode($title), ['view', 'id' => $model->id]); }, 'format' => 'raw', ], diff --git a/common/tests/_data/user.php b/common/tests/_data/user.php index 9c9f50a..81a1748 100644 --- a/common/tests/_data/user.php +++ b/common/tests/_data/user.php @@ -1,14 +1,49 @@ 'bayer.hudson', - 'auth_key' => 'HP187Mvq7Mmm3CTU80dLkGmni_FUH_lR', - //password_0 - 'password_hash' => '$2y$13$EjaPFBnZOQsHdGuHI.xvhuDp1fHpo8hKRSk6yshqa9c5EG8s3C3lO', - 'password_reset_token' => 'ExzkCOaYc1L8IOBs4wdTGGbgNiG3Wz1I_1402312317', - 'created_at' => '1402312317', - 'updated_at' => '1402312317', - 'email' => 'nicole.paucek@schultz.info', - ], + 'user1' => [ + "id" => 1, + "username" => "Error202", + "auth_key" => "I4MJAUm8ZZ4rennRmwhjfeZ7xV2-FpYn", + "password_hash" => '$2y$13$Q/XqSZs.6Y5KYmKf5OhpEOGWoB1GfBjxg8DTTnvionrJrCkezgyZe', + "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", + "backend_language" => "ru", + "frontend_language" => "ru", + ], + '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, + "backend_language" => "ru", + "frontend_language" => "ru", + ], + '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, + "backend_language" => "ru", + "frontend_language" => "ru", + ], ]; diff --git a/common/tests/unit/models/LoginFormTest.php b/common/tests/unit/models/LoginFormTest.php index 820030e..7023f19 100644 --- a/common/tests/unit/models/LoginFormTest.php +++ b/common/tests/unit/models/LoginFormTest.php @@ -8,19 +8,30 @@ use core\repositories\user\UserRepository; use core\services\auth\AuthService; use core\dispatchers\SimpleEventDispatcher; use Yii; -use common\models\LoginForm; +use core\forms\auth\LoginForm; use common\fixtures\UserFixture; +use yii\helpers\VarDumper; /** * Login form test */ class LoginFormTest extends \Codeception\Test\Unit { + /** * @var \common\tests\UnitTester */ protected $tester; + public function __construct( ?string $name = null, array $data = [], string $dataName = '') { + parent::__construct( $name, $data, $dataName ); + } + + protected function _after() { + //Yii::$app->user->logout(); + //Yii::$app->session->close(); + } + /** * @return array */ @@ -28,7 +39,7 @@ class LoginFormTest extends \Codeception\Test\Unit { return [ 'user' => [ - 'class' => UserFixture::className(), + 'class' => UserFixture::class, 'dataFile' => codecept_data_dir() . 'user.php' ] ]; @@ -36,39 +47,73 @@ class LoginFormTest extends \Codeception\Test\Unit public function testLoginNoUser() { - $form = new \core\forms\auth\LoginForm(); + $form = new LoginForm(); $form->username = 'not_existing_username'; $form->password = 'not_existing_password'; - $model = new User($form); + $model = User::find()->andWhere(['or', ['username' => $form->username], ['email' => $form->username]])->one(); - //$as = new AuthService(new UserRepository(new SimpleEventDispatcher(null, null))); - //$as->auth($form); - expect('model should not login user', Yii::$app->user->login(new Identity($model)))->false(); + expect('user not exists', !$model)->true(); + expect('model should not login user', $model && Yii::$app->user->login(new Identity($model)))->false(); expect('user should not be logged in', Yii::$app->user->isGuest)->true(); } public function testLoginWrongPassword() { - $model = new LoginForm([ - 'username' => 'bayer.hudson', - 'password' => 'wrong_password', - ]); + $form = new LoginForm(); + $form->username = 'Error202'; + $form->password = 'wrong_password'; + + $model = User::find()->andWhere(['or', ['username' => $form->username], ['email' => $form->username]])->one(); - expect('model should not login user', $model->login())->false(); - expect('error message should be set', $model->errors)->hasKey('password'); + //VarDumper::dump($form); + + expect('model should not login user', $model && Yii::$app->user->login(new Identity($model)))->false(); + //expect('error message should be set', $form->errors)->hasKey('password'); expect('user should not be logged in', Yii::$app->user->isGuest)->true(); } public function testLoginCorrect() { - $model = new LoginForm([ - 'username' => 'bayer.hudson', - 'password' => 'password_0', - ]); + $form = new LoginForm(); + $form->username = 'Error202'; + $form->password = '1111111'; + + //$user->validatePassword($form->password) + $model = User::find()->andWhere(['or', ['username' => $form->username], ['email' => $form->username]])->one(); - expect('model should login user', $model->login())->true(); - expect('error message should not be set', $model->errors)->hasntKey('password'); + //expect('model should login user', $model && $model->validatePassword($form->password))->true(); + expect('model should login user', $model && Yii::$app->user->login(new Identity($model)))->true(); + //expect('error message should not be set', $model->errors)->hasntKey('password'); expect('user should be logged in', Yii::$app->user->isGuest)->false(); } + + public function testValidPassword() + { + $form = new LoginForm(); + $form->username = 'Error202'; + $form->password = '1111111'; + + $model = User::find()->andWhere(['or', ['username' => $form->username], ['email' => $form->username]])->one(); + + expect('user password validation correct', $model && $model->validatePassword($form->password))->true(); + } + + public function testNotValidPassword() + { + $form = new LoginForm(); + $form->username = 'Error202'; + $form->password = 'wrong_password'; + + $model = User::find()->andWhere(['or', ['username' => $form->username], ['email' => $form->username]])->one(); + + expect('user password not valid', $model && $model->validatePassword($form->password))->false(); + } + + public function testFindByUsername() + { + $model = User::findByUsername('Error202'); + expect('find user by username correct', $model && $model->id == 1)->true(); + expect('find user by username failed', !$model || $model->id != 1)->false(); + } } diff --git a/core/behaviors/LanguageBehavior.php b/core/behaviors/LanguageBehavior.php index 4eb1a8b..cc1418f 100644 --- a/core/behaviors/LanguageBehavior.php +++ b/core/behaviors/LanguageBehavior.php @@ -180,8 +180,10 @@ class LanguageBehavior extends Behavior { /** @var ActiveRecord $owner */ $owner = $this->owner; - if ($owner->isRelationPopulated('translations')) { + //if ($owner->isRelationPopulated('translations')) { + if ($translationRecords = $owner->translations) { $translations = $this->indexByLanguage($owner->getRelatedRecords()['translations']); + //$translations = $this->indexByLanguage($translationRecords); $this->saveTranslations($translations); } } @@ -255,6 +257,9 @@ class LanguageBehavior extends Behavior { /** @var ActiveRecord $owner */ $owner = $this->owner; + if (!isset($owner->_form) || !$owner->_form) { + return; + } foreach ($this->translatedLanguages as $language) { $isDefaultLanguage = $language == $this->defaultLanguage; if (!isset($translations[$language])) { @@ -315,7 +320,12 @@ class LanguageBehavior extends Behavior public function getTranslation($language = null) { - $language = $language ?: $this->defaultLanguage; + //if (basename(\Yii::$app->getBasePath()) === 'backend') { + // $language = $language ?: $this->defaultLanguage; + //} + //else { + $language = $language ?: \Yii::$app->language; + //} // if translate exists $translate = $this->virtualClassName::find() ->andWhere([$this->relativeField => $this->owner->id]) diff --git a/core/components/LanguageDynamicModel.php b/core/components/LanguageDynamicModel.php index 68efba4..74f2c1f 100644 --- a/core/components/LanguageDynamicModel.php +++ b/core/components/LanguageDynamicModel.php @@ -9,6 +9,7 @@ namespace core\components; use yii\base\DynamicModel; use Yii; +use yii\db\ActiveRecord; class LanguageDynamicModel extends DynamicModel { @@ -16,9 +17,46 @@ class LanguageDynamicModel extends DynamicModel private $new_hints = []; private $new_rules = []; - public function __construct( array $attributes = [], array $config = [] ) + public function __construct( ActiveRecord $entity = null, array $attributes = [], array $config = [] ) { + $used_attributes = $this->getStringAttributes(); parent::__construct( array_merge($this->getPublicAttributes(), $this->prepareLanguageAttributes()), $config ); + + if ($entity) { + foreach ($used_attributes as $used_attribute) { + foreach ( $entity->translations as $translate ) { + $defaultLanguage = basename( \Yii::$app->getBasePath() ) === 'backend' + ? + Yii::$app->params['backendDefaultLanguage'] + : + Yii::$app->params['defaultLanguage']; + + $languageAttribute = $used_attribute . '_' . $translate->language; + + if ( $translate->language === $defaultLanguage && isset($translate->{$used_attribute})) { + $this->{$used_attribute} = $translate->{$used_attribute}; + } + elseif (isset($translate->{$used_attribute})) { + $this->{$languageAttribute} = $translate->{$used_attribute}; + } + } + } + } + } + + private function getStringAttributes() + { + $string_attributes = []; + foreach ($this->rules() as $rule) { + $attributes = is_array($rule[0]) ? $rule[0] : [$rule[0]]; + $type = $rule[1]; + if ($type == 'string') { + foreach ($attributes as $attribute) { + $string_attributes[] = $attribute; + } + } + } + return $string_attributes; } private function prepareLanguageAttributes() diff --git a/core/components/modules/ModuleManager.php b/core/components/modules/ModuleManager.php index 6c50a94..b5d7135 100644 --- a/core/components/modules/ModuleManager.php +++ b/core/components/modules/ModuleManager.php @@ -41,7 +41,7 @@ class ModuleManager $modules = []; $localModules = $this->getLocalModules(); foreach ($localModules as $local_module) { - if (!$db_module = ModuleRecord::find()->andWhere(['name' => $local_module['name']])->one()) { + if ($this->isTableExist('modules') && !$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; @@ -87,4 +87,9 @@ class ModuleManager $this->moduleNames = $names; } + public function isTableExist($name): bool + { + return Yii::$app->db->schema->getTableSchema($name) !== null; + } + } \ No newline at end of file diff --git a/core/entities/Settings.php b/core/entities/Settings.php index 02b87e0..c88f67a 100644 --- a/core/entities/Settings.php +++ b/core/entities/Settings.php @@ -65,7 +65,7 @@ class Settings extends ActiveRecord public function behaviors(): array { return [ - TimestampBehavior::className(), + TimestampBehavior::class, ]; } } \ No newline at end of file diff --git a/core/entities/Slider.php b/core/entities/Slider.php index 5967ad1..963cc23 100644 --- a/core/entities/Slider.php +++ b/core/entities/Slider.php @@ -65,7 +65,7 @@ class Slider extends ActiveRecord { return [ [ - 'class' => ImageUploadBehavior::className(), + 'class' => ImageUploadBehavior::class, 'attribute' => 'image', 'createThumbsOnRequest' => true, 'filePath' => '@staticRoot/origin/slider/[[id]].[[extension]]', diff --git a/core/forms/menu/MenuForm.php b/core/forms/menu/MenuForm.php index d8c7383..32ccc5c 100644 --- a/core/forms/menu/MenuForm.php +++ b/core/forms/menu/MenuForm.php @@ -16,18 +16,7 @@ class MenuForm extends LanguageDynamicModel if ($menu) { $this->_menu = $menu; } - parent::__construct( $attributes, $config ); - // fill translate values - if ($menu) { - foreach ( $menu->translations as $translate ) { - if ($translate->language == Yii::$app->params['backendDefaultLanguage']) { - $this->name = $translate->name; - } - else { - $this->{'name' . '_' . $translate->language} = $translate->name; - } - }; - }; + parent::__construct( $menu, $attributes, $config ); } public function rules(): array diff --git a/core/forms/menu/MenuItemForm.php b/core/forms/menu/MenuItemForm.php index eb24989..fa81491 100644 --- a/core/forms/menu/MenuItemForm.php +++ b/core/forms/menu/MenuItemForm.php @@ -21,7 +21,7 @@ class MenuItemForm extends LanguageDynamicModel private $_menu; - public function __construct(MenuItem $menu = null, $config = []) + public function __construct(MenuItem $menu = null, array $attributes = [], $config = []) { if ($menu) { $this->menu_id = $menu->menu_id; @@ -35,7 +35,7 @@ class MenuItemForm extends LanguageDynamicModel $this->_menu = $menu; } - parent::__construct($config); + parent::__construct($menu, $attributes, $config); if ($menu) { foreach ( $menu->translations as $translate ) { if ($translate->language == Yii::$app->params['backendDefaultLanguage']) { diff --git a/frontend/config/LanguageUrlManager.php b/frontend/config/LanguageUrlManager.php index 87a4390..45f3430 100644 --- a/frontend/config/LanguageUrlManager.php +++ b/frontend/config/LanguageUrlManager.php @@ -15,6 +15,9 @@ class LanguageUrlManager extends UrlManager { public function init() { + if (basename(Yii::$app->getBasePath()) !== 'frontend') { + return parent::init(); + } LanguageHelper::setLanguage(Yii::$app->request->getUrl()); $langPrefix = Yii::$app->language . '/'; $finalRules[$langPrefix] = ''; diff --git a/frontend/config/test.php b/frontend/config/test.php index 5881579..a525120 100644 --- a/frontend/config/test.php +++ b/frontend/config/test.php @@ -8,5 +8,11 @@ return [ 'urlManager' => [ 'showScriptName' => true, ], + 'user' => [ + 'identityClass' => 'common\auth\Identity', + 'enableAutoLogin' => true, + 'identityCookie' => ['name' => '_identity', 'httpOnly' => true, 'domain' => $params['cookieDomain']], + 'loginUrl' => ['auth/auth/login'], + ], ], ]; diff --git a/frontend/controllers/auth/AuthController.php b/frontend/controllers/auth/AuthController.php index 3e76e83..6593c98 100644 --- a/frontend/controllers/auth/AuthController.php +++ b/frontend/controllers/auth/AuthController.php @@ -24,7 +24,7 @@ class AuthController extends Controller { return [ 'access' => [ - 'class' => AccessControl::className(), + 'class' => AccessControl::class, 'rules' => [ [ 'actions' => ['login'], diff --git a/frontend/tests/fixtures/UserFixture.php b/frontend/tests/fixtures/UserFixture.php index 8f250bb..e5573b2 100644 --- a/frontend/tests/fixtures/UserFixture.php +++ b/frontend/tests/fixtures/UserFixture.php @@ -7,9 +7,10 @@ namespace frontend\tests\fixtures; +use core\entities\user\User; use yii\test\ActiveFixture; class UserFixture extends ActiveFixture { - public $modelClass = 'core\entites\user\User'; + public $modelClass = User::class; } \ No newline at end of file diff --git a/frontend/tests/fixtures/data/user.php b/frontend/tests/fixtures/data/user.php index 4c33041..0c58d09 100644 --- a/frontend/tests/fixtures/data/user.php +++ b/frontend/tests/fixtures/data/user.php @@ -12,7 +12,9 @@ return [ "status" => 10, "created_at" => 1516021751, "updated_at" => 1530816306, - "user_pic" => "avatar_e188db6330ceab81865b3996f7bbb3d6_300.png" + "user_pic" => "avatar_e188db6330ceab81865b3996f7bbb3d6_300.png", + "backend_language" => "ru", + "frontend_language" => "ru", ], 'user2' => [ "id" => 17, @@ -25,7 +27,9 @@ return [ "status" => 10, "created_at" => 1518122129, "updated_at" => 1518127758, - "user_pic" => null + "user_pic" => null, + "backend_language" => "ru", + "frontend_language" => "ru", ], 'user3' => [ "id" => 18, @@ -38,6 +42,8 @@ return [ "status" => 0, "created_at" => 1518157352, "updated_at" => 1518157352, - "user_pic" => null + "user_pic" => null, + "backend_language" => "ru", + "frontend_language" => "ru", ], ]; \ No newline at end of file diff --git a/frontend/tests/unit/UserTest.php b/frontend/tests/unit/UserTest.php index c8d5639..d3781b1 100644 --- a/frontend/tests/unit/UserTest.php +++ b/frontend/tests/unit/UserTest.php @@ -7,6 +7,7 @@ namespace frontend\tests\unit; use Codeception\Test\Unit; +use core\entities\Meta; use frontend\tests\UnitTester; use frontend\tests\fixtures\UserFixture; @@ -21,6 +22,8 @@ class UserTest extends Unit { return [ 'users' => UserFixture::class, + //'dataFile' => '/app/frontend/tests/fixtures/data/user.php', + //'dataFile' => codecept_data_dir() . 'user.php' ]; } @@ -32,10 +35,38 @@ class UserTest extends Unit } - // test - public function testTest() + public function testFindUserByUsername() { $user = $this->tester->grabFixture('users', 'user1'); + //$user = $this->users['user1']; + //expect_that($user = User::findByUsername('Error202')); + //expect($user->id)->equals(1); + + + + $this->assertEquals(1, $user->id); + $this->assertEquals('Error202', $user->username); + //expect_not(User::findByUsername('Error203')); + } + + /*public function testValidateUser() + { + $user = User::findByUsername('Error202'); + expect_that($user->validatePassword('4220618')); + expect_not($user->validatePassword('123456')); + }*/ + + public function testMeta() + { + $meta = new Meta('test', 'desc', 'keys'); + expect($meta->title)->equals('test'); + } + // test + /*public function testTest() + { + $user = $this->tester->grabFixture('users', 'user1'); + }*/ + } \ No newline at end of file diff --git a/frontend/web/themes/start/modules/blog/views/post/_post.php b/frontend/web/themes/start/modules/blog/views/post/_post.php index 8679979..40e8852 100644 --- a/frontend/web/themes/start/modules/blog/views/post/_post.php +++ b/frontend/web/themes/start/modules/blog/views/post/_post.php @@ -13,11 +13,11 @@ $url_full = Yii::$app->params['frontendHostInfo'] . Url::to(['/blog/post/post',
- <?= Html::encode($model->title) ?> + <?= Html::encode($model->translation->title) ?>
-

title) ?>

-

description), 30, '...') ?>

- +

translation->title) ?>

+

translation->description), 30, '...') ?>

+