Browse Source

Blog languages

LanguageDynamicForm without init values in children
User tests in common
Console run fix
master
Egorka 6 years ago
parent
commit
b631e5f90b
  1. 1
      backend/bootstrap/SetUp.php
  2. 4
      backend/controllers/AuthController.php
  3. 5
      backend/controllers/MenuController.php
  4. 2
      backend/controllers/SliderController.php
  5. 41
      common/bootstrap/SetUp.php
  6. 5
      common/codeception.yml
  7. 2
      common/modules/blog/BlogModule.php
  8. 7
      common/modules/blog/controllers/PostController.php
  9. 5
      common/modules/blog/controllers/manage/CategoryController.php
  10. 4
      common/modules/blog/controllers/manage/CommentController.php
  11. 48
      common/modules/blog/controllers/manage/PostController.php
  12. 4
      common/modules/blog/controllers/manage/TagController.php
  13. 67
      common/modules/blog/entities/BlogCategory.php
  14. 57
      common/modules/blog/entities/BlogPost.php
  15. 2
      common/modules/blog/entities/BlogTagAssignment.php
  16. 15
      common/modules/blog/entities/queries/BlogCategoryQuery.php
  17. 3
      common/modules/blog/entities/queries/BlogPostQuery.php
  18. 52
      common/modules/blog/forms/BlogCategoryForm.php
  19. 54
      common/modules/blog/forms/BlogPostForm.php
  20. 5
      common/modules/blog/forms/search/BlogCategorySearch.php
  21. 39
      common/modules/blog/helpers/BlogPostHelper.php
  22. 6
      common/modules/blog/messages/ru/blog.php
  23. 54
      common/modules/blog/migrations/m180828_190314_create_blog_post_lng_table.php
  24. 55
      common/modules/blog/migrations/m180830_163050_create_blog_categories_lng_table.php
  25. 4
      common/modules/blog/repositories/read/BlogPostReadRepository.php
  26. 22
      common/modules/blog/services/BlogCategoryManageService.php
  27. 146
      common/modules/blog/services/BlogPostManageService.php
  28. 13
      common/modules/blog/urls/BlogCategoryUrlRule.php
  29. 8
      common/modules/blog/urls/BlogMainUrlRule.php
  30. 33
      common/modules/blog/views/manage/category/_form.php
  31. 35
      common/modules/blog/views/manage/category/_form_tab.php
  32. 77
      common/modules/blog/views/manage/category/_view_tab.php
  33. 9
      common/modules/blog/views/manage/category/index.php
  34. 4
      common/modules/blog/views/manage/category/update.php
  35. 53
      common/modules/blog/views/manage/category/view.php
  36. 66
      common/modules/blog/views/manage/post/_form.php
  37. 35
      common/modules/blog/views/manage/post/_form_tab.php
  38. 78
      common/modules/blog/views/manage/post/_view_tab.php
  39. 3
      common/modules/blog/views/manage/post/index.php
  40. 4
      common/modules/blog/views/manage/post/update.php
  41. 80
      common/modules/blog/views/manage/post/view.php
  42. 2
      common/modules/blog/widgets/MenuItemCreatorWidget.php
  43. 2
      common/modules/forms/FormsModule.php
  44. 7
      common/modules/languages/views/manage/language/_form.php
  45. 13
      common/modules/pages/entities/Page.php
  46. 30
      common/modules/pages/forms/PageForm.php
  47. 4
      common/modules/pages/migrations/m180824_202316_create_pages_lng_table.php
  48. 8
      common/modules/pages/services/PageManageService.php
  49. 3
      common/modules/pages/views/manage/page/index.php
  50. 53
      common/tests/_data/user.php
  51. 83
      common/tests/unit/models/LoginFormTest.php
  52. 14
      core/behaviors/LanguageBehavior.php
  53. 40
      core/components/LanguageDynamicModel.php
  54. 7
      core/components/modules/ModuleManager.php
  55. 2
      core/entities/Settings.php
  56. 2
      core/entities/Slider.php
  57. 13
      core/forms/menu/MenuForm.php
  58. 4
      core/forms/menu/MenuItemForm.php
  59. 3
      frontend/config/LanguageUrlManager.php
  60. 6
      frontend/config/test.php
  61. 2
      frontend/controllers/auth/AuthController.php
  62. 3
      frontend/tests/fixtures/UserFixture.php
  63. 12
      frontend/tests/fixtures/data/user.php
  64. 35
      frontend/tests/unit/UserTest.php
  65. 8
      frontend/web/themes/start/modules/blog/views/post/_post.php
  66. 12
      frontend/web/themes/start/modules/blog/views/post/post.php
  67. BIN
      static/cache/posts/368_287_11.jpg
  68. BIN
      static/cache/posts/370_325_11.jpg
  69. BIN
      static/cache/posts/94_94_11.jpg
  70. BIN
      static/cache/posts/admin_11.jpg
  71. BIN
      static/cache/posts/home_slider_11.jpg
  72. BIN
      static/cache/posts/list_11.jpg
  73. BIN
      static/cache/posts/origin_11.jpg
  74. BIN
      static/cache/posts/thumb_11.jpg
  75. BIN
      static/cache/posts/thumb_gallery_view_11.jpg
  76. BIN
      static/origin/posts/10.jpg
  77. BIN
      static/origin/posts/11.jpg
  78. BIN
      static/origin/posts/5.jpg
  79. BIN
      static/origin/posts/6.jpg

