Passed
Push — develop ( 1400c3...4b192b )
by Портнов
04:46
created

BaseController::customWikiLinks()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 9
c 1
b 0
f 0
dl 0
loc 13
rs 9.9666
cc 3
nc 3
nop 0
1
<?php
2
/*
3
 * MikoPBX - free phone system for small business
4
 * Copyright (C) 2017-2020 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\Models\{PbxExtensionModules, PbxSettings};
23
use Phalcon\Mvc\{Controller, View};
24
use Phalcon\Logger;
25
use Phalcon\Tag;
26
use Phalcon\Text;
27
use Sentry\SentrySdk;
28
29
30
/**
31
 * @property array                                         sessionRO
32
 * @property \Phalcon\Session\Manager                      session
33
 * @property \MikoPBX\Common\Providers\TranslationProvider translation
34
 * @property string                                        language
35
 * @property \MikoPBX\AdminCabinet\Library\Elements        elements
36
 * @property string                                        moduleName
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
48
    public const WIKI_LINKS = '/var/etc/wiki-links-LANG.json';
49
50
    /**
51
     * Initializes base class
52
     */
53
    public function initialize(): void
54
    {
55
        $this->actionName                = $this->dispatcher->getActionName();
56
        $this->controllerName            = Text::camelize($this->dispatcher->getControllerName(), '_');
57
        $this->controllerNameUnCamelized = Text::uncamelize($this->controllerName, '-');
58
59
        $this->moduleName = $this->dispatcher->getModuleName();
60
61
        if ($this->request->isAjax() === false) {
62
            $this->prepareView();
63
        }
64
    }
65
66
    /**
67
     * Кастомизация ссылок на wiki документацию.
68
     * @return void
69
     */
70
    private function customWikiLinks(): void
71
    {
72
        $filename = str_replace('LANG', $this->language, self::WIKI_LINKS);
73
        if(!file_exists($filename)){
74
            return;
75
        }
76
        try {
77
            $links = json_decode(file_get_contents($filename), true, 512, JSON_THROW_ON_ERROR);
78
        }catch (\Exception $e){
79
            return;
80
        }
81
        $this->view->urlToWiki    = $links[$this->view->urlToWiki]??$this->view->urlToWiki;
82
        $this->view->urlToSupport = $links[$this->view->urlToSupport]??$this->view->urlToSupport;
83
    }
84
85
    /**
86
     * Prepares some environments to every controller and view
87
     *
88
     */
89
    protected function prepareView(): void
90
    {
91
        date_default_timezone_set($this->getSessionData('PBXTimezone'));
92
        $roSession              = $this->sessionRO;
93
        $this->view->PBXVersion = $this->getSessionData('PBXVersion');
94
        if ($roSession !== null && array_key_exists('auth', $roSession)) {
95
            $this->view->SSHPort    = $this->getSessionData('SSHPort');
96
            $this->view->PBXLicense = $this->getSessionData('PBXLicense');
97
        } else {
98
            $this->view->SSHPort    = '';
99
            $this->view->PBXLicense = '';
100
        }
101
        // Кеш версий модулей и атс, для правильной работы АТС при установке модулей
102
        $versionHash = $this->getVersionsHash();
103
        $this->session->set('versionHash', $versionHash);
104
105
        $this->view->WebAdminLanguage   = $this->getSessionData('WebAdminLanguage');
106
        $this->view->AvailableLanguages = json_encode($this->elements->getAvailableWebAdminLanguages());
107
108
        if ($roSession !== null && array_key_exists('SubmitMode', $roSession)) {
109
            $this->view->submitMode = $roSession['SubmitMode'];
110
        } else {
111
            $this->view->submitMode = 'SaveSettings';
112
        }
113
114
        // Добавим версию модуля, если это модуль
115
        if ($this->moduleName === 'PBXExtension') {
116
            $module = PbxExtensionModules::findFirstByUniqid($this->controllerName);
117
            if ($module === null) {
118
                $module           = new PbxExtensionModules();
119
                $module->disabled = '1';
120
                $module->name     = 'Unknown module';
121
            }
122
            $this->view->module = $module;
123
        }
124
125
        // Разрешим отправку анонимной информации об ошибках
126
        if ($this->getSessionData('SendMetrics') === '1') {
127
            touch('/tmp/sendmetrics');
128
            $this->view->lastSentryEventId = SentrySdk::getCurrentHub()->getLastEventId();
129
        } else {
130
            if (file_exists('/tmp/sendmetrics')) {
131
                unlink('/tmp/sendmetrics');
132
            }
133
            $this->view->lastSentryEventId = null;
134
        }
135
        $title = 'MikoPBX';
136
        switch ($this->actionName) {
137
            case'index':
138
            case'delete':
139
            case'save':
140
            case'modify':
141
            case'*** WITHOUT ACTION ***':
142
                $title .= '|'. $this->translation->_("Breadcrumb{$this->controllerName}");
143
                break;
144
            default:
145
                $title .= '|'. $this->translation->_("Breadcrumb{$this->controllerName}{$this->actionName}");
146
        }
147
        Tag::setTitle($title);
148
        $this->view->t         = $this->translation;
149
        $this->view->debugMode = $this->config->path('adminApplication.debugMode');
150
        $this->view->urlToLogo = $this->url->get('assets/img/logo-mikopbx.svg');
151
        if ($this->language === 'ru') {
152
            $this->view->urlToWiki
153
                = "https://wiki.mikopbx.com/{$this->controllerNameUnCamelized}";
154
            $this->view->urlToSupport
155
                = 'https://www.mikopbx.ru/support/?fromPBX=true';
156
        } else {
157
            $this->view->urlToWiki
158
                = "https://wiki.mikopbx.com/{$this->language}:{$this->controllerNameUnCamelized}";
159
            $this->view->urlToSupport
160
                = 'https://www.mikopbx.com/support/?fromPBX=true';
161
        }
162
163
        $this->customWikiLinks();
164
165
        $this->view->urlToController = $this->url->get($this->controllerNameUnCamelized);
166
        $this->view->represent       = '';
167
        $this->view->cacheName       = "{$this->controllerName}{$this->actionName}{$this->language}{$versionHash}";
168
169
        // If it is module we have to use another template
170
        if ($this->moduleName === 'PBXExtension') {
171
            $this->view->setTemplateAfter('modules');
172
        } else {
173
            $this->view->setTemplateAfter('main');
174
        }
175
176
    }
