/
mikopbx
/
ModulePhoneBook
Обзор
Документация
Войти
/
mikopbx
/
ModulePhoneBook
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
master
App/Controllers/ModulePhoneBookController.php
261 строка
10 KB
Nikolay Beketov
fix: resolve code review issues in phonebook module
06 дек 2025, 03:26
06 дек 2025, 03:26
4ac0ed9
Код
Авторство
О чём код?
<?php /* * MikoPBX - free phone system for small business * Copyright © 2017-2024 Alexey Portnov and Nikolay Beketov * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program. * If not, see <https://www.gnu.org/licenses/>. */ namespace Modules\ModulePhoneBook\App\Controllers; use MikoPBX\AdminCabinet\Controllers\BaseController; use MikoPBX\AdminCabinet\Providers\AssetProvider; use Modules\ModulePhoneBook\App\Forms\ModuleConfigForm; use Modules\ModulePhoneBook\Models\PhoneBook; use Modules\ModulePhoneBook\Models\Settings; class ModulePhoneBookController extends BaseController { private $moduleUniqueID = 'ModulePhoneBook'; public bool $showModuleStatusToggle = false; /** * Controller for the index page. */ public function indexAction(): void { $this->view->logoImagePath = "{$this->url->get()}assets/img/cache/{$this->moduleUniqueID}/logo.svg"; $this->view->submitMode = null; // Add necessary CSS files $headerCollectionCSS = $this->assets->collection(AssetProvider::HEADER_CSS); $headerCollectionCSS ->addCss('css/vendor/datatable/dataTables.semanticui.min.css', true) ->addCss("css/cache/{$this->moduleUniqueID}/module-phonebook.css", true); // Add Semantic UI modal CSS $semanticCollectionCSS = $this->assets->collection(AssetProvider::SEMANTIC_UI_CSS); $semanticCollectionCSS ->addCss('css/vendor/semantic/progress.min.css', true) ->addCss('css/vendor/semantic/modal.min.css', true); // Add Semantic UI modal JS $semanticCollectionJS = $this->assets->collection(AssetProvider::SEMANTIC_UI_JS); $semanticCollectionJS ->addJs('js/vendor/semantic/progress.min.js', true) ->addJs('js/vendor/semantic/modal.min.js', true); // Add JS files required for this page $footerCollection = $this->assets->collection(AssetProvider::FOOTER_JS); $footerCollection ->addJs('js/vendor/inputmask/inputmask.js', true) ->addJs('js/vendor/inputmask/jquery.inputmask.js', true) ->addJs('js/vendor/inputmask/jquery.inputmask-multi.js', true) ->addJs('js/vendor/inputmask/bindings/inputmask.binding.js', true) ->addJs('js/vendor/datatable/dataTables.semanticui.js', true) ->addJs('js/pbx/Extensions/input-mask-patterns.js', true) ->addJs('js/vendor/resumable.js', true) ->addJs("js/cache/{$this->moduleUniqueID}/module-phonebook-status.js", true) ->addJs("js/cache/{$this->moduleUniqueID}/module-phonebook-index.js", true) ->addJs("js/cache/{$this->moduleUniqueID}/module-phonebook-settings.js", true) ->addJs("js/cache/{$this->moduleUniqueID}/module-phonebook-merging-worker.js", true) ->addJs("js/cache/{$this->moduleUniqueID}/module-phonebook-import.js", true) ->addJs("js/cache/{$this->moduleUniqueID}/module-phonebook-datatable.js", true); $settings = Settings::findFirst(); if ($settings === null) { $settings = new Settings(); $settings->disableInputMask = '0'; } $this->view->form = new ModuleConfigForm($settings); } /** * Request new call history records for DataTable in JSON format. */ public function getNewRecordsAction(): void { $currentPage = $this->request->getPost('draw'); $position = $this->request->getPost('start'); $recordsPerPage = $this->request->getPost('length'); $searchPhrase = $this->request->getPost('search'); $this->view->draw = $currentPage; $this->view->recordsTotal = 0; $this->view->recordsFiltered = 0; $this->view->data = []; // Count the total number of unique records in the phonebook table $parameters['columns'] = 'COUNT(*) as rows'; $recordsTotalReq = PhoneBook::findFirst($parameters); if ($recordsTotalReq !== null) { $recordsTotal = $recordsTotalReq->rows; $this->view->recordsTotal = $recordsTotal; } else { return; } // Count the number of records based on the search filter if (!empty($searchPhrase['value'])) { $this->prepareConditionsForSearchPhrases($searchPhrase['value'], $parameters); } $recordsFilteredReq = PhoneBook::findFirst($parameters); if ($recordsFilteredReq !== null) { $recordsFiltered = $recordsFilteredReq->rows; $this->view->recordsFiltered = $recordsFiltered; } // Retrieve all records that match the filter criteria $parameters['columns'] = [ 'call_id', 'number' => 'number_rep', 'created' => 'created', 'DT_RowId' => 'id', ]; $parameters['order'] = ['call_id desc']; $parameters['limit'] = $recordsPerPage; $parameters['offset'] = $position; $records = PhoneBook::find($parameters); $this->view->data = $records->toArray(); } /** * Prepare search conditions for filtering phonebook records. * * @param string $searchPhrase The search phrase entered by the user * @param array $parameters The query parameters to filter the phonebook records */ private function prepareConditionsForSearchPhrases(string &$searchPhrase, array &$parameters): void { $parameters['conditions'] = 'search_index like :SearchPhrase:'; $parameters['bind']['SearchPhrase'] = "%$searchPhrase%"; } /** * Save settings via an AJAX request. */ public function saveAction(): void { if (!$this->request->isPost()) { return; } $dataId = $this->request->getPost('id', ['string', 'trim']); $callId = $this->request->getPost('call_id', ['string', 'trim']); $numberRep = $this->request->getPost('number_rep', ['string', 'trim']); $number = PhoneBook::cleanPhoneNumber($numberRep, TRUE); if (empty($callId) || empty($number)) { return; } // If we are unable to change the primary field, delete the old record and recreate it $record = null; if (stripos($dataId, 'new') === false) { $record = PhoneBook::findFirstById($dataId); if ($record !== null && $record->number !== $number) { $record->delete(); $record = null; } } if ($record === null) { $record = new PhoneBook(); } $record->setPhonebookRecord($callId, $numberRep); if ($record->save() === false) { $errors = $record->getMessages(); $this->flash->error(implode('<br>', $errors)); $this->view->success = false; $this->response->setStatusCode(500); return; } $this->view->data = ['oldId' => $dataId, 'newId' => $record->id]; $this->view->success = true; } /** * Delete a phonebook record. * * @param string|null $id The record ID to delete */ public function deleteAction(?string $id = null): void { $record = PhoneBook::findFirstById($id); if ($record !== null && !$record->delete()) { $this->flash->error(implode('<br>', $record->getMessages())); $this->view->success = false; return; } $this->view->success = true; } /** * Delete all phonebook records. */ public function deleteAllRecordsAction(): void { $phoneBook = new PhoneBook(); $connection = $phoneBook->getWriteConnection(); $tableName = $phoneBook->getSource(); try { $connection->execute("DELETE FROM {$tableName}"); $this->view->result = true; $this->view->reload = 'module-phone-book/module-phone-book/index'; } catch (\Throwable $e) { $this->flash->error($e->getMessage()); $this->view->result = false; } } /** * Save settings */ public function saveSettingsAction(): void { if (!$this->request->isPost()) { return; } $settings = Settings::findFirst(); if ($settings === null) { $settings = new Settings(); } if ($this->request->hasPost('disableInputMask')) { $settings->disableInputMask = $this->request->getPost('disableInputMask') === 'true' ? '1' : '0'; } if ($this->request->hasPost('phoneBookApiUrl')) { $settings->phoneBookApiUrl = empty($this->request->getPost('phoneBookApiUrl')) ? NULL : $this->request->getPost('phoneBookApiUrl', 'trim'); $settings->phoneBookLifeTime = empty($this->request->getPost('phoneBookLifeTime')) ? 0 : $this->request->getPost('phoneBookLifeTime', 'int!'); } if (!$settings->save()) { $this->flash->error(implode('<br>', $settings->getMessages())); $this->view->success = false; $this->response->setStatusCode(500); return; } $this->view->success = true; } }