diff --git a/.editorconfig b/.editorconfig
index b58baa8..d705472 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -45,7 +45,7 @@ indent_size=2
indent_style=space
indent_size=2
-[{*.yml,*.yaml}]
+[{*.yml,*.yaml,*.xml}]
indent_style=space
indent_size=2
diff --git a/README.md b/README.md
index 6acca0f..9e364e6 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,5 @@
-
-
-
-
Yii 2 Advanced Project Template
+ ZxCMS - Yii2 site management system
@@ -17,10 +14,6 @@ deploying the application in different environments.
Documentation is at [docs/guide/README.md](docs/guide/README.md).
-[![Latest Stable Version](https://poser.pugx.org/yiisoft/yii2-app-advanced/v/stable.png)](https://packagist.org/packages/yiisoft/yii2-app-advanced)
-[![Total Downloads](https://poser.pugx.org/yiisoft/yii2-app-advanced/downloads.png)](https://packagist.org/packages/yiisoft/yii2-app-advanced)
-[![Build Status](https://travis-ci.org/yiisoft/yii2-app-advanced.svg?branch=master)](https://travis-ci.org/yiisoft/yii2-app-advanced)
-
DIRECTORY STRUCTURE
-------------------
diff --git a/backend/bootstrap/SetUp.php b/backend/bootstrap/SetUp.php
index 9a1c71e..872eb09 100644
--- a/backend/bootstrap/SetUp.php
+++ b/backend/bootstrap/SetUp.php
@@ -2,9 +2,11 @@
namespace backend\bootstrap;
+use core\entities\Settings;
use mihaildev\ckeditor\CKEditor;
use mihaildev\elfinder\ElFinder;
use yii\base\BootstrapInterface;
+use yii\helpers\ArrayHelper;
class SetUp implements BootstrapInterface
{
@@ -14,5 +16,19 @@ class SetUp implements BootstrapInterface
$container->set(CKEditor::class, [
'editorOptions' => ElFinder::ckeditorOptions('elfinder', []),
]);
+
+ // load settings
+ $settings = ArrayHelper::map(Settings::find()->andWhere(['active' => 1])->all(), 'key', 'value', 'section');
+ $app->params['settings'] = $settings;
+
+ // Connect backend modules
+
+ // Add finish UrlRules
+ $app->getUrlManager()->addRules([
+ '<_c:[\w\-]+>' => '<_c>/index',
+ '<_c:[\w\-]+>/' => '<_c>/view',
+ '<_c:[\w\-]+>/<_a:[\w-]+>' => '<_c>/<_a>',
+ '<_c:[\w\-]+>//<_a:[\w\-]+>' => '<_c>/<_a>',
+ ]);
}
}
\ No newline at end of file
diff --git a/backend/components/ToggleAction.php b/backend/components/ToggleAction.php
new file mode 100644
index 0000000..4c4a191
--- /dev/null
+++ b/backend/components/ToggleAction.php
@@ -0,0 +1,113 @@
+request->getIsPost()) {
+ throw new MethodNotAllowedHttpException();
+ }
+ $id = (int)$id;
+ $result = null;
+ if (empty($this->modelClass) || !class_exists($this->modelClass)) {
+ throw new InvalidConfigException("Model class doesn't exist");
+ }
+ /* @var $modelClass \yii\db\ActiveRecord */
+ $modelClass = $this->modelClass;
+ $attribute = $this->attribute;
+ $model = $modelClass::find()->where([$this->primaryKey => $id]);
+ if (!empty($this->andWhere)) {
+ $model->andWhere($this->andWhere);
+ }
+ $model = $model->one();
+ if (!is_null($this->scenario)) {
+ $model->scenario = $this->scenario;
+ }
+ if (!$model->hasAttribute($this->attribute)) {
+ throw new InvalidConfigException("Attribute doesn't exist");
+ }
+ if ($model->$attribute == $this->onValue) {
+ $model->$attribute = $this->offValue;
+ } elseif ($this->onValue instanceof Expression && $model->$attribute != $this->offValue) {
+ $model->$attribute = $this->offValue;
+ } else {
+ $model->$attribute = $this->onValue;
+ }
+ if ($model->save()) {
+ if ($this->setFlash) {
+ Yii::$app->session->setFlash('success', $this->flashSuccess);
+ }
+ } else {
+ if ($this->setFlash) {
+ Yii::$app->session->setFlash('error', $this->flashError);
+ }
+ }
+ if (Yii::$app->request->getIsAjax()) {
+ Yii::$app->end();
+ }
+ /* @var $controller \yii\web\Controller */
+ $controller = $this->controller;
+ if (!empty($this->redirect)) {
+ return $controller->redirect($this->redirect);
+ }
+ return $controller->redirect(Yii::$app->request->getReferrer());
+ }
+}
\ No newline at end of file
diff --git a/backend/components/ToggleColumn.php b/backend/components/ToggleColumn.php
new file mode 100644
index 0000000..0a2823c
--- /dev/null
+++ b/backend/components/ToggleColumn.php
@@ -0,0 +1,143 @@
+onText === null) {
+ $this->onText = Yii::t('main', 'On');
+ }
+ if ($this->offText === null) {
+ $this->offText = Yii::t('main', 'Off');
+ }
+ if ($this->onValueText === null) {
+ $this->onValueText = Yii::t('main', 'Active');
+ }
+ if ($this->offValueText === null) {
+ $this->offValueText = Yii::t('main', 'Inactive');
+ }
+ if ($this->enableAjax) {
+ $this->registerJs();
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function renderDataCellContent($model, $key, $index)
+ {
+ $url = [$this->action, 'id' => $model->{$this->primaryKey}];
+
+ $attribute = $this->attribute;
+ $value = $model->$attribute;
+
+ if ($value === null || $value == true) {
+ $icon = $this->iconOn;
+ $title = $this->offText;
+ $valueText = $this->onValueText;
+ $color = 'green';
+ } else {
+ $icon = $this->iconOff;
+ $title = $this->onText;
+ $valueText = $this->offValueText;
+ $color = 'red';
+ }
+ return Html::a(
+ '',
+ $url,
+ [
+ 'title' => $title,
+ 'class' => 'toggle-column',
+ 'style' => 'color:' . $color,
+ 'data-method' => 'post',
+ 'data-pjax' => '0',
+ ]
+ ) . ( $this->displayValueText ? " {$valueText}" : "" );
+ }
+
+ /**
+ * Registers the ajax JS
+ */
+ public function registerJs()
+ {
+ if(Yii::$app->request->isAjax) {
+ return;
+ }
+ $js = <<<'JS'
+$(document.body).on("click", "a.toggle-column", function(e) {
+ e.preventDefault();
+ $.post($(this).attr("href"), function(data) {
+ var pjaxId = $(e.target).closest("[data-pjax-container]").attr("id");
+ $.pjax.reload({container:"#" + pjaxId});
+ });
+ return false;
+});
+JS;
+ $this->grid->view->registerJs($js, View::POS_READY, 'zx-toggle-column');
+ }
+}
\ No newline at end of file
diff --git a/backend/config/urlManager.php b/backend/config/urlManager.php
index 30a648e..4d4641d 100644
--- a/backend/config/urlManager.php
+++ b/backend/config/urlManager.php
@@ -12,9 +12,10 @@ return [
'' => 'site/index',
'<_a:login|logout>' => 'auth/<_a>',
+ /* Moved to end of bootstrap - SetUp.php
'<_c:[\w\-]+>' => '<_c>/index',
'<_c:[\w\-]+>/' => '<_c>/view',
'<_c:[\w\-]+>/<_a:[\w-]+>' => '<_c>/<_a>',
- '<_c:[\w\-]+>//<_a:[\w\-]+>' => '<_c>/<_a>',
+ '<_c:[\w\-]+>//<_a:[\w\-]+>' => '<_c>/<_a>',*/
],
];
diff --git a/backend/controllers/SettingsController.php b/backend/controllers/SettingsController.php
new file mode 100644
index 0000000..25b7b2b
--- /dev/null
+++ b/backend/controllers/SettingsController.php
@@ -0,0 +1,150 @@
+service = $service;
+ }
+
+ public function behaviors()
+ {
+ return [
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'delete' => ['POST'],
+ ],
+ ],
+ 'access' => [
+ 'class' => AccessControl::className(),
+ 'rules' => [
+ [
+ 'actions' => ['create','view','index', 'update', 'delete', 'toggle'],
+ 'allow' => true,
+ 'roles' => ['SettingsManagement'],
+ ],
+ [ // all the action are accessible to admin
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ ];
+ }
+
+ public function actions()
+ {
+ return [
+ 'toggle' => [
+ 'class' => ToggleAction::className(),
+ 'modelClass' => Settings::class,
+ //'setFlash' => true,
+ ]
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $searchModel = new SettingsSearch();
+ $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
+ return $this->render(
+ 'index',
+ [
+ 'searchModel' => $searchModel,
+ 'dataProvider' => $dataProvider,
+ ]
+ );
+ }
+
+ public function actionView($id)
+ {
+ return $this->render(
+ 'view',
+ [
+ 'model' => $this->findModel($id),
+ ]
+ );
+ }
+
+ public function actionCreate()
+ {
+ $form = new SettingsForm();
+ if ($form->load(Yii::$app->request->post()) && $form->validate()) {
+ try {
+ $settings = $this->service->create($form);
+ return $this->redirect(['view', 'id' => $settings->id]);
+ } catch (\DomainException $e) {
+ Yii::$app->errorHandler->logException($e);
+ Yii::$app->session->setFlash('error', $e->getMessage());
+ }
+ }
+ else {
+ $form->active = 1;
+ }
+ return $this->render(
+ 'create',
+ [
+ 'model' => $form,
+ ]
+ );
+ }
+
+ public function actionUpdate($id)
+ {
+ $settings = $this->findModel($id);
+
+ $form = new SettingsForm($settings);
+ if ($form->load(Yii::$app->request->post()) && $form->validate()) {
+ try {
+ $this->service->edit($settings->id, $form);
+ return $this->redirect(['view', 'id' => $settings->id]);
+ } catch (\DomainException $e) {
+ Yii::$app->errorHandler->logException($e);
+ Yii::$app->session->setFlash('error', $e->getMessage());
+ }
+ }
+ return $this->render(
+ 'update',
+ [
+ 'model' => $form,
+ 'settings' => $settings,
+ ]
+ );
+ }
+
+ public function actionDelete($id)
+ {
+ $this->service->remove($id);
+ return $this->redirect(['index']);
+ }
+
+ protected function findModel($id)
+ {
+ if (($model = Settings::findOne($id)) !== null) {
+ return $model;
+ } else {
+ throw new NotFoundHttpException('The requested page does not exist.');
+ }
+ }
+}
\ No newline at end of file
diff --git a/backend/forms/SettingsSearch.php b/backend/forms/SettingsSearch.php
new file mode 100644
index 0000000..42f101f
--- /dev/null
+++ b/backend/forms/SettingsSearch.php
@@ -0,0 +1,66 @@
+ $query,
+ ]
+ );
+ if (!($this->load($params) && $this->validate())) {
+ return $dataProvider;
+ }
+ $query->andFilterWhere(
+ [
+ 'id' => $this->id,
+ 'active' => $this->active,
+ 'section' => $this->section,
+ ]
+ );
+ $query->andFilterWhere(['like', 'key', $this->key])
+ ->andFilterWhere(['like', 'value', $this->value]);
+ return $dataProvider;
+ }
+
+}
\ No newline at end of file
diff --git a/backend/messages/ru/buttons.php b/backend/messages/ru/buttons.php
index 8038f70..657a957 100644
--- a/backend/messages/ru/buttons.php
+++ b/backend/messages/ru/buttons.php
@@ -7,4 +7,6 @@ return [
'Delete' => 'Удалить',
'Edit' => 'Изменить',
'Editing' => 'Редактирование',
+ 'All Settings' => 'Все настройки',
+ 'Create Setting' => 'Новый параметр',
];
\ No newline at end of file
diff --git a/backend/messages/ru/main.php b/backend/messages/ru/main.php
index 0071bde..f5e1cd7 100644
--- a/backend/messages/ru/main.php
+++ b/backend/messages/ru/main.php
@@ -8,4 +8,20 @@ return [
'Profile' => 'Профиль',
'Error' => 'Ошибка',
'Return to back or login page please.' => 'Вернитесь назад или авторизуйтесь снова.',
+ '{attribute} "{value}" already exists for this section.' => '{attribute} "{value}" уже есть в этом разделе.',
+ '"{attribute}" must be a valid JSON object' => '"{attribute}" должен быть в формате Json',
+ 'Please select correct type' => 'Укажите правильный тип',
+ 'Settings' => 'Настройки',
+ 'Type' => 'Тип',
+ 'Section' => 'Раздел',
+ 'Key' => 'Ключ',
+ 'Value' => 'Значение',
+ 'Active' => 'Активная',
+ 'Created At' => 'Создано',
+ 'Updated At' => 'Обновлено',
+ 'On' => 'Включить',
+ 'Off' => 'Выключить',
+ 'Updating Setting' => 'Редактирование параметра',
+ 'Editing' => 'Редактирование',
+ 'Change at your own risk' => 'Редактируйте на свой страх и риск',
];
\ No newline at end of file
diff --git a/backend/views/layouts/header.php b/backend/views/layouts/header.php
index 9fc4146..24c9ab3 100644
--- a/backend/views/layouts/header.php
+++ b/backend/views/layouts/header.php
@@ -1,13 +1,16 @@
- = Html::a('APP' . Yii::$app->name . '', Yii::$app->homeUrl, ['class' => 'logo']) ?>
+ = Html::a(''.(isset(Yii::$app->params['settings']['site']['short_name']) ? Yii::$app->params['settings']['site']['short_name'] : 'APP').'' . (isset(Yii::$app->params['settings']['site']['name']) ? Yii::$app->params['settings']['site']['name'] : Yii::$app->name) . '', Yii::$app->homeUrl, ['class' => 'logo']) ?>