mirror of
https://github.com/fusionpbx/fusionpbx.git
synced 2025-12-30 09:03:49 +00:00
* remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove class_exists wrapper for class definitions * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove include statement of class file * remove closing tag * remove invalid method params * remove closing tag * remove closing tag * Update auto_loader to load each class file in the project Update the auto_loader class to use an include statement on each file in the project to load the class within the file. This will allow mismatched names within the file to be loaded and mapped according to the declaration instead of the filename. The class is then checked against the parsed classes from the PHP engine so that namespaces are available and mapped to the file they were declared in. An update was also made to the search algorithm used to find a file that was not already loaded by collapsing the array to have only valid matches to increase performance on a cache miss. Logging within the auto_loader has been moved to a function. Multiple files were modified to allow the include statement. When the class has the `if(class_exists())` statement, the auto_loader is called to check for the class. This caused an infinite loop scenario so all wrappers have been removed. The auto_loader will now break the loop by directly modifying the internal classes array instead of trying to restart with the 'reload_classes' method. - APCu is used to cache classes so any loading of the classes is done only once. To clear the APCu cache, restart php-fpm or call the auto_loader::clear_cache() function. - Cache file is used when APCu is not available. To clear the cache remove it from the tmp folder or call the auto_loader::clear_cache() function. - All classes must no longer have a class_exists wrapper to benefit from the performance boost. - Classes should not be directly included when the auto_loader is used. * remove include statement of class file * Update destinations.php
915 lines
30 KiB
PHP
915 lines
30 KiB
PHP
<?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>
|
|
Copyright (C) 2013 - 2023
|
|
All Rights Reserved.
|
|
|
|
Contributor(s):
|
|
Mark J Crane <markjcrane@fusionpbx.com>
|
|
*/
|
|
|
|
//define the schema class
|
|
class schema {
|
|
|
|
//define variables
|
|
private $database;
|
|
public $apps;
|
|
public $db_type;
|
|
public $result;
|
|
public $data_types;
|
|
|
|
//class constructor
|
|
public function __construct() {
|
|
|
|
//includes files
|
|
require dirname(__DIR__, 2) . "/resources/require.php";
|
|
|
|
//connect to the database
|
|
$this->database = database::new();
|
|
|
|
//get the list of 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) {
|
|
try {
|
|
include($config_path);
|
|
} catch (Exception $e) {
|
|
//echo 'Caught exception: ', $e->getMessage(), "\n";
|
|
}
|
|
$x++;
|
|
}
|
|
$this->apps = $apps;
|
|
}
|
|
|
|
//create the database schema
|
|
public function sql() {
|
|
$sql = '';
|
|
$sql_schema = '';
|
|
foreach ($this->apps as $app) {
|
|
if (isset($app['db']) && count($app['db'])) {
|
|
foreach ($app['db'] as $row) {
|
|
//create the sql string
|
|
$table_name = $row['table']['name'];
|
|
$sql = "CREATE TABLE " . $row['table']['name'] . " (\n";
|
|
$field_count = 0;
|
|
foreach ($row['fields'] as $field) {
|
|
if (!empty($field['deprecated']) and ($field['deprecated'] == "true")) {
|
|
//skip this field
|
|
} 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'][$this->db_type];
|
|
} else {
|
|
$sql .= $field['type'];
|
|
}
|
|
if (isset($field['key']) && isset($field['key']['type']) && ($field['key']['type'] == "primary")) {
|
|
$sql .= " PRIMARY KEY";
|
|
}
|
|
if (isset($field['key']) && isset($field['key']['type']) && ($field['key']['type'] == "foreign")) {
|
|
if ($this->db_type == "pgsql") {
|
|
//$sql .= " references ".$field['key']['reference']['table']."(".$field['key']['reference']['field'].")";
|
|
}
|
|
if ($this->db_type == "sqlite") {
|
|
//$sql .= " references ".$field['key']['reference']['table']."(".$field['key']['reference']['field'].")";
|
|
}
|
|
if ($this->db_type == "mysql") {
|
|
//$sql .= " references ".$field['key']['reference']['table']."(".$field['key']['reference']['field'].")";
|
|
}
|
|
}
|
|
$field_count++;
|
|
}
|
|
}
|
|
if ($this->db_type == "mysql") {
|
|
$sql .= ") ENGINE=INNODB;";
|
|
} else {
|
|
$sql .= ");";
|
|
}
|
|
$this->result['sql'][] = $sql;
|
|
unset($sql);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//create the database schema
|
|
public function exec() {
|
|
foreach ($this->result['sql'] as $sql) {
|
|
//start the sql transaction
|
|
$this->database->beginTransaction();
|
|
//execute the sql query
|
|
try {
|
|
$this->database->query($sql);
|
|
} catch (PDOException $error) {
|
|
echo "error: " . $error->getMessage() . " sql: $sql<br/>";
|
|
}
|
|
//complete the transaction
|
|
$this->database->commit();
|
|
}
|
|
}
|
|
|
|
//check if a column exists in sqlite
|
|
private function sqlite_column_exists($table_info, $column_name) {
|
|
foreach ($table_info as $key => $row) {
|
|
if ($row['name'] == $column_name) {
|
|
return true;
|
|
}
|
|
}
|
|
return $false;
|
|
}
|
|
|
|
//check if a column exists
|
|
public function column_exists($db_name, $table_name, $column_name) {
|
|
|
|
if ($this->db_type == "sqlite") {
|
|
$table_info = $this->table_info($db_name, $table_name);
|
|
if ($this->sqlite_column_exists($table_info, $column_name)) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
if ($this->db_type == "pgsql") {
|
|
$sql = "SELECT attname FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = '$table_name' limit 1) AND attname = '$column_name'; ";
|
|
}
|
|
if ($this->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 = $this->database->db->prepare($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);
|
|
}
|
|
}
|
|
|
|
//get the table information
|
|
public function table_info($db_name, $table_name) {
|
|
if (empty($table_name)) {
|
|
return false;
|
|
}
|
|
if ($this->db_type == "sqlite") {
|
|
$sql = "PRAGMA table_info(" . $table_name . ");";
|
|
}
|
|
if ($this->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 ($this->db_type == "mysql") {
|
|
$sql = "describe " . $table_name . ";";
|
|
}
|
|
$prep_statement = $this->database->db->prepare($sql);
|
|
$prep_statement->execute();
|
|
return $prep_statement->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
//database table exists alternate
|
|
private function db_table_exists_alternate($db_type, $table_name) {
|
|
$sql = "select count(*) from $table_name ";
|
|
$result = $this->database->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_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 = $this->database->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_name, $db_type, $table_name) {
|
|
if (empty($table_name)) {
|
|
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 = $this->database->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_type, $db_name, $table_name, $column_name) {
|
|
|
|
if ($db_type == "sqlite") {
|
|
$table_info = $this->db_table_info($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' limit 1) 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 = $this->database->db->prepare(check_sql($sql));
|
|
$prep_statement->execute();
|
|
$result = $prep_statement->fetchAll(PDO::FETCH_NAMED);
|
|
if (!empty($result)) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
unset($prep_statement);
|
|
}
|
|
}
|
|
|
|
//database column data type
|
|
private function db_column_data_type($db_type, $db_name, $table_name, $column_name) {
|
|
$table_info = $this->db_table_info($db_name, $db_type, $table_name);
|
|
return $this->db_data_type($db_type, $table_info, $column_name);
|
|
}
|
|
|
|
//database create table
|
|
public function db_create_table($apps, $db_type, $table) {
|
|
if (empty($apps)) {
|
|
return false;
|
|
}
|
|
if (is_array($apps)) {
|
|
foreach ($apps as $x => $app) {
|
|
if (!empty($app['db']) && is_array($app['db'])) {
|
|
foreach ($app['db'] as $y => $row) {
|
|
if (!empty($row['table']['name']) && is_array($row['table']['name'])) {
|
|
$table_name = $row['table']['name']['text'];
|
|
} else {
|
|
$table_name = $row['table']['name'];
|
|
}
|
|
if ($table_name == $table) {
|
|
$sql = "CREATE TABLE " . $table_name . " (\n";
|
|
(int) $field_count = 0;
|
|
if (!empty($row['fields']) && is_array($row['fields'])) {
|
|
foreach ($row['fields'] as $field) {
|
|
if (!empty($field['deprecated']) && $field['deprecated'] == "true") {
|
|
//skip this row
|
|
} else {
|
|
if ($field_count > 0) {
|
|
$sql .= ",\n";
|
|
}
|
|
if (!empty($field['name']) && is_array($field['name'])) {
|
|
$sql .= $field['name']['text'] . " ";
|
|
} else {
|
|
$sql .= $field['name'] . " ";
|
|
}
|
|
if (!empty($field['type']) && is_array($field['type'])) {
|
|
$sql .= $field['type'][$db_type];
|
|
} else {
|
|
$sql .= $field['type'];
|
|
}
|
|
if (!empty($field['key']['type']) && $field['key']['type'] == "primary") {
|
|
$sql .= " PRIMARY KEY";
|
|
}
|
|
$field_count++;
|
|
}
|
|
}
|
|
}
|
|
$sql .= ");\n";
|
|
return $sql;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//database insert
|
|
private function db_insert_into($apps, $db_type, $table) {
|
|
global $db_name;
|
|
foreach ($apps as $x => $app) {
|
|
foreach ($app['db'] as $y => $row) {
|
|
if ($row['table']['name'] == $table) {
|
|
$sql = "INSERT INTO " . $row['table']['name'] . " (";
|
|
$field_count = 0;
|
|
foreach ($row['fields'] as $field) {
|
|
if (!empty($field['deprecated']) && $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 (!empty($field['deprecated']) && $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_type, $db_name, 'tmp_' . $table, $row)) {
|
|
$sql .= $row;
|
|
$found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!$found) {
|
|
$sql .= "''";
|
|
}
|
|
} else {
|
|
if ($this->db_column_exists($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";
|
|
return $sql;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//datatase schema
|
|
public function schema($format = '') {
|
|
|
|
//set the global variable
|
|
global $text, $output_format;
|
|
|
|
if ($format == '') {
|
|
$format = $output_format;
|
|
}
|
|
|
|
//get the db variables
|
|
//$config = new config;
|
|
//$config_exists = $config->exists();
|
|
//$config_path = $config->find();
|
|
//$config->get();
|
|
//$db_type = $config->db_type;
|
|
//$db_name = $config->db_name;
|
|
//$db_username = $config->db_username;
|
|
//$db_password = $config->db_password;
|
|
//$db_host = $config->db_host;
|
|
//$db_path = $config->db_path;
|
|
//$db_port = $config->db_port;
|
|
//includes files
|
|
require dirname(__DIR__, 2) . "/resources/require.php";
|
|
|
|
//add multi-lingual support
|
|
if (!isset($text)) {
|
|
$language = new text;
|
|
$text = $language->get(null, 'core/upgrade');
|
|
}
|
|
|
|
//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
|
|
//update the app db array add exists true or false
|
|
$sql = '';
|
|
foreach ($this->apps as $x => $app) {
|
|
if (isset($app['db'])) {
|
|
foreach ($app['db'] as $y => $row) {
|
|
if (isset($row['table']['name'])) {
|
|
if (is_array($row['table']['name'])) {
|
|
$table_name = $row['table']['name']['text'];
|
|
} else {
|
|
$table_name = $row['table']['name'];
|
|
}
|
|
} else {
|
|
//old array syntax
|
|
if (is_array($row['table'])) {
|
|
$table_name = $row['table']['text'];
|
|
} else {
|
|
$table_name = $row['table'];
|
|
}
|
|
}
|
|
if (!empty($table_name)) {
|
|
|
|
//check if the table exists
|
|
if ($this->db_table_exists($db_type, $db_name, $table_name)) {
|
|
$this->apps[$x]['db'][$y]['exists'] = 'true';
|
|
} else {
|
|
$this->apps[$x]['db'][$y]['exists'] = 'false';
|
|
}
|
|
//check if the column exists
|
|
foreach ($row['fields'] as $z => $field) {
|
|
if (!empty($field['deprecated']) && $field['deprecated'] == "true") {
|
|
//skip this field
|
|
} else {
|
|
if (is_array($field['name'])) {
|
|
$field_name = $field['name']['text'];
|
|
} else {
|
|
$field_name = $field['name'];
|
|
}
|
|
if (!empty($field_name)) {
|
|
if ($this->db_column_exists($db_type, $db_name, $table_name, $field_name)) {
|
|
//found
|
|
$this->apps[$x]['db'][$y]['fields'][$z]['exists'] = 'true';
|
|
} else {
|
|
//not found
|
|
$this->apps[$x]['db'][$y]['fields'][$z]['exists'] = 'false';
|
|
}
|
|
}
|
|
unset($field_name);
|
|
}
|
|
}
|
|
unset($table_name);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//prepare the variables
|
|
$sql_update = '';
|
|
|
|
//add missing tables and fields
|
|
foreach ($this->apps as $x => $app) {
|
|
if (isset($app['db'])) {
|
|
foreach ($app['db'] as $y => $row) {
|
|
if (is_array($row['table']['name'])) {
|
|
$table_name = $row['table']['name']['text'];
|
|
if ($this->db_table_exists($db_type, $db_name, $row['table']['name']['deprecated'])) {
|
|
$row['exists'] = "false"; //testing
|
|
if ($db_type == "pgsql") {
|
|
$sql_update .= "ALTER TABLE " . $row['table']['name']['deprecated'] . " RENAME TO " . $row['table']['name']['text'] . ";\n";
|
|
}
|
|
if ($db_type == "mysql") {
|
|
$sql_update .= "RENAME TABLE " . $row['table']['name']['deprecated'] . " TO " . $row['table']['name']['text'] . ";\n";
|
|
}
|
|
if ($db_type == "sqlite") {
|
|
$sql_update .= "ALTER TABLE " . $row['table']['name']['deprecated'] . " RENAME TO " . $row['table']['name']['text'] . ";\n";
|
|
}
|
|
} else {
|
|
if ($this->db_table_exists($db_type, $db_name, $row['table']['name']['text'])) {
|
|
$row['exists'] = "true";
|
|
} else {
|
|
$row['exists'] = "false";
|
|
$sql_update .= $this->db_create_table($this->apps, $db_type, $row['table']['name']['text']);
|
|
}
|
|
}
|
|
} else {
|
|
if ($this->db_table_exists($db_type, $db_name, $row['table']['name'])) {
|
|
$row['exists'] = "true";
|
|
} else {
|
|
$row['exists'] = "false";
|
|
}
|
|
$table_name = $row['table']['name'];
|
|
}
|
|
|
|
//check if the table exists
|
|
if ($row['exists'] == "true") {
|
|
if (count($row['fields']) > 0) {
|
|
foreach ($row['fields'] as $z => $field) {
|
|
if (!empty($field['deprecated']) && $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'];
|
|
}
|
|
|
|
//check if the field exists
|
|
// if ($this->db_column_exists($db_type, $db_name, $table_name, $field_name)) {
|
|
// $field['exists'] = "true";
|
|
// }
|
|
// else {
|
|
// $field['exists'] = "false";
|
|
// }
|
|
//add or rename fields
|
|
if (isset($field['name']['deprecated']) && $this->db_column_exists($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
|
|
$this->apps[$x]['db'][$y]['rebuild'] = 'true';
|
|
}
|
|
} else {
|
|
//find missing fields and add them
|
|
if ($field['exists'] == "false") {
|
|
$sql_update .= "ALTER TABLE " . $table_name . " ADD " . $field_name . " " . $field_type . ";\n";
|
|
}
|
|
}
|
|
|
|
//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 ($this->data_types) {
|
|
$db_field_type = $this->db_column_data_type($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) && !empty($db_field_type)) {
|
|
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 {
|
|
//field type has not changed
|
|
if ($db_field_type == "integer" && strtolower($field_type) == "serial") {
|
|
|
|
} else if ($db_field_type == "timestamp without time zone" && strtolower($field_type) == "timestamp") {
|
|
|
|
} else if ($db_field_type == "timestamp without time zone" && strtolower($field_type) == "datetime") {
|
|
|
|
} else if ($db_field_type == "timestamp with time zone" && strtolower($field_type) == "timestamptz") {
|
|
|
|
} else if ($db_field_type == "integer" && strtolower($field_type) == "numeric") {
|
|
|
|
} else if ($db_field_type == "character" && strtolower($field_type) == "char") {
|
|
|
|
}
|
|
//field type has changed
|
|
else {
|
|
switch ($field_type) {
|
|
case 'numeric': $using = $field_name . "::numeric";
|
|
break;
|
|
case 'timestamp':
|
|
case 'datetime': $using = $field_name . "::timestamp without time zone";
|
|
break;
|
|
case 'timestamptz': $using = $field_name . "::timestamp with time zone";
|
|
break;
|
|
case 'boolean': $using = $field_name . "::boolean";
|
|
break;
|
|
default: unset($using);
|
|
}
|
|
$sql_update .= "ALTER TABLE " . $table_name . " ALTER COLUMN " . $field_name . " TYPE " . $field_type . " " . ($using ? "USING " . $using : null) . ";\n";
|
|
}
|
|
}
|
|
}
|
|
if ($db_type == "mysql") {
|
|
$type = explode("(", $db_field_type);
|
|
if ($type[0] == $field_type) {
|
|
//do nothing
|
|
} else if ($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
|
|
$this->apps[$x]['db'][$y]['rebuild'] = 'true';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} elseif (!is_array($row['table']['name'])) {
|
|
//create table
|
|
$sql_update .= $this->db_create_table($this->apps, $db_type, $row['table']['name']);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//rebuild and populate the table
|
|
foreach ($this->apps as $x => $app) {
|
|
if (isset($app['db'])) {
|
|
foreach ($app['db'] as $y => $row) {
|
|
if (is_array($row['table']['name'])) {
|
|
$table_name = $row['table']['name']['text'];
|
|
} else {
|
|
$table_name = $row['table']['name'];
|
|
}
|
|
if (!empty($field['rebuild']) && $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($this->apps, $db_type, $table_name);
|
|
//insert the data into the new table
|
|
$sql_update .= $this->db_insert_into($this->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 ($format == "html") {
|
|
//show the database type
|
|
$response .= "<strong>" . $text['header-database_type'] . ": " . $db_type . "</strong><br /><br />";
|
|
//start the table
|
|
$response .= "<table width='100%' border='0' cellpadding='20' cellspacing='0'>\n";
|
|
//show the changes
|
|
if (!empty($sql_update)) {
|
|
$response .= "<tr>\n";
|
|
$response .= "<td class='row_style1' colspan='3'>\n";
|
|
$response .= "<br />\n";
|
|
$response .= "<strong>" . $text['label-sql_changes'] . ":</strong><br />\n";
|
|
$response .= "<pre>\n";
|
|
$response .= $sql_update;
|
|
$response .= "</pre>\n";
|
|
$response .= "<br />\n";
|
|
$response .= "</td>\n";
|
|
$response .= "</tr>\n";
|
|
}
|
|
//list all tables
|
|
$response .= "<tr>\n";
|
|
$response .= "<th>" . $text['label-table'] . "</th>\n";
|
|
$response .= "<th>" . $text['label-exists'] . "</th>\n";
|
|
$response .= "<th>" . $text['label-details'] . "</th>\n";
|
|
$response .= "<tr>\n";
|
|
//build the html while looping through the app db array
|
|
$sql = '';
|
|
foreach ($this->apps as $app) {
|
|
if (isset($app['db'])) {
|
|
foreach ($app['db'] as $row) {
|
|
if (is_array($row['table']['name'])) {
|
|
$table_name = $row['table']['name']['text'];
|
|
} else {
|
|
$table_name = $row['table']['name'];
|
|
}
|
|
$response .= "<tr>\n";
|
|
|
|
//check if the table exists
|
|
if ($row['exists'] == "true") {
|
|
$response .= "<td valign='top' class='row_style1'>" . $table_name . "</td>\n";
|
|
$response .= "<td valign='top' class='vncell' style='padding-top: 3px;'>" . $text['option-true'] . "</td>\n";
|
|
|
|
if (count($row['fields']) > 0) {
|
|
$response .= "<td class='row_style1'>\n";
|
|
//show the list of columns
|
|
$response .= "<table border='0' cellpadding='10' cellspacing='0'>\n";
|
|
$response .= "<tr>\n";
|
|
$response .= "<th>" . $text['label-name'] . "</th>\n";
|
|
$response .= "<th>" . $text['label-type'] . "</th>\n";
|
|
$response .= "<th>" . $text['label-exists'] . "</th>\n";
|
|
$response .= "</tr>\n";
|
|
foreach ($row['fields'] as $field) {
|
|
if (!empty($field['deprecated']) && $field['deprecated'] == "true") {
|
|
//skip this field
|
|
} else {
|
|
if (is_array($field['name'])) {
|
|
$field_name = $field['name']['text'];
|
|
} else {
|
|
$field_name = $field['name'];
|
|
}
|
|
if (is_array($field['type'])) {
|
|
$field_type = $field['type'][$db_type];
|
|
} else {
|
|
$field_type = $field['type'];
|
|
}
|
|
$response .= "<tr>\n";
|
|
$response .= "<td class='row_style1' width='200'>" . $field_name . "</td>\n";
|
|
$response .= "<td class='row_style1'>" . $field_type . "</td>\n";
|
|
if ($field['exists'] == "true") {
|
|
$response .= "<td class='row_style0' style=''>" . $text['option-true'] . "</td>\n";
|
|
$response .= "<td> </td>\n";
|
|
} else {
|
|
$response .= "<td class='row_style1' style='background-color:#444444;color:#CCCCCC;'>" . $text['option-false'] . "</td>\n";
|
|
$response .= "<td> </td>\n";
|
|
}
|
|
$response .= "</tr>\n";
|
|
}
|
|
}
|
|
$response .= " </table>\n";
|
|
$response .= "</td>\n";
|
|
}
|
|
} else {
|
|
$response .= "<td valign='top' class='row_style1'>$table_name</td>\n";
|
|
$response .= "<td valign='top' class='row_style1' style='background-color:#444444;color:#CCCCCC;'><strong>" . $text['label-exists'] . "</strong><br />" . $text['option-false'] . "</td>\n";
|
|
$response .= "<td valign='top' class='row_style1'> </td>\n";
|
|
}
|
|
$response .= "</tr>\n";
|
|
}
|
|
}
|
|
}
|
|
//end the list of tables
|
|
$response .= "</table>\n";
|
|
$response .= "<br />\n";
|
|
}
|
|
|
|
//loop line by line through all the lines of sql code
|
|
$x = 0;
|
|
if (empty($sql_update) && $format == "text") {
|
|
$response .= " " . $text['label-schema'] . ": " . $text['label-no_change'] . "\n";
|
|
} else {
|
|
if ($format == "text") {
|
|
$response .= " " . $text['label-schema'] . "\n";
|
|
}
|
|
//$this->db->beginTransaction();
|
|
$update_array = explode(";", $sql_update);
|
|
foreach ($update_array as $sql) {
|
|
if (strlen(trim($sql))) {
|
|
try {
|
|
$this->database->db->query(trim($sql));
|
|
if ($format == "text") {
|
|
$response .= " $sql;\n";
|
|
}
|
|
} catch (PDOException $error) {
|
|
$response .= " error: " . $error->getMessage() . " sql: $sql\n";
|
|
}
|
|
}
|
|
}
|
|
//$this->db->commit();
|
|
$response .= "\n";
|
|
unset($sql_update, $sql);
|
|
}
|
|
|
|
//refresh each postgresql subscription with its publication
|
|
if ($db_type == "pgsql") {
|
|
//get the list of postgresql subscriptions
|
|
$sql = "select subname from pg_subscription; ";
|
|
$pg_subscriptions = $this->database->select($sql, null, 'all');
|
|
unset($sql, $parameters);
|
|
|
|
//refresh each subscription publication
|
|
foreach ($pg_subscriptions as $row) {
|
|
$sql = "ALTER SUBSCRIPTION " . $row['subname'] . " REFRESH PUBLICATION;";
|
|
$response .= $sql;
|
|
$this->database->execute($sql);
|
|
}
|
|
}
|
|
|
|
//handle response
|
|
//if ($output == "echo") {
|
|
// echo $response;
|
|
//}
|
|
//else if ($output == "return") {
|
|
return $response;
|
|
//}
|
|
} //end function
|
|
}
|
|
|
|
|
|
//example use
|
|
//$obj = new schema;
|
|
//$obj->db_type = $db_type;
|
|
//$obj->schema();
|
|
//$result_array = $schema->obj['sql'];
|
|
//print_r($result_array);
|