177
178
    /**
179
     * Gets data from session or database if it not exists in session store
180
     *
181
     * @param $key string session parameter
182
     *
183
     * @return string
184
     */
185
    protected function getSessionData(string $key): string
186
    {
187
        $roSession = $this->sessionRO;
188
        if ($roSession !== null && array_key_exists($key, $roSession) && ! empty($roSession[$key])) {
189
            $value = $roSession[$key];
190
        } else {
191
            $value = PbxSettings::getValueByKey($key);
192
            $this->session->set($key, $value);
193
        }
194
195
        return $value;
196
    }
197
198
    /**
199
     * Generates common hash sum for correct combine CSS and JS according to installed modules
200
     *
201
     */
202
    private function getVersionsHash(): string
203
    {
204
        $result          = PbxSettings::getValueByKey('PBXVersion');
205
        $modulesVersions = PbxExtensionModules::getModulesArray();
206
        foreach ($modulesVersions as $module) {
207
            $result .= "{$module['id']}{$module['version']}";
208
        }
209
210
        return md5($result);
211
    }
212
213
    /**
214
     * Changes the AJAX response by expected format
215
     *
216
     * @return \Phalcon\Http\Response|\Phalcon\Http\ResponseInterface
217
     */
218
    public function afterExecuteRoute()
219
    {
220
        if ($this->request->isAjax() === true) {
221
            $this->view->setRenderLevel(View::LEVEL_NO_RENDER);
222
            $this->response->setContentType('application/json', 'UTF-8');
223
            $data = $this->view->getParamsToView();
224
225
            /* Set global params if is not set in controller/action */
226
            if (is_array($data) && isset($data['raw_response'])) {
227
                $result = $data['raw_response'];
228
            } elseif (is_array($data)) {
229
                $data['success'] = array_key_exists('success', $data) ? $data['success'] : true;
230
                $data['reload']  = array_key_exists('reload', $data) ? $data['reload'] : false;
231
                $data['message'] = $data['message'] ?? $this->flash->getMessages();
232
233
                // Добавим информацию о последней ошибке для отображения диалогового окна для пользователя
234
                if (file_exists('/tmp/sendmetrics')) {
235
                    $data['lastSentryEventId'] = SentrySdk::getCurrentHub()->getLastEventId();
236
                }
237
                $result = json_encode($data);
238
            } else {
239
                $result = '';
240
            }
241
242
            $this->response->setContent($result);
243
        }
244
245
        return $this->response->send();
246
    }
247
248
    /**
249
     * Callback before execute any route
250
     */
251
    public function beforeExecuteRoute(): void
252
    {
253
        if ($this->request->isPost()) {
254
            $data = $this->request->getPost('submitMode');
255
            if ( ! empty($data)) {
256
                $this->session->set('SubmitMode', $data);
257
            }
258
        }
259
    }
260
261
    /**
262
     * Change page without reload browser page
263
     *
264
     * @param string $uri
265
     */
266
    protected function forward(string $uri): void
267
    {
268
        $uriParts = explode('/', $uri);
269
        $params   = array_slice($uriParts, 2);
270
271
        $this->dispatcher->forward(
272
            [
273
                'controller' => $uriParts[0],
274
                'action'     => $uriParts[1],
275
                'params'     => $params,
276
            ]
277
278
        );
279
    }
280
281
    /**
282
     * Removes all dangerous symbols from CallerID
283
     * @param string $callerId
284
     *
285
     * @return string
286
     */
287
    protected function sanitizeCallerId(string $callerId): string
288
    {
289
        return preg_replace('/[^a-zA-Zа-яА-Я0-9 ]/ui', '', $callerId);
290
    }
291
292
    /**
293
     * Sorts array by priority field
294
     *
295
     * @param $a
296
     * @param $b
297
     *
298
     * @return int|null
299
     */
300
    protected function sortArrayByPriority($a, $b): ?int
301
    {
302
        if (is_array($a)){
303
            $a = (int)$a['priority'];
304
        } else {
305
            $a = (int)$a->priority;
306
        }
307
308
        if (is_array($b)){
309
            $b = (int)$b['priority'];
310
        } else {
311
            $b = (int)$b->priority;
312
        }
313
314
        if ($a === $b) {
315
            return 0;
316
        } else {
317
            return ($a < $b) ? -1 : 1;
318
        }
319
    }
320
}
321