schema.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  1. <?php
  2. /*
  3. FusionPBX
  4. Version: MPL 1.1
  5. The contents of this file are subject to the Mozilla Public License Version
  6. 1.1 (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.mozilla.org/MPL/
  9. Software distributed under the License is distributed on an "AS IS" basis,
  10. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. for the specific language governing rights and limitations under the
  12. License.
  13. The Original Code is FusionPBX
  14. The Initial Developer of the Original Code is
  15. Mark J Crane <[email protected]>
  16. Copyright (C) 2013 - 2019
  17. All Rights Reserved.
  18. Contributor(s):
  19. Mark J Crane <[email protected]>
  20. */
  21. include "root.php";
  22. //define the schema class
  23. if (!class_exists('schema')) {
  24. class schema {
  25. //define variables
  26. public $db;
  27. public $apps;
  28. public $db_type;
  29. public $result;
  30. //class constructor
  31. public function __construct() {
  32. //connect to the database if not connected
  33. if (!$this->db) {
  34. require_once "resources/classes/database.php";
  35. $database = new database;
  36. $database->connect();
  37. $this->db = $database->db;
  38. }
  39. //get the list of installed apps from the core and mod directories
  40. $config_list = glob($_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/*/*/app_config.php");
  41. $x=0;
  42. foreach ($config_list as &$config_path) {
  43. include($config_path);
  44. $x++;
  45. }
  46. $this->apps = $apps;
  47. }
  48. //create the database schema
  49. public function sql() {
  50. $sql = '';
  51. $sql_schema = '';
  52. foreach ($this->apps as $app) {
  53. if (isset($app['db']) && count($app['db'])) {
  54. foreach ($app['db'] as $row) {
  55. //create the sql string
  56. $table_name = $row['table']['name'];
  57. $sql = "CREATE TABLE " . $row['table']['name'] . " (\n";
  58. $field_count = 0;
  59. foreach ($row['fields'] as $field) {
  60. if (isset($field['deprecated']) and ($field['deprecated'] == "true")) {
  61. //skip this field
  62. }
  63. else {
  64. if ($field_count > 0 ) { $sql .= ",\n"; }
  65. if (is_array($field['name'])) {
  66. $sql .= $field['name']['text']." ";
  67. }
  68. else {
  69. $sql .= $field['name']." ";
  70. }
  71. if (is_array($field['type'])) {
  72. $sql .= $field['type'][$this->db_type];
  73. }
  74. else {
  75. $sql .= $field['type'];
  76. }
  77. if (isset($field['key']) && isset($field['key']['type']) && ($field['key']['type'] == "primary")) {
  78. $sql .= " PRIMARY KEY";
  79. }
  80. if (isset($field['key']) && isset($field['key']['type']) && ($field['key']['type'] == "foreign")) {
  81. if ($this->db_type == "pgsql") {
  82. //$sql .= " references ".$field['key']['reference']['table']."(".$field['key']['reference']['field'].")";
  83. }
  84. if ($this->db_type == "sqlite") {
  85. //$sql .= " references ".$field['key']['reference']['table']."(".$field['key']['reference']['field'].")";
  86. }
  87. if ($this->db_type == "mysql") {
  88. //$sql .= " references ".$field['key']['reference']['table']."(".$field['key']['reference']['field'].")";
  89. }
  90. }
  91. $field_count++;
  92. }
  93. }
  94. if ($this->db_type == "mysql") {
  95. $sql .= ") ENGINE=INNODB;";
  96. }
  97. else {
  98. $sql .= ");";
  99. }
  100. $this->result['sql'][] = $sql;
  101. unset($sql);
  102. }
  103. }
  104. }
  105. }
  106. //create the database schema
  107. public function exec() {
  108. foreach ($this->result['sql'] as $sql) {
  109. //start the sql transaction
  110. $this->db->beginTransaction();
  111. //execute the sql query
  112. try {
  113. $this->db->query($sql);
  114. }
  115. catch (PDOException $error) {
  116. echo "error: " . $error->getMessage() . " sql: $sql<br/>";
  117. }
  118. //complete the transaction
  119. $this->db->commit();
  120. }
  121. }
  122. //check if a column exists in sqlite
  123. private function sqlite_column_exists($table_info, $column_name) {
  124. foreach ($table_info as $key => &$row) {
  125. if ($row['name'] == $column_name) {
  126. return true;
  127. }
  128. }
  129. return $false;
  130. }
  131. //check if a column exists
  132. public function column_exists ($db_name, $table_name, $column_name) {
  133. if ($this->db_type == "sqlite") {
  134. $table_info = $this->table_info($db_name, $table_name);
  135. if ($this->sqlite_column_exists($table_info, $column_name)) {
  136. return true;
  137. }
  138. else {
  139. return false;
  140. }
  141. }
  142. if ($this->db_type == "pgsql") {
  143. $sql = "SELECT attname FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = '$table_name') AND attname = '$column_name'; ";
  144. }
  145. if ($this->db_type == "mysql") {
  146. //$sql .= "SELECT * FROM information_schema.COLUMNS where TABLE_SCHEMA = '$db_name' and TABLE_NAME = '$table_name' and COLUMN_NAME = '$column_name' ";
  147. $sql = "show columns from $table_name where field = '$column_name' ";
  148. }
  149. if ($sql) {
  150. $prep_statement = $this->db->prepare($sql);
  151. $prep_statement->execute();
  152. $result = $prep_statement->fetchAll(PDO::FETCH_NAMED);
  153. if (!$result) {
  154. return false;
  155. }
  156. if (count($result) > 0) {
  157. return true;
  158. }
  159. else {
  160. return false;
  161. }
  162. unset ($prep_statement);
  163. }
  164. }
  165. //get the table information
  166. public function table_info($db_name, $table_name) {
  167. if (strlen($table_name) == 0) { return false; }
  168. if ($this->db_type == "sqlite") {
  169. $sql = "PRAGMA table_info(".$table_name.");";
  170. }
  171. if ($this->db_type == "pgsql") {
  172. $sql = "SELECT ordinal_position, ";
  173. $sql .= "column_name, ";
  174. $sql .= "data_type, ";
  175. $sql .= "column_default, ";
  176. $sql .= "is_nullable, ";
  177. $sql .= "character_maximum_length, ";
  178. $sql .= "numeric_precision ";
  179. $sql .= "FROM information_schema.columns ";
  180. $sql .= "WHERE table_name = '".$table_name."' ";
  181. $sql .= "and table_catalog = '".$db_name."' ";
  182. $sql .= "ORDER BY ordinal_position; ";
  183. }
  184. if ($this->db_type == "mysql") {
  185. $sql = "describe ".$table_name.";";
  186. }
  187. $prep_statement = $this->db->prepare($sql);
  188. $prep_statement->execute();
  189. return $prep_statement->fetchAll(PDO::FETCH_ASSOC);
  190. }
  191. //database table exists alternate
  192. private function db_table_exists_alternate ($db_type, $table_name) {
  193. $sql = "select count(*) from $table_name ";
  194. $result = $this->db->query($sql);
  195. if ($result > 0) {
  196. return true; //table exists
  197. }
  198. else {
  199. return false; //table doesn't exist
  200. }
  201. }
  202. //database table exists
  203. private function db_table_exists ($db_type, $db_name, $table_name) {
  204. $sql = "";
  205. if ($db_type == "sqlite") {
  206. $sql .= "SELECT * FROM sqlite_master WHERE type='table' and name='$table_name' ";
  207. }
  208. if ($db_type == "pgsql") {
  209. $sql .= "select * from pg_tables where schemaname='public' and tablename = '$table_name' ";
  210. }
  211. if ($db_type == "mysql") {
  212. $sql .= "SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = '$db_name' and TABLE_NAME = '$table_name' ";
  213. }
  214. $prep_statement = $this->db->prepare(check_sql($sql));
  215. $prep_statement->execute();
  216. $result = $prep_statement->fetchAll(PDO::FETCH_NAMED);
  217. if (count($result) > 0) {
  218. return true; //table exists
  219. }
  220. else {
  221. return false; //table doesn't exist
  222. }
  223. }
  224. //database table information
  225. private function db_table_info($db_name, $db_type, $table_name) {
  226. if (strlen($table_name) == 0) { return false; }
  227. if ($db_type == "sqlite") {
  228. $sql = "PRAGMA table_info(".$table_name.");";
  229. }
  230. if ($db_type == "pgsql") {
  231. $sql = "SELECT ordinal_position, ";
  232. $sql .= "column_name, ";
  233. $sql .= "data_type, ";
  234. $sql .= "column_default, ";
  235. $sql .= "is_nullable, ";
  236. $sql .= "character_maximum_length, ";
  237. $sql .= "numeric_precision ";
  238. $sql .= "FROM information_schema.columns ";
  239. $sql .= "WHERE table_name = '".$table_name."' ";
  240. $sql .= "and table_catalog = '".$db_name."' ";
  241. $sql .= "ORDER BY ordinal_position; ";
  242. }
  243. if ($db_type == "mysql") {
  244. $sql = "describe ".$table_name.";";
  245. }
  246. $prep_statement = $this->db->prepare($sql);
  247. $prep_statement->execute();
  248. return $prep_statement->fetchAll(PDO::FETCH_ASSOC);
  249. }
  250. //database type
  251. private function db_data_type($db_type, $table_info, $column_name) {
  252. if ($db_type == "sqlite") {
  253. foreach ($table_info as $key => &$row) {
  254. if ($row['name'] == $column_name) {
  255. return $row['type'];
  256. }
  257. }
  258. }
  259. if ($db_type == "pgsql") {
  260. foreach ($table_info as $key => &$row) {
  261. if ($row['column_name'] == $column_name) {
  262. return $row['data_type'];
  263. }
  264. }
  265. }
  266. if ($db_type == "mysql") {
  267. foreach ($table_info as $key => &$row) {
  268. if ($row['Field'] == $column_name) {
  269. return $row['Type'];
  270. }
  271. }
  272. }
  273. }
  274. //sqlite column exists
  275. private function db_sqlite_column_exists($table_info, $column_name) {
  276. foreach ($table_info as $key => &$row) {
  277. if ($row['name'] == $column_name) {
  278. return true;
  279. }
  280. }
  281. return $false;
  282. }
  283. //database column exists
  284. private function db_column_exists ($db_type, $db_name, $table_name, $column_name) {
  285. if ($db_type == "sqlite") {
  286. $table_info = $this->db_table_info($db_name, $db_type, $table_name);
  287. if ($this->db_sqlite_column_exists($table_info, $column_name)) {
  288. return true;
  289. }
  290. else {
  291. return false;
  292. }
  293. }
  294. if ($db_type == "pgsql") {
  295. $sql = "SELECT attname FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = '$table_name') AND attname = '$column_name'; ";
  296. }
  297. if ($db_type == "mysql") {
  298. //$sql .= "SELECT * FROM information_schema.COLUMNS where TABLE_SCHEMA = '$db_name' and TABLE_NAME = '$table_name' and COLUMN_NAME = '$column_name' ";
  299. $sql = "show columns from $table_name where field = '$column_name' ";
  300. }
  301. if ($sql) {
  302. $prep_statement = $this->db->prepare(check_sql($sql));
  303. $prep_statement->execute();
  304. $result = $prep_statement->fetchAll(PDO::FETCH_NAMED);
  305. if (!$result) {
  306. return false;
  307. }
  308. if (count($result) > 0) {
  309. return true;
  310. }
  311. else {
  312. return false;
  313. }
  314. unset ($prep_statement);
  315. }
  316. }
  317. //database column data type
  318. private function db_column_data_type ($db_type, $db_name, $table_name, $column_name) {
  319. $table_info = $this->db_table_info($db_name, $db_type, $table_name);
  320. return $this->db_data_type($db_type, $table_info, $column_name);
  321. }
  322. //database create table
  323. public function db_create_table ($apps, $db_type, $table) {
  324. if (is_array($apps)) foreach ($apps as $x => &$app) {
  325. if (is_array($app['db'])) foreach ($app['db'] as $y => $row) {
  326. if (is_array($row['table']['name'])) {
  327. $table_name = $row['table']['name']['text'];
  328. }
  329. else {
  330. $table_name = $row['table']['name'];
  331. }
  332. if ($table_name == $table) {
  333. $sql = "CREATE TABLE " . $table_name . " (\n";
  334. $field_count = 0;
  335. if (is_array($row['fields'])) foreach ($row['fields'] as $field) {
  336. if ($field['deprecated'] == "true") {
  337. //skip this row
  338. }
  339. else {
  340. if ($field_count > 0 ) { $sql .= ",\n"; }
  341. if (is_array($field['name'])) {
  342. $sql .= $field['name']['text'] . " ";
  343. }
  344. else {
  345. $sql .= $field['name'] . " ";
  346. }
  347. if (is_array($field['type'])) {
  348. $sql .= $field['type'][$db_type];
  349. }
  350. else {
  351. $sql .= $field['type'];
  352. }
  353. if ($field['key']['type'] == "primary") {
  354. $sql .= " PRIMARY KEY";
  355. }
  356. $field_count++;
  357. }
  358. }
  359. $sql .= ");\n\n";
  360. return $sql;
  361. }
  362. }
  363. }
  364. }
  365. //database insert
  366. private function db_insert_into ($apps, $db_type, $table) {
  367. global $db_name;
  368. foreach ($apps as $x => &$app) {
  369. foreach ($app['db'] as $y => $row) {
  370. if ($row['table']['name'] == $table) {
  371. $sql = "INSERT INTO " . $row['table']['name'] . " (";
  372. $field_count = 0;
  373. foreach ($row['fields'] as $field) {
  374. if ($field['deprecated'] == "true") {
  375. //skip this field
  376. }
  377. else {
  378. if ($field_count > 0 ) { $sql .= ","; }
  379. if (is_array($field['name'])) {
  380. $sql .= $field['name']['text'];
  381. }
  382. else {
  383. $sql .= $field['name'];
  384. }
  385. $field_count++;
  386. }
  387. }
  388. $sql .= ")\n";
  389. $sql .= "SELECT ";
  390. $field_count = 0;
  391. foreach ($row['fields'] as $field) {
  392. if ($field['deprecated'] == "true") {
  393. //skip this field
  394. }
  395. else {
  396. if ($field_count > 0 ) { $sql .= ","; }
  397. if (is_array($field['name'])) {
  398. if ($field['exists'] == "false") {
  399. if (is_array($field['name']['deprecated'])) {
  400. $found = false;
  401. foreach ($field['name']['deprecated'] as $row) {
  402. if ($this->db_column_exists ($db_type, $db_name, 'tmp_'.$table, $row)) {
  403. $sql .= $row;
  404. $found = true;
  405. break;
  406. }
  407. }
  408. if (!$found) { $sql .= "''"; }
  409. }
  410. else {
  411. if ($this->db_column_exists ($db_type, $db_name, 'tmp_'.$table, $field['name']['deprecated'])) {
  412. $sql .= $field['name']['deprecated'];
  413. }
  414. else {
  415. $sql .= "''";
  416. }
  417. }
  418. }
  419. else {
  420. $sql .= $field['name']['text'];
  421. }
  422. }
  423. else {
  424. $sql .= $field['name'];
  425. }
  426. $field_count++;
  427. }
  428. }
  429. $sql .= " FROM tmp_".$table.";\n\n";
  430. return $sql;
  431. }
  432. }
  433. }
  434. }
  435. //datatase schema
  436. public function schema ($format = '') {
  437. //set the global variable
  438. global $db, $upgrade_data_types, $text,$output_format;
  439. if ($format=='') $format = $output_format;
  440. //get the db variables
  441. require_once "resources/classes/config.php";
  442. $config = new config;
  443. $config_exists = $config->exists();
  444. $config_path = $config->find();
  445. $config->get();
  446. $db_type = $config->db_type;
  447. $db_name = $config->db_name;
  448. $db_username = $config->db_username;
  449. $db_password = $config->db_password;
  450. $db_host = $config->db_host;
  451. $db_path = $config->db_path;
  452. $db_port = $config->db_port;
  453. //get the PROJECT PATH
  454. include "root.php";
  455. //add multi-lingual support
  456. if (!isset($text)) {
  457. $language = new text;
  458. $text = $language->get(null,'core/upgrade');
  459. }
  460. //PHP PDO check if table or column exists
  461. //check if table exists
  462. // SELECT * FROM sqlite_master WHERE type='table' AND name='v_cdr'
  463. //check if column exists
  464. // SELECT * FROM sqlite_master WHERE type='table' AND name='v_cdr' AND sql LIKE '%caller_id_name TEXT,%'
  465. //aditional information
  466. // http://www.sqlite.org/faq.html#q9
  467. //postgresql
  468. //list all tables in the database
  469. // SELECT table_name FROM pg_tables WHERE schemaname='public';
  470. //check if table exists
  471. // SELECT * FROM pg_tables WHERE schemaname='public' AND table_name = 'v_groups'
  472. //check if column exists
  473. // SELECT attname FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = 'v_cdr') AND attname = 'caller_id_name';
  474. //mysql
  475. //list all tables in the database
  476. // SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = 'fusionpbx'
  477. //check if table exists
  478. // SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = 'fusionpbx' AND TABLE_NAME = 'v_groups'
  479. //check if column exists
  480. // SELECT * FROM information_schema.COLUMNS where TABLE_SCHEMA = 'fusionpbx' AND TABLE_NAME = 'v_cdr' AND COLUMN_NAME = 'context'
  481. //oracle
  482. //check if table exists
  483. // SELECT TABLE_NAME FROM ALL_TABLES
  484. //get the $apps array from the installed apps from the core and mod directories
  485. $config_list = glob($_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/*/*/app_config.php");
  486. $x=0;
  487. foreach ($config_list as &$config_path) {
  488. include($config_path);
  489. $x++;
  490. }
  491. //update the app db array add exists true or false
  492. $sql = '';
  493. foreach ($apps as $x => &$app) {
  494. if (isset($app['db'])) foreach ($app['db'] as $y => &$row) {
  495. if (isset($row['table']['name'])) {
  496. if (is_array($row['table']['name'])) {
  497. $table_name = $row['table']['name']['text'];
  498. }
  499. else {
  500. $table_name = $row['table']['name'];
  501. }
  502. }
  503. else {
  504. //old array syntax
  505. if (is_array($row['table'])) {
  506. $table_name = $row['table']['text'];
  507. }
  508. else {
  509. $table_name = $row['table'];
  510. }
  511. }
  512. if (strlen($table_name) > 0) {
  513. //check if the table exists
  514. if ($this->db_table_exists($db_type, $db_name, $table_name)) {
  515. $apps[$x]['db'][$y]['exists'] = 'true';
  516. }
  517. else {
  518. $apps[$x]['db'][$y]['exists'] = 'false';
  519. }
  520. //check if the column exists
  521. foreach ($row['fields'] as $z => $field) {
  522. if ($field['deprecated'] == "true") {
  523. //skip this field
  524. }
  525. else {
  526. if (is_array($field['name'])) {
  527. $field_name = $field['name']['text'];
  528. }
  529. else {
  530. $field_name = $field['name'];
  531. }
  532. if (strlen($field_name) > 0) {
  533. if ($this->db_column_exists ($db_type, $db_name, $table_name, $field_name)) {
  534. //found
  535. $apps[$x]['db'][$y]['fields'][$z]['exists'] = 'true';
  536. }
  537. else {
  538. //not found
  539. $apps[$x]['db'][$y]['fields'][$z]['exists'] = 'false';
  540. }
  541. }
  542. unset($field_name);
  543. }
  544. }
  545. unset($table_name);
  546. }
  547. }
  548. }
  549. //prepare the variables
  550. $sql_update = '';
  551. $var_uuid = $_GET["id"];
  552. //add missing tables and fields
  553. foreach ($apps as $x => &$app) {
  554. if (isset($app['db'])) foreach ($app['db'] as $y => &$row) {
  555. if (is_array($row['table']['name'])) {
  556. $table_name = $row['table']['name']['text'];
  557. if ($this->db_table_exists($db_type, $db_name, $row['table']['name']['deprecated'])) {
  558. $row['exists'] = "false"; //testing
  559. if ($db_type == "pgsql") {
  560. $sql_update .= "ALTER TABLE ".$row['table']['name']['deprecated']." RENAME TO ".$row['table']['name']['text'].";\n";
  561. }
  562. if ($db_type == "mysql") {
  563. $sql_update .= "RENAME TABLE ".$row['table']['name']['deprecated']." TO ".$row['table']['name']['text'].";\n";
  564. }
  565. if ($db_type == "sqlite") {
  566. $sql_update .= "ALTER TABLE ".$row['table']['name']['deprecated']." RENAME TO ".$row['table']['name']['text'].";\n";
  567. }
  568. }
  569. else {
  570. if ($this->db_table_exists($db_type, $db_name, $row['table']['name']['text'])) {
  571. $row['exists'] = "true";
  572. }
  573. else {
  574. $row['exists'] = "false";
  575. $sql_update .= $this->db_create_table($apps, $db_type, $row['table']['name']['text']);
  576. }
  577. }
  578. }
  579. else {
  580. $table_name = $row['table']['name'];
  581. }
  582. //check if the table exists
  583. if ($row['exists'] == "true") {
  584. if (count($row['fields']) > 0) {
  585. foreach ($row['fields'] as $z => $field) {
  586. if ($field['deprecated'] == "true") {
  587. //skip this field
  588. }
  589. else {
  590. //get the data type
  591. if (is_array($field['type'])) {
  592. $field_type = $field['type'][$db_type];
  593. }
  594. else {
  595. $field_type = $field['type'];
  596. }
  597. //get the field name
  598. if (is_array($field['name'])) {
  599. $field_name = $field['name']['text'];
  600. if (!$this->db_column_exists ($db_type, $db_name, $table_name, $field_name)) {
  601. $field['exists'] == "false";
  602. }
  603. }
  604. else {
  605. $field_name = $field['name'];
  606. }
  607. //add or rename fields
  608. if (isset($field['name']['deprecated']) && $this->db_column_exists ($db_type, $db_name, $table_name, $field['name']['deprecated'])) {
  609. if ($db_type == "pgsql") {
  610. $sql_update .= "ALTER TABLE ".$table_name." RENAME COLUMN ".$field['name']['deprecated']." to ".$field['name']['text'].";\n";
  611. }
  612. if ($db_type == "mysql") {
  613. $field_type = str_replace("AUTO_INCREMENT PRIMARY KEY", "", $field_type);
  614. $sql_update .= "ALTER TABLE ".$table_name." CHANGE ".$field['name']['deprecated']." ".$field['name']['text']." ".$field_type.";\n";
  615. }
  616. if ($db_type == "sqlite") {
  617. //a change has been made to the field name
  618. $apps[$x]['db'][$y]['rebuild'] = 'true';
  619. }
  620. }
  621. else {
  622. //find missing fields and add them
  623. if ($field['exists'] == "false") {
  624. $sql_update .= "ALTER TABLE ".$table_name." ADD ".$field_name." ".$field_type.";\n";
  625. }
  626. }
  627. //change the data type if it has been changed
  628. //if the data type in the app db array is different than the type in the database then change the data type
  629. if ($upgrade_data_types) {
  630. $db_field_type = $this->db_column_data_type ($db_type, $db_name, $table_name, $field_name);
  631. $field_type_array = explode("(", $field_type);
  632. $field_type = $field_type_array[0];
  633. if (trim($db_field_type) != trim($field_type) && strlen($db_field_type) > 0) {
  634. if ($db_type == "pgsql") {
  635. if (strtolower($field_type) == "uuid") {
  636. $sql_update .= "ALTER TABLE ".$table_name." ALTER COLUMN ".$field_name." TYPE uuid USING\n";
  637. $sql_update .= "CAST(regexp_replace(".$field_name.", '([A-Z0-9]{4})([A-Z0-9]{12})', E'\\1-\\2')\n";
  638. $sql_update .= "AS uuid);\n";
  639. }
  640. else {
  641. if ($db_field_type == "integer" && strtolower($field_type) == "serial") {
  642. //field type has not changed
  643. }
  644. else if ($db_field_type == "timestamp without time zone" && strtolower($field_type) == "timestamp") {
  645. //field type has not changed
  646. }
  647. else if ($db_field_type == "timestamp without time zone" && strtolower($field_type) == "datetime") {
  648. //field type has not changed
  649. }
  650. else if ($db_field_type == "timestamp with time zone" && strtolower($field_type) == "timestamptz") {
  651. //field type has not changed
  652. }
  653. else if ($db_field_type == "integer" && strtolower($field_type) == "numeric") {
  654. //field type has not changed
  655. }
  656. else if ($db_field_type == "character" && strtolower($field_type) == "char") {
  657. //field type has not changed
  658. }
  659. else {
  660. switch ($field_type) {
  661. case 'timestamp':
  662. case 'datetime':
  663. $sql_update .= "ALTER TABLE ".$table_name." ALTER COLUMN ".$field_name." TYPE ".$field_type." USING ".$field_name."::timestamp without time zone;\n";
  664. break;
  665. case 'timestamptz':
  666. $sql_update .= "ALTER TABLE ".$table_name." ALTER COLUMN ".$field_name." TYPE ".$field_type." USING ".$field_name."::timestamp with time zone;\n";
  667. break;
  668. default:
  669. //$sql_update .= "-- $db_type, $db_name, $table_name, $field_name ".db_column_data_type ($db_type, $db_name, $table_name, $field_name)."<br>";
  670. $sql_update .= "ALTER TABLE ".$table_name." ALTER COLUMN ".$field_name." TYPE ".$field_type.";\n";
  671. }
  672. }
  673. }
  674. }
  675. if ($db_type == "mysql") {
  676. $type = explode("(", $db_field_type);
  677. if ($type[0] == $field_type) {
  678. //do nothing
  679. }
  680. else if ($field_type == "numeric" && $type[0] == "decimal") {
  681. //do nothing
  682. }
  683. else {
  684. $sql_update .= "ALTER TABLE ".$table_name." modify ".$field_name." ".$field_type.";\n";
  685. }
  686. unset($type);
  687. }
  688. if ($db_type == "sqlite") {
  689. //a change has been made to the field type
  690. $apps[$x]['db'][$y]['rebuild'] = 'true';
  691. }
  692. }
  693. }
  694. }
  695. }
  696. unset($column_array);
  697. }
  698. }
  699. else {
  700. //create table
  701. if (!is_array($row['table']['name'])) {
  702. $sql_update .= $this->db_create_table($apps, $db_type, $row['table']['name']);
  703. }
  704. }
  705. }
  706. }
  707. //rebuild and populate the table
  708. foreach ($apps as $x => &$app) {
  709. if (isset($app['db'])) foreach ($app['db'] as $y => &$row) {
  710. if (is_array($row['table']['name'])) {
  711. $table_name = $row['table']['name']['text'];
  712. }
  713. else {
  714. $table_name = $row['table']['name'];
  715. }
  716. if ($row['rebuild'] == "true") {
  717. if ($db_type == "sqlite") {
  718. //start the transaction
  719. //$sql_update .= "BEGIN TRANSACTION;\n";
  720. //rename the table
  721. $sql_update .= "ALTER TABLE ".$table_name." RENAME TO tmp_".$table_name.";\n";
  722. //create the table
  723. $sql_update .= $this->db_create_table($apps, $db_type, $table_name);
  724. //insert the data into the new table
  725. $sql_update .= $this->db_insert_into($apps, $db_type, $table_name);
  726. //drop the old table
  727. $sql_update .= "DROP TABLE tmp_".$table_name.";\n";
  728. //commit the transaction
  729. //$sql_update .= "COMMIT;\n";
  730. }
  731. }
  732. }
  733. }
  734. // initialize response variable
  735. $response = '';
  736. //display results as html
  737. if ($format == "html") {
  738. //show the database type
  739. $response .= "<strong>".$text['header-database_type'].": ".$db_type. "</strong><br /><br />";
  740. //start the table
  741. $response .= "<table width='100%' border='0' cellpadding='20' cellspacing='0'>\n";
  742. //show the changes
  743. if (strlen($sql_update) > 0) {
  744. $response .= "<tr>\n";
  745. $response .= "<td class='row_style1' colspan='3'>\n";
  746. $response .= "<br />\n";
  747. $response .= "<strong>".$text['label-sql_changes'].":</strong><br />\n";
  748. $response .= "<pre>\n";
  749. $response .= $sql_update;
  750. $response .= "</pre>\n";
  751. $response .= "<br />\n";
  752. $response .= "</td>\n";
  753. $response .= "</tr>\n";
  754. }
  755. //list all tables
  756. $response .= "<tr>\n";
  757. $response .= "<th>".$text['label-table']."</th>\n";
  758. $response .= "<th>".$text['label-exists']."</th>\n";
  759. $response .= "<th>".$text['label-details']."</th>\n";
  760. $response .= "<tr>\n";
  761. //build the html while looping through the app db array
  762. $sql = '';
  763. foreach ($apps as &$app) {
  764. if (isset($app['db'])) foreach ($app['db'] as $row) {
  765. if (is_array($row['table']['name'])) {
  766. $table_name = $row['table']['name']['text'];
  767. }
  768. else {
  769. $table_name = $row['table']['name'];
  770. }
  771. $response .= "<tr>\n";
  772. //check if the table exists
  773. if ($row['exists'] == "true") {
  774. $response .= "<td valign='top' class='row_style1'>".$table_name."</td>\n";
  775. $response .= "<td valign='top' class='vncell' style='padding-top: 3px;'>".$text['option-true']."</td>\n";
  776. if (count($row['fields']) > 0) {
  777. $response .= "<td class='row_style1'>\n";
  778. //show the list of columns
  779. $response .= "<table border='0' cellpadding='10' cellspacing='0'>\n";
  780. $response .= "<tr>\n";
  781. $response .= "<th>".$text['label-name']."</th>\n";
  782. $response .= "<th>".$text['label-type']."</th>\n";
  783. $response .= "<th>".$text['label-exists']."</th>\n";
  784. $response .= "</tr>\n";
  785. foreach ($row['fields'] as $field) {
  786. if ($field['deprecated'] == "true") {
  787. //skip this field
  788. }
  789. else {
  790. if (is_array($field['name'])) {
  791. $field_name = $field['name']['text'];
  792. }
  793. else {
  794. $field_name = $field['name'];
  795. }
  796. if (is_array($field['type'])) {
  797. $field_type = $field['type'][$db_type];
  798. }
  799. else {
  800. $field_type = $field['type'];
  801. }
  802. $response .= "<tr>\n";
  803. $response .= "<td class='row_style1' width='200'>".$field_name."</td>\n";
  804. $response .= "<td class='row_style1'>".$field_type."</td>\n";
  805. if ($field['exists'] == "true") {
  806. $response .= "<td class='row_style0' style=''>".$text['option-true']."</td>\n";
  807. $response .= "<td>&nbsp;</td>\n";
  808. }
  809. else {
  810. $response .= "<td class='row_style1' style='background-color:#444444;color:#CCCCCC;'>".$text['option-false']."</td>\n";
  811. $response .= "<td>&nbsp;</td>\n";
  812. }
  813. $response .= "</tr>\n";
  814. }
  815. }
  816. unset($column_array);
  817. $response .= " </table>\n";
  818. $response .= "</td>\n";
  819. }
  820. }
  821. else {
  822. $response .= "<td valign='top' class='row_style1'>$table_name</td>\n";
  823. $response .= "<td valign='top' class='row_style1' style='background-color:#444444;color:#CCCCCC;'><strong>".$text['label-exists']."</strong><br />".$text['option-false']."</td>\n";
  824. $response .= "<td valign='top' class='row_style1'>&nbsp;</td>\n";
  825. }
  826. $response .= "</tr>\n";
  827. }
  828. }
  829. unset ($prep_statement);
  830. //end the list of tables
  831. $response .= "</table>\n";
  832. $response .= "<br />\n";
  833. }
  834. //loop line by line through all the lines of sql code
  835. $x = 0;
  836. if (strlen($sql_update) == 0 && $format == "text") {
  837. $response .= " ".$text['label-schema'].": ".$text['label-no_change']."\n";
  838. }
  839. else {
  840. if ($format == "text") {
  841. $response .= " ".$text['label-schema']."\n";
  842. }
  843. //$this->db->beginTransaction();
  844. $update_array = explode(";", $sql_update);
  845. foreach($update_array as $sql) {
  846. if (strlen(trim($sql))) {
  847. try {
  848. $this->db->query(trim($sql));
  849. if ($format == "text") {
  850. $response .= " $sql\n";
  851. }
  852. }
  853. catch (PDOException $error) {
  854. $response .= " error: " . $error->getMessage() . " sql: $sql<br/>";
  855. }
  856. }
  857. }
  858. //$this->db->commit();
  859. $response .= "\n";
  860. unset ($file_contents, $sql_update, $sql);
  861. }
  862. //handle response
  863. //if ($output == "echo") {
  864. // echo $response;
  865. //}
  866. //else if ($output == "return") {
  867. return $response;
  868. //}
  869. } //end function
  870. }
  871. }
  872. //example use
  873. //require_once "resources/classes/schema.php";
  874. //$obj = new schema;
  875. //$obj->db_type = $db_type;
  876. //$obj->schema();
  877. //$result_array = $schema->obj['sql'];
  878. //print_r($result_array);
  879. ?>