Commit fd238f57919408dbd91ae5d9d5c8fe4cddaaed7f
1 parent
93c267f7
Admin begin refactor.
Showing
8 changed files
with
257 additions
and
115 deletions
Show diff stats
backend/controllers/ArticlesController.php
@@ -9,7 +9,6 @@ | @@ -9,7 +9,6 @@ | ||
9 | use yii\web\NotFoundHttpException; | 9 | use yii\web\NotFoundHttpException; |
10 | use yii\filters\VerbFilter; | 10 | use yii\filters\VerbFilter; |
11 | use developeruz\db_rbac\behaviors\AccessBehavior; | 11 | use developeruz\db_rbac\behaviors\AccessBehavior; |
12 | - use yii\web\UploadedFile; | ||
13 | 12 | ||
14 | /** | 13 | /** |
15 | * ArticlesController implements the CRUD actions for Articles model. | 14 | * ArticlesController implements the CRUD actions for Articles model. |
@@ -86,18 +85,12 @@ | @@ -86,18 +85,12 @@ | ||
86 | $model_langs = $model->generateLangs(); | 85 | $model_langs = $model->generateLangs(); |
87 | if($model->load(Yii::$app->request->post())) { | 86 | if($model->load(Yii::$app->request->post())) { |
88 | $model->loadLangs(\Yii::$app->request, $model_langs); | 87 | $model->loadLangs(\Yii::$app->request, $model_langs); |
89 | - if($model->save()) { | ||
90 | - if($model->linkLangs($model_langs) && $model->saveLangs($model_langs)) { | ||
91 | - return $this->redirect([ | ||
92 | - 'view', | ||
93 | - 'id' => $model->id, | ||
94 | - ]); | ||
95 | - } else { | ||
96 | - return $this->redirect([ | ||
97 | - 'update', | ||
98 | - 'id' => $model->id, | ||
99 | - ]); | ||
100 | - } | 88 | + $model->model_langs = $model_langs; |
89 | + if($model->save() && $model->transactionStatus) { | ||
90 | + return $this->redirect([ | ||
91 | + 'view', | ||
92 | + 'id' => $model->id, | ||
93 | + ]); | ||
101 | } | 94 | } |
102 | } | 95 | } |
103 | return $this->render('create', [ | 96 | return $this->render('create', [ |
@@ -120,13 +113,12 @@ | @@ -120,13 +113,12 @@ | ||
120 | $model_langs = $model->generateLangs(); | 113 | $model_langs = $model->generateLangs(); |
121 | if($model->load(Yii::$app->request->post())) { | 114 | if($model->load(Yii::$app->request->post())) { |
122 | $model->loadLangs(\Yii::$app->request, $model_langs); | 115 | $model->loadLangs(\Yii::$app->request, $model_langs); |
123 | - if($model->save()) { | ||
124 | - if($model->linkLangs($model_langs) && $model->saveLangs($model_langs)) { | ||
125 | - return $this->redirect([ | ||
126 | - 'view', | ||
127 | - 'id' => $model->id, | ||
128 | - ]); | ||
129 | - } | 116 | + $model->model_langs = $model_langs; |
117 | + if($model->save() && $model->transactionStatus) { | ||
118 | + return $this->redirect([ | ||
119 | + 'view', | ||
120 | + 'id' => $model->id, | ||
121 | + ]); | ||
130 | } | 122 | } |
131 | } | 123 | } |
132 | return $this->render('update', [ | 124 | return $this->render('update', [ |
@@ -162,7 +154,11 @@ | @@ -162,7 +154,11 @@ | ||
162 | */ | 154 | */ |
163 | protected function findModel($id) | 155 | protected function findModel($id) |
164 | { | 156 | { |
165 | - if(( $model = Articles::findOne($id) ) !== NULL) { | 157 | + if(( $model = Articles::find() |
158 | + ->where([ 'id' => $id ]) | ||
159 | + ->with('lang') | ||
160 | + ->one() ) !== NULL | ||
161 | + ) { | ||
166 | return $model; | 162 | return $model; |
167 | } else { | 163 | } else { |
168 | throw new NotFoundHttpException('The requested page does not exist.'); | 164 | throw new NotFoundHttpException('The requested page does not exist.'); |
backend/views/articles/index.php
1 | <?php | 1 | <?php |
2 | - | ||
3 | -use yii\helpers\Html; | ||
4 | -use yii\grid\GridView; | ||
5 | - | ||
6 | -/* @var $this yii\web\View */ | ||
7 | -/* @var $searchModel common\models\ArticlesSearch */ | ||
8 | -/* @var $dataProvider yii\data\ActiveDataProvider */ | ||
9 | - | ||
10 | -$this->title = \Yii::t('app', 'Articles'); | ||
11 | -$this->params['breadcrumbs'][] = $this->title; | 2 | + |
3 | + use yii\helpers\Html; | ||
4 | + use yii\grid\GridView; | ||
5 | + | ||
6 | + /** | ||
7 | + * @var yii\web\View $this | ||
8 | + * @var common\models\ArticlesSearch $searchModel | ||
9 | + * @var yii\data\ActiveDataProvider $dataProvider | ||
10 | + */ | ||
11 | + | ||
12 | + $this->title = \Yii::t('app', 'Articles'); | ||
13 | + $this->params[ 'breadcrumbs' ][] = $this->title; | ||
12 | ?> | 14 | ?> |
13 | <div class="articles-index"> | 15 | <div class="articles-index"> |
14 | <h1><?= Html::encode($this->title) ?></h1> | 16 | <h1><?= Html::encode($this->title) ?></h1> |
15 | <p> | 17 | <p> |
16 | - <?= Html::a(\Yii::t('app', 'Create Articles'), ['create'], ['class' => 'btn btn-success']) ?> | 18 | + <?= Html::a(\Yii::t('app', 'Create Articles'), [ 'create' ], [ 'class' => 'btn btn-success' ]) ?> |
17 | </p> | 19 | </p> |
18 | <?= GridView::widget([ | 20 | <?= GridView::widget([ |
19 | 'dataProvider' => $dataProvider, | 21 | 'dataProvider' => $dataProvider, |
20 | - 'filterModel' => $searchModel, | ||
21 | - 'columns' => [ | ||
22 | - ['class' => 'yii\grid\SerialColumn'], | 22 | + 'filterModel' => $searchModel, |
23 | + 'columns' => [ | ||
23 | 'id', | 24 | 'id', |
24 | - 'date', | 25 | + [ |
26 | + 'attribute' => 'title', | ||
27 | + 'value' => 'lang.title', | ||
28 | + ], | ||
29 | + 'date:date', | ||
25 | 'imageUrl:image', | 30 | 'imageUrl:image', |
26 | - ['class' => 'yii\grid\ActionColumn'], | 31 | + [ 'class' => 'yii\grid\ActionColumn' ], |
27 | ], | 32 | ], |
28 | ]); ?> | 33 | ]); ?> |
29 | </div> | 34 | </div> |
backend/views/articles/view.php
1 | <?php | 1 | <?php |
2 | - | ||
3 | -use yii\helpers\Html; | ||
4 | -use yii\widgets\DetailView; | ||
5 | - | ||
6 | -/* @var $this yii\web\View */ | ||
7 | -/* @var $model common\models\Articles */ | ||
8 | - | ||
9 | -$this->title = $model->id; | ||
10 | -$this->params['breadcrumbs'][] = ['label' => \Yii::t('app', 'Articles'), 'url' => ['index']]; | ||
11 | -$this->params['breadcrumbs'][] = $this->title; | 2 | + |
3 | + use yii\helpers\Html; | ||
4 | + use yii\widgets\DetailView; | ||
5 | + | ||
6 | + /** | ||
7 | + * @var yii\web\View $this | ||
8 | + * @var common\models\Articles $model | ||
9 | + */ | ||
10 | + | ||
11 | + $this->title = $model->lang->title; | ||
12 | + $this->params[ 'breadcrumbs' ][] = [ | ||
13 | + 'label' => \Yii::t('app', 'Articles'), | ||
14 | + 'url' => [ 'index' ], | ||
15 | + ]; | ||
16 | + $this->params[ 'breadcrumbs' ][] = $this->title; | ||
12 | ?> | 17 | ?> |
13 | <div class="articles-view"> | 18 | <div class="articles-view"> |
14 | <h1><?= Html::encode($this->title) ?></h1> | 19 | <h1><?= Html::encode($this->title) ?></h1> |
15 | <p> | 20 | <p> |
16 | - <?= Html::a(\Yii::t('app', 'Update'), ['update', 'id' => $model->id], ['class' => 'btn btn-primary']) ?> | ||
17 | - <?= Html::a(\Yii::t('app', 'Delete'), ['delete', 'id' => $model->id], [ | 21 | + <?= Html::a(\Yii::t('app', 'Update'), [ |
22 | + 'update', | ||
23 | + 'id' => $model->id, | ||
24 | + ], [ 'class' => 'btn btn-primary' ]) ?> | ||
25 | + <?= Html::a(\Yii::t('app', 'Delete'), [ | ||
26 | + 'delete', | ||
27 | + 'id' => $model->id, | ||
28 | + ], [ | ||
18 | 'class' => 'btn btn-danger', | 29 | 'class' => 'btn btn-danger', |
19 | - 'data' => [ | 30 | + 'data' => [ |
20 | 'confirm' => \Yii::t('app', 'Are you sure you want to delete this item?'), | 31 | 'confirm' => \Yii::t('app', 'Are you sure you want to delete this item?'), |
21 | - 'method' => 'post', | 32 | + 'method' => 'post', |
22 | ], | 33 | ], |
23 | ]) ?> | 34 | ]) ?> |
24 | </p> | 35 | </p> |
25 | <?= DetailView::widget([ | 36 | <?= DetailView::widget([ |
26 | - 'model' => $model, | 37 | + 'model' => $model, |
27 | 'attributes' => [ | 38 | 'attributes' => [ |
28 | 'id', | 39 | 'id', |
29 | - 'date', | 40 | + 'date:date', |
41 | + 'lang.title', | ||
42 | + 'lang.body:html', | ||
43 | + 'imageUrl:image', | ||
30 | ], | 44 | ], |
31 | ]) ?> | 45 | ]) ?> |
32 | </div> | 46 | </div> |
backend/web/css/site.css
@@ -207,3 +207,9 @@ a.desc:after { | @@ -207,3 +207,9 @@ a.desc:after { | ||
207 | text-align: center; | 207 | text-align: center; |
208 | font-size: 13px !important; | 208 | font-size: 13px !important; |
209 | } | 209 | } |
210 | +.grid-view td img { | ||
211 | + max-width: 250px; | ||
212 | +} | ||
213 | +.detail-view td img { | ||
214 | + max-width: 100%; | ||
215 | +} | ||
210 | \ No newline at end of file | 216 | \ No newline at end of file |
common/models/Articles.php
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | namespace common\models; | 3 | namespace common\models; |
4 | - | 4 | + |
5 | + use common\modules\language\behaviors\TransactionBehavior; | ||
5 | use common\modules\language\behaviors\LanguageBehavior; | 6 | use common\modules\language\behaviors\LanguageBehavior; |
6 | use common\behaviors\SaveImgBehavior; | 7 | use common\behaviors\SaveImgBehavior; |
7 | use common\modules\comment\models\CommentModel; | 8 | use common\modules\comment\models\CommentModel; |
@@ -32,6 +33,11 @@ | @@ -32,6 +33,11 @@ | ||
32 | * @method bool linkLangs(ActiveRecord[] $model_langs) | 33 | * @method bool linkLangs(ActiveRecord[] $model_langs) |
33 | * @method bool saveLangs(ActiveRecord[] $model_langs) | 34 | * @method bool saveLangs(ActiveRecord[] $model_langs) |
34 | * * End language behavior * | 35 | * * End language behavior * |
36 | + * * From transaction behavior * | ||
37 | + * @property ArticlesLang[] $model_langs | ||
38 | + * @property bool $transactionStatus | ||
39 | + * @method bool getTransactionStatus() | ||
40 | + * * End transaction behavior * | ||
35 | */ | 41 | */ |
36 | class Articles extends \yii\db\ActiveRecord | 42 | class Articles extends \yii\db\ActiveRecord |
37 | { | 43 | { |
@@ -63,6 +69,9 @@ | @@ -63,6 +69,9 @@ | ||
63 | 'language' => [ | 69 | 'language' => [ |
64 | 'class' => LanguageBehavior::className(), | 70 | 'class' => LanguageBehavior::className(), |
65 | ], | 71 | ], |
72 | + 'transaction' => [ | ||
73 | + 'class' => TransactionBehavior::className(), | ||
74 | + ], | ||
66 | ]; | 75 | ]; |
67 | } | 76 | } |
68 | 77 |
common/models/ArticlesSearch.php
1 | <?php | 1 | <?php |
2 | - | ||
3 | -namespace common\models; | ||
4 | - | ||
5 | -use yii\base\Model; | ||
6 | -use yii\data\ActiveDataProvider; | ||
7 | - | ||
8 | -/** | ||
9 | - * ArticlesSearch represents the model behind the search form about `common\models\Articles`. | ||
10 | - */ | ||
11 | -class ArticlesSearch extends Articles | ||
12 | -{ | ||
13 | - /** | ||
14 | - * @inheritdoc | ||
15 | - */ | ||
16 | - public function rules() | ||
17 | - { | ||
18 | - return [ | ||
19 | - [['id'], 'integer'], | ||
20 | - ]; | ||
21 | - } | ||
22 | 2 | ||
23 | - public function behaviors() | ||
24 | - { | ||
25 | - return []; | ||
26 | - } | 3 | + namespace common\models; |
27 | 4 | ||
28 | - /** | ||
29 | - * @inheritdoc | ||
30 | - */ | ||
31 | - public function scenarios() | ||
32 | - { | ||
33 | - // bypass scenarios() implementation in the parent class | ||
34 | - return Model::scenarios(); | ||
35 | - } | 5 | + use yii\base\Model; |
6 | + use yii\data\ActiveDataProvider; | ||
7 | + use yii\data\Sort; | ||
36 | 8 | ||
37 | /** | 9 | /** |
38 | - * Creates data provider instance with search query applied | ||
39 | - * | ||
40 | - * @param array $params | ||
41 | - * | ||
42 | - * @return ActiveDataProvider | 10 | + * ArticlesSearch represents the model behind the search form about `common\models\Articles`. |
43 | */ | 11 | */ |
44 | - public function search($params) | 12 | + class ArticlesSearch extends Articles |
45 | { | 13 | { |
46 | - $query = Articles::find(); | ||
47 | - | ||
48 | - // add conditions that should always apply here | ||
49 | - | ||
50 | - $dataProvider = new ActiveDataProvider([ | ||
51 | - 'query' => $query, | ||
52 | - ]); | ||
53 | - | ||
54 | - $this->load($params); | ||
55 | - | ||
56 | - if (!$this->validate()) { | ||
57 | - // uncomment the following line if you do not want to return any records when validation fails | ||
58 | - // $query->where('0=1'); | 14 | + |
15 | + public $title; | ||
16 | + | ||
17 | + /** | ||
18 | + * @inheritdoc | ||
19 | + */ | ||
20 | + public function rules() | ||
21 | + { | ||
22 | + return [ | ||
23 | + [ | ||
24 | + [ 'id' ], | ||
25 | + 'integer', | ||
26 | + ], | ||
27 | + [ | ||
28 | + [ 'title' ], | ||
29 | + 'string', | ||
30 | + ], | ||
31 | + ]; | ||
32 | + } | ||
33 | + | ||
34 | + public function behaviors() | ||
35 | + { | ||
36 | + return []; | ||
37 | + } | ||
38 | + | ||
39 | + /** | ||
40 | + * @inheritdoc | ||
41 | + */ | ||
42 | + public function scenarios() | ||
43 | + { | ||
44 | + // bypass scenarios() implementation in the parent class | ||
45 | + return Model::scenarios(); | ||
46 | + } | ||
47 | + | ||
48 | + /** | ||
49 | + * Creates data provider instance with search query applied | ||
50 | + * | ||
51 | + * @param array $params | ||
52 | + * | ||
53 | + * @return ActiveDataProvider | ||
54 | + */ | ||
55 | + public function search($params) | ||
56 | + { | ||
57 | + $query = Articles::find() | ||
58 | + ->joinWith('lang'); | ||
59 | + | ||
60 | + // add conditions that should always apply here | ||
61 | + | ||
62 | + $dataProvider = new ActiveDataProvider([ | ||
63 | + 'query' => $query, | ||
64 | + 'sort' => [ | ||
65 | + 'attributes' => [ | ||
66 | + 'id', | ||
67 | + 'title' => [ | ||
68 | + 'asc' => [ 'articles_lang.title' => SORT_ASC ], | ||
69 | + 'desc' => [ 'articles_lang.title' => SORT_DESC ], | ||
70 | + ], | ||
71 | + ], | ||
72 | + ], | ||
73 | + ]); | ||
74 | + | ||
75 | + $this->load($params); | ||
76 | + | ||
77 | + if(!$this->validate()) { | ||
78 | + // uncomment the following line if you do not want to return any records when validation fails | ||
79 | + // $query->where('0=1'); | ||
80 | + return $dataProvider; | ||
81 | + } | ||
82 | + | ||
83 | + // grid filtering conditions | ||
84 | + $query->andFilterWhere([ | ||
85 | + 'id' => $this->id, | ||
86 | + ]); | ||
87 | + | ||
88 | + $query->andFilterWhere([ | ||
89 | + 'like', | ||
90 | + 'articles_lang.title', | ||
91 | + $this->title, | ||
92 | + ]); | ||
93 | + | ||
59 | return $dataProvider; | 94 | return $dataProvider; |
60 | } | 95 | } |
61 | - | ||
62 | - // grid filtering conditions | ||
63 | - $query->andFilterWhere([ | ||
64 | - 'id' => $this->id, | ||
65 | - ]); | ||
66 | - | ||
67 | - return $dataProvider; | ||
68 | } | 96 | } |
69 | -} |
common/modules/language/behaviors/TransactionBehavior.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | + namespace common\modules\language\behaviors; | ||
4 | + | ||
5 | + use yii\base\Behavior; | ||
6 | + use yii\db\ActiveRecord; | ||
7 | + use yii\db\Transaction; | ||
8 | + | ||
9 | + /** | ||
10 | + * Class Save Image Behavior | ||
11 | + * @property ActiveRecord $owner | ||
12 | + * @package common\behaviors | ||
13 | + */ | ||
14 | + class TransactionBehavior extends Behavior | ||
15 | + { | ||
16 | + | ||
17 | + /** | ||
18 | + * @var Transaction $_transaction | ||
19 | + */ | ||
20 | + private $_transaction; | ||
21 | + | ||
22 | + /** | ||
23 | + * @var bool $_transaction_status | ||
24 | + */ | ||
25 | + private $_transaction_status = false; | ||
26 | + | ||
27 | + /** | ||
28 | + * @var ActiveRecord[] $model_langs | ||
29 | + */ | ||
30 | + public $model_langs = []; | ||
31 | + | ||
32 | + public function events() | ||
33 | + { | ||
34 | + return [ | ||
35 | + ActiveRecord::EVENT_BEFORE_INSERT => 'beforeSave', | ||
36 | + ActiveRecord::EVENT_BEFORE_UPDATE => 'beforeSave', | ||
37 | + ActiveRecord::EVENT_AFTER_INSERT => 'afterSave', | ||
38 | + ActiveRecord::EVENT_AFTER_UPDATE => 'afterSave', | ||
39 | + ]; | ||
40 | + } | ||
41 | + | ||
42 | + public function beforeSave($event) { | ||
43 | + /** | ||
44 | + * @var ActiveRecord $owner | ||
45 | + */ | ||
46 | + $owner = $this->owner; | ||
47 | + $db = $owner::getDb(); | ||
48 | + $this->_transaction = $db->beginTransaction(); | ||
49 | + } | ||
50 | + | ||
51 | + public function afterSave($event) { | ||
52 | + /** | ||
53 | + * @var ActiveRecord $owner | ||
54 | + */ | ||
55 | + $owner = $this->owner; | ||
56 | + if(!empty($this->model_langs) && $owner->getBehavior('language')) { | ||
57 | + if($owner->linkLangs($this->model_langs) && $owner->saveLangs($this->model_langs)) { | ||
58 | + $this->_transaction->commit(); | ||
59 | + $this->_transaction_status = true; | ||
60 | + } else { | ||
61 | + $this->_transaction->rollBack(); | ||
62 | + $this->_transaction_status = false; | ||
63 | + } | ||
64 | + } else { | ||
65 | + $this->_transaction->commit(); | ||
66 | + $this->_transaction_status = true; | ||
67 | + } | ||
68 | + } | ||
69 | + | ||
70 | + /** | ||
71 | + * @return bool | ||
72 | + */ | ||
73 | + public function getTransactionStatus():bool { | ||
74 | + return $this->_transaction_status; | ||
75 | + } | ||
76 | + | ||
77 | + } | ||
0 | \ No newline at end of file | 78 | \ No newline at end of file |
common/modules/language/readme.txt
@@ -45,6 +45,9 @@ public function behaviors() { | @@ -45,6 +45,9 @@ public function behaviors() { | ||
45 | 'ownerKey' => {Table}->id //optional, default to {Table}->primaryKey()[0] | 45 | 'ownerKey' => {Table}->id //optional, default to {Table}->primaryKey()[0] |
46 | 'langKey' => {TableLang}->table_id //optional, default to {Table}->tableName().'_id' | 46 | 'langKey' => {TableLang}->table_id //optional, default to {Table}->tableName().'_id' |
47 | ], | 47 | ], |
48 | + 'transaction' => [ | ||
49 | + 'class' => TransactionBehavior::className(), | ||
50 | + ], | ||
48 | ]; | 51 | ]; |
49 | } | 52 | } |
50 | 3.1. PHPDoc для {Table}: | 53 | 3.1. PHPDoc для {Table}: |
@@ -65,6 +68,11 @@ public function behaviors() { | @@ -65,6 +68,11 @@ public function behaviors() { | ||
65 | * @method bool linkLangs(ActiveRecord[] $model_langs) | 68 | * @method bool linkLangs(ActiveRecord[] $model_langs) |
66 | * @method bool saveLangs(ActiveRecord[] $model_langs) | 69 | * @method bool saveLangs(ActiveRecord[] $model_langs) |
67 | * * End language behavior * | 70 | * * End language behavior * |
71 | + * * From transaction behavior * | ||
72 | + * @property {TableLang}[] $model_langs | ||
73 | + * @property bool $transactionStatus | ||
74 | + * @method bool getTransactionStatus() | ||
75 | + * * End transaction behavior * | ||
68 | 3.2. Убрать language behavior с наследуемых таблиц от {Table} ({TableSearch}...) | 76 | 3.2. Убрать language behavior с наследуемых таблиц от {Table} ({TableSearch}...) |
69 | 4. Доступные полезные методы: | 77 | 4. Доступные полезные методы: |
70 | {Table}->getLangs() - получить все текущие {TableLang} для {Table} проиндексированные по language_id | 78 | {Table}->getLangs() - получить все текущие {TableLang} для {Table} проиндексированные по language_id |
@@ -83,6 +91,6 @@ public function behaviors() { | @@ -83,6 +91,6 @@ public function behaviors() { | ||
83 | 6. Обрабатывать данные в контроллере. | 91 | 6. Обрабатывать данные в контроллере. |
84 | 1. После создания/поиска {Table} создаем/находим языковые модели {Table}->generateLangs() | 92 | 1. После создания/поиска {Table} создаем/находим языковые модели {Table}->generateLangs() |
85 | 2. При POST запросе загружаем данные в языковые модели {Table}->loadLangs(Request $request, {TableLangs[]} $model_langs) | 93 | 2. При POST запросе загружаем данные в языковые модели {Table}->loadLangs(Request $request, {TableLangs[]} $model_langs) |
86 | - 3. Связываем модель {Table} с языковыми моделями {Table}->linkLangs({TableLang[]} $model_langs). Возвращает true при успехе. | ||
87 | - 4. Сохраняе языковые модели в базу {Table}->saveLangs({TableLang[]} $model_langs). Возвращает true при успешной валидации каждого {TableLang}. | 94 | + 3. Передаем в свойство model_langs модели {Table} массив {TableLang[]}: $model->model_langs = $model_langs |
95 | + 4. После сохранения, если транзанкция успешна, то свойство {Table}->transactionStatus будет true, иначе возникла ошибка в какой то модели. | ||
88 | 7. Получать данные на публичной части сайта через {Table}->lang. | 96 | 7. Получать данные на публичной части сайта через {Table}->lang. |
89 | \ No newline at end of file | 97 | \ No newline at end of file |