Merge b822acadb6 into 48a0990d51
This commit is contained in:
commit
778596baf9
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* FusionPBX
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FusionPBX
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mark J Crane <markjcrane@fusionpbx.com>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008-2024
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mark J Crane <markjcrane@fusionpbx.com>
|
||||
* Tim Fry <tim@fusionpbx.com>
|
||||
*/
|
||||
|
||||
echo "<!doctype html>";
|
||||
echo "<html><head></head><body><script src='resources/javascript/phrase_fetch.js'></script></body></html>";
|
||||
|
|
@ -25,244 +25,286 @@
|
|||
*/
|
||||
|
||||
//includes files
|
||||
require_once dirname(__DIR__, 2) . "/resources/require.php";
|
||||
require_once "resources/check_auth.php";
|
||||
require_once dirname(__DIR__, 2) . "/resources/require.php";
|
||||
require_once "resources/check_auth.php";
|
||||
|
||||
//check permissions
|
||||
if (permission_exists('phrase_add') || permission_exists('phrase_edit')) {
|
||||
//access granted
|
||||
}
|
||||
else {
|
||||
echo "access denied";
|
||||
exit;
|
||||
if (permission_exists('phrase_add') || permission_exists('phrase_edit')) {
|
||||
//access granted
|
||||
}
|
||||
else {
|
||||
echo "access denied";
|
||||
exit;
|
||||
}
|
||||
|
||||
function build_data_array_from_post(settings $settings) {
|
||||
global $domain_uuid, $drop_rows;
|
||||
$phrase_uuid = $_POST['phrase_uuid'];
|
||||
$array = [];
|
||||
$drop_rows = [];
|
||||
$drop_row_count = 0;
|
||||
|
||||
//load sound files from the switch so we can validate selections
|
||||
$sound_files = (new file)->sounds();
|
||||
|
||||
//update the phrase information
|
||||
$array['phrases'][0]['domain_uuid'] = $domain_uuid;
|
||||
$array['phrases'][0]['phrase_uuid'] = $phrase_uuid;
|
||||
$array['phrases'][0]['phrase_name'] = $_POST['phrase_name'];
|
||||
$array['phrases'][0]['phrase_language'] = $_POST['phrase_language'];
|
||||
$array['phrases'][0]['phrase_enabled'] = $_POST['phrase_enabled'];
|
||||
$array['phrases'][0]['phrase_description'] = $_POST['phrase_description'];
|
||||
|
||||
//recording_files are:
|
||||
// 'recording_uuid' => 'recording.wav'
|
||||
// OR
|
||||
// 'recording_uuid' => '${lua streamfile.lua ' . base64_data .'}'
|
||||
$recording_files = phrases::get_all_domain_recordings($settings);
|
||||
|
||||
//
|
||||
// Create two arrays - one for rows to delete and one for new/updated rows
|
||||
//
|
||||
for ($i = 0; $i < count($_POST['phrase_detail_function']); $i++) {
|
||||
//check for function to perform
|
||||
$phrase_detail_function = $_POST['phrase_detail_function'][$i];
|
||||
$phrase_detail_data = null;
|
||||
$recording_uuid_or_file = '';
|
||||
$phrase_detail_uuid = '';
|
||||
//check for the empty rows to delete -- 0,false,null is valid
|
||||
if (strlen($_POST['phrase_detail_data'][$i]) === 0
|
||||
&& !empty($_POST['phrase_detail_uuid'][$i])
|
||||
&& empty($_POST['slider'][$i])
|
||||
&& empty($_POST['phrase_detail_text'][$i])) {
|
||||
$drop_rows['phrase_details'][$drop_row_count++]['phrase_detail_uuid'] = $_POST['phrase_detail_uuid'][$i];
|
||||
continue;
|
||||
}
|
||||
switch ($phrase_detail_function) {
|
||||
case 'play-file':
|
||||
//only save rows with data
|
||||
if (!empty($_POST['phrase_detail_data'][$i])) {
|
||||
$recording_uuid_or_file = $_POST['phrase_detail_data'][$i];
|
||||
//check for valid recordings and files
|
||||
if (is_uuid($recording_uuid_or_file)) {
|
||||
//recording UUID
|
||||
$phrase_detail_data = $recording_files[$recording_uuid_or_file];
|
||||
} else {
|
||||
//not a recording so must be valid path inside the switch recording files
|
||||
if (in_array($recording_uuid_or_file, $sound_files)) {
|
||||
//valid switch audio file
|
||||
$phrase_detail_data = $recording_uuid_or_file;
|
||||
} else {
|
||||
//ignore an invalid audio file
|
||||
continue(2);
|
||||
}
|
||||
}
|
||||
//build data array
|
||||
if ($_POST['phrase_detail_function'][$i] == 'execute' && substr($_POST['phrase_detail_data'][$i], 0,5) != "sleep" && !permission_exists("phrase_execute")) {
|
||||
header("Location: phrase_edit.php?id=".$phrase_uuid);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'pause':
|
||||
//check for value
|
||||
$phrase_detail_data = $_POST['slider'][$i];
|
||||
break;
|
||||
case 'execute':
|
||||
//check for the empty rows to delete
|
||||
if (empty($_POST['phrase_detail_text'][$i]) && !empty($_POST['phrase_detail_uuid'][$i])) {
|
||||
$drop_rows['phrase_details'][$drop_row_count++]['phrase_detail_uuid'] = $_POST['phrase_detail_uuid'][$i];
|
||||
continue(2);
|
||||
}
|
||||
$phrase_detail_data = $_POST['phrase_detail_text'][$i];
|
||||
break;
|
||||
}
|
||||
|
||||
$_POST['phrase_detail_tag'] = 'action'; // default, for now
|
||||
$_POST['phrase_detail_group'] = "0"; // one group, for now
|
||||
|
||||
if ($phrase_detail_data !== null) {
|
||||
if (!empty($_POST['phrase_detail_uuid'][$i])) {
|
||||
//update existing records in the database
|
||||
$phrase_detail_uuid = $_POST['phrase_detail_uuid'][$i];
|
||||
} else {
|
||||
//new record
|
||||
$phrase_detail_uuid = uuid();
|
||||
}
|
||||
$array['phrase_details'][$i]['phrase_detail_uuid'] = $phrase_detail_uuid;
|
||||
$array['phrase_details'][$i]['phrase_uuid'] = $phrase_uuid;
|
||||
$array['phrase_details'][$i]['domain_uuid'] = $domain_uuid;
|
||||
$array['phrase_details'][$i]['phrase_detail_order'] = $i;
|
||||
$array['phrase_details'][$i]['phrase_detail_tag'] = $_POST['phrase_detail_tag'];
|
||||
$array['phrase_details'][$i]['phrase_detail_pattern'] = $_POST['phrase_detail_pattern'] ?? null;
|
||||
$array['phrase_details'][$i]['phrase_detail_function'] = $phrase_detail_function;
|
||||
$array['phrase_details'][$i]['phrase_detail_data'] = $phrase_detail_data; //path and filename of recording
|
||||
$array['phrase_details'][$i]['phrase_detail_method'] = $_POST['phrase_detail_method'] ?? null;
|
||||
$array['phrase_details'][$i]['phrase_detail_type'] = $_POST['phrase_detail_type'] ?? null;
|
||||
$array['phrase_details'][$i]['phrase_detail_group'] = $_POST['phrase_detail_group'];
|
||||
}
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
//set default domain
|
||||
if (empty($domain_uuid)) {
|
||||
$domain_uuid = $_SESSION['domain_uuid'] ?? '';
|
||||
}
|
||||
|
||||
//set default user
|
||||
if (empty($user_uuid)) {
|
||||
$user_uuid = $_SESSION['user_uuid'] ?? '';
|
||||
}
|
||||
|
||||
//add multi-lingual support
|
||||
$language = new text;
|
||||
$text = $language->get();
|
||||
$language = new text;
|
||||
$text = $language->get();
|
||||
|
||||
//ensure we have a database object
|
||||
$database = database::new();
|
||||
|
||||
//ensure we have a settings object
|
||||
$settings = new settings(['database' => $database, 'domain_uuid' => $domain_uuid, 'user_uuid' => $user_uuid]);
|
||||
|
||||
//add the defaults
|
||||
$phrase_name = '';
|
||||
$phrase_language = '';
|
||||
$phrase_description = '';
|
||||
$phrase_name = '';
|
||||
$phrase_language = '';
|
||||
$phrase_description = '';
|
||||
|
||||
//set the action as an add or an update
|
||||
if (!empty($_REQUEST["id"])) {
|
||||
$action = "update";
|
||||
$phrase_uuid = $_REQUEST["id"];
|
||||
}
|
||||
else {
|
||||
$action = "add";
|
||||
}
|
||||
if (!empty($_REQUEST["id"])) {
|
||||
$action = "update";
|
||||
$phrase_uuid = $_REQUEST["id"];
|
||||
}
|
||||
else {
|
||||
$action = "add";
|
||||
}
|
||||
|
||||
//get the form value and set to php variables
|
||||
if (count($_POST) > 0) {
|
||||
if (count($_POST) > 0) {
|
||||
|
||||
//process the http post data by submitted action
|
||||
if (!empty($_POST['action']) && is_uuid($_POST['phrase_uuid'])) {
|
||||
$array[0]['checked'] = 'true';
|
||||
$array[0]['uuid'] = $_POST['phrase_uuid'];
|
||||
//process the http post data by submitted action
|
||||
if (!empty($_POST['action']) && is_uuid($_POST['phrase_uuid'])) {
|
||||
$array[0]['checked'] = 'true';
|
||||
$array[0]['uuid'] = $_POST['phrase_uuid'];
|
||||
|
||||
switch ($_POST['action']) {
|
||||
case 'delete':
|
||||
if (permission_exists('phrase_delete')) {
|
||||
$obj = new phrases;
|
||||
$obj->delete($array);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
header('Location: phrases.php');
|
||||
exit;
|
||||
switch ($_POST['action']) {
|
||||
case 'delete':
|
||||
if (permission_exists('phrase_delete')) {
|
||||
$obj = new phrases;
|
||||
$obj->delete($array);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (permission_exists('phrase_domain')) {
|
||||
$domain_uuid = $_POST["domain_uuid"];
|
||||
header('Location: phrases.php');
|
||||
exit;
|
||||
}
|
||||
$phrase_name = $_POST["phrase_name"];
|
||||
$phrase_language = $_POST["phrase_language"];
|
||||
$phrase_enabled = $_POST["phrase_enabled"] ?? 'false';
|
||||
$phrase_description = $_POST["phrase_description"];
|
||||
$phrase_details_delete = $_POST["phrase_details_delete"] ?? '';
|
||||
|
||||
//clean the name
|
||||
$phrase_name = str_replace(" ", "_", $phrase_name);
|
||||
$phrase_name = str_replace("'", "", $phrase_name);
|
||||
if (permission_exists('phrase_domain')) {
|
||||
$domain_uuid = $_POST["domain_uuid"];
|
||||
}
|
||||
$phrase_name = $_POST["phrase_name"];
|
||||
$phrase_language = $_POST["phrase_language"];
|
||||
$phrase_enabled = $_POST["phrase_enabled"] ?? 'false';
|
||||
$phrase_description = $_POST["phrase_description"];
|
||||
$phrase_details_delete = $_POST["phrase_details_delete"] ?? '';
|
||||
|
||||
//clean the name
|
||||
$phrase_name = str_replace(" ", "_", $phrase_name);
|
||||
$phrase_name = str_replace("'", "", $phrase_name);
|
||||
}
|
||||
|
||||
//process the changes from the http post
|
||||
if (count($_POST) > 0 && empty($_POST["persistformvar"])) {
|
||||
|
||||
//get the uuid
|
||||
if ($action == "update") {
|
||||
$phrase_uuid = $_POST["phrase_uuid"];
|
||||
}
|
||||
if ($action == "update") {
|
||||
$phrase_uuid = $_POST["phrase_uuid"];
|
||||
}
|
||||
|
||||
//validate the token
|
||||
$token = new token;
|
||||
if (!$token->validate($_SERVER['PHP_SELF'])) {
|
||||
message::add($text['message-invalid_token'],'negative');
|
||||
header('Location: phrases.php');
|
||||
exit;
|
||||
}
|
||||
$token = new token;
|
||||
if (!$token->validate($_SERVER['PHP_SELF'])) {
|
||||
message::add($text['message-invalid_token'],'negative');
|
||||
header('Location: phrases.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
//check for all required data
|
||||
$msg = '';
|
||||
if (empty($phrase_name)) { $msg .= $text['message-required']." ".$text['label-name']."<br>\n"; }
|
||||
if (empty($phrase_language)) { $msg .= $text['message-required']." ".$text['label-language']."<br>\n"; }
|
||||
if (!empty($msg) && empty($_POST["persistformvar"])) {
|
||||
require_once "resources/header.php";
|
||||
require_once "resources/persist_form_var.php";
|
||||
echo "<div align='center'>\n";
|
||||
echo "<table><tr><td>\n";
|
||||
echo $msg."<br />";
|
||||
echo "</td></tr></table>\n";
|
||||
persistformvar($_POST);
|
||||
echo "</div>\n";
|
||||
require_once "resources/footer.php";
|
||||
return;
|
||||
}
|
||||
$msg = '';
|
||||
if (empty($phrase_name)) { $msg .= $text['message-required']." ".$text['label-name']."<br>\n"; }
|
||||
if (empty($phrase_language)) { $msg .= $text['message-required']." ".$text['label-language']."<br>\n"; }
|
||||
if (!empty($msg) && empty($_POST["persistformvar"])) {
|
||||
require_once "resources/header.php";
|
||||
require_once "resources/persist_form_var.php";
|
||||
echo "<div align='center'>\n";
|
||||
echo "<table><tr><td>\n";
|
||||
echo $msg."<br />";
|
||||
echo "</td></tr></table>\n";
|
||||
persistformvar($_POST);
|
||||
echo "</div>\n";
|
||||
require_once "resources/footer.php";
|
||||
return;
|
||||
}
|
||||
|
||||
//add the phrase
|
||||
if (empty($_POST["persistformvar"]) || $_POST["persistformvar"] != "true") {
|
||||
if ($action == "add" && permission_exists('phrase_add')) {
|
||||
//build data array
|
||||
$phrase_uuid = uuid();
|
||||
$array['phrases'][0]['domain_uuid'] = $domain_uuid;
|
||||
$array['phrases'][0]['phrase_uuid'] = $phrase_uuid;
|
||||
$array['phrases'][0]['phrase_name'] = $phrase_name;
|
||||
$array['phrases'][0]['phrase_language'] = $phrase_language;
|
||||
$array['phrases'][0]['phrase_enabled'] = $phrase_enabled;
|
||||
$array['phrases'][0]['phrase_description'] = $phrase_description;
|
||||
|
||||
if ($_POST['phrase_detail_function'] != '') {
|
||||
if ($_POST['phrase_detail_function'] == 'execute' && substr($_POST['phrase_detail_data'], 0,5) != "sleep" && !permission_exists("phrase_execute")) {
|
||||
header("Location: phrase_edit.php");
|
||||
exit;
|
||||
}
|
||||
$_POST['phrase_detail_tag'] = 'action'; // default, for now
|
||||
$_POST['phrase_detail_group'] = "0"; // one group, for now
|
||||
|
||||
if ($_POST['phrase_detail_data'] != '') {
|
||||
$phrase_detail_uuid = uuid();
|
||||
$array['phrase_details'][0]['phrase_detail_uuid'] = $phrase_detail_uuid;
|
||||
$array['phrase_details'][0]['phrase_uuid'] = $phrase_uuid;
|
||||
$array['phrase_details'][0]['domain_uuid'] = $domain_uuid;
|
||||
$array['phrase_details'][0]['phrase_detail_order'] = $_POST['phrase_detail_order'];
|
||||
$array['phrase_details'][0]['phrase_detail_tag'] = $_POST['phrase_detail_tag'];
|
||||
$array['phrase_details'][0]['phrase_detail_pattern'] = $_POST['phrase_detail_pattern'] ?? null;
|
||||
$array['phrase_details'][0]['phrase_detail_function'] = $_POST['phrase_detail_function'];
|
||||
$array['phrase_details'][0]['phrase_detail_data'] = $_POST['phrase_detail_data'];
|
||||
$array['phrase_details'][0]['phrase_detail_method'] = $_POST['phrase_detail_method'] ?? null;
|
||||
$array['phrase_details'][0]['phrase_detail_type'] = $_POST['phrase_detail_type'] ?? null;
|
||||
$array['phrase_details'][0]['phrase_detail_group'] = $_POST['phrase_detail_group'];
|
||||
}
|
||||
if (empty($_POST["persistformvar"]) || $_POST["persistformvar"] != "true") {
|
||||
$message = '';
|
||||
switch ($action) {
|
||||
case 'add':
|
||||
//redirect when they don't have permission to add a phrase
|
||||
if (!permission_exists('phrase_add')) {
|
||||
header('Location: phrases.php');
|
||||
exit();
|
||||
}
|
||||
//set user feedback message to add
|
||||
$message = $text['message-add'];
|
||||
$phrase_uuid = uuid();
|
||||
//do not break
|
||||
case 'update':
|
||||
//redirect when not adding and don't have permission to edit a phrase
|
||||
if (empty($message)) {
|
||||
if (!permission_exists('phrase_edit')) {
|
||||
header('Location: phrases.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
//execute insert
|
||||
$p = permissions::new();
|
||||
$p->add('phrase_detail_add', 'temp');
|
||||
|
||||
$database = new database;
|
||||
$database->app_name = 'phrases';
|
||||
$database->app_uuid = '5c6f597c-9b78-11e4-89d3-123b93f75cba';
|
||||
$database->save($array);
|
||||
unset($array);
|
||||
|
||||
$p->delete('phrase_detail_add', 'temp');
|
||||
|
||||
//save the xml to the file system if the phrase directory is set
|
||||
//save_phrases_xml();
|
||||
|
||||
//clear the cache
|
||||
$cache = new cache;
|
||||
$cache->delete("languages:".$phrase_language.".".$phrase_uuid);
|
||||
|
||||
//clear the destinations session array
|
||||
if (isset($_SESSION['destinations']['array'])) {
|
||||
unset($_SESSION['destinations']['array']);
|
||||
}
|
||||
|
||||
//send a redirect
|
||||
message::add($text['message-add']);
|
||||
header("Location: phrase_edit.php?id=".$phrase_uuid);
|
||||
exit;
|
||||
}
|
||||
|
||||
//update the phrase
|
||||
if ($action == "update" && permission_exists('phrase_edit')) {
|
||||
//build data array
|
||||
$array['phrases'][0]['domain_uuid'] = $domain_uuid;
|
||||
$array['phrases'][0]['phrase_uuid'] = $phrase_uuid;
|
||||
$array['phrases'][0]['phrase_name'] = $phrase_name;
|
||||
$array['phrases'][0]['phrase_language'] = $phrase_language;
|
||||
$array['phrases'][0]['phrase_enabled'] = $phrase_enabled;
|
||||
$array['phrases'][0]['phrase_description'] = $phrase_description;
|
||||
|
||||
if ($_POST['phrase_detail_function'] != '') {
|
||||
if ($_POST['phrase_detail_function'] == 'execute' && substr($_POST['phrase_detail_data'], 0,5) != "sleep" && !permission_exists("phrase_execute")) {
|
||||
header("Location: phrase_edit.php?id=".$phrase_uuid);
|
||||
exit;
|
||||
}
|
||||
$_POST['phrase_detail_tag'] = 'action'; // default, for now
|
||||
$_POST['phrase_detail_group'] = "0"; // one group, for now
|
||||
|
||||
if ($_POST['phrase_detail_data'] != '') {
|
||||
$phrase_detail_uuid = uuid();
|
||||
$array['phrase_details'][0]['phrase_detail_uuid'] = $phrase_detail_uuid;
|
||||
$array['phrase_details'][0]['phrase_uuid'] = $phrase_uuid;
|
||||
$array['phrase_details'][0]['domain_uuid'] = $domain_uuid;
|
||||
$array['phrase_details'][0]['phrase_detail_order'] = $_POST['phrase_detail_order'];
|
||||
$array['phrase_details'][0]['phrase_detail_tag'] = $_POST['phrase_detail_tag'];
|
||||
$array['phrase_details'][0]['phrase_detail_pattern'] = $_POST['phrase_detail_pattern'] ?? null;
|
||||
$array['phrase_details'][0]['phrase_detail_function'] = $_POST['phrase_detail_function'];
|
||||
$array['phrase_details'][0]['phrase_detail_data'] = $_POST['phrase_detail_data'];
|
||||
$array['phrase_details'][0]['phrase_detail_method'] = $_POST['phrase_detail_method'] ?? null;
|
||||
$array['phrase_details'][0]['phrase_detail_type'] = $_POST['phrase_detail_type'] ?? null;
|
||||
$array['phrase_details'][0]['phrase_detail_group'] = $_POST['phrase_detail_group'];
|
||||
}
|
||||
}
|
||||
|
||||
//set user feedback message to update
|
||||
$message = $text['message-update'];
|
||||
}
|
||||
if (!empty($_POST['phrase_detail_function'])) {
|
||||
$array = build_data_array_from_post($settings);
|
||||
}
|
||||
//execute update/insert
|
||||
$p = permissions::new();
|
||||
$p->add('phrase_detail_add', 'temp');
|
||||
|
||||
$database = new database;
|
||||
$database->app_name = 'phrases';
|
||||
$database->app_uuid = '5c6f597c-9b78-11e4-89d3-123b93f75cba';
|
||||
$p = permissions::new();
|
||||
$p->add('phrase_detail_add', 'temp');
|
||||
$p->add('phrase_detail_edit', 'temp');
|
||||
$p->add('phrase_detail_delete', 'temp');
|
||||
$database->app_name = 'phrases';
|
||||
$database->app_uuid = '5c6f597c-9b78-11e4-89d3-123b93f75cba';
|
||||
if (count($array) > 0) {
|
||||
$database->save($array);
|
||||
unset($array);
|
||||
|
||||
$p->delete('phrase_detail_add', 'temp');
|
||||
|
||||
//remove checked phrase details
|
||||
if (
|
||||
is_array($phrase_details_delete)
|
||||
&& @sizeof($phrase_details_delete) != 0
|
||||
) {
|
||||
$obj = new phrases;
|
||||
$obj->phrase_uuid = $phrase_uuid;
|
||||
$obj->delete_details($phrase_details_delete);
|
||||
}
|
||||
|
||||
}
|
||||
if (count($drop_rows) > 0) {
|
||||
$database->delete($drop_rows);
|
||||
unset($drop_rows);
|
||||
}
|
||||
$p->delete('phrase_detail_add', 'temp');
|
||||
//clear the cache
|
||||
$cache = new cache;
|
||||
$cache->delete("languages:".$phrase_language.".".$phrase_uuid);
|
||||
$cache = new cache;
|
||||
$cache->delete("languages:".$phrase_language.".".$phrase_uuid);
|
||||
|
||||
//clear the destinations session array
|
||||
if (isset($_SESSION['destinations']['array'])) {
|
||||
unset($_SESSION['destinations']['array']);
|
||||
}
|
||||
if (isset($_SESSION['destinations']['array'])) {
|
||||
unset($_SESSION['destinations']['array']);
|
||||
}
|
||||
|
||||
//send a redirect
|
||||
message::add($text['message-update']);
|
||||
header("Location: phrase_edit.php?id=".$phrase_uuid);
|
||||
exit;;
|
||||
|
||||
}
|
||||
|
||||
message::add($message);
|
||||
header("Location: phrase_edit.php?id=".$phrase_uuid);
|
||||
exit;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//pre-populate the form
|
||||
|
|
@ -276,7 +318,6 @@
|
|||
$sql .= "and phrase_uuid = :phrase_uuid ";
|
||||
$parameters['domain_uuid'] = $domain_uuid;
|
||||
$parameters['phrase_uuid'] = $phrase_uuid;
|
||||
$database = new database;
|
||||
$row = $database->select($sql, $parameters, 'row');
|
||||
if (is_array($row) && @sizeof($row) != 0) {
|
||||
$phrase_name = $row["phrase_name"];
|
||||
|
|
@ -298,20 +339,22 @@
|
|||
$sql .= "order by phrase_detail_order asc ";
|
||||
$parameters['domain_uuid'] = $_SESSION['domain_uuid'];
|
||||
$parameters['phrase_uuid'] = $phrase_uuid;
|
||||
$database = new database;
|
||||
$phrase_details = $database->select($sql, $parameters, 'all');
|
||||
unset($sql, $parameters);
|
||||
}
|
||||
|
||||
//get the recording names from the database.
|
||||
$sql = "select recording_name, recording_filename from v_recordings ";
|
||||
$sql = "select recording_uuid, recording_name, recording_filename, domain_uuid from v_recordings ";
|
||||
$sql .= "where domain_uuid = :domain_uuid ";
|
||||
$sql .= "order by recording_name asc ";
|
||||
$parameters['domain_uuid'] = $_SESSION['domain_uuid'];
|
||||
$database = new database;
|
||||
$recordings = $database->select($sql, $parameters, 'all');
|
||||
unset($sql, $parameters);
|
||||
|
||||
//get the switch sound files
|
||||
$file = new file;
|
||||
$sound_files = $file->sounds();
|
||||
|
||||
//create token
|
||||
$object = new token;
|
||||
$token = $object->create($_SERVER['PHP_SELF']);
|
||||
|
|
@ -321,126 +364,76 @@
|
|||
if ($action == 'update') { $document['title'] = $text['title-edit_phrase']; }
|
||||
require_once "resources/header.php";
|
||||
|
||||
//js to control action form input
|
||||
echo "<script type='text/javascript'>\n";
|
||||
|
||||
echo "function load_action_options(selected_index) {\n";
|
||||
echo " var obj_action = document.getElementById('phrase_detail_data');\n";
|
||||
echo " if (selected_index == 0 || selected_index == 1) {\n";
|
||||
echo " if (obj_action.type == 'text') {\n";
|
||||
echo " action_to_select();\n";
|
||||
echo " var obj_action = document.getElementById('phrase_detail_data');\n";
|
||||
echo " obj_action.setAttribute('style', 'width: 300px; min-width: 300px; max-width: 300px;');\n";
|
||||
echo " }\n";
|
||||
echo " else {\n";
|
||||
echo " clear_action_options();\n";
|
||||
echo " }\n";
|
||||
echo " }\n";
|
||||
if (if_group("superadmin")) {
|
||||
echo " else {\n";
|
||||
echo " document.getElementById('phrase_detail_data_switch').style.display='none';\n";
|
||||
echo " obj_action.setAttribute('style', 'width: 300px; min-width: 300px; max-width: 300px;');\n";
|
||||
echo " }\n";
|
||||
//javascript constants for use in the selection option group
|
||||
echo "<script>\n";
|
||||
echo "window.permission_execute = " . (permission_exists('phrase_execute') ? 'true' : 'false') . ";\n";
|
||||
echo "window.phrase_label_sounds = '" . ($text['label-sounds'] ?? 'Sounds') . "';\n";
|
||||
echo "window.phrase_label_recordings = '" . ($text['label-recordings'] ?? 'Recordings') . "';\n";
|
||||
//only include permissive actions
|
||||
$phrase_commands = [];
|
||||
if (permission_exists('phrase_play')) {
|
||||
$phrase_commands[] = $text['label-play'] ?? 'Play';
|
||||
$phrase_commands[] = $text['label-pause'] ?? 'Pause';
|
||||
}
|
||||
echo " if (selected_index == 0) {\n"; //play
|
||||
echo " obj_action.options[obj_action.options.length] = new Option('', '');\n"; //blank option
|
||||
//recordings
|
||||
$tmp_selected = false;
|
||||
if (is_array($recordings) && @sizeof($recordings) != 0) {
|
||||
echo "var opt_group = document.createElement('optgroup');\n";
|
||||
echo "opt_group.label = \"".$text['label-recordings']."\";\n";
|
||||
foreach ($recordings as $row) {
|
||||
if (!empty($_SESSION['recordings']['storage_type']['text']) && $_SESSION['recordings']['storage_type']['text'] == 'base64') {
|
||||
echo "opt_group.appendChild(new Option(\"".$row["recording_name"]."\", \"\${lua streamfile.lua ".$row["recording_filename"]."}\"));\n";
|
||||
}
|
||||
else {
|
||||
echo "opt_group.appendChild(new Option(\"".$row["recording_name"]."\", \"".$_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/'.$row["recording_filename"]."\"));\n";
|
||||
|
||||
if (permission_exists('phrase_execute')) {
|
||||
$phrase_commands[] = $text['label-execute'] ?? 'Execute';
|
||||
}
|
||||
echo "window.phrase_commands = " . json_encode($phrase_commands, true) . ";\n";
|
||||
|
||||
//existing details
|
||||
if (!empty($phrase_details)) {
|
||||
//update the array to include the recording name for display in select box
|
||||
foreach ($phrase_details as &$row) {
|
||||
$row['display_name'] = '';
|
||||
$file = basename($row['phrase_detail_data']);
|
||||
//get the display_name from recording name based on the file matched
|
||||
foreach ($recordings as $key => $recordings_row) {
|
||||
//match on filename first and then domain_uuid
|
||||
if ($recordings_row['recording_filename'] === $file && $recordings_row['domain_uuid'] === $row['domain_uuid']) {
|
||||
$row['display_name'] = $recordings[$key]['recording_name'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
echo "obj_action.appendChild(opt_group);\n";
|
||||
}
|
||||
unset($recordings, $row);
|
||||
//sounds
|
||||
$file = new file;
|
||||
$sound_files = $file->sounds();
|
||||
if (is_array($sound_files) && @sizeof($sound_files) != 0) {
|
||||
echo "var opt_group = document.createElement('optgroup');\n";
|
||||
echo "opt_group.label = \"".$text['label-sounds']."\";\n";
|
||||
foreach ($sound_files as $value) {
|
||||
if (!empty($value)) {
|
||||
echo "opt_group.appendChild(new Option(\"".$value."\", \"".$value."\"));\n";
|
||||
//check if display_name was not found in the recording names
|
||||
if (strlen($row['display_name']) === 0) {
|
||||
//try finding display_name in the switch sound files
|
||||
if (!empty($sound_files)) {
|
||||
//use optimized php function with strict comparison
|
||||
$i = array_search($row['phrase_detail_data'], $sound_files, true);
|
||||
//if found in the switch sound files
|
||||
if ($i !== false) {
|
||||
//set the display_name to the switch sound file name
|
||||
$row['display_name'] = $sound_files[$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
echo "obj_action.appendChild(opt_group);\n";
|
||||
}
|
||||
unset($sound_files, $row);
|
||||
echo " }\n";
|
||||
echo " else if (selected_index == 1) {\n"; //pause
|
||||
echo " obj_action.options[obj_action.options.length] = new Option('', '');\n"; //blank option
|
||||
for ($s = 0.1; $s <= 5; $s = $s + 0.1) {
|
||||
echo " obj_action.options[obj_action.options.length] = new Option('".number_format($s, 1)."s', 'sleep(".($s * 1000).")');\n";
|
||||
//send the phrase details to the browser as a global scope json array object
|
||||
//echo "window.phrase_details = " . json_encode($phrase_details, true) . ";\n";
|
||||
} else {
|
||||
//send an empty array to the browser as a global scope json array object
|
||||
//echo "window.phrase_details = [];\n";
|
||||
}
|
||||
echo " }\n";
|
||||
if (if_group("superadmin")) {
|
||||
echo " else if (selected_index == 2) {\n"; //execute
|
||||
echo " action_to_input();\n";
|
||||
echo " }\n";
|
||||
|
||||
//recording files
|
||||
if ($recordings !== false) {
|
||||
//send recordings to the browser as a global scope json array object
|
||||
echo "window.phrase_recordings = " . json_encode($recordings, true) . ";\n";
|
||||
} else {
|
||||
//send an empty array
|
||||
echo "window.phrase_recordings = [];\n";
|
||||
}
|
||||
echo "}\n";
|
||||
|
||||
echo "function clear_action_options() {\n";
|
||||
echo " var len, groups, par;\n";
|
||||
echo " sel = document.getElementById('phrase_detail_data');\n";
|
||||
echo " groups = sel.getElementsByTagName('optgroup');\n";
|
||||
echo " len = groups.length;\n";
|
||||
echo " for (var i=len; i; i--) {\n";
|
||||
echo " sel.removeChild( groups[i-1] );\n";
|
||||
echo " }\n";
|
||||
echo " len = sel.options.length;\n";
|
||||
echo " for (var i=len; i; i--) {\n";
|
||||
echo " par = sel.options[i-1].parentNode;\n";
|
||||
echo " par.removeChild( sel.options[i-1] );\n";
|
||||
echo " }\n";
|
||||
echo "}\n";
|
||||
|
||||
if (if_group("superadmin")) {
|
||||
echo "function action_to_input() {\n";
|
||||
echo " obj = document.getElementById('phrase_detail_data');\n";
|
||||
echo " tb = document.createElement('INPUT');\n";
|
||||
echo " tb.type = 'text';\n";
|
||||
echo " tb.name = obj.name;\n";
|
||||
echo " tb.id = obj.id;\n";
|
||||
echo " tb.value = obj.options[obj.selectedIndex].value;\n";
|
||||
echo " tb.className = 'formfld';\n";
|
||||
echo " tb_width = (document.getElementById('phrase_detail_function').selectedIndex == 2) ? '300px' : '267px';\n";
|
||||
echo " tb.setAttribute('style', 'width: '+tb_width+'; min-width: '+tb_width+'; max-width: '+tb_width+';');\n";
|
||||
echo " obj.parentNode.insertBefore(tb, obj);\n";
|
||||
echo " obj.parentNode.removeChild(obj);\n";
|
||||
echo " if (document.getElementById('phrase_detail_function').selectedIndex != 2) {\n";
|
||||
echo " tb.setAttribute('style', 'width: 263px; min-width: 263px; max-width: 263px;');\n";
|
||||
echo " document.getElementById('phrase_detail_data_switch').style.display='';\n";
|
||||
echo " }\n";
|
||||
echo " else {\n";
|
||||
echo " tb.focus();\n";
|
||||
echo " }\n";
|
||||
echo "}\n";
|
||||
|
||||
echo "function action_to_select() {\n";
|
||||
echo " obj = document.getElementById('phrase_detail_data');\n";
|
||||
echo " sb = document.createElement('SELECT');\n";
|
||||
echo " sb.name = obj.name;\n";
|
||||
echo " sb.id = obj.id;\n";
|
||||
echo " sb.className = 'formfld';\n";
|
||||
echo " sb.setAttribute('style', 'width: 300px; min-width: 300px; max-width: 300px;');\n";
|
||||
echo " sb.setAttribute('onchange', 'action_to_input();');\n";
|
||||
echo " obj.parentNode.insertBefore(sb, obj);\n";
|
||||
echo " obj.parentNode.removeChild(obj);\n";
|
||||
echo " document.getElementById('phrase_detail_data_switch').style.display='none';\n";
|
||||
echo " clear_action_options();\n";
|
||||
echo "}\n";
|
||||
if (!empty($sound_files)) {
|
||||
//send sounds to the browser as a global scope json array object
|
||||
echo "window.phrase_sounds = " . json_encode($sound_files, true) . ";\n";
|
||||
}
|
||||
echo "</script>\n";
|
||||
|
||||
//javascript to control action form input using drag and drop
|
||||
echo "<script src='resources/javascript/phrase_edit.js'></script>\n";
|
||||
|
||||
//show the content
|
||||
echo "<form method='post' name='frm' id='frm'>\n";
|
||||
|
||||
|
|
@ -458,7 +451,7 @@
|
|||
if ($action == "update" && permission_exists('phrase_delete')) {
|
||||
echo button::create(['type'=>'button','label'=>$text['button-delete'],'icon'=>$_SESSION['theme']['button_icon_delete'],'name'=>'btn_delete','style'=>'margin-left: 15px;','onclick'=>"modal_open('modal-delete','btn_delete');"]);
|
||||
}
|
||||
echo button::create(['type'=>'submit','label'=>$text['button-save'],'icon'=>$_SESSION['theme']['button_icon_save'],'id'=>'btn_save','style'=>'margin-left: 15px;']);
|
||||
echo button::create(['type'=>'submit','onclick'=>'submit_phrase()','label'=>$text['button-save'],'icon'=>$_SESSION['theme']['button_icon_save'],'id'=>'btn_save','style'=>'margin-left: 15px;']);
|
||||
echo " </div>\n";
|
||||
echo " <div style='clear: both;'></div>\n";
|
||||
echo "</div>\n";
|
||||
|
|
@ -491,88 +484,62 @@
|
|||
echo " ".$text['description-language']."\n";
|
||||
echo "</td>\n";
|
||||
echo "</tr>\n";
|
||||
|
||||
//structure row
|
||||
echo "<tr>";
|
||||
echo "<td class='vncell' valign='top'>".$text['label-structure']."</td>";
|
||||
echo "<td class='vtable' align='left'>";
|
||||
echo " <table border='0' cellpadding='0' cellspacing='0'>\n";
|
||||
//style for dragging rows
|
||||
echo " <link rel=stylesheet href='resources/styles/phrase_edit.css' />";
|
||||
//structure table
|
||||
echo " <table border='0' cellpadding='0' cellspacing='0' id='phrases_table'>\n";
|
||||
//headings
|
||||
echo " <thead>\n";
|
||||
echo " <tr>\n";
|
||||
echo " <td class='vtable'><strong>".$text['label-function']."</strong></td>\n";
|
||||
echo " <td class='vtable'><strong>" . ($text['label-order'] ?? 'Order') . "</strong></td>\n";
|
||||
echo " <td class='vtable'><strong>".$text['label-action']."</strong></td>\n";
|
||||
echo " <td class='vtable' style='text-align: center;'><strong>".$text['label-order']."</strong></td>\n";
|
||||
if (!empty($phrase_details)) {
|
||||
echo " <td class='vtable edit_delete_checkbox_all' onmouseover=\"swap_display('delete_label_details', 'delete_toggle_details');\" onmouseout=\"swap_display('delete_label_details', 'delete_toggle_details');\">\n";
|
||||
echo " <span id='delete_label_details'>".$text['label-delete']."</span>\n";
|
||||
echo " <span id='delete_toggle_details'><input type='checkbox' id='checkbox_all_details' name='checkbox_all' onclick=\"edit_all_toggle('details');\"></span>\n";
|
||||
echo " </td>\n";
|
||||
}
|
||||
echo " <td class='vtable'><strong>".($text['label-recording'] ?? 'Recording')."</strong></td>\n";
|
||||
echo " </tr>\n";
|
||||
if (!empty($phrase_details)) {
|
||||
foreach($phrase_details as $x => $field) {
|
||||
//clean up output for display
|
||||
if ($field['phrase_detail_function'] == 'play-file' && substr($field['phrase_detail_data'], 0, 21) == '${lua streamfile.lua ') {
|
||||
$phrase_detail_function = $text['label-play'];
|
||||
$phrase_detail_data = str_replace('${lua streamfile.lua ', '', $field['phrase_detail_data']);
|
||||
$phrase_detail_data = str_replace('}', '', $phrase_detail_data);
|
||||
}
|
||||
else if ($field['phrase_detail_function'] == 'execute' && substr($field['phrase_detail_data'], 0, 6) == 'sleep(') {
|
||||
$phrase_detail_function = $text['label-pause'];
|
||||
$phrase_detail_data = str_replace('sleep(', '', $field['phrase_detail_data']);
|
||||
$phrase_detail_data = str_replace(')', '', $phrase_detail_data);
|
||||
$phrase_detail_data = ($phrase_detail_data / 1000).'s'; // seconds
|
||||
}
|
||||
else if ($field['phrase_detail_function'] == 'play-file') {
|
||||
$phrase_detail_function = $text['label-play'];
|
||||
$phrase_detail_data = str_replace($_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/', '', $field['phrase_detail_data']);
|
||||
}
|
||||
else {
|
||||
$phrase_detail_function = $field['phrase_detail_function'];
|
||||
$phrase_detail_data = $field['phrase_detail_data'];
|
||||
}
|
||||
echo "<tr>\n";
|
||||
echo " <td class='vtable'>".escape($phrase_detail_function)." </td>\n";
|
||||
echo " <td class='vtable'>".escape($phrase_detail_data)." </td>\n";
|
||||
echo " <td class='vtable' style='text-align: center;'>".$field['phrase_detail_order']." </td>\n";
|
||||
echo " <td class='vtable' style='text-align: center; padding-bottom: 3px;'>";
|
||||
if (is_uuid($field['phrase_detail_uuid'])) {
|
||||
echo " <input type='checkbox' name='phrase_details_delete[".$x."][checked]' value='true' class='chk_delete checkbox_details' onclick=\"edit_delete_action('details');\">\n";
|
||||
echo " <input type='hidden' name='phrase_details_delete[".$x."][uuid]' value='".escape($field['phrase_detail_uuid'])."' />\n";
|
||||
}
|
||||
echo " </td>\n";
|
||||
echo "</tr>\n";
|
||||
}
|
||||
}
|
||||
unset($phrase_details, $field);
|
||||
echo "<tr>\n";
|
||||
echo " </thead>\n";
|
||||
//draggable rows are initially empty
|
||||
echo "<tbody id='structure'>\n";
|
||||
echo "</tbody>";
|
||||
//show loading
|
||||
echo "<tbody id='loading'><tr><td> </td><td><center>Loading...</center></td><td> </td></tr></tbody>\n";
|
||||
//cloning row and buttons created outside of 'structure' table body
|
||||
echo "<tbody>";
|
||||
echo "<tr id='empty_row' style='display: none;'>\n";
|
||||
echo " <td style='border-bottom: none;' nowrap='nowrap'><center><span class='fa-solid fa-arrows-up-down'></span></center></td>";
|
||||
echo " <td class='vtable' style='border-bottom: none;' align='left' nowrap='nowrap'>\n";
|
||||
echo " <select name='phrase_detail_function' id='phrase_detail_function' class='formfld' onchange=\"load_action_options(this.selectedIndex);\">\n";
|
||||
echo " <select class='formfld' name='phrase_detail_function_empty' id='phrase_detail_function_empty' tag=''>\n";
|
||||
echo " <option value='play-file'>".$text['label-play']."</option>\n";
|
||||
echo " <option value='execute'>".$text['label-pause']."</option>\n";
|
||||
if (if_group("superadmin")) {
|
||||
echo " <option value='pause'>".$text['label-pause']."</option>\n";
|
||||
if (permission_exists('phrase_execute')) {
|
||||
echo " <option value='execute'>".$text['label-execute']."</option>\n";
|
||||
}
|
||||
echo " </select>\n";
|
||||
echo " </td>\n";
|
||||
echo " <td class='vtable' style='border-bottom: none;' align='left' nowrap='nowrap'>\n";
|
||||
echo " <select name='phrase_detail_data' id='phrase_detail_data' class='formfld' style='width: 300px; min-width: 300px; max-width: 300px;' ".((if_group("superadmin")) ? "onchange='action_to_input();'" : null)."></select>";
|
||||
if (if_group("superadmin")) {
|
||||
echo " <input id='phrase_detail_data_switch' type='button' class='btn' style='margin-left: 4px; display: none;' value='◁' onclick=\"action_to_select(); load_action_options(document.getElementById('phrase_detail_function').selectedIndex);\">\n";
|
||||
}
|
||||
echo " <script>load_action_options(0);</script>\n";
|
||||
echo " <select class='formfld' id='phrase_detail_data_empty' name='phrase_detail_data_empty' style='width: 300px; min-width: 300px; max-width: 300px;' tag=''></select>";
|
||||
// if (permission_exists('phrase_execute')) {
|
||||
// echo " <input id='phrase_detail_data_switch_empty' type='button' class='btn' style='margin-left: 4px; display: none;' value='◁' onclick=\"action_to_select(); load_action_options(document.getElementById('phrase_detail_function_empty').selectedIndex);\">\n";
|
||||
// }
|
||||
echo " <input type=hidden name='empty_uuid' value=''>";
|
||||
echo " <input class='formfld' type=text name='empty_phrase_detail_text' value='' style='width: 300px; min-width: 300px; max-width: 300px; display: none'>";
|
||||
echo " <span style='white-space: nowrap; display: flex; align-items: center; gap: 10px;'>";
|
||||
echo " <input class='form-control-range' type=range name='range' minrange='1' style='width: 250px; min-width: 250px; max-width: 250px; display: none'>";
|
||||
echo " <input type='text' class='formfld' name='sleep' style='width: 40px; min-width: 40px; max-width: 40px; display: none'>";
|
||||
echo " </span>";
|
||||
echo " </td>\n";
|
||||
echo " <td class='vtable' style='border-bottom: none;'>\n";
|
||||
echo " <select name='phrase_detail_order' class='formfld'>\n";
|
||||
for ($i = 0; $i <= 999; $i++) {
|
||||
$i_padded = str_pad($i, 3, '0', STR_PAD_LEFT);
|
||||
echo " <option value='".escape($i_padded)."'>".escape($i_padded)."</option>\n";
|
||||
}
|
||||
echo " </select>\n";
|
||||
echo " </td>\n";
|
||||
echo " <td>\n";
|
||||
echo button::create(['type'=>'submit','label'=>$text['button-add'],'icon'=>$_SESSION['theme']['button_icon_add']]);
|
||||
echo " </td>\n";
|
||||
|
||||
echo " </tr>\n";
|
||||
echo "</tr>\n";
|
||||
echo "<tr>";
|
||||
echo "<td> </td>";
|
||||
echo "<td class='vtable' style='align=center;' colspan='2'><center>";
|
||||
echo button::create(['type'=>'button','icon'=>$_SESSION['theme']['button_icon_add'], 'label' => $text['label-add'], 'onclick' => 'add_row()']);
|
||||
echo button::create(['type'=>'button','icon'=>'fa-solid fa-minus', 'label' => $text['label-delete'], 'onclick' => 'remove_row()']);
|
||||
echo "</center></td>";
|
||||
echo "<td> </td>";
|
||||
echo "</tr>";
|
||||
echo "</tbody>\n";
|
||||
echo "</table>\n";
|
||||
|
||||
echo " ".$text['description-structure']."\n";
|
||||
|
|
@ -650,5 +617,3 @@
|
|||
|
||||
//include the footer
|
||||
require_once "resources/footer.php";
|
||||
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,199 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* FusionPBX
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FusionPBX
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mark J Crane <markjcrane@fusionpbx.com>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008-2024
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mark J Crane <markjcrane@fusionpbx.com>
|
||||
* Tim Fry <tim@fusionpbx.com>
|
||||
*/
|
||||
|
||||
// require the class loader and global functions
|
||||
//require dirname(__DIR__, 2) . '/resources/classes/auto_loader.php'; new auto_loader();
|
||||
//require dirname(__DIR__, 2) . '/resources/functions.php';
|
||||
|
||||
require_once dirname(__DIR__, 2) . '/resources/require.php';
|
||||
|
||||
// Disable output buffering and compression
|
||||
ini_set('output_buffering', 'off');
|
||||
ini_set('zlib.output_compression', 'off');
|
||||
ini_set('implicit_flush', 1);
|
||||
ob_implicit_flush(1);
|
||||
|
||||
// Set headers to ensure immediate response
|
||||
header('Content-Type: text/plain');
|
||||
header('Cache-Control: no-cache');
|
||||
header('Content-Encoding: none');
|
||||
|
||||
function fetch_recordings(database $database): array {
|
||||
global $domain_uuid;
|
||||
// guard against corrupt data
|
||||
if (empty($domain_uuid) || !is_uuid($domain_uuid)) {
|
||||
throw new Exception('Domain is invalid');
|
||||
}
|
||||
// always return an array
|
||||
$return_value = [];
|
||||
$sql = "select recording_uuid, recording_name, recording_filename, domain_uuid from v_recordings ";
|
||||
$sql .= "where domain_uuid = :domain_uuid ";
|
||||
$sql .= "order by recording_name asc ";
|
||||
$parameters['domain_uuid'] = $domain_uuid;
|
||||
$recordings = $database->select($sql, $parameters, 'all');
|
||||
if (!empty($recordings)) {
|
||||
$return_value = $recordings;
|
||||
}
|
||||
return $return_value;
|
||||
}
|
||||
|
||||
function fetch_sound_files(settings $settings) {
|
||||
$return_value = [];
|
||||
//get the switch sound files
|
||||
$file = new file($settings);
|
||||
$sound_files = $file->sounds();
|
||||
|
||||
//try finding display_name in the switch sound files
|
||||
if (!empty($sound_files)) {
|
||||
$return_value = $sound_files;
|
||||
}
|
||||
return $return_value;
|
||||
}
|
||||
|
||||
function fetch_phrase_details(settings $settings, string $phrase_uuid): array {
|
||||
global $domain_uuid;
|
||||
// guard against corrupt data
|
||||
if (empty($domain_uuid) || !is_uuid($domain_uuid)) {
|
||||
throw new Exception('Domain is invalid');
|
||||
}
|
||||
if (empty($phrase_uuid) || !is_uuid($phrase_uuid)) {
|
||||
throw new Exception('Phrase UUID is invalid');
|
||||
}
|
||||
|
||||
$database = $settings->database();
|
||||
// set the return value to be an empty array
|
||||
$return_value = [];
|
||||
// get the phrase details
|
||||
if (!empty($phrase_uuid)) {
|
||||
$sql = "select * from v_phrase_details ";
|
||||
$sql .= "where domain_uuid = :domain_uuid ";
|
||||
$sql .= "and phrase_uuid = :phrase_uuid ";
|
||||
$sql .= "order by phrase_detail_order asc ";
|
||||
$parameters['domain_uuid'] = $domain_uuid;
|
||||
$parameters['phrase_uuid'] = $phrase_uuid;
|
||||
$phrase_details = $database->select($sql, $parameters, 'all');
|
||||
}
|
||||
//existing details
|
||||
if (!empty($phrase_details)) {
|
||||
$recordings = fetch_recordings($database);
|
||||
$sound_files = fetch_sound_files($settings);
|
||||
//update the array to include the recording name for display in select box
|
||||
foreach ($phrase_details as &$row) {
|
||||
$row['display_name'] = '';
|
||||
$file = basename($row['phrase_detail_data']);
|
||||
//get the display_name from recording name based on the file matched
|
||||
foreach ($recordings as $key => $recordings_row) {
|
||||
//match on filename first and then domain_uuid
|
||||
if ($recordings_row['recording_filename'] === $file && $recordings_row['domain_uuid'] === $row['domain_uuid']) {
|
||||
$row['display_name'] = $recordings[$key]['recording_name'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
//check if display_name was not found in the recording names
|
||||
if (strlen($row['display_name']) === 0) {
|
||||
//try finding display_name in the switch sound files
|
||||
if (!empty($sound_files)) {
|
||||
//use optimized php function with strict comparison
|
||||
$i = array_search($row['phrase_detail_data'], $sound_files, true);
|
||||
//if found in the switch sound files
|
||||
if ($i !== false) {
|
||||
//set the display_name to the switch sound file name
|
||||
$row['display_name'] = $sound_files[$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$return_value = $phrase_details;
|
||||
}
|
||||
return $return_value;
|
||||
}
|
||||
|
||||
function fetch_domain_uuid(database $database): string {
|
||||
$domain = $_SERVER['HTTP_HOST'];
|
||||
$domain_uuid = '';
|
||||
$sql = 'select domain_uuid from v_domains where domain_name = :domain';
|
||||
$parameters = [];
|
||||
$parameters['domain'] = $domain;
|
||||
$result = $database->select($sql, $parameters, 'column');
|
||||
if (!empty($result)) {
|
||||
$domain_uuid = $result;
|
||||
}
|
||||
return $domain_uuid;
|
||||
}
|
||||
|
||||
function send_message(string $json_data) {
|
||||
echo $json_data . "\n";
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
|
||||
$config = config::load();
|
||||
$database = database::new(['config' => $config]);
|
||||
$domain_uuid = fetch_domain_uuid($database);
|
||||
$settings = new settings(['database' => $database, 'domain_uuid' => $domain_uuid]);
|
||||
|
||||
// Set default response
|
||||
$response = ['code' => 200, 'message' => ''];
|
||||
|
||||
// Check if the request method is POST
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$message = '';
|
||||
// Get the raw POST data
|
||||
$input = file_get_contents('php://input');
|
||||
|
||||
// Parse JSON data
|
||||
$data = json_decode($input, true); // Decode JSON as associative array
|
||||
|
||||
if (isset($data['request'])) {
|
||||
try {
|
||||
//check the data source requested
|
||||
switch ($data['request']) {
|
||||
case 'sound_files':
|
||||
$message = fetch_sound_files($settings);
|
||||
break;
|
||||
case 'recordings':
|
||||
$message = fetch_recordings($database);
|
||||
break;
|
||||
case 'phrase_details':
|
||||
$phrase_uuid = $data['data'];
|
||||
$message = fetch_phrase_details($settings, $phrase_uuid);
|
||||
break;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$response['code'] = 500;
|
||||
$message = $e->getMessage();
|
||||
}
|
||||
}
|
||||
//save the message
|
||||
$response['message'] = $message;
|
||||
//send the response
|
||||
send_message(json_encode($response));
|
||||
exit();
|
||||
}
|
||||
|
||||
exit();
|
||||
|
|
@ -75,7 +75,7 @@
|
|||
$token = new token;
|
||||
if (!$token->validate($_SERVER['PHP_SELF'])) {
|
||||
message::add($text['message-invalid_token'],'negative');
|
||||
header('Location: '.$this->list_page);
|
||||
header('Location: '.$this->list_page);$is_uuid
|
||||
exit;
|
||||
}
|
||||
|
||||
|
|
@ -429,4 +429,70 @@
|
|||
}
|
||||
} //method
|
||||
|
||||
} //class
|
||||
/**
|
||||
* Returns a path and filename of the recording_uuid provided from the database.
|
||||
* If the recording is a base64 encoded file the file and path may be empty.
|
||||
* @param database $database Database object
|
||||
* @param string $recording_uuid Recording UUID
|
||||
* @return string recording path and filename or an empty string when not found or base64
|
||||
*/
|
||||
public static function get_recording_filename(database $database, string $recording_uuid): string {
|
||||
$sql = "select recording_filename from v_recordings";
|
||||
$sql .= " where recording_uuid = :recording_uuid";
|
||||
$parameters = [];
|
||||
$parameters['recording_uuid'] = $recording_uuid;
|
||||
$result = $database->select($sql, $parameters, 'column');
|
||||
if ($result !== false) {
|
||||
return $result;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an associative array of recordings with the uuid as key and recording filename as value.
|
||||
* When the recording is a base64 encoded recording, the filename returned is the filename only with no path.
|
||||
* @param settings $settings Settings object
|
||||
* @param int $limit (Optional) Limit the number of results returned
|
||||
* @return array
|
||||
*/
|
||||
public static function get_all_domain_recordings(settings $settings, int $limit = 0): array {
|
||||
//set defaults
|
||||
$recordings = [];
|
||||
$parameters = [];
|
||||
//get the database object from the settings object
|
||||
$database = $settings->database();
|
||||
//get the domain name using the domain_uuid in the database object
|
||||
$domain_uuid = $settings->domain_uuid();
|
||||
$domain_name = $database->select("SELECT domain_name from v_domains where domain_uuid = :domain_uuid", ['domain_uuid' => $domain_uuid], 'column');
|
||||
//get the recording directory
|
||||
$recordings_dir = $settings->get('switch', 'recordings', '/var/lib/freeswitch/recordings') . DIRECTORY_SEPARATOR . $domain_name;
|
||||
//build initial sql that ignores the domain_uuid
|
||||
$sql = "SELECT recording_uuid, recording_filename, recording_base64 IS NOT NULL AS has_base64_recording FROM v_recordings";
|
||||
//add domain_uuid to sql when available
|
||||
if (!empty($domain_name) && is_uuid($domain_uuid)) {
|
||||
$sql .= " where domain_uuid = :domain_uuid";
|
||||
$parameters['domain_uuid'] = $domain_uuid;
|
||||
}
|
||||
//add limit to sql if needed
|
||||
if (!empty($limit)) {
|
||||
$sql .= " limit $limit";
|
||||
}
|
||||
//get the result
|
||||
$rows = $database->select($sql, $parameters);
|
||||
//iterate over all rows returned to remap them to uuid => filename
|
||||
if (!empty($rows)) {
|
||||
//set the path and filename for each of the uuids
|
||||
foreach($rows as $row) {
|
||||
if ($row['has_base64_recording']) {
|
||||
$recordings[$row['recording_uuid']] = '${lua streamfile.lua ' . basename($row['recording_filename']) .'}';
|
||||
} else {
|
||||
$recordings[$row['recording_uuid']] = $recordings_dir . DIRECTORY_SEPARATOR . $row['recording_filename'];
|
||||
}
|
||||
}
|
||||
}
|
||||
//return recordings or empty array
|
||||
return $recordings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,377 @@
|
|||
// use an async function so page works without delays
|
||||
document.addEventListener("DOMContentLoaded", async function () {
|
||||
// Initialize the select options
|
||||
const select = document.getElementById('phrase_detail_data_empty');
|
||||
const grp_rec = document.createElement('optgroup');
|
||||
const grp_snd = document.createElement('optgroup');
|
||||
|
||||
// Add a blank entry
|
||||
select.appendChild(new Option('', ''));
|
||||
|
||||
// Add recordings
|
||||
grp_rec.label = window.phrase_label_recordings;
|
||||
try {
|
||||
const phrase_recordings = await fetch_data({request: 'recordings', data: ''});
|
||||
for (let i = 0; i < phrase_recordings.length; i++) {
|
||||
grp_rec.appendChild(new Option(phrase_recordings[i].recording_name, phrase_recordings[i].recording_uuid));
|
||||
}
|
||||
select.appendChild(grp_rec);
|
||||
} catch (error) {
|
||||
console.error("Error fetching recordings:", error);
|
||||
}
|
||||
|
||||
// Add sounds
|
||||
grp_snd.label = window.phrase_label_sounds;
|
||||
try {
|
||||
const phrase_sounds = await fetch_data({request: 'sound_files', data: ''});
|
||||
for (let i = 0; i < phrase_sounds.length; i++) {
|
||||
grp_snd.appendChild(new Option(phrase_sounds[i], phrase_sounds[i]));
|
||||
}
|
||||
select.appendChild(grp_snd);
|
||||
} catch (error) {
|
||||
console.error("Error fetching recordings:", error);
|
||||
}
|
||||
|
||||
// add the existing data
|
||||
add_existing();
|
||||
|
||||
// add empty row
|
||||
add_row();
|
||||
|
||||
// Initialize draggable rows
|
||||
add_draggable_rows();
|
||||
});
|
||||
|
||||
function remove_loading() {
|
||||
//remove loading
|
||||
const loading = document.getElementById('loading');
|
||||
if (loading) {
|
||||
loading.remove();
|
||||
}
|
||||
}
|
||||
|
||||
async function fetch_data(command) {
|
||||
try {
|
||||
const response = await fetch('resources/phrase_responder.php', {
|
||||
method: 'POST', // or 'GET' depending on your requirement
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(command) // If sending data with POST
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
return data.message;
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Inserts all existing records before the empty one
|
||||
//
|
||||
async function add_existing() {
|
||||
//get the body structure
|
||||
const tbody = document.getElementById('structure');
|
||||
//get the phrase id
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const phrase_uuid = urlParams.get('id');
|
||||
//fetch the phrase details from the database
|
||||
const phrase_details = await fetch_data({request: 'phrase_details', data: phrase_uuid});
|
||||
//display the phrase details
|
||||
for (let index=0; index < phrase_details.length; index++) {
|
||||
//add an empty row
|
||||
add_row();
|
||||
//get the action select box
|
||||
const select_action = document.getElementById('phrase_detail_function[' + index + ']');
|
||||
//set the chosen option
|
||||
select_by_value(select_action, phrase_details[index].phrase_detail_function);
|
||||
//get the data select box
|
||||
const select_data = document.getElementById('phrase_detail_data[' + index + ']');
|
||||
//set the chosen option
|
||||
select_by_text(select_data, phrase_details[index]['display_name']);
|
||||
const uuid_field = document.getElementById('phrase_detail_uuid[' +index+']');
|
||||
uuid_field.value = phrase_details[index]['phrase_detail_uuid'];
|
||||
//set the slider value
|
||||
const slider = document.getElementById('slider['+index+']');
|
||||
const sleep = document.getElementById('sleep['+index+']');
|
||||
const phrase_detail_text = document.getElementById('phrase_detail_text['+index+']');
|
||||
//update the sleep data
|
||||
if (phrase_details[index].phrase_detail_function === 'pause') {
|
||||
sleep.value = phrase_details[index].phrase_detail_data;
|
||||
slider.value = phrase_details[index].phrase_detail_data;
|
||||
}
|
||||
//update the execute text
|
||||
if (phrase_details[index].phrase_detail_function === 'execute') {
|
||||
phrase_detail_text.value = phrase_details[index].phrase_detail_data;
|
||||
}
|
||||
// Manually trigger the change event to select the proper display
|
||||
if (phrase_details[index].phrase_detail_function !== 'play-file') {
|
||||
const changeEvent = new Event('change', { bubbles: true });
|
||||
select_action.dispatchEvent(changeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
remove_loading();
|
||||
}
|
||||
|
||||
//
|
||||
// Set the selected index on a dropdown box based on the value (key)
|
||||
//
|
||||
function select_by_value(selectElement, valueToFind) {
|
||||
// Loop through the options of the select element
|
||||
for (let i = 0; i < selectElement.options.length; i++) {
|
||||
if (selectElement.options[i].value === valueToFind) {
|
||||
selectElement.selectedIndex = i; // Set the selected index
|
||||
return; // Exit the loop once found
|
||||
}
|
||||
}
|
||||
console.warn('Value not found in select options');
|
||||
}
|
||||
|
||||
//
|
||||
// Set the selected index on a dropdown box based on the text
|
||||
//
|
||||
function select_by_text(selectElement, textToFind) {
|
||||
for (let i = 0; i < selectElement.options.length; i++) {
|
||||
if (selectElement.options[i].text === textToFind) {
|
||||
selectElement.selectedIndex = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
console.warn('Text not found in select options');
|
||||
}
|
||||
|
||||
//
|
||||
// Add draggable functionality to rows
|
||||
//
|
||||
function add_draggable_rows() {
|
||||
const tableBody = document.getElementById('structure');
|
||||
let draggedRow = null;
|
||||
|
||||
// Add drag listeners only to the leftmost cell on the row
|
||||
tableBody.querySelectorAll('tr').forEach(row => {
|
||||
const dragHandleCell = row.cells[0]; // Assuming the first cell is the one left to the dropdown
|
||||
|
||||
if (!dragHandleCell) return;
|
||||
|
||||
// Enable dragging from this cell
|
||||
dragHandleCell.setAttribute('draggable', 'true');
|
||||
|
||||
dragHandleCell.addEventListener('dragstart', (e) => {
|
||||
draggedRow = row;
|
||||
row.classList.add('dragging');
|
||||
});
|
||||
|
||||
dragHandleCell.addEventListener('dragend', () => {
|
||||
if (draggedRow) {
|
||||
draggedRow.classList.remove('dragging');
|
||||
draggedRow = null;
|
||||
}
|
||||
});
|
||||
|
||||
dragHandleCell.addEventListener('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
const targetRow = e.target.closest('tr');
|
||||
if (targetRow && targetRow !== draggedRow) {
|
||||
const bounding = targetRow.getBoundingClientRect();
|
||||
const offset = e.clientY - bounding.top;
|
||||
if (offset > bounding.height / 2) {
|
||||
targetRow.parentNode.insertBefore(draggedRow, targetRow.nextSibling);
|
||||
} else {
|
||||
targetRow.parentNode.insertBefore(draggedRow, targetRow);
|
||||
}
|
||||
}
|
||||
});
|
||||
dragHandleCell.addEventListener('dragend', () => {
|
||||
if (draggedRow) {
|
||||
draggedRow.classList.remove('dragging');
|
||||
draggedRow = null;
|
||||
update_order();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Function to update the 'name' attribute based on row numbers
|
||||
//
|
||||
function update_order() {
|
||||
const tableBody = document.getElementById('structure');
|
||||
const rows = tableBody.querySelectorAll('tr');
|
||||
|
||||
//iterate over all rows to renumber them
|
||||
rows.forEach((row, index) => {
|
||||
//set 'name' attribute and id
|
||||
row.setAttribute('name', 'row_' + index);
|
||||
row.id = 'row_' + index;
|
||||
|
||||
//get the select boxes
|
||||
const select_list = row.querySelectorAll('td select'); //action and recording select dropdown boxes
|
||||
|
||||
//get the input boxes
|
||||
const input_boxes = row.querySelectorAll('td input');
|
||||
//uuid
|
||||
const phrase_detail_uuid = input_boxes[0];
|
||||
phrase_detail_uuid.removeAttribute('id');
|
||||
phrase_detail_uuid.id = 'phrase_detail_uuid[' + index + ']';
|
||||
phrase_detail_uuid.name = phrase_detail_uuid.id;
|
||||
//execute action
|
||||
const phrase_detail_text = input_boxes[1];
|
||||
temp_value = phrase_detail_text.value;
|
||||
phrase_detail_text.removeAttribute('id');
|
||||
phrase_detail_text.id = 'phrase_detail_text[' + index + ']';
|
||||
phrase_detail_text.name = phrase_detail_text.id;
|
||||
phrase_detail_text.value = temp_value;
|
||||
//slider
|
||||
const slider = input_boxes[2];
|
||||
slider.removeAttribute('id');
|
||||
slider.id = 'slider[' + index + ']';
|
||||
slider.name = slider.id;
|
||||
//sleep value
|
||||
const sleep = input_boxes[3];
|
||||
temp_value = sleep.value;
|
||||
sleep.removeAttribute('id');
|
||||
sleep.id = 'sleep[' + index + ']';
|
||||
sleep.name = sleep.id;
|
||||
sleep.value = temp_value;
|
||||
|
||||
//play, pause, execute select box
|
||||
const select_function = select_list[0];
|
||||
select_function.removeAttribute('id');
|
||||
select_function.id = 'phrase_detail_function[' + index + ']'
|
||||
select_function.name = select_function.id;
|
||||
|
||||
//recording select box
|
||||
const select_data = select_list[1];
|
||||
select_data.removeAttribute('id');
|
||||
select_data.id = 'phrase_detail_data[' + index + ']'
|
||||
select_data.name = select_data.id;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Ensure the order is updated when submitting the form
|
||||
//
|
||||
function submit_phrase() {
|
||||
//ensure order is updated before submitting form
|
||||
update_order();
|
||||
//submit form
|
||||
const form = document.getElementById('frm').submit();
|
||||
}
|
||||
|
||||
//
|
||||
// Add a new row to the table
|
||||
//
|
||||
function add_row() {
|
||||
const tbody = document.getElementById('structure');
|
||||
|
||||
// current index is the count subtract the hidden row
|
||||
const index = tbody.childElementCount;
|
||||
|
||||
const newRow = document.getElementById('empty_row').cloneNode(true);
|
||||
//reset id
|
||||
newRow.removeAttribute('id');
|
||||
newRow.id = 'row_' + index;
|
||||
|
||||
//un-hide row
|
||||
newRow.style.display = '';
|
||||
|
||||
//reset 'name' attribute
|
||||
newRow.setAttribute('name', 'recording_' + index);
|
||||
|
||||
//get the select boxes
|
||||
const select_list = newRow.querySelectorAll('td select'); //action and recording select dropdown boxes
|
||||
//play, pause, execute select box
|
||||
const select_action = select_list[0];
|
||||
select_action.removeAttribute('id');
|
||||
select_action.id = 'phrase_detail_function[' + index + ']';
|
||||
select_action.name = 'phrase_detail_function[' + index + ']';
|
||||
//recording select box
|
||||
const select_data = select_list[1];
|
||||
select_data.removeAttribute('id');
|
||||
select_data.id = 'phrase_detail_data[' + index + ']';
|
||||
select_data.name = 'phrase_detail_data[' + index + ']';
|
||||
//uuid field
|
||||
const uuid_field = newRow.querySelector('input[name="empty_uuid"]');
|
||||
uuid_field.removeAttribute('id');
|
||||
uuid_field.id = 'phrase_detail_uuid[' + index +']';
|
||||
uuid_field.name = 'phrase_detail_uuid[' + index +']';
|
||||
const phrase_detail_text = newRow.querySelector('input[name="empty_phrase_detail_text"]');
|
||||
phrase_detail_text.removeAttribute('id');
|
||||
phrase_detail_text.id = 'phrase_detail_text[' + index + ']';
|
||||
phrase_detail_text.name = 'phrase_detail_text[' + index + ']';
|
||||
//slider
|
||||
const slider = newRow.querySelector('input[name="range"]');
|
||||
slider.removeAttribute('id');
|
||||
slider.id = 'slider[' + index + ']';
|
||||
slider.name = 'slider[' + index + ']';
|
||||
//sleep
|
||||
const sleep = newRow.querySelector('input[name="sleep"]');
|
||||
sleep.removeAttribute('id');
|
||||
sleep.id = 'sleep[' + index + ']';
|
||||
sleep.name = 'sleep[' + index + ']';
|
||||
sleep.value = slider.value;
|
||||
|
||||
let changing = false;
|
||||
|
||||
slider.addEventListener('mousemove', function () {
|
||||
changing = true;
|
||||
sleep.value = slider.value;
|
||||
changing = false;
|
||||
});
|
||||
|
||||
sleep.addEventListener('keyup', function() {
|
||||
if (!changing) {
|
||||
if (sleep.value.length > 0)
|
||||
slider.value = sleep.value;
|
||||
else {
|
||||
slider.value = 0;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
//add switchable select box to text input box
|
||||
select_action.addEventListener('change', function () {
|
||||
if (select_action.value === 'execute') {
|
||||
//show text box
|
||||
select_data.style.display = 'none';
|
||||
slider.style.display = 'none';
|
||||
sleep.style.display = 'none';
|
||||
phrase_detail_text.style.display = 'block';
|
||||
} else if (select_action.value === 'pause') {
|
||||
//show the range bar
|
||||
select_data.style.display = 'none';
|
||||
phrase_detail_text.style.display = 'none';
|
||||
slider.style.display = 'block';
|
||||
sleep.style.display = 'block';
|
||||
} else {
|
||||
//show drop down
|
||||
phrase_detail_text.style.display = 'none';
|
||||
slider.style.display = 'none';
|
||||
sleep.style.display = 'none';
|
||||
select_data.style.display = 'block';
|
||||
}
|
||||
});
|
||||
|
||||
//add the row to the table body
|
||||
tbody.appendChild(newRow);
|
||||
|
||||
//reinitialize draggable functionality on the row
|
||||
add_draggable_rows();
|
||||
return index;
|
||||
}
|
||||
|
||||
//
|
||||
// Remove the last row in the table
|
||||
//
|
||||
function remove_row() {
|
||||
const tbody = document.getElementById('structure');
|
||||
if (tbody && tbody.rows.length > 1) {
|
||||
tbody.lastElementChild.remove();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* FusionPBX
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FusionPBX
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mark J Crane <markjcrane@fusionpbx.com>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008-2024
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mark J Crane <markjcrane@fusionpbx.com>
|
||||
* Tim Fry <tim@fusionpbx.com>
|
||||
*/
|
||||
|
||||
async function fetchData() {
|
||||
try {
|
||||
const response = await fetch('phrase_responder.php', {
|
||||
method: 'POST', // or 'GET' depending on your requirement
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ request: 'phrase_details', phrase_uuid: '86141ace-b218-4f07-b412-fe02d4fdde17' }) // If sending data with POST
|
||||
});
|
||||
|
||||
const data = await response.text();
|
||||
const json = JSON.parse(data);
|
||||
|
||||
const body = document.body;
|
||||
const input = document.createElement('input');
|
||||
input.type = 'text';
|
||||
input.value = json.message;
|
||||
body.appendChild(input);
|
||||
|
||||
console.log(data);
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
fetchData();
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* FusionPBX
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FusionPBX
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mark J Crane <markjcrane@fusionpbx.com>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008-2024
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mark J Crane <markjcrane@fusionpbx.com>
|
||||
* Tim Fry <tim@fusionpbx.com>
|
||||
*/
|
||||
|
||||
require_once dirname(__DIR__, 3) . '/resources/require.php';
|
||||
|
||||
//check permissions
|
||||
if (permission_exists('phrase_add') || permission_exists('phrase_edit')) {
|
||||
//access granted
|
||||
}
|
||||
else {
|
||||
echo "access denied";
|
||||
exit;
|
||||
}
|
||||
|
||||
// Disable output buffering and compression
|
||||
ini_set('output_buffering', 'off');
|
||||
ini_set('zlib.output_compression', 'off');
|
||||
ini_set('implicit_flush', 1);
|
||||
ob_implicit_flush(1);
|
||||
|
||||
// Set headers to ensure immediate response
|
||||
header('Content-Type: text/plain');
|
||||
header('Cache-Control: no-cache');
|
||||
header('Content-Encoding: none');
|
||||
|
||||
function fetch_recordings(database $database): array {
|
||||
global $domain_uuid;
|
||||
// guard against corrupt data
|
||||
if (empty($domain_uuid) || !is_uuid($domain_uuid)) {
|
||||
throw new Exception('Domain is invalid');
|
||||
}
|
||||
// always return an array
|
||||
$return_value = [];
|
||||
$sql = "select recording_uuid, recording_name, recording_filename, domain_uuid from v_recordings ";
|
||||
$sql .= "where domain_uuid = :domain_uuid ";
|
||||
$sql .= "order by recording_name asc ";
|
||||
$parameters['domain_uuid'] = $domain_uuid;
|
||||
$recordings = $database->select($sql, $parameters, 'all');
|
||||
if (!empty($recordings)) {
|
||||
$return_value = $recordings;
|
||||
}
|
||||
return $return_value;
|
||||
}
|
||||
|
||||
function fetch_sound_files(settings $settings) {
|
||||
$return_value = [];
|
||||
//get the switch sound files
|
||||
$file = new file($settings);
|
||||
$sound_files = $file->sounds();
|
||||
|
||||
//try finding display_name in the switch sound files
|
||||
if (!empty($sound_files)) {
|
||||
$return_value = $sound_files;
|
||||
}
|
||||
return $return_value;
|
||||
}
|
||||
|
||||
function fetch_phrase_details(settings $settings, string $phrase_uuid): array {
|
||||
global $domain_uuid;
|
||||
// guard against corrupt data
|
||||
if (empty($domain_uuid) || !is_uuid($domain_uuid)) {
|
||||
throw new Exception('Domain is invalid');
|
||||
}
|
||||
if (empty($phrase_uuid) || !is_uuid($phrase_uuid)) {
|
||||
throw new Exception('Phrase UUID is invalid');
|
||||
}
|
||||
|
||||
$database = $settings->database();
|
||||
// set the return value to be an empty array
|
||||
$return_value = [];
|
||||
// get the phrase details
|
||||
if (!empty($phrase_uuid)) {
|
||||
$sql = "select * from v_phrase_details ";
|
||||
$sql .= "where domain_uuid = :domain_uuid ";
|
||||
$sql .= "and phrase_uuid = :phrase_uuid ";
|
||||
$sql .= "order by phrase_detail_order asc ";
|
||||
$parameters['domain_uuid'] = $domain_uuid;
|
||||
$parameters['phrase_uuid'] = $phrase_uuid;
|
||||
$phrase_details = $database->select($sql, $parameters, 'all');
|
||||
}
|
||||
//existing details
|
||||
if (!empty($phrase_details)) {
|
||||
$recordings = fetch_recordings($database);
|
||||
$sound_files = fetch_sound_files($settings);
|
||||
//update the array to include the recording name for display in select box
|
||||
foreach ($phrase_details as &$row) {
|
||||
$row['display_name'] = '';
|
||||
$file = basename($row['phrase_detail_data']);
|
||||
//get the display_name from recording name based on the file matched
|
||||
foreach ($recordings as $key => $recordings_row) {
|
||||
//match on filename first and then domain_uuid
|
||||
if ($recordings_row['recording_filename'] === $file && $recordings_row['domain_uuid'] === $row['domain_uuid']) {
|
||||
$row['display_name'] = $recordings[$key]['recording_name'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
//check if display_name was not found in the recording names
|
||||
if (strlen($row['display_name']) === 0) {
|
||||
//try finding display_name in the switch sound files
|
||||
if (!empty($sound_files)) {
|
||||
//use optimized php function with strict comparison
|
||||
$i = array_search($row['phrase_detail_data'], $sound_files, true);
|
||||
//if found in the switch sound files
|
||||
if ($i !== false) {
|
||||
//set the display_name to the switch sound file name
|
||||
$row['display_name'] = $sound_files[$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$return_value = $phrase_details;
|
||||
}
|
||||
return $return_value;
|
||||
}
|
||||
|
||||
function fetch_domain_uuid(database $database): string {
|
||||
$domain = $_SERVER['HTTP_HOST'];
|
||||
$domain_uuid = '';
|
||||
$sql = 'select domain_uuid from v_domains where domain_name = :domain';
|
||||
$parameters = [];
|
||||
$parameters['domain'] = $domain;
|
||||
$result = $database->select($sql, $parameters, 'column');
|
||||
if (!empty($result)) {
|
||||
$domain_uuid = $result;
|
||||
}
|
||||
return $domain_uuid;
|
||||
}
|
||||
|
||||
function send_message(string $json_data) {
|
||||
echo $json_data . "\n";
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
|
||||
$config = config::load();
|
||||
$database = database::new(['config' => $config]);
|
||||
$domain_uuid = fetch_domain_uuid($database);
|
||||
$settings = new settings(['database' => $database, 'domain_uuid' => $domain_uuid]);
|
||||
|
||||
// Set default response
|
||||
$response = ['code' => 200, 'message' => ''];
|
||||
|
||||
// Check if the request method is POST
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$message = '';
|
||||
// Get the raw POST data
|
||||
$input = file_get_contents('php://input');
|
||||
|
||||
// Parse JSON data
|
||||
$data = json_decode($input, true); // Decode JSON as associative array
|
||||
|
||||
if (isset($data['request'])) {
|
||||
try {
|
||||
//check the data source requested
|
||||
switch ($data['request']) {
|
||||
case 'sound_files':
|
||||
$message = fetch_sound_files($settings);
|
||||
break;
|
||||
case 'recordings':
|
||||
$message = fetch_recordings($database);
|
||||
break;
|
||||
case 'phrase_details':
|
||||
$phrase_uuid = $data['data'];
|
||||
$message = fetch_phrase_details($settings, $phrase_uuid);
|
||||
break;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$response['code'] = 500;
|
||||
$message = $e->getMessage();
|
||||
}
|
||||
}
|
||||
//save the message
|
||||
$response['message'] = $message;
|
||||
//send the response
|
||||
send_message(json_encode($response));
|
||||
exit();
|
||||
}
|
||||
|
||||
exit();
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
.draggable-row {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.dragging {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.target-background {
|
||||
background-color: #ffc107;
|
||||
}
|
||||
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
/**
|
||||
* cache class provides an abstracted cache
|
||||
*
|
||||
* @method string glob
|
||||
*/
|
||||
class file {
|
||||
|
||||
|
|
@ -12,12 +10,17 @@ class file {
|
|||
*/
|
||||
public $recursive;
|
||||
public $files;
|
||||
private $settings;
|
||||
|
||||
/**
|
||||
* Called when the object is created
|
||||
* @param settings $settings Settings object
|
||||
*/
|
||||
public function __construct() {
|
||||
//place holder
|
||||
public function __construct($settings = null) {
|
||||
if ($settings === null) {
|
||||
$settings = new settings();
|
||||
}
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -66,8 +69,8 @@ class file {
|
|||
if (!isset($voice)) { $voice = 'callie'; }
|
||||
|
||||
//set the variables
|
||||
if (!empty($_SESSION['switch']['sounds']['dir']) && file_exists($_SESSION['switch']['sounds']['dir'])) {
|
||||
$dir = $_SESSION['switch']['sounds']['dir'].'/'.$language.'/'.$dialect.'/'.$voice;
|
||||
if (!empty($this->settings->get('switch', 'sounds')) && file_exists($this->settings->get('switch', 'sounds'))) {
|
||||
$dir = $this->settings->get('switch', 'sounds').'/'.$language.'/'.$dialect.'/'.$voice;
|
||||
$rate = '8000';
|
||||
$files = $this->glob($dir.'/*/'.$rate, true);
|
||||
}
|
||||
|
|
@ -93,5 +96,3 @@ class file {
|
|||
$files = $file->sounds();
|
||||
print_r($files);
|
||||
*/
|
||||
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -110,6 +110,22 @@ class settings implements clear_cache {
|
|||
return $this->database;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the domain_uuid that was used to load the settings
|
||||
* @return string domain_uuid or an empty string
|
||||
*/
|
||||
public function domain_uuid(): string {
|
||||
return $this->domain_uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user_uuid that was used to load the settings
|
||||
* @return string user_uuid or an empty string
|
||||
*/
|
||||
public function user_uuid(): string {
|
||||
return $this->user_uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the settings from the database
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue