Passed
Push — develop ( 0ee469...5a686e )
by Nikolay
04:29
created

BaseController::initialize()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
c 0
b 0
f 0
dl 0
loc 9
rs 10
cc 2
nc 2
nop 0
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\Common\Providers\PBXConfModulesProvider;
23
use MikoPBX\Modules\Config\WebUIConfigInterface;
24
use MikoPBX\Common\Models\{PbxExtensionModules, PbxSettings};
25
use Phalcon\Http\ResponseInterface;
26
use Phalcon\Mvc\{Controller, View};
27
use Phalcon\Tag;
28
use Phalcon\Text;
29
use Sentry\SentrySdk;
30
31
/**
32
 * @property \Phalcon\Session\Manager session
33
 * @property \MikoPBX\Common\Providers\TranslationProvider translation
34
 * @property string language
35
 * @property bool showModuleStatusToggle if false it hides status toggle on current UI page
36
 * @property \MikoPBX\AdminCabinet\Library\Elements elements
37
 * @property \Phalcon\Flash\Session flash
38
 * @property \Phalcon\Tag tag
39
 * @property \Phalcon\Config\Adapter\Json config
40
 * @property \Phalcon\Logger loggerAuth
41
 */
42
class BaseController extends Controller
43
{
44
    protected string $actionName;
45
    protected string $controllerName;
46
    protected string $controllerNameUnCamelized;
47
    protected bool $isExternalModuleController;
48
49
    /**
50
     * Initializes base class
51
     */
52
    public function initialize(): void
53
    {
54
        $this->actionName = $this->dispatcher->getActionName();
55
        $this->controllerName = Text::camelize($this->dispatcher->getControllerName(), '_');
56
        $this->controllerNameUnCamelized = Text::uncamelize($this->controllerName, '-');
57
        $this->isExternalModuleController = str_starts_with($this->dispatcher->getNamespaceName(), '\\Module');
58
59
        if ($this->request->isAjax() === false) {
60
            $this->prepareView();
61
        }
62
    }
63
64
    /**
65
     * Prepares the view by setting necessary variables and configurations.
66
     *
67
     * @return void
68
     */
69
    protected function prepareView(): void
70
    {
71
        // Set the default timezone based on PBX settings
72
        date_default_timezone_set(PbxSettings::getValueByKey('PBXTimezone'));
73
74
        // Set PBXLicense view variable if session exists
75
        if ($this->session->has(SessionController::SESSION_ID)) {
76
            $this->view->PBXLicense = PbxSettings::getValueByKey('PBXLicense');
77
        } else {
78
            $this->view->PBXLicense = '';
79
        }
80
81
        // Set URLs for Wiki and Support based on language
82
        $this->view->urlToWiki = "https://wiki.mikopbx.com/{$this->controllerNameUnCamelized}";
83
        if ($this->language === 'ru') {
84
            $this->view->urlToSupport = 'https://www.mikopbx.ru/support/?fromPBX=true';
85
        } else {
86
            $this->view->urlToSupport = 'https://www.mikopbx.com/support/?fromPBX=true';
87
        }
88
89
        // Set the title based on the current action
90
        $title = 'MikoPBX';
91
        switch ($this->actionName) {
92
            case'index':
93
            case'delete':
94
            case'save':
95
            case'modify':
96
            case'*** WITHOUT ACTION ***':
97
                $title .= '|' . $this->translation->_("Breadcrumb{$this->controllerName}");
98
                break;
99
            default:
100
                $title .= '|' . $this->translation->_("Breadcrumb{$this->controllerName}{$this->actionName}");
101
        }
102
        Tag::setTitle($title);
103
104
        // Set other view variables
105
        $this->view->t = $this->translation;
106
        $this->view->debugMode = $this->config->path('adminApplication.debugMode');
107
        $this->view->urlToLogo = $this->url->get('assets/img/logo-mikopbx.svg');
108
        $this->view->urlToController = $this->url->get($this->controllerNameUnCamelized);
109
        $this->view->represent = '';
110
        $this->view->WebAdminLanguage = PbxSettings::getValueByKey('WebAdminLanguage');
111
        $this->view->AvailableLanguages = json_encode($this->elements->getAvailableWebAdminLanguages());
112
        $this->view->submitMode = $this->session->get('SubmitMode') ?? 'SaveSettings';
113
        $this->view->lastSentryEventId = $this->setLastSentryEventId();
114
        $this->view->PBXVersion = PbxSettings::getValueByKey('PBXVersion');
115
        $this->view->MetaTegHeadDescription = $this->translation->_('MetaTegHeadDescription');
116
        $this->view->isExternalModuleController = $this->isExternalModuleController;
117
118
        if ($this->controllerName!=='Session'){
119
            $this->view->setTemplateAfter('main');
120
        }
121
122
        $this->view->globalModuleUniqueId = '';
123
        $this->view->actionName = $this->dispatcher->getActionName();
124
        $this->view->controllerName = $this->controllerName;
125
126
        // Add module variables into view if it is an external module controller
127
        if ($this->isExternalModuleController) {
128
            /** @var PbxExtensionModules $module */
129
            $module = PbxExtensionModules::findFirstByUniqid($this->getModuleUniqueId());
130
            if ($module === null) {
131
                $module = new PbxExtensionModules();
132
                $module->disabled = '1';
133
                $module->name = 'Unknown module';
134
            }
135
            $this->view->module = $module->toArray();
136
            $this->view->globalModuleUniqueId = $module->uniqid;
137
        }
138
    }
139
140
    /**
141
     * Performs actions after executing the route and returns the response.
142
     *
143
     * @return \Phalcon\Http\ResponseInterface
144
     */
145
    public function afterExecuteRoute(): ResponseInterface
146
    {
147
148
        if ($this->request->isAjax() === true) {
149
            $this->view->setRenderLevel(View::LEVEL_NO_RENDER);
150
            $this->response->setContentType('application/json', 'UTF-8');
151
            $data = $this->view->getParamsToView();
152
153
            /* Set global params if is not set in controller/action */
154
            if (isset($data['raw_response'])) {
155
                $result = $data['raw_response'];
156
            } else {
157
                $data['success'] = $data['success'] ?? true;
158
                $data['reload'] = $data['reload'] ?? false;
159
                $data['message'] = $data['message'] ?? $this->flash->getMessages();
160
161
                // Let's add information about the last error to display a dialog window for the user.
162
                if (file_exists('/etc/sendmetrics')) {
163
                    $data['lastSentryEventId'] = SentrySdk::getCurrentHub()->getLastEventId();
164
                }
165
                $result = json_encode($data);
166
            }
167
            $this->response->setContent($result);
168
        }
169
170
        PBXConfModulesProvider::hookModulesMethod(WebUIConfigInterface::ON_AFTER_EXECUTE_ROUTE,[$this]);
171
172
        return $this->response->send();
173
    }
174
175
    /**
176
     * Performs actions before executing the route.
177
     *
178
     * @return void
179
     */
180
    public function beforeExecuteRoute(): void
181
    {
182
        PBXConfModulesProvider::hookModulesMethod(WebUIConfigInterface::ON_BEFORE_EXECUTE_ROUTE,[$this]);
183
184
        // Check if the request method is POST
185
        if ($this->request->isPost()) {
186
            // Retrieve the 'submitMode' data from the request
187
            $data = $this->request->getPost('submitMode');
188
            if (!empty($data)) {
189
                // Set the 'SubmitMode' session variable to the retrieved data
190
                $this->session->set('SubmitMode', $data);
191
            }
192
        }
193
    }
194
195
    /**
196
     * Forwards the request to a different controller and action based on the provided URI.
197
     *
198
     * @param string $uri The URI to forward to.
199
     * @return void
200
     */
201
    protected function forward(string $uri): void
202
    {
203
        $uriParts = explode('/', $uri);
204
        $params = array_slice($uriParts, 2);
205
206
        $this->dispatcher->forward(
207
            [
208
                'controller' => $uriParts[0],
209
                'action' => $uriParts[1],
210
                'params' => $params,
211
            ]
212
213
        );
214
    }
215
216
    /**
217
     * Sanitizes the caller ID by removing any characters that are not alphanumeric or spaces.
218
     *
219
     * @param string $callerId The caller ID to sanitize.
220
     * @return string The sanitized caller ID.
221
     */
222
    protected function sanitizeCallerId(string $callerId): string
223
    {
224
        return preg_replace('/[^a-zA-Zа-яА-Я0-9 ]/ui', '', $callerId);
225
    }
226
227
    /**
228
     * Sorts array by priority field
229
     *
230
     * @param $a
231
     * @param $b
232
     *
233
     * @return int|null
234
     */
235
    protected function sortArrayByPriority($a, $b): ?int
236
    {
237
        if (is_array($a)) {
238
            $a = (int)$a['priority'];
239
        } else {
240
            $a = (int)$a->priority;
241
        }
242
243
        if (is_array($b)) {
244
            $b = (int)$b['priority'];
245
        } else {
246
            $b = (int)$b->priority;
247
        }
248
249
        if ($a === $b) {
250
            return 0;
251
        } else {
252
            return ($a < $b) ? -1 : 1;
253
        }
254
    }
255
256
    /**
257
     * Sets the last Sentry event ID.
258
     *
259
     * @return \Sentry\EventId|null The last Sentry event ID, or null if metrics sending is disabled.
260
     */
261
    private function setLastSentryEventId(): ?\Sentry\EventId
262
    {
263
        $result = null;
264
        // Allow anonymous statistics collection for JS code
265
        if (PbxSettings::getValueByKey('SendMetrics') === '1') {
266
            touch('/etc/sendmetrics');
267
            $result = SentrySdk::getCurrentHub()->getLastEventId();
268
        } elseif (file_exists('/etc/sendmetrics')) {
269
            unlink('/etc/sendmetrics');
270
        }
271
        return $result;
272
    }
273
274
    /**
275
     *  Returns the unique ID of the module parsing controller namespace;
276
     * @return string
277
     */
278
    private function getModuleUniqueId():string
279
    {
280
        // Split the namespace into an array using the backslash as a separator
281
        $parts = explode('\\', get_class($this));
282
283
        // Get the second part of the namespace
284
        return $parts[1];
285
    }
286
}
287