1
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,
]),
]);

4
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'],
],

5
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'],
],

2
backend/controllers/SliderController.php

@ -44,7 +44,7 @@ class SliderController extends Controller
],
],
'verbs' => [
'class' => VerbFilter::className(),
'class' => VerbFilter::class,
'actions' => [
'delete' => ['POST'],
],

41
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);
}
}
else { // connect all existing modules
$this->connectExistingModules();
}
}
// 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']);
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 );
}
}
}

5
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/*

2
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([

7
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,
]);

5
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'],
],

4
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'],
],

48
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.');
}
}

4
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'],
],

67
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);
}
}

57
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

2
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']);
}
}

15
common/modules/blog/entities/queries/BlogCategoryQuery.php

@ -0,0 +1,15 @@
<?php
/**
* Created by Error202
* Date: 27.07.2018
*/
namespace common\modules\blog\entities\queries;
use yii\db\ActiveQuery;
use core\components\LanguageTranslateTrait;
class BlogCategoryQuery extends ActiveQuery
{
use LanguageTranslateTrait;
}

3
common/modules/blog/entities/queries/BlogPostQuery.php

@ -3,10 +3,13 @@
namespace common\modules\blog\entities\queries;
use common\modules\blog\entities\BlogPost;
use core\components\LanguageTranslateTrait;
use yii\db\ActiveQuery;
class BlogPostQuery extends ActiveQuery
{
use LanguageTranslateTrait;
/**
* @param null $alias
* @return $this

52
common/modules/blog/forms/BlogCategoryForm.php

@ -3,6 +3,7 @@
namespace common\modules\blog\forms;
use common\modules\blog\entities\BlogCategory;
use core\components\LanguageDynamicModel;
use core\forms\CompositeForm;
use core\forms\MetaForm;
use core\validators\SlugValidator;
@ -11,67 +12,72 @@ use Yii;
/**
* @property MetaForm $meta;
*/
class BlogCategoryForm extends CompositeForm
class BlogCategoryForm extends LanguageDynamicModel
{
public $name;
public $slug;
public $title;
public $description;
public $sort;
public $meta_title;
public $meta_description;
public $meta_keywords;
private $_category;
public $_category;
public function __construct(BlogCategory $category = null, $config = [])
public function __construct(BlogCategory $category = null, array $attributes = [], $config = [])
{
if ($category) {
$this->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 [
return array_merge(
parent::rules(),
[
[['name'], 'required'],
[['name', 'slug', 'title'], 'string', 'max' => 255],
[['description'], 'string'],
[['name', 'slug', 'title', 'meta_title', 'meta_keywords'], 'string', 'max' => 255],
[['description', 'meta_description'], 'string'],
['slug', SlugValidator::class],
[['name', 'slug'], 'unique', 'targetClass' => BlogCategory::class, 'filter' => $this->_category ? ['<>', 'id', $this->_category->id] : null]
];
[['slug'], 'unique', 'targetClass' => BlogCategory::class, 'filter' => $this->_category ? ['<>', 'id', $this->_category->id] : null]
]
);
}
public function attributeLabels()
{
return [
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 [
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'];
}
}

54
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,45 +32,42 @@ 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 [
return array_merge(
parent::rules(),
[
[['category_id', 'title'], 'required'],
[['title', 'video'], 'string', 'max' => 255],
[['title', 'video', 'meta_title', 'meta_keywords'], 'string', 'max' => 255],
[['category_id', 'status'], 'integer'],
[['description', 'content'], 'string'],
[['description', 'content', 'meta_description'], '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);
@ -80,12 +79,15 @@ class BlogPostForm extends CompositeForm
}
return $query;
}],
];
]
);
}
public function attributeLabels()
{
return [
return array_merge(
parent::attributeLabels(),
[
'id' => Yii::t('blog', 'ID'),
'category_id' => Yii::t('blog', 'Category'),
'published_at' => Yii::t('blog', 'Published At'),
@ -97,29 +99,37 @@ class BlogPostForm extends CompositeForm
'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'),
];
'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 [
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

5
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;
}
}

39
common/modules/blog/helpers/BlogPostHelper.php

@ -3,7 +3,13 @@
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;
@ -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();
if ($model->image) {
$path = Yii::getAlias( '@staticRoot/origin/posts' );
$parts = pathinfo( $model->image );
copy( $path . '/' . $model->id . '.' . $parts['extension'], $path . '/' . $revision->id . '.' . $parts['extension'] );
}
}
}
}

