Fix Enable/Disable buttons in Phone Types - now contextual on page Reformulate sub views (enabled or disabled not all) Change page Layout and formatting Fix response feedback Tidy up html Fix issue with running validate
453 lines
21 KiB
PHP
453 lines
21 KiB
PHP
<?php
|
|
|
|
/**
|
|
*
|
|
* Core Comsnd Interface
|
|
*
|
|
*
|
|
*/
|
|
|
|
namespace FreePBX\modules\Sccp_manager;
|
|
|
|
class dbinterface
|
|
{
|
|
|
|
private $val_null = 'NONE'; /// REPLACE to null Field
|
|
|
|
public function __construct($parent_class = null)
|
|
{
|
|
$this->paren_class = $parent_class;
|
|
$this->db = \FreePBX::Database();
|
|
}
|
|
|
|
public function info()
|
|
{
|
|
$Ver = '16.0.0.1'; // This should be updated
|
|
return array('Version' => $Ver,
|
|
'about' => 'Data access interface ver: ' . $Ver);
|
|
}
|
|
|
|
/*
|
|
* Core Access Function
|
|
*/
|
|
public function get_db_SccpTableByID($dataid, $data = array(), $indexField = '')
|
|
{
|
|
$result = array();
|
|
$raw = $this->getSccpDeviceTableData($dataid, $data);
|
|
if (empty($raw) || empty($indexField)) {
|
|
return $raw;
|
|
}
|
|
foreach ($raw as $value) {
|
|
$id = $value[$indexField];
|
|
$result[$id] = $value;
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
public function getSccpDeviceTableData(string $dataid, $data = array())
|
|
{
|
|
// $stmt is a single row fetch, $stmts is a fetchAll while stmtU is fetchAll UNIQUE
|
|
$stmt = '';
|
|
$stmts = '';
|
|
$stmtU = '';
|
|
|
|
switch ($dataid) {
|
|
case 'extGrid':
|
|
// only called by getExtensionGrid from hardware.extension.php view
|
|
$stmts = $this->db->prepare("SELECT sccpline.name, sccpline.label, sccpbuttonconfig.ref AS mac, '-|-' AS line_status
|
|
FROM sccpline LEFT JOIN sccpbuttonconfig
|
|
ON sccpline.name = TRIM(TRAILING '!silent' FROM sccpbuttonconfig.name) ORDER BY sccpline.name");
|
|
break;
|
|
case 'SccpExtension':
|
|
if (empty($data['name'])) {
|
|
$stmtU = $this->db->prepare('SELECT name, sccpline.* FROM sccpline ORDER BY name');
|
|
} else {
|
|
$stmts = $this->db->prepare('SELECT * FROM sccpline WHERE name = :name');
|
|
$stmts->bindParam(':name', $data['name'],\PDO::PARAM_STR);
|
|
}
|
|
break;
|
|
case 'sccpHints':
|
|
$stmtU = $this->db->prepare('SELECT name, name, label FROM sccpline ORDER BY name');
|
|
break;
|
|
case 'phoneGrid':
|
|
switch ($data['type']) {
|
|
case "cisco-sip":
|
|
$stmts = $this->db->prepare("SELECT name, type, button, addon, description, 'not connected' AS status, '- -' AS address, 'N' AS new_hw
|
|
FROM sccpdeviceconfig WHERE RIGHT(type,4) = '-sip' ORDER BY name");
|
|
break;
|
|
case "sccp": // Fall through to default intentionally
|
|
default:
|
|
$stmts = $this->db->prepare("SELECT name, type, button, addon, description, 'not connected' AS status, '- -' AS address, 'N' AS new_hw
|
|
FROM sccpdeviceconfig WHERE RIGHT(type,4) != '-sip' ORDER BY name");
|
|
break;
|
|
}
|
|
break;
|
|
case 'SccpDevice':
|
|
if (empty($data['fields'])) {
|
|
$fld = 'name, name as mac, type, button, addon, description';
|
|
} else {
|
|
switch ($data['fields']) {
|
|
case "all":
|
|
$fld ='*';
|
|
break;
|
|
case "sip_ext":
|
|
$fld ='button as sip_lines, description as description, addon';
|
|
break;
|
|
default:
|
|
$fld = $data['fields'];
|
|
break;
|
|
}
|
|
}
|
|
if (!empty($data['name'])) { //either filter by name or by type
|
|
$stmt = $this->db->prepare('SELECT ' . $fld . ' FROM sccpdeviceconfig WHERE name = :name ORDER BY name');
|
|
$stmt->bindParam(':name', $data['name'],\PDO::PARAM_STR);
|
|
} elseif (!empty($data['type'])) {
|
|
switch ($data['type']) {
|
|
case "cisco-sip":
|
|
$stmts = $this->db->prepare("SELECT {$fld} FROM sccpdeviceconfig WHERE RIGHT(type,4) = '-sip' ORDER BY name");
|
|
break;
|
|
case "cisco": // Fall through to default intentionally
|
|
default:
|
|
$stmts = $this->db->prepare("SELECT {$fld} FROM sccpdeviceconfig WHERE RIGHT(type,4) != '-sip' ORDER BY name");
|
|
break;
|
|
}
|
|
} else { //no filter and no name provided - return all
|
|
$stmts = $this->db->prepare("SELECT {$fld} FROM sccpdeviceconfig ORDER BY name");
|
|
}
|
|
break;
|
|
case 'get_columns_sccpdevice':
|
|
$stmtU = $this->db->prepare('DESCRIBE sccpdevice');
|
|
break;
|
|
case 'get_columns_sccpuser':
|
|
$stmts = $this->db->prepare('DESCRIBE sccpuser');
|
|
break;
|
|
case 'get_columns_sccpline':
|
|
$stmtU = $this->db->prepare('DESCRIBE sccpline');
|
|
break;
|
|
case 'get_sccpdevice_byid':
|
|
$stmt = $this->db->prepare('SELECT t1.*, types.dns, types.buttons, types.loadimage, types.nametemplate as nametemplate,
|
|
addon.buttons as addon_buttons FROM sccpdevice AS t1
|
|
LEFT JOIN sccpdevmodel as types ON t1.type=types.model
|
|
LEFT JOIN sccpdevmodel as addon ON t1.addon=addon.model WHERE name = :name');
|
|
$stmt->bindParam(':name', $data['id'],\PDO::PARAM_STR);
|
|
break;
|
|
case 'get_sccpuser':
|
|
$stmt = $this->db->prepare('SELECT * FROM sccpuser WHERE name = :name');
|
|
$stmt->bindParam(':name', $data['id'],\PDO::PARAM_STR);
|
|
break;
|
|
case 'getAssignedExtensions':
|
|
// all extensions that are designed as default lines
|
|
$stmtU = $this->db->prepare("SELECT DISTINCT name, name FROM sccpbuttonconfig WHERE buttontype = 'line' AND instance =1");
|
|
break;
|
|
case 'getDefaultLine':
|
|
$stmt = $this->db->prepare("SELECT name FROM sccpbuttonconfig WHERE ref = '{$data['id']}' and instance =1 and buttontype = 'line'");
|
|
break;
|
|
case 'get_sccpdevice_buttons':
|
|
$sql = '';
|
|
if (!empty($data['buttontype'])) {
|
|
$sql .= 'buttontype = :buttontype';
|
|
}
|
|
if (!empty($data['id'])) {
|
|
$sql .= (empty($sql)) ? 'ref = :ref' : ' and ref = :ref';
|
|
}
|
|
if (!empty($sql)) {
|
|
$stmts = $this->db->prepare("SELECT * FROM sccpbuttonconfig WHERE {$sql} ORDER BY instance");
|
|
// Now bind labels - only bind label if it exists or bind will create exception.
|
|
// can only bind once have prepared, so need to test again.
|
|
if (!empty($data['buttontype'])) {
|
|
$stmts->bindParam(':buttontype', $data['buttontype'],\PDO::PARAM_STR);
|
|
}
|
|
if (!empty($data['id'])) {
|
|
$stmts->bindParam(':ref', $data['id'],\PDO::PARAM_STR);
|
|
}
|
|
} else {
|
|
$raw_settings = array();
|
|
}
|
|
break;
|
|
// No default case so will give exception of $raw_settings undefined if the
|
|
// dataid is not in the switch.
|
|
}
|
|
if (!empty($stmt)) {
|
|
$stmt->execute();
|
|
$raw_settings = $stmt->fetch(\PDO::FETCH_ASSOC);
|
|
} elseif (!empty($stmts)) {
|
|
$stmts->execute();
|
|
$raw_settings = $stmts->fetchAll(\PDO::FETCH_ASSOC);
|
|
} elseif (!empty($stmtU)) {
|
|
//returns an assoc array indexed on first field
|
|
$stmtU->execute();
|
|
$raw_settings = $stmtU->fetchAll(\PDO::FETCH_ASSOC|\PDO::FETCH_UNIQUE);
|
|
}
|
|
return $raw_settings;
|
|
}
|
|
|
|
public function get_db_SccpSetting()
|
|
{
|
|
$stmt = $this->db->prepare('SELECT keyword, sccpsettings.* FROM sccpsettings ORDER BY type, seq');
|
|
$stmt->execute();
|
|
$settingsFromDb = $stmt->fetchAll(\PDO::FETCH_ASSOC|\PDO::FETCH_UNIQUE);
|
|
return $settingsFromDb;
|
|
}
|
|
|
|
public function get_db_sysvalues()
|
|
{
|
|
$stmt = $this->db->prepare('SHOW VARIABLES LIKE \'%group_concat%\'');
|
|
$stmt->execute();
|
|
return $stmt->fetch(\PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
/*
|
|
* Get Sccp Device Model information
|
|
*/
|
|
|
|
function getModelInfoFromDb($get = 'all', $format_list = 'all', $filter = array())
|
|
{
|
|
$sel_inf = "*, model";
|
|
if ($format_list === 'model') {
|
|
$sel_inf = "model, vendor, dns, buttons";
|
|
}
|
|
switch ($get) {
|
|
case 'byciscoid':
|
|
if (isset($filter['model'])) {
|
|
if (!strpos($filter['model'], 'loadInformation')) {
|
|
$filter['model'] = 'loadInformation' . $filter['model'];
|
|
}
|
|
$stmt = $this->db->prepare("SELECT ${sel_inf} FROM sccpdevmodel WHERE (loadinformationid = :model ) ORDER BY model");
|
|
$stmt->bindParam(':model', $filter['model'], \PDO::PARAM_STR);
|
|
} else {
|
|
$stmt = $this->db->prepare("SELECT ${sel_inf} FROM sccpdevmodel ORDER BY model");
|
|
}
|
|
break;
|
|
case 'byid':
|
|
if (isset($filter['model'])) {
|
|
$stmtU = $this->db->prepare("SELECT ${sel_inf} FROM sccpdevmodel WHERE model = :model ORDER BY model");
|
|
$stmtU->bindParam(':model', $filter['model'],\PDO::PARAM_STR);
|
|
} else {
|
|
$stmtU = $this->db->prepare("SELECT ${sel_inf} FROM sccpdevmodel ORDER BY model");
|
|
}
|
|
$stmtU->execute();
|
|
return $stmtU->fetchAll(\PDO::FETCH_ASSOC|\PDO::FETCH_UNIQUE);
|
|
break;
|
|
case 'expansion':
|
|
$stmt = $this->db->prepare("SELECT ${sel_inf} FROM sccpdevmodel WHERE (dns = 0) and (enabled = 1) ORDER BY model");
|
|
break;
|
|
case 'enabled':
|
|
//$stmt = $db->prepare('SELECT ' . {$sel_inf} . ' FROM sccpdevmodel WHERE enabled = 1 ORDER BY model'); //previously this fell through to phones.
|
|
//break; // above includes expansion modules but was not original behaviour so commented out. Falls through to phones.
|
|
case 'phones':
|
|
$stmt = $this->db->prepare("SELECT ${sel_inf} FROM sccpdevmodel WHERE (dns != 0) and (enabled = 1) ORDER BY model");
|
|
break;
|
|
case 'disabled':
|
|
$stmt = $this->db->prepare("SELECT ${sel_inf} FROM sccpdevmodel WHERE (dns != 0) and (enabled = 0) ORDER BY model");
|
|
break;
|
|
case 'ciscophones':
|
|
$stmt = $this->db->prepare("SELECT ${sel_inf} FROM sccpdevmodel WHERE (dns > 0) and (enabled = 1) AND RIGHT(vendor,4) != '-sip' ORDER BY model");
|
|
break;
|
|
case 'sipphones':
|
|
$stmt = $this->db->prepare("SELECT ${sel_inf} FROM sccpdevmodel WHERE (dns > 0) and (enabled = 1) AND RIGHT(vendor,4) = '-sip' ORDER BY model");
|
|
break;
|
|
case 'all': // Fall through to default
|
|
default:
|
|
$stmt = $this->db->prepare("SELECT ${sel_inf} FROM sccpdevmodel ORDER BY model");
|
|
break;
|
|
}
|
|
$stmt->execute();
|
|
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
function write(string $table_name, $save_value = array(), string $mode = 'update', $key_fld = "", $hwid = "")
|
|
{
|
|
// mode clear - Empty table before update
|
|
// mode update - update / replace record
|
|
$result = false;
|
|
switch ($table_name) {
|
|
case 'sccpsettings':
|
|
if ($mode == 'replace') { // Change mode name to be more transparent
|
|
$this->db->prepare('TRUNCATE sccpsettings')->execute();
|
|
$stmt = $this->db->prepare('INSERT INTO sccpsettings (keyword, data, seq, type, systemdefault) VALUES (:keyword,:data,:seq,:type,:systemdefault)');
|
|
} else {
|
|
$stmt = $this->db->prepare('REPLACE INTO sccpsettings (keyword, data, seq, type, systemdefault) VALUES (:keyword,:data,:seq,:type,:systemdefault)');
|
|
}
|
|
foreach ($save_value as $key => $dataArr) {
|
|
if (empty($dataArr)) {
|
|
continue;
|
|
}
|
|
$stmt->bindParam(':keyword',$dataArr['keyword'],\PDO::PARAM_STR);
|
|
$stmt->bindParam(':data',$dataArr['data'],\PDO::PARAM_STR);
|
|
$stmt->bindParam(':seq',$dataArr['seq'],\PDO::PARAM_INT);
|
|
$stmt->bindParam(':type',$dataArr['type'],\PDO::PARAM_INT);
|
|
$stmt->bindParam(':systemdefault',$dataArr['systemdefault'],\PDO::PARAM_STR);
|
|
$result = $stmt->execute();
|
|
}
|
|
break;
|
|
case 'sccpdevmodel': // Fall through to next intentionally
|
|
case 'sccpdevice': // Fall through to next intentionally
|
|
case 'sccpuser':
|
|
$sql_key = '';
|
|
$stmt = '';
|
|
$formattedSQL = array_reduce(
|
|
array_keys($save_value), // pass in the array_keys instead of the array here
|
|
function ($carry, $key) use ($save_value) { // ... then 'use' the actual array here
|
|
return "${carry}${key} = '${save_value[$key]}', ";
|
|
},
|
|
);
|
|
if (isset($formattedSQL)) { // if array is empty returns null
|
|
$formattedSQL = rtrim($formattedSQL,', '); // Remove the trailing ',' and any spaces.
|
|
switch ($mode) {
|
|
case 'delete':
|
|
if (array_key_exists($key_fld, $save_value)) {
|
|
$sql_key = "${key_fld} = '${save_value[$key_fld]}'"; //quote data as normally is string
|
|
$stmt = $this->db->prepare("DELETE FROM {$table_name} WHERE {$sql_key}");
|
|
}
|
|
break;
|
|
case 'update':
|
|
if (array_key_exists($key_fld, $save_value)) {
|
|
$sql_key = "${key_fld} = '${save_value[$key_fld]}'"; //quote data as normally is string
|
|
$stmt = $this->db->prepare("UPDATE {$table_name} SET {$formattedSQL} WHERE {$sql_key}");
|
|
}
|
|
break;
|
|
case 'replace':
|
|
$stmt = $this->db->prepare("REPLACE INTO {$table_name} SET {$formattedSQL}");
|
|
break;
|
|
// no default mode - must be explicit.
|
|
}
|
|
}
|
|
$result = (!empty($stmt)) ? $stmt->execute() : false;
|
|
break;
|
|
case 'sccpbuttons':
|
|
switch ($mode) {
|
|
case 'delete':
|
|
$sql = 'DELETE FROM sccpbuttonconfig WHERE ref = :hwid';
|
|
$stmt = $this->db->prepare($sql);
|
|
$stmt->bindParam(':hwid', $hwid,\PDO::PARAM_STR);
|
|
$result = $stmt->execute();
|
|
break;
|
|
case 'replace':
|
|
foreach ($save_value as $button_array) {
|
|
$stmt = $this->db->prepare('UPDATE sccpbuttonconfig SET name =:name WHERE ref = :ref AND reftype =:reftype AND instance = :instance AND buttontype = :buttontype AND options = :options');
|
|
$stmt->bindParam(':ref', $button_array['ref'],\PDO::PARAM_STR);
|
|
$stmt->bindParam(':reftype', $button_array['reftype'],\PDO::PARAM_STR);
|
|
$stmt->bindParam(':instance', $button_array['instance'],\PDO::PARAM_INT);
|
|
$stmt->bindParam(':buttontype', $button_array['buttontype'],\PDO::PARAM_STR);
|
|
$stmt->bindParam(':name', $button_array['name'],\PDO::PARAM_STR);
|
|
$stmt->bindParam(':options', $button_array['options'],\PDO::PARAM_STR);
|
|
$result= $stmt->execute();
|
|
}
|
|
break;
|
|
case 'add':
|
|
foreach ($save_value as $button_array) {
|
|
$stmt = $this->db->prepare("INSERT INTO sccpbuttonconfig SET ref = :ref, reftype = :reftype, instance = :instance, buttontype = :buttontype, name = :name, options = :options");
|
|
$stmt->bindParam(':ref', $button_array['ref'],\PDO::PARAM_STR);
|
|
$stmt->bindParam(':reftype', $button_array['reftype'],\PDO::PARAM_STR);
|
|
$stmt->bindParam(':instance', $button_array['instance'],\PDO::PARAM_INT);
|
|
$stmt->bindParam(':buttontype', $button_array['buttontype'],\PDO::PARAM_STR);
|
|
$stmt->bindParam(':name', $button_array['name'],\PDO::PARAM_STR);
|
|
$stmt->bindParam(':options', $button_array['options'],\PDO::PARAM_STR);
|
|
$result = $stmt->execute();
|
|
|
|
}
|
|
break;
|
|
case 'clear';
|
|
// Clear is equivalent of delete + insert. Mode is used in order to activate trigger.
|
|
$this->write('sccpbuttons', '', $mode = 'delete','', $hwid);
|
|
$this->write('sccpbuttons', $save_value, $mode = 'add','', $hwid);
|
|
break;
|
|
// No default case - must be specific in request.
|
|
}
|
|
}
|
|
return $result;
|
|
}
|
|
//******** Get SIP settings *******
|
|
public function getSipTableData(string $dataid, $line='') {
|
|
global $db;
|
|
$tech = array();
|
|
switch ($dataid) {
|
|
case "DeviceById":
|
|
// TODO: This needs to be rewritten
|
|
$stmt = $this->db->prepare("SELECT keyword,data FROM sip WHERE id = '${line}'");
|
|
$stmt->execute();
|
|
$tech = $stmt->fetchAll(\PDO::FETCH_COLUMN | \PDO::FETCH_GROUP);
|
|
foreach ($tech as &$value) {
|
|
$value = $value[0];
|
|
}
|
|
|
|
return $tech;
|
|
case "extensionList";
|
|
$stmt = $this->db->prepare("SELECT id as name, data as label FROM sip WHERE keyword = 'callerid' order by name");
|
|
$stmt->execute();
|
|
$result = $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
|
/*
|
|
foreach ($result as $value) {
|
|
if (empty($tech[$value['id']]['id'])) {
|
|
$tech[$value['id']]['id']= $value['id'];
|
|
}
|
|
$tech[$value['id']][$value['keyword']]=$value['data'];
|
|
}
|
|
*/
|
|
return $result;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Maybe Replace by SccpTables ??!
|
|
*
|
|
*/
|
|
public function dump_sccp_tables($data_path, $database, $user, $pass)
|
|
{
|
|
$filename = $data_path.'/sccp_backup_'.date('G_a_m_d_y').'.sql';
|
|
$result = exec('mysqldump '.$database.' --password='.$pass.' --user='.$user.' --single-transaction >'.$filename, $output);
|
|
return $filename;
|
|
}
|
|
|
|
public function updateTableDefaults($table, $field, $value) {
|
|
$stmt = $this->db->prepare("ALTER TABLE {$table} ALTER COLUMN {$field} SET DEFAULT '{$value}'");
|
|
$stmt->execute();
|
|
}
|
|
|
|
/*
|
|
* Check Table structure
|
|
*/
|
|
public function validate()
|
|
{
|
|
$result = 0;
|
|
$check_fields = [
|
|
'431' => ['private'=> "enum('on','off')"],
|
|
'433' => ['directed_pickup'=>'']
|
|
];
|
|
$stmt = $this->db->prepare('DESCRIBE sccpdevice');
|
|
$stmt->execute();
|
|
foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $value) {
|
|
$id_result[$value['Field']] = $value['Type'];
|
|
}
|
|
foreach ($check_fields as $key => $value) {
|
|
if (!empty(array_intersect_assoc($value, $id_result))) {
|
|
$result = $key;
|
|
} else {
|
|
// no match but maybe checking against an empty string so just need to check key does not exist
|
|
foreach ($value as $skey => $svalue) {
|
|
if (empty($svalue) && (!isset($id_result[$skey]))) {
|
|
$result = $key;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function getNamedGroup($callGroup) {
|
|
$sql = "SELECT {$callGroup} FROM sccpline GROUP BY {$callGroup}";
|
|
$sth = $this->db->prepare($sql);
|
|
$result = array();
|
|
$tech = array();
|
|
try {
|
|
$sth->execute();
|
|
$result = $sth->fetchAll();
|
|
foreach($result as $val) {
|
|
$tech[$callGroup][] = $val[0];
|
|
}
|
|
} catch(\Exception $e) {}
|
|
return $tech;
|
|
}
|
|
}
|