diff --git a/resources/classes/domains.php b/resources/classes/domains.php
index 034f683034..81edad15a5 100644
--- a/resources/classes/domains.php
+++ b/resources/classes/domains.php
@@ -29,8 +29,8 @@
public function set() {
- //set the variable
- $db = $this->db;
+ //set the global variable
+ global $db;
//clear the sessions
unset($_SESSION['contact']);
@@ -185,8 +185,8 @@
public function upgrade() {
- //set the variable
- $db = $this->db;
+ //set the global variable
+ global $db;
//get the list of installed apps from the core and mod directories
$config_list = glob($_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/*/*/app_config.php");
diff --git a/resources/classes/schema.php b/resources/classes/schema.php
index bbfcb95cc1..9c76db8403 100644
--- a/resources/classes/schema.php
+++ b/resources/classes/schema.php
@@ -27,10 +27,11 @@ include "root.php";
//define the schema class
class schema {
- public $db;
- public $apps;
- public $db_type;
- public $result;
+ //define variables
+ public $db;
+ public $apps;
+ public $db_type;
+ public $result;
//get the list of installed apps from the core and mod directories
public function __construct() {
@@ -193,7 +194,659 @@ include "root.php";
$prep_statement->execute();
return $prep_statement->fetchAll(PDO::FETCH_ASSOC);
}
- }
+
+ //database table exists alternate
+ private function db_table_exists_alternate ($db, $db_type, $table_name) {
+ $sql = "select count(*) from $table_name ";
+ $result = $db->query($sql);
+ if ($result > 0) {
+ return true; //table exists
+ }
+ else {
+ return false; //table doesn't exist
+ }
+ }
+
+ //database table exists
+ private function db_table_exists ($db, $db_type, $db_name, $table_name) {
+ $sql = "";
+ if ($db_type == "sqlite") {
+ $sql .= "SELECT * FROM sqlite_master WHERE type='table' and name='$table_name' ";
+ }
+ if ($db_type == "pgsql") {
+ $sql .= "select * from pg_tables where schemaname='public' and tablename = '$table_name' ";
+ }
+ if ($db_type == "mysql") {
+ $sql .= "SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = '$db_name' and TABLE_NAME = '$table_name' ";
+ }
+ $prep_statement = $db->prepare(check_sql($sql));
+ $prep_statement->execute();
+ $result = $prep_statement->fetchAll(PDO::FETCH_NAMED);
+ if (count($result) > 0) {
+ return true; //table exists
+ }
+ else {
+ return false; //table doesn't exist
+ }
+ }
+
+ //database table information
+ private function db_table_info($db, $db_name, $db_type, $table_name) {
+ if (strlen($table_name) == 0) { return false; }
+ if ($db_type == "sqlite") {
+ $sql = "PRAGMA table_info(".$table_name.");";
+ }
+ if ($db_type == "pgsql") {
+ $sql = "SELECT ordinal_position, ";
+ $sql .= "column_name, ";
+ $sql .= "data_type, ";
+ $sql .= "column_default, ";
+ $sql .= "is_nullable, ";
+ $sql .= "character_maximum_length, ";
+ $sql .= "numeric_precision ";
+ $sql .= "FROM information_schema.columns ";
+ $sql .= "WHERE table_name = '".$table_name."' ";
+ $sql .= "and table_catalog = '".$db_name."' ";
+ $sql .= "ORDER BY ordinal_position; ";
+ }
+ if ($db_type == "mysql") {
+ $sql = "describe ".$table_name.";";
+ }
+ $prep_statement = $db->prepare($sql);
+ $prep_statement->execute();
+ return $prep_statement->fetchAll(PDO::FETCH_ASSOC);
+ }
+
+ //database type
+ private function db_data_type($db_type, $table_info, $column_name) {
+ if ($db_type == "sqlite") {
+ foreach ($table_info as $key => &$row) {
+ if ($row['name'] == $column_name) {
+ return $row['type'];
+ }
+ }
+ }
+ if ($db_type == "pgsql") {
+ foreach ($table_info as $key => &$row) {
+ if ($row['column_name'] == $column_name) {
+ return $row['data_type'];
+ }
+ }
+ }
+ if ($db_type == "mysql") {
+ foreach ($table_info as $key => &$row) {
+ if ($row['Field'] == $column_name) {
+ return $row['Type'];
+ }
+ }
+ }
+ }
+
+ //sqlite column exists
+ private function db_sqlite_column_exists($table_info, $column_name) {
+ foreach ($table_info as $key => &$row) {
+ if ($row['name'] == $column_name) {
+ return true;
+ }
+ }
+ return $false;
+ }
+
+ //database column exists
+ private function db_column_exists ($db, $db_type, $db_name, $table_name, $column_name) {
+ global $display_type;
+
+ if ($db_type == "sqlite") {
+ $table_info = $this->db_table_info($db, $db_name, $db_type, $table_name);
+ if ($this->db_sqlite_column_exists($table_info, $column_name)) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ if ($db_type == "pgsql") {
+ $sql = "SELECT attname FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = '$table_name') AND attname = '$column_name'; ";
+ }
+ if ($db_type == "mysql") {
+ //$sql .= "SELECT * FROM information_schema.COLUMNS where TABLE_SCHEMA = '$db_name' and TABLE_NAME = '$table_name' and COLUMN_NAME = '$column_name' ";
+ $sql = "show columns from $table_name where field = '$column_name' ";
+ }
+ if ($sql) {
+ $prep_statement = $db->prepare(check_sql($sql));
+ $prep_statement->execute();
+ $result = $prep_statement->fetchAll(PDO::FETCH_NAMED);
+ if (!$result) {
+ return false;
+ }
+ if (count($result) > 0) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ unset ($prep_statement);
+ }
+ }
+
+ //database column data type
+ private function db_column_data_type ($db, $db_type, $db_name, $table_name, $column_name) {
+ $table_info = $this->db_table_info($db, $db_name, $db_type, $table_name);
+ return $this->db_data_type($db_type, $table_info, $column_name);
+ }
+
+ //database create table
+ private function db_create_table ($apps, $db_type, $table) {
+ foreach ($apps as $x => &$app) {
+ foreach ($app['db'] as $y => $row) {
+ if ($row['table'] == $table) {
+ $sql = "CREATE TABLE " . $row['table'] . " (\n";
+ $field_count = 0;
+ foreach ($row['fields'] as $field) {
+ if ($field['deprecated'] == "true") {
+ //skip this row
+ }
+ else {
+ if ($field_count > 0 ) { $sql .= ",\n"; }
+ if (is_array($field['name'])) {
+ $sql .= $field['name']['text'] . " ";
+ }
+ else {
+ $sql .= $field['name'] . " ";
+ }
+ if (is_array($field['type'])) {
+ $sql .= $field['type'][$db_type];
+ }
+ else {
+ $sql .= $field['type'];
+ }
+ if ($field['key']['type'] == "primary") {
+ $sql .= " PRIMARY KEY";
+ }
+ $field_count++;
+ }
+ }
+ $sql .= ");\n\n";
+ return $sql;
+ }
+ }
+ }
+ }
+
+ //database insert
+ private function db_insert_into ($apps, $db_type, $table) {
+ global $db, $db_name;
+ foreach ($apps as $x => &$app) {
+ foreach ($app['db'] as $y => $row) {
+ if ($row['table'] == $table) {
+ $sql = "INSERT INTO " . $row['table'] . " (";
+ $field_count = 0;
+ foreach ($row['fields'] as $field) {
+ if ($field['deprecated'] == "true") {
+ //skip this field
+ }
+ else {
+ if ($field_count > 0 ) { $sql .= ","; }
+ if (is_array($field['name'])) {
+ $sql .= $field['name']['text'];
+ }
+ else {
+ $sql .= $field['name'];
+ }
+ $field_count++;
+ }
+ }
+ $sql .= ")\n";
+ $sql .= "SELECT ";
+ $field_count = 0;
+ foreach ($row['fields'] as $field) {
+ if ($field['deprecated'] == "true") {
+ //skip this field
+ }
+ else {
+ if ($field_count > 0 ) { $sql .= ","; }
+ if (is_array($field['name'])) {
+ if ($field['exists'] == "false") {
+ if (is_array($field['name']['deprecated'])) {
+ $found = false;
+ foreach ($field['name']['deprecated'] as $row) {
+ if ($this->db_column_exists ($db, $db_type, $db_name, 'tmp_'.$table, $row)) {
+ $sql .= $row;
+ $found = true;
+ break;
+ }
+ }
+ if (!$found) { $sql .= "''"; }
+ }
+ else {
+ if ($this->db_column_exists ($db, $db_type, $db_name, 'tmp_'.$table, $field['name']['deprecated'])) {
+ $sql .= $field['name']['deprecated'];
+ }
+ else {
+ $sql .= "''";
+ }
+ }
+ }
+ else {
+ $sql .= $field['name']['text'];
+ }
+ }
+ else {
+ $sql .= $field['name'];
+ }
+ $field_count++;
+ }
+ }
+ $sql .= " FROM tmp_".$table.";\n\n";
+ return $sql;
+ }
+ }
+ }
+ }
+
+ //datatase schema
+ public function schema ($db, $db_type, $db_name, $response_output) {
+ global $db;
+ global $text; // pulls in language variable array
+ global $response_format;
+ global $upgrade_data_types;
+
+ //PHP PDO check if table or column exists
+ //check if table exists
+ // SELECT * FROM sqlite_master WHERE type='table' AND name='v_cdr'
+ //check if column exists
+ // SELECT * FROM sqlite_master WHERE type='table' AND name='v_cdr' AND sql LIKE '%caller_id_name TEXT,%'
+ //aditional information
+ // http://www.sqlite.org/faq.html#q9
+
+ //postgresql
+ //list all tables in the database
+ // SELECT table_name FROM pg_tables WHERE schemaname='public';
+ //check if table exists
+ // SELECT * FROM pg_tables WHERE schemaname='public' AND table_name = 'v_groups'
+ //check if column exists
+ // SELECT attname FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = 'v_cdr') AND attname = 'caller_id_name';
+ //mysql
+ //list all tables in the database
+ // SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = 'fusionpbx'
+ //check if table exists
+ // SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = 'fusionpbx' AND TABLE_NAME = 'v_groups'
+ //check if column exists
+ // SELECT * FROM information_schema.COLUMNS where TABLE_SCHEMA = 'fusionpbx' AND TABLE_NAME = 'v_cdr' AND COLUMN_NAME = 'context'
+ //oracle
+ //check if table exists
+ // SELECT TABLE_NAME FROM ALL_TABLES
+
+ //get the $apps array from the installed apps from the core and mod directories
+ $config_list = glob($_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/*/*/app_config.php");
+ $x=0;
+ foreach ($config_list as &$config_path) {
+ include($config_path);
+ $x++;
+ }
+
+ //update the app db array add exists true or false
+ $sql = '';
+ foreach ($apps as $x => &$app) {
+ foreach ($app['db'] as $y => &$row) {
+ if (is_array($row['table'])) {
+ $table_name = $row['table']['text'];
+ }
+ else {
+ $table_name = $row['table'];
+ }
+ if (strlen($table_name) > 0) {
+ //check if the table exists
+ if ($this->db_table_exists($db, $db_type, $db_name, $table_name)) {
+ $apps[$x]['db'][$y]['exists'] = 'true';
+ }
+ else {
+ $apps[$x]['db'][$y]['exists'] = 'false';
+ }
+ //check if the column exists
+ foreach ($row['fields'] as $z => $field) {
+ if ($field['deprecated'] == "true") {
+ //skip this field
+ }
+ else {
+ if (is_array($field['name'])) {
+ $field_name = $field['name']['text'];
+ }
+ else {
+ $field_name = $field['name'];
+ }
+ if (strlen(field_name) > 0) {
+ if ($this->db_column_exists ($db, $db_type, $db_name, $table_name, $field_name)) {
+ //found
+ $apps[$x]['db'][$y]['fields'][$z]['exists'] = 'true';
+ }
+ else {
+ //not found
+ $apps[$x]['db'][$y]['fields'][$z]['exists'] = 'false';
+ }
+ }
+ unset($field_name);
+ }
+ }
+ unset($table_name);
+ }
+ }
+ }
+
+ //prepare the variables
+ $sql_update = '';
+ $var_uuid = $_GET["id"];
+
+ //add missing tables and fields
+ foreach ($apps as $x => &$app) {
+ foreach ($app['db'] as $y => &$row) {
+ if (is_array($row['table'])) {
+ $table_name = $row['table']['text'];
+ if (!$this->db_table_exists($db, $db_type, $db_name, $row['table']['text'])) {
+ $row['exists'] = "true"; //testing
+ //if (db_table_exists($db, $db_type, $db_name, $row['table']['deprecated'])) {
+ if ($db_type == "pgsql") {
+ $sql_update .= "ALTER TABLE ".$row['table']['deprecated']." RENAME TO ".$row['table']['text'].";\n";
+ }
+ if ($db_type == "mysql") {
+ $sql_update .= "RENAME TABLE ".$row['table']['deprecated']." TO ".$row['table']['text'].";\n";
+ }
+ if ($db_type == "sqlite") {
+ $sql_update .= "ALTER TABLE ".$row['table']['deprecated']." RENAME TO ".$row['table']['text'].";\n";
+ }
+ //}
+ }
+ }
+ else {
+ $table_name = $row['table'];
+ }
+ //check if the table exists
+ if ($row['exists'] == "true") {
+ if (count($row['fields']) > 0) {
+ foreach ($row['fields'] as $z => $field) {
+ if ($field['deprecated'] == "true") {
+ //skip this field
+ }
+ else {
+ //get the data type
+ if (is_array($field['type'])) {
+ $field_type = $field['type'][$db_type];
+ }
+ else {
+ $field_type = $field['type'];
+ }
+ //get the field name
+ if (is_array($field['name'])) {
+ $field_name = $field['name']['text'];
+ }
+ else {
+ $field_name = $field['name'];
+ }
+ //find missing fields and add them
+ if ($field['deprecated'] == "true") {
+ //skip this row
+ }
+ else {
+ if (!is_array($field['name'])) {
+ if ($field['exists'] == "false") {
+ $sql_update .= "ALTER TABLE ".$table_name." ADD ".$field['name']." ".$field_type.";\n";
+ }
+ }
+ }
+ //rename fields where the name has changed
+ if (is_array($field['name'])) {
+ if ($this->db_column_exists ($db, $db_type, $db_name, $table_name, $field['name']['deprecated'])) {
+ if ($db_type == "pgsql") {
+ $sql_update .= "ALTER TABLE ".$table_name." RENAME COLUMN ".$field['name']['deprecated']." to ".$field['name']['text'].";\n";
+ }
+ if ($db_type == "mysql") {
+ $field_type = str_replace("AUTO_INCREMENT PRIMARY KEY", "", $field_type);
+ $sql_update .= "ALTER TABLE ".$table_name." CHANGE ".$field['name']['deprecated']." ".$field['name']['text']." ".$field_type.";\n";
+ }
+ if ($db_type == "sqlite") {
+ //a change has been made to the field name
+ $apps[$x]['db'][$y]['rebuild'] = 'true';
+ }
+ }
+ }
+ //change the data type if it has been changed
+ //if the data type in the app db array is different than the type in the database then change the data type
+ if ($upgrade_data_types) {
+ $db_field_type = $this->db_column_data_type ($db, $db_type, $db_name, $table_name, $field_name);
+ $field_type_array = explode("(", $field_type);
+ $field_type = $field_type_array[0];
+ if (trim($db_field_type) != trim($field_type) && strlen($db_field_type) > 0) {
+ if ($db_type == "pgsql") {
+ if (strtolower($field_type) == "uuid") {
+ $sql_update .= "ALTER TABLE ".$table_name." ALTER COLUMN ".$field_name." TYPE uuid USING\n";
+ $sql_update .= "CAST(regexp_replace(".$field_name.", '([A-Z0-9]{4})([A-Z0-9]{12})', E'\\1-\\2')\n";
+ $sql_update .= "AS uuid);\n";
+ }
+ else {
+ if ($db_field_type = "integer" && strtolower($field_type) == "serial") {
+ //field type has not changed
+ } elseif ($db_field_type = "timestamp without time zone" && strtolower($field_type) == "timestamp") {
+ //field type has not changed
+ } elseif ($db_field_type = "timestamp without time zone" && strtolower($field_type) == "datetime") {
+ //field type has not changed
+ } elseif ($db_field_type = "integer" && strtolower($field_type) == "numeric") {
+ //field type has not changed
+ } elseif ($db_field_type = "character" && strtolower($field_type) == "char") {
+ //field type has not changed
+ }
+ else {
+ //$sql_update .= "-- $db_type, $db_name, $table_name, $field_name ".db_column_data_type ($db, $db_type, $db_name, $table_name, $field_name)."
";
+ $sql_update .= "ALTER TABLE ".$table_name." ALTER COLUMN ".$field_name." TYPE ".$field_type.";\n";
+ }
+ }
+ }
+ if ($db_type == "mysql") {
+ $type = explode("(", $db_field_type);
+ if ($type[0] == $field_type) {
+ //do nothing
+ }
+ elseif ($field_type == "numeric" && $type[0] == "decimal") {
+ //do nothing
+ }
+ else {
+ $sql_update .= "ALTER TABLE ".$table_name." modify ".$field_name." ".$field_type.";\n";
+ }
+ unset($type);
+ }
+ if ($db_type == "sqlite") {
+ //a change has been made to the field type
+ $apps[$x]['db'][$y]['rebuild'] = 'true';
+ }
+ }
+ }
+
+ }
+ }
+ unset($column_array);
+ }
+ }
+ else {
+ //create table
+ if (!is_array($row['table'])) {
+ $sql_update .= $this->db_create_table($apps, $db_type, $row['table']);
+ }
+ }
+ }
+ }
+ //rebuild and populate the table
+ foreach ($apps as $x => &$app) {
+ foreach ($app['db'] as $y => &$row) {
+ if (is_array($row['table'])) {
+ $table_name = $row['table']['text'];
+ }
+ else {
+ $table_name = $row['table'];
+ }
+ if ($row['rebuild'] == "true") {
+ if ($db_type == "sqlite") {
+ //start the transaction
+ //$sql_update .= "BEGIN TRANSACTION;\n";
+ //rename the table
+ $sql_update .= "ALTER TABLE ".$table_name." RENAME TO tmp_".$table_name.";\n";
+ //create the table
+ $sql_update .= $this->db_create_table($apps, $db_type, $table_name);
+ //insert the data into the new table
+ $sql_update .= $this->db_insert_into($apps, $db_type, $table_name);
+ //drop the old table
+ $sql_update .= "DROP TABLE tmp_".$table_name.";\n";
+ //commit the transaction
+ //$sql_update .= "COMMIT;\n";
+ }
+ }
+ }
+ }
+
+ // initialize response variable
+ $response = '';
+
+ //display results as html
+ if ($response_output != '' && $response_format == "html") {
+ //show the database type
+ $response .= "".$text['header-database_type'].": ".$db_type. "
";
+ //start the table
+ $response .= "
| \n";
+ $response .= " \n"; + $response .= "".$text['label-sql_changes'].": \n"; + $response .= " \n"; + $response .= $sql_update; + $response .= "\n"; + $response .= " \n"; + $response .= " | \n";
+ $response .= "||||||||||||||
| ".$text['label-table']." | \n"; + $response .= "".$text['label-exists']." | \n"; + $response .= "".$text['label-details']." | \n"; + $response .= "||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ".$table_name." | \n"; + $response .= "".$text['option-true']." | \n"; + + if (count($row['fields']) > 0) { + $response .= "\n";
+ //show the list of columns
+ $response .= "
| \n";
+ }
+ }
+ else {
+ $response .= "$table_name | \n"; + $response .= "".$text['label-exists']." ".$text['option-false']." | \n";
+ $response .= "\n"; + } + $response .= " | |||||||||