6
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}',

54
common/modules/blog/migrations/m180828_190314_create_blog_post_lng_table.php

@ -0,0 +1,54 @@
<?php
use yii\db\Migration;
/**
* Handles the creation of table `blog_post_lng`.
*/
class m180828_190314_create_blog_post_lng_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
$this->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}}');
}
}

55
common/modules/blog/migrations/m180830_163050_create_blog_categories_lng_table.php

@ -0,0 +1,55 @@
<?php
use yii\db\Migration;
/**
* Handles the creation of table `blog_categories_lng`.
*/
class m180830_163050_create_blog_categories_lng_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
$this->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');
}
}

4
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();
}
}

22
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);
}

146
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'] );
}
});
}
}*/
}

13
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;
}

8
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;
}

33
common/modules/blog/views/manage/category/_form.php

@ -1,6 +1,5 @@
<?php
use zertex\ckeditor\CKEditor;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
@ -37,27 +36,31 @@ $this->registerJs($js2);
<div class="col-md-2">
<?= $form->field($model, 'sort')->textInput(['maxlength' => true]) ?>
</div>
<div class="col-md-5">
<?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
</div>
<div class="col-md-5">
<div class="col-md-10">
<?= $form->field($model, 'slug')->textInput(['maxlength' => true]) ?>
</div>
</div>
<?php
$items = [];
foreach (Yii::$app->params['translatedLanguages'] as $language => $language_name) {
$items[] = [
'label' => $language_name,
'content' => $this->render('_form_tab', [
'form' => $form,
'model' => $model,
'language' => $language,
]),
];
}
?>
<?= $form->field($model, 'title')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'description')->widget(CKEditor::className()) ?>
</div>
<div class="nav-tabs-custom">
<?= \yii\bootstrap\Tabs::widget([
'items' => $items
]) ?>
</div>
<div class="box box-default">
<div class="box-header with-border"><?= Yii::t('blog', 'SEO') ?></div>
<div class="box-body">
<?= $form->field($model->meta, 'title')->textInput() ?>
<?= $form->field($model->meta, 'description')->textarea(['rows' => 2]) ?>
<?= $form->field($model->meta, 'keywords')->textInput() ?>
</div>
</div>

35
common/modules/blog/views/manage/category/_form_tab.php

@ -0,0 +1,35 @@
<?php
/**
* Created by Error202
* Date: 28.08.2018
*/
use zertex\ckeditor\CKEditor;
/**
* @var $this \yii\web\View
* @var $form \yii\widgets\ActiveForm
* @var $model \common\modules\blog\forms\BlogPostForm
* @var $language string
*/
$postfix = $language == Yii::$app->params['defaultLanguage'] ? '' : '_' . $language;
?>
<div class="box box-default">
<div class="box-body">
<?= $form->field($model, 'name' . $postfix)->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'title' . $postfix)->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'description' . $postfix)->widget(CKEditor::class) ?>
</div>
</div>
<div class="box box-default">
<div class="box-header with-border"><?= Yii::t('blog', 'SEO') ?></div>
<div class="box-body">
<?= $form->field($model, 'meta_title' . $postfix)->textInput() ?>
<?= $form->field($model, 'meta_description' . $postfix)->textarea(['rows' => 2]) ?>
<?= $form->field($model, 'meta_keywords' . $postfix)->textInput() ?>
</div>
</div>

77
common/modules/blog/views/manage/category/_view_tab.php

@ -0,0 +1,77 @@
<?php
/**
* Created by Error202
* Date: 25.08.2018
*/
use yii\widgets\DetailView;
use common\modules\blog\entities\BlogCategory;
/**
* @var $this \yii\web\View
* @var $category BlogCategory
* @var $language string
*/
?>
<?= DetailView::widget([
'model' => $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;
}
],
],
]) ?>
<div class="box">
<div class="box-header with-border"><?= Yii::t('blog', 'SEO') ?></div>
<div class="box-body">
<?= DetailView::widget([
'model' => $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;
}
],
],
]) ?>
</div>
</div>
<div class="box">
<div class="box-header with-border"><?= Yii::t('blog', 'Description') ?></div>
<div class="box-body">
<?= Yii::$app->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/)%',
]) ?>
</div>
</div>

9
common/modules/blog/views/manage/category/index.php

@ -13,7 +13,7 @@ $title = Yii::t('blog', 'Categories');
$this->title = $title;
$this->params['breadcrumbs'][] = $title;
?>
<div class="user-index">
<div class="blog-category-index">
<p>
<?= Html::a(Yii::t('blog', 'Create Category'), ['create'], ['class' => 'btn btn-success']) ?>
@ -32,7 +32,7 @@ $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',
],
@ -41,6 +41,11 @@ $this->params['breadcrumbs'][] = $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,

4
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');
?>
<div class="category-update">

