diff --git a/backend/components/menu/widgets/views/_item.php b/backend/components/menu/widgets/views/_item.php
index d4a3f0f..c888c72 100644
--- a/backend/components/menu/widgets/views/_item.php
+++ b/backend/components/menu/widgets/views/_item.php
@@ -5,10 +5,12 @@
*/
use yii\helpers\Html;
+use kartik\form\ActiveForm;
/**
* @var $this \yii\web\View
* @var $item array
+ * @var $model \core\forms\menu\MenuItemForm
*/
/* @var $menu_item \core\entities\menu\MenuItem */
@@ -23,96 +25,65 @@ $menu_item = $item['item'];
= Html::submitButton(Yii::t('buttons', 'Save'), ['class' => 'btn btn-success']) ?>
diff --git a/common/modules/pages/views/manage/page/_form_tab.php b/common/modules/pages/views/manage/page/_form_tab.php
new file mode 100644
index 0000000..c124b20
--- /dev/null
+++ b/common/modules/pages/views/manage/page/_form_tab.php
@@ -0,0 +1,29 @@
+params['defaultLanguage'] ? '' : '_' . $language;
+?>
+
+= $form->field($model, 'title' . $postfix)->textInput(['maxlength' => true]) ?>
+= $form->field($model, 'content' . $postfix)->widget(CKEditor::class) ?>
+
+
+
+
+ = $form->field($model, 'meta_title' . $postfix)->textInput() ?>
+ = $form->field($model, 'meta_description' . $postfix)->textarea(['rows' => 2]) ?>
+ = $form->field($model, 'meta_keywords' . $postfix)->textInput() ?>
+
+
diff --git a/common/modules/pages/views/manage/page/_view_tab.php b/common/modules/pages/views/manage/page/_view_tab.php
new file mode 100644
index 0000000..bc6827c
--- /dev/null
+++ b/common/modules/pages/views/manage/page/_view_tab.php
@@ -0,0 +1,71 @@
+
+
+= DetailView::widget([
+ 'model' => $page,
+ 'attributes' => [
+ [
+ 'label' => Yii::t('pages', 'Title'),
+ 'value' => function(Page $entity) use ($language) {
+ return $entity->findTranslation($language)->title;
+ }
+ ],
+ ],
+]) ?>
+
+
+
+
+
+= DetailView::widget([
+ 'model' => $page,
+ 'attributes' => [
+ [
+ 'label' => Yii::t('pages', 'META Title'),
+ 'value' => function(Page $entity) use ($language) {
+ return $entity->findTranslation($language)->meta_title;
+ }
+ ],
+ [
+ 'label' => Yii::t('pages', 'META Description'),
+ 'value' => function(Page $entity) use ($language) {
+ return $entity->findTranslation($language)->meta_description;
+ }
+ ],
+ [
+ 'label' => Yii::t('pages', 'META Keywords'),
+ 'value' => function(Page $entity) use ($language) {
+ return $entity->findTranslation($language)->meta_keywords;
+ }
+ ],
+ ],
+]) ?>
+
+
+
+
+
+
+ = Yii::$app->formatter->asHtml($page->findTranslation($language)->content, [
+ 'Attr.AllowedRel' => array('nofollow'),
+ 'HTML.SafeObject' => true,
+ 'Output.FlashCompat' => true,
+ 'HTML.SafeIframe' => true,
+ 'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%',
+ ]) ?>
+
+
\ No newline at end of file
diff --git a/common/modules/pages/views/manage/page/index.php b/common/modules/pages/views/manage/page/index.php
index 01dfdad..b99c454 100644
--- a/common/modules/pages/views/manage/page/index.php
+++ b/common/modules/pages/views/manage/page/index.php
@@ -28,7 +28,7 @@ $this->params['breadcrumbs'][] = $this->title;
'attribute' => 'title',
'value' => function (Page $model) {
$indent = ($model->depth > 1 ? str_repeat(' ', $model->depth - 1) . ' ' : '');
- return $indent . Html::a(Html::encode($model->title), ['view', 'id' => $model->id]);
+ return $indent . Html::a(Html::encode($model->translation->title), ['view', 'id' => $model->id]);
},
'format' => 'raw',
],
diff --git a/common/modules/pages/views/manage/page/update.php b/common/modules/pages/views/manage/page/update.php
index cea060a..cfefaf8 100644
--- a/common/modules/pages/views/manage/page/update.php
+++ b/common/modules/pages/views/manage/page/update.php
@@ -4,9 +4,9 @@
/* @var $page \common\modules\pages\entities\Page */
/* @var $model \common\modules\pages\forms\PageForm */
-$this->title = Yii::t('pages', 'Update Page: {name}', ['name' => $page->title]);
+$this->title = Yii::t('pages', 'Update Page: {name}', ['name' => $page->translation->title]);
$this->params['breadcrumbs'][] = ['label' => Yii::t('pages', 'Pages'), 'url' => ['index']];
-$this->params['breadcrumbs'][] = ['label' => $page->title, 'url' => ['view', 'id' => $page->id]];
+$this->params['breadcrumbs'][] = ['label' => $page->translation->title, 'url' => ['view', 'id' => $page->id]];
$this->params['breadcrumbs'][] = Yii::t('buttons', 'Editing');
?>
diff --git a/common/modules/pages/views/manage/page/view.php b/common/modules/pages/views/manage/page/view.php
index ec2920e..9dba667 100644
--- a/common/modules/pages/views/manage/page/view.php
+++ b/common/modules/pages/views/manage/page/view.php
@@ -7,9 +7,16 @@ use yii\widgets\DetailView;
/* @var $page \common\modules\pages\entities\Page */
/* @var $history \common\modules\pages\entities\Page[] */
-$this->title = $page->title;
+$this->title = $page->translation->title;
$this->params['breadcrumbs'][] = ['label' => Yii::t('pages', 'Pages'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
+
+$css = <<
registerCss($css);
?>
@@ -35,48 +42,30 @@ $this->params['breadcrumbs'][] = $this->title;
'model' => $page,
'attributes' => [
'id',
- 'title',
'slug',
],
]) ?>
-
-
-
- = Yii::$app->formatter->asHtml($page->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/)%',
- ]) ?>
-
-
-
-
-
-
- = DetailView::widget([
- 'model' => $page,
- 'attributes' => [
- [
- 'attribute' => 'meta.title',
- 'label' => Yii::t('main', 'Title'),
- ],
- [
- 'attribute' => 'meta.description',
- 'label' => Yii::t('main', 'Description'),
- ],
- [
- 'attribute' => 'meta.keywords',
- 'label' => Yii::t('main', 'Keywords'),
- ],
- ],
- ]) ?>
-
-
+ params['translatedLanguages'] as $language => $language_name) {
+ $items[] = [
+ 'label' => $language_name,
+ 'content' => $this->render('_view_tab', [
+ 'page' => $page,
+ 'language' => $language,
+ ]),
+ ];
+ }
+ ?>
+
+
+ = \yii\bootstrap\Tabs::widget([
+ 'items' => $items,
+ ]) ?>
+
diff --git a/common/modules/pages/widgets/MenuItemCreatorWidget.php b/common/modules/pages/widgets/MenuItemCreatorWidget.php
index a8bcebc..a0d1c90 100644
--- a/common/modules/pages/widgets/MenuItemCreatorWidget.php
+++ b/common/modules/pages/widgets/MenuItemCreatorWidget.php
@@ -16,9 +16,9 @@ class MenuItemCreatorWidget extends Widget
public function run()
{
$form = new MenuItemForm();
- $form->module = \Yii::t('pages', 'Pages');
- $form->name = \Yii::t('pages', 'Pages');
- $form->title_attr = \Yii::t('pages', 'Pages');
+ $form->module = 'pages';
+ $form->name = 'pages';
+ $form->title_attr = 'pages';
$form->menu_id = $this->menu_id;
$form->url = '/pages/page/index';
diff --git a/composer.json b/composer.json
index bd4a8e8..2b00c31 100644
--- a/composer.json
+++ b/composer.json
@@ -41,7 +41,9 @@
"paulzi/yii2-adjacency-list" : "^2.1",
"yiisoft/yii2-jui": "^2.0",
"zertex/yii2-elfinder": "^1.2",
- "zertex/yii2-ckeditor": "^1.0"
+ "zertex/yii2-ckeditor": "^1.0",
+ "omgdef/yii2-multilingual-behavior": "^2.1",
+ "kartik-v/yii2-detail-view": "@dev"
},
"require-dev": {
"yiisoft/yii2-debug": "~2.0.0",
diff --git a/console/migrations/m180824_081717_create_menu_lng_table.php b/console/migrations/m180824_081717_create_menu_lng_table.php
new file mode 100644
index 0000000..87873b3
--- /dev/null
+++ b/console/migrations/m180824_081717_create_menu_lng_table.php
@@ -0,0 +1,42 @@
+db->driverName === 'mysql') {
+ $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB';
+ }
+
+ $this->createTable('{{%menu_lng}}', [
+ 'id' => $this->primaryKey(),
+ 'menu_id' => $this->integer()->notNull(),
+ 'language' => $this->string(6)->notNull(),
+ 'name' => $this->string(255)->notNull(),
+ ], $tableOptions);
+
+ $this->createIndex('idx_menu_lng_language', '{{%menu_lng}}', 'language');
+ $this->createIndex('idx_menu_lng_menu_id', '{{%menu_lng}}', 'menu_id');
+ $this->addForeignKey('frg_menu_lng_menu_menu_id_id', '{{%menu_lng}}', 'menu_id', '{{%menu}}', 'id', 'CASCADE', 'CASCADE');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function safeDown()
+ {
+ $this->dropForeignKey('frg_menu_lng_menu_menu_id_id', '{{%menu_lng}}');
+ $this->dropColumn('idx_menu_lng_menu_id', '{{%menu_lng}}');
+ $this->dropColumn('idx_menu_lng_language', '{{%menu_lng}}');
+ $this->dropTable('{{%menu_lng}}');
+ }
+}
diff --git a/console/migrations/m180826_171901_remove_menu_name_field.php b/console/migrations/m180826_171901_remove_menu_name_field.php
new file mode 100644
index 0000000..b497f75
--- /dev/null
+++ b/console/migrations/m180826_171901_remove_menu_name_field.php
@@ -0,0 +1,25 @@
+dropColumn('{{%menu}}', 'name');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function safeDown()
+ {
+ $this->addColumn('{{%menu}}', 'name', $this->string(255)->notNull());
+ }
+}
diff --git a/console/migrations/m180826_204039_create_menu_items_lng_lng_table.php b/console/migrations/m180826_204039_create_menu_items_lng_lng_table.php
new file mode 100644
index 0000000..4034070
--- /dev/null
+++ b/console/migrations/m180826_204039_create_menu_items_lng_lng_table.php
@@ -0,0 +1,43 @@
+db->driverName === 'mysql') {
+ $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB';
+ }
+
+ $this->createTable('{{%menu_items_lng}}', [
+ 'id' => $this->primaryKey(),
+ 'menu_item_id' => $this->integer()->notNull(),
+ 'language' => $this->string(6)->notNull(),
+ 'name' => $this->string(255)->notNull(),
+ 'title_attr' => $this->string(255),
+ ], $tableOptions);
+
+ $this->createIndex('idx_menu_items_lng_language', '{{%menu_items_lng}}', 'language');
+ $this->createIndex('idx_menu_items_lng_page_id', '{{%menu_items_lng}}', 'menu_item_id');
+ $this->addForeignKey('frg_menu_items_lng_menu_items_menu_item_id_id', '{{%menu_items_lng}}', 'menu_item_id', '{{%menu_items}}', 'id', 'CASCADE', 'CASCADE');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function safeDown()
+ {
+ $this->dropForeignKey('frg_menu_items_lng_menu_items_menu_item_id_id', '{{%menu_items_lng}}');
+ $this->dropColumn('idx_menu_items_lng_page_id', '{{%menu_items_lng}}');
+ $this->dropColumn('idx_menu_items_lng_language', '{{%menu_items_lng}}');
+ $this->dropTable('{{%menu_items_lng}}');
+ }
+}
diff --git a/console/migrations/m180826_215830_remove_menu_items_name_title_attr_fields.php b/console/migrations/m180826_215830_remove_menu_items_name_title_attr_fields.php
new file mode 100644
index 0000000..b07e33d
--- /dev/null
+++ b/console/migrations/m180826_215830_remove_menu_items_name_title_attr_fields.php
@@ -0,0 +1,27 @@
+dropColumn('{{%menu_items}}', 'name');
+ $this->dropColumn('{{%menu_items}}', 'title_attr');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function safeDown()
+ {
+ $this->addColumn('{{%menu_items}}', 'name', $this->string(255)->notNull());
+ $this->addColumn('{{%menu_items}}', 'title_attr', $this->string(255));
+ }
+}
diff --git a/console/migrations/m180827_194913_set_core_tables_unicode_oollate.php b/console/migrations/m180827_194913_set_core_tables_unicode_oollate.php
new file mode 100644
index 0000000..3c6d093
--- /dev/null
+++ b/console/migrations/m180827_194913_set_core_tables_unicode_oollate.php
@@ -0,0 +1,33 @@
+getDb();
+ $db->createCommand('SET FOREIGN_KEY_CHECKS=0;')->execute();
+
+ foreach ($tables as $table) {
+ $db->createCommand( "ALTER TABLE `$table` CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci" )->execute();
+ }
+
+ $db->createCommand('SET FOREIGN_KEY_CHECKS=1;')->execute();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function safeDown()
+ {
+ true;
+ }
+}
diff --git a/core/behaviors/LanguageBehavior.php b/core/behaviors/LanguageBehavior.php
new file mode 100644
index 0000000..e62b0a8
--- /dev/null
+++ b/core/behaviors/LanguageBehavior.php
@@ -0,0 +1,351 @@
+ 'afterFind',
+ ActiveRecord::EVENT_AFTER_UPDATE => 'afterUpdate',
+ ActiveRecord::EVENT_AFTER_INSERT => 'afterInsert',
+ ActiveRecord::EVENT_AFTER_DELETE => 'afterDelete',
+ //ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate',
+ ];
+ }
+
+ public function attach( $owner ) {
+ /** @var ActiveRecord $owner */
+ parent::attach($owner);
+ if (empty($this->translatedLanguages) || !is_array($this->translatedLanguages)) {
+ throw new InvalidConfigException('Please specify array of available languages for the ' . get_class($this) . ' in the '
+ . get_class($this->owner) . ' or in the application parameters', 101);
+ }
+
+ if (array_values($this->translatedLanguages) !== $this->translatedLanguages) { //associative array
+ $this->translatedLanguages = array_keys($this->translatedLanguages);
+ }
+
+ if (!$this->defaultLanguage) {
+ throw new InvalidConfigException('Please specify default language for the ' . get_class($this));
+ }
+
+ if (empty($this->attributes) || !is_array($this->attributes)) {
+ throw new InvalidConfigException('Please specify translated attributes for the ' . get_class($this) . ' in the '
+ . get_class($this->owner), 103);
+ }
+
+ $this->ownerClassName = get_class($this->owner);
+ $this->ownerClassShortName = $this->getShortClassName($this->ownerClassName);
+
+ /** @var ActiveRecord $className */
+ $className = $this->ownerClassName;
+ $this->ownerPrimaryKey = $className::primaryKey()[0];
+
+ if (!isset($this->relativeField)) {
+ throw new InvalidConfigException('Please specify relativeField for the ' . get_class($this) . ' in the '
+ . get_class($this->owner), 105);
+ }
+
+ //$rules = $owner->rules();
+ //$validators = $owner->getValidators();
+ /*foreach ($rules as $rule) {
+ if (in_array($rule[1], $this->excludedValidators))
+ continue;
+ $rule_attributes = is_array($rule[0]) ? $rule[0] : [$rule[0]];
+ $attributes = array_intersect($this->attributes, $rule_attributes);
+ if (empty($attributes))
+ continue;
+ $rule_attributes = [];
+ foreach ($attributes as $key => $attribute) {
+ foreach ($this->languages as $language)
+ if ($language != $this->defaultLanguage)
+ $rule_attributes[] = $this->getAttributeName($attribute, $language);
+ }
+ if (isset($rule['skipOnEmpty']) && !$rule['skipOnEmpty'])
+ $rule['skipOnEmpty'] = !$this->requireTranslations;
+ $params = array_slice($rule, 2);
+ if ($rule[1] !== 'required' || $this->requireTranslations) {
+ $validators[] = Validator::createValidator($rule[1], $owner, $rule_attributes, $params);
+ } elseif ($rule[1] === 'required') {
+ $validators[] = Validator::createValidator('safe', $owner, $rule_attributes, $params);
+ }
+ }*/
+
+ $this->createLanguageClass();
+ $translation = new $this->virtualClassName;
+
+ foreach ($this->translatedLanguages as $language) {
+ foreach ($this->attributes as $attribute) {
+ $attributeName = $attribute;
+ $this->setLanguageAttribute($attribute . '_' . $language, $translation->{$attributeName});
+
+ //$this->owner->__set($attribute . '_' . $language, $translation->{$attributeName});
+ //$this->owner->{$attribute . '_' . $language} = $translation->{$attributeName};
+ //$this->owner->createProperty($attribute . '_' . $language, $translation->{$attributeName});
+
+ if ($language == $this->defaultLanguage) {
+ $this->setLanguageAttribute($attribute, $translation->{$attributeName});
+ //$this->owner->__set($attribute, $translation->{$attributeName});
+ }
+ }
+ }
+ }
+
+ /**
+ * Insert event
+ */
+ public function afterInsert()
+ {
+ $this->saveTranslations();
+ }
+
+ /**
+ * Update event
+ */
+ public function afterUpdate()
+ {
+ /** @var ActiveRecord $owner */
+ $owner = $this->owner;
+ if ($owner->isRelationPopulated('translations')) {
+ $translations = $this->indexByLanguage($owner->getRelatedRecords()['translations']);
+ $this->saveTranslations($translations);
+ }
+ }
+
+ /**
+ * Find event
+ */
+ public function afterFind()
+ {
+ /** @var ActiveRecord $owner */
+ $owner = $this->owner;
+ if ($owner->isRelationPopulated('translations') && $related = $owner->getRelatedRecords()['translations']) {
+ $translations = $this->indexByLanguage($related);
+ foreach ($this->translatedLanguages as $language) {
+ foreach ($this->attributes as $attribute) {
+ foreach ($translations as $translation) {
+ if ($translation->{$this->languageField} == $language) {
+ $attributeName = $attribute;
+ $this->setLanguageAttribute($attribute . '_' . $language, $translation->{$attributeName});
+ if ($language == $this->defaultLanguage) {
+ $this->setLanguageAttribute($attribute, $translation->{$attributeName});
+ }
+ }
+ }
+ }
+ }
+ } else {
+ if (!$owner->isRelationPopulated('translation')) {
+ $owner->translation;
+ }
+ $translation = $owner->getRelatedRecords()['translation'];
+ if ($translation) {
+ foreach ($this->attributes as $attribute) {
+ $attribute_name = $attribute;
+ $owner->setLanguageAttribute($attribute, $translation->$attribute_name);
+ }
+ }
+ }
+ foreach ($this->attributes as $attribute) {
+ if ($owner->hasAttribute($attribute) && $this->getLangAttribute($attribute)) {
+ $owner->setAttribute($attribute, $this->getLangAttribute($attribute));
+ }
+ }
+ }
+
+ public function afterDelete()
+ {
+ if ($this->forceDelete) {
+ /** @var ActiveRecord $owner */
+ $owner = $this->owner;
+ $owner->unlinkAll('translations', true);
+ }
+ }
+
+ public function createLanguageClass()
+ {
+ if (!class_exists($this->virtualClassName, false)) {
+ eval('
+ use yii\db\ActiveRecord;
+ class ' . $this->virtualClassName . ' extends ActiveRecord
+ {
+ public static function tableName()
+ {
+ return \'' . $this->tableName . '\';
+ }
+ }');
+ }
+ }
+
+ private function saveTranslations($translations = [])
+ {
+ /** @var ActiveRecord $owner */
+ $owner = $this->owner;
+ foreach ($this->translatedLanguages as $language) {
+ $isDefaultLanguage = $language == $this->defaultLanguage;
+ if (!isset($translations[$language])) {
+ /** @var ActiveRecord $translation */
+ $translation = new $this->virtualClassName;
+ $translation->{$this->languageField} = $language;
+ $translation->{$this->relativeField} = $owner->getPrimaryKey();
+ } else {
+ $translation = $translations[$language];
+ }
+ $save = false;
+ foreach ($this->attributes as $attribute) {
+ //$value = $isDefaultLanguage ? $owner->$attribute : $owner->{$attribute . '_' . $language};
+ $value = $isDefaultLanguage ? $owner->_form->$attribute : $owner->_form->{$attribute . '_' . $language};
+ if ($value !== null) {
+ //$field = $isDefaultLanguage ? $attribute : $attribute . '_' . $language;
+ $field = $attribute;
+ $translation->$field = $value;
+ $save = true;
+ }
+ }
+ if ($translation->isNewRecord && !$save) {
+ continue;
+ }
+ $translation->save();
+ }
+ }
+
+ private function getShortClassName($className)
+ {
+ return substr($className, strrpos($className, '\\') + 1);
+ }
+
+ public function setLanguageAttribute($name, $value)
+ {
+ $this->languageAttributes[$name] = $value;
+ }
+
+ protected function indexByLanguage(array $records)
+ {
+ $sorted = [];
+ foreach ($records as $record) {
+ $sorted[$record->{$this->languageField}] = $record;
+ }
+ unset($records);
+ return $sorted;
+ }
+
+ /**
+ * Relation to model translations
+ * @return ActiveQuery
+ */
+ public function getTranslations()
+ {
+ /** @var ActiveRecord */
+ return $this->owner->hasMany($this->virtualClassName, [$this->relativeField => $this->ownerPrimaryKey]);
+ }
+
+ public function getTranslation($language = null)
+ {
+ $language = $language ?: \Yii::$app->language;
+ // if translate exists
+ $translate = $this->virtualClassName::find()
+ ->andWhere([$this->relativeField => $this->owner->id])
+ ->andWhere([$this->languageField => $language])
+ ->one();
+
+ $language = $translate ? $language : \Yii::$app->params['defaultLanguage'];
+
+ return $this->owner->hasOne($this->virtualClassName, [$this->relativeField => $this->ownerPrimaryKey])
+ ->where([$this->languageField => $language]);
+ }
+
+ public function findTranslation($language = null)
+ {
+ $language = $language ?: \Yii::$app->language;
+ //$class = call_user_func(array($this->virtualClassName, 'getInstance'));
+ return $this->virtualClassName::find()
+ ->andWhere([$this->relativeField => $this->owner->id])
+ ->andWhere([$this->languageField => $language])
+ ->one();
+ }
+
+ public function hasLangAttribute($name)
+ {
+ return array_key_exists($name, $this->languageAttributes);
+ }
+
+ public function getLangAttribute($name)
+ {
+ return $this->hasLangAttribute($name) ? $this->languageAttributes[$name] : null;
+ }
+
+}
diff --git a/core/components/LanguageDynamicModel.php b/core/components/LanguageDynamicModel.php
new file mode 100644
index 0000000..68efba4
--- /dev/null
+++ b/core/components/LanguageDynamicModel.php
@@ -0,0 +1,64 @@
+getPublicAttributes(), $this->prepareLanguageAttributes()), $config );
+ }
+
+ private function prepareLanguageAttributes()
+ {
+ $language_attributes = [];
+ $labels = $this->attributeLabels();
+ $hints = $this->attributeHints();
+ foreach ($this->rules() as $rule) {
+ $attributes = is_array($rule[0]) ? $rule[0] : [$rule[0]];
+ $type = $rule[1];
+ if ($type == 'string') {
+ foreach (Yii::$app->params['translatedLanguages'] as $language => $language_name) {
+ $rule_attributes = [];
+ foreach ($attributes as $attribute) {
+ // add attribute
+ $language_attributes[] = $attribute . '_' . $language;
+ $this->new_labels[$attribute . '_' . $language] = isset($labels[$attribute]) ? $labels[$attribute] : null;
+ $this->new_hints[$attribute . '_' . $language] = isset($hints[$attribute]) ? $hints[$attribute] : null;
+ $rule_attributes[] = $attribute . '_' . $language;
+ }
+ // add rule
+ if (!empty($rule_attributes)) {
+ $this->new_rules[] = [ $rule_attributes, $rule[1] ];
+ }
+ }
+ }
+ }
+ return $language_attributes;
+ }
+
+ public function attributeLabels(){
+ return $this->new_labels;
+ }
+
+ public function rules() {
+ return $this->new_rules;
+ }
+
+ public function getPublicAttributes () {
+ return call_user_func('get_object_vars', $this);
+ }
+
+}
diff --git a/core/components/LanguageTranslateQuery.php b/core/components/LanguageTranslateQuery.php
new file mode 100644
index 0000000..8978637
--- /dev/null
+++ b/core/components/LanguageTranslateQuery.php
@@ -0,0 +1,15 @@
+language;
+ if (!isset($this->with['translations'])) {
+ $this->with(['translation' => function ($query) use ($language, $abridge) {
+ /** @var ActiveQuery $query */
+ $query->where([$this->languageField => $abridge ? substr($language, 0, 2) : $language]);
+ }]);
+ }
+ return $this;
+ }
+ /**
+ * Scope for querying by all languages
+ * @return $this
+ */
+ public function multilingual()
+ {
+ if (isset($this->with['translation'])) {
+ unset($this->with['translation']);
+ }
+ $this->with('translations');
+ return $this;
+ }
+}
\ No newline at end of file
diff --git a/core/components/TestForm.php b/core/components/TestForm.php
new file mode 100644
index 0000000..63b04de
--- /dev/null
+++ b/core/components/TestForm.php
@@ -0,0 +1,39 @@
+ 50],
+ ['content', 'string'],
+ ['number', 'integer'],
+ ]
+ );
+ }
+
+ public function attributeLabels() {
+ return array_merge(
+ parent::attributeLabels(),
+ [
+ 'name' => \Yii::t('main', 'Name'),
+ 'content' => \Yii::t('main', 'Key'),
+ 'number' => \Yii::t('main', 'Value'),
+ ]
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/core/entities/Meta.php b/core/entities/Meta.php
index f529925..1f39a25 100644
--- a/core/entities/Meta.php
+++ b/core/entities/Meta.php
@@ -2,6 +2,8 @@
namespace core\entities;
+use yii\helpers\Json;
+
class Meta
{
public $title;
@@ -14,4 +16,15 @@ class Meta
$this->description = $description;
$this->keywords = $keywords;
}
+
+ public static function createMeta($json): Meta
+ {
+ $meta = new Meta(null, null, null);
+ $meta_data = Json::decode($json);
+ $meta->title = isset($meta_data->title) ? $meta_data->title : '';
+ $meta->description = isset($meta_data->description) ? $meta_data->description : '';
+ $meta->keywords = isset($meta_data->keywords) ? $meta_data->keywords : '';
+ return $meta;
+ }
+
}
\ No newline at end of file
diff --git a/core/entities/menu/Menu.php b/core/entities/menu/Menu.php
index 711d6de..1d28eb3 100644
--- a/core/entities/menu/Menu.php
+++ b/core/entities/menu/Menu.php
@@ -6,6 +6,7 @@
namespace core\entities\menu;
+use core\behaviors\LanguageBehavior;
use yii\db\ActiveRecord;
/**
@@ -13,23 +14,30 @@ use yii\db\ActiveRecord;
* @package core\entities
*
* @property integer $id
- * @property string $name
+ *
+ * @method ActiveRecord findTranslation(string $language)
+ * @method void saveTranslations($translations)
+ *
+ * @property ActiveRecord[] translations
+ * @property ActiveRecord[] translation
*
* @property MenuItem[] $items
*/
class Menu extends ActiveRecord
{
- public static function create($name): self
+ public $_form;
+
+ public static function create($form): self
{
$menu = new static();
- $menu->name = $name;
+ $menu->_form = $form;
return $menu;
}
- public function edit($name): void
+ public function edit($form): void
{
- $this->name = $name;
+ $this->_form = $form;
}
public static function tableName(): string
@@ -41,4 +49,24 @@ class Menu extends ActiveRecord
{
return $this->hasMany(MenuItem::class, ['menu_id' => 'id'])->orderBy(['sort' => SORT_ASC]);
}
-}
\ No newline at end of file
+
+ public function behaviors()
+ {
+ return [
+ [
+ 'class' => LanguageBehavior::class,
+ 'virtualClassName' => 'MenuVirtualTranslate',
+ 'translatedLanguages' => \Yii::$app->params['translatedLanguages'],
+ 'relativeField' => 'menu_id',
+ 'tableName' => "{{%menu_lng}}",
+ 'attributes' => ['name'],
+ 'defaultLanguage' => \Yii::$app->params['defaultLanguage'],
+ ],
+ ];
+ }
+
+ /*public static function find()
+ {
+ return new LanguageTranslateQuery(get_called_class());
+ }*/
+}
diff --git a/core/entities/menu/MenuItem.php b/core/entities/menu/MenuItem.php
index f9cc849..5fc70b2 100644
--- a/core/entities/menu/MenuItem.php
+++ b/core/entities/menu/MenuItem.php
@@ -6,6 +6,7 @@
namespace core\entities\menu;
+use core\behaviors\LanguageBehavior;
use yii\db\ActiveRecord;
use yii\helpers\Json;
use yii\helpers\Url;
@@ -27,39 +28,46 @@ use yii\helpers\Url;
* @property string $url_params
* @property integer $sort
*
+ * @method ActiveRecord findTranslation(string $language)
+ * @method void saveTranslations($translations)
+ *
+ * @property ActiveRecord[] translations
+ * @property ActiveRecord[] translation
+ *
* @property MenuItem $parent
* @property MenuItem[] $children
+ * @property Menu $menu
*/
class MenuItem extends ActiveRecord
{
- public static function create($menu_id, $parent_id, $name, $title_attr, $target, $css, $style, $module, $url, $url_params): self
+ public $_form;
+
+ public static function create($form, $menu_id, $parent_id, $target, $css, $style, $module, $url, $url_params): self
{
$menu = new static();
$menu->menu_id = $menu_id;
$menu->parent_id = $parent_id;
- $menu->name = $name;
- $menu->title_attr = $title_attr;
$menu->target = $target;
$menu->css = $css;
$menu->style = $style;
$menu->module = $module;
$menu->url = $url;
$menu->url_params = $url_params;
+ $menu->_form = $form;
return $menu;
}
- public function edit($menu_id, $parent_id, $name, $title_attr, $target, $css, $style, $module, $url, $url_params): void
+ public function edit($form, $menu_id, $parent_id, $target, $css, $style, $module, $url, $url_params): void
{
$this->menu_id = $menu_id;
$this->parent_id = $parent_id;
- $this->name = $name;
- $this->title_attr = $title_attr;
$this->target = $target;
$this->css = $css;
$this->style = $style;
$this->module = $module;
$this->url = $url;
+ $this->_form = $form;
$this->url_params = $url_params;
}
@@ -124,4 +132,24 @@ class MenuItem extends ActiveRecord
{
return $this->hasOne(MenuItem::class, ['id' => 'parent_id']);
}
+
+ public function getMenu()
+ {
+ return $this->hasOne(Menu::class, ['id' => 'menu_id']);
+ }
+
+ public function behaviors()
+ {
+ return [
+ [
+ 'class' => LanguageBehavior::class,
+ 'virtualClassName' => 'MenuItemVirtualTranslate',
+ 'translatedLanguages' => \Yii::$app->params['translatedLanguages'],
+ 'relativeField' => 'menu_item_id',
+ 'tableName' => "{{%menu_items_lng}}",
+ 'attributes' => ['name', 'title_attr'],
+ 'defaultLanguage' => \Yii::$app->params['defaultLanguage'],
+ ],
+ ];
+ }
}
\ No newline at end of file
diff --git a/core/forms/CompositeLanguageForm.php b/core/forms/CompositeLanguageForm.php
new file mode 100644
index 0000000..9dce07e
--- /dev/null
+++ b/core/forms/CompositeLanguageForm.php
@@ -0,0 +1,110 @@
+forms as $name => $form) {
+ if (is_array($form)) {
+ $success = Model::loadMultiple($form, $data, $formName === null ? null : $name) && $success;
+ } else {
+ $success = $form->load($data, $formName !== '' ? null : $name) && $success;
+ }
+ }
+ return $success;
+ }
+
+ public function validate($attributeNames = null, $clearErrors = true): bool
+ {
+ $parentNames = $attributeNames !== null ? array_filter((array)$attributeNames, 'is_string') : null;
+ $success = parent::validate($parentNames, $clearErrors);
+ foreach ($this->forms as $name => $form) {
+ if (is_array($form)) {
+ $success = Model::validateMultiple($form) && $success;
+ } else {
+ $innerNames = $attributeNames !== null ? ArrayHelper::getValue($attributeNames, $name) : null;
+ $success = $form->validate($innerNames ?: null, $clearErrors) && $success;
+ }
+ }
+ return $success;
+ }
+
+ public function hasErrors($attribute = null): bool
+ {
+ if ($attribute !== null) {
+ return parent::hasErrors($attribute);
+ }
+ if (parent::hasErrors($attribute)) {
+ return true;
+ }
+ foreach ($this->forms as $name => $form) {
+ if (is_array($form)) {
+ foreach ($form as $i => $item) {
+ if ($item->hasErrors()) {
+ return true;
+ }
+ }
+ } else {
+ if ($form->hasErrors()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public function getFirstErrors(): array
+ {
+ $errors = parent::getFirstErrors();
+ foreach ($this->forms as $name => $form) {
+ if (is_array($form)) {
+ foreach ($form as $i => $item) {
+ foreach ($item->getFirstErrors() as $attribute => $error) {
+ $errors[$name . '.' . $i . '.' . $attribute] = $error;
+ }
+ }
+ } else {
+ foreach ($form->getFirstErrors() as $attribute => $error) {
+ $errors[$name . '.' . $attribute] = $error;
+ }
+ }
+ }
+ return $errors;
+ }
+
+ public function __get($name)
+ {
+ if (isset($this->forms[$name])) {
+ return $this->forms[$name];
+ }
+ return parent::__get($name);
+ }
+
+ public function __set($name, $value)
+ {
+ if (in_array($name, $this->internalForms(), true)) {
+ $this->forms[$name] = $value;
+ } else {
+ parent::__set($name, $value);
+ }
+ }
+
+ public function __isset($name)
+ {
+ return isset($this->forms[$name]) || parent::__isset($name);
+ }
+}
\ No newline at end of file
diff --git a/core/forms/MetaForm-org.php b/core/forms/MetaForm-org.php
new file mode 100644
index 0000000..ce9cbed
--- /dev/null
+++ b/core/forms/MetaForm-org.php
@@ -0,0 +1,40 @@
+title = $meta->title;
+ $this->description = $meta->description;
+ $this->keywords = $meta->keywords;
+ }
+ parent::__construct($config);
+ }
+
+ public function rules(): array
+ {
+ return [
+ [['title'], 'string', 'max' => 255],
+ [['description', 'keywords'], 'string'],
+ ];
+ }
+
+ public function attributeLabels() {
+ return [
+ 'title' => Yii::t('main', 'Title'),
+ 'description' => Yii::t('main', 'Description'),
+ 'keywords' => Yii::t('main', 'Keywords'),
+ ];
+ }
+}
\ No newline at end of file
diff --git a/core/forms/MetaForm.php b/core/forms/MetaForm.php
index 4927246..5e686a7 100644
--- a/core/forms/MetaForm.php
+++ b/core/forms/MetaForm.php
@@ -2,39 +2,56 @@
namespace core\forms;
+use core\components\LanguageDynamicModel;
use core\entities\Meta;
-use yii\base\Model;
use Yii;
-class MetaForm extends Model
+class MetaForm extends LanguageDynamicModel
{
public $title;
public $description;
public $keywords;
+ private $_meta;
+
public function __construct(Meta $meta = null, $config = [])
{
if ($meta) {
$this->title = $meta->title;
$this->description = $meta->description;
$this->keywords = $meta->keywords;
+ $this->_meta = $meta;
}
parent::__construct($config);
+ // fill translate values
+ /*if ($meta) {
+ foreach ( $meta->translations as $translate ) {
+ $this->{'title' . '_' . $translate->language} = $translate->title;
+ $this->{'description' . '_' . $translate->language} = $translate->description;
+ $this->{'keywords' . '_' . $translate->language} = $translate->keywords;
+ };
+ };*/
}
public function rules(): array
{
- return [
- [['title'], 'string', 'max' => 255],
- [['description', 'keywords'], 'string'],
- ];
+ return array_merge(
+ parent::rules(),
+ [
+ [['title'], 'string', 'max' => 255],
+ [['description', 'keywords'], 'string'],
+ ]
+ );
}
public function attributeLabels() {
- return [
- 'title' => Yii::t('main', 'Title'),
- 'description' => Yii::t('main', 'Description'),
- 'keywords' => Yii::t('main', 'Keywords'),
- ];
+ return array_merge(
+ parent::attributeLabels(),
+ [
+ 'title' => Yii::t('main', 'Title'),
+ 'description' => Yii::t('main', 'Description'),
+ 'keywords' => Yii::t('main', 'Keywords'),
+ ]
+ );
}
}
\ No newline at end of file
diff --git a/core/forms/menu/MenuForm.php b/core/forms/menu/MenuForm.php
index 1342aaa..d8c7383 100644
--- a/core/forms/menu/MenuForm.php
+++ b/core/forms/menu/MenuForm.php
@@ -2,36 +2,51 @@
namespace core\forms\menu;
+use core\components\LanguageDynamicModel;
use core\entities\menu\Menu;
-use yii\base\Model;
use Yii;
-class MenuForm extends Model
+class MenuForm extends LanguageDynamicModel
{
public $name;
private $_menu;
- public function __construct(Menu $menu = null, $config = [])
- {
- if ($menu) {
- $this->name = $menu->name;
- $this->_menu = $menu;
- }
- parent::__construct($config);
+ public function __construct( Menu $menu = null, array $attributes = [], array $config = [] ) {
+ 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;
+ }
+ };
+ };
}
public function rules(): array
{
- return [
- [['name'], 'required'],
- [['name'], 'string', 'max' => 255],
- ];
+ return array_merge(
+ parent::rules(),
+ [
+ [['name'], 'required'],
+ [['name'], 'string', 'max' => 255],
+ ]
+ );
}
public function attributeLabels() {
- return [
- 'name' => Yii::t('main', 'Name'),
- ];
+ return array_merge(
+ parent::attributeLabels(),
+ [
+ 'name' => Yii::t('main', 'Name'),
+ ]
+ );
}
}
diff --git a/core/forms/menu/MenuItemForm.php b/core/forms/menu/MenuItemForm.php
index 1244525..eb24989 100644
--- a/core/forms/menu/MenuItemForm.php
+++ b/core/forms/menu/MenuItemForm.php
@@ -2,11 +2,11 @@
namespace core\forms\menu;
+use core\components\LanguageDynamicModel;
use core\entities\menu\MenuItem;
-use yii\base\Model;
use Yii;
-class MenuItemForm extends Model
+class MenuItemForm extends LanguageDynamicModel
{
public $menu_id;
public $parent_id;
@@ -26,8 +26,6 @@ class MenuItemForm extends Model
if ($menu) {
$this->menu_id = $menu->menu_id;
$this->parent_id = $menu->parent_id;
- $this->name = $menu->name;
- $this->title_attr = $menu->title_attr;
$this->target = $menu->target;
$this->css = $menu->css;
$this->style = $menu->style;
@@ -38,31 +36,49 @@ class MenuItemForm extends Model
$this->_menu = $menu;
}
parent::__construct($config);
+ if ($menu) {
+ foreach ( $menu->translations as $translate ) {
+ if ($translate->language == Yii::$app->params['backendDefaultLanguage']) {
+ $this->name = $translate->name;
+ $this->title_attr = $translate->title_attr;
+ }
+ else {
+ $this->{'name' . '_' . $translate->language} = $translate->name;
+ $this->{'title_attr' . '_' . $translate->language} = $translate->title_attr;
+ }
+ };
+ }
}
public function rules(): array
{
- return [
- [['name', 'menu_id', 'url'], 'required'],
- [['name', 'title_attr', 'css', 'style', 'module', 'url'], 'string', 'max' => 255],
- [['target'], 'string', 'max' => 20],
- ['url_params', 'string'],
- [['parent_id', 'menu_id'], 'integer'],
- ];
+ return array_merge(
+ parent::rules(),
+ [
+ [['name', 'menu_id'], 'required'],
+ [['name', 'title_attr', 'css', 'style', 'module', 'url'], 'string', 'max' => 255],
+ [['target'], 'string', 'max' => 20],
+ ['url_params', 'string'],
+ [['parent_id', 'menu_id'], 'integer'],
+ ]
+ );
}
public function attributeLabels() {
- return [
- 'menu_id' => Yii::t('main', 'Menu'),
- 'parent id' => Yii::t('main', 'Parent menu item'),
- 'name' => Yii::t('main', 'Name'),
- 'title_attr' => Yii::t('main', 'Title attribute'),
- 'target' => Yii::t('main', 'Target'),
- 'css' => Yii::t('main', 'CSS Classes'),
- 'style' => Yii::t('main', 'CSS Style'),
- 'module' => Yii::t('main', 'Module'),
- 'url' => Yii::t('main', 'Url'),
- 'url_params' => Yii::t('main', 'Url Params'),
- ];
+ return array_merge(
+ parent::attributeLabels(),
+ [
+ 'menu_id' => Yii::t('menu', 'Menu'),
+ 'parent id' => Yii::t('menu', 'Parent menu item'),
+ 'name' => Yii::t('menu', 'Name'),
+ 'title_attr' => Yii::t('menu', 'Title attribute'),
+ 'target' => Yii::t('menu', 'Target'),
+ 'css' => Yii::t('menu', 'CSS Classes'),
+ 'style' => Yii::t('menu', 'CSS Style'),
+ 'module' => Yii::t('menu', 'Module'),
+ 'url' => Yii::t('menu', 'Url'),
+ 'url_params' => Yii::t('menu', 'Url Params'),
+ ]
+ );
}
}
diff --git a/core/helpers/LanguageHelper.php b/core/helpers/LanguageHelper.php
new file mode 100644
index 0000000..b19d42b
--- /dev/null
+++ b/core/helpers/LanguageHelper.php
@@ -0,0 +1,119 @@
+params['translatedLanguages']) > 1;
+ }
+
+ public static function suffixList()
+ {
+ $list = array();
+ $enabled = self::enabled();
+
+ foreach (Yii::$app->params['translatedLanguages'] as $lang => $name) {
+ if ($lang === Yii::$app->params['defaultLanguage']) {
+ $suffix = '';
+ $list[$suffix] = $enabled ? $name : '';
+ } else {
+ $suffix = '_' . $lang;
+ $list[$suffix] = $name;
+ }
+ }
+
+ return $list;
+ }
+
+ public static function isLangExists($url): bool
+ {
+ $index = self::_getLangIndex();
+ $domains = explode('/', ltrim($url, '/'));
+ return in_array($domains[$index], array_keys(Yii::$app->params['translatedLanguages']));
+ }
+
+ public static function setLanguage($url)
+ {
+ $index = self::_getLangIndex();
+ $domains = explode('/', ltrim($url, '/'));
+ $isLangExists = in_array($domains[$index], array_keys(Yii::$app->params['translatedLanguages']));
+ if ($isLangExists) {
+ Yii::$app->language = $domains[$index];
+ }
+ else {
+ Yii::$app->language = Yii::$app->params['defaultLanguage'];
+ }
+ }
+
+ public static function processLangInUrl($url): string
+ {
+ if (self::enabled()) {
+ $index = self::_getLangIndex();
+ $domains = explode('/', ltrim($url, '/'));
+ $isLangExists = in_array($domains[$index], array_keys(Yii::$app->params['translatedLanguages']));
+ $isDefaultLang = $domains[$index] == Yii::$app->params['defaultLanguage'];
+
+ if ($isLangExists && !$isDefaultLang) {
+ array_splice($domains, $index, 1);
+ }
+ $url = '/' . implode('/', $domains);
+ }
+ return $url;
+ }
+
+ public static function addLangToUrl($url, $language = null): string
+ {
+ if (self::enabled()) {
+ $index = self::_getLangIndex();
+ $domains = explode('/', ltrim($url, '/'));
+ $isHasLang = in_array($language ?: $domains[$index], array_keys(Yii::$app->params['translatedLanguages']));
+ $isDefaultLang = $language ? $language == Yii::$app->params['defaultLanguage'] : Yii::$app->language == Yii::$app->params['defaultLanguage'];
+
+ if ($isHasLang && $isDefaultLang) {
+ array_splice($domains, $index, 1);
+ }
+
+ if (!$isHasLang && !$isDefaultLang) {
+ array_splice($domains, $index, 0, Yii::$app->language);
+ }
+
+ $domains = array_filter($domains);
+ $url = '/' . implode('/', $domains);
+ }
+ return $url;
+ }
+
+ public static function getName($language)
+ {
+ return isset(Yii::$app->params['translatedLanguages'][$language]) ? Yii::$app->params['translatedLanguages'][$language] : $language;
+ }
+
+ public static function getBackendName($language)
+ {
+ return isset(Yii::$app->params['backendTranslatedLanguages'][$language]) ? Yii::$app->params['backendTranslatedLanguages'][$language] : Yii::$app->params['backendTranslatedLanguages'][Yii::$app->params['backendDefaultLanguage']];
+ }
+
+ private static function _getLangIndex(): int
+ {
+ $index = 0;
+ $baseUrl = ltrim(Yii::$app->request->baseUrl, '/');
+
+ if (strlen($baseUrl)) {
+ $baseUrlChunks = explode('/', $baseUrl);
+ if (count($baseUrlChunks) > 0) {
+ $index = count( $baseUrlChunks );
+ }
+ }
+ return $index;
+ }
+}
diff --git a/core/repositories/menu/MenuItemRepository.php b/core/repositories/menu/MenuItemRepository.php
index a1d30d4..b487260 100644
--- a/core/repositories/menu/MenuItemRepository.php
+++ b/core/repositories/menu/MenuItemRepository.php
@@ -9,7 +9,8 @@ class MenuItemRepository
{
public function get($id): MenuItem
{
- if (!$item = MenuItem::findOne($id)) {
+ if (!$item = MenuItem::find()->with('translations')->andWhere(['id' => $id])->one()) {
+ //if (!$item = MenuItem::findOne($id)) {
throw new NotFoundException('Menu is not found.');
}
return $item;
diff --git a/core/repositories/menu/MenuRepository.php b/core/repositories/menu/MenuRepository.php
index 6b5e1fe..03eb61e 100644
--- a/core/repositories/menu/MenuRepository.php
+++ b/core/repositories/menu/MenuRepository.php
@@ -9,7 +9,8 @@ class MenuRepository
{
public function get($id): Menu
{
- if (!$menu = Menu::findOne($id)) {
+ //if (!$menu = Menu::findOne($id)) {
+ if (!$menu = Menu::find()->with('translations')->andWhere(['id' => $id])->one()) {
throw new NotFoundException('Menu is not found.');
}
return $menu;
diff --git a/core/services/menu/MenuItemManageService.php b/core/services/menu/MenuItemManageService.php
index 194c0e1..a86ed14 100644
--- a/core/services/menu/MenuItemManageService.php
+++ b/core/services/menu/MenuItemManageService.php
@@ -18,10 +18,9 @@ class MenuItemManageService
public function create(MenuItemForm $form): MenuItem
{
$menu = MenuItem::create(
+ $form,
$form->menu_id,
$form->parent_id,
- $form->name,
- $form->title_attr,
$form->target,
$form->css,
$form->style,
@@ -37,10 +36,9 @@ class MenuItemManageService
{
$menu = $this->repository->get($id);
$menu->edit(
+ $form,
$form->menu_id,
$form->parent_id,
- $form->name,
- $form->title_attr,
$form->target,
$form->css,
$form->style,
diff --git a/core/services/menu/MenuManageService.php b/core/services/menu/MenuManageService.php
index b079f39..866bb32 100644
--- a/core/services/menu/MenuManageService.php
+++ b/core/services/menu/MenuManageService.php
@@ -18,7 +18,7 @@ class MenuManageService
public function create(MenuForm $form): Menu
{
$menu = Menu::create(
- $form->name
+ $form
);
$this->repository->save($menu);
return $menu;
@@ -28,7 +28,7 @@ class MenuManageService
{
$menu = $this->repository->get($id);
$menu->edit(
- $form->name
+ $form
);
$this->repository->save($menu);
}
diff --git a/core/services/user/UserManageService.php b/core/services/user/UserManageService.php
index acac74e..d710103 100644
--- a/core/services/user/UserManageService.php
+++ b/core/services/user/UserManageService.php
@@ -68,6 +68,15 @@ class UserManageService
});
}
+ public function setBackendLanguage($language): void
+ {
+ if (in_array($language, array_keys(\Yii::$app->params['backendTranslatedLanguages']))) {
+ $user = $this->repository->get(\Yii::$app->user->id);
+ $user->backend_language = $language;
+ $this->repository->save($user);
+ }
+ }
+
public function assignRole($id, $role): void
{
$user = $this->repository->get($id);
diff --git a/core/widgets/menu/MenuWidget.php b/core/widgets/menu/MenuWidget.php
index 7a56d05..847451d 100644
--- a/core/widgets/menu/MenuWidget.php
+++ b/core/widgets/menu/MenuWidget.php
@@ -15,6 +15,7 @@ class MenuWidget extends Widget
public function run() {
$menu = Menu::findOne($this->menu_id);
+
return $this->render('menu', [
'menu' => $menu,
]);
diff --git a/core/widgets/menu/views/menu.php b/core/widgets/menu/views/menu.php
index 8025e30..caf8b8c 100644
--- a/core/widgets/menu/views/menu.php
+++ b/core/widgets/menu/views/menu.php
@@ -24,7 +24,7 @@
parent_id == 0): ?>
-