OutOffWorkTimeController::indexAction()   B
last analyzed

Complexity

Conditions 9
Paths 129

Size

Total Lines 49
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 29
c 0
b 0
f 0
dl 0
loc 49
rs 7.8138
cc 9
nc 129
nop 0
1
<?php
2
3
/*
4
 * MikoPBX - free phone system for small business
5
 * Copyright © 2017-2023 Alexey Portnov and Nikolay Beketov
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License along with this program.
18
 * If not, see <https://www.gnu.org/licenses/>.
19
 */
20
21
namespace MikoPBX\AdminCabinet\Controllers;
22
23
use MikoPBX\AdminCabinet\Forms\TimeFrameEditForm;
24
use MikoPBX\Common\Models\{Extensions,
25
    IncomingRoutingTable,
26
    OutWorkTimes,
27
    OutWorkTimesRouts,
28
    Sip,
29
    SoundFiles};
30
use MikoPBX\Core\Asterisk\Configs\SIPConf;
31
32
class OutOffWorkTimeController extends BaseController
33
{
34
    /**
35
     * This function retrieves OutWorkTimes data and formats it into an array that is used to display on the index page.
36
     */
37
    public function indexAction(): void
38
    {
39
        // Define query parameters for retrieving OutWorkTimes data from the database.
40
        $parameters = [
41
            'order' => 'priority, date_from, weekday_from, time_from',
42
        ];
43
44
        // Initialize an empty array to hold the retrieved OutWorkTimes data.
45
        $timeframesTable = [];
46
47
        // Retrieve OutWorkTimes data from the database using the query parameters defined earlier.
48
        $timeFrames = OutWorkTimes::find($parameters);
49
50
        $calTypeArray = [
51
            OutWorkTimes::CAL_TYPE_NONE     => '',
52
            OutWorkTimes::CAL_TYPE_CALDAV   => $this->translation->_('tf_CAL_TYPE_CALDAV'),
53
            OutWorkTimes::CAL_TYPE_ICAL     => $this->translation->_('tf_CAL_TYPE_ICAL'),
54
        ];
55
56
        // Iterate over each OutWorkTimes record and format it into an array for displaying on the index page.
57
        foreach ($timeFrames as $timeFrame) {
58
            // If the description is less than 45 characters, use the entire string.
59
            // Otherwise, truncate it to 45 characters and add an ellipsis.
60
            if (mb_strlen($timeFrame->description) < 45) {
61
                $shot_description = $timeFrame->description;
62
            } else {
63
                $shot_description = trim(mb_substr($timeFrame->description, 0, 45)) . '...';
64
            }
65
            // Add the formatted OutWorkTimes record to the array of records to be displayed on the index page.
66
            $timeframesTable[] = [
67
                'id'               => $timeFrame->id,
68
                'calType'          => $calTypeArray[$timeFrame->calType],
69
                'date_from'        => ( ! empty($timeFrame->date_from)) > 0 ? date("d.m.Y", $timeFrame->date_from) : '',
70
                'date_to'          => ( ! empty($timeFrame->date_to)) > 0 ? date("d.m.Y", $timeFrame->date_to) : '',
71
                'weekday_from'     => ( ! empty($timeFrame->weekday_from)) ? $this->translation->_(date('D', strtotime("Sunday +$timeFrame->weekday_from days"))) : '',
72
                'weekday_to'       => ( ! empty($timeFrame->weekday_to)) ? $this->translation->_(date('D', strtotime("Sunday +$timeFrame->weekday_to days"))) : '',
73
                'time_from'        => $timeFrame->time_from,
74
                'time_to'          => $timeFrame->time_to,
75
                'action'           => $timeFrame->action,
76
                'audio_message_id' => ($timeFrame->SoundFiles) ? $timeFrame->SoundFiles->name : '',
77
                'extension'        => ($timeFrame->Extensions) ? $timeFrame->Extensions->getRepresent() : '',
78
                'description'      => $timeFrame->description,
79
                'allowRestriction' => $timeFrame->allowRestriction,
80
                'shot_description' => $shot_description,
81
            ];
82
        }
83
84
        // Assign the formatted OutWorkTimes data to the view variable used for displaying it on the index page.
85
        $this->view->indexTable = $timeframesTable;
86
    }
87
88
    /**
89
     * Changes the priority of the OutWorkTimes data based on the provided priority table.
90
     * @return void
91
     */
92
    public function changePriorityAction(): void
93
    {
94
        $this->view->disable();
95
        $result = true;
96
97
        if (! $this->request->isPost()) {
98
            return;
99
        }
100
        $priorityTable = $this->request->getPost();
101
        $rules = OutWorkTimes::find();
102
        foreach ($rules as $rule) {
103
            if (array_key_exists($rule->id, $priorityTable)) {
104
                $rule->priority = $priorityTable[$rule->id];
105
                $result         .= $rule->update();
106
            }
107
        }
108
        echo json_encode($result);
109
    }
110
111
    /**
112
     * This function modifies the OutWorkTimes data based on the provided ID.
113
     *
114
     * @param string $id - The ID of the OutWorkTimes data to modify. (Optional)
115
     *
116
     * @return void
117
     */
118
    public function modifyAction(string $id = ''): void
119
    {
120
        // Find the OutWorkTimes data based on the provided ID
121
        // or create a new one if the ID is not provided or not found.
122
        $timeFrame = OutWorkTimes::findFirstById($id);
123
        if ($timeFrame === null) {
124
            $timeFrame = new OutWorkTimes();
125
        }
126
127
        // Create an array to store the extensions to forward calls to and populate it with the default value.
128
        $forwardingExtensions = [];
129
        $forwardingExtensions[""] = $this->translation->_("ex_SelectNumber");
130
131
        // Set the parameters to find extensions matching the extension in the OutWorkTimes data.
132
        $parameters = [
133
            'conditions' => 'number = :extension:',
134
            'bind' => [
135
                'extension' => $timeFrame->extension,
136
            ],
137
        ];
138
139
        // Find the extensions matching the specified parameters and add them to the $forwardingExtensions array.
140
        $extensions = Extensions::find($parameters);
141
        foreach ($extensions as $record) {
142
            $forwardingExtensions[$record->number] = $record->getRepresent();
143
        }
144
145
        // Create an array to store the available audio messages and populate it with the default value.
146
        $audioMessages = [];
147
        $audioMessages[""] = $this->translation->_("sf_SelectAudioFile");
148
149
        // Find the sound files with the "custom" category and add them to the $audioMessages array.
150
        $soundFiles = SoundFiles::find('category="custom"');
151
        foreach ($soundFiles as $record) {
152
            $audioMessages[$record->id] = $record->name;
153
        }
154
155
        // Create an array to store the available actions and populate it with the default values.
156
        $availableActions = [
157
            'playmessage' => $this->translation->_('tf_SelectActionPlayMessage'),
158
            'extension' => $this->translation->_('tf_SelectActionRedirectToExtension'),
159
        ];
160
161
        // Create an array to store the available week days and populate it with the default values.
162
        $weekDays = ['-1' => '-'];
163
        for ($i = "1"; $i <= 7; $i++) {
164
            $weekDays[$i] = $this->translation->_(date('D', strtotime("Sunday +$i days")));
165
        }
166
167
        // Create a new TimeFrameEditForm object with the $timeFrame
168
        // and arrays for the forwarding extensions, audio messages, available actions, and week days.
169
        $form = new TimeFrameEditForm(
170
            $timeFrame,
171
            [
172
                'extensions' => $forwardingExtensions,
173
                'audio-message' => $audioMessages,
174
                'available-actions' => $availableActions,
175
                'week-days' => $weekDays,
176
            ]
177
        );
178
179
        // Set the form and the represented value of the $timeFrame object to the view.
180
        $this->view->form = $form;
181
        $this->view->represent = $timeFrame->getRepresent();
182
183
        // Get the list of allowed routing rules for the specified time condition ID.
184
        $parameters = [
185
            'columns' => 'routId AS rule_id',
186
            'conditions' => 'timeConditionId=:timeConditionId:',
187
            'bind' => [
188
                'timeConditionId' => $id,
189
            ],
190
        ];
191
        $allowedRules    = OutWorkTimesRouts::find($parameters)->toArray();
192
        $allowedRulesIds = array_column($allowedRules, 'rule_id');
193
194
195
        $filter = [
196
            'conditions' => 'type="friend"',
197
            'columns' => 'host,port,uniqid,registration_type',
198
        ];
199
        $data = Sip::find($filter)->toArray();
200
        $providersId = [];
201
        foreach ($data as $providerData) {
202
            if ($providerData['registration_type'] === Sip::REG_TYPE_INBOUND || empty($providerData['host'])) {
203
                $providersId[$providerData['uniqid']] = $providerData['uniqid'];
204
            } else {
205
                $providersId[$providerData['uniqid']]
206
                    = SIPConf::getContextId($providerData['host'], $providerData['port']);
207
            }
208
        }
209
        unset($data);
210
211
        // Get the list of allowed routing rules
212
        $rules        = IncomingRoutingTable::find(['order' => 'provider,number,priority', 'conditions' => 'id>1']);
213
        $routingTable = [];
214
        foreach ($rules as $rule) {
215
            $provider = $rule->Providers;
216
            if ($provider) {
217
                $modelType  = ucfirst($provider->type);
218
                $provByType = $provider->$modelType;
219
            } else {
220
                $provByType = new SIP();
221
            }
222
            $extension = $rule->Extensions;
223
            $values = [
224
                'id'        => $rule->id,
225
                'rulename'  => $rule->rulename,
226
                'priority'  => $rule->priority,
227
                'number'    => $rule->number,
228
                'timeout'   => $rule->timeout,
229
                'provider'  => $rule->Providers ? $rule->Providers->getRepresent() : '',
230
                'provider-uniqid'  => $rule->Providers ? $rule->Providers->uniqid : 'none',
231
                'context-id'  => $rule->Providers ? $providersId[$rule->Providers->uniqid] : 'none',
232
                'disabled'  => $provByType->disabled,
233
                'extension' => $rule->extension,
234
                'callerid'  => $extension ? $extension->getRepresent() : '',
235
                'note'      => $rule->note,
236
                'status'    => in_array($rule->id, $allowedRulesIds, false) ? '' : 'disabled',
237
            ];
238
239
            $routingTable[] = $values;
240
        }
241
242
        $this->view->rules = $routingTable;
243
244
        // Prepare time zone offset
245
        $dateTime = new \DateTime();
246
        $this->view->setVar('serverOffset', $dateTime->getOffset() / 60);
247
    }
248
249
    /**
250
     * Saves out of work time for a user
251
     */
252
    public function saveAction(): void
253
    {
254
        // Check if the request method is POST
255
        if (! $this->request->isPost()) {
256
            return;
257
        }
258
259
        // Get the data from the POST request
260
        $data = $this->request->getPost();
261
262
        // Begin a database transaction
263
        $this->db->begin();
264
265
        // Find the out-of-work time record by ID, or create a new record if it doesn't exist
266
        $timeFrame = OutWorkTimes::findFirstByid($data['id']);
267
        if ($timeFrame === null) {
268
            $timeFrame = new OutWorkTimes();
269
        }
270
271
        // Set the user parameters based on the data in the POST request
272
        foreach ($timeFrame as $name => $value) {
273
            switch ($name) {
274
                case 'weekday_from':
275
                case 'weekday_to':
276
                    if (! array_key_exists($name, $data)) {
277
                        $timeFrame->$name = '';
278
                    } else {
279
                        $timeFrame->$name = ($data[$name] < 1) ? null : $data[$name];
280
                    }
281
                    break;
282
                case 'allowRestriction':
283
                    if (isset($data[$name])) {
284
                        $timeFrame->$name = ($data[$name] === 'on') ? '1' : '0';
285
                    } else {
286
                        $timeFrame->$name = '0';
287
                    }
288
                    break;
289
                case 'calType':
290
                    $timeFrame->$name = ($data[$name] === 'none') ? '' : $data[$name];
291
                    break;
292
                case 'date_from':
293
                case 'date_to':
294
                case 'time_from':
295
                case 'time_to':
296
                    if (! array_key_exists($name, $data)) {
297
                        $timeFrame->$name = '';
298
                    } else {
299
                        $timeFrame->$name = $data[$name];
300
                    }
301
                    break;
302
                default:
303
                    if (! array_key_exists($name, $data)) {
304
                        continue 2;
305
                    }
306
                    $timeFrame->$name = $data[$name];
307
            }
308
        }
309
310
        // If the action is 'playmessage', set the extension to an empty string
311
        if ('playmessage' === $timeFrame->action) {
312
            $timeFrame->extension = '';
313
        }
314
315
        // Save the out-of-work time record to the database
316
        $error = !$timeFrame->save();
317
318
        // If there was an error saving the record, display the error message
319
        if ($error === false) {
320
            $errors = $timeFrame->getMessages();
321
            $this->flash->warning(implode('<br>', $errors));
322
        }
323
324
        // If the ID is empty, set the reload parameter to the modified record's ID
325
        if (empty($data['id'])) {
326
            $this->view->reload = "out-off-work-time/modify/$timeFrame->id";
327
        }
328
329
        // If there was no error saving the record, save the allowed outbound rules
330
        if (!$error) {
331
            $data['id'] = $timeFrame->id;
332
            $error = ! $this->saveAllowedOutboundRules($data);
333
        }
334
335
        // If there was an error, rollback the database transaction and set the success parameter to false
336
        if ($error) {
337
            $this->view->success = false;
338
            $this->db->rollback();
339
        } else { // Otherwise, commit the transaction, display a success message, and set the success parameter to true
340
            $this->flash->success($this->translation->_('ms_SuccessfulSaved'));
341
            $this->view->success = true;
342
            $this->db->commit();
343
        }
344
    }
345
346
    /**
347
     * Saves allowed outbound rules for a given time condition
348
     *
349
     * @param array $data
350
     *
351
     * @return bool
352
     */
353
    private function saveAllowedOutboundRules(array $data): bool
354
    {
355
        // Step 1: Delete old links to rules associated with the time condition.
356
        $parameters = [
357
            'conditions' => 'timeConditionId=:timeConditionId:',
358
            'bind'       => [
359
                'timeConditionId' => $data['id'],
360
            ],
361
        ];
362
        $oldRules   = OutWorkTimesRouts::find($parameters);
363
        if ($oldRules->delete() === false) {
364
            $errors = $oldRules->getMessages();
365
            $this->flash->error(implode('<br>', $errors));
366
367
            return false;
368
        }
369
370
        // 2. Writes the allowed outbound rules to the database for the time condition.
371
        foreach ($data as $key => $value) {
372
            if (substr_count($key, 'rule-') > 0) {
373
                $rule_id = explode('rule-', $key)[1];
374
                if ($value === 'on') {
375
                    $newRule = new OutWorkTimesRouts();
376
                    $newRule->timeConditionId = $data['id'];
377
                    $newRule->routId          = $rule_id;
378
                    if ($newRule->save() === false) {
379
                        $errors = $newRule->getMessages();
380
                        $this->flash->error(implode('<br>', $errors));
381
                        return false;
382
                    }
383
                }
384
            }
385
        }
386
387
        return true;
388
    }
389
390
    /**
391
     * Deletes the OutWorkTimes record with the specified id.
392
     *
393
     * @param string $id The id of the OutWorkTimes record to delete.
394
     * @return void
395
     */
396
    public function deleteAction(string $id = ''): void
397
    {
398
        // Find the OutWorkTimes record with the specified id
399
        $timeFrame = OutWorkTimes::findFirstByid($id);
400
        // If the record exists, delete it
401
        $timeFrame?->delete();
402
403
        // Redirect to the OutOffWorkTime index page
404
        $this->forward('OutOffWorkTime/index');
405
    }
406
}
407