53
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 = <<<CSS
.detail-view th {
width: 25%;
}
CSS;
$this->registerCss($css);
?>
<div class="user-view">
<div class="blog-category-view">
<p>
<?= Html::a(Yii::t('blog', 'Categories'), ['index'], ['class' => 'btn btn-default']) ?>
@ -32,39 +40,30 @@ $this->params['breadcrumbs'][] = $title;
'model' => $category,
'attributes' => [
'id',
'name',
'slug',
'title',
'sort',
],
]) ?>
</div>
</div>
<div class="box">
<div class="box-header with-border"><?= Yii::t('blog', 'Description') ?></div>
<div class="box-body">
<?= Yii::$app->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/)%',
]) ?>
</div>
</div>
<?php
$items = [];
foreach (Yii::$app->params['translatedLanguages'] as $language => $language_name) {
$items[] = [
'label' => $language_name,
'content' => $this->render('_view_tab', [
'category' => $category,
'language' => $language,
]),
];
}
?>
<div class="box">
<div class="box-header with-border"><?= Yii::t('blog', 'SEO') ?></div>
<div class="box-body">
<?= DetailView::widget([
'model' => $category,
'attributes' => [
'meta.title',
'meta.description',
'meta.keywords',
],
<div class="nav-tabs-custom">
<?= \yii\bootstrap\Tabs::widget([
'items' => $items,
]) ?>
</div>
</div>
</div>

66
common/modules/blog/views/manage/post/_form.php

@ -63,7 +63,7 @@ $this->registerJs($js2);
<div class="col-md-6">
<div class="box box-default">
<div class="box-body">
<?= $form->field($model, 'category_id')->dropDownList($model->categoriesList(), ['prompt' => '']) ?>
<?= $form->field($model, 'category_id')->dropDownList($model->categoriesList()) ?>
</div>
</div>
</div>
@ -96,13 +96,33 @@ $this->registerJs($js2);
<div class="box box-default">
<div class="box-body">
<?= $form->field($model, 'title')->textInput(['maxlength' => true]) ?>
<!-- < ?= $form->field($model, 'title')->textInput(['maxlength' => true]) ?> -->
<?= $form->field($model, 'slug')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'description')->textarea(['rows' => 5]) ?>
<?= $form->field($model, 'content')->widget(CKEditor::class) ?>
<!-- < ?= $form->field($model, 'description')->textarea(['rows' => 5]) ?>
< ?= $form->field($model, 'content')->widget(CKEditor::class) ?> -->
</div>
</div>
<?php
$items = [];
foreach (Yii::$app->params['translatedLanguages'] as $language => $language_name) {
$items[] = [
'label' => $language_name,
'content' => $this->render('_form_tab', [
'form' => $form,
'model' => $model,
'language' => $language,
]),
];
}
?>
<div class="nav-tabs-custom">
<?= \yii\bootstrap\Tabs::widget([
'items' => $items
]) ?>
</div>
<div class="box box-default">
<div class="box-body">
@ -139,15 +159,6 @@ $this->registerJs($js2);
</div>
</div>
<div class="box box-default">
<div class="box-header with-border"><?= Yii::t('blog', 'SEO') ?></div>
<div class="box-body">
<?= $form->field($model->meta, 'title')->textInput() ?>
<?= $form->field($model->meta, 'description')->textarea(['rows' => 2]) ?>
<?= $form->field($model->meta, 'keywords')->textInput() ?>
</div>
</div>
<div class="form-group">
<?= Html::submitButton(Yii::t('buttons', 'Save'), [
'class' => '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',
]) ?>
<div class="btn-group">
<button type="button" class="btn btn-info"><?= Yii::t('blog', 'Preview on site') ?></button>
<button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu" role="menu">
<?php foreach (Yii::$app->params['translatedLanguages'] as $language => $language_name): ?>
<li>
<?= Html::submitButton($language_name, [
'class' => 'btn btn-block btn-flat bg-white',
'value'=>'preview',
'name'=>'submit_preview',
'formaction' => \yii\helpers\Url::to(['/blog/manage/post/create-preview', 'language' => $language == Yii::$app->params['defaultLanguage'] ? '' : $language]),
'formtarget' => '_blank',
'style' => 'border:0; background-color:#ffffff;',
]) ?>
</li>
<?php endforeach; ?>
</ul>
</div>
<hr>
<?= $form->field($model, 'status')->radioList(BlogPostHelper::statusList()) ?>
<hr>

35
common/modules/blog/views/manage/post/_form_tab.php

@ -0,0 +1,35 @@
<?php
/**
* Created by Error202
* Date: 28.08.2018
*/
use zertex\ckeditor\CKEditor;
/**
* @var $this \yii\web\View
* @var $form \yii\widgets\ActiveForm
* @var $model \common\modules\blog\forms\BlogPostForm
* @var $language string
*/
$postfix = $language == Yii::$app->params['defaultLanguage'] ? '' : '_' . $language;
?>
<div class="box box-default">
<div class="box-body">
<?= $form->field($model, 'title' . $postfix)->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'description' . $postfix)->textarea(['rows' => 5]) ?>
<?= $form->field($model, 'content' . $postfix)->widget(CKEditor::class) ?>
</div>
</div>
<div class="box box-default">
<div class="box-header with-border"><?= Yii::t('blog', 'SEO') ?></div>
<div class="box-body">
<?= $form->field($model, 'meta_title' . $postfix)->textInput() ?>
<?= $form->field($model, 'meta_description' . $postfix)->textarea(['rows' => 2]) ?>
<?= $form->field($model, 'meta_keywords' . $postfix)->textInput() ?>
</div>
</div>

