Completed
Push — master ( ee406a...a0eb04 )
by Klochok
14:02
created

TicketController::actionPriorityUp()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13

Duplication

Lines 13
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 13
loc 13
ccs 0
cts 7
cp 0
rs 9.8333
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 6
1
<?php
2
/**
3
 * HiPanel tickets module
4
 *
5
 * @link      https://github.com/hiqdev/hipanel-module-ticket
6
 * @package   hipanel-module-ticket
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2015-2017, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hipanel\modules\ticket\controllers;
12
13
use hipanel\actions\Action;
14
use hipanel\actions\IndexAction;
15
use hipanel\actions\PrepareAjaxViewAction;
16
use hipanel\actions\PrepareBulkAction;
17
use hipanel\actions\ProxyAction;
18
use hipanel\actions\RedirectAction;
19
use hipanel\actions\SmartCreateAction;
20
use hipanel\actions\SmartPerformAction;
21
use hipanel\actions\SmartUpdateAction;
22
use hipanel\actions\ValidateFormAction;
23
use hipanel\actions\VariantsAction;
24
use hipanel\actions\ViewAction;
25
use hipanel\filters\EasyAccessControl;
26
use hipanel\modules\client\models\Client;
27
use hipanel\modules\client\models\stub\ClientRelationFreeStub;
28
use hipanel\modules\server\models\Server;
29
use hipanel\modules\ticket\models\Thread;
30
use hipanel\modules\ticket\models\ThreadSearch;
31
use hipanel\modules\ticket\models\TicketSettings;
32
use hiqdev\hiart\ResponseErrorException;
33
use Yii;
34
use yii\base\Event;
35
use yii\filters\PageCache;
36
use yii\helpers\ArrayHelper;
37
use yii\web\NotFoundHttpException;
38
use yii\web\Response;
39
40
/**
41
 * Class TicketController.
42
 */
43
class TicketController extends \hipanel\base\CrudController
44
{
45
    /**
46
     * Used to create newModel.
47
     * @return string
48
     */
49
    public static function modelClassName()
50
    {
51
        return Thread::class;
52
    }
53
54
    public function behaviors()
55
    {
56
        return array_merge(parent::behaviors(), [
57
            [
58
                'class' => PageCache::class,
59
                'only' => ['templates'],
60
                'duration' => 7200, // 2h
61
                'variations' => [
62
                    Yii::$app->user->getId(),
63
                ],
64
            ],
65
            [
66
                'class' => EasyAccessControl::class,
67
                'actions' => [
68
                    'create'    => 'ticket.create',
69
                    'answer'    => 'ticket.answer',
70
                    'delete'    => 'ticket.delete',
71
                    '*'         => 'ticket.read',
72
                ],
73
            ],
74
        ]);
75
    }
76
77
    public function actions()
78
    {
79
        return array_merge(parent::actions(), [
80
            'index' => [
81
                'class' => IndexAction::class,
82
                'data' => $this->prepareRefs(),
83
                'responseVariants' => [
84
                    'get-total-count' => fn(VariantsAction $action): int => Thread::find()->count(),
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_VARIABLE, expecting ',' or ')'
Loading history...
85
                ],
86
            ],
87
            'view' => [
88
                'class' => ViewAction::class,
89
                'findOptions' => $this->getSearchOptions(),
90
                'on beforeSave' => function (Event $event) {
91
                    /** @var PrepareBulkAction $action */
92
                    $action = $event->sender;
93
                    $dataProvider = $action->getDataProvider();
94
                    $dataProvider->query->joinWith('answers');
95
                },
96
                'data' => function ($action) {
97
                    $ticket = $action->model;
98
99
                    $attributes = [
100
                        'id' => $ticket->recipient_id,
101
                        'login' => $ticket->recipient,
102
                        'seller' => $ticket->recipient_seller,
103
                        'seller_id' => $ticket->recipient_seller_id,
104
                    ];
105
106
                    $isAnonymTicket = $ticket->recipient === 'anonym';
107
                    if ($isAnonymTicket) {
108
                        $attributes['seller'] = $ticket->anonym_seller;
109
                    }
110
111
                    $client = new ClientRelationFreeStub($attributes);
112
113
                    if ($isAnonymTicket) {
114
                        $client->email = $ticket->anonym_email;
115
                        $client->name = $ticket->anonym_name;
116
                    }
117
118
                    return array_merge(compact('client'), $this->prepareRefs());
119
                },
120
            ],
121
            'validate-form' => [
122
                'class' => ValidateFormAction::class,
123
            ],
124
            'answer' => [
125
                'class' => SmartUpdateAction::class,
126
                'success' => Yii::t('hipanel:ticket', 'Ticket changed'),
127
                'POST html' => [
128
                    'save' => true,
129
                    'success' => [
130
                        'class' => RedirectAction::class,
131
                        'url'   => function ($action) {
132
                            return $action->collection->count() > 1
133
                                ? $action->controller->getSearchUrl()
134
                                : $action->controller->getActionUrl('view', ['id' => $action->collection->first->id]);
135
                        },
136
                    ],
137
                    'error' => [
138
                        'class' => RedirectAction::class,
139
                    ]
140
                ],
141
            ],
142
            'create' => [
143
                'class' => SmartCreateAction::class,
144
                'success' => Yii::t('hipanel:ticket', 'Ticket posted'),
145
                'data' => function () {
146
                    return $this->prepareRefs();
147
                },
148
            ],
149
            'delete' => [
150
                'class' => SmartPerformAction::class,
151
                'success' => Yii::t('hipanel:ticket', 'Ticket deleted'),
152
            ],
153
            'subscribe' => [
154
                'class' => SmartPerformAction::class,
155
                'scenario' => 'answer',
156
                'success' => Yii::t('hipanel:ticket', 'Subscribed'),
157
                'on beforeSave' => function (Event $event) {
158
                    /** @var Action $action */
159
                    $action = $event->sender;
160
                    foreach ($action->collection->models as $model) {
161
                        $model->{$this->_subscribeAction[$action->id]} = Yii::$app->user->identity->username;
162
                    }
163
                },
164
                'POST pjax' => [
165
                    'save' => true,
166
                    'success' => [
167
                        'class' => ViewAction::class,
168
                        'view' => '_subscribeButton',
169
                        'findOptions' => ['with_answers' => 1, 'show_closed' => 1],
170
                    ],
171
                ],
172
            ],
173
            'unsubscribe' => [
174
                'class' => SmartPerformAction::class,
175
                'scenario' => 'answer',
176
                'success' => Yii::t('hipanel:ticket', 'Unsubscribed'),
177
                'on beforeSave' => function (Event $event) {
178
                    /** @var Action $action */
179
                    $action = $event->sender;
180
                    foreach ($action->collection->models as $model) {
181
                        $model->{$this->_subscribeAction[$action->id]} = Yii::$app->user->identity->username;
182
                    }
183
                },
184
                'POST pjax' => [
185
                    'save' => true,
186
                    'success' => [
187
                        'class' => ViewAction::class,
188
                        'view' => '_subscribeButton',
189
                        'findOptions' => ['with_answers' => 1, 'show_closed' => 1],
190
                    ],
191
                ],
192
            ],
193
            'close' => [
194
                'class' => SmartPerformAction::class,
195
                'scenario' => 'close',
196
                'success' => Yii::t('hipanel:ticket', 'Ticket closed'),
197
                'on beforeSave' => function (Event $event) {
198
                    /** @var Action $action */
199
                    $action = $event->sender;
200
                    foreach ($action->collection->models as $model) {
201
                        $model->{'state'} = Thread::STATE_CLOSE;
202
                    }
203
                },
204
                'POST pjax' => [
205
                    'save' => true,
206
                    'success' => [
207
                        'class' => ProxyAction::class,
208
                        'action' => 'view',
209
                        'params' => function ($action, $model) {
210
                            return ['id' => $model->id];
211
                        },
212
                    ],
213
                ],
214
            ],
215
            'open' => [
216
                'class' => SmartPerformAction::class,
217
                'scenario' => 'open',
218
                'success' => Yii::t('hipanel:ticket', 'Ticket opened'),
219
                'on beforeSave' => function (Event $event) {
220
                    /** @var Action $action */
221
                    $action = $event->sender;
222
                    foreach ($action->collection->models as $model) {
223
                        $model->{'state'} = Thread::STATE_OPEN;
224
                    }
225
                },
226
                'POST pjax' => [
227
                    'save' => true,
228
                    'success' => [
229
                        'class' => ProxyAction::class,
230
                        'action' => 'view',
231
                        'params' => function ($action, $model) {
232
                            return ['id' => $model->id];
233
                        },
234
                    ],
235
                ],
236
            ],
237
            'update-answer-modal' => [
238
                'class' => PrepareAjaxViewAction::class,
239
                'on beforeSave' => function (Event $event) {
240
                    /** @var PrepareBulkAction $action */
241
                    $action = $event->sender;
242
                    $dataProvider = $action->getDataProvider();
243
                    $dataProvider->query->joinWith('answers');
244
                },
245
                'data' => function ($action, $data) {
246
                    $answer_id = Yii::$app->request->get('answer_id');
247
                    if (!is_numeric($answer_id)) {
248
                        throw new NotFoundHttpException('Invalid answer_id');
249
                    }
250
251
                    return ArrayHelper::merge($data, [
252
                        'answer_id' => $answer_id,
253
                    ]);
254
                },
255
                'findOptions' => $this->getSearchOptions(),
256
                'scenario' => 'answer-update',
257
                'view' => '_updateAnswerModal',
258
            ],
259
        ]);
260
    }
261
262
    /**
263
     * @var array
264
     */
265
    private $_subscribeAction = ['subscribe' => 'add_watchers', 'unsubscribe' => 'del_watchers'];
266
267
    /**
268
     * @return array
269
     */
270
    protected function prepareRefs()
271
    {
272
        $state_data = array_merge(['all' => Yii::t('hipanel', 'Show all')], $this->getClassRefs('state', 'hipanel:ticket'));
273
        return [
274
            'topic_data' => $this->getRefs('topic,ticket', 'hipanel:ticket'),
275
            'state_data' => $state_data,
276
            'priority_data' => $this->getPriorities(),
277
        ];
278
    }
279
280
    /**
281
     * @return string
282
     */
283
    public function actionSettings()
284
    {
285
        $model = new TicketSettings();
286
        $request = Yii::$app->request;
287
        if ($request->isAjax && $model->load($request->post()) && $model->validate()) {
288
            $model->setFormData();
289
            Yii::$app->getSession()->setFlash('success', Yii::t('hipanel:ticket', 'Ticket settings saved'));
290
        } else {
291
            $model->getFormData();
292
        }
293
294
        return $this->render('settings', [
295
            'model' => $model,
296
        ]);
297
    }
298
299
    /**
300
     * @param $id
301
     * @return \yii\web\Response
302
     */
303
    public function actionPriorityUp($id)
304
    {
305
        $options[$id] = ['id' => $id, 'priority' => 'high'];
306
        if ($this->_ticketChange($options)) {
307
            Yii::$app->getSession()->setFlash('success',
308
                Yii::t('hipanel:ticket', 'Priority has been changed to high'));
309
        } else {
310
            Yii::$app->getSession()->setFlash('error',
311
                Yii::t('hipanel:ticket', 'Some error occurred! Priority has not been changed to high'));
312
        }
313
314
        return $this->redirect(Yii::$app->request->referrer);
315
    }
316
317
    /**
318
     * @param $id
319
     * @return \yii\web\Response
320
     */
321
    public function actionPriorityDown($id)
322
    {
323
        $options[$id] = ['id' => $id, 'priority' => 'medium'];
324
        if ($this->_ticketChange($options)) {
325
            Yii::$app->getSession()->setFlash('success',
326
                Yii::t('hipanel:ticket', 'Priority has been changed to medium'));
327
        } else {
328
            Yii::$app->getSession()->setFlash('error', Yii::t('hipanel:ticket', 'Something goes wrong!'));
329
        }
330
331
        return $this->redirect(Yii::$app->request->referrer);
332
    }
333
334
    /**
335
     * Numerous ticket changes in one method, like BladeRoot did :).
336
     * @param array $options
337
     * @param string $action
338
     * @param bool $batch
339
     * @return bool
340
     */
341
    private function _ticketChange($options = [], $action = 'answer', $batch = true)
342
    {
343
        try {
344
            Thread::perform($action, $options, ['batch' => $batch]);
345
        } catch (ResponseErrorException $e) {
346
            return false;
347
        }
348
349
        return true;
350
    }
351
352
    /**
353
     * @return string
354
     */
355
    public function actionGetQuotedAnswer()
356
    {
357
        $request = Yii::$app->request;
358
        if ($request->isAjax) {
359
            $id = $request->post('id');
360
            if ($id !== null) {
361
                try {
362
                    $answer = Thread::perform('get-answer', ['id' => $id]);
363
                } catch (ResponseErrorException $e) {
364
                }
365
                if (isset($answer['message'])) {
366
                    return '> ' . str_replace("\n", "\n> ", $answer['message']);
367
                }
368
            }
369
        }
370
        Yii::$app->end();
371
    }
372
373
    /**
374
     * @return mixed|string
375
     */
376
    public function actionPreview()
377
    {
378
        $request = Yii::$app->request;
379
        if ($request->isAjax) {
380
            $text = $request->post('text');
381
            if ($text) {
382
                return Thread::parseMessage($text);
383
            }
384
        }
385
        Yii::$app->end();
386
    }
387
388
    public function actionGetNewAnswers($id, $answer_id)
389
    {
390
        Yii::$app->response->format = Response::FORMAT_JSON;
391
392
        $result = ['id' => $id, 'answer_id' => $answer_id];
393
394
        try {
395
            $data = Thread::perform('get-last-answer-id', ['id' => $id, 'answer_id' => $answer_id]);
396
            $result['answer_id'] = $data['answer_id'];
397
            if ($data['answer_id'] > $answer_id) {
398
                $dataProvider = (new ThreadSearch())->search([]);
399
                $dataProvider->query->joinWith('answers');
400
                $dataProvider->query->andWhere(['id' => $id]);
401
                $dataProvider->query->andWhere($this->getSearchOptions());
402
                $models = $dataProvider->getModels();
403
404
                $result['html'] = $this->renderPartial('_answers', ['model' => reset($models)]);
405
            }
406
        } catch (ResponseErrorException $e) {
407
        }
408
409
        return $result;
410
    }
411
412
    private function getSearchOptions()
413
    {
414
        return ['with_anonym' => 1, 'with_answers' => 1, 'with_files' => 1, 'show_closed' => 1];
415
    }
416
417
    public function getPriorities()
418
    {
419
        return $this->getRefs('type,priority', 'hipanel:ticket');
420
    }
421
422
    public function actionRenderClientInfo($id)
423
    {
424
        $client = Client::find()
425
            ->where(['id' => $id])
426
            ->joinWith('contact')
427
            ->andWhere([
428
                'with_servers_count' => 1,
429
                'with_hosting_count' => 1,
430
            ])
431
            ->withDomains()
432
            ->one();
433
434
        return $this->renderAjax('_clientInfo', ['client' => $client]);
435
    }
436
}
437