Passed
Push — develop ( 558982...38f712 )
by Nikolay
06:07
created

prepareConditionsForSearchPhrases()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
c 0
b 0
f 0
dl 0
loc 13
rs 10
cc 1
nc 1
nop 2
1
<?php
2
/*
3
 * MikoPBX - free phone system for small business
4
 * Copyright © 2017-2023 Alexey Portnov and Nikolay Beketov
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with this program.
17
 * If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
namespace MikoPBX\AdminCabinet\Controllers;
21
22
use MikoPBX\AdminCabinet\Forms\ExtensionEditForm;
23
use MikoPBX\Common\Models\{Extensions, Sip, Users};
24
use MikoPBX\Common\Providers\PBXCoreRESTClientProvider;
25
use function MikoPBX\Common\Config\appPath;
26
27
class ExtensionsController extends BaseController
28
{
29
    /**
30
     * Build the list of internal numbers and employees.
31
     */
32
    public function indexAction(): void
33
    {
34
35
    }
36
37
    /**
38
     * Fetches new records based on the request and populates the view
39
     *
40
     * @return void
41
     */
42
    public function getNewRecordsAction(): void
43
    {
44
        // Fetching parameters from POST request
45
        $currentPage = $this->request->getPost('draw');
46
        $position = $this->request->getPost('start');
47
        $recordsPerPage = $this->request->getPost('length');
48
        $searchPhrase = $this->request->getPost('search');
49
        $order = $this->request->getPost('order');
50
        $columns = $this->request->getPost('columns');
51
52
        // Initializing view variables
53
        $this->view->draw = $currentPage;
54
        $this->view->recordsFiltered = 0;
55
        $this->view->data = [];
56
57
        // Building query parameters
58
        $parameters = $this->buildQueryParameters();
59
60
        // Count the number of unique calls considering filters
61
        if (!empty($searchPhrase['value'])) {
62
            $this->prepareConditionsForSearchPhrases($searchPhrase['value'], $parameters);
63
        }
64
65
        // Execute the query and populate recordsFiltered
66
        $this->executeCountQuery($parameters);
67
68
        // Update query parameters for the main query
69
        $this->updateMainQueryParameters($parameters, $order, $columns, $recordsPerPage, $position);
70
71
        // Execute the main query and populate the view
72
        $this->executeMainQuery($parameters);
73
74
    }
75
76
    /**
77
     * Builds the initial query parameters for database queries
78
     *
79
     * @return array The array of query parameters
80
     */
81
    private function buildQueryParameters(): array
82
    {
83
        return [
84
            'models' => [
85
                'Users' => Users::class,
86
            ],
87
            'joins' => [
88
                'Sip' => [
89
                    0 => Sip::class,
90
                    1 => 'Sip.extension=Extensions.number',
91
                    2 => 'Sip',
92
                    3 => 'INNER',
93
                ],
94
                'Extensions' => [
95
                    0 => Extensions::class,
96
                    1 => 'Extensions.userid=Users.id and Extensions.is_general_user_number = "1" and Extensions.type="' . Extensions::TYPE_SIP . '"',
97
                    2 => 'Extensions',
98
                    3 => 'INNER',
99
                ],
100
                'ExternalExtensions' => [
101
                    0 => Extensions::class,
102
                    1 => 'ExternalExtensions.userid=Users.id and Extensions.is_general_user_number = "1" and ExternalExtensions.type="' . Extensions::TYPE_EXTERNAL . '"',
103
                    2 => 'ExternalExtensions',
104
                    3 => 'LEFT',
105
                ],
106
            ],
107
        ];
108
    }
109
110
    /**
111
     * Prepares conditions for database query based on the search phrase
112
     *
113
     * @param string $searchPhrase The search phrase to filter by
114
     * @param array $parameters Reference to the database query parameters
115
     * @return void
116
     */