78
common/modules/blog/views/manage/post/_view_tab.php

@ -0,0 +1,78 @@
<?php
/**
* Created by Error202
* Date: 25.08.2018
*/
use yii\widgets\DetailView;
use common\modules\blog\entities\BlogPost;
/**
* @var $this \yii\web\View
* @var $post \common\modules\blog\entities\BlogPost
* @var $language string
*/
?>
<?= DetailView::widget([
'model' => $post,
'attributes' => [
[
'label' => Yii::t('blog', 'Title'),
'value' => function(BlogPost $entity) use ($language) {
return $entity->findTranslation($language)->title;
}
],
],
]) ?>
<div class="box">
<div class="box-header with-border"><?= Yii::t('blog', 'SEO') ?></div>
<div class="box-body">
<?= DetailView::widget([
'model' => $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;
}
],
],
]) ?>
</div>
</div>
<div class="box">
<div class="box-header with-border"><?= Yii::t('blog', 'Description') ?></div>
<div class="box-body">
<?= Yii::$app->formatter->asNtext($post->findTranslation($language)->description) ?>
</div>
</div>
<div class="box">
<div class="box-header with-border"><?= Yii::t('blog', 'Content') ?></div>
<div class="box-body">
<?= Yii::$app->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/)%',
]) ?>
</div>
</div>

3
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',
],

4
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');
?>
<div class="post-update">

80
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 = <<<CSS
.detail-view th {
width: 25%;
}
CSS;
$this->registerCss($css);
?>
<div class="post-view">
@ -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' => '<i class="fa fa-tag" aria-hidden="true"></i> ' . implode(' <i class="fa fa-tag" aria-hidden="true"></i> ', ArrayHelper::getColumn($post->tags, 'name')),
],
'slug'
],
]) ?>
</div>
</div>
<?php
$items = [];
foreach (Yii::$app->params['translatedLanguages'] as $language => $language_name) {
$items[] = [
'label' => $language_name,
'content' => $this->render('_view_tab', [
'post' => $post,
'language' => $language,
]),
];
}
?>
<div class="nav-tabs-custom">
<?= \yii\bootstrap\Tabs::widget([
'items' => $items,
]) ?>
</div>
<?php if ($post->image): ?>
<div class="box">
<div class="box-header with-border"><?= Yii::t('blog', 'Image') ?></div>
@ -104,56 +130,11 @@ $this->params['breadcrumbs'][] = $title;
</div>
</div>
<?php endif; ?>
<div class="box">
<div class="box-header with-border"><?= Yii::t('blog', 'Description') ?></div>
<div class="box-body">
<?= Yii::$app->formatter->asNtext($post->description) ?>
</div>
</div>
<div class="box">
<div class="box-header with-border"><?= Yii::t('blog', 'Content') ?></div>
<div class="box-body">
<?= Yii::$app->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/)%',
]) ?>
</div>
</div>
<div class="box">
<div class="box-header with-border"><?= Yii::t('blog', 'SEO') ?></div>
<div class="box-body">
<?= DetailView::widget([
'model' => $post,
'attributes' => [
[
'attribute' => 'meta.title',
'value' => $post->meta->title,
],
[
'attribute' => 'meta.description',
'value' => $post->meta->description,
],
[
'attribute' => 'meta.keywords',
'value' => $post->meta->keywords,
],
],
]) ?>
</div>
</div>
</div>
<div class="col-md-3">
<div class="box">
<div class="box-header with-border"><?= Yii::t('blog', 'History') ?></div>
<div class="box-body">
<?php if ($history): ?>
<ul>
<?php foreach ($history as $item): ?>
@ -161,12 +142,10 @@ $this->params['breadcrumbs'][] = $title;
<?php if ($item->revision_id): ?>
<?= date('d.m.Y H:i', $item->revision_at) ?>
<?= Html::a(Yii::t('blog', 'View'), \yii\helpers\Url::to(Yii::$app->get('frontendUrlManager')->createAbsoluteUrl(['/blog/post/preview', 'id' => $item->id])), [
'style' => 'font-size:11px;',
'target' => '_blank',
]) ?>
|
<?= Html::a(Yii::t('blog', 'Restore'), ['/blog/manage/post/restore-history', 'id' => $item->id], [
@ -183,7 +162,6 @@ $this->params['breadcrumbs'][] = $title;
</li>
<?php endforeach; ?>
</ul>
<?= Html::a(Yii::t('blog', 'Clear History'), ['/blog/manage/post/clear-history', 'id' => $post->id], [
'class' => 'btn btn-danger btn-sm pull-right',
'data' => [

2
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;

2
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',

7
common/modules/languages/views/manage/language/_form.php

@ -58,13 +58,12 @@ $this->registerJs($js2);
<div class="box-header with-border"><?= Yii::t('languages', 'Publish') ?></div>
<div class="box-body">
<?php if (!$model->_language->default): ?>
<?= $form->field($model, 'status')->radioList(LanguageHelper::statusList()) ?>
<?php else: ?>
<?php if (isset($model->_language->default) && $model->_language->default): ?>
<div class="callout callout-danger">
<p><?= Yii::t('languages', 'Status for default language is active always') ?></p>
</div>
<?php else: ?>
<?= $form->field($model, 'status')->radioList(LanguageHelper::statusList()) ?>
<?php endif; ?>
</div>
</div>

13
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,

30
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) {

4
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}}');
}
}

8
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);

3
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('&nbsp;&nbsp;', $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',
],

53
common/tests/_data/user.php

@ -1,14 +1,49 @@
<?php
return [
[
'username' => '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",
],
];

83
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();
}
}

14
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])

40
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()

7
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;
}
}

2
core/entities/Settings.php

@ -65,7 +65,7 @@ class Settings extends ActiveRecord
public function behaviors(): array
{
return [
TimestampBehavior::className(),
TimestampBehavior::class,
];
}
}

2
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]]',

13
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

4
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']) {

3
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] = '';

6
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'],
],
],
];

2
frontend/controllers/auth/AuthController.php

@ -24,7 +24,7 @@ class AuthController extends Controller
{
return [
'access' => [
'class' => AccessControl::className(),
'class' => AccessControl::class,
'rules' => [
[
'actions' => ['login'],

3
frontend/tests/fixtures/UserFixture.php vendored

@ -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;
}

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

@ -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",
],
];

35
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');
}*/
}

8
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',
<!-- Blog Post -->
<div class="card mb-4">
<a href="<?= $url ?>" title="<?= Html::encode($model->title) ?>"><img class="card-img-top" src="<?= Html::encode($model->getThumbFileUrl('image', 'blog_list')) ?>" alt="<?= Html::encode($model->title) ?>"></a>
<a href="<?= $url ?>" title="<?= Html::encode($model->translation->title) ?>"><img class="card-img-top" src="<?= Html::encode($model->getThumbFileUrl('image', 'blog_list')) ?>" alt="<?= Html::encode($model->translation->title) ?>"></a>
<div class="card-body">
<h2 class="card-title"><?= Html::encode($model->title) ?></h2>
<p class="card-text"><?= StringHelper::truncateWords(Html::encode($model->description), 30, '...') ?></p>
<a href="<?= $url ?>" class="btn btn-primary" title="<?= Html::encode($model->title) ?>"><?= Yii::t('blog_public', 'Read More') ?> &rarr;</a>
<h2 class="card-title"><?= Html::encode($model->translation->title) ?></h2>
<p class="card-text"><?= StringHelper::truncateWords(Html::encode($model->translation->description), 30, '...') ?></p>
<a href="<?= $url ?>" class="btn btn-primary" title="<?= Html::encode($model->translation->title) ?>"><?= Yii::t('blog_public', 'Read More') ?> &rarr;</a>
</div>
<div class="card-footer text-muted">
<time datetime="<?= date('Y') ?>"><?= Yii::$app->formatter->asDate($model->published_at, 'php:d F, Y') ?></time>

12
frontend/web/themes/start/modules/blog/views/post/post.php

@ -9,12 +9,12 @@ use yii\helpers\Url;
$this->title = $post->getSeoTitle();
$this->registerMetaTag(['name' =>'description', 'content' => $post->meta->description]);
$this->registerMetaTag(['name' =>'keywords', 'content' => $post->meta->keywords]);
$this->registerMetaTag(['name' =>'description', 'content' => $post->translation->meta_description]);
$this->registerMetaTag(['name' =>'keywords', 'content' => $post->translation->meta_keywords]);
$this->params['breadcrumbs'][] = ['label' => Yii::t('blog_public', 'Blog'), 'url' => ['/blog/post/index']];
$this->params['breadcrumbs'][] = ['label' => $post->category->name, 'url' => ['/blog/post/category', 'id' => $post->category->id]];
$this->params['breadcrumbs'][] = $post->title;
$this->params['breadcrumbs'][] = $post->translation->title;
$this->params['active_category'] = $post->category;
@ -30,7 +30,7 @@ $url_full = Yii::$app->params['frontendHostInfo'] . Url::to(['/blog/post/post',
<!-- Post Content Column -->
<!-- Title -->
<h1 class="mt-4"><?= Html::encode($post->title) ?></h1>
<h1 class="mt-4"><?= Html::encode($post->translation->title) ?></h1>
<hr>
@ -51,11 +51,11 @@ $url_full = Yii::$app->params['frontendHostInfo'] . Url::to(['/blog/post/post',
<hr>
<!-- Post Content -->
<p class="lead"><?= Html::encode($post->description) ?></p>
<p class="lead"><?= Html::encode($post->translation->description) ?></p>
<!-- < ?= $post->content ?> -->
<?= Yii::$app->formatter->asHtml($post->content, [
<?= Yii::$app->formatter->asHtml($post->translation->content, [
'Attr.AllowedRel' => array('nofollow'),
'HTML.SafeObject' => true,
'Output.FlashCompat' => true,

BIN
static/cache/posts/368_287_11.jpg vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

BIN
static/cache/posts/370_325_11.jpg vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

BIN
static/cache/posts/94_94_11.jpg vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

BIN
static/cache/posts/admin_11.jpg vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

BIN
static/cache/posts/home_slider_11.jpg vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

BIN
static/cache/posts/list_11.jpg vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

BIN
static/cache/posts/origin_11.jpg vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

BIN
static/cache/posts/thumb_11.jpg vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

BIN
static/cache/posts/thumb_gallery_view_11.jpg vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

BIN
static/origin/posts/10.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

BIN
static/origin/posts/11.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

BIN
static/origin/posts/5.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 924 KiB

BIN
static/origin/posts/6.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 240 KiB

Loading…
Cancel
Save