Commit 97be095e30b29a6b7f1534d3b4653b6e54b16eb9
1 parent
9744f0d3
message
Showing
33 changed files
with
1321 additions
and
76 deletions
Show diff stats
backend/config/main.php
... | ... | @@ -23,6 +23,16 @@ return [ |
23 | 23 | ], |
24 | 24 | ], |
25 | 25 | 'components' => [ |
26 | + 'mailer' => [ | |
27 | + 'class' => 'yii\swiftmailer\Mailer', | |
28 | + 'transport' => [ | |
29 | + 'class' => 'Swift_SpoolTransport', | |
30 | + 'constructArgs' => [ | |
31 | + 'spool' => new common\components\DbSpool(), | |
32 | + ] | |
33 | + ], | |
34 | + 'useFileTransport' => false, | |
35 | + ], | |
26 | 36 | 'user' => [ |
27 | 37 | 'identityClass' => 'common\models\User', |
28 | 38 | 'enableAutoLogin' => true, | ... | ... |
backend/config/params.php
1 | +<?php | |
2 | +namespace backend\controllers; | |
3 | + | |
4 | +use backend\models\Language; | |
5 | +use backend\models\MessageLang; | |
6 | +use backend\models\Message; | |
7 | +use yii\web\Controller; | |
8 | +use yii\web\ForbiddenHttpException; | |
9 | +use yii\web\NotFoundHttpException; | |
10 | + | |
11 | +class AjaxController extends Controller | |
12 | +{ | |
13 | + public function beforeAction($action) | |
14 | + { | |
15 | + if(!\Yii::$app->request->getIsAjax()) { | |
16 | + //throw new ForbiddenHttpException('Permission denied'); | |
17 | + } | |
18 | + | |
19 | + if(!parent::beforeAction($action)) { | |
20 | + return false; | |
21 | + } | |
22 | + | |
23 | + return true; | |
24 | + } | |
25 | + public function actionMessageForm($lang_id, $widget_id) | |
26 | + { | |
27 | + $model = Language::find()->where(['>=', 'language_id', 1])->andWhere(['active' => 1, 'language_id' => $lang_id])->one(); | |
28 | + if(!$model) { | |
29 | + throw new NotFoundHttpException('Language not found'); | |
30 | + } | |
31 | + $message_lang = new MessageLang(); | |
32 | + return $this->renderAjax('message_form', ['model' => $model, 'message_lang' => $message_lang, 'widget_id' => $widget_id]); | |
33 | + } | |
34 | + | |
35 | + /* public function actionRemoveImage() | |
36 | + { | |
37 | + $post = \Yii::$app->request->post(); | |
38 | + if(!empty($post['article_media_id'])) { | |
39 | + $article_media = ArticleMedia::findOne($post['article_media_id']); | |
40 | + if($post['remove_media']) { | |
41 | + $media = $article_media->media->delete(); | |
42 | + } | |
43 | + if(!empty($article_media)) { | |
44 | + $article_media->delete(); | |
45 | + } | |
46 | + return true; | |
47 | + } else { | |
48 | + return false; | |
49 | + } | |
50 | + } | |
51 | + | |
52 | + public function actionRemoveImageCategory() | |
53 | + { | |
54 | + $post = \Yii::$app->request->post(); | |
55 | + if(!empty($post['category_media_id'])) { | |
56 | + $category_media = ArticleCategoryMedia::findOne($post['category_media_id']); | |
57 | + if($post['remove_media']) { | |
58 | + $media = $category_media->media->delete(); | |
59 | + } | |
60 | + if(!empty($category_media)) { | |
61 | + $category_media->delete(); | |
62 | + } | |
63 | + return true; | |
64 | + } else { | |
65 | + return false; | |
66 | + } | |
67 | + }*/ | |
68 | +} | ... | ... |
1 | +<?php | |
2 | + | |
3 | +namespace backend\controllers; | |
4 | + | |
5 | +use backend\models\Message; | |
6 | +use backend\models\MessageLang; | |
7 | +use Yii; | |
8 | +use common\models\MailerQueue; | |
9 | +use common\components\DbSpool; | |
10 | +use yii\data\ActiveDataProvider; | |
11 | +use yii\web\Controller; | |
12 | +use yii\web\NotFoundHttpException; | |
13 | +use yii\filters\VerbFilter; | |
14 | + | |
15 | +/** | |
16 | + * MailerQueueController implements the CRUD actions for MailerQueue model. | |
17 | + */ | |
18 | +class MailerQueueController extends Controller | |
19 | +{ | |
20 | + public function behaviors() | |
21 | + { | |
22 | + return [ | |
23 | + 'verbs' => [ | |
24 | + 'class' => VerbFilter::className(), | |
25 | + 'actions' => [ | |
26 | + 'delete' => ['post'], | |
27 | + ], | |
28 | + ], | |
29 | + ]; | |
30 | + } | |
31 | + | |
32 | + /** | |
33 | + * @param integer $id message id | |
34 | + * add message to queue | |
35 | + */ | |
36 | + public function actionSpooler($id) | |
37 | + { | |
38 | + $curr_lang=2; | |
39 | + $message_tempalete = Message::findOne(['id'=>$id]); | |
40 | + $message_template_langs = $message_tempalete->getMessageLangs()->where(['>=', 'lang_id', '1'])->indexBy('lang_id')->all(); | |
41 | + $message = \Swift_Message::newInstance(); | |
42 | + $spool = new DbSpool(); | |
43 | + $transport = \Swift_SpoolTransport::newInstance($spool); | |
44 | + $mailer = \Swift_Mailer::newInstance($transport); | |
45 | + foreach ($message_template_langs as $message_template_lang) | |
46 | + { | |
47 | + if($message_template_lang->lang_id == $curr_lang ) | |
48 | + { | |
49 | + $message ->setSubject($message_template_lang->title) | |
50 | + ->setFrom('info@example.com') | |
51 | + ->setTo('alexandr.khivrich@gmail.com') | |
52 | + ->setBody($message_template_lang->body); | |
53 | + if($message_template_lang->is_html) | |
54 | + { | |
55 | + $message ->setContentType('text\html'); | |
56 | + } | |
57 | + break; | |
58 | + } | |
59 | + } | |
60 | + $result = $mailer->send($message); | |
61 | + } | |
62 | + | |
63 | + /** | |
64 | + * Send Queue messages | |
65 | + */ | |
66 | + public function actionSend() | |
67 | + { | |
68 | + $messageLimit = 10; | |
69 | + $timeLimit = 0; | |
70 | + | |
71 | + $spool = new DbSpool(); | |
72 | + //$transportReal = \Swift_MailTransport::newInstance(); | |
73 | + $transportReal = \Swift_SmtpTransport::newInstance( | |
74 | + "smtp.gmail.com", | |
75 | + "465", | |
76 | + "ssl" | |
77 | + ) | |
78 | + ->setUsername("alexandr.khivrich@gmail.com") | |
79 | + ->setPassword("10181997Nadia"); | |
80 | + | |
81 | + $spool->setMessageLimit($messageLimit); | |
82 | + $spool->setTimeLimit($timeLimit); | |
83 | + $sent = $spool->flushQueue($transportReal); | |
84 | + | |
85 | + echo sprintf('sent %s emails', $sent); | |
86 | + } | |
87 | + /** | |
88 | + * Finds the MailerQueue model based on its primary key value. | |
89 | + * If the model is not found, a 404 HTTP exception will be thrown. | |
90 | + * @param integer $id | |
91 | + * @return MailerQueue the loaded model | |
92 | + * @throws NotFoundHttpException if the model cannot be found | |
93 | + */ | |
94 | + protected function findModel($id) | |
95 | + { | |
96 | + if (($model = MailerQueue::findOne($id)) !== null) { | |
97 | + return $model; | |
98 | + } else { | |
99 | + throw new NotFoundHttpException('The requested page does not exist.'); | |
100 | + } | |
101 | + } | |
102 | +} | ... | ... |
1 | +<?php | |
2 | + | |
3 | +namespace backend\controllers; | |
4 | +use common\models\Language; | |
5 | +use backend\models\MessageLang; | |
6 | +use Yii; | |
7 | +use backend\models\Message; | |
8 | +use app\models\MessageSearch; | |
9 | +use yii\web\Controller; | |
10 | +use yii\web\NotFoundHttpException; | |
11 | +use yii\filters\VerbFilter; | |
12 | +use yii\data\ActiveDataProvider; | |
13 | +/** | |
14 | + * MessageController implements the CRUD actions for Message model. | |
15 | + */ | |
16 | +class MessageController extends Controller | |
17 | +{ | |
18 | + public function behaviors() | |
19 | + { | |
20 | + return [ | |
21 | + 'verbs' => [ | |
22 | + 'class' => VerbFilter::className(), | |
23 | + 'actions' => [ | |
24 | + 'delete' => ['post'], | |
25 | + ], | |
26 | + ], | |
27 | + ]; | |
28 | + } | |
29 | + | |
30 | + /** | |
31 | + * Lists all Message models. | |
32 | + * @return mixed | |
33 | + */ | |
34 | + public function actionIndex() | |
35 | + { | |
36 | + $searchModel = new MessageSearch(); | |
37 | + $dataProvider = $searchModel->search(Yii::$app->request->queryParams); | |
38 | + | |
39 | + return $this->render('index', [ | |
40 | + 'searchModel' => $searchModel, | |
41 | + 'dataProvider' => $dataProvider, | |
42 | + ]); | |
43 | + } | |
44 | + | |
45 | + /** | |
46 | + * Displays a single Message model. | |
47 | + * @param integer $id | |
48 | + * @return mixed | |
49 | + */ | |
50 | + public function actionView($id) | |
51 | + { | |
52 | + return $this->render('view', [ | |
53 | + 'model' => $this->findModel($id), | |
54 | + 'model_lang'=>$model_lang = MessageLang::findOne(['message_id'=>$id]) | |
55 | + ]); | |
56 | + } | |
57 | + | |
58 | + /** | |
59 | + * Creates a new Message model. | |
60 | + * If creation is successful, the browser will be redirected to the 'view' page. | |
61 | + * @return mixed | |
62 | + */ | |
63 | + public function actionCreate() | |
64 | + { | |
65 | + $message_langs = array(); | |
66 | + $message = new Message(); | |
67 | + $images = array(); | |
68 | + $message->loadDefaultValues(); | |
69 | + $langs = Language::getActiveLanguages(); | |
70 | + $default_lang = Language::getDefaultLang(); | |
71 | + $isValid = false; | |
72 | + | |
73 | + if(!empty(\Yii::$app->request->post())) | |
74 | + { | |
75 | + | |
76 | + $isValid = true; | |
77 | + $message->load(\Yii::$app->request->post()); | |
78 | + $isValid = $message->validate(); | |
79 | + if(empty(\Yii::$app->request->post()['MessageLang'])) | |
80 | + { | |
81 | + | |
82 | + $message_langs[$default_lang->language_id] = new MessageLang(); | |
83 | + $isValid = MessageLang::validateMultiple($message_langs) && $isValid; | |
84 | + } | |
85 | + else | |
86 | + { | |
87 | + foreach(\Yii::$app->request->post()['MessageLang'] as $index => $message_lang) { | |
88 | + $message_langs[$index] = new MessageLang(); | |
89 | + } | |
90 | + MessageLang::loadMultiple($message_langs, \Yii::$app->request->post()); | |
91 | + // $isValid = MessageLang::validateMultiple($message_langs) && $isValid; | |
92 | + } | |
93 | + } | |
94 | + else | |
95 | + { | |
96 | + $message_langs[$default_lang->language_id] = new MessageLang(); | |
97 | + } | |
98 | + if($isValid) | |
99 | + { | |
100 | + $message->save(); | |
101 | + $first = 1; | |
102 | + foreach($message_langs as $message_lang) { | |
103 | + $message_lang->message_id=$message->id; | |
104 | + $message_lang->save(); | |
105 | + } | |
106 | + $this->redirect('index'); | |
107 | + } | |
108 | + else | |
109 | + { | |
110 | + return $this->render('create', [ | |
111 | + 'message_langs' => $message_langs, | |
112 | + 'message' => $message, | |
113 | + 'langs' => $langs, | |
114 | + ]); | |
115 | + } | |
116 | + } | |
117 | + | |
118 | + /** | |
119 | + * Updates an existing Message model. | |
120 | + * If update is successful, the browser will be redirected to the 'view' page. | |
121 | + * @param integer $id | |
122 | + * @return mixed | |
123 | + */ | |
124 | + public function actionUpdate($id) | |
125 | + { | |
126 | + $message = $this->findModel($id); | |
127 | + $message_langs=$message->getMessageLangs()->where(['>=', 'lang_id', '1'])->indexBy('lang_id')->all(); | |
128 | + $langs = Language::getActiveLanguages(); | |
129 | + $default_lang = Language::getDefaultLang(); | |
130 | + $isValid = false; | |
131 | + $post=\Yii::$app->request->post(); | |
132 | + if(!empty($post)) | |
133 | + { | |
134 | + $message->load($post); | |
135 | + $isValid = $message->validate(); | |
136 | + } | |
137 | + if(empty($post['MessageLang'])) | |
138 | + { | |
139 | + $isValid = MessageLang::validateMultiple($message_langs) && $isValid; | |
140 | + } | |
141 | + else | |
142 | + { | |
143 | + foreach($post['MessageLang'] as $index => $message_lang) | |
144 | + { | |
145 | + if (!array_key_exists($index, $message_langs)) | |
146 | + { | |
147 | + $message_langs[$index] = new MessageLang(); | |
148 | + $message_langs[$index]->message_id = $message->id; | |
149 | + } | |
150 | + } | |
151 | + MessageLang::loadMultiple($message_langs,$post); | |
152 | + } | |
153 | + if($isValid) | |
154 | + { | |
155 | + $message->save(); | |
156 | + $first = 1; | |
157 | + foreach($message_langs as $message_lang) { | |
158 | + $message_lang->message_id=$message->id; | |
159 | + $message_lang->save(); | |
160 | + } | |
161 | + $this->redirect('index'); | |
162 | + } | |
163 | + else | |
164 | + { | |
165 | + return $this->render('update', [ | |
166 | + 'message_langs' => $message_langs, | |
167 | + 'message' => $message, | |
168 | + 'langs' => $langs, | |
169 | + ]); | |
170 | + } | |
171 | + } | |
172 | + | |
173 | + /** | |
174 | + * Deletes an existing Message model. | |
175 | + * If deletion is successful, the browser will be redirected to the 'index' page. | |
176 | + * @param integer $id | |
177 | + * @return mixed | |
178 | + */ | |
179 | + public function actionDelete($id) | |
180 | + { | |
181 | + foreach(MessageLang::findAll(['message_id'=>$id])as $message_lang) | |
182 | + { | |
183 | + $message_lang->delete(); | |
184 | + } | |
185 | + | |
186 | + $this->findModel($id)->delete(); | |
187 | + return $this->redirect(['index']); | |
188 | + } | |
189 | + | |
190 | + /** | |
191 | + * Finds the Message model based on its primary key value. | |
192 | + * If the model is not found, a 404 HTTP exception will be thrown. | |
193 | + * @param integer $id | |
194 | + * @return Message the loaded model | |
195 | + * @throws NotFoundHttpException if the model cannot be found | |
196 | + */ | |
197 | + protected function findModel($id) | |
198 | + { | |
199 | + if (($model = Message::findOne($id)) !== null) { | |
200 | + return $model; | |
201 | + } else { | |
202 | + throw new NotFoundHttpException('The requested page does not exist.'); | |
203 | + } | |
204 | + } | |
205 | +} | ... | ... |
1 | +<?php | |
2 | + | |
3 | +namespace backend\models; | |
4 | + | |
5 | +use Yii; | |
6 | + | |
7 | +/** | |
8 | + * This is the model class for table "message". | |
9 | + * | |
10 | + * @property integer $id | |
11 | + * @property string $name | |
12 | + * @property boolean $is_sevice_sender | |
13 | + * @property boolean $is_server_sender | |
14 | + * @property boolean $is_sms | |
15 | + * | |
16 | + * @property MessageLang[] $messageLangs | |
17 | + */ | |
18 | +class Message extends \yii\db\ActiveRecord | |
19 | +{ | |
20 | + /** | |
21 | + * @inheritdoc | |
22 | + */ | |
23 | + public static function tableName() | |
24 | + { | |
25 | + return 'message'; | |
26 | + } | |
27 | + | |
28 | + /** | |
29 | + * @inheritdoc | |
30 | + */ | |
31 | + public function rules() | |
32 | + { | |
33 | + return [ | |
34 | + [['is_sevice_sender', 'is_sevice_sender', 'is_sms'], 'boolean'], | |
35 | + [['name'], 'string', 'max' => 255] | |
36 | + ]; | |
37 | + } | |
38 | + | |
39 | + /** | |
40 | + * @inheritdoc | |
41 | + */ | |
42 | + public function attributeLabels() | |
43 | + { | |
44 | + return [ | |
45 | + 'id' => 'ID', | |
46 | + 'name' => 'Name', | |
47 | + 'is_sevice_sender' => 'Sevice sender', | |
48 | + 'is_server_sender' => 'Server sender', | |
49 | + 'is_sms' => 'Is SMS', | |
50 | + ]; | |
51 | + } | |
52 | + | |
53 | + /** | |
54 | + * @return \yii\db\ActiveQuery | |
55 | + */ | |
56 | + public function getMessageLangs() | |
57 | + { | |
58 | + return $this->hasMany(MessageLang::className(), ['message_id' => 'id']); | |
59 | + } | |
60 | +} | ... | ... |
1 | +<?php | |
2 | + | |
3 | +namespace backend\models; | |
4 | + | |
5 | +use Yii; | |
6 | + | |
7 | +/** | |
8 | + * This is the model class for table "message_lang". | |
9 | + * | |
10 | + * @property string $body | |
11 | + * @property string $title | |
12 | + * @property integer $lang_id | |
13 | + * @property string $body_sms | |
14 | + * @property boolean $is_html | |
15 | + * @property integer $message_id | |
16 | + * @property integer $id | |
17 | + * | |
18 | + * @property Language $lang | |
19 | + * @property Message $message | |
20 | + */ | |
21 | +class MessageLang extends \yii\db\ActiveRecord | |
22 | +{ | |
23 | + /** | |
24 | + * @inheritdoc | |
25 | + */ | |
26 | + public static function tableName() | |
27 | + { | |
28 | + return 'message_lang'; | |
29 | + } | |
30 | + | |
31 | + /** | |
32 | + * @inheritdoc | |
33 | + */ | |
34 | + public function rules() | |
35 | + { | |
36 | + return [ | |
37 | + [['body', 'message_id'], 'required'], | |
38 | + [['body', 'body_sms'], 'string'], | |
39 | + [['lang_id', 'message_id'], 'integer'], | |
40 | + [['is_html'], 'boolean'], | |
41 | + [['title'], 'string', 'max' => 255] | |
42 | + ]; | |
43 | + } | |
44 | + | |
45 | + /** | |
46 | + * @inheritdoc | |
47 | + */ | |
48 | + public function attributeLabels() | |
49 | + { | |
50 | + return [ | |
51 | + 'body' => 'Body', | |
52 | + 'title' => 'Title', | |
53 | + 'lang_id' => 'Lang ID', | |
54 | + 'body_sms' => 'SMS', | |
55 | + 'is_html' => 'Is Html', | |
56 | + 'message_id' => 'Message ID', | |
57 | + 'id' => 'ID', | |
58 | + ]; | |
59 | + } | |
60 | + | |
61 | + /** | |
62 | + * @return \yii\db\ActiveQuery | |
63 | + */ | |
64 | + public function getLang() | |
65 | + { | |
66 | + return $this->hasOne(Language::className(), ['language_id' => 'lang_id']); | |
67 | + } | |
68 | + | |
69 | + /** | |
70 | + * @return \yii\db\ActiveQuery | |
71 | + */ | |
72 | + public function getMessage() | |
73 | + { | |
74 | + return $this->hasOne(Message::className(), ['id' => 'message_id']); | |
75 | + } | |
76 | +} | ... | ... |
1 | +<?php | |
2 | + | |
3 | +namespace app\models; | |
4 | + | |
5 | +use Yii; | |
6 | +use yii\base\Model; | |
7 | +use yii\data\ActiveDataProvider; | |
8 | +use backend\models\Message; | |
9 | + | |
10 | +/** | |
11 | + * MessageSearch represents the model behind the search form about `backend\models\Message`. | |
12 | + */ | |
13 | +class MessageSearch extends Message | |
14 | +{ | |
15 | + /** | |
16 | + * @inheritdoc | |
17 | + */ | |
18 | + public function rules() | |
19 | + { | |
20 | + return [ | |
21 | + [['id'], 'integer'], | |
22 | + [['name'], 'safe'], | |
23 | + ]; | |
24 | + } | |
25 | + | |
26 | + /** | |
27 | + * @inheritdoc | |
28 | + */ | |
29 | + public function scenarios() | |
30 | + { | |
31 | + // bypass scenarios() implementation in the parent class | |
32 | + return Model::scenarios(); | |
33 | + } | |
34 | + | |
35 | + /** | |
36 | + * Creates data provider instance with search query applied | |
37 | + * | |
38 | + * @param array $params | |
39 | + * | |
40 | + * @return ActiveDataProvider | |
41 | + */ | |
42 | + public function search($params) | |
43 | + { | |
44 | + $query = Message::find(); | |
45 | + | |
46 | + $dataProvider = new ActiveDataProvider([ | |
47 | + 'query' => $query, | |
48 | + ]); | |
49 | + | |
50 | + $this->load($params); | |
51 | + | |
52 | + if (!$this->validate()) { | |
53 | + // uncomment the following line if you do not want to return any records when validation fails | |
54 | + // $query->where('0=1'); | |
55 | + return $dataProvider; | |
56 | + } | |
57 | + | |
58 | + $query->andFilterWhere([ | |
59 | + 'id' => $this->id, | |
60 | + ]); | |
61 | + | |
62 | + $query->andFilterWhere(['like', 'name', $this->name]); | |
63 | + | |
64 | + return $dataProvider; | |
65 | + } | |
66 | +} | ... | ... |
1 | +<?php | |
2 | + | |
3 | +use yii\bootstrap\ActiveField; | |
4 | +use mihaildev\ckeditor\CKEditor; | |
5 | + | |
6 | +$form = \yii\bootstrap\ActiveForm::begin(); | |
7 | +?> | |
8 | +<div role="" class="tab-pane active ajax-loaded" id="<?=$widget_id?>-<?=$model->language_id?>"> | |
9 | + | |
10 | + <?= (new ActiveField(['model' => $message_lang, 'attribute' => "[$model->language_id]lang_id"]))->label(false)->hiddenInput(['value' => $model->language_id]) ?> | |
11 | + | |
12 | + <?= (new ActiveField(['model' => $message_lang, 'attribute' => "[$model->language_id]title", 'form' => $form]))->textInput() ?> | |
13 | + | |
14 | + <?= (new ActiveField(['model' => $message_lang, 'attribute' => "[$model->language_id]body", 'form' => $form]))->widget(CKEditor::className(),['editorOptions' => [ 'preset' => 'full', 'inline' => false, ], ]); ?> | |
15 | + | |
16 | + <?= (new ActiveField(['model' => $message_lang, 'attribute' => "[$model->language_id]body_sms"]))->textarea() ?> | |
17 | +</div> | |
18 | +<?php | |
19 | +$form->end(); | |
20 | +?> | ... | ... |
backend/views/language/index.php
... | ... | @@ -24,7 +24,7 @@ echo $this->render('layout'); |
24 | 24 | [ |
25 | 25 | 'class' => Column::className(), |
26 | 26 | 'content' => function($model, $key, $index, $column) { |
27 | - return '<span class="f32"><span class="flag '.$model->country_code.'"></span></span>'; | |
27 | + return '<span class="f32"><span class="flag '.$model->lang_code.'"></span></span>'; | |
28 | 28 | } |
29 | 29 | ], |
30 | 30 | 'language_name', | ... | ... |
backend/views/layouts/left.php
... | ... | @@ -38,6 +38,7 @@ |
38 | 38 | ['label' => 'Gii', 'icon' => 'fa fa-file-code-o', 'url' => ['/gii']], |
39 | 39 | ['label' => 'Debug', 'icon' => 'fa fa-dashboard', 'url' => ['/debug']], |
40 | 40 | ['label' => 'Login', 'url' => ['site/login'], 'visible' => Yii::$app->user->isGuest], |
41 | + ['label'=>'Messages','url'=>['/message']], | |
41 | 42 | ['label' => 'Пользователи', 'icon' => 'fa fa-file-code-o', 'url' => ['/user/']], |
42 | 43 | [ |
43 | 44 | 'label' => Yii::t('app', 'Blog'), | ... | ... |
1 | +<?php | |
2 | + | |
3 | +use yii\helpers\Html; | |
4 | +use common\widgets\Multilang; | |
5 | +use mihaildev\ckeditor\CKEditor; | |
6 | +use yii\bootstrap\ActiveForm; | |
7 | +use yii\helpers\Json; | |
8 | +use yii\helpers\Url; | |
9 | +use yii\widgets\Pjax; | |
10 | +use backend\models\Message; | |
11 | +use yii\helpers\ArrayHelper; | |
12 | +/* @var $this yii\web\View */ | |
13 | +/* @var $model backend\models\Message */ | |
14 | +/* @var $form yii\widgets\ActiveForm */ | |
15 | +$def_lang = array_keys($langs)[0]; | |
16 | +?> | |
17 | + | |
18 | +<div class="message-form"> | |
19 | + <?php $form = \yii\bootstrap\ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?> | |
20 | + <?= $form->field($message,'name')->textInput()?> | |
21 | + <?= $form->field($message,'is_sevice_sender')->checkbox()?> | |
22 | + <?= $form->field($message,'is_server_sender')->checkbox()?> | |
23 | + <?= $form->field($message,'is_sms')->checkbox()?> | |
24 | + <?php | |
25 | + $multilang = Multilang::begin(['ajaxpath' => Url::to(['/ajax/message-form']), 'form' => $form, 'data_langs' => $message_langs]); | |
26 | + ?> | |
27 | + <?php | |
28 | + $first = 1; | |
29 | + foreach($message_langs as $index => $message_lang) { | |
30 | + ?> | |
31 | + <div role="" class="tab-pane <?php if($first) { echo 'active main-tab'; } ?>" id="<?=$multilang->id?>-<?=$index?>"> | |
32 | + | |
33 | + <?= $form->field($message_langs[$index], "[$index]lang_id")->label(false)->hiddenInput(['value' =>$index]) ?> | |
34 | + | |
35 | + <?= $form->field($message_langs[$index], "[$index]title")->textInput() ?> | |
36 | + | |
37 | + <?= $form->field($message_langs[$index], "[$index]body")->widget(CKEditor::className(),['editorOptions' => [ 'preset' => 'full', 'inline' => false, ], ]); ?> | |
38 | + | |
39 | + <?= $form->field($message_langs[$index], "[$index]body_sms")->textarea()?> | |
40 | + </div> | |
41 | + <?php | |
42 | + $first = 0; | |
43 | + } | |
44 | + ?> | |
45 | + <?php | |
46 | + $multilang->end(); | |
47 | + ?> | |
48 | + <div class="form-group"> | |
49 | + <?= Html::submitButton($message->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> | |
50 | + </div> | |
51 | + <?php ActiveForm::end(); ?> | |
52 | + | |
53 | +</div> | ... | ... |
1 | +<?php | |
2 | + | |
3 | +use yii\helpers\Html; | |
4 | +use yii\widgets\ActiveForm; | |
5 | + | |
6 | +/* @var $this yii\web\View */ | |
7 | +/* @var $model app\models\MessageSearch */ | |
8 | +/* @var $form yii\widgets\ActiveForm */ | |
9 | +?> | |
10 | + | |
11 | +<div class="message-search"> | |
12 | + | |
13 | + <?php $form = ActiveForm::begin([ | |
14 | + 'action' => ['index'], | |
15 | + 'method' => 'get', | |
16 | + ]); ?> | |
17 | + | |
18 | + <?= $form->field($model, 'id') ?> | |
19 | + | |
20 | + <?= $form->field($model, 'name') ?> | |
21 | + | |
22 | + <div class="form-group"> | |
23 | + <?= Html::submitButton('Search', ['class' => 'btn btn-primary']) ?> | |
24 | + <?= Html::resetButton('Reset', ['class' => 'btn btn-default']) ?> | |
25 | + </div> | |
26 | + | |
27 | + <?php ActiveForm::end(); ?> | |
28 | + | |
29 | +</div> | ... | ... |
1 | +<?php | |
2 | + | |
3 | +use yii\helpers\Html; | |
4 | + | |
5 | + | |
6 | +/* @var $this yii\web\View */ | |
7 | +/* @var $model backend\models\Message */ | |
8 | + | |
9 | +$this->title = 'Create Message'; | |
10 | +$this->params['breadcrumbs'][] = ['label' => 'Messages', 'url' => ['index']]; | |
11 | +$this->params['breadcrumbs'][] = $this->title; | |
12 | +?> | |
13 | +<div class="message-create"> | |
14 | + | |
15 | + <h1><?= Html::encode($this->title) ?></h1> | |
16 | + | |
17 | + <?= $this->render('_form', [ | |
18 | + 'message_langs' => $message_langs, | |
19 | + 'message' => $message, | |
20 | + 'langs' => $langs, | |
21 | + ]) ?> | |
22 | + | |
23 | +</div> | ... | ... |
1 | +<?php | |
2 | + | |
3 | +use yii\helpers\Html; | |
4 | +use yii\grid\GridView; | |
5 | + | |
6 | +/* @var $this yii\web\View */ | |
7 | +/* @var $searchModel app\models\MessageSearch */ | |
8 | +/* @var $dataProvider yii\data\ActiveDataProvider */ | |
9 | + | |
10 | +$this->title = 'Messages'; | |
11 | +$this->params['breadcrumbs'][] = $this->title; | |
12 | +?> | |
13 | +<div class="message-index"> | |
14 | + | |
15 | + <h1><?= Html::encode($this->title) ?></h1> | |
16 | + <?php // echo $this->render('_search', ['model' => $searchModel]); ?> | |
17 | + | |
18 | + <p> | |
19 | + <?= Html::a('Create Message', ['create'], ['class' => 'btn btn-success']) ?> | |
20 | + </p> | |
21 | + | |
22 | + <?= GridView::widget([ | |
23 | + 'dataProvider' => $dataProvider, | |
24 | + 'filterModel' => $searchModel, | |
25 | + 'columns' => [ | |
26 | + ['class' => 'yii\grid\SerialColumn'], | |
27 | + | |
28 | + 'id', | |
29 | + 'name', | |
30 | + | |
31 | + ['class' => 'yii\grid\ActionColumn'], | |
32 | + ], | |
33 | + ]); ?> | |
34 | + | |
35 | +</div> | ... | ... |
1 | +<?php | |
2 | + | |
3 | +use yii\helpers\Html; | |
4 | + | |
5 | +/* @var $this yii\web\View */ | |
6 | +/* @var $model backend\models\Message */ | |
7 | + | |
8 | +$this->title = 'Update Message: ' . ' ' . $model->name; | |
9 | +$this->params['breadcrumbs'][] = ['label' => 'Messages', 'url' => ['index']]; | |
10 | +$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->id]]; | |
11 | +$this->params['breadcrumbs'][] = 'Update'; | |
12 | +?> | |
13 | +<div class="message-update"> | |
14 | + | |
15 | + <h1><?= Html::encode($this->title) ?></h1> | |
16 | + | |
17 | + <?= $this->render('_form', [ | |
18 | + 'message_langs' => $message_langs, | |
19 | + 'message' => $message, | |
20 | + 'langs' => $langs, | |
21 | + ]) ?> | |
22 | + | |
23 | +</div> | ... | ... |
1 | +<?php | |
2 | + | |
3 | +use yii\helpers\Html; | |
4 | +use yii\widgets\DetailView; | |
5 | + | |
6 | +/* @var $this yii\web\View */ | |
7 | +/* @var $model backend\models\Message */ | |
8 | + | |
9 | +$this->title = $model->name; | |
10 | +$this->params['breadcrumbs'][] = ['label' => 'Messages', 'url' => ['index']]; | |
11 | +$this->params['breadcrumbs'][] = $this->title; | |
12 | +?> | |
13 | +<div class="message-view"> | |
14 | + | |
15 | + <h1><?= Html::encode($this->title) ?></h1> | |
16 | + | |
17 | + <p> | |
18 | + <?= Html::a('Update', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']) ?> | |
19 | + <?= Html::a('Delete', ['delete', 'id' => $model->id], [ | |
20 | + 'class' => 'btn btn-danger', | |
21 | + 'data' => [ | |
22 | + 'confirm' => 'Are you sure you want to delete this item?', | |
23 | + 'method' => 'post', | |
24 | + ], | |
25 | + ]) ?> | |
26 | + </p> | |
27 | + | |
28 | + <?= DetailView::widget([ | |
29 | + 'model' => $model, | |
30 | + 'attributes' => [ | |
31 | + 'id', | |
32 | + 'name', | |
33 | + [ | |
34 | + 'label'=>'Lang', | |
35 | + 'value'=>$model_lang->lang->language_name | |
36 | + ] | |
37 | + ], | |
38 | + ]) ?> | |
39 | + | |
40 | +</div> | ... | ... |
backend/web/js/option.js
... | ... | @@ -36,42 +36,6 @@ $(function() { |
36 | 36 | $(document).on('click', '.remove_lang', function() { |
37 | 37 | $(this).parents('.form-wrapper').remove(); |
38 | 38 | }); |
39 | - if($('#lang-tabs li').length > 1) { | |
40 | - $('#lang-tabs li').append('<span class="glyphicon glyphicon-remove-circle remove-lang"></span>') | |
41 | - } | |
42 | - $(document).on('click', '#lang-dropdown li a[data-lang]', function() { | |
43 | - var lang = $(this).data('lang'); | |
44 | - var flag = $(this).find('span').first().clone(); | |
45 | - var el = $(this); | |
46 | - $.get('/blog/ajax/category-form', { lang_id: lang }, function(data) { | |
47 | - $('#lang-tabs li').removeClass('active'); | |
48 | - $('#lang-tabs').append('<li role="lang_inputs" class="active" data-lang="'+lang+'"><a href="#lang-'+lang+'" aria-controls="lang-'+lang+'" role="tab" data-toggle="tab">'+$('<p>').append($(flag)).html()+'</a></li>'); | |
49 | - $('.lang-tab-content .tab-pane.active').removeClass('active'); | |
50 | - $('.lang-tab-content').append($(data).find('.ajax-loaded').first()); | |
51 | - $('body').append($(data).filter('script')); | |
52 | - $(el).parent().remove(); | |
53 | - if(!$('#lang-dropdown li').length) { | |
54 | - $('#dropdownLang').addClass('disabled'); | |
55 | - } | |
56 | - if($('#lang-tabs li').length > 1) { | |
57 | - $('#lang-tabs li').append('<span class="glyphicon glyphicon-remove-circle remove-lang"></span>') | |
58 | - } | |
59 | - }); | |
60 | - }); | |
61 | - $(document).on('click', '.remove-lang', function() { | |
62 | - var lang = $(this).parent().data('lang'); | |
63 | - var flag = $(this).parent().find('span.flag').first().clone(); | |
64 | - $('#lang-'+lang).remove(); | |
65 | - $('#lang-dropdown').append('<li><a href="#lang-tabs" data-lang="'+lang+'">'+$('<p>').append($(flag)).html()+'</a></li>'); | |
66 | - $('#dropdownLang').removeClass('disabled'); | |
67 | - $(this).parent().remove(); | |
68 | - if($('#lang-tabs li').length <= 1) { | |
69 | - $('#lang-tabs li').find('.remove-lang').remove(); | |
70 | - } | |
71 | - if(!$('#lang-tabs>li.active').length) { | |
72 | - $('#lang-tabs>li').first().find('a').tab('show'); | |
73 | - } | |
74 | - }); | |
75 | 39 | $(document).on('change', '.image_inputs_field', function() { |
76 | 40 | readURL(this); |
77 | 41 | }); |
... | ... | @@ -89,4 +53,55 @@ $(function() { |
89 | 53 | } |
90 | 54 | return false; |
91 | 55 | }); |
56 | + $.each($('.nav-tabs.f32'), function(key, value) { | |
57 | + if($(value).find('li').length > 1) { | |
58 | + $(value).find('li').append('<span class="glyphicon glyphicon-remove-circle remove-lang"></span>'); | |
59 | + } | |
60 | + }); | |
61 | + $(document).on('click', '.dropdown-menu.f32 li a[data-lang]', function() { | |
62 | + var lang = $(this).data('lang'); | |
63 | + var flag = $(this).find('span').first().clone(); | |
64 | + var el = $(this); | |
65 | + var id = $(this).attr('href').substr(1); | |
66 | + $.get(form[id], { lang_id: lang, widget_id: id }, function(data) { | |
67 | + $('#'+id+'-tabs li').removeClass('active'); | |
68 | + $('#'+id+'-tabs').append('<li role="lang_inputs" class="active" data-lang="'+lang+'"><a href="#'+id+'-'+lang+'" aria-controls="'+id+'-'+lang+'" role="tab" data-toggle="tab">'+$('<p>').append($(flag)).html()+'</a></li>'); | |
69 | + $('#tab-content-'+id+' .tab-pane.active').removeClass('active'); | |
70 | + $('#tab-content-'+id).append($(data).find('.ajax-loaded').first()); | |
71 | + $('body').append($(data).filter('script')); | |
72 | + $(el).parent().remove(); | |
73 | + if(!$('#lang-'+id+' li').length) { | |
74 | + $('#'+id+'Lang').addClass('disabled'); | |
75 | + } | |
76 | + if($('#'+id+'-tabs li').length > 1) { | |
77 | + $('#'+id+'-tabs li').append('<span class="glyphicon glyphicon-remove-circle remove-lang"></span>') | |
78 | + } | |
79 | + }); | |
80 | + }); | |
81 | + $(document).on('click', '.remove-lang', function() { | |
82 | + var lang = $(this).parent().data('lang'); | |
83 | + var flag = $(this).parent().find('span.flag').first().clone(); | |
84 | + var id = $(this).parent().find('a[aria-controls]').first().attr('aria-controls').substr(0,8); | |
85 | + $('#'+id+'-'+lang).remove(); | |
86 | + $('#lang-'+id).append('<li><a href="#'+id+'" data-lang="'+lang+'">'+$('<p>').append($(flag)).html()+'</a></li>'); | |
87 | + $('#'+id+'Lang').removeClass('disabled'); | |
88 | + $(this).parent().remove(); | |
89 | + if($('#'+id+'-tabs li').length <= 1) { | |
90 | + $('#'+id+'-tabs li').find('.remove-lang').remove(); | |
91 | + } | |
92 | + if(!$('#'+id+'-tabs>li.active').length) { | |
93 | + $('#'+id+'-tabs>li').first().find('a').tab('show'); | |
94 | + } | |
95 | + }); | |
96 | + $('#message-is_sms').change() | |
97 | + { | |
98 | + if ($('#message-is_sms').is(":checked")) | |
99 | + { | |
100 | + | |
101 | + $(".field-message-cmctext").css({'display': 'block'}); | |
102 | + } | |
103 | + else { | |
104 | + $(".field-message-cmctext").css({'display': 'none'}); | |
105 | + } | |
106 | + } | |
92 | 107 | }); |
93 | 108 | \ No newline at end of file | ... | ... |
1 | +<?php | |
2 | +namespace common\components; | |
3 | +use common\models\MailerQueue; | |
4 | +use yii\swiftmailer\Message; | |
5 | +use yii\helpers\HtmlPurifier; | |
6 | +use yii\helpers\Json; | |
7 | + | |
8 | +class DbSpool extends \Swift_ConfigurableSpool | |
9 | +{ | |
10 | + | |
11 | + /** | |
12 | + * File WriteRetry Limit | |
13 | + * | |
14 | + * @var int | |
15 | + */ | |
16 | + private $_retryLimit = 10; | |
17 | + | |
18 | +// /** | |
19 | +// * Create a new DbSpool. | |
20 | +// * | |
21 | +// * @param string $path | |
22 | +// | |
23 | +// */ | |
24 | + public function __construct() | |
25 | + { | |
26 | + | |
27 | + } | |
28 | + public function __destruct() | |
29 | + { | |
30 | + /* if (method_exists($this->_cache, 'clearAll')) | |
31 | + { | |
32 | + $this->_cache->clearAll($this->_cacheKey); | |
33 | + }*/ | |
34 | + } | |
35 | + /** | |
36 | + * Tests if this Spool mechanism has started. | |
37 | + * | |
38 | + * @return bool | |
39 | + */ | |
40 | + public function isStarted() | |
41 | + { | |
42 | + return true; | |
43 | + } | |
44 | + | |
45 | + /** | |
46 | + * Starts this Spool mechanism. | |
47 | + */ | |
48 | + public function start() | |
49 | + { | |
50 | + | |
51 | + } | |
52 | + | |
53 | + /** | |
54 | + * Stops this Spool mechanism. | |
55 | + */ | |
56 | + public function stop() | |
57 | + { | |
58 | + | |
59 | + } | |
60 | + | |
61 | + /** | |
62 | + * Allow to manage the enqueuing retry limit. | |
63 | + * | |
64 | + * Default, is ten and allows over 64^20 different fileNames | |
65 | + * | |
66 | + * @param int $limit | |
67 | + */ | |
68 | + public function setRetryLimit($limit) | |
69 | + { | |
70 | + $this->_retryLimit = $limit; | |
71 | + } | |
72 | + | |
73 | + /** | |
74 | + * Queues a message. | |
75 | + * | |
76 | + * @param Swift_Mime_Message $message The message to store | |
77 | + * | |
78 | + * @return bool | |
79 | + * | |
80 | + * @throws Swift_IoException | |
81 | + */ | |
82 | + public function queueMessage(\Swift_Mime_Message $message) | |
83 | + { | |
84 | + | |
85 | + $message->getBody(); | |
86 | + $queueObject = new MailerQueue(); | |
87 | + | |
88 | + $queueObject->text_body = $message->getBody(); | |
89 | + $queueObject->subject = $message->getSubject(); | |
90 | + $queueObject->to = Json::encode($message->getTo()); | |
91 | + $queueObject->save(); | |
92 | + } | |
93 | + | |
94 | + /** | |
95 | + * Sends messages using the given transport instance. | |
96 | + * | |
97 | + * @param Swift_Transport $transport A transport instance | |
98 | + * @param string[] $failedRecipients An array of failures by-reference | |
99 | + * | |
100 | + * @return int The number of sent e-mail's | |
101 | + */ | |
102 | + public function flushQueue(\Swift_Transport $transport, &$failedRecipients = null) | |
103 | + { | |
104 | + if (!$transport->isStarted()) | |
105 | + { | |
106 | + $transport->start(); | |
107 | + } | |
108 | + | |
109 | + $failedRecipients = (array) $failedRecipients; | |
110 | + | |
111 | + $count = 0; | |
112 | + $emails = MailerQueue::find() | |
113 | + ->where('sent_time IS NULL') | |
114 | + ->orderBy('id') | |
115 | + ->all(); | |
116 | + | |
117 | + if (!count($emails)) | |
118 | + { | |
119 | + return 0; | |
120 | + } | |
121 | + // print_r($emails); | |
122 | + foreach($emails as $email) | |
123 | + { | |
124 | + //$message = unserialize($email->message_object); | |
125 | + | |
126 | + $message = \Swift_Message::newInstance($email->subject) | |
127 | + ->setFrom(array('info@example.com' => 'ArtWeb')) | |
128 | + ->setTo(Json::decode($email->to)) | |
129 | + ->setBody($email->text_body); | |
130 | + try | |
131 | + { | |
132 | + $count+= $transport->send($message, $failedRecipients); | |
133 | + if($count > 0) | |
134 | + { | |
135 | + | |
136 | + $time = new \DateTime(); | |
137 | + $email->setAttribute('sent_time', $time->format('Y-m-d H:i:s')); | |
138 | + $email->save(); | |
139 | + } | |
140 | + else | |
141 | + { | |
142 | + throw new \Swift_SwiftException('The email was not sent.'); | |
143 | + } | |
144 | + } | |
145 | + catch(\Swift_SwiftException $ex) | |
146 | + { | |
147 | + | |
148 | + } | |
149 | + } | |
150 | + return $count; | |
151 | + } | |
152 | +} | |
153 | + | ... | ... |
common/config/main.php
... | ... | @@ -166,7 +166,17 @@ return [ |
166 | 166 | /*========End======= |
167 | 167 | *end api sicial |
168 | 168 | * */ |
169 | - | |
169 | + 'mailer' => [ | |
170 | + 'class' => 'yii\swiftmailer\Mailer', | |
171 | + 'transport' => [ | |
172 | + 'class' => 'Swift_SmtpTransport', | |
173 | + 'host' => 'smtp.gmail.com', // e.g. smtp.mandrillapp.com or smtp.gmail.com | |
174 | + 'username' => 'alexandr.khivrich@gmail.com', | |
175 | + 'password' => '10181997Nadia', | |
176 | + 'port' => '587', // Port 25 is a very common port too | |
177 | + 'encryption' => 'tls', // It is often used, check your provider or mail servers | |
178 | + ] | |
179 | + ], | |
170 | 180 | ], |
171 | 181 | 'language' => 'ru-RU' |
172 | 182 | ]; | ... | ... |
1 | +<?php | |
2 | + | |
3 | +namespace common\models; | |
4 | + | |
5 | +use Yii; | |
6 | + | |
7 | +/** | |
8 | + * This is the model class for table "mailer_queue". | |
9 | + * | |
10 | + * @property integer $id | |
11 | + * @property string $sent_time | |
12 | + * @property string $to | |
13 | + * @property string $text_body | |
14 | + * @property string $charset | |
15 | + * @property string $subject | |
16 | + */ | |
17 | +class MailerQueue extends \yii\db\ActiveRecord | |
18 | +{ | |
19 | + /** | |
20 | + * @inheritdoc | |
21 | + */ | |
22 | + public static function tableName() | |
23 | + { | |
24 | + return 'mailer_queue'; | |
25 | + } | |
26 | + | |
27 | + /** | |
28 | + * @inheritdoc | |
29 | + */ | |
30 | + public function rules() | |
31 | + { | |
32 | + return [ | |
33 | + [['sent_time'], 'safe'], | |
34 | + [['text_body'], 'string'], | |
35 | + [['to', 'subject'], 'string', 'max' => 255] | |
36 | + ]; | |
37 | + } | |
38 | + | |
39 | + /** | |
40 | + * @inheritdoc | |
41 | + */ | |
42 | + public function attributeLabels() | |
43 | + { | |
44 | + return [ | |
45 | + 'id' => 'ID', | |
46 | + 'sent_time' => 'Sent Time', | |
47 | + 'to' => 'To', | |
48 | + 'text_body' => 'Text Body', | |
49 | + 'subject' => 'Subject', | |
50 | + ]; | |
51 | + } | |
52 | +} | ... | ... |
1 | +<?php | |
2 | +namespace common\widgets; | |
3 | +use common\models\Language; | |
4 | +use yii\base\InvalidParamException; | |
5 | +use yii\base\Widget; | |
6 | +use yii\bootstrap\ActiveForm; | |
7 | + | |
8 | +class Multilang extends Widget | |
9 | +{ | |
10 | + public $id; | |
11 | + | |
12 | + public $langs; | |
13 | + | |
14 | + public $data_langs = []; | |
15 | + | |
16 | + public $ajaxpath; | |
17 | + | |
18 | + public $form; | |
19 | + | |
20 | + public function init() | |
21 | + { | |
22 | + parent::init(); | |
23 | + if(empty($this->id)) | |
24 | + { | |
25 | + $this->id = \Yii::$app->security->generateRandomString(8); | |
26 | + } | |
27 | + if(empty($this->langs)) | |
28 | + { | |
29 | + $this->langs = Language::getActiveLanguages(); | |
30 | + } | |
31 | + if(empty($this->ajaxpath)) | |
32 | + { | |
33 | + throw new InvalidParamException('ajaxpath must be set'); | |
34 | + } | |
35 | + if(empty($this->form)) | |
36 | + { | |
37 | + throw new InvalidParamException('form must be set'); | |
38 | + } | |
39 | + ob_start(); | |
40 | + echo $this->render('multilang-begin', ['id' => $this->id, 'langs' => $this->langs, 'data_langs' => $this->data_langs, 'ajaxpath' => $this->ajaxpath, 'form' => $this->form]); | |
41 | + } | |
42 | + | |
43 | + public function run() | |
44 | + { | |
45 | + echo $this->render('multilang-end', ['id' => $this->id, 'langs' => $this->langs, 'data_langs' => $this->data_langs, 'ajaxpath' => $this->ajaxpath, 'form' => $this->form]); | |
46 | + $content = ob_get_clean(); | |
47 | + return $content; | |
48 | + } | |
49 | +} | |
0 | 50 | \ No newline at end of file | ... | ... |
1 | +<?php | |
2 | +use yii\helpers\Url; | |
3 | +?> | |
4 | +<div class="dropdown pull-right"> | |
5 | + <button class="btn btn-default dropdown-toggle" type="button" id="<?=$id?>Lang" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true"> | |
6 | + <?= Yii::t('app', 'Add language') ?> | |
7 | + <span class="caret"></span> | |
8 | + </button> | |
9 | + <ul class="dropdown-menu f32" id="lang-<?=$id?>" aria-labelledby="<?=$id?>Menu"> | |
10 | + <?php foreach($langs as $index => $lang) { | |
11 | + if(in_array($index, array_keys($data_langs))) continue; | |
12 | + ?> | |
13 | + <li><a href="#<?=$id?>" data-lang="<?=$lang->language_id?>"><span class="flag <?=$lang->lang_code?>"></span></a></li> | |
14 | + <?php } ?> | |
15 | + </ul> | |
16 | +</div> | |
17 | +<ul class="nav nav-tabs f32" id="<?=$id?>-tabs" role="tablist"> | |
18 | + <?php | |
19 | + $first = 1; | |
20 | + foreach($data_langs as $index => $data_lang) { | |
21 | + ?> | |
22 | + <li role="lang_inputs" class="<?php if($first) { echo 'active'; }?>" data-lang="<?=$index?>"><a href="#<?=$id?>-<?=$index?>" aria-controls="<?=$id?>-<?=$index?>" role="tab" data-toggle="tab"><span class="flag <?=$langs[$index]->lang_code?>"></span></a></li> | |
23 | + <?php | |
24 | + $first = 0; | |
25 | + } | |
26 | + ?> | |
27 | +</ul> | |
28 | +<div class="tab-content lang-tab-content" id="tab-content-<?=$id?>"> | |
29 | + | ... | ... |
composer.json
... | ... | @@ -23,7 +23,8 @@ |
23 | 23 | "kartik-v/yii2-widget-select2": "@dev", |
24 | 24 | "mihaildev/yii2-ckeditor": "*", |
25 | 25 | "developeruz/yii2-db-rbac": "*", |
26 | - "nodge/yii2-eauth": "*" | |
26 | + "nodge/yii2-eauth": "*", | |
27 | + "iutbay/yii2-kcfinder": "*" | |
27 | 28 | }, |
28 | 29 | "require-dev": { |
29 | 30 | "yiisoft/yii2-codeception": "*", | ... | ... |
1 | +<?php | |
2 | + | |
3 | +namespace backend\controllers; | |
4 | + | |
5 | +use Yii; | |
6 | +use common\components\DbSpool; | |
7 | +use yii\data\ActiveDataProvider; | |
8 | +use yii\web\Controller; | |
9 | +use yii\web\NotFoundHttpException; | |
10 | +use yii\filters\VerbFilter; | |
11 | + | |
12 | +/** | |
13 | + * MailerQueueController implements the CRUD actions for MailerQueue model. | |
14 | + */ | |
15 | +class MailerQueueController extends Controller | |
16 | +{ | |
17 | + public function behaviors() | |
18 | + { | |
19 | + return [ | |
20 | + 'verbs' => [ | |
21 | + 'class' => VerbFilter::className(), | |
22 | + 'actions' => [ | |
23 | + 'delete' => ['post'], | |
24 | + ], | |
25 | + ], | |
26 | + ]; | |
27 | + } | |
28 | + /** | |
29 | + * Send Queue messages | |
30 | + */ | |
31 | + public function actionSend() | |
32 | + { | |
33 | + $messageLimit = 10; | |
34 | + $timeLimit = 0; | |
35 | + | |
36 | + $spool = new DbSpool(); | |
37 | + $transportReal = \Swift_SmtpTransport::newInstance( | |
38 | + "smtp.gmail.com", | |
39 | + "465", | |
40 | + "ssl" | |
41 | + ) | |
42 | + ->setUsername("alexandr.khivrich@gmail.com") | |
43 | + ->setPassword("10181997Nadia"); | |
44 | + | |
45 | + $spool->setMessageLimit($messageLimit); | |
46 | + $spool->setTimeLimit($timeLimit); | |
47 | + $sent = $spool->flushQueue($transportReal); | |
48 | + | |
49 | + echo sprintf('sent %s emails', $sent); | |
50 | + } | |
51 | +} | ... | ... |
frontend/models/OptionValues.php
... | ... | @@ -73,7 +73,7 @@ class OptionValues extends \yii\db\ActiveRecord |
73 | 73 | } |
74 | 74 | return $langs; |
75 | 75 | } |
76 | - public function beforeSave($insert) { | |
76 | + public function beforeSave($insert){ | |
77 | 77 | if (parent::beforeSave($insert)) { |
78 | 78 | $this->option_user = \Yii::$app->user->getId(); |
79 | 79 | if($this->option_value_parent == 0) { | ... | ... |
frontend/web/js/option.js
... | ... | @@ -36,42 +36,6 @@ $(function() { |
36 | 36 | $(document).on('click', '.remove_lang', function() { |
37 | 37 | $(this).parents('.form-wrapper').remove(); |
38 | 38 | }); |
39 | - if($('#lang-tabs li').length > 1) { | |
40 | - $('#lang-tabs li').append('<span class="glyphicon glyphicon-remove-circle remove-lang"></span>') | |
41 | - } | |
42 | - $(document).on('click', '#lang-dropdown li a[data-lang]', function() { | |
43 | - var lang = $(this).data('lang'); | |
44 | - var flag = $(this).find('span').first().clone(); | |
45 | - var el = $(this); | |
46 | - $.get('/blog/ajax/category-form', { lang_id: lang }, function(data) { | |
47 | - $('#lang-tabs li').removeClass('active'); | |
48 | - $('#lang-tabs').append('<li role="lang_inputs" class="active" data-lang="'+lang+'"><a href="#lang-'+lang+'" aria-controls="lang-'+lang+'" role="tab" data-toggle="tab">'+$('<p>').append($(flag)).html()+'</a></li>'); | |
49 | - $('.lang-tab-content .tab-pane.active').removeClass('active'); | |
50 | - $('.lang-tab-content').append($(data).find('.ajax-loaded').first()); | |
51 | - $('body').append($(data).filter('script')); | |
52 | - $(el).parent().remove(); | |
53 | - if(!$('#lang-dropdown li').length) { | |
54 | - $('#dropdownLang').addClass('disabled'); | |
55 | - } | |
56 | - if($('#lang-tabs li').length > 1) { | |
57 | - $('#lang-tabs li').append('<span class="glyphicon glyphicon-remove-circle remove-lang"></span>') | |
58 | - } | |
59 | - }); | |
60 | - }); | |
61 | - $(document).on('click', '.remove-lang', function() { | |
62 | - var lang = $(this).parent().data('lang'); | |
63 | - var flag = $(this).parent().find('span.flag').first().clone(); | |
64 | - $('#lang-'+lang).remove(); | |
65 | - $('#lang-dropdown').append('<li><a href="#lang-tabs" data-lang="'+lang+'">'+$('<p>').append($(flag)).html()+'</a></li>'); | |
66 | - $('#dropdownLang').removeClass('disabled'); | |
67 | - $(this).parent().remove(); | |
68 | - if($('#lang-tabs li').length <= 1) { | |
69 | - $('#lang-tabs li').find('.remove-lang').remove(); | |
70 | - } | |
71 | - if(!$('#lang-tabs>li.active').length) { | |
72 | - $('#lang-tabs>li').first().find('a').tab('show'); | |
73 | - } | |
74 | - }); | |
75 | 39 | $(document).on('change', '.image_inputs_field', function() { |
76 | 40 | readURL(this); |
77 | 41 | }); |
... | ... | @@ -89,4 +53,44 @@ $(function() { |
89 | 53 | } |
90 | 54 | return false; |
91 | 55 | }); |
56 | + $.each($('.nav-tabs.f32'), function(key, value) { | |
57 | + if($(value).find('li').length > 1) { | |
58 | + $(value).find('li').append('<span class="glyphicon glyphicon-remove-circle remove-lang"></span>'); | |
59 | + } | |
60 | + }); | |
61 | + $(document).on('click', '.dropdown-menu.f32 li a[data-lang]', function() { | |
62 | + var lang = $(this).data('lang'); | |
63 | + var flag = $(this).find('span').first().clone(); | |
64 | + var el = $(this); | |
65 | + var id = $(this).attr('href').substr(1); | |
66 | + $.get(form[id], { lang_id: lang, widget_id: id }, function(data) { | |
67 | + $('#'+id+'-tabs li').removeClass('active'); | |
68 | + $('#'+id+'-tabs').append('<li role="lang_inputs" class="active" data-lang="'+lang+'"><a href="#'+id+'-'+lang+'" aria-controls="'+id+'-'+lang+'" role="tab" data-toggle="tab">'+$('<p>').append($(flag)).html()+'</a></li>'); | |
69 | + $('#tab-content-'+id+' .tab-pane.active').removeClass('active'); | |
70 | + $('#tab-content-'+id).append($(data).find('.ajax-loaded').first()); | |
71 | + $('body').append($(data).filter('script')); | |
72 | + $(el).parent().remove(); | |
73 | + if(!$('#lang-'+id+' li').length) { | |
74 | + $('#'+id+'Lang').addClass('disabled'); | |
75 | + } | |
76 | + if($('#'+id+'-tabs li').length > 1) { | |
77 | + $('#'+id+'-tabs li').append('<span class="glyphicon glyphicon-remove-circle remove-lang"></span>') | |
78 | + } | |
79 | + }); | |
80 | + }); | |
81 | + $(document).on('click', '.remove-lang', function() { | |
82 | + var lang = $(this).parent().data('lang'); | |
83 | + var flag = $(this).parent().find('span.flag').first().clone(); | |
84 | + var id = $(this).parent().find('a[aria-controls]').first().attr('aria-controls').substr(0,8); | |
85 | + $('#'+id+'-'+lang).remove(); | |
86 | + $('#lang-'+id).append('<li><a href="#'+id+'" data-lang="'+lang+'">'+$('<p>').append($(flag)).html()+'</a></li>'); | |
87 | + $('#'+id+'Lang').removeClass('disabled'); | |
88 | + $(this).parent().remove(); | |
89 | + if($('#'+id+'-tabs li').length <= 1) { | |
90 | + $('#'+id+'-tabs li').find('.remove-lang').remove(); | |
91 | + } | |
92 | + if(!$('#'+id+'-tabs>li.active').length) { | |
93 | + $('#'+id+'-tabs>li').first().find('a').tab('show'); | |
94 | + } | |
95 | + }); | |
92 | 96 | }); |
93 | 97 | \ No newline at end of file | ... | ... |
1 | +-----BEGIN RSA PRIVATE KEY----- | |
2 | +MIIEpQIBAAKCAQEAq1wH6wvvKupU9Qb/OzNlQgNEQucwLrSm56lTGX0Tme56zSs5 | |
3 | +k+44WdPQuF4xIHdzftGzna9OEat18fbdGXXrg8r2h2N7nmNkJz08DCrKQxVuyeVW | |
4 | +y1ktKu7qzy/5rQcSKbHARB0c/L8Iv9j63ZWu2EbBoz9rAxbUxImIwuXcLELlxHL1 | |
5 | +aD33VYB7ODqI0b/FBN2Su+4QlzaOW8Nhu2ctUDM3R0j2cpGa0rqAGjIUtCZiUeUa | |
6 | ++TsYbJwoQg+kVN9gb06I6uDsijxVexYNeuFj+JGjQm80pXqcJn92e8G3FQISan6g | |
7 | +BkVClr9VBlc14HV3DLFy36RuLDzkA1vmUMNd6wIDAQABAoIBACaZzaLSBmdJcCfe | |
8 | +EqKYWkf7imXzxDPROAPZbcHBHig/w2PyR78eG42InGzbsv9YSSkZPffYZKKwWBpQ | |
9 | +fM/ec1Y140DuVQuB4i7AqYUoInXoHxPV2K5oATe5qCVR7lFe1WWVB/WQBVaeBe+J | |
10 | +hkFiFYfcsIQApi+E9hrrzGXy95z0enNpv8cJ1z9xVNts8oxXiFwzaY8Kcz56W5mS | |
11 | +/XDboVI2Od+NHY3rJnWj63OLyRIBnyjYfNFMXysRZs64lRUxKvt74RB2hx+q6wlF | |
12 | +djTEqTdMzm9tCCbGI5InXovCkXZToQ8ed+8071eohMxpFBqP6TSFEQf1Og+T8TzK | |
13 | +JndHcMkCgYEA2gxBgGJmHVDaK7eiI7Fqg+ehI0GamTT/ZBHW6xvKHgMI54CUQ4c+ | |
14 | +acLBctailDP2VNd0gKe1RRE10dz5Akzw+MydUASQONqoO8LU5eLuyNlI7QT259Xd | |
15 | +Yfvw+BXUEN+WDtJNESbXhTYaO/3B7l2EzsWc6ToJRSoafiem4aEhsVUCgYEAyS9w | |
16 | +/W2U4IiIVzke2tjRm/vb+T3OmOv1i/y2f79PnQMPJ5oNyxdtZ3axOapMv0KZXApo | |
17 | +dWL205eYu0fYZpdVhtHuPAhK6tNi4CDPW2dGWB5dVaGfFMCF1CVoUJlpJT+DOfqp | |
18 | +d774ID5dZ1PpvJoODcPXa3Bmh+83NbmpIrH90j8CgYEAoYD+azd25zPhxQvI/qME | |
19 | +gBrq0ZBgECafG+HSzGXS+RPKXp5wMuxToEZuvr6XwSoTxJepZTnTHAs5T+5aSgfv | |
20 | +XHlB8+jNYi8i+NDAnF3P+9hlGZnZv7I6vb68pyST5MOXA/dkudWJQNPn7pNwNzvx | |
21 | +iK36IQ2pnB8pbFO2WdzdddkCgYEAoXvO+dyHb2Kn7TsQJSF7vfR/MKQHvH9JbL+/ | |
22 | +zPJGeQUHmQXypF19l1qSDnM/fxV5+4LvLant7RD1qv2UGWTHZZwD2XPejnZ2Gui7 | |
23 | +B+bxc7GLwTwlcIbH5OzRukApQZilQFiOxmsmxtrIJjQYnSYaubnEo5xo8Bt2+Uy5 | |
24 | +EfxEfAkCgYEAvwGvYDdCcjozwnAdMSSHLa0rVoChet/cZTsqpagIF7zjMq9ljG2J | |
25 | +7pK+esJeAwpGTwXSpIPWHDIOhScsL6iiKu2BRPa6NostlpUjDzciPZzrizz+okuP | |
26 | +palma9L1DuQqUSC+Vqe25Qmnk7F+Hiw+Fu3L4pMcxw8/ZgUagMpkOHM= | |
27 | +-----END RSA PRIVATE KEY----- | ... | ... |
1 | +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrXAfrC+8q6lT1Bv87M2VCA0RC5zAutKbnqVMZfROZ7nrNKzmT7jhZ09C4XjEgd3N+0bOdr04Rq3Xx9t0ZdeuDyvaHY3ueY2QnPTwMKspDFW7J5VbLWS0q7urPL/mtBxIpscBEHRz8vwi/2Prdla7YRsGjP2sDFtTEiYjC5dwsQuXEcvVoPfdVgHs4OojRv8UE3ZK77hCXNo5bw2G7Zy1QMzdHSPZykZrSuoAaMhS0JmJR5Rr5OxhsnChCD6RU32BvTojq4OyKPFV7Fg164WP4kaNCbzSlepwmf3Z7wbcVAhJqfqAGRUKWv1UGVzXgdXcMsXLfpG4sPOQDW+ZQw13r alexandr.khivrich@gmail.com | ... | ... |
1 | +-----BEGIN RSA PRIVATE KEY----- | |
2 | +MIIEpAIBAAKCAQEAmHwDO+WhonC49gHe2DNx7OD16hfMU2JS3Y26AsE+dSlWiYlZ | |
3 | +U0NWkmDgM88e3EpzxXECInn42OjjHxaAPcPsAnICmLjMHjAvUzQQXoPMbbbuPJxD | |
4 | +aanh/NZnyeHy9xj6lrUgNvsrljRjdQ20SSAcdkcsOj4+HBBxnaFIzh+GW8Ha3b26 | |
5 | +dBUYjOL/oxrUW0AKehpDJWlf6mzHBDa+DWCOSXK4zNI9K+y3lqeoWVIzKdrxHRfs | |
6 | +tnhBs7/La+pU+kxGY6B1PouB+McdG3CBZ/yMUX/o4dDamTCU85VbyoLo5R2d7Pv2 | |
7 | +P2y2i4/tS3E9mCAbmrYIUwShYVgYlWyYJnWCgQIDAQABAoIBAHZECQYVzk18/Bfh | |
8 | +z4MEM6IzwMe1eYZaxkaMO+8TDmw0iafW3W8U1Tpm5L2KMTdOj4hdY/h1fapOxolA | |
9 | +HGrLYGttHdJx0e7AFJSF1wRXWODndtOPp0F2v44ohQsxsg4wU3s8NCYwnNe8/j61 | |
10 | +SFVHEIw0G3t49xcxMc2+YAdur/jNqXAR8w4GplW03K73R8Y4jPStk4KPU8MnLfKZ | |
11 | +XWGq37hp5mVJlkDO91nxys4ZSvh2plKz3zRKfImEU99mWj7u8ZSKPpYU/LCm97FA | |
12 | +CdweW5PIyzWKSNAV/4Ge0o015rPSAlWEfGXQ8rW08oxzgEz59YOBSsxUo+4AE5zW | |
13 | +Gyls4AECgYEAylOrVBmzxoeNguyNlvmNsHOt8xz4XEA0RlZ6PnWSIT2PZ4NT1jAB | |
14 | +J9g/u2Il6zLJOvnN777+4Od4aITNVdS1xUYTkbJ8pv0dZEH9nO3BSKzHgx8S/Har | |
15 | +Rq02B2ZDvcV0r462QV/t1YXzrtcqSasyfZbiFSTQjYYRn7I0fB8LW0ECgYEAwO93 | |
16 | +ufeogMRRb5lkI5kI85vcQChWeIwUA3HbZt6BiInmhtP8Ep9YVjamMR5bCy/m25yl | |
17 | +IJK82gD8RDuFqjJNyUoiJuHPUonxYM/msZvshEUOoCvQQkRAG5SYlSEW083Vw6wM | |
18 | +3b80nqYkYvNyJrhd93lfk9LBYJulOppYDOHAl0ECgYEAs2H1P+49xuH95DtI2bdO | |
19 | +GUimzCo+RMQj1MztOx1QPypuT29PUFJlY+dFsiQ1zE7NvP0nyc0D+3Ed/0TnLJcX | |
20 | +xdz4kq+19vPpMC+V5KGjQYT2qtlNIwsvlc0SXwMbQlCjwNb93f5oRmyp/bUE6CXh | |
21 | +8RlqPybRxPg9/eGoyPdZQUECgYBxrGW5Lx6bh4+HljO2+ZKZnWoebuXLrpSYFvwy | |
22 | +1sQxAzbMl5d8DWBJo3c1l3IC3F1DZT6xO2ODenMnbH5rcan8/+2xRPgW5GlQJg4A | |
23 | +9SJcKCfe3RGeCYJP/bQMoWtGrY7V88e82swQ8Uic+Fx4TcYnad6TROhkmC+4oHli | |
24 | +VZxYQQKBgQCx+bLdGDTfI4qYEvTyyRrTX3nv4Q31EjF2kByusObqzaliLWWnezIQ | |
25 | +yt4WMMcIP1cT4iJoSpmahkiMBwRhvAzXsPoupGVIYoT34I5zsL8aTCRHYRza75ij | |
26 | +ZreEZj3XBzYSDrigAIxsDyNzF6Ku1+VtGAL3gJXsJPDPKRH/88YOdw== | |
27 | +-----END RSA PRIVATE KEY----- | ... | ... |
1 | +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCYfAM75aGicLj2Ad7YM3Hs4PXqF8xTYlLdjboCwT51KVaJiVlTQ1aSYOAzzx7cSnPFcQIiefjY6OMfFoA9w+wCcgKYuMweMC9TNBBeg8xttu48nENpqeH81mfJ4fL3GPqWtSA2+yuWNGN1DbRJIBx2Ryw6Pj4cEHGdoUjOH4Zbwdrdvbp0FRiM4v+jGtRbQAp6GkMlaV/qbMcENr4NYI5JcrjM0j0r7LeWp6hZUjMp2vEdF+y2eEGzv8tr6lT6TEZjoHU+i4H4xx0bcIFn/IxRf+jh0NqZMJTzlVvKgujlHZ3s+/Y/bLaLj+1LcT2YIBuatghTBKFhWBiVbJgmdYKB alexandr.khivrich@gmail.com | ... | ... |