117
    private function prepareConditionsForSearchPhrases(string $searchPhrase, array &$parameters): void
118
    {
119
        // Prepare SQL conditions to search in username, number, email, etc.
120
        $parameters['conditions'] = 'Users.username LIKE :SearchPhrase1:';
121
        $parameters['conditions'] .= ' OR Extensions.number LIKE :SearchPhrase2:';
122
        $parameters['conditions'] .= ' OR ExternalExtensions.number LIKE :SearchPhrase3:';
123
        $parameters['conditions'] .= ' OR Users.email LIKE :SearchPhrase4:';
124
125
        // Bind search parameters
126
        $parameters['bind']['SearchPhrase1'] = "%{$searchPhrase}%";
127
        $parameters['bind']['SearchPhrase2'] = "%{$searchPhrase}%";
128
        $parameters['bind']['SearchPhrase3'] = "%{$searchPhrase}%";
129
        $parameters['bind']['SearchPhrase4'] = "%{$searchPhrase}%";
130
    }
131
132
    /**
133
     * Executes the query to count filtered records and populates 'recordsFiltered'
134
     *
135
     * @param array $parameters The query parameters
136
     */
137
    private function executeCountQuery(array $parameters): void
138
    {
139
        $parameters['columns'] = 'COUNT(DISTINCT(Users.id)) as rows';
140
        // Count the number of unique calls considering filters
141
        if (!empty($searchPhrase['value'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $searchPhrase seems to never exist and therefore empty should always be true.
Loading history...
142
            $this->prepareConditionsForSearchPhrases($searchPhrase['value'], $parameters);
143
        }
144
        $query = $this->di->get('modelsManager')->createBuilder($parameters)->getQuery();
145
        $recordsFilteredReq = $query->execute()->toArray();
146
        $this->view->recordsFiltered = $recordsFilteredReq[0]['rows'] ?? 0;
147
    }
148
149
    /**
150
     * Updates the query parameters for the main query based on pagination and sorting
151
     *
152
     * @param array $parameters Existing query parameters
153
     * @param array|null $order The sorting order
154
     * @param array|null $columns The columns to consider for sorting
155
     * @param int|null $recordsPerPage The number of records per page
156
     * @param int|null $position The starting position for the query
157
     */
158
    private function updateMainQueryParameters(array &$parameters, ?array $order, ?array $columns, ?int $recordsPerPage, ?int $position): void
159
    {
160
        // Find all Users that match the specified filter
161
        $parameters['columns'] = ['id' => 'Users.id'];
162
        $userOrder = 'CAST(Extensions.number AS INTEGER)';
163
        if (is_array($order) and is_array($columns)) {
0 ignored issues
show
introduced by
The condition is_array($columns) is always true.
Loading history...
164
            $columnName = $columns[$order[0]['column']]['data'] ?? 'number';
165
            $sortDirection = $order[0]['dir'] ?? 'asc';
166
            $userOrder = $columnName . ' ' . $sortDirection;
167
        }
168
169
        $parameters['limit'] = $recordsPerPage;
170
        $parameters['offset'] = $position;
171
        $parameters['order'] = $userOrder;
172
173
        $query = $this->di->get('modelsManager')->createBuilder($parameters)->getQuery();
174
        $selectedUsers = $query->execute()->toArray();
175
        $arrIDS = array_column($selectedUsers, 'id');
176
        if (empty($arrIDS)) {
177
            return;
178
        }
179
180
        $parameters = [
181
            'models' => [
182
                'Users' => Users::class,
183
            ],
184
            'columns' => [
185
                'id' => 'Extensions.id',
186
                'username' => 'Users.username',
187
                'number' => 'Extensions.number',
188
                'mobile' => 'ExternalExtensions.number',
189
                'user_id' => 'Users.id',
190
                'disabled' => 'Sip.disabled',
191
                'email' => 'Users.email',
192
                'type' => 'Extensions.type',
193
                'avatar' => 'Users.avatar',
194
            ],
195
            'joins' => [
196
                'Sip' => [
197
                    0 => Sip::class,
198
                    1 => 'Sip.extension=Extensions.number',
199
                    2 => 'Sip',
200
                    3 => 'INNER',
201
                ],
202
                'Extensions' => [
203
                    0 => Extensions::class,
204
                    1 => 'Extensions.userid=Users.id and Extensions.is_general_user_number = "1" and Extensions.type="' . Extensions::TYPE_SIP . '"',
205
                    2 => 'Extensions',
206
                    3 => 'INNER',
207
                ],
208
                'ExternalExtensions' => [
209
                    0 => Extensions::class,
210
                    1 => 'ExternalExtensions.userid=Users.id and Extensions.is_general_user_number = "1" and ExternalExtensions.type="' . Extensions::TYPE_EXTERNAL . '"',
211
                    2 => 'ExternalExtensions',
212
                    3 => 'LEFT',
213
                ],
214
            ],
215
            'conditions' => 'Users.id IN ({ids:array})',
216
            'bind' => ['ids' => $arrIDS],
217
            'order' => $userOrder
218
        ];
219
    }
220
221
    /**
222
     * Executes the main query to fetch the records and populates the view data
223
     *
224
     * @param array $parameters The query parameters
225
     */
226
    private function executeMainQuery(array $parameters): void
227
    {
228
        $query = $this->di->get('modelsManager')->createBuilder($parameters)->getQuery();
229
        $selectedUsers = $query->execute()->toArray();
230
231
        $extensionTable = [];
232
        foreach ($selectedUsers as $userData) {
233
            if ($userData['avatar']) {
234
                $filename = md5($userData['avatar']);
235
                $imgCacheDir = appPath('sites/admin-cabinet/assets/img/cache');
236
                $imgFile = "{$imgCacheDir}/$filename.jpg";
237
                if (!file_exists($imgFile)) {
238
                    $this->base64ToJpegFile($userData['avatar'], $imgFile);
239
                }
240
                $userData['avatar'] = "{$this->url->get()}assets/img/cache/{$filename}.jpg";
241
            } else {
242
                $userData['avatar'] = "{$this->url->get()}assets/img/unknownPerson.jpg";
243
            }
244
            $userData['DT_RowId'] = $userData['id'];
245
            $userData['DT_RowClass'] = $userData['disabled'] === '1' ? 'extension-row disabled' : 'extension-row';
246
            $extensionTable[] = $userData;
247
        }
248
        $this->view->data = $extensionTable;
249
    }
250
251
    /**
252
     * Modify extension settings.
253
     *
254
     * @param string $id The ID of the extension being modified.
255
     *
256
     * @return void
257
     */
258
    public function modifyAction(string $id = ''): void
259
    {
260
        $restAnswer = $this->di->get(PBXCoreRESTClientProvider::SERVICE_NAME, [
261
            '/pbxcore/api/extensions/getRecord',
262
            PBXCoreRESTClientProvider::HTTP_METHOD_GET,
263
            ['id' => $id]
264
        ]);
265
        if ($restAnswer->success) {
266
            $getRecordStructure = (object)$restAnswer->data;
267
        } else {
268
            $this->flash->error(implode(', ', $restAnswer->messages));
269
            $this->dispatcher->forward([
270
                'controller' => 'extensions',
271
                'action' => 'index'
272
            ]);
273
            return;
274
        }
275
276
        // Create the form for editing the extension
277
        $form = new ExtensionEditForm($getRecordStructure);
278
279
        // Pass the form and extension details to the view
280
        $this->view->form = $form;
281
        $extension = Extensions::findFirstById($getRecordStructure->id) ?? new Extensions();
282
        $this->view->represent = $extension->getRepresent();
283
        $this->view->avatar = $getRecordStructure->user_avatar;
284
    }
285
286
}