The branch, master has been updated via 8a011f77b8c75edb5f5461a69de39bbea66596c5 (commit) via f84659efcba18bf33e0d59187044d3b4ab285bfb (commit) via 1c20d31e65f5862f429df22b14d2bd33247bd2ed (commit) via ab03dc8d5ce6ab25bf39726bbe894987002533b7 (commit) via 2ea03801ebf3c2862f25f5a79a5e93c33e682757 (commit) via dd809980808b5707cf72223009171ab0b320fb2a (commit) via 8a827e52614960f90c4d741ee6f89123424363c4 (commit) via 13abea596a0c951c78e3161b95e38d99cb2f615d (commit) via 5fb5678a50f155041edd5a3fad6c93ff6e1df3ee (commit) via 75623e5066071c91b12e5b2e565dd9907e790180 (commit) via 27fe8e4658cc8a79cfce17ac359dfdf7b41ba98b (commit) via afcf1e6bbee7c7a1720df0e61b2ef64a925b8f0b (commit) via d579653dc5fd6af2dac343b8b750806354dc405a (commit) via 4a4ddeadcf85f11edf580894d754ade80cb975be (commit) via 381ba1be0f921788bfd1f99baae0ff149cf239bb (commit) via d6c630c64e279e85cc9b2062e3b499c1567ded7e (commit) via 36ba514c5109c679fcee0e4139b2411a4c5803ce (commit) via ae877a1de6a6cfe36beeb139456ea8c45277822a (commit) via 03b1bbf9b3910fe3ffe9539d639bf300ff4c51da (commit) via b95a14c0de93965cd5eb29edcedae60d7cf97e8b (commit) via 224abbaf5efd89c7fecf4b2c01ef45297a4a444b (commit) via 1cdf881f42a49988300b898caf7e16f2b6c5fdc3 (commit) via 03d37b45f1ec22cfc9a7c46ee9d9f549980d10bb (commit) via 2a5a6e39b1eb888bd01d3c00af69b2b4a77dccbf (commit) via 821b8b134e27813e1eb686c0c8948bacbbfea131 (commit) via 6f750d73797e1034804956ce90a6c00e1e17e943 (commit) via 2c42e1bccba5b848bca81de475343d2876d5e029 (commit) via bdf033115b18c271c3398b8c60ba372a92d6f4ac (commit) via a7e3c0475cacadbc8ca6e477bd4d733f510c5d36 (commit) via 14b26e314a159c4b282e02940d3c44563f302251 (commit) via 9595dce3b824ab5c35706d470b4d34ce355bab51 (commit) via cc4ace1f22921439d1fd7ec6cb23316c76d53bd6 (commit) via ac3909d990a2a4e7f65e1aecdd2a25dc6d99d5cf (commit) via 5a884f2f4dd655d32ac338b2b210bd867e546847 (commit) via 4adc0c15cd1d03c51b88bbd792aea3bb1e57ed09 (commit) via 2ca3d4d8f444d5dc9f4ea632015fbfadbb9481c4 (commit) via 6fc9576f3ed0da066365eb8dfb6b804d04748c4e (commit) via 45399cbadd638b30cea9473e834201b963afa31d (commit) via f9c29173bfb080910e15ac46c6a34f8be8aac51e (commit) via 9fb8619f2ace178e5d4d4dc055ce7e5358b9bcd8 (commit) via 459eeb12300e8c10f750bab57320634406db2c03 (commit) via 79c6f847fd9b50c8e25361a482b29ee798c3fb7d (commit) via 07cee82af681ca5602c704e438eff39c83825db3 (commit) via 1ca552a8e14306b723019b2268c8aab7c20bb06c (commit) via cd41a8dc281561d00fe66237fe335d944582ae07 (commit) via 39db171819a65a49699180705b2ecae2968b4c2c (commit) via c62004a8c91cf9c7f704da0e3899e6595d6ea1f2 (commit) via 737fb9df271d723111b82dbfcbec74f168275f71 (commit) via ba9924054be621d2bad7d977eb05180c01e31b8c (commit) via 188c7b8d38fdffa19ed0cefe8ca0af047495adba (commit) via 1ef5f8564e1013ed737b7491aa6fe806612dea8d (commit) via cba214aee41a6da0e24b559d32fbb15a1d6bbb64 (commit) via dd217e8dffe87efeb6f01a9ee4210c3c3f6ab394 (commit) via 7660295dca0850f3918abcda3559db5a86c73ab6 (commit) via 9befa3965e3b9e82532a1bc43e199e269f73a925 (commit) via 8dc2149272811636fcb90f809c936a8b068356eb (commit) via 0e9f6247e4d2d554b5eb59f637e6b9edaed5cda4 (commit) via fc838dd0cbd085e7d09c40b0b89e038671cfff97 (commit) via 589eef328048df3e74e3a713c8de06e304688c96 (commit) via d38b380c3205b29fe7d5e89f1502aac67f3c2179 (commit) via 3805338674202055aa7724e42b23c894b06bd4c0 (commit) via 5d7998984d8dbf6d2065d06bb9c93668a852ec4a (commit) via 7d125e01a822a26571e4938eb1e97beac6056a73 (commit) via 14e6af7d8aeb05ea32ee7defa9aee335041bd3cc (commit) via 793468f14075b64d8c4f992b6fe2b1d3bcd3341b (commit) from d5912b19e4d2083d7703c48aa0320a565f24a5da (commit)
- Log ----------------------------------------------------------------- commit 8a011f77b8c75edb5f5461a69de39bbea66596c5 Author: Michal Čihař mcihar@novell.com Date: Mon Aug 23 10:55:57 2010 +0200
Better name for schema export script.
commit f84659efcba18bf33e0d59187044d3b4ab285bfb Author: Michal Čihař mcihar@novell.com Date: Mon Aug 23 10:55:19 2010 +0200
Better file name for schema edit page.
commit 1c20d31e65f5862f429df22b14d2bd33247bd2ed Author: Michal Čihař mcihar@novell.com Date: Mon Aug 23 10:52:46 2010 +0200
No upper case in box title.
commit ab03dc8d5ce6ab25bf39726bbe894987002533b7 Author: Michal Čihař mcihar@novell.com Date: Mon Aug 23 10:50:17 2010 +0200
Whitespace cleanup.
commit 2ea03801ebf3c2862f25f5a79a5e93c33e682757 Author: Michal Čihař mcihar@novell.com Date: Mon Aug 23 10:33:05 2010 +0200
Better size of Dia export.
commit dd809980808b5707cf72223009171ab0b320fb2a Merge: d5912b19e4d2083d7703c48aa0320a565f24a5da 8a827e52614960f90c4d741ee6f89123424363c4 Author: Michal Čihař mcihar@novell.com Date: Mon Aug 23 10:21:22 2010 +0200
Merge remote branch 'adnan/export_branch'
commit 8a827e52614960f90c4d741ee6f89123424363c4 Author: Adnan hiddenpearls@gmail.com Date: Fri Aug 20 12:13:30 2010 +0500
TCPDF: removed ob_get_contents() [was added for debugging]
commit 13abea596a0c951c78e3161b95e38d99cb2f615d Merge: 5fb5678a50f155041edd5a3fad6c93ff6e1df3ee a590931896df99fde96f37d8e77a45eeb254749c Author: Adnan hiddenpearls@gmail.com Date: Fri Aug 20 11:34:36 2010 +0500
Merge remote branch 'origin/master' into export_branch
commit 5fb5678a50f155041edd5a3fad6c93ff6e1df3ee Author: Adnan hiddenpearls@gmail.com Date: Fri Aug 20 11:11:51 2010 +0500
DIA Relation Schema: scale diagram fix
commit 75623e5066071c91b12e5b2e565dd9907e790180 Author: Adnan hiddenpearls@gmail.com Date: Fri Aug 20 11:09:37 2010 +0500
EPS Relation Schema: missing lines fix
commit 27fe8e4658cc8a79cfce17ac359dfdf7b41ba98b Author: Adnan hiddenpearls@gmail.com Date: Thu Aug 19 17:32:43 2010 +0500
Indenation fix in functions.js
commit afcf1e6bbee7c7a1720df0e61b2ef64a925b8f0b Author: Adnan hiddenpearls@gmail.com Date: Thu Aug 19 17:31:01 2010 +0500
Automatic Foreign/Internal Layout fix
commit d579653dc5fd6af2dac343b8b750806354dc405a Author: Adnan hiddenpearls@gmail.com Date: Wed Aug 18 19:31:29 2010 +0500
Removed debug commented code
commit 4a4ddeadcf85f11edf580894d754ade80cb975be Author: Adnan hiddenpearls@gmail.com Date: Wed Aug 18 18:05:01 2010 +0500
Fixed mime types and improve comments
commit 381ba1be0f921788bfd1f99baae0ff149cf239bb Merge: d6c630c64e279e85cc9b2062e3b499c1567ded7e 1f248cc2549a2f5c1a47d209f2062ccb1fa4682c Author: Adnan hiddenpearls@gmail.com Date: Wed Aug 18 17:03:35 2010 +0500
Merge remote branch 'origin/master' into export_branch
commit d6c630c64e279e85cc9b2062e3b499c1567ded7e Author: Adnan hiddenpearls@gmail.com Date: Wed Aug 18 15:58:24 2010 +0500
Proper Error handling of Schema
commit 36ba514c5109c679fcee0e4139b2411a4c5803ce Author: Adnan hiddenpearls@gmail.com Date: Wed Aug 18 15:55:06 2010 +0500
Eval security issue & Indentation fixed
commit ae877a1de6a6cfe36beeb139456ea8c45277822a Author: Adnan hiddenpearls@gmail.com Date: Wed Aug 18 12:27:02 2010 +0500
UserInterface show/hide Schema Generation Options Available
commit 03b1bbf9b3910fe3ffe9539d639bf300ff4c51da Author: Adnan hiddenpearls@gmail.com Date: Wed Aug 18 12:22:56 2010 +0500
User Interface change in Schema Generation Options Box
commit b95a14c0de93965cd5eb29edcedae60d7cf97e8b Author: Adnan hiddenpearls@gmail.com Date: Tue Aug 17 22:26:15 2010 +0500
TCPDF: merge conflict fixed
commit 224abbaf5efd89c7fecf4b2c01ef45297a4a444b Author: Adnan hiddenpearls@gmail.com Date: Tue Aug 17 21:02:54 2010 +0500
TCPDF: reverted back from 14b26e3
commit 1cdf881f42a49988300b898caf7e16f2b6c5fdc3 Author: Adnan hiddenpearls@gmail.com Date: Tue Aug 17 20:41:15 2010 +0500
handling headers issue in schema export
commit 03d37b45f1ec22cfc9a7c46ee9d9f549980d10bb Author: Adnan hiddenpearls@gmail.com Date: Tue Aug 17 15:23:06 2010 +0500
Removing previous schema generation code which was duplicating
commit 2a5a6e39b1eb888bd01d3c00af69b2b4a77dccbf Author: Adnan hiddenpearls@gmail.com Date: Mon Aug 16 17:53:30 2010 +0500
EPS Relation Schema Class: adding boundingbox and pages commands
commit 821b8b134e27813e1eb686c0c8948bacbbfea131 Merge: 6f750d73797e1034804956ce90a6c00e1e17e943 b51a217c36b45194f79915992a599338b3bac9ef Author: Adnan hiddenpearls@gmail.com Date: Mon Aug 16 04:52:53 2010 +0500
Merge remote branch 'origin/master' into export_branch
commit 6f750d73797e1034804956ce90a6c00e1e17e943 Author: Adnan hiddenpearls@gmail.com Date: Mon Aug 16 04:49:45 2010 +0500
Visio Relation Schema Class
commit 2c42e1bccba5b848bca81de475343d2876d5e029 Author: Adnan hiddenpearls@gmail.com Date: Sun Aug 15 15:06:26 2010 +0500
EPS Relation Schema Class
commit bdf033115b18c271c3398b8c60ba372a92d6f4ac Merge: a7e3c0475cacadbc8ca6e477bd4d733f510c5d36 887e2be664f04827fe164d724d233598a251bcb9 Author: Adnan hiddenpearls@gmail.com Date: Mon Aug 2 10:46:50 2010 +0500
Merge remote branch 'origin/master' into export_branch
commit a7e3c0475cacadbc8ca6e477bd4d733f510c5d36 Merge: 14b26e314a159c4b282e02940d3c44563f302251 873ad99ed2fa8e5a46f1a92faccb8e163c0f0bc3 Author: Adnan hiddenpearls@gmail.com Date: Thu Jul 22 16:03:50 2010 +0500
Merge Origin: Conflicts in js/functions.js
commit 14b26e314a159c4b282e02940d3c44563f302251 Author: Adnan hiddenpearls@gmail.com Date: Wed Jul 21 16:12:49 2010 +0500
TCPDF Class: Clean output buffer before downloading file
commit 9595dce3b824ab5c35706d470b4d34ce355bab51 Author: Adnan hiddenpearls@gmail.com Date: Wed Jul 21 16:11:08 2010 +0500
PDF + SVG + Dia Schema: Notices Fix + Prompt User for Download Files
commit cc4ace1f22921439d1fd7ec6cb23316c76d53bd6 Author: Adnan hiddenpearls@gmail.com Date: Wed Jul 21 16:08:48 2010 +0500
Export Relation Schema: fixing notices
commit ac3909d990a2a4e7f65e1aecdd2a25dc6d99d5cf Author: Adnan hiddenpearls@gmail.com Date: Tue Jul 20 16:22:50 2010 +0500
TCPDF Class [Tabs removed Commit]: Reverted back
commit 5a884f2f4dd655d32ac338b2b210bd867e546847 Author: Adnan hiddenpearls@gmail.com Date: Thu Jul 15 01:01:16 2010 +0500
export_relation_schema.php: improved documentation
commit 4adc0c15cd1d03c51b88bbd792aea3bb1e57ed09 Author: Adnan hiddenpearls@gmail.com Date: Thu Jul 15 00:59:30 2010 +0500
User Schema + pdf Relation Schema Class: Improved documentation
commit 2ca3d4d8f444d5dc9f4ea632015fbfadbb9481c4 Author: Adnan hiddenpearls@gmail.com Date: Wed Jul 14 22:46:51 2010 +0500
Export Relation Schema Class: Improved documentation + handling requests
commit 6fc9576f3ed0da066365eb8dfb6b804d04748c4e Author: Adnan hiddenpearls@gmail.com Date: Wed Jul 14 20:36:13 2010 +0500
Svg Schema Class: removed global vars + improved documentation
commit 45399cbadd638b30cea9473e834201b963afa31d Author: Adnan hiddenpearls@gmail.com Date: Wed Jul 14 06:10:05 2010 +0500
Dia Schema Class: download fileName added + improved documentation
commit f9c29173bfb080910e15ac46c6a34f8be8aac51e Author: Adnan hiddenpearls@gmail.com Date: Wed Jul 14 02:32:57 2010 +0500
Dia Schem Class: documented + implemented
commit 9fb8619f2ace178e5d4d4dc055ce7e5358b9bcd8 Author: Adnan hiddenpearls@gmail.com Date: Sat Jul 10 15:44:17 2010 +0500
PDF Schema File: Relation_Stats class structured
commit 459eeb12300e8c10f750bab57320634406db2c03 Author: Adnan hiddenpearls@gmail.com Date: Fri Jul 9 15:31:18 2010 +0500
TCPDF Class: tabs removed
commit 79c6f847fd9b50c8e25361a482b29ee798c3fb7d Author: Adnan hiddenpearls@gmail.com Date: Fri Jul 9 15:15:49 2010 +0500
Pdf Schema Class: Reduce global variables + added attributes in Export Relation Schema
commit 07cee82af681ca5602c704e438eff39c83825db3 Author: Adnan hiddenpearls@gmail.com Date: Fri Jul 9 14:39:03 2010 +0500
User Schema Class: big switch into several methods + reduce global variables
commit 1ca552a8e14306b723019b2268c8aab7c20bb06c Author: Adnan hiddenpearls@gmail.com Date: Thu Jul 8 12:23:51 2010 +0500
SVG Schema Class: spaces around = , fixed.
commit cd41a8dc281561d00fe66237fe335d944582ae07 Author: Adnan hiddenpearls@gmail.com Date: Thu Jul 8 12:05:52 2010 +0500
SVG Schema Class
commit 39db171819a65a49699180705b2ecae2968b4c2c Author: Adnan hiddenpearls@gmail.com Date: Sat Jul 3 23:50:13 2010 +0500
because of changes in User Schema etc PDF Schema wasn't working, It is fixed now
commit c62004a8c91cf9c7f704da0e3899e6595d6ea1f2 Merge: 737fb9df271d723111b82dbfcbec74f168275f71 3e9e18aebb5d551f260e178f2f311384c2653b28 Author: Adnan hiddenpearls@gmail.com Date: Sat Jul 3 23:47:15 2010 +0500
Merge remote branch 'origin/master' into export_branch
commit 737fb9df271d723111b82dbfcbec74f168275f71 Merge: ba9924054be621d2bad7d977eb05180c01e31b8c 9e857f9f84591eedf3be50668356411eb52da0fa Author: Adnan hiddenpearls@gmail.com Date: Sat Jul 3 13:54:41 2010 +0500
Merge remote branch 'origin/master' into export_branch
commit ba9924054be621d2bad7d977eb05180c01e31b8c Author: Adnan hiddenpearls@gmail.com Date: Sat Jul 3 13:52:43 2010 +0500
export_relation_schema.php: commenting improved
commit 188c7b8d38fdffa19ed0cefe8ca0af047495adba Author: Adnan hiddenpearls@gmail.com Date: Fri Jul 2 16:31:32 2010 +0500
User_Schema class : removed tabs + commented code + organized structure, Delete listing of schema classes in process relation schema file
commit 1ef5f8564e1013ed737b7491aa6fe806612dea8d Merge: cba214aee41a6da0e24b559d32fbb15a1d6bbb64 7d4c3174f7e28a17fbacab91b67eb7cc1ff4ed0a Author: Adnan hiddenpearls@gmail.com Date: Fri Jul 2 16:23:58 2010 +0500
Merge remote branch 'origin/master' into export_branch
commit cba214aee41a6da0e24b559d32fbb15a1d6bbb64 Author: Adnan hiddenpearls@gmail.com Date: Sat Jun 26 11:16:11 2010 +0500
Export Relation Schema: deleting wrong name files
commit dd217e8dffe87efeb6f01a9ee4210c3c3f6ab394 Author: Adnan hiddenpearls@gmail.com Date: Fri Jun 25 19:14:47 2010 +0500
Export Relation Schema: renaming files + renaming classes according to pear standards
commit 7660295dca0850f3918abcda3559db5a86c73ab6 Author: Adnan hiddenpearls@gmail.com Date: Thu Jun 24 20:39:46 2010 +0500
Schema Classes structure, PDF and SVG
commit 9befa3965e3b9e82532a1bc43e199e269f73a925 Author: Adnan hiddenpearls@gmail.com Date: Thu Jun 24 20:37:39 2010 +0500
Schema Classes structure
commit 8dc2149272811636fcb90f809c936a8b068356eb Merge: 0e9f6247e4d2d554b5eb59f637e6b9edaed5cda4 1be2d538dfae929582b9ff6b4a6bdc643609da9e Author: Adnan hiddenpearls@gmail.com Date: Thu Jun 24 20:32:35 2010 +0500
Merge remote branch 'origin/master' into export_branch
commit 0e9f6247e4d2d554b5eb59f637e6b9edaed5cda4 Author: Adnan hiddenpearls@gmail.com Date: Thu Jun 24 20:26:14 2010 +0500
Revert "schema classes structure"
This reverts commit 589eef328048df3e74e3a713c8de06e304688c96.
commit fc838dd0cbd085e7d09c40b0b89e038671cfff97 Merge: 589eef328048df3e74e3a713c8de06e304688c96 6bb0cef5360aa53ebef4df12dac3f80c4fd60273 Author: Adnan hiddenpearls@gmail.com Date: Thu Jun 24 18:31:54 2010 +0500
Merge remote branch 'origin/master' into export_branch
commit 589eef328048df3e74e3a713c8de06e304688c96 Author: Adnan hiddenpearls@gmail.com Date: Thu Jun 24 18:31:42 2010 +0500
schema classes structure
commit d38b380c3205b29fe7d5e89f1502aac67f3c2179 Merge: 3805338674202055aa7724e42b23c894b06bd4c0 aeb14a271ab439b0f62940049aa07edf1240f46b Author: Adnan hiddenpearls@gmail.com Date: Mon Jun 7 05:01:59 2010 +0500
Merge remote branch 'origin/master' into export_branch
commit 3805338674202055aa7724e42b23c894b06bd4c0 Author: Adnan hiddenpearls@gmail.com Date: Thu Jun 3 17:51:05 2010 +0500
Rename libraries/classes to libraries/schema
commit 5d7998984d8dbf6d2065d06bb9c93668a852ec4a Author: Adnan hiddenpearls@gmail.com Date: Thu Jun 3 17:09:57 2010 +0500
adding classes to libraries dir
commit 7d125e01a822a26571e4938eb1e97beac6056a73 Author: Adnan hiddenpearls@gmail.com Date: Thu Jun 3 17:07:01 2010 +0500
moved classes to libraries directory
commit 14e6af7d8aeb05ea32ee7defa9aee335041bd3cc Author: Adnan hiddenpearls@gmail.com Date: Thu Jun 3 16:01:12 2010 +0500
done
commit 793468f14075b64d8c4f992b6fe2b1d3bcd3341b Author: Adnan hiddenpearls@gmail.com Date: Thu Jun 3 15:28:00 2010 +0500
classes structure
-----------------------------------------------------------------------
Summary of changes: db_operations.php | 10 +- js/functions.js | 48 +- libraries/display_pdf_schema.lib.php | 71 - libraries/schema/Dia_Relation_Schema.class.php | 779 ++++++++++++ libraries/schema/Eps_Relation_Schema.class.php | 858 +++++++++++++ libraries/schema/Export_Relation_Schema.class.php | 223 ++++ libraries/schema/Pdf_Relation_Schema.class.php | 1352 ++++++++++++++++++++ libraries/schema/Svg_Relation_Schema.class.php | 854 +++++++++++++ libraries/schema/User_Schema.class.php | 821 ++++++++++++ libraries/schema/Visio_Relation_Schema.class.php | 599 +++++++++ libraries/tcpdf/tcpdf.php | 3 + pdf_pages.php | 559 -------- pdf_schema.php | 1404 --------------------- schema_edit.php | 140 ++ schema_export.php | 49 + 15 files changed, 5729 insertions(+), 2041 deletions(-) delete mode 100644 libraries/display_pdf_schema.lib.php create mode 100644 libraries/schema/Dia_Relation_Schema.class.php create mode 100644 libraries/schema/Eps_Relation_Schema.class.php create mode 100644 libraries/schema/Export_Relation_Schema.class.php create mode 100644 libraries/schema/Pdf_Relation_Schema.class.php create mode 100644 libraries/schema/Svg_Relation_Schema.class.php create mode 100644 libraries/schema/User_Schema.class.php create mode 100644 libraries/schema/Visio_Relation_Schema.class.php delete mode 100644 pdf_pages.php delete mode 100644 pdf_schema.php create mode 100644 schema_edit.php create mode 100644 schema_export.php
diff --git a/db_operations.php b/db_operations.php index 53a2821..fe4d1cc 100644 --- a/db_operations.php +++ b/db_operations.php @@ -520,15 +520,15 @@ if ($cfgRelation['pdfwork'] && $num_tables > 0) { ?> WHERE db_name = '' . PMA_sqlAddslashes($db) . '''; $test_rs = PMA_query_as_controluser($test_query, null, PMA_DBI_QUERY_STORE);
- if ($test_rs && PMA_DBI_num_rows($test_rs) > 0) { - include('./libraries/display_pdf_schema.lib.php'); - } // end if - echo '<fieldset><a href="pdf_pages.php?' . $url_query . '">'; + /* + * Export Relational Schema View + */ + echo '<fieldset><a href="schema_edit.php?' . $url_query . '">'; if ($cfg['PropertiesIconic']) { echo '<img class="icon" src="' . $pmaThemeImage . 'b_edit.png"' .' alt="" width="16" height="16" />'; } - echo __('Edit PDF Pages') . '</a></fieldset>'; + echo __('Export Relational Schema View') . '</a></fieldset>'; } // end if
/** diff --git a/js/functions.js b/js/functions.js index 75ffee5..9702f3a 100644 --- a/js/functions.js +++ b/js/functions.js @@ -1436,8 +1436,11 @@ function refreshDragOption(e) { function refreshLayout() { var elm = $('#pdflayout') var orientation = $('#orientation_opt').val(); - var paper = $('#paper_opt').val(); - + if($('#paper_opt').length==1){ + var paper = $('#paper_opt').val(); + }else{ + var paper = 'A4'; + } if (orientation == 'P') { posa = 'x'; posb = 'y'; @@ -1687,6 +1690,47 @@ $(document).ready(function(){ insertQuery(evt.target.id); return false; }); + + $("#export_type").change(function(){ + if($("#export_type").val()=='svg'){ + $("#show_grid_opt").attr("disabled","disabled"); + $("#orientation_opt").attr("disabled","disabled"); + $("#with_doc").attr("disabled","disabled"); + $("#show_table_dim_opt").removeAttr("disabled"); + $("#all_table_same_wide").removeAttr("disabled"); + $("#paper_opt").removeAttr("disabled","disabled"); + $("#show_color_opt").removeAttr("disabled","disabled"); + //$(this).css("background-color","yellow"); + }else if($("#export_type").val()=='dia'){ + $("#show_grid_opt").attr("disabled","disabled"); + $("#with_doc").attr("disabled","disabled"); + $("#show_table_dim_opt").attr("disabled","disabled"); + $("#all_table_same_wide").attr("disabled","disabled"); + $("#paper_opt").removeAttr("disabled","disabled"); + $("#show_color_opt").removeAttr("disabled","disabled"); + $("#orientation_opt").removeAttr("disabled","disabled"); + }else if($("#export_type").val()=='eps'){ + $("#show_grid_opt").attr("disabled","disabled"); + $("#orientation_opt").removeAttr("disabled"); + $("#with_doc").attr("disabled","disabled"); + $("#show_table_dim_opt").attr("disabled","disabled"); + $("#all_table_same_wide").attr("disabled","disabled"); + $("#paper_opt").attr("disabled","disabled"); + $("#show_color_opt").attr("disabled","disabled"); + + }else if($("#export_type").val()=='pdf'){ + $("#show_grid_opt").removeAttr("disabled"); + $("#orientation_opt").removeAttr("disabled"); + $("#with_doc").removeAttr("disabled","disabled"); + $("#show_table_dim_opt").removeAttr("disabled","disabled"); + $("#all_table_same_wide").removeAttr("disabled","disabled"); + $("#paper_opt").removeAttr("disabled","disabled"); + $("#show_color_opt").removeAttr("disabled","disabled"); + }else{ + // nothing + } + }); + $('#sqlquery').focus(); if ($('#input_username')) { if ($('#input_username').val() == '') { diff --git a/libraries/display_pdf_schema.lib.php b/libraries/display_pdf_schema.lib.php deleted file mode 100644 index ad12fc3..0000000 --- a/libraries/display_pdf_schema.lib.php +++ /dev/null @@ -1,71 +0,0 @@ -<!-- PDF schema --> -<form method="post" action="pdf_schema.php"> -<fieldset> - <legend> - <?php - echo PMA_generate_common_hidden_inputs($db); - if ($cfg['PropertiesIconic']) { - echo '<img class="icon" src="' . $pmaThemeImage . 'b_view.png"' - .' alt="" width="16" height="16" />'; - } - echo __('Display PDF schema'); - ?>: - </legend> - <?php - if (isset($test_rs)) { - ?> - <label for="pdf_page_number_opt"><?php echo __('Page number:'); ?></label> - <select name="pdf_page_number" id="pdf_page_number_opt"> - <?php - while ($pages = @PMA_DBI_fetch_assoc($test_rs)) { - echo ' <option value="' . $pages['page_nr'] . '">' - . $pages['page_nr'] . ': ' . htmlspecialchars($pages['page_descr']) . '</option>' . "\n"; - } // end while - PMA_DBI_free_result($test_rs); - unset($test_rs); - ?> - </select><br /> - <?php } else { ?> - <input type="hidden" name="pdf_page_number" value="<?php echo htmlspecialchars($chpage); ?>" /> - <?php } ?> - - <input type="checkbox" name="show_grid" id="show_grid_opt" /> - <label for="show_grid_opt"><?php echo __('Show grid'); ?></label><br /> - <input type="checkbox" name="show_color" id="show_color_opt" - checked="checked" /> - <label for="show_color_opt"><?php echo __('Show color'); ?></label><br /> - <input type="checkbox" name="show_table_dimension" id="show_table_dim_opt" /> - <label for="show_table_dim_opt"><?php echo __('Show dimension of tables'); ?> - </label><br /> - <input type="checkbox" name="all_tab_same_wide" id="all_tab_same_wide" /> - <label for="all_tab_same_wide"><?php echo __('Display all tables with the same width'); ?> - </label><br /> - <input type="checkbox" name="with_doc" id="with_doc" checked="checked" /> - <label for="with_doc"><?php echo __('Data Dictionary'); ?></label><br /> - <input type="checkbox" name="show_keys" id="show_keys" /> - <label for="show_keys"><?php echo __('Only show keys'); ?></label><br /> - - <label for="orientation_opt"><?php echo __('Data Dictionary Format'); ?></label> - <select name="orientation" id="orientation_opt"> - <option value="L"><?php echo __('Landscape');?></option> - <option value="P"><?php echo __('Portrait');?></option> - </select><br /> - - <label for="paper_opt"><?php echo __('Paper size'); ?></label> - <select name="paper" id="paper_opt"> - <?php - foreach ($cfg['PDFPageSizes'] AS $key => $val) { - echo '<option value="' . $val . '"'; - if ($val == $cfg['PDFDefaultPageSize']) { - echo ' selected="selected"'; - } - echo ' >' . $val . '</option>' . "\n"; - } - ?> - </select> -</fieldset> -<fieldset class="tblFooters"> - <input type="submit" value="<?php echo __('Go'); ?>" /> -</fieldset> -</form> - diff --git a/libraries/schema/Dia_Relation_Schema.class.php b/libraries/schema/Dia_Relation_Schema.class.php new file mode 100644 index 0000000..6b8affa --- /dev/null +++ b/libraries/schema/Dia_Relation_Schema.class.php @@ -0,0 +1,779 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * + * @version $Id$ + * @package phpMyAdmin + */ + +include_once("Export_Relation_Schema.class.php"); + +/** + * This Class inherits the XMLwriter class and + * helps in developing structure of DIA Schema Export + * + * @name PMA_DIA + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + * @access public + * @see http://php.net/manual/en/book.xmlwriter.php + */ + +class PMA_DIA extends XMLWriter +{ + public $title; + public $author; + public $font; + public $fontSize; + + /** + * The "PMA_DIA" constructor + * + * Upon instantiation This starts writing the Dia XML document + * + * @return void + * @see XMLWriter::openMemory(),XMLWriter::setIndent(),XMLWriter::startDocument() + */ + function __construct() + { + $this->openMemory(); + /* + * Set indenting using three spaces, + * so output is formatted + */ + + $this->setIndent(TRUE); + $this->setIndentString(' '); + /* + * Create the XML document + */ + + $this->startDocument('1.0','UTF-8'); + } + + /** + * Starts Dia Document + * + * dia document starts by first initializing dia:diagram tag + * then dia:diagramdata contains all the attributes that needed + * to define the document, then finally a Layer starts which + * holds all the objects. + * + * @param string paper The size of the paper/document + * @param float topMargin top margin of the paper/document in cm + * @param float bottomMargin bottom margin of the paper/document in cm + * @param float leftMargin left margin of the paper/document in cm + * @param float rightMargin right margin of the paper/document in cm + * @param string portrait document will be portrait or landscape + * @return void + * @access public + * @see XMLWriter::startElement(),XMLWriter::writeAttribute(),XMLWriter::writeRaw() + */ + function startDiaDoc($paper,$topMargin,$bottomMargin,$leftMargin,$rightMargin,$portrait) + { + if($portrait == 'P'){ + $isPortrait='true'; + }else{ + $isPortrait='false'; + } + $this->startElement('dia:diagram'); + $this->writeAttribute('xmlns:dia', 'http://www.lysator.liu.se/~alla/dia/'); + $this->startElement('dia:diagramdata'); + $this->writeRaw ( + '<dia:attribute name="background"> + <dia:color val="#ffffff"/> + </dia:attribute> + <dia:attribute name="pagebreak"> + <dia:color val="#000099"/> + </dia:attribute> + <dia:attribute name="paper"> + <dia:composite type="paper"> + <dia:attribute name="name"> + <dia:string>#'.$paper.'#</dia:string> + </dia:attribute> + <dia:attribute name="tmargin"> + <dia:real val="'.$topMargin.'"/> + </dia:attribute> + <dia:attribute name="bmargin"> + <dia:real val="'.$bottomMargin.'"/> + </dia:attribute> + <dia:attribute name="lmargin"> + <dia:real val="'.$leftMargin.'"/> + </dia:attribute> + <dia:attribute name="rmargin"> + <dia:real val="'.$rightMargin.'"/> + </dia:attribute> + <dia:attribute name="is_portrait"> + <dia:boolean val="'.$isPortrait.'"/> + </dia:attribute> + <dia:attribute name="scaling"> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="fitto"> + <dia:boolean val="false"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="grid"> + <dia:composite type="grid"> + <dia:attribute name="width_x"> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="width_y"> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="visible_x"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="visible_y"> + <dia:int val="1"/> + </dia:attribute> + <dia:composite type="color"/> + </dia:composite> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#d8e5e5"/> + </dia:attribute> + <dia:attribute name="guides"> + <dia:composite type="guides"> + <dia:attribute name="hguides"/> + <dia:attribute name="vguides"/> + </dia:composite> + </dia:attribute>'); + $this->endElement(); + $this->startElement('dia:layer'); + $this->writeAttribute('name', 'Background'); + $this->writeAttribute('visible', 'true'); + $this->writeAttribute('active', 'true'); + + } + + /** + * Ends Dia Document + * + * @return void + * @access public + * @see XMLWriter::endElement(),XMLWriter::endDocument() + */ + function endDiaDoc() + { + $this->endElement(); + $this->endDocument(); + } + + /** + * Output Dia Document for download + * + * @param string fileName name of the dia document + * @return void + * @access public + * @see XMLWriter::flush() + */ + function showOutput($fileName) + { + if(ob_get_clean()){ + ob_end_clean(); + } + header('Content-type: application/x-dia-diagram'); + header('Content-Disposition: attachment; filename="'.$fileName.'.dia"'); + $output = $this->flush(); + print $output; + } +} + +/** + * Table preferences/statistics + * + * This class preserves the table co-ordinates,fields + * and helps in drawing/generating the Tables in dia XML document. + * + * @name Table_Stats + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + * @see PMA_DIA + */ +class Table_Stats +{ + /** + * Defines properties + */ + public $tableName; + public $fields = array(); + public $x, $y; + public $primary = array(); + public $tableId; + public $tableColor; + + /** + * The "Table_Stats" constructor + * + * @param string table_name The table name + * @param integer pageNumber The current page number (from the + * $cfg['Servers'][$i]['table_coords'] table) + * @param boolean showKeys Whether to display ONLY keys or not + * @return void + * @global object The current dia document + * @global array The relations settings + * @global string The current db name + * @see PMA_DIA + */ + function __construct($tableName, $pageNumber, $showKeys = false) + { + global $dia, $cfgRelation, $db; + + $this->tableName = $tableName; + $sql = 'DESCRIBE ' . PMA_backquote($tableName); + $result = PMA_DBI_try_query($sql, null, PMA_DBI_QUERY_STORE); + if (!$result || !PMA_DBI_num_rows($result)) { + $dia->dieSchema($pageNumber,"DIA",sprintf(__('The %s table doesn\'t exist!'), $tableName)); + } + /* + * load fields + * check to see if it will load all fields or only the foreign keys + */ + if ($showKeys) { + $indexes = PMA_Index::getFromTable($this->tableName, $db); + $all_columns = array(); + foreach ($indexes as $index) { + $all_columns = array_merge($all_columns, array_flip(array_keys($index->getColumns()))); + } + $this->fields = array_keys($all_columns); + } else { + while ($row = PMA_DBI_fetch_row($result)) { + $this->fields[] = $row[0]; + } + } + + $sql = 'SELECT x, y FROM ' + . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) + . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' + . ' AND table_name = \'' . PMA_sqlAddslashes($tableName) . '\'' + . ' AND pdf_page_number = ' . $pageNumber; + $result = PMA_query_as_controluser($sql, false, PMA_DBI_QUERY_STORE); + if (!$result || !PMA_DBI_num_rows($result)) { + $dia->dieSchema($pageNumber,"DIA",sprintf(__('Please configure the coordinates for table %s'), $tableName)); + } + list($this->x, $this->y) = PMA_DBI_fetch_row($result); + $this->x = (double) $this->x; + $this->y = (double) $this->y; + /* + * displayfield + */ + $this->displayfield = PMA_getDisplayField($db, $tableName); + /* + * index + */ + $result = PMA_DBI_query('SHOW INDEX FROM ' . PMA_backquote($tableName) . ';', null, PMA_DBI_QUERY_STORE); + if (PMA_DBI_num_rows($result) > 0) { + while ($row = PMA_DBI_fetch_assoc($result)) { + if ($row['Key_name'] == 'PRIMARY') { + $this->primary[] = $row['Column_name']; + } + } + } + /** + * Every object in Dia document needs an ID to identify + * so, we used a static variable to keep the things unique + */ + PMA_Dia_Relation_Schema::$objectId += 1; + $this->tableId = PMA_Dia_Relation_Schema::$objectId; + } + + /** + * Do draw the table + * + * Tables are generated using object type Database - Table + * primary fields are underlined in tables. Dia object + * is used to generate the XML of Dia Document. Database Table + * Object and their attributes are involved in the combination + * of displaing Database - Table on Dia Document. + + * @param boolean changeColor Whether to show color for tables text or not + if changeColor is true then an array of $listOfColors + will be used to choose the random colors for tables text + we can change/add more colors to this array + @return void + * @global object The current Dia document + * @access public + * @see PMA_DIA + */ + public function tableDraw($changeColor) + { + global $dia; + + if ($changeColor) { + $listOfColors = array( + 'FF0000', + '000099', + '00FF00' + ); + shuffle($listOfColors); + $this->tableColor = '#'.$listOfColors[0].''; + } else { + $this->tableColor = '#000000'; + } + + $factor = 0.1; + + $dia->startElement('dia:object'); + $dia->writeAttribute('type', 'Database - Table'); + $dia->writeAttribute('version', '0'); + $dia->writeAttribute('id', ''.$this->tableId.''); + $dia->writeRaw( + '<dia:attribute name="obj_pos"> + <dia:point val="'.($this->x * $factor).','.($this->y * $factor).'"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="'.($this->x * $factor).','.($this->y * $factor).';9.97,9.2"/> + </dia:attribute> + <dia:attribute name="meta"> + <dia:composite type="dict"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="'.($this->x * $factor).','.($this->y * $factor).'"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="5.9199999999999999"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="3.5"/> + </dia:attribute> + <dia:attribute name="text_colour"> + <dia:color val="'.$this->tableColor.'"/> + </dia:attribute> + <dia:attribute name="line_colour"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="fill_colour"> + <dia:color val="#ffffff"/> + </dia:attribute> + <dia:attribute name="line_width"> + <dia:real val="0.10000000000000001"/> + </dia:attribute> + <dia:attribute name="name"> + <dia:string>#'.$this->tableName.'#</dia:string> + </dia:attribute> + <dia:attribute name="comment"> + <dia:string>##</dia:string> + </dia:attribute> + <dia:attribute name="visible_comment"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="tagging_comment"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="underline_primary_key"> + <dia:boolean val="true"/> + </dia:attribute> + <dia:attribute name="bold_primary_keys"> + <dia:boolean val="true"/> + </dia:attribute> + <dia:attribute name="normal_font"> + <dia:font family="monospace" style="0" name="Courier"/> + </dia:attribute> + <dia:attribute name="name_font"> + <dia:font family="sans" style="80" name="Helvetica-Bold"/> + </dia:attribute> + <dia:attribute name="comment_font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="normal_font_height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="name_font_height"> + <dia:real val="0.69999999999999996"/> + </dia:attribute> + <dia:attribute name="comment_font_height"> + <dia:real val="0.69999999999999996"/> + </dia:attribute>' + ); + + $dia->startElement('dia:attribute'); + $dia->writeAttribute('name', 'attributes'); + + foreach ($this->fields as $field) { + $dia->writeRaw( + '<dia:composite type="table_attribute"> + <dia:attribute name="name"> + <dia:string>#'.$field.'#</dia:string> + </dia:attribute> + <dia:attribute name="type"> + <dia:string>##</dia:string> + </dia:attribute> + <dia:attribute name="comment"> + <dia:string>##</dia:string> + </dia:attribute>' + ); + unset($pm); + $pm = 'false'; + if (in_array($field, $this->primary)) { + $pm = 'true'; + } + if ($field == $this->displayfield) { + $pm = 'false'; + } + $dia->writeRaw( + '<dia:attribute name="primary_key"> + <dia:boolean val="'.$pm.'"/> + </dia:attribute> + <dia:attribute name="nullable"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="unique"> + <dia:boolean val="'.$pm.'"/> + </dia:attribute> + </dia:composite>' + ); + } + $dia->endElement(); + $dia->endElement(); + } +} + +/** + * Relation preferences/statistics + * + * This class fetches the table master and foreign fields positions + * and helps in generating the Table references and then connects + * master table's master field to foreign table's foreign key + * in dia XML document. + * + * @name Relation_Stats + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + * @see PMA_DIA + */ +class Relation_Stats +{ + /** + * Defines properties + */ + public $srcConnPointsRight; + public $srcConnPointsLeft; + public $destConnPointsRight; + public $destConnPointsLeft; + public $masterTableId; + public $foreignTableId; + public $masterTablePos; + public $foreignTablePos; + public $referenceColor; + + /** + * The "Relation_Stats" constructor + * + * @param string master_table The master table name + * @param string master_field The relation field in the master table + * @param string foreign_table The foreign table name + * @param string foreigh_field The relation field in the foreign table + * @return void + * @see Relation_Stats::_getXy + */ + function __construct($master_table, $master_field, $foreign_table, $foreign_field) + { + $src_pos = $this->_getXy($master_table, $master_field); + $dest_pos = $this->_getXy($foreign_table, $foreign_field); + $this->srcConnPointsLeft = $src_pos[0]; + $this->srcConnPointsRight = $src_pos[1]; + $this->destConnPointsLeft = $dest_pos[0]; + $this->destConnPointsRight = $dest_pos[1]; + $this->masterTablePos = $src_pos[2]; + $this->foreignTablePos = $dest_pos[2]; + $this->masterTableId = $master_table->tableId; + $this->foreignTableId = $foreign_table->tableId; + } + + /** + * Each Table object have connection points + * which is used to connect to other objects in Dia + * we detect the position of key in fields and + * then determines its left and right connection + * points. + * + * @param string table The current table name + * @param string column The relation column name + * @return array Table right,left connection points and key position + * @access private + */ + private function _getXy($table, $column) + { + $pos = array_search($column, $table->fields); + // left, right, position + $value = 12; + if($pos != 0) + { + return array($pos + $value + $pos, $pos + $value + $pos + 1, $pos); + } + return array($pos + $value , $pos + $value + 1, $pos); + } + + /** + * Draws relation references + * + * connects master table's master field to foreign table's + * forein field using Dia object type Database - Reference + * Dia object is used to generate the XML of Dia Document. + * Database reference Object and their attributes are involved + * in the combination of displaing Database - reference on Dia Document. + * + * @param boolean changeColor Whether to use one color per relation or not + if changeColor is true then an array of $listOfColors + will be used to choose the random colors for references + lines. we can change/add more colors to this array + * @return void + * @global object The current Dia document + * @access public + * @see PMA_PDF + */ + public function relationDraw($changeColor) + { + global $dia; + + PMA_Dia_Relation_Schema::$objectId += 1; + /* + * if source connection points and destination connection + * points are same then return it false and don't draw that + * relation + */ + if ( $this->srcConnPointsRight == $this->destConnPointsRight ){ + if ( $this->srcConnPointsLeft == $this->destConnPointsLeft ){ + return false; + } + } + + if ($changeColor) { + $listOfColors = array( + 'FF0000', + '000099', + '00FF00' + ); + shuffle($listOfColors); + $this->referenceColor = '#'.$listOfColors[0].''; + } else { + $this->referenceColor = '#000000'; + } + + $dia->writeRaw( + '<dia:object type="Database - Reference" version="0" id="'.PMA_Dia_Relation_Schema::$objectId.'"> + <dia:attribute name="obj_pos"> + <dia:point val="3.27,18.9198"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="2.27,8.7175;17.7679,18.9198"/> + </dia:attribute> + <dia:attribute name="meta"> + <dia:composite type="dict"/> + </dia:attribute> + <dia:attribute name="orth_points"> + <dia:point val="3.27,18.9198"/> + <dia:point val="2.27,18.9198"/> + <dia:point val="2.27,14.1286"/> + <dia:point val="17.7679,14.1286"/> + <dia:point val="17.7679,9.3375"/> + <dia:point val="16.7679,9.3375"/> + </dia:attribute> + <dia:attribute name="orth_orient"> + <dia:enum val="0"/> + <dia:enum val="1"/> + <dia:enum val="0"/> + <dia:enum val="1"/> + <dia:enum val="0"/> + </dia:attribute> + <dia:attribute name="orth_autoroute"> + <dia:boolean val="true"/> + </dia:attribute> + <dia:attribute name="text_colour"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="line_colour"> + <dia:color val="'.$this->referenceColor.'"/> + </dia:attribute> + <dia:attribute name="line_width"> + <dia:real val="0.10000000000000001"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="0"/> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="corner_radius"> + <dia:real val="0"/> + </dia:attribute> + <dia:attribute name="end_arrow"> + <dia:enum val="22"/> + </dia:attribute> + <dia:attribute name="end_arrow_length"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="end_arrow_width"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="start_point_desc"> + <dia:string>#1#</dia:string> + </dia:attribute> + <dia:attribute name="end_point_desc"> + <dia:string>#n#</dia:string> + </dia:attribute> + <dia:attribute name="normal_font"> + <dia:font family="monospace" style="0" name="Courier"/> + </dia:attribute> + <dia:attribute name="normal_font_height"> + <dia:real val="0.59999999999999998"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="'.$this->masterTableId.'" connection="'.$this->srcConnPointsRight.'"/> + <dia:connection handle="1" to="'.$this->foreignTableId.'" connection="'.$this->destConnPointsRight.'"/> + </dia:connections> + </dia:object>' + ); + } +} + +/** + * Dia Relation Schema Class + * + * Purpose of this class is to generate the Dia XML Document + * which is used for representing the database diagrams in Dia IDE + * This class uses Database Table and Reference Objects of Dia and with + * the combination of these objects actually helps in preparing Dia XML. + * + * Dia XML is generated by using XMLWriter php extension and this class + * inherits Export_Relation_Schema class has common functionality added + * to this class + * + * @name Dia_Relation_Schema + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + */ +class PMA_Dia_Relation_Schema extends PMA_Export_Relation_Schema +{ + /** + * Defines properties + */ + private $_tables = array(); + private $_relations = array(); + private $_topMargin = 2.8222000598907471; + private $_bottomMargin = 2.8222000598907471; + private $_leftMargin = 2.8222000598907471; + private $_rightMargin = 2.8222000598907471; + public static $objectId = 0; + + /** + * The "PMA_Dia_Relation_Schema" constructor + * + * Upon instantiation This outputs the Dia XML document + * that user can download + * + * @return void + * @see PMA_DIA,Table_Stats,Relation_Stats + */ + function __construct() + { + global $dia,$db; + + $this->setPageNumber($_POST['pdf_page_number']); + $this->setShowGrid(isset($_POST['show_grid'])); + $this->setShowColor($_POST['show_color']); + $this->setShowKeys(isset($_POST['show_keys'])); + $this->setOrientation(isset($_POST['orientation'])); + $this->setPaper($_POST['paper']); + $this->setExportType($_POST['export_type']); + + $dia = new PMA_DIA(); + $dia->startDiaDoc($this->paper,$this->_topMargin,$this->_bottomMargin,$this->_leftMargin,$this->_rightMargin,$this->orientation); + $alltables = $this->getAllTables($db,$this->pageNumber); + foreach ($alltables as $table) { + if (!isset($this->tables[$table])) { + $this->tables[$table] = new Table_Stats($table, $this->pageNumber, $this->showKeys); + } + } + + $seen_a_relation = false; + foreach ($alltables as $one_table) { + $exist_rel = PMA_getForeigners($db, $one_table, '', 'both'); + if ($exist_rel) { + $seen_a_relation = true; + foreach ($exist_rel as $master_field => $rel) { + /* put the foreign table on the schema only if selected + * by the user + * (do not use array_search() because we would have to + * to do a === FALSE and this is not PHP3 compatible) + */ + if (in_array($rel['foreign_table'], $alltables)) { + $this->_addRelation($one_table, $master_field, $rel['foreign_table'], $rel['foreign_field'],$this->showKeys); + } + } + } + } + $this->_drawTables($this->showColor); + + if ($seen_a_relation) { + $this->_drawRelations($this->showColor); + } + $dia->endDiaDoc(); + $dia->showOutput($db.'-'.$this->pageNumber); + exit(); + } + + /** + * Defines relation objects + * + * @param string masterTable The master table name + * @param string masterField The relation field in the master table + * @param string foreignTable The foreign table name + * @param string foreignField The relation field in the foreign table + * @return void + * @access private + * @see Table_Stats::__construct(),Relation_Stats::__construct() + */ + private function _addRelation($masterTable, $masterField, $foreignTable, $foreignField, $showKeys) + { + if (!isset($this->tables[$masterTable])) { + $this->tables[$masterTable] = new Table_Stats($masterTable, $this->pageNumber, $showKeys); + } + if (!isset($this->tables[$foreignTable])) { + $this->tables[$foreignTable] = new Table_Stats($foreignTable, $this->pageNumber, $showKeys); + } + $this->_relations[] = new Relation_Stats($this->tables[$masterTable], $masterField, $this->tables[$foreignTable], $foreignField); + } + + /** + * Draws relation references + * + * connects master table's master field to + * foreign table's forein field using Dia object + * type Database - Reference + * + * @param boolean changeColor Whether to use one color per relation or not + * @return void + * @access private + * @see Relation_Stats::relationDraw() + */ + private function _drawRelations($changeColor) + { + foreach ($this->_relations as $relation) { + $relation->relationDraw($changeColor); + } + } + + /** + * Draws tables + * + * Tables are generated using Dia object type Database - Table + * primary fields are underlined and bold in tables + * + * @param boolean changeColor Whether to show color for tables text or not + * @return void + * @access private + * @see Table_Stats::tableDraw() + */ + private function _drawTables($changeColor) + { + foreach ($this->tables as $table) { + $table->tableDraw($changeColor); + } + } +} +?> diff --git a/libraries/schema/Eps_Relation_Schema.class.php b/libraries/schema/Eps_Relation_Schema.class.php new file mode 100644 index 0000000..e783cbd --- /dev/null +++ b/libraries/schema/Eps_Relation_Schema.class.php @@ -0,0 +1,858 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * + * @version $Id$ + * @package phpMyAdmin + */ + +include_once("Export_Relation_Schema.class.php"); + +/** + * This Class is EPS Library and + * helps in developing structure of EPS Schema Export + * + * @name PMA_EPS + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + * @access public + * @see http://php.net/manual/en/book.xmlwriter.php + */ + +class PMA_EPS +{ + public $font; + public $fontSize; + public $stringCommands; + + /** + * The "PMA_EPS" constructor + * + * Upon instantiation This starts writing the EPS Document. + * %!PS-Adobe-3.0 EPSF-3.0 This is the MUST first comment to include + * it shows/tells that the Post Script document is purely under + * Document Structuring Convention [DSC] and is Compliant + * Encapsulated Post Script Document + * + * @return void + * @access public + */ + function __construct() + { + $this->stringCommands = ""; + $this->stringCommands .= "%!PS-Adobe-3.0 EPSF-3.0 \n"; + } + + /** + * Set document title + * + * @param string value sets the title text + * @return void + * @access public + */ + function setTitle($value) + { + $this->stringCommands .= '%%Title: ' . $value . "\n"; + } + + /** + * Set document author + * + * @param string value sets the author + * @return void + * @access public + */ + function setAuthor($value) + { + $this->stringCommands .= '%%Creator: ' . $value . "\n"; + } + + /** + * Set document creation date + * + * @param string value sets the date + * @return void + * @access public + */ + function setDate($value) + { + $this->stringCommands .= '%%CreationDate: ' . $value . "\n"; + } + + /** + * Set document orientation + * + * @param string value sets the author + * @return void + * @access public + */ + function setOrientation($value) + { + $this->stringCommands .= "%%PageOrder: Ascend \n"; + if($value == "L"){ + $value = "Landscape"; + $this->stringCommands .= '%%Orientation: ' . $value . "\n"; + }else{ + $value = "Portrait"; + $this->stringCommands .= '%%Orientation: ' . $value . "\n"; + } + $this->stringCommands .= "%%EndComments \n"; + $this->stringCommands .= "%%Pages 1 \n"; + $this->stringCommands .= "%%BoundingBox: 72 150 144 170 \n"; + } + + /** + * Set the font and size + * + * font can be set whenever needed in EPS + * + * @param string value sets the font name e.g Arial + * @param integer value sets the size of the font e.g 10 + * @return void + * @access public + */ + function setFont($value,$size) + { + $this->font = $value; + $this->fontSize = $size; + $this->stringCommands .= "/".$value." findfont % Get the basic font\n"; + $this->stringCommands .= "".$size." scalefont % Scale the font to $size points\n"; + $this->stringCommands .= "setfont % Make it the current font\n"; + } + + /** + * Get the font + * + * @return string return the font name e.g Arial + * @access public + */ + function getFont() + { + return $this->font; + } + + /** + * Get the font Size + * + * @return string return the size of the font e.g 10 + * @access public + */ + function getFontSize() + { + return $this->fontSize; + } + + /** + * Draw the line + * + * drawing the lines from x,y source to x,y destination and set the + * width of the line. lines helps in showing relationships of tables + * + * @param integer x_from The x_from attribute defines the start + left position of the element + * @param integer y_from The y_from attribute defines the start + right position of the element + * @param integer x_to The x_to attribute defines the end + left position of the element + * @param integer y_to The y_to attribute defines the end + right position of the element + * @param integer lineWidth sets the width of the line e.g 2 + * @return void + * @access public + */ + function line($x_from=0, $y_from=0, $x_to=0, $y_to=0, $lineWidth=0) + { + $this->stringCommands .= $lineWidth . " setlinewidth \n"; + $this->stringCommands .= $x_from . ' ' . $y_from . " moveto \n"; + $this->stringCommands .= $x_to . ' ' . $y_to . " lineto \n"; + $this->stringCommands .= "stroke \n"; + } + + /** + * Draw the rectangle + * + * drawing the rectangle from x,y source to x,y destination and set the + * width of the line. rectangles drawn around the text shown of fields + * + * @param integer x_from The x_from attribute defines the start + left position of the element + * @param integer y_from The y_from attribute defines the start + right position of the element + * @param integer x_to The x_to attribute defines the end + left position of the element + * @param integer y_to The y_to attribute defines the end + right position of the element + * @param integer lineWidth sets the width of the line e.g 2 + * @return void + * @access public + */ + function rect($x_from, $y_from, $x_to, $y_to, $lineWidth) + { + $this->stringCommands .= $lineWidth . " setlinewidth \n"; + $this->stringCommands .= "newpath \n"; + $this->stringCommands .= $x_from . " " . $y_from . " moveto \n"; + $this->stringCommands .= "0 " . $y_to . " rlineto \n"; + $this->stringCommands .= $x_to . " 0 rlineto \n"; + $this->stringCommands .= "0 -" . $y_to . " rlineto \n"; + $this->stringCommands .= "closepath \n"; + $this->stringCommands .= "stroke \n"; + } + + /** + * Set the current point + * + * The moveto operator takes two numbers off the stack and treats + * them as x and y coordinates to which to move. The coordinates + * specified become the current point. + * + * @param integer x The x attribute defines the + left position of the element + * @param integer y The y attribute defines the + right position of the element + * @return void + * @access public + */ + function moveTo($x, $y) + { + $this->stringCommands .= $x . ' ' . $y . " moveto \n"; + } + + /** + * Output/Display the text + * + * @param string text The string to be displayed + * @return void + * @access public + */ + function show($text) + { + $this->stringCommands .= '(' . $text . ") show \n"; + } + + /** + * Output the text at specified co-ordinates + * + * @param string text The string to be displayed + * @param integer x The x attribute defines the + left position of the element + * @param integer y The y attribute defines the + right position of the element + * @return void + * @access public + */ + function showXY($text, $x, $y) + { + $this->moveTo($x, $y); + $this->show($text); + } + + /** + * get width of string/text + * + * EPS text width is calcualted depending on font name + * and font size. It is very important to know the width of text + * because rectangle is drawn around it. + * + * This is a bit hardcore method. I didn't found any other better than this. + * if someone found better than this. would love to hear that method + * + * @param string text string that width will be calculated + * @param integer font name of the font like Arial,sans-serif etc + * @param integer fontSize size of font + * @return integer width of the text + * @access public + */ + function getStringWidth($text,$font,$fontSize) + { + /* + * Start by counting the width, giving each character a modifying value + */ + $count = 0; + $count = $count + ((strlen($text) - strlen(str_replace(array("i","j","l"),"",$text)))*0.23);//ijl + $count = $count + ((strlen($text) - strlen(str_replace(array("f"),"",$text)))*0.27);//f + $count = $count + ((strlen($text) - strlen(str_replace(array("t","I"),"",$text)))*0.28);//tI + $count = $count + ((strlen($text) - strlen(str_replace(array("r"),"",$text)))*0.34);//r + $count = $count + ((strlen($text) - strlen(str_replace(array("1"),"",$text)))*0.49);//1 + $count = $count + ((strlen($text) - strlen(str_replace(array("c","k","s","v","x","y","z","J"),"",$text)))*0.5);//cksvxyzJ + $count = $count + ((strlen($text) - strlen(str_replace(array("a","b","d","e","g","h","n","o","p","q","u","L","0","2","3","4","5","6","7","8","9"),"",$text)))*0.56);//abdeghnopquL023456789 + $count = $count + ((strlen($text) - strlen(str_replace(array("F","T","Z"),"",$text)))*0.61);//FTZ + $count = $count + ((strlen($text) - strlen(str_replace(array("A","B","E","K","P","S","V","X","Y"),"",$text)))*0.67);//ABEKPSVXY + $count = $count + ((strlen($text) - strlen(str_replace(array("w","C","D","H","N","R","U"),"",$text)))*0.73);//wCDHNRU + $count = $count + ((strlen($text) - strlen(str_replace(array("G","O","Q"),"",$text)))*0.78);//GOQ + $count = $count + ((strlen($text) - strlen(str_replace(array("m","M"),"",$text)))*0.84);//mM + $count = $count + ((strlen($text) - strlen(str_replace("W","",$text)))*.95);//W + $count = $count + ((strlen($text) - strlen(str_replace(" ","",$text)))*.28);//" " + $text = str_replace(" ","",$text);//remove the " "'s + $count = $count + (strlen(preg_replace("/[a-z0-9]/i","",$text))*0.3); //all other chrs + + $modifier = 1; + $font = strtolower($font); + switch($font){ + /* + * no modifier for arial and sans-serif + */ + case 'arial': + case 'sans-serif': + break; + /* + * .92 modifer for time, serif, brushscriptstd, and californian fb + */ + case 'times': + case 'serif': + case 'brushscriptstd': + case 'californian fb': + $modifier = .92; + break; + /* + * 1.23 modifier for broadway + */ + case 'broadway': + $modifier = 1.23; + break; + } + $textWidth = $count*$fontSize; + return ceil($textWidth*$modifier); + } + + /** + * Ends EPS Document + * + * @return void + * @access public + */ + function endEpsDoc() + { + $this->stringCommands .= "showpage \n"; + } + + /** + * Output EPS Document for download + * + * @param string fileName name of the eps document + * @return void + * @access public + */ + function showOutput($fileName) + { + // if(ob_get_clean()){ + //ob_end_clean(); + //} + header('Content-type: image/x-eps'); + header('Content-Disposition: attachment; filename="'.$fileName.'.eps"'); + $output = $this->stringCommands; + print $output; + } +} + +/** + * Table preferences/statistics + * + * This class preserves the table co-ordinates,fields + * and helps in drawing/generating the Tables in EPS. + * + * @name Table_Stats + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + * @see PMA_EPS + */ +class Table_Stats +{ + /** + * Defines properties + */ + + private $_tableName; + private $_showInfo = false; + + public $width = 0; + public $height; + public $fields = array(); + public $heightCell = 0; + public $currentCell = 0; + public $x, $y; + public $primary = array(); + + /** + * The "Table_Stats" constructor + * + * @param string tableName The table name + * @param string font The font name + * @param integer fontSize The font size + * @param integer same_wide_width The max width among tables + * @param boolean showKeys Whether to display keys or not + * @param boolean showInfo Whether to display table position or not + * @global object The current eps document + * @global integer The current page number (from the + * $cfg['Servers'][$i]['table_coords'] table) + * @global array The relations settings + * @global string The current db name + * @access private + * @see PMA_EPS, Table_Stats::Table_Stats_setWidth, + Table_Stats::Table_Stats_setHeight + */ + function __construct($tableName, $font, $fontSize, $pageNumber, &$same_wide_width, $showKeys = false, $showInfo = false) + { + global $eps, $cfgRelation, $db; + + $this->_tableName = $tableName; + $sql = 'DESCRIBE ' . PMA_backquote($tableName); + $result = PMA_DBI_try_query($sql, null, PMA_DBI_QUERY_STORE); + if (!$result || !PMA_DBI_num_rows($result)) { + $eps->dieSchema($pageNumber,"EPS",sprintf(__('The %s table doesn\'t exist!'), $tableName)); + } + + /* + * load fields + * check to see if it will load all fields or only the foreign keys + */ + if ($showKeys) { + $indexes = PMA_Index::getFromTable($this->_tableName, $db); + $all_columns = array(); + foreach ($indexes as $index) { + $all_columns = array_merge($all_columns, array_flip(array_keys($index->getColumns()))); + } + $this->fields = array_keys($all_columns); + } else { + while ($row = PMA_DBI_fetch_row($result)) { + $this->fields[] = $row[0]; + } + } + + $this->_showInfo = $showInfo; + + // height and width + $this->_setHeightTable($fontSize); + + // setWidth must me after setHeight, because title + // can include table height which changes table width + $this->_setWidthTable($font,$fontSize); + if ($same_wide_width < $this->width) { + $same_wide_width = $this->width; + } + + // x and y + $sql = 'SELECT x, y FROM ' + . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) + . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' + . ' AND table_name = \'' . PMA_sqlAddslashes($tableName) . '\'' + . ' AND pdf_page_number = ' . $pageNumber; + $result = PMA_query_as_controluser($sql, false, PMA_DBI_QUERY_STORE); + + if (!$result || !PMA_DBI_num_rows($result)) { + $eps->dieSchema($pageNumber,"EPS",sprintf(__('Please configure the coordinates for table %s'), $tableName)); + } + list($this->x, $this->y) = PMA_DBI_fetch_row($result); + $this->x = (double) $this->x; + $this->y = (double) $this->y; + // displayfield + $this->displayfield = PMA_getDisplayField($db, $tableName); + // index + $result = PMA_DBI_query('SHOW INDEX FROM ' . PMA_backquote($tableName) . ';', null, PMA_DBI_QUERY_STORE); + if (PMA_DBI_num_rows($result) > 0) { + while ($row = PMA_DBI_fetch_assoc($result)) { + if ($row['Key_name'] == 'PRIMARY') { + $this->primary[] = $row['Column_name']; + } + } + } + } + + /** + * Returns title of the current table, + * title can have the dimensions/co-ordinates of the table + * + * @return string The relation/table name + * @access private + */ + private function _getTitle() + { + return ($this->_showInfo ? sprintf('%.0f', $this->width) . 'x' . sprintf('%.0f', $this->heightCell) : '') . ' ' . $this->_tableName; + } + + /** + * Sets the width of the table + * + * @param string font The font name + * @param integer fontSize The font size + * @global object The current eps document + * @return void + * @access private + * @see PMA_EPS + */ + private function _setWidthTable($font,$fontSize) + { + global $eps; + + foreach ($this->fields as $field) { + $this->width = max($this->width, $eps->getStringWidth($field,$font,$fontSize)); + } + $this->width += $eps->getStringWidth(' ',$font,$fontSize); + /* + * it is unknown what value must be added, because + * table title is affected by the tabe width value + */ + while ($this->width < $eps->getStringWidth($this->_getTitle(),$font,$fontSize)) { + $this->width += 7; + } + } + + /** + * Sets the height of the table + * + * @param integer fontSize The font size + * @return void + * @access private + */ + private function _setHeightTable($fontSize) + { + $this->heightCell = $fontSize + 4; + $this->height = (count($this->fields) + 1) * $this->heightCell; + } + + /** + * Draw the table + * + * @param boolean showColor Whether to display color + * @global object The current eps document + * @return void + * @access public + * @see PMA_EPS,PMA_EPS::line,PMA_EPS::rect + */ + public function tableDraw($showColor) + { + global $eps; + //echo $this->_tableName.'<br />'; + $eps->rect($this->x,$this->y + 12, + $this->width,$this->heightCell, + 1 + ); + $eps->showXY($this->_getTitle(),$this->x + 5,$this->y + 14); + foreach ($this->fields as $field) { + $this->currentCell += $this->heightCell; + $showColor = 'none'; + if ($showColor) { + if (in_array($field, $this->primary)) { + $showColor = '#0c0'; + } + if ($field == $this->displayfield) { + $showColor = 'none'; + } + } + $eps->rect($this->x,$this->y + 12 + $this->currentCell, + $this->width, $this->heightCell,1); + $eps->showXY($field, $this->x + 5, $this->y + 14 + $this->currentCell); + } + } +} + +/** + * Relation preferences/statistics + * + * This class fetches the table master and foreign fields positions + * and helps in generating the Table references and then connects + * master table's master field to foreign table's foreign key + * in EPS document. + * + * @name Relation_Stats + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + * @see PMA_EPS + */ +class Relation_Stats +{ + /** + * Defines properties + */ + public $xSrc, $ySrc; + public $srcDir ; + public $destDir; + public $xDest, $yDest; + public $wTick = 10; + + /** + * The "Relation_Stats" constructor + * + * @param string master_table The master table name + * @param string master_field The relation field in the master table + * @param string foreign_table The foreign table name + * @param string foreigh_field The relation field in the foreign table + * @see Relation_Stats::_getXy + */ + function __construct($master_table, $master_field, $foreign_table, $foreign_field) + { + $src_pos = $this->_getXy($master_table, $master_field); + $dest_pos = $this->_getXy($foreign_table, $foreign_field); + /* + * [0] is x-left + * [1] is x-right + * [2] is y + */ + $src_left = $src_pos[0] - $this->wTick; + $src_right = $src_pos[1] + $this->wTick; + $dest_left = $dest_pos[0] - $this->wTick; + $dest_right = $dest_pos[1] + $this->wTick; + + $d1 = abs($src_left - $dest_left); + $d2 = abs($src_right - $dest_left); + $d3 = abs($src_left - $dest_right); + $d4 = abs($src_right - $dest_right); + $d = min($d1, $d2, $d3, $d4); + + if ($d == $d1) { + $this->xSrc = $src_pos[0]; + $this->srcDir = -1; + $this->xDest = $dest_pos[0]; + $this->destDir = -1; + } elseif ($d == $d2) { + $this->xSrc = $src_pos[1]; + $this->srcDir = 1; + $this->xDest = $dest_pos[0]; + $this->destDir = -1; + } elseif ($d == $d3) { + $this->xSrc = $src_pos[0]; + $this->srcDir = -1; + $this->xDest = $dest_pos[1]; + $this->destDir = 1; + } else { + $this->xSrc = $src_pos[1]; + $this->srcDir = 1; + $this->xDest = $dest_pos[1]; + $this->destDir = 1; + } + $this->ySrc = $src_pos[2] + 10; + $this->yDest = $dest_pos[2] + 10; + } + + /** + * Gets arrows coordinates + * + * @param string table The current table name + * @param string column The relation column name + * @return array Arrows coordinates + * @access private + */ + private function _getXy($table, $column) + { + $pos = array_search($column, $table->fields); + // x_left, x_right, y + return array($table->x, $table->x + $table->width, $table->y + ($pos + 1.5) * $table->heightCell); + } + + /** + * draws relation links and arrows + * shows foreign key relations + * + * @param boolean changeColor Whether to use one color per relation or not + * @global object The current EPS document + * @access public + * @see PMA_EPS + */ + public function relationDraw($changeColor) + { + global $eps; + + if ($changeColor) { + $listOfColors = array( + 'red', + 'grey', + 'black', + 'yellow', + 'green', + 'cyan', + ' orange' + ); + shuffle($listOfColors); + $color = $listOfColors[0]; + } else { + $color = 'black'; + } + // draw a line like -- to foreign field + $eps->line($this->xSrc,$this->ySrc, + $this->xSrc + $this->srcDir * $this->wTick,$this->ySrc, + 1 + ); + // draw a line like -- to master field + $eps->line($this->xDest + $this->destDir * $this->wTick, $this->yDest, + $this->xDest, $this->yDest, + 1 + ); + // draw a line that connects to master field line and foreign field line + $eps->line($this->xSrc + $this->srcDir * $this->wTick,$this->ySrc, + $this->xDest + $this->destDir * $this->wTick, $this->yDest, + 1 + ); + $root2 = 2 * sqrt(2); + $eps->line($this->xSrc + $this->srcDir * $this->wTick * 0.75, $this->ySrc, + $this->xSrc + $this->srcDir * (0.75 - 1 / $root2) * $this->wTick , + $this->ySrc + $this->wTick / $root2 , + 1 + ); + $eps->line($this->xSrc + $this->srcDir * $this->wTick * 0.75, $this->ySrc, + $this->xSrc + $this->srcDir * (0.75 - 1 / $root2) * $this->wTick , + $this->ySrc - $this->wTick / $root2 , + 1 + ); + $eps->line($this->xDest + $this->destDir * $this->wTick / 2 , $this->yDest , + $this->xDest + $this->destDir * (0.5 + 1 / $root2) * $this->wTick, + $this->yDest + $this->wTick / $root2 , + 1); + $eps->line($this->xDest + $this->destDir * $this->wTick / 2 , + $this->yDest , $this->xDest + $this->destDir * (0.5 + 1 / $root2) * $this->wTick , + $this->yDest - $this->wTick / $root2 , + 1 + ); + } +} +/* +* end of the "Relation_Stats" class +*/ + +/** + * EPS Relation Schema Class + * + * Purpose of this class is to generate the EPS Document + * which is used for representing the database diagrams. + * This class uses post script commands and with + * the combination of these commands actually helps in preparing EPS Document. + * + * This class inherits Export_Relation_Schema class has common functionality added + * to this class + * + * @name Eps_Relation_Schema + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + */ +class PMA_Eps_Relation_Schema extends PMA_Export_Relation_Schema +{ + private $tables = array(); + private $_relations = array(); + + /** + * The "PMA_EPS_Relation_Schema" constructor + * + * Upon instantiation This starts writing the EPS document + * user will be prompted for download as .eps extension + * + * @return void + * @see PMA_EPS + */ + function __construct() + { + global $eps,$db; + + $this->setPageNumber($_POST['pdf_page_number']); + $this->setShowColor(isset($_POST['show_color'])); + $this->setShowKeys(isset($_POST['show_keys'])); + $this->setTableDimension(isset($_POST['show_table_dimension'])); + $this->setAllTableSameWidth(isset($_POST['all_table_same_wide'])); + $this->setOrientation($_POST['orientation']); + $this->setExportType($_POST['export_type']); + + $eps = new PMA_EPS(); + $eps->setTitle(sprintf(__('Schema of the %s database - Page %s'), $db, $this->pageNumber)); + $eps->setAuthor('phpMyAdmin ' . PMA_VERSION); + $eps->setDate(date("j F Y, g:i a")); + $eps->setOrientation($this->orientation); + $eps->setFont('Verdana','10'); + + + + $alltables = $this->getAllTables($db,$this->pageNumber); + + foreach ($alltables AS $table) { + if (!isset($this->tables[$table])) { + $this->tables[$table] = new Table_Stats($table,$eps->getFont(),$eps->getFontSize(), $this->pageNumber, $this->_tablewidth, $this->showKeys, $this->tableDimension); + } + + if ($this->sameWide) { + $this->tables[$table]->width = $this->_tablewidth; + } + } + + $seen_a_relation = false; + foreach ($alltables as $one_table) { + $exist_rel = PMA_getForeigners($db, $one_table, '', 'both'); + if ($exist_rel) { + $seen_a_relation = true; + foreach ($exist_rel as $master_field => $rel) { + /* put the foreign table on the schema only if selected + * by the user + * (do not use array_search() because we would have to + * to do a === FALSE and this is not PHP3 compatible) + */ + if (in_array($rel['foreign_table'], $alltables)) { + $this->_addRelation($one_table,$eps->getFont(),$eps->getFontSize(), $master_field, $rel['foreign_table'], $rel['foreign_field'], $this->tableDimension); + } + } + } + } + if ($seen_a_relation) { + $this->_drawRelations($this->showColor); + } + + $this->_drawTables($this->showColor); + $eps->endEpsDoc(); + $eps->showOutput($db.'-'.$this->pageNumber); + exit(); + } + + /** + * Defines relation objects + * + * @param string masterTable The master table name + * @param string masterField The relation field in the master table + * @param string foreignTable The foreign table name + * @param string foreignField The relation field in the foreign table + * @param boolean showInfo Whether to display table position or not + * @return void + * @access private + * @see _setMinMax,Table_Stats::__construct(),Relation_Stats::__construct() + */ + private function _addRelation($masterTable,$font,$fontSize, $masterField, $foreignTable, $foreignField, $showInfo) + { + if (!isset($this->tables[$masterTable])) { + $this->tables[$masterTable] = new Table_Stats($masterTable, $font, $fontSize, $this->pageNumber, $this->_tablewidth, false, $showInfo); + } + if (!isset($this->tables[$foreignTable])) { + $this->tables[$foreignTable] = new Table_Stats($foreignTable,$font,$fontSize,$this->pageNumber, $this->_tablewidth, false, $showInfo); + } + $this->_relations[] = new Relation_Stats($this->tables[$masterTable], $masterField, $this->tables[$foreignTable], $foreignField); + } + + /** + * Draws relation arrows and lines + * connects master table's master field to + * foreign table's forein field + * + * @param boolean changeColor Whether to use one color per relation or not + * @return void + * @access private + * @see Relation_Stats::relationDraw() + */ + private function _drawRelations($changeColor) + { + foreach ($this->_relations as $relation) { + $relation->relationDraw($changeColor); + } + } + + /** + * Draws tables + * + * @param boolean changeColor Whether to show color for primary fields or not + * @return void + * @access private + * @see Table_Stats::Table_Stats_tableDraw() + */ + private function _drawTables($changeColor) + { + foreach ($this->tables as $table) { + $table->tableDraw($changeColor); + } + } +} +?> \ No newline at end of file diff --git a/libraries/schema/Export_Relation_Schema.class.php b/libraries/schema/Export_Relation_Schema.class.php new file mode 100644 index 0000000..af9b4de --- /dev/null +++ b/libraries/schema/Export_Relation_Schema.class.php @@ -0,0 +1,223 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * + * @version $Id$ + * @package phpMyAdmin + */ + +/** + * This class is inherited by all schema classes + * It contains those methods which are common in them + * it works like factory pattern + * + * @name Export Relation Schema + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + */ + +class PMA_Export_Relation_Schema +{ + private $_pageTitle; + public $showGrid; + public $showColor; + public $tableDimension; + public $sameWide; + public $withDoc; + public $showKeys; + public $orientation; + public $paper; + public $pageNumber; + + /** + * Set Page Number + * + * @param integer value Page Number of the document to be created + * @return void + * @access public + */ + public function setPageNumber($value) + { + $this->pageNumber = isset($value) ? $value : 1; + } + + /** + * Set Show Grid + * + * @param boolean value show grid of the document or not + * @return void + * @access public + */ + public function setShowGrid($value) + { + $this->showGrid = (isset($value) && $value == 'on') ? 1 : 0; + } + + public function setShowColor($value) + { + $this->showColor = (isset($value) && $value == 'on') ? 1 : 0; + } + + /** + * Set Table Dimension + * + * @param boolean value show table co-ordinates or not + * @return void + * @access public + */ + public function setTableDimension($value) + { + $this->tableDimension = (isset($value) && $value == 'on') ? 1 : 0; + } + + /** + * Set same width of All Tables + * + * @param boolean value set same width of all tables or not + * @return void + * @access public + */ + public function setAllTableSameWidth($value) + { + $this->sameWide = (isset($value) && $value == 'on') ? 1 : 0; + } + + /** + * Set Data Dictionary + * + * @param boolean value show selected database data dictionary or not + * @return void + * @access public + */ + public function setWithDataDictionary($value) + { + $this->withDoc = (isset($value) && $value == 'on') ? 1 : 0; + } + + /** + * Set Show only keys + * + * @param boolean value show only keys or not + * @return void + * @access public + */ + public function setShowKeys($value) + { + $this->showKeys = (isset($value) && $value == 'on') ? 1 : 0; + } + + /** + * Set Orientation + * + * @param string value Orientation will be portrait or landscape + * @return void + * @access public + */ + public function setOrientation($value) + { + $this->orientation = (isset($value) && $value == 'P') ? 'P' : 'L'; + } + + /** + * Set type of paper + * + * @param string value paper type can be A4 etc + * @return void + * @access public + */ + public function setPaper($value) + { + $this->paper = isset($value) ? $value : 'A4'; + } + + /** + * Set title of the page + * + * @param string value title of the page displayed at top of the document + * @return void + * @access public + */ + public function setPageTitle($title) + { + $this->_pageTitle=$title; + } + + /** + * Set type of export relational schema + * + * @param string value can be pdf,svg,dia,visio,eps etc + * @return void + * @access public + */ + public function setExportType($value) + { + $this->exportType=$value; + } + + /** + * get all tables involved or included in page + * + * @param string db name of the database + * @param integer pageNumber page number whose tables will be fetched in an array + * @return Array an array of tables + * @access public + */ + public function getAllTables($db,$pageNumber) + { + global $cfgRelation; + // Get All tables + $tab_sql = 'SELECT table_name FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) + . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' + . ' AND pdf_page_number = ' . $pageNumber; + + $tab_rs = PMA_query_as_controluser($tab_sql, null, PMA_DBI_QUERY_STORE); + if (!$tab_rs || !PMA_DBI_num_rows($tab_rs) > 0) { + $this->_die('',__('No tables')); + } + while ($curr_table = @PMA_DBI_fetch_assoc($tab_rs)) { + $alltables[] = PMA_sqlAddslashes($curr_table['table_name']); + } + return $alltables; + } + + /** + * Displays an error message + * + * @param integer pageNumber ID of the page choosen + * @param string type Schema Type + * @param string error_message the error mesage + * @global array the PMA configuration array + * @global integer the current server id + * @global string the current language + * @global string the charset to convert to + * @global string the current database name + * @global string the current charset + * @global string the current text direction + * @global string a localized string + * @global string an other localized string + * @access public + * @return void + */ + function dieSchema($pageNumber, $type = '', $error_message = '') + { + global $cfg; + global $server, $lang, $convcharset, $db; + global $charset, $text_dir; + + require_once './libraries/header.inc.php'; + echo "<p><strong>" . __("SCHEMA ERROR: ") . $type ."</strong></p>" . "\n"; + if (!empty($error_message)) { + $error_message = htmlspecialchars($error_message); + } + echo '<p>' . "\n"; + echo ' ' . $error_message . "\n"; + echo '</p>' . "\n"; + echo '<a href="schema_edit.php?' . PMA_generate_common_url($db).'&do=selectpage&chpage='.$pageNumber.'&action_choose=0' + . '">' . __('Back') . '</a>'; + echo "\n"; + require_once './libraries/footer.inc.php'; + exit(); + } +} +?> diff --git a/libraries/schema/Pdf_Relation_Schema.class.php b/libraries/schema/Pdf_Relation_Schema.class.php new file mode 100644 index 0000000..78e6387 --- /dev/null +++ b/libraries/schema/Pdf_Relation_Schema.class.php @@ -0,0 +1,1352 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * + * @version $Id$ + * @package phpMyAdmin + */ + +include_once("Export_Relation_Schema.class.php"); + +/** + * Font used in PDF. + * + * @todo Make this configuratble (at least Sans/Serif). + */ +define('PMA_PDF_FONT', 'DejaVuSans'); +require_once './libraries/tcpdf/tcpdf.php'; + +/** + * Extends the "TCPDF" class and helps + * in developing the structure of PDF Schema Export + * + * @name PMA_PDF + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + * @access public + * @see TCPDF + */ +class PMA_PDF extends TCPDF +{ + /** + * Defines properties + */ + var $_xMin; + var $_yMin; + var $leftMargin = 10; + var $topMargin = 10; + var $scale; + var $PMA_links; + var $Outlines = array(); + var $def_outlines; + var $Alias = array(); + var $widths; + + public function getFh() + { + return $this->fh; + } + + public function getFw() + { + return $this->fw; + } + + public function setCMargin($c_margin) + { + $this->cMargin = $c_margin; + } + + function SetAlias($name, $value) + { + $this->Alias[$name] = $value ; + } + + function _putpages() + { + if (count($this->Alias) > 0) { + $nb = $this->page; + foreach ($this->Alias as $alias => $value) { + for ($n = 1;$n <= $nb;$n++) + $this->pages[$n]=str_replace($alias, $value, $this->pages[$n]); + } + } + parent::_putpages(); + } + + // added because tcpdf for PHP 5 has a protected $buffer + public function getBuffer() + { + return $this->buffer; + } + + public function getState() + { + return $this->state; + } + + /** + * Sets the scaling factor, defines minimum coordinates and margins + * + * @param float scale The scaling factor + * @param float _xMin The minimum X coordinate + * @param float _yMin The minimum Y coordinate + * @param float leftMargin The left margin + * @param float topMargin The top margin + * @access public + */ + function PMA_PDF_setScale($scale = 1, $xMin = 0, $yMin = 0, $leftMargin = -1, $topMargin = -1) + { + $this->scale = $scale; + $this->_xMin = $xMin; + $this->_yMin = $yMin; + if ($this->leftMargin != -1) { + $this->leftMargin = $leftMargin; + } + if ($this->topMargin != -1) { + $this->topMargin = $topMargin; + } + } + + /** + * Outputs a scaled cell + * + * @param float w The cell width + * @param float h The cell height + * @param string txt The text to output + * @param mixed border Whether to add borders or not + * @param integer ln Where to put the cursor once the output is done + * @param string align Align mode + * @param integer fill Whether to fill the cell with a color or not + * @access public + * @see TCPDF::Cell() + */ + function PMA_PDF_cellScale($w, $h = 0, $txt = '', $border = 0, $ln = 0, $align = '', $fill = 0, $link = '') + { + $h = $h / $this->scale; + $w = $w / $this->scale; + $this->Cell($w, $h, $txt, $border, $ln, $align, $fill, $link); + } + + /** + * Draws a scaled line + * + * @param float x1 The horizontal position of the starting point + * @param float y1 The vertical position of the starting point + * @param float x2 The horizontal position of the ending point + * @param float y2 The vertical position of the ending point + * @access public + * @see TCPDF::Line() + */ + function PMA_PDF_lineScale($x1, $y1, $x2, $y2) + { + $x1 = ($x1 - $this->_xMin) / $this->scale + $this->leftMargin; + $y1 = ($y1 - $this->_yMin) / $this->scale + $this->topMargin; + $x2 = ($x2 - $this->_xMin) / $this->scale + $this->leftMargin; + $y2 = ($y2 - $this->_yMin) / $this->scale + $this->topMargin; + $this->Line($x1, $y1, $x2, $y2); + } + + /** + * Sets x and y scaled positions + * + * @param float x The x position + * @param float y The y position + * @access public + * @see TCPDF::SetXY() + */ + function PMA_PDF_setXyScale($x, $y) + { + $x = ($x - $this->_xMin) / $this->scale + $this->leftMargin; + $y = ($y - $this->_yMin) / $this->scale + $this->topMargin; + $this->SetXY($x, $y); + } + + /** + * Sets the X scaled positions + * + * @param float x The x position + * @access public + * @see TCPDF::SetX() + */ + function PMA_PDF_setXScale($x) + { + $x = ($x - $this->_xMin) / $this->scale + $this->leftMargin; + $this->SetX($x); + } + + /** + * Sets the scaled font size + * + * @param float size The font size (in points) + * @access public + * @see TCPDF::SetFontSize() + */ + function PMA_PDF_setFontSizeScale($size) + { + // Set font size in points + $size = $size / $this->scale; + $this->SetFontSize($size); + } + + /** + * Sets the scaled line width + * + * @param float width The line width + * @access public + * @see TCPDF::SetLineWidth() + */ + function PMA_PDF_setLineWidthScale($width) + { + $width = $width / $this->scale; + $this->SetLineWidth($width); + } + + /** + * Displays an error message + * + * @param string error_message the error mesage + * @access public + * @see PMA_Export_Relation_Schema::dieSchema + */ + function Error($error_message = '') + { + PMA_Export_Relation_Schema::dieSchema($error_message); + } + + function Header() + { + // We only show this if we find something in the new pdf_pages table + + // This function must be named "Header" to work with the TCPDF library + global $cfgRelation, $db, $pdf_page_number, $with_doc; + if ($with_doc) { + $test_query = 'SELECT * FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['pdf_pages']) + . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' + . ' AND page_nr = \'' . $pdf_page_number . '\''; + $test_rs = PMA_query_as_controluser($test_query); + $pages = @PMA_DBI_fetch_assoc($test_rs); + $this->SetFont('', 'B', 14); + $this->Cell(0, 6, ucfirst($pages['page_descr']), 'B', 1, 'C'); + $this->SetFont('', ''); + $this->Ln(); + } + } + + function Footer() + { + // This function must be named "Footer" to work with the TCPDF library + global $with_doc; + if ($with_doc) { + $this->SetY(-15); + $this->SetFont('', '', 14); + $this->Cell(0, 6, __('Page number:') . ' ' . $this->PageNo() . '/{nb}', 'T', 0, 'C'); + $this->Cell(0, 6, PMA_localisedDate(), 0, 1, 'R'); + $this->SetY(20); + } + } + + function Bookmark($txt, $level = 0, $y = 0) + { + // Add a bookmark + $this->Outlines[0][] = $level; + $this->Outlines[1][] = $txt; + $this->Outlines[2][] = $this->page; + if ($y == -1) { + $y = $this->GetY(); + } + $this->Outlines[3][] = round($this->hPt - $y * $this->k, 2); + } + + function _putbookmarks() + { + if (count($this->Outlines) > 0) { + // Save object number + $memo_n = $this->n; + // Take the number of sub elements for an outline + $nb_outlines = sizeof($this->Outlines[0]); + $first_level = array(); + $parent = array(); + $parent[0] = 1; + for ($i = 0; $i < $nb_outlines; $i++) { + $level = $this->Outlines[0][$i]; + $kids = 0; + $last = -1; + $prev = -1; + $next = -1; + if ($i > 0) { + $cursor = $i-1; + // Take the previous outline in the same level + while ($this->Outlines[0][$cursor] > $level && $cursor > 0) + $cursor--; + if ($this->Outlines[0][$cursor] == $level) { + $prev = $cursor; + } + } + if ($i < $nb_outlines-1) { + $cursor = $i + 1; + while (isset($this->Outlines[0][$cursor]) && $this->Outlines[0][$cursor] > $level) { + // Take the immediate kid in level + 1 + if ($this->Outlines[0][$cursor] == $level + 1) { + $kids++; + $last = $cursor; + } + $cursor++; + } + $cursor = $i + 1; + // Take the next outline in the same level + while ($this->Outlines[0][$cursor] > $level && ($cursor + 1 < sizeof($this->Outlines[0]))) + $cursor++; + if ($this->Outlines[0][$cursor] == $level) { + $next = $cursor; + } + } + $this->_newobj(); + $parent[$level + 1] = $this->n; + if ($level == 0) { + $first_level[] = $this->n; + } + $this->_out('<<'); + $this->_out('/Title (' . $this->Outlines[1][$i] . ')'); + $this->_out('/Parent ' . $parent[$level] . ' 0 R'); + if ($prev != -1) { + $this->_out('/Prev ' . ($memo_n + $prev + 1) . ' 0 R'); + } + if ($next != -1) { + $this->_out('/Next ' . ($this->n + $next - $i) . ' 0 R'); + } + $this->_out('/Dest [' . (1 + (2 * $this->Outlines[2][$i])) . ' 0 R /XYZ null ' . $this->Outlines[3][$i] . ' null]'); + if ($kids > 0) { + $this->_out('/First ' . ($this->n + 1) . ' 0 R'); + $this->_out('/Last ' . ($this->n + $last - $i) . ' 0 R'); + $this->_out('/Count -' . $kids); + } + $this->_out('>>'); + $this->_out('endobj'); + } + // First page of outlines + $this->_newobj(); + $this->def_outlines = $this->n; + $this->_out('<<'); + $this->_out('/Type'); + $this->_out('/Outlines'); + $this->_out('/First ' . $first_level[0] . ' 0 R'); + $this->_out('/Last ' . $first_level[sizeof($first_level)-1] . ' 0 R'); + $this->_out('/Count ' . sizeof($first_level)); + $this->_out('>>'); + $this->_out('endobj'); + } + } + + function _putresources() + { + parent::_putresources(); + $this->_putbookmarks(); + } + + function _putcatalog() + { + parent::_putcatalog(); + if (count($this->Outlines) > 0) { + $this->_out('/Outlines ' . $this->def_outlines . ' 0 R'); + $this->_out('/PageMode /UseOutlines'); + } + } + + function SetWidths($w) + { + // column widths + $this->widths = $w; + } + + function Row($data, $links) + { + // line height + $nb = 0; + $data_cnt = count($data); + for ($i = 0;$i < $data_cnt;$i++) + $nb = max($nb, $this->NbLines($this->widths[$i], $data[$i])); + $il = $this->FontSize; + $h = ($il + 1) * $nb; + // page break if necessary + $this->CheckPageBreak($h); + // draw the cells + $data_cnt = count($data); + for ($i = 0;$i < $data_cnt;$i++) { + $w = $this->widths[$i]; + // save current position + $x = $this->GetX(); + $y = $this->GetY(); + // draw the border + $this->Rect($x, $y, $w, $h); + if (isset($links[$i])) { + $this->Link($x, $y, $w, $h, $links[$i]); + } + // print text + $this->MultiCell($w, $il + 1, $data[$i], 0, 'L'); + // go to right side + $this->SetXY($x + $w, $y); + } + // go to line + $this->Ln($h); + } + + function CheckPageBreak($h) + { + // if height h overflows, manual page break + if ($this->GetY() + $h > $this->PageBreakTrigger) { + $this->AddPage($this->CurOrientation); + } + } + + function NbLines($w, $txt) + { + // compute number of lines used by a multicell of width w + $cw = &$this->CurrentFont['cw']; + if ($w == 0) { + $w = $this->w - $this->rMargin - $this->x; + } + $wmax = ($w-2 * $this->cMargin) * 1000 / $this->FontSize; + $s = str_replace("\r", '', $txt); + $nb = strlen($s); + if ($nb > 0 and $s[$nb-1] == "\n") { + $nb--; + } + $sep = -1; + $i = 0; + $j = 0; + $l = 0; + $nl = 1; + while ($i < $nb) { + $c = $s[$i]; + if ($c == "\n") { + $i++; + $sep = -1; + $j = $i; + $l = 0; + $nl++; + continue; + } + if ($c == ' ') { + $sep = $i; + } + $l += isset($cw[ord($c)])?$cw[ord($c)]:0 ; + if ($l > $wmax) { + if ($sep == -1) { + if ($i == $j) { + $i++; + } + } else { + $i = $sep + 1; + } + $sep = -1; + $j = $i; + $l = 0; + $nl++; + } else { + $i++; + } + } + return $nl; + } +} + +/** + * Table preferences/statistics + * + * This class preserves the table co-ordinates,fields + * and helps in drawing/generating the Tables in PDF document. + * + * @name Table_Stats + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + * @see PMA_PDF + */ +class Table_Stats +{ + /** + * Defines properties + */ + private $_tableName; + private $_showInfo = false; + + public $nb_fiels; + public $width = 0; + public $height; + public $fields = array(); + public $heightCell = 6; + public $x, $y; + public $primary = array(); + + /** + * The "Table_Stats" constructor + * + * @param string table_name The table name + * @param integer fontSize The font size + * @param integer pageNumber The current page number (from the + * $cfg['Servers'][$i]['table_coords'] table) + * @param integer sameWideWidth The max. with among tables + * @param boolean showKeys Whether to display keys or not + * @param boolean showInfo Whether to display table position or not + * @global object The current PDF document + * @global array The relations settings + * @global string The current db name + * @see PMA_PDF, Table_Stats::Table_Stats_setWidth, + Table_Stats::Table_Stats_setHeight + */ + function __construct($tableName, $fontSize, $pageNumber, &$sameWideWidth, $showKeys = false, $showInfo = false) + { + global $pdf, $cfgRelation, $db; + + $this->_tableName = $tableName; + $sql = 'DESCRIBE ' . PMA_backquote($tableName); + $result = PMA_DBI_try_query($sql, null, PMA_DBI_QUERY_STORE); + if (!$result || !PMA_DBI_num_rows($result)) { + $pdf->Error(sprintf(__('The %s table doesn\'t exist!'), $tableName)); + } + // load fields + //check to see if it will load all fields or only the foreign keys + if ($showKeys) { + $indexes = PMA_Index::getFromTable($this->_tableName, $db); + $all_columns = array(); + foreach ($indexes as $index) { + $all_columns = array_merge($all_columns, array_flip(array_keys($index->getColumns()))); + } + $this->fields = array_keys($all_columns); + } else { + while ($row = PMA_DBI_fetch_row($result)) { + $this->fields[] = $row[0]; + } + } + + $this->_showInfo = $showInfo; + $this->_setHeight(); + /* + * setWidth must me after setHeight, because title + * can include table height which changes table width + */ + $this->_setWidth($fontSize); + if ($sameWideWidth < $this->width) { + $sameWideWidth = $this->width; + } + $sql = 'SELECT x, y FROM ' + . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) + . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' + . ' AND table_name = \'' . PMA_sqlAddslashes($tableName) . '\'' + . ' AND pdf_page_number = ' . $pageNumber; + $result = PMA_query_as_controluser($sql, false, PMA_DBI_QUERY_STORE); + if (!$result || !PMA_DBI_num_rows($result)) { + $pdf->Error(sprintf(__('Please configure the coordinates for table %s'), $tableName)); + } + list($this->x, $this->y) = PMA_DBI_fetch_row($result); + $this->x = (double) $this->x; + $this->y = (double) $this->y; + /* + * displayfield + */ + $this->displayfield = PMA_getDisplayField($db, $tableName); + /* + * index + */ + $result = PMA_DBI_query('SHOW INDEX FROM ' . PMA_backquote($tableName) . ';', null, PMA_DBI_QUERY_STORE); + if (PMA_DBI_num_rows($result) > 0) { + while ($row = PMA_DBI_fetch_assoc($result)) { + if ($row['Key_name'] == 'PRIMARY') { + $this->primary[] = $row['Column_name']; + } + } + } + } + + /** + * Returns title of the current table, + * title can have the dimensions of the table + * + * @access private + */ + private function _getTitle() + { + return ($this->_showInfo ? sprintf('%.0f', $this->width) . 'x' . sprintf('%.0f', $this->height) : '') . ' ' . $this->_tableName; + } + + /** + * Sets the width of the table + * + * @param integer fontSize The font size + * @global object The current PDF document + * @access private + * @see PMA_PDF + */ + function _setWidth($fontSize) + { + global $pdf; + + foreach ($this->fields as $field) { + $this->width = max($this->width, $pdf->GetStringWidth($field)); + } + $this->width += $pdf->GetStringWidth(' '); + $pdf->SetFont($fontSize, 'B'); + /* + * it is unknown what value must be added, because + * table title is affected by the tabe width value + */ + while ($this->width < $pdf->GetStringWidth($this->_getTitle())) { + $this->width += 5; + } + $pdf->SetFont($fontSize, ''); + } + + /** + * Sets the height of the table + * + * @access private + */ + private function _setHeight() + { + $this->height = (count($this->fields) + 1) * $this->heightCell; + } + + /** + * Do draw the table + * + * @param integer fontSize The font size + * @param boolean setColor Whether to display color + * @global object The current PDF document + * @access public + * @see PMA_PDF + */ + public function tableDraw($fontSize, $withDoc, $setColor = 0) + { + global $pdf, $withDoc; + + $pdf->PMA_PDF_setXyScale($this->x, $this->y); + $pdf->SetFont($fontSize, 'B'); + if ($setColor) { + $pdf->SetTextColor(200); + $pdf->SetFillColor(0, 0, 128); + } + if ($withDoc) { + $pdf->SetLink($pdf->PMA_links['RT'][$this->_tableName]['-'], -1); + } else { + $pdf->PMA_links['doc'][$this->_tableName]['-'] = ''; + } + + $pdf->PMA_PDF_cellScale($this->width, $this->heightCell, $this->_getTitle(), 1, 1, 'C', $setColor, $pdf->PMA_links['doc'][$this->_tableName]['-']); + $pdf->PMA_PDF_setXScale($this->x); + $pdf->SetFont($fontSize, ''); + $pdf->SetTextColor(0); + $pdf->SetFillColor(255); + + foreach ($this->fields as $field) { + if ($setColor) { + if (in_array($field, $this->primary)) { + $pdf->SetFillColor(215, 121, 123); + } + if ($field == $this->displayfield) { + $pdf->SetFillColor(142, 159, 224); + } + } + if ($withDoc) { + $pdf->SetLink($pdf->PMA_links['RT'][$this->_tableName][$field], -1); + } else { + $pdf->PMA_links['doc'][$this->_tableName][$field] = ''; + } + + $pdf->PMA_PDF_cellScale($this->width, $this->heightCell, ' ' . $field, 1, 1, 'L', $setColor, $pdf->PMA_links['doc'][$this->_tableName][$field]); + $pdf->PMA_PDF_setXScale($this->x); + $pdf->SetFillColor(255); + } + /*if ($pdf->PageNo() > 1) { + $pdf->PMA_PDF_die(__('The scale factor is too small to fit the schema on one page')); + } */ + } +} + +/** + * Relation preferences/statistics + * + * This class fetches the table master and foreign fields positions + * and helps in generating the Table references and then connects + * master table's master field to foreign table's foreign key + * in PDF document. + * + * @name Relation_Stats + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + * @see PMA_PDF::SetDrawColor,PMA_PDF::PMA_PDF_setLineWidthScale,PMA_PDF::PMA_PDF_lineScale + */ +class Relation_Stats +{ + /** + * Defines properties + */ + public $xSrc, $ySrc; + public $srcDir; + public $destDir; + public $xDest, $yDest; + public $wTick = 5; + + /** + * The "Relation_Stats" constructor + * + * @param string master_table The master table name + * @param string master_field The relation field in the master table + * @param string foreign_table The foreign table name + * @param string foreigh_field The relation field in the foreign table + * @see Relation_Stats::_getXy + */ + function __construct($master_table, $master_field, $foreign_table, $foreign_field) + { + $src_pos = $this->_getXy($master_table, $master_field); + $dest_pos = $this->_getXy($foreign_table, $foreign_field); + /* + * [0] is x-left + * [1] is x-right + * [2] is y + */ + $src_left = $src_pos[0] - $this->wTick; + $src_right = $src_pos[1] + $this->wTick; + $dest_left = $dest_pos[0] - $this->wTick; + $dest_right = $dest_pos[1] + $this->wTick; + + $d1 = abs($src_left - $dest_left); + $d2 = abs($src_right - $dest_left); + $d3 = abs($src_left - $dest_right); + $d4 = abs($src_right - $dest_right); + $d = min($d1, $d2, $d3, $d4); + + if ($d == $d1) { + $this->xSrc = $src_pos[0]; + $this->srcDir = -1; + $this->xDest = $dest_pos[0]; + $this->destDir = -1; + } elseif ($d == $d2) { + $this->xSrc = $src_pos[1]; + $this->srcDir = 1; + $this->xDest = $dest_pos[0]; + $this->destDir = -1; + } elseif ($d == $d3) { + $this->xSrc = $src_pos[0]; + $this->srcDir = -1; + $this->xDest = $dest_pos[1]; + $this->destDir = 1; + } else { + $this->xSrc = $src_pos[1]; + $this->srcDir = 1; + $this->xDest = $dest_pos[1]; + $this->destDir = 1; + } + $this->ySrc = $src_pos[2]; + $this->yDest = $dest_pos[2]; + } + + /** + * Gets arrows coordinates + * + * @param string table The current table name + * @param string column The relation column name + * @return array Arrows coordinates + * @access private + */ + private function _getXy($table, $column) + { + $pos = array_search($column, $table->fields); + // x_left, x_right, y + return array($table->x, $table->x + + $table->width, $table->y + ($pos + 1.5) * $table->heightCell); + } + + /** + * draws relation links and arrows + * shows foreign key relations + * + * @param boolean changeColor Whether to use one color per relation or not + * @param integer i The id of the link to draw + * @global object The current PDF document + * @access public + * @see PMA_PDF + */ + public function relationDraw($changeColor, $i) + { + global $pdf; + + if ($changeColor) { + $d = $i % 6; + $j = ($i - $d) / 6; + $j = $j % 4; + $j++; + $case = array( + array(1, 0, 0), + array(0, 1, 0), + array(0, 0, 1), + array(1, 1, 0), + array(1, 0, 1), + array(0, 1, 1) + ); + list ($a, $b, $c) = $case[$d]; + $e = (1 - ($j - 1) / 6); + $pdf->SetDrawColor($a * 255 * $e, $b * 255 * $e, $c * 255 * $e); + } else { + $pdf->SetDrawColor(0); + } + $pdf->PMA_PDF_setLineWidthScale(0.2); + $pdf->PMA_PDF_lineScale($this->xSrc, $this->ySrc, $this->xSrc + $this->srcDir * $this->wTick, $this->ySrc); + $pdf->PMA_PDF_lineScale($this->xDest + $this->destDir * $this->wTick, $this->yDest, $this->xDest, $this->yDest); + $pdf->PMA_PDF_setLineWidthScale(0.1); + $pdf->PMA_PDF_lineScale($this->xSrc + $this->srcDir * $this->wTick, $this->ySrc, $this->xDest + $this->destDir * $this->wTick, $this->yDest); + /* + * Draws arrows -> + */ + $root2 = 2 * sqrt(2); + $pdf->PMA_PDF_lineScale($this->xSrc + $this->srcDir * $this->wTick * 0.75, $this->ySrc, $this->xSrc + $this->srcDir * (0.75 - 1 / $root2) * $this->wTick, $this->ySrc + $this->wTick / $root2); + $pdf->PMA_PDF_lineScale($this->xSrc + $this->srcDir * $this->wTick * 0.75, $this->ySrc, $this->xSrc + $this->srcDir * (0.75 - 1 / $root2) * $this->wTick, $this->ySrc - $this->wTick / $root2); + + $pdf->PMA_PDF_lineScale($this->xDest + $this->destDir * $this->wTick / 2, $this->yDest, $this->xDest + $this->destDir * (0.5 + 1 / $root2) * $this->wTick, $this->yDest + $this->wTick / $root2); + $pdf->PMA_PDF_lineScale($this->xDest + $this->destDir * $this->wTick / 2, $this->yDest, $this->xDest + $this->destDir * (0.5 + 1 / $root2) * $this->wTick, $this->yDest - $this->wTick / $root2); + $pdf->SetDrawColor(0); + } +} + +/** + * Pdf Relation Schema Class + * + * Purpose of this class is to generate the PDF Document. PDF is widely + * used format for documenting text,fonts,images and 3d vector graphics. + * + * This class inherits Export_Relation_Schema class has common functionality added + * to this class + * + * @name Pdf_Relation_Schema + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + */ +class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema +{ + /** + * Defines properties + */ + private $_tables = array(); + private $_relations = array(); + private $_ff = PMA_PDF_FONT; + private $_xMax = 0; + private $_yMax = 0; + private $scale; + private $_xMin = 100000; + private $_yMin = 100000; + private $topMargin = 10; + private $bottomMargin = 10; + private $leftMargin = 10; + private $rightMargin = 10; + private $_tablewidth; + + /** + * The "PMA_Pdf_Relation_Schema" constructor + * + * @global object The current PDF Schema document + * @global string The current db name + * @global array The relations settings + * @access private + * @see PMA_PDF + */ + function __construct() + { + global $pdf,$db,$cfgRelation; + + $this->setPageNumber($_POST['pdf_page_number']); + $this->setShowGrid(isset($_POST['show_grid'])); + $this->setShowColor(isset($_POST['show_color'])); + $this->setShowKeys(isset($_POST['show_keys'])); + $this->setTableDimension(isset($_POST['show_table_dimension'])); + $this->setAllTableSameWidth(isset($_POST['all_table_same_wide'])); + $this->setWithDataDictionary($_POST['with_doc']); + $this->setOrientation($_POST['orientation']); + $this->setPaper($_POST['paper']); + $this->setExportType($_POST['export_type']); + + // Initializes a new document + $pdf = new PMA_PDF('L', 'mm', $this->paper); + $pdf->SetTitle(sprintf(__('Schema of the %s database - Page %s'), $GLOBALS['db'], $this->pageNumber)); + $pdf->setCMargin(0); + $pdf->Open(); + $pdf->SetAuthor('phpMyAdmin ' . PMA_VERSION); + $pdf->AliasNbPages(); + $pdf->AddFont('DejaVuSans', '', 'dejavusans.php'); + $pdf->AddFont('DejaVuSans', 'B', 'dejavusansb.php'); + $pdf->AddFont('DejaVuSerif', '', 'dejavuserif.php'); + $pdf->AddFont('DejaVuSerif', 'B', 'dejavuserifb.php'); + $pdf->SetFont($this->_ff, '', 14); + $pdf->SetAutoPageBreak('auto'); + $alltables = $this->getAllTables($db,$this->pageNumber); + + if ($this->withDoc) { + $pdf->SetAutoPageBreak('auto', 15); + $pdf->setCMargin(1); + $this->dataDictionaryDoc($alltables); + $pdf->SetAutoPageBreak('auto'); + $pdf->setCMargin(0); + } + + $pdf->Addpage(); + + if ($this->withDoc) { + $pdf->SetLink($pdf->PMA_links['RT']['-'], -1); + $pdf->Bookmark(__('Relational schema')); + $pdf->SetAlias('{00}', $pdf->PageNo()) ; + $this->topMargin = 28; + $this->bottomMargin = 28; + } + + /* snip */ + foreach ($alltables as $table) { + if (!isset($this->tables[$table])) { + $this->tables[$table] = new Table_Stats($table, $this->_ff, $this->pageNumber, $this->_tablewidth, $this->showKeys, $this->tableDimension); + } + if ($this->sameWide) { + $this->tables[$table]->width = $this->_tablewidth; + } + $this->_setMinMax($this->tables[$table]); + } + + // Defines the scale factor + $this->scale = ceil( + max( + ($this->_xMax - $this->_xMin) / ($pdf->getFh() - $this->rightMargin - $this->leftMargin), + ($this->_yMax - $this->_yMin) / ($pdf->getFw() - $this->topMargin - $this->bottomMargin)) + * 100) / 100; + + $pdf->PMA_PDF_setScale($this->scale, $this->_xMin, $this->_yMin, $this->leftMargin, $this->topMargin); + // Builds and save the PDF document + $pdf->PMA_PDF_setLineWidthScale(0.1); + + if ($this->showGrid) { + $pdf->SetFontSize(10); + $this->_strokeGrid(); + } + $pdf->PMA_PDF_setFontSizeScale(14); + // previous logic was checking master tables and foreign tables + // but I think that looping on every table of the pdf page as a master + // and finding its foreigns is OK (then we can support innodb) + $seen_a_relation = false; + foreach ($alltables as $one_table) { + $exist_rel = PMA_getForeigners($db, $one_table, '', 'both'); + if ($exist_rel) { + $seen_a_relation = true; + foreach ($exist_rel as $master_field => $rel) { + // put the foreign table on the schema only if selected + // by the user + // (do not use array_search() because we would have to + // to do a === FALSE and this is not PHP3 compatible) + if (in_array($rel['foreign_table'], $alltables)) { + $this->_addRelation($one_table, $master_field, $rel['foreign_table'], $rel['foreign_field'], $this->tableDimension); + } + } // end while + } // end if + } // end while + + if ($seen_a_relation) { + $this->_drawRelations($this->showColor); + } + $this->_drawTables($this->showColor); + $this->_showOutput($this->pageNumber); + exit(); + } + + /** + * Sets X and Y minimum and maximum for a table cell + * + * @param string table The table name of which sets XY co-ordinates + * @access private + */ + private function _setMinMax($table) + { + $this->_xMax = max($this->_xMax, $table->x + $table->width); + $this->_yMax = max($this->_yMax, $table->y + $table->height); + $this->_xMin = min($this->_xMin, $table->x); + $this->_yMin = min($this->_yMin, $table->y); + } + + /** + * Defines relation objects + * + * @param string master_table The master table name + * @param string master_field The relation field in the master table + * @param string foreign_table The foreign table name + * @param string foreign_field The relation field in the foreign table + * @param boolean show_info Whether to display table position or not + * @access private + * @see _setMinMax + */ + private function _addRelation($masterTable, $masterField, $foreignTable, $foreignField, $showInfo) + { + if (!isset($this->tables[$masterTable])) { + $this->tables[$masterTable] = new Table_Stats($masterTable, $this->_ff, $this->pageNumber, $this->_tablewidth, false, $showInfo); + $this->_setMinMax($this->tables[$masterTable]); + } + if (!isset($this->tables[$foreignTable])) { + $this->tables[$foreignTable] = new Table_Stats($foreignTable, $this->_ff, $this->pageNumber, $this->_tablewidth, false, $showInfo); + $this->_setMinMax($this->tables[$foreignTable]); + } + $this->relations[] = new Relation_Stats($this->tables[$masterTable], $masterField, $this->tables[$foreignTable], $foreignField); + } + + /** + * Draws the grid + * + * @global object the current PMA_PDF instance + * @access private + * @see PMA_PDF + */ + private function _strokeGrid() + { + global $pdf; + + $pdf->SetMargins(0, 0); + $pdf->SetDrawColor(200, 200, 200); + // Draws horizontal lines + for ($l = 0; $l < 21; $l++) { + $pdf->line(0, $l * 10, $pdf->getFh(), $l * 10); + // Avoid duplicates + if ($l > 0) { + $pdf->SetXY(0, $l * 10); + $label = (string) sprintf('%.0f', ($l * 10 - $this->topMargin) * $this->scale + $this->_yMin); + $pdf->Cell(5, 5, ' ' . $label); + } // end if + } // end for + // Draws vertical lines + for ($j = 0; $j < 30 ;$j++) { + $pdf->line($j * 10, 0, $j * 10, $pdf->getFw()); + $pdf->SetXY($j * 10, 0); + $label = (string) sprintf('%.0f', ($j * 10 - $this->leftMargin) * $this->scale + $this->_xMin); + $pdf->Cell(5, 7, $label); + } + } + + /** + * Draws relation arrows + * + * @param boolean changeColor Whether to use one color per relation or not + * @access private + * @see Relation_Stats::relationdraw() + */ + private function _drawRelations($changeColor) + { + $i = 0; + foreach ($this->relations as $relation) { + $relation->relationDraw($changeColor, $i); + $i++; + } + } + + /** + * Draws tables + * + * @param boolean changeColor Whether to display table position or not + * @access private + * @see Table_Stats::tableDraw() + */ + private function _drawTables($changeColor = 0) + { + foreach ($this->tables as $table) { + $table->tableDraw($this->_ff, $this->withDoc, $changeColor); + } + } + + /** + * Ouputs the PDF document to a file + * or sends the output to browser + * + * @global object The current PDF document + * @global string The current database name + * @global integer The current page number (from the + * $cfg['Servers'][$i]['table_coords'] table) + * @access private + * @see PMA_PDF + */ + private function _showOutput($pageNumber) + { + global $pdf, $db, $cfgRelation; + + $pdf->SetFontSize(14); + $pdf->SetLineWidth(0.2); + $pdf->SetDisplayMode('fullpage'); + // Get the name of this pdfpage to use as filename (Mike Beck) + $_name_sql = 'SELECT page_descr FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['pdf_pages']) + . ' WHERE page_nr = ' . $pageNumber; + $_name_rs = PMA_query_as_controluser($_name_sql); + if ($_name_rs) { + $_name_row = PMA_DBI_fetch_row($_name_rs); + $filename = $_name_row[0] . '.pdf'; + } + if (empty($filename)) { + $filename = $pageNumber . '.pdf'; + } + // instead of $pdf->Output(): + $pdfData = $pdf->getPDFData(); + header('Content-Type: application/pdf'); + header('Content-Length: '.strlen($pdfData).''); + header('Content-disposition: attachment; filename="'.$filename.'"'); + echo $pdfData; + } + + public function dataDictionaryDoc($alltables) + { + global $db, $pdf, $orientation, $paper; + // TOC + $pdf->addpage($GLOBALS['orientation']); + $pdf->Cell(0, 9, __('Table of contents'), 1, 0, 'C'); + $pdf->Ln(15); + $i = 1; + foreach ($alltables as $table) { + $pdf->PMA_links['doc'][$table]['-'] = $pdf->AddLink(); + $pdf->SetX(10); + // $pdf->Ln(1); + $pdf->Cell(0, 6, __('Page number:') . ' {' . sprintf("%02d", $i + 1) . '}', 0, 0, 'R', 0, $pdf->PMA_links['doc'][$table]['-']); + $pdf->SetX(10); + $pdf->Cell(0, 6, $i . ' ' . $table, 0, 1, 'L', 0, $pdf->PMA_links['doc'][$table]['-']); + // $pdf->Ln(1); + $result = PMA_DBI_query('SHOW FIELDS FROM ' . PMA_backquote($table) . ';'); + while ($row = PMA_DBI_fetch_assoc($result)) { + $pdf->SetX(20); + $field_name = $row['Field']; + $pdf->PMA_links['doc'][$table][$field_name] = $pdf->AddLink(); + // $pdf->Cell(0, 6, $field_name,0,1,'L',0, $pdf->PMA_links['doc'][$table][$field_name]); + } + $lasttable = $table; + $i++; + } + $pdf->PMA_links['RT']['-'] = $pdf->AddLink(); + $pdf->SetX(10); + $pdf->Cell(0, 6, __('Page number:') . ' {' . sprintf("%02d", $i + 1) . '}', 0, 0, 'R', 0, $pdf->PMA_links['doc'][$lasttable]['-']); + $pdf->SetX(10); + $pdf->Cell(0, 6, $i + 1 . ' ' . __('Relational schema'), 0, 1, 'L', 0, $pdf->PMA_links['RT']['-']); + $z = 0; + foreach ($alltables as $table) { + $z++; + $pdf->addpage($GLOBALS['orientation']); + $pdf->Bookmark($table); + $pdf->SetAlias('{' . sprintf("%02d", $z) . '}', $pdf->PageNo()) ; + $pdf->PMA_links['RT'][$table]['-'] = $pdf->AddLink(); + $pdf->SetLink($pdf->PMA_links['doc'][$table]['-'], -1); + $pdf->SetFont('', 'B', 18); + $pdf->Cell(0, 8, $z . ' ' . $table, 1, 1, 'C', 0, $pdf->PMA_links['RT'][$table]['-']); + $pdf->SetFont('', '', 8); + $pdf->ln(); + + $cfgRelation = PMA_getRelationsParam(); + $comments = PMA_getComments($db, $table); + if ($cfgRelation['mimework']) { + $mime_map = PMA_getMIME($db, $table, true); + } + + /** + * Gets table informations + */ + $showtable = PMA_Table::sGetStatusInfo($db, $table); + $num_rows = (isset($showtable['Rows']) ? $showtable['Rows'] : 0); + $show_comment = (isset($showtable['Comment']) ? $showtable['Comment'] : ''); + $create_time = (isset($showtable['Create_time']) ? PMA_localisedDate(strtotime($showtable['Create_time'])) : ''); + $update_time = (isset($showtable['Update_time']) ? PMA_localisedDate(strtotime($showtable['Update_time'])) : ''); + $check_time = (isset($showtable['Check_time']) ? PMA_localisedDate(strtotime($showtable['Check_time'])) : ''); + + /** + * Gets table keys and retains them + */ + $result = PMA_DBI_query('SHOW KEYS FROM ' . PMA_backquote($table) . ';'); + $primary = ''; + $indexes = array(); + $lastIndex = ''; + $indexes_info = array(); + $indexes_data = array(); + $pk_array = array(); // will be use to emphasis prim. keys in the table + // view + while ($row = PMA_DBI_fetch_assoc($result)) { + // Backups the list of primary keys + if ($row['Key_name'] == 'PRIMARY') { + $primary .= $row['Column_name'] . ', '; + $pk_array[$row['Column_name']] = 1; + } + // Retains keys informations + if ($row['Key_name'] != $lastIndex) { + $indexes[] = $row['Key_name']; + $lastIndex = $row['Key_name']; + } + $indexes_info[$row['Key_name']]['Sequences'][] = $row['Seq_in_index']; + $indexes_info[$row['Key_name']]['Non_unique'] = $row['Non_unique']; + if (isset($row['Cardinality'])) { + $indexes_info[$row['Key_name']]['Cardinality'] = $row['Cardinality']; + } + // I don't know what does following column mean.... + // $indexes_info[$row['Key_name']]['Packed'] = $row['Packed']; + $indexes_info[$row['Key_name']]['Comment'] = $row['Comment']; + + $indexes_data[$row['Key_name']][$row['Seq_in_index']]['Column_name'] = $row['Column_name']; + if (isset($row['Sub_part'])) { + $indexes_data[$row['Key_name']][$row['Seq_in_index']]['Sub_part'] = $row['Sub_part']; + } + } // end while + if ($result) { + PMA_DBI_free_result($result); + } + + /** + * Gets fields properties + */ + $result = PMA_DBI_query('SHOW FIELDS FROM ' . PMA_backquote($table) . ';', null, PMA_DBI_QUERY_STORE); + $fields_cnt = PMA_DBI_num_rows($result); + // Check if we can use Relations (Mike Beck) + if (!empty($cfgRelation['relation'])) { + // Find which tables are related with the current one and write it in + // an array + $res_rel = PMA_getForeigners($db, $table); + + if (count($res_rel) > 0) { + $have_rel = true; + } else { + $have_rel = false; + } + } else { + $have_rel = false; + } // end if + + /** + * Displays the comments of the table if MySQL >= 3.23 + */ + + $break = false; + if (!empty($show_comment)) { + $pdf->Cell(0, 3, __('Table comments') . ' : ' . $show_comment, 0, 1); + $break = true; + } + + if (!empty($create_time)) { + $pdf->Cell(0, 3, __('Creation') . ': ' . $create_time, 0, 1); + $break = true; + } + + if (!empty($update_time)) { + $pdf->Cell(0, 3, __('Last update') . ': ' . $update_time, 0, 1); + $break = true; + } + + if (!empty($check_time)) { + $pdf->Cell(0, 3, __('Last check') . ': ' . $check_time, 0, 1); + $break = true; + } + + if ($break == true) { + $pdf->Cell(0, 3, '', 0, 1); + $pdf->Ln(); + } + + $pdf->SetFont('', 'B'); + if (isset($orientation) && $orientation == 'L') { + $pdf->Cell(25, 8, ucfirst(__('Column')), 1, 0, 'C'); + $pdf->Cell(20, 8, ucfirst(__('Type')), 1, 0, 'C'); + $pdf->Cell(20, 8, ucfirst(__('Attributes')), 1, 0, 'C'); + $pdf->Cell(10, 8, ucfirst(__('Null')), 1, 0, 'C'); + $pdf->Cell(20, 8, ucfirst(__('Default')), 1, 0, 'C'); + $pdf->Cell(25, 8, ucfirst(__('Extra')), 1, 0, 'C'); + $pdf->Cell(45, 8, ucfirst(__('Links to')), 1, 0, 'C'); + + if ($paper == 'A4') { + $comments_width = 67; + } else { + // this is really intended for 'letter' + /** + * @todo find optimal width for all formats + */ + $comments_width = 50; + } + $pdf->Cell($comments_width, 8, ucfirst(__('Comments')), 1, 0, 'C'); + $pdf->Cell(45, 8, 'MIME', 1, 1, 'C'); + $pdf->SetWidths(array(25, 20, 20, 10, 20, 25, 45, $comments_width, 45)); + } else { + $pdf->Cell(20, 8, ucfirst(__('Column')), 1, 0, 'C'); + $pdf->Cell(20, 8, ucfirst(__('Type')), 1, 0, 'C'); + $pdf->Cell(20, 8, ucfirst(__('Attributes')), 1, 0, 'C'); + $pdf->Cell(10, 8, ucfirst(__('Null')), 1, 0, 'C'); + $pdf->Cell(15, 8, ucfirst(__('Default')), 1, 0, 'C'); + $pdf->Cell(15, 8, ucfirst(__('Extra')), 1, 0, 'C'); + $pdf->Cell(30, 8, ucfirst(__('Links to')), 1, 0, 'C'); + $pdf->Cell(30, 8, ucfirst(__('Comments')), 1, 0, 'C'); + $pdf->Cell(30, 8, 'MIME', 1, 1, 'C'); + $pdf->SetWidths(array(20, 20, 20, 10, 15, 15, 30, 30, 30)); + } + $pdf->SetFont('', ''); + + while ($row = PMA_DBI_fetch_assoc($result)) { + $type = $row['Type']; + // reformat mysql query output + // set or enum types: slashes single quotes inside options + if (preg_match('@^(set|enum)\((.+)\)$@i', $type, $tmp)) { + $tmp[2] = substr(preg_replace("@([^,])''@", "\\1\\'", ',' . $tmp[2]), 1); + $type = $tmp[1] . '(' . str_replace(',', ', ', $tmp[2]) . ')'; + $type_nowrap = ''; + + $binary = 0; + $unsigned = 0; + $zerofill = 0; + } else { + $type_nowrap = ' nowrap="nowrap"'; + $type = preg_replace('@BINARY@i', '', $type); + $type = preg_replace('@ZEROFILL@i', '', $type); + $type = preg_replace('@UNSIGNED@i', '', $type); + if (empty($type)) { + $type = ' '; + } + + $binary = stristr($row['Type'], 'BINARY'); + $unsigned = stristr($row['Type'], 'UNSIGNED'); + $zerofill = stristr($row['Type'], 'ZEROFILL'); + } + $attribute = ' '; + if ($binary) { + $attribute = 'BINARY'; + } + if ($unsigned) { + $attribute = 'UNSIGNED'; + } + if ($zerofill) { + $attribute = 'UNSIGNED ZEROFILL'; + } + if (!isset($row['Default'])) { + if ($row['Null'] != '' && $row['Null'] != 'NO') { + $row['Default'] = 'NULL'; + } + } + $field_name = $row['Field']; + // $pdf->Ln(); + $pdf->PMA_links['RT'][$table][$field_name] = $pdf->AddLink(); + $pdf->Bookmark($field_name, 1, -1); + $pdf->SetLink($pdf->PMA_links['doc'][$table][$field_name], -1); + $pdf_row = array($field_name, + $type, + $attribute, + ($row['Null'] == '' || $row['Null'] == 'NO') ? __('No') : __('Yes'), + ((isset($row['Default'])) ? $row['Default'] : ''), + $row['Extra'], + ((isset($res_rel[$field_name])) ? $res_rel[$field_name]['foreign_table'] . ' -> ' . $res_rel[$field_name]['foreign_field'] : ''), + ((isset($comments[$field_name])) ? $comments[$field_name] : ''), + ((isset($mime_map) && isset($mime_map[$field_name])) ? str_replace('_', '/', $mime_map[$field_name]['mimetype']) : '') + ); + $links[0] = $pdf->PMA_links['RT'][$table][$field_name]; + if (isset($res_rel[$field_name]['foreign_table']) AND + isset($res_rel[$field_name]['foreign_field']) AND + isset($pdf->PMA_links['doc'][$res_rel[$field_name]['foreign_table']][$res_rel[$field_name]['foreign_field']]) + ) + { + $links[6] = $pdf->PMA_links['doc'][$res_rel[$field_name]['foreign_table']][$res_rel[$field_name]['foreign_field']]; + } else { + unset($links[6]); + } + $pdf->Row($pdf_row, $links); + } // end while + $pdf->SetFont('', '', 14); + PMA_DBI_free_result($result); + } //end each + } +} +?> \ No newline at end of file diff --git a/libraries/schema/Svg_Relation_Schema.class.php b/libraries/schema/Svg_Relation_Schema.class.php new file mode 100644 index 0000000..a0bba96 --- /dev/null +++ b/libraries/schema/Svg_Relation_Schema.class.php @@ -0,0 +1,854 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * + * @version $Id$ + * @package phpMyAdmin + */ + +include_once("Export_Relation_Schema.class.php"); + +/** + * This Class inherits the XMLwriter class and + * helps in developing structure of SVG Schema Export + * + * @name PMA_SVG + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + * @access public + * @see http://php.net/manual/en/book.xmlwriter.php + */ + +class PMA_SVG extends XMLWriter +{ + public $title; + public $author; + public $font; + public $fontSize; + + /** + * The "PMA_SVG" constructor + * + * Upon instantiation This starts writing the Svg XML document + * + * @return void + * @see XMLWriter::openMemory(),XMLWriter::setIndent(),XMLWriter::startDocument() + */ + function __construct() + { + $this->openMemory(); + /* + * Set indenting using three spaces, + * so output is formatted + */ + + $this->setIndent(TRUE); + $this->setIndentString(' '); + /* + * Create the XML document + */ + + $this->startDocument('1.0','UTF-8'); + $this->startDtd('svg','-//W3C//DTD SVG 1.1//EN','http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'); + $this->endDtd(); + } + + /** + * Set document title + * + * @param string value sets the title text + * @return void + * @access public + */ + function setTitle($value) + { + $this->title = $value; + } + + /** + * Set document author + * + * @param string value sets the author + * @return void + * @access public + */ + function setAuthor($value) + { + $this->author = $value; + } + + /** + * Set document font + * + * @param string value sets the font e.g Arial, Sans-serif etc + * @return void + * @access public + */ + function setFont($value) + { + $this->font = $value; + } + + /** + * Get document font + * + * @return string returns the font name + * @access public + */ + function getFont() + { + return $this->font; + } + + /** + * Set document font size + * + * @param string value sets the font size in pixels + * @return void + * @access public + */ + function setFontSize($value) + { + $this->fontSize = $value; + } + + /** + * Get document font size + * + * @return string returns the font size + * @access public + */ + function getFontSize() + { + return $this->fontSize; + } + + /** + * Starts Svg Document + * + * svg document starts by first initializing svg tag + * which contains all the attributes and namespace that needed + * to define the svg document + * + * @param integer width total width of the Svg document + * @param integer height total height of the Svg document + * @return void + * @access public + * @see XMLWriter::startElement(),XMLWriter::writeAttribute() + */ + function startSvgDoc($width,$height) + { + $this->startElement('svg'); + $this->writeAttribute('width', $width); + $this->writeAttribute('height', $height); + $this->writeAttribute('xmlns', 'http://www.w3.org/2000/svg'); + $this->writeAttribute('version', '1.1'); + } + + /** + * Ends Svg Document + * + * @return void + * @access public + * @see XMLWriter::endElement(),XMLWriter::endDocument() + */ + function endSvgDoc() + { + $this->endElement(); + $this->endDocument(); + } + + /** + * output Svg Document + * + * svg document prompted to the user for download + * Svg document saved in .svg extension and can be + * easily changeable by using any svg IDE + * + * @return void + * @access public + * @see XMLWriter::startElement(),XMLWriter::writeAttribute() + */ + function showOutput($fileName) + { + //ob_get_clean(); + header('Content-type: image/svg+xml'); + header('Content-Disposition: attachment; filename="'.$fileName.'.svg"'); + $output = $this->flush(); + print $output; + } + + /** + * Draws Svg elements + * + * SVG has some predefined shape elements like rectangle & text + * and other elements who have x,y co-ordinates are drawn. + * specify their width and height and can give styles too. + * + * @param string name Svg element name + * @param integer x The x attribute defines the left position of the element + (e.g. x="0" places the element 0 pixels from the left of + the browser window) + * @param integer y The y attribute defines the top position of the element + (e.g. y="0" places the element 0 pixels from the top of + the browser window) + * @param integer width The width attribute defines the width the element + * @param integer height The height attribute defines the height the element + * @param string text The text attribute defines the text the element + * @param string styles The style attribute defines the style the element + styles can be defined like CSS styles + * @return void + * @access public + * @see XMLWriter::startElement(),XMLWriter::writeAttribute(),XMLWriter::text(),XMLWriter::endElement() + */ + function printElement($name,$x,$y,$width = '',$height = '',$text = '',$styles = '') + { + $this->startElement($name); + $this->writeAttribute('width',$width); + $this->writeAttribute('height',$height); + $this->writeAttribute('x', $x); + $this->writeAttribute('y', $y); + $this->writeAttribute('style', $styles); + if(isset($text)){ + $this->writeAttribute('font-family', $this->font); + $this->writeAttribute('font-size', $this->fontSize); + $this->text($text); + } + $this->endElement(); + } + + /** + * Draws Svg Line element + * + * Svg line element is drawn for connecting the tables. + * arrows are also drawn by specify its start and ending + * co-ordinates + * + * @param string name Svg element name i.e line + * @param integer x1 The x1 attribute defines the start of the line on the x-axis + * @param integer y1 The y1 attribute defines the start of the line on the y-axis + * @param integer x2 The x2 attribute defines the end of the line on the x-axis + * @param integer y2 The y2 attribute defines the end of the line on the y-axis + * @param string styles The style attribute defines the style the element + styles can be defined like CSS styles + * @return void + * @access public + * @see XMLWriter::startElement(),XMLWriter::writeAttribute(),XMLWriter::endElement() + */ + function printElementLine($name,$x1,$y1,$x2,$y2,$styles) + { + $this->startElement($name); + $this->writeAttribute('x1',$x1); + $this->writeAttribute('y1',$y1); + $this->writeAttribute('x2', $x2); + $this->writeAttribute('y2', $y2); + $this->writeAttribute('style', $styles); + $this->endElement(); + } + + /** + * get width of string/text + * + * Svg text element width is calcualted depending on font name + * and font size. It is very important to know the width of text + * because rectangle is drawn around it. + * + * This is a bit hardcore method. I didn't found any other than this. + * + * @param string text string that width will be calculated + * @param integer font name of the font like Arial,sans-serif etc + * @param integer fontSize size of font + * @return integer width of the text + * @access public + */ + function getStringWidth($text,$font,$fontSize) + { + /* + * Start by counting the width, giving each character a modifying value + */ + $count = 0; + $count = $count + ((strlen($text) - strlen(str_replace(array("i","j","l"),"",$text)))*0.23);//ijl + $count = $count + ((strlen($text) - strlen(str_replace(array("f"),"",$text)))*0.27);//f + $count = $count + ((strlen($text) - strlen(str_replace(array("t","I"),"",$text)))*0.28);//tI + $count = $count + ((strlen($text) - strlen(str_replace(array("r"),"",$text)))*0.34);//r + $count = $count + ((strlen($text) - strlen(str_replace(array("1"),"",$text)))*0.49);//1 + $count = $count + ((strlen($text) - strlen(str_replace(array("c","k","s","v","x","y","z","J"),"",$text)))*0.5);//cksvxyzJ + $count = $count + ((strlen($text) - strlen(str_replace(array("a","b","d","e","g","h","n","o","p","q","u","L","0","2","3","4","5","6","7","8","9"),"",$text)))*0.56);//abdeghnopquL023456789 + $count = $count + ((strlen($text) - strlen(str_replace(array("F","T","Z"),"",$text)))*0.61);//FTZ + $count = $count + ((strlen($text) - strlen(str_replace(array("A","B","E","K","P","S","V","X","Y"),"",$text)))*0.67);//ABEKPSVXY + $count = $count + ((strlen($text) - strlen(str_replace(array("w","C","D","H","N","R","U"),"",$text)))*0.73);//wCDHNRU + $count = $count + ((strlen($text) - strlen(str_replace(array("G","O","Q"),"",$text)))*0.78);//GOQ + $count = $count + ((strlen($text) - strlen(str_replace(array("m","M"),"",$text)))*0.84);//mM + $count = $count + ((strlen($text) - strlen(str_replace("W","",$text)))*.95);//W + $count = $count + ((strlen($text) - strlen(str_replace(" ","",$text)))*.28);//" " + $text = str_replace(" ","",$text);//remove the " "'s + $count = $count + (strlen(preg_replace("/[a-z0-9]/i","",$text))*0.3); //all other chrs + + $modifier = 1; + $font = strtolower($font); + switch($font){ + /* + * no modifier for arial and sans-serif + */ + case 'arial': + case 'sans-serif': + break; + /* + * .92 modifer for time, serif, brushscriptstd, and californian fb + */ + case 'times': + case 'serif': + case 'brushscriptstd': + case 'californian fb': + $modifier = .92; + break; + /* + * 1.23 modifier for broadway + */ + case 'broadway': + $modifier = 1.23; + break; + } + $textWidth = $count*$fontSize; + return ceil($textWidth*$modifier); + } +} + +/** + * Table preferences/statistics + * + * This class preserves the table co-ordinates,fields + * and helps in drawing/generating the Tables in SVG XML document. + * + * @name Table_Stats + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + * @see PMA_SVG + */ +class Table_Stats +{ + /** + * Defines properties + */ + + private $_tableName; + private $_showInfo = false; + + public $width = 0; + public $height; + public $fields = array(); + public $heightCell = 0; + public $currentCell = 0; + public $x, $y; + public $primary = array(); + + /** + * The "Table_Stats" constructor + * + * @param string table_name The table name + * @param integer ff The font size + * @param integer samewidth The max. with among tables + * @param boolean show_keys Whether to display keys or not + * @param boolean show_info Whether to display table position or not + * @global object The current SVG image document + * @global integer The current page number (from the + * $cfg['Servers'][$i]['table_coords'] table) + * @global array The relations settings + * @global string The current db name + * @access private + * @see PMA_SVG, Table_Stats::Table_Stats_setWidth, + Table_Stats::Table_Stats_setHeight + */ + function __construct($tableName, $font, $fontSize, $pageNumber, &$same_wide_width, $showKeys = false, $showInfo = false) + { + global $svg, $cfgRelation, $db; + + $this->_tableName = $tableName; + $sql = 'DESCRIBE ' . PMA_backquote($tableName); + $result = PMA_DBI_try_query($sql, null, PMA_DBI_QUERY_STORE); + if (!$result || !PMA_DBI_num_rows($result)) { + $svg->dieSchema($pageNumber,"SVG",sprintf(__('The %s table doesn\'t exist!'), $tableName)); + } + + /* + * load fields + * check to see if it will load all fields or only the foreign keys + */ + + if ($showKeys) { + $indexes = PMA_Index::getFromTable($this->_tableName, $db); + $all_columns = array(); + foreach ($indexes as $index) { + $all_columns = array_merge($all_columns, array_flip(array_keys($index->getColumns()))); + } + $this->fields = array_keys($all_columns); + } else { + while ($row = PMA_DBI_fetch_row($result)) { + $this->fields[] = $row[0]; + } + } + + $this->_showInfo = $showInfo; + + // height and width + $this->_setHeightTable($fontSize); + + // setWidth must me after setHeight, because title + // can include table height which changes table width + $this->_setWidthTable($font,$fontSize); + if ($same_wide_width < $this->width) { + $same_wide_width = $this->width; + } + + // x and y + $sql = 'SELECT x, y FROM ' + . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) + . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' + . ' AND table_name = \'' . PMA_sqlAddslashes($tableName) . '\'' + . ' AND pdf_page_number = ' . $pageNumber; + $result = PMA_query_as_controluser($sql, false, PMA_DBI_QUERY_STORE); + + if (!$result || !PMA_DBI_num_rows($result)) { + $svg->dieSchema($pageNumber,"SVG",sprintf(__('Please configure the coordinates for table %s'), $tableName)); + } + list($this->x, $this->y) = PMA_DBI_fetch_row($result); + $this->x = (double) $this->x; + $this->y = (double) $this->y; + // displayfield + $this->displayfield = PMA_getDisplayField($db, $tableName); + // index + $result = PMA_DBI_query('SHOW INDEX FROM ' . PMA_backquote($tableName) . ';', null, PMA_DBI_QUERY_STORE); + if (PMA_DBI_num_rows($result) > 0) { + while ($row = PMA_DBI_fetch_assoc($result)) { + if ($row['Key_name'] == 'PRIMARY') { + $this->primary[] = $row['Column_name']; + } + } + } + } + + /** + * Returns title of the current table, + * title can have the dimensions/co-ordinates of the table + * + * @access private + */ + private function _getTitle() + { + return ($this->_showInfo ? sprintf('%.0f', $this->width) . 'x' . sprintf('%.0f', $this->heightCell) : '') . ' ' . $this->_tableName; + } + + /** + * Sets the width of the table + * + * @param string font The font size + * @param integer fontSize The font size + * @global object The current SVG image document + * @access private + * @see PMA_SVG + */ + function _setWidthTable($font,$fontSize) + { + global $svg; + + foreach ($this->fields as $field) { + $this->width = max($this->width, $svg->getStringWidth($field,$font,$fontSize)); + } + $this->width += $svg->getStringWidth(' ',$font,$fontSize); + /* + * it is unknown what value must be added, because + * table title is affected by the tabe width value + */ + while ($this->width < $svg->getStringWidth($this->_getTitle(),$font,$fontSize)) { + $this->width += 7; + } + } + + /** + * Sets the height of the table + * + * @access private + */ + function _setHeightTable($fontSize) + { + $this->heightCell = $fontSize + 4; + $this->height = (count($this->fields) + 1) * $this->heightCell; + } + + /** + * draw the table + * + * @param boolean showColor Whether to display color + * @global object The current SVG image document + * @access public + * @see PMA_SVG,PMA_SVG::printElement + */ + public function tableDraw($showColor) + { + global $svg; + //echo $this->_tableName.'<br />'; + $svg->printElement('rect',$this->x,$this->y, + $this->width,$this->heightCell, + NULL,'fill:red;stroke:black;' + ); + $svg->printElement('text',$this->x + 5,$this->y+ 14, + $this->width,$this->heightCell, + $this->_getTitle(), + 'fill:none;stroke:black;' + ); + foreach ($this->fields as $field) { + $this->currentCell += $this->heightCell; + $showColor = 'none'; + if ($showColor) { + if (in_array($field, $this->primary)) { + $showColor = '#0c0'; + } + if ($field == $this->displayfield) { + $showColor = 'none'; + } + } + $svg->printElement('rect', $this->x,$this->y + $this->currentCell, + $this->width, $this->heightCell, + NULL, + 'fill:'.$showColor.';stroke:black;' + ); + $svg->printElement('text', $this->x + 5, $this->y + 14 + $this->currentCell, + $this->width, $this->heightCell, + $field, + 'fill:none;stroke:black;' + ); + } + } +} + + +/** + * Relation preferences/statistics + * + * This class fetches the table master and foreign fields positions + * and helps in generating the Table references and then connects + * master table's master field to foreign table's foreign key + * in SVG XML document. + * + * @name Relation_Stats + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + * @see PMA_SVG::printElementLine + */ +class Relation_Stats +{ + /** + * Defines properties + */ + public $xSrc, $ySrc; + public $srcDir ; + public $destDir; + public $xDest, $yDest; + public $wTick = 10; + + /** + * The "Relation_Stats" constructor + * + * @param string master_table The master table name + * @param string master_field The relation field in the master table + * @param string foreign_table The foreign table name + * @param string foreigh_field The relation field in the foreign table + * @see Relation_Stats::_getXy + */ + function __construct($master_table, $master_field, $foreign_table, $foreign_field) + { + $src_pos = $this->_getXy($master_table, $master_field); + $dest_pos = $this->_getXy($foreign_table, $foreign_field); + /* + * [0] is x-left + * [1] is x-right + * [2] is y + */ + $src_left = $src_pos[0] - $this->wTick; + $src_right = $src_pos[1] + $this->wTick; + $dest_left = $dest_pos[0] - $this->wTick; + $dest_right = $dest_pos[1] + $this->wTick; + + $d1 = abs($src_left - $dest_left); + $d2 = abs($src_right - $dest_left); + $d3 = abs($src_left - $dest_right); + $d4 = abs($src_right - $dest_right); + $d = min($d1, $d2, $d3, $d4); + + if ($d == $d1) { + $this->xSrc = $src_pos[0]; + $this->srcDir = -1; + $this->xDest = $dest_pos[0]; + $this->destDir = -1; + } elseif ($d == $d2) { + $this->xSrc = $src_pos[1]; + $this->srcDir = 1; + $this->xDest = $dest_pos[0]; + $this->destDir = -1; + } elseif ($d == $d3) { + $this->xSrc = $src_pos[0]; + $this->srcDir = -1; + $this->xDest = $dest_pos[1]; + $this->destDir = 1; + } else { + $this->xSrc = $src_pos[1]; + $this->srcDir = 1; + $this->xDest = $dest_pos[1]; + $this->destDir = 1; + } + $this->ySrc = $src_pos[2]; + $this->yDest = $dest_pos[2]; + } + + /** + * Gets arrows coordinates + * + * @param string table The current table name + * @param string column The relation column name + * @return array Arrows coordinates + * @access private + */ + function _getXy($table, $column) + { + $pos = array_search($column, $table->fields); + // x_left, x_right, y + return array($table->x, $table->x + $table->width, $table->y + ($pos + 1.5) * $table->heightCell); + } + + /** + * draws relation links and arrows + * shows foreign key relations + * + * @param boolean changeColor Whether to use one color per relation or not + * @global object The current SVG image document + * @access public + * @see PMA_SVG + */ + public function relationDraw($changeColor) + { + global $svg; + + if ($changeColor) { + $listOfColors = array( + 'red', + 'grey', + 'black', + 'yellow', + 'green', + 'cyan', + ' orange' + ); + shuffle($listOfColors); + $color = $listOfColors[0]; + } else { + $color = 'black'; + } + + $svg->printElementLine('line',$this->xSrc,$this->ySrc, + $this->xSrc + $this->srcDir * $this->wTick,$this->ySrc, + 'fill:'.$color.';stroke:black;stroke-width:2;' + ); + $svg->printElementLine('line',$this->xDest + $this->destDir * $this->wTick, $this->yDest, + $this->xDest, $this->yDest, + 'fill:'.$color.';stroke:black;stroke-width:2;' + ); + $svg->printElementLine('line',$this->xSrc + $this->srcDir * $this->wTick,$this->ySrc, + $this->xDest + $this->destDir * $this->wTick, $this->yDest, + 'fill:'.$color.';stroke:'.$color.';stroke-width:1;' + ); + $root2 = 2 * sqrt(2); + $svg->printElementLine('line',$this->xSrc + $this->srcDir * $this->wTick * 0.75, $this->ySrc, + $this->xSrc + $this->srcDir * (0.75 - 1 / $root2) * $this->wTick , + $this->ySrc + $this->wTick / $root2 , + 'fill:'.$color.';stroke:black;stroke-width:2;' + ); + $svg->printElementLine('line',$this->xSrc + $this->srcDir * $this->wTick * 0.75, $this->ySrc, + $this->xSrc + $this->srcDir * (0.75 - 1 / $root2) * $this->wTick , + $this->ySrc - $this->wTick / $root2 , + 'fill:'.$color.';stroke:black;stroke-width:2;' + ); + $svg->printElementLine('line',$this->xDest + $this->destDir * $this->wTick / 2 , $this->yDest , + $this->xDest + $this->destDir * (0.5 + 1 / $root2) * $this->wTick, + $this->yDest + $this->wTick / $root2 , + 'fill:'.$color.';stroke:black;stroke-width:2;'); + $svg->printElementLine('line',$this->xDest + $this->destDir * $this->wTick / 2 , + $this->yDest , $this->xDest + $this->destDir * (0.5 + 1 / $root2) * $this->wTick , + $this->yDest - $this->wTick / $root2 , + 'fill:'.$color.';stroke:black;stroke-width:2;' + ); + } +} +/* +* end of the "Relation_Stats" class +*/ + +/** + * Svg Relation Schema Class + * + * Purpose of this class is to generate the SVG XML Document because + * SVG defines the graphics in XML format which is used for representing + * the database diagrams as vector image. This class actually helps + * in preparing SVG XML format. + * + * SVG XML is generated by using XMLWriter php extension and this class + * inherits Export_Relation_Schema class has common functionality added + * to this class + * + * @name Svg_Relation_Schema + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + */ +class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema +{ + + private $tables = array(); + private $_relations = array(); + private $_xMax = 0; + private $_yMax = 0; + private $scale; + private $_xMin = 100000; + private $_yMin = 100000; + private $t_marg = 10; + private $b_marg = 10; + private $l_marg = 10; + private $r_marg = 10; + private $_tablewidth; + + /** + * The "PMA_Svg_Relation_Schema" constructor + * + * Upon instantiation This starts writing the SVG XML document + * user will be prompted for download as .svg extension + * + * @return void + * @see PMA_SVG + */ + function __construct() + { + global $svg,$db; + + $this->setPageNumber($_POST['pdf_page_number']); + $this->setShowColor(isset($_POST['show_color'])); + $this->setShowKeys(isset($_POST['show_keys'])); + $this->setTableDimension(isset($_POST['show_table_dimension'])); + $this->setAllTableSameWidth(isset($_POST['all_table_same_wide'])); + $this->setExportType($_POST['export_type']); + + $svg = new PMA_SVG(); + $svg->setTitle(sprintf(__('Schema of the %s database - Page %s'), $db, $this->pageNumber)); + $svg->SetAuthor('phpMyAdmin ' . PMA_VERSION); + $svg->setFont('Arial'); + $svg->setFontSize('16px'); + $svg->startSvgDoc('1000px','1000px'); + $alltables = $this->getAllTables($db,$this->pageNumber); + + foreach ($alltables AS $table) { + if (!isset($this->tables[$table])) { + $this->tables[$table] = new Table_Stats($table,$svg->getFont(),$svg->getFontSize(), $this->pageNumber, $this->_tablewidth, $this->showKeys, $this->tableDimension); + } + + if ($this->sameWide) { + $this->tables[$table]->width = $this->_tablewidth; + } + $this->_setMinMax($this->tables[$table]); + } + $seen_a_relation = false; + foreach ($alltables as $one_table) { + $exist_rel = PMA_getForeigners($db, $one_table, '', 'both'); + if ($exist_rel) { + $seen_a_relation = true; + foreach ($exist_rel as $master_field => $rel) { + /* put the foreign table on the schema only if selected + * by the user + * (do not use array_search() because we would have to + * to do a === FALSE and this is not PHP3 compatible) + */ + if (in_array($rel['foreign_table'], $alltables)) { + $this->_addRelation($one_table,$svg->getFont(),$svg->getFontSize(), $master_field, $rel['foreign_table'], $rel['foreign_field'], $this->tableDimension); + } + } + } + } + if ($seen_a_relation) { + $this->_drawRelations($this->showColor); + } + + $this->_drawTables($this->showColor); + $svg->endSvgDoc(); + $svg->showOutput($db.'-'.$this->pageNumber); + exit(); + } + + /** + * Sets X and Y minimum and maximum for a table cell + * + * @param string table The table name + * @access private + */ + private function _setMinMax($table) + { + $this->_xMax = max($this->_xMax, $table->x + $table->width); + $this->_yMax = max($this->_yMax, $table->y + $table->height); + $this->_xMin = min($this->_xMin, $table->x); + $this->_yMin = min($this->_yMin, $table->y); + } + + /** + * Defines relation objects + * + * @param string masterTable The master table name + * @param string masterField The relation field in the master table + * @param string foreignTable The foreign table name + * @param string foreignField The relation field in the foreign table + * @param boolean showInfo Whether to display table position or not + * @access private + * @see _setMinMax,Table_Stats::__construct(),Relation_Stats::__construct() + */ + private function _addRelation($masterTable,$font,$fontSize, $masterField, $foreignTable, $foreignField, $showInfo) + { + if (!isset($this->tables[$masterTable])) { + $this->tables[$masterTable] = new Table_Stats($masterTable, $font, $fontSize, $this->pageNumber, $this->_tablewidth, false, $showInfo); + $this->_setMinMax($this->tables[$masterTable]); + } + if (!isset($this->tables[$foreignTable])) { + $this->tables[$foreignTable] = new Table_Stats($foreignTable,$font,$fontSize,$this->pageNumber, $this->_tablewidth, false, $showInfo); + $this->_setMinMax($this->tables[$foreignTable]); + } + $this->_relations[] = new Relation_Stats($this->tables[$masterTable], $masterField, $this->tables[$foreignTable], $foreignField); + } + + /** + * Draws relation arrows and lines + * connects master table's master field to + * foreign table's forein field + * + * @param boolean changeColor Whether to use one color per relation or not + * @access private + * @see Relation_Stats::relationDraw() + */ + private function _drawRelations($changeColor) + { + foreach ($this->_relations as $relation) { + $relation->relationDraw($changeColor); + } + } + + /** + * Draws tables + * + * @param boolean changeColor Whether to show color for primary fields or not + * @access private + * @see Table_Stats::Table_Stats_tableDraw() + */ + private function _drawTables($changeColor) + { + foreach ($this->tables as $table) { + $table->tableDraw($changeColor); + } + } +} +?> diff --git a/libraries/schema/User_Schema.class.php b/libraries/schema/User_Schema.class.php new file mode 100644 index 0000000..31aa6de --- /dev/null +++ b/libraries/schema/User_Schema.class.php @@ -0,0 +1,821 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * + * @version $Id$ + * @package phpMyAdmin + */ + +/** + * This Class interacts with the user to gather the information + * about their tables for which they want to export the relational schema + * export options are shown to user from they can choose + * + * @name User_Schema + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + */ + +class PMA_User_Schema +{ + + public $choosenPage; + public $autoLayoutForeign; + public $autoLayoutInternal; + public $pageNumber; + public $c_table_rows; + public $action; + + public function setAction($value) + { + $this->action = $value; + } + /** + * This function will process the user defined pages + * and tables which will be exported as Relational schema + * you can set the table positions on the paper via scratchboard + * for table positions, put the x,y co-ordinates + * + * @param string $this->action It tells what the Schema is supposed to do + * create and select a page, generate schema etc + * @access public + */ + + public function processUserPreferences() + { + global $action_choose,$db,$cfgRelation,$cfg,$query_default_option; + + if (isset($this->action)) { + switch ($this->action) { + case 'selectpage': + $this->choosenPage = $_REQUEST['chpage']; + if ($action_choose=="1") { + $this->deleteCoordinates($db, $cfgRelation, $this->choosenPage, $query_default_option); + $this->deletePages($db, $cfgRelation, $this->choosenPage, $query_default_option); + $this->choosenPage = 0; + } + break; + case 'createpage': + $this->pageNumber = PMA_REL_create_page($_POST['newpage'], $cfgRelation, $db, $query_default_option); + $this->autoLayoutForeign = isset($_POST['auto_layout_foreign']) ? "1":NULL; + $this->autoLayoutInternal = isset($_POST['auto_layout_internal']) ? "1":NULL; + $this->processRelations($db, $this->pageNumber,$cfgRelation,$query_default_option); + break; + case 'edcoord': + $this->choosenPage = $_POST['chpage']; + $this->c_table_rows = $_POST['c_table_rows']; + $this->_editCoordinates($db, $cfgRelation,$query_default_option); + break; + case 'deleteCrap': + $this->_deleteTableRows($delrow,$cfgRelation,$db,$this->choosenPage); + break; + case 'process_export': + $this->_processExportSchema(); + break; + + } // end switch + } // end if (isset($do)) + + } + + /** + * shows/displays the HTML FORM to create the page + * + * @param string db name of the selected database + * @return void + * @access public + */ + public function createPage($db) + { + ?> + <form method="post" action="schema_edit.php" name="frm_create_page"> + <fieldset> + <legend> + <?php echo __('Create a page') . "\n"; ?> + </legend> + <?php echo PMA_generate_common_hidden_inputs($db); ?> + <input type="hidden" name="do" value="createpage" /> + <table> + <tr> + <td><label for="id_newpage"><?php echo __('Page name'); ?></label></td> + <td><input type="text" name="newpage" id="id_newpage" size="20" maxlength="50" /></td> + </tr> + <tr> + <td><?php echo __('Automatic layout based on'); ?></td> + <td> + <input type="checkbox" name="auto_layout_internal" id="id_auto_layout_internal" /><label for="id_auto_layout_internal"> + <?php echo __('Internal relations'); ?></label><br /> + <?php + /* + * Check to see whether INNODB and PBXT storage engines are Available in MYSQL PACKAGE + * If available, then provide AutoLayout for Foreign Keys in Schema View + */ + + if (PMA_StorageEngine::isValid('InnoDB') || PMA_StorageEngine::isValid('PBXT')) { + ?> + <input type="checkbox" name="auto_layout_foreign" id="id_auto_layout_foreign" /><label for="id_auto_layout_foreign"> + <?php echo __('FOREIGN KEY'); ?></label><br /> + <?php + } + ?> + </td></tr> + </table> + </fieldset> + <fieldset class="tblFooters"> + <input type="submit" value="<?php echo __('Go'); ?>" /> + </fieldset> + </form> + <?php + } + + /** + * shows/displays the created page names in a drop down list + * User can select any page number and edit it using dashboard etc + * + * @return void + * @access public + */ + public function selectPage() + { + global $db,$table,$query_default_option,$cfgRelation; + $page_query = 'SELECT * FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['pdf_pages']) + . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\''; + $page_rs = PMA_query_as_controluser($page_query, FALSE, $query_default_option); + if ($page_rs && PMA_DBI_num_rows($page_rs) > 0) { + ?> + <form method="get" action="schema_edit.php" name="frm_select_page"> + <fieldset> + <legend> + <?php echo __('Please choose a page to edit') . "\n"; ?> + </legend> + <?php echo PMA_generate_common_hidden_inputs($db, $table); ?> + <input type="hidden" name="do" value="selectpage" /> + <select name="chpage" id="chpage" onchange="this.form.submit()"> + <option value="0"><?php echo __('Select page'); ?></option> + <?php + while ($curr_page = PMA_DBI_fetch_assoc($page_rs)) { + echo "\n" . ' ' + . '<option value="' . $curr_page['page_nr'] . '"'; + if (isset($this->choosenPage) && $this->choosenPage == $curr_page['page_nr']) { + echo ' selected="selected"'; + } + echo '>' . $curr_page['page_nr'] . ': ' . htmlspecialchars($curr_page['page_descr']) . '</option>'; + } // end while + echo "\n"; + ?> + </select> + <?php + $choices = array( + '0' => __('Edit'), + '1' => __('Delete') + ); + PMA_display_html_radio('action_choose', $choices, '0', false); + unset($choices); + ?> + </fieldset> + <fieldset class="tblFooters"> + <input type="submit" value="<?php echo __('Go'); ?>" /><br /> + </fieldset> + </form> + <?php + } // end IF + echo "\n"; + } // end function + + /** + * A dashboard is displayed to AutoLayout the position of tables + * users can drag n drop the tables and change their positions + * + * @return void + * @access public + */ + public function showTableDashBoard() + { + global $db,$cfgRelation,$table,$cfg,$with_field_names,$query_default_option; + /* + * We will need an array of all tables in this db + */ + $selectboxall = array('--'); + $alltab_rs = PMA_DBI_query('SHOW TABLES FROM ' . PMA_backquote($db) . ';', null, PMA_DBI_QUERY_STORE); + while ($val = @PMA_DBI_fetch_row($alltab_rs)) { + $selectboxall[] = $val[0]; + } + + /* + * Now if we already have chosen a page number then we should + * show the tables involved + */ + + if (isset($this->choosenPage) && $this->choosenPage > 0) { + echo "\n"; + ?> + <h2><?php echo __('Select Tables') ;?></h2> + <?php + $page_query = 'SELECT * FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) + . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' + . ' AND pdf_page_number = \'' . PMA_sqlAddslashes($this->choosenPage) . '\''; + $page_rs = PMA_query_as_controluser($page_query, FALSE, $query_default_option); + $array_sh_page = array(); + $draginit = ''; + $reset_draginit = ''; + $i = 0; + while ($temp_sh_page = @PMA_DBI_fetch_assoc($page_rs)) { + $array_sh_page[] = $temp_sh_page; + } + /* + * Display WYSIWYG-PDF parts? + */ + + if ($cfg['WYSIWYG-PDF']) { + if (!isset($_POST['with_field_names']) && !isset($_POST['showwysiwyg'])) { + $with_field_names = TRUE; + } + $this->_displayScratchboardTables($array_sh_page,$draginit,$reset_draginit); + } + ?> + + <form method="post" action="schema_edit.php" name="edcoord"> + <?php echo PMA_generate_common_hidden_inputs($db, $table); ?> + <input type="hidden" name="chpage" value="<?php echo htmlspecialchars($this->choosenPage); ?>" /> + <input type="hidden" name="do" value="edcoord" /> + <table border="0"> + <tr> + <th><?php echo __('Table'); ?></th> + <th><?php echo __('Delete'); ?></th> + <th>X</th> + <th>Y</th> + </tr> + <?php + if (isset($ctable)) { + unset($ctable); + } + + $i = 0; + $odd_row = true; + foreach ($array_sh_page as $dummy_sh_page => $sh_page) { + $_mtab = $sh_page['table_name']; + $tabExist[$_mtab] = FALSE; + echo "\n" . ' <tr class="'; + if ($odd_row) { + echo 'odd'; + } else { + echo 'even'; + } + echo '">'; + $odd_row != $odd_row; + echo "\n" . ' <td>' + . "\n" . ' <select name="c_table_' . $i . '[name]">'; + foreach ($selectboxall as $key => $value) { + echo "\n" . ' <option value="' . htmlspecialchars($value) . '"'; + if ($value == $sh_page['table_name']) { + echo ' selected="selected"'; + $tabExist[$_mtab] = TRUE; + } + echo '>' . htmlspecialchars($value) . '</option>'; + } + echo "\n" . ' </select>' + . "\n" . ' </td>'; + echo "\n" . ' <td>' + . "\n" . ' <input type="checkbox" name="c_table_' . $i . '[delete]" value="y" />' . __('Delete'); + echo "\n" . ' </td>'; + echo "\n" . ' <td>' + . "\n" . ' <input type="text" ' . ($cfg['WYSIWYG-PDF'] ? 'onchange="dragPlace(' . $i . ', \'x\', this.value)"' : '') . ' name="c_table_' . $i . '[x]" value="' . $sh_page['x'] . '" />'; + echo "\n" . ' </td>'; + echo "\n" . ' <td>' + . "\n" . ' <input type="text" ' . ($cfg['WYSIWYG-PDF'] ? 'onchange="dragPlace(' . $i . ', \'y\', this.value)"' : '') . ' name="c_table_' . $i . '[y]" value="' . $sh_page['y'] . '" />'; + echo "\n" . ' </td>'; + echo "\n" . ' </tr>'; + $i++; + } + /* + * Add one more empty row + */ + echo "\n" . ' <tr class="'; + if ($odd_row) { + echo 'odd'; + } else { + echo 'even'; + } + $odd_row != $odd_row; + echo '">'; + echo "\n" . ' <td>' + . "\n" . ' <select name="c_table_' . $i . '[name]">'; + foreach ($selectboxall as $key => $value) { + echo "\n" . ' <option value="' . htmlspecialchars($value) . '">' . htmlspecialchars($value) . '</option>'; + } + echo "\n" . ' </select>' + . "\n" . ' </td>'; + echo "\n" . ' <td>' + . "\n" . ' <input type="checkbox" name="c_table_' . $i . '[delete]" value="y" />' . __('Delete'); + echo "\n" . ' </td>'; + echo "\n" . ' <td>' + . "\n" . ' <input type="text" name="c_table_' . $i . '[x]" value="' . (isset($sh_page['x'])?$sh_page['x']:'') . '" />'; + echo "\n" . ' </td>'; + echo "\n" . ' <td>' + . "\n" . ' <input type="text" name="c_table_' . $i . '[y]" value="' . (isset($sh_page['y'])?$sh_page['y']:'') . '" />'; + echo "\n" . ' </td>'; + echo "\n" . ' </tr>'; + echo "\n" . ' </table>' . "\n"; + + echo "\n" . ' <input type="hidden" name="c_table_rows" value="' . ($i + 1) . '" />'; + echo ($cfg['WYSIWYG-PDF'] ? "\n" . ' <input type="hidden" id="showwysiwyg" name="showwysiwyg" value="' . ((isset($showwysiwyg) && $showwysiwyg == '1') ? '1' : '0') . '" />' : ''); + echo "\n" . ' <input type="checkbox" name="with_field_names" ' . (isset($with_field_names) ? 'checked="checked"' : ''). ' />' . __('Column names') . '<br />'; + echo "\n" . ' <input type="submit" value="' . __('Save') . '" />'; + echo "\n" . '</form>' . "\n\n"; + } // end if + + $this->_deleteTables($db, $this->choosenPage, isset($tabExist)); + } + + /** + * show Export relational schema generation options + * user can select export type of his own choice + * and the attributes related to it + * + * @return void + * @access public + */ + + public function displaySchemaGenerationOptions() + { + global $cfg,$pmaThemeImage,$db,$test_rs,$chpage; + ?> + <form method="post" action="schema_export.php"> + <fieldset> + <legend> + <?php + echo PMA_generate_common_hidden_inputs($db); + if ($cfg['PropertiesIconic']) { + echo '<img class="icon" src="' . $pmaThemeImage . 'b_view.png"' + .' alt="" width="16" height="16" />'; + } + echo __('Display relational schema'); + ?>: + </legend> + <select name="export_type" id="export_type"> + <option value="pdf" selected="selected"><?php echo __('PDF');?></option> + <option value="svg"><?php echo __('SVG');?></option> + <option value="dia"><?php echo __('DIA');?></option> + <option value="visio"><?php echo __('VISIO');?></option> + <option value="eps"><?php echo __('EPS');?></option> + </select> + <label><?php echo __('Select Export Relational Type');?></label><br /> + <?php + if (isset($test_rs)) { + ?> + <label for="pdf_page_number_opt"><?php echo __('Page number:'); ?></label> + <select name="pdf_page_number" id="pdf_page_number_opt"> + <?php + while ($pages = @PMA_DBI_fetch_assoc($test_rs)) { + echo ' <option value="' . $pages['page_nr'] . '">' + . $pages['page_nr'] . ': ' . htmlspecialchars($pages['page_descr']) . '</option>' . "\n"; + } // end while + PMA_DBI_free_result($test_rs); + unset($test_rs); + ?> + </select><br /> + <?php } else { ?> + <input type="hidden" name="pdf_page_number" value="<?php echo htmlspecialchars($this->choosenPage); ?>" /> + <?php } ?> + <input type="hidden" name="do" value="process_export" /> + <input type="hidden" name="chpage" value="<?php echo $chpage; ?>" /> + <input type="checkbox" name="show_grid" id="show_grid_opt" /> + <label for="show_grid_opt"><?php echo __('Show grid'); ?></label><br /> + <input type="checkbox" name="show_color" id="show_color_opt" checked="checked" /> + <label for="show_color_opt"><?php echo __('Show color'); ?></label><br /> + <input type="checkbox" name="show_table_dimension" id="show_table_dim_opt" /> + <label for="show_table_dim_opt"><?php echo __('Show dimension of tables'); ?> + </label><br /> + <input type="checkbox" name="all_table_same_wide" id="all_table_same_wide" /> + <label for="all_table_same_wide"><?php echo __('Display all tables with the same width'); ?> + </label><br /> + <input type="checkbox" name="with_doc" id="with_doc" checked="checked" /> + <label for="with_doc"><?php echo __('Data Dictionary'); ?></label><br /> + <input type="checkbox" name="show_keys" id="show_keys" /> + <label for="show_keys"><?php echo __('Only show keys'); ?></label><br /> + <select name="orientation" id="orientation_opt"> + <option value="L"><?php echo __('Landscape');?></option> + <option value="P"><?php echo __('Portrait');?></option> + </select> + <label for="orientation_opt"><?php echo __('Orientation'); ?></label> + <br /> + <select name="paper" id="paper_opt"> + <?php + foreach ($cfg['PDFPageSizes'] as $key => $val) { + echo '<option value="' . $val . '"'; + if ($val == $cfg['PDFDefaultPageSize']) { + echo ' selected="selected"'; + } + echo ' >' . $val . '</option>' . "\n"; + } + ?> + </select> + <label for="paper_opt"><?php echo __('Paper size'); ?></label> + </fieldset> + <fieldset class="tblFooters"> + <input type="submit" value="<?php echo __('Go'); ?>" /> + </fieldset> + </form> + <?php + } + + /** + * Check if there are tables that need to be deleted in dashboard, + * if there are, ask the user for allowance + * + * @param string db name of database selected + * @param integer chpage selected page + * @param array tabExist + * @return void + * @access private + */ + private function _deleteTables($db, $chpage, $tabExist) + { + $_strtrans = ''; + $_strname = ''; + $shoot = FALSE; + if (!empty($tabExist) && is_array($tabExist)) { + foreach ($tabExist as $key => $value) { + if (!$value) { + $_strtrans .= '<input type="hidden" name="delrow[]" value="' . htmlspecialchars($key) . '" />' . "\n"; + $_strname .= '<li>' . htmlspecialchars($key) . '</li>' . "\n"; + $shoot = TRUE; + } + } + if ($shoot) { + echo '<form action="schema_edit.php" method="post">' . "\n" + . PMA_generate_common_hidden_inputs($db, $table) + . '<input type="hidden" name="do" value="deleteCrap" />' . "\n" + . '<input type="hidden" name="chpage" value="' . htmlspecialchars($chpage) . '" />' . "\n" + . __('The current page has references to tables that no longer exist. Would you like to delete those references?') + . '<ul>' . "\n" + . $_strname + . '</ul>' . "\n" + . $_strtrans + . '<input type="submit" value="' . __('Go') . '" />' . "\n" + . '</form>'; + } + } + + } + + /** + * Check if there are tables that need to be deleted in dashboard, + * if there are, ask the user for allowance + * + * @return void + * @access private + */ + private function _displayScratchboardTables($array_sh_page,$draginit,$reset_draginit) + { + global $with_field_names,$cfg,$db; + ?> + <script type="text/javascript" src="./js/dom-drag.js"></script> + <form method="post" action="schema_edit.php" name="dragdrop"> + <input type="button" name="dragdrop" value="<?php echo __('Toggle scratchboard'); ?>" onclick="ToggleDragDrop('pdflayout');" /> + <input type="button" name="dragdropreset" value="<?php echo __('Reset'); ?>" onclick="resetDrag();" /> + </form> + <div id="pdflayout" class="pdflayout" style="visibility: hidden;"> + <?php + $i = 0; + foreach ($array_sh_page as $key => $temp_sh_page) { + $drag_x = $temp_sh_page['x']; + $drag_y = $temp_sh_page['y']; + + $draginit .= ' Drag.init(getElement("table_' . $i . '"), null, 0, parseInt(myid.style.width)-2, 0, parseInt(myid.style.height)-5);' . "\n"; + $draginit .= ' getElement("table_' . $i . '").onDrag = function (x, y) { document.edcoord.elements["c_table_' . $i . '[x]"].value = parseInt(x); document.edcoord.elements["c_table_' . $i . '[y]"].value = parseInt(y) }' . "\n"; + $draginit .= ' getElement("table_' . $i . '").style.left = "' . $drag_x . 'px";' . "\n"; + $draginit .= ' getElement("table_' . $i . '").style.top = "' . $drag_y . 'px";' . "\n"; + $reset_draginit .= ' getElement("table_' . $i . '").style.left = "2px";' . "\n"; + $reset_draginit .= ' getElement("table_' . $i . '").style.top = "' . (15 * $i) . 'px";' . "\n"; + $reset_draginit .= ' document.edcoord.elements["c_table_' . $i . '[x]"].value = "2"' . "\n"; + $reset_draginit .= ' document.edcoord.elements["c_table_' . $i . '[y]"].value = "' . (15 * $i) . '"' . "\n"; + + $local_query = 'SHOW FIELDS FROM ' + . PMA_backquote($temp_sh_page['table_name']) + . ' FROM ' . PMA_backquote($db); + $fields_rs = PMA_DBI_query($local_query); + unset($local_query); + $fields_cnt = PMA_DBI_num_rows($fields_rs); + + echo '<div id="table_' . $i . '" class="pdflayout_table"><u>' . $temp_sh_page['table_name'] . '</u>'; + if (isset($with_field_names)) { + while ($row = PMA_DBI_fetch_assoc($fields_rs)) { + echo '<br />' . htmlspecialchars($row['Field']) . "\n"; + } + } + echo '</div>' . "\n"; + PMA_DBI_free_result($fields_rs); + unset($fields_rs); + $i++; + } + ?> + </div> + <script type="text/javascript"> + //<![CDATA[ + function PDFinit() { + refreshLayout(); + myid = getElement('pdflayout'); + <?php echo $draginit; ?> + } + + function resetDrag() { + <?php echo $reset_draginit; ?> + } + //]]> + </script> + <?php + } + + /** + * delete the table rows with table co-ordinates + * + * @param int delrow delete selected table from list of tables + * @param array cfgRelation relation settings + * @param string db database name + * @param integer chpage selected page for adding relations etc + * @return void + * @access private + */ + private function _deleteTableRows($delrow,$cfgRelation,$db,$chpage) + { + foreach ($delrow as $current_row) { + $del_query = 'DELETE FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) . ' ' . "\n" + . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' . "\n" + . ' AND table_name = \'' . PMA_sqlAddslashes($current_row) . '\'' . "\n" + . ' AND pdf_page_number = \'' . PMA_sqlAddslashes($chpage) . '\''; + echo $del_query; + PMA_query_as_controluser($del_query, FALSE, $query_default_option); + } + } + + /** + * get all the export options and verify + * call and include the appropriate Schema Class depending on $export_type + * + * @return void + * @access private + */ + private function _processExportSchema() + { + /** + * Settings for relation stuff + */ + require_once './libraries/transformations.lib.php'; + require_once './libraries/Index.class.php'; + /** + * default is PDF + */ + global $db,$export_type; + $export_type = isset($export_type) ? $export_type : 'pdf'; + PMA_DBI_select_db($db); + + include("./libraries/schema/".ucfirst($export_type)."_Relation_Schema.class.php"); + $obj_schema = eval("new PMA_".ucfirst($export_type)."_Relation_Schema();"); + } + + /** + * delete X and Y coordinates + * + * @param string db The database name + * @param array cfgRelation relation settings + * @param integer choosePage selected page for adding relations etc + * @return void + * @access private + */ + public function deleteCoordinates($db, $cfgRelation, $choosePage, $query_default_option) + { + $query = 'DELETE FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) + . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' + . ' AND pdf_page_number = \'' . PMA_sqlAddslashes($choosePage) . '\''; + PMA_query_as_controluser($query, FALSE, $query_default_option); + } + + /** + * delete pages + * + * @param string db The database name + * @param array cfgRelation relation settings + * @param integer choosePage selected page for adding relations etc + * @return void + * @access private + */ + public function deletePages($db, $cfgRelation, $choosePage, $query_default_option) + { + $query = 'DELETE FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['pdf_pages']) + . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' + . ' AND page_nr = \'' . PMA_sqlAddslashes($choosePage) . '\''; + PMA_query_as_controluser($query, FALSE, $query_default_option); + } + + /** + * process internal and foreign key relations + * + * @param string db The database name + * @param array cfgRelation relation settings + * @param integer pageNumber document number/Id + * @return void + * @access private + */ + public function processRelations($db, $pageNumber, $cfgRelation, $query_default_option) + { + /* + * A u t o m a t i c l a y o u t + * + * There are 2 kinds of relations in PMA + * 1) Internal Relations 2) Foreign Key Relations + */ + if (isset($this->autoLayoutInternal) || isset($this->autoLayoutForeign)) { + $all_tables = array(); + } + + if (isset($this->autoLayoutForeign)) { + /* + * get the tables list + * who support FOREIGN KEY, it's not + * important that we group together InnoDB tables + * and PBXT tables, as this logic is just to put + * the tables on the layout, not to determine relations + */ + $tables = PMA_DBI_get_tables_full($db); + $foreignkey_tables = array(); + foreach($tables as $table_name => $table_properties) { + if (PMA_foreignkey_supported($table_properties['ENGINE'])) { + $foreignkey_tables[] = $table_name; + } + } + $all_tables = $foreignkey_tables; + /* + * could be improved by finding the tables which have the + * most references keys and placing them at the beginning + * of the array (so that they are all center of schema) + */ + unset($tables, $foreignkey_tables); + } + + if (isset($this->autoLayoutInternal)) { + /* + * get the tables list who support Internal Relations; + * This type of relations will be created when + * you setup the PMA tables correctly + */ + $master_tables = 'SELECT COUNT(master_table), master_table' + . ' FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['relation']) + . ' WHERE master_db = \'' . $db . '\'' + . ' GROUP BY master_table' + . ' ORDER BY ' . PMA_backquote('COUNT(master_table)') . ' DESC '; + $master_tables_rs = PMA_query_as_controluser($master_tables, FALSE, $query_default_option); + if ($master_tables_rs && PMA_DBI_num_rows($master_tables_rs) > 0) { + /* first put all the master tables at beginning + * of the list, so they are near the center of + * the schema + */ + while (list(, $master_table) = PMA_DBI_fetch_row($master_tables_rs)) { + $all_tables[] = $master_table; + } + + /* Now for each master, add its foreigns into an array + * of foreign tables, if not already there + * (a foreign might be foreign for more than + * one table, and might be a master itself) + */ + + $foreign_tables = array(); + foreach ($all_tables as $master_table) { + $foreigners = PMA_getForeigners($db, $master_table); + foreach ($foreigners as $foreigner) { + if (!in_array($foreigner['foreign_table'], $foreign_tables)) { + $foreign_tables[] = $foreigner['foreign_table']; + } + } + } + + /* + * Now merge the master and foreign arrays/tables + */ + foreach ($foreign_tables as $foreign_table) { + if (!in_array($foreign_table, $all_tables)) { + $all_tables[] = $foreign_table; + } + } + } + } + + if (isset($this->autoLayoutInternal) || isset($this->autoLayoutForeign)) { + $this->addRelationCoordinates($all_tables,$pageNumber,$db, $cfgRelation,$query_default_option); + } + + $this->choosenPage = $pageNumber; + } + + /** + * Add X and Y coordinates for a table + * + * @param string db The database name + * @param array cfgRelation relation settings + * @param integer pageNumber document number/Id + * @param array all_tables A list of all tables involved + * @return void + * @access private + */ + public function addRelationCoordinates($all_tables,$pageNumber,$db, $cfgRelation,$query_default_option) + { + /* + * Now generate the coordinates for the schema + * in a clockwise spiral and add to co-ordinates table + */ + $pos_x = 300; + $pos_y = 300; + $delta = 110; + $delta_mult = 1.10; + $direction = "right"; + foreach ($all_tables as $current_table) { + /* + * save current table's coordinates + */ + $insert_query = 'INSERT INTO ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) . ' ' + . '(db_name, table_name, pdf_page_number, x, y) ' + . 'VALUES (\'' . PMA_sqlAddslashes($db) . '\', \'' . PMA_sqlAddslashes($current_table) . '\',' . $pageNumber . ',' . $pos_x . ',' . $pos_y . ')'; + PMA_query_as_controluser($insert_query, FALSE, $query_default_option); + + /* + * compute for the next table + */ + switch ($direction) { + case 'right': + $pos_x += $delta; + $direction = "down"; + $delta *= $delta_mult; + break; + case 'down': + $pos_y += $delta; + $direction = "left"; + $delta *= $delta_mult; + break; + case 'left': + $pos_x -= $delta; + $direction = "up"; + $delta *= $delta_mult; + break; + case 'up': + $pos_y -= $delta; + $direction = "right"; + $delta *= $delta_mult; + break; + } + } + } + + /** + * update X and Y coordinates for a table + * + * @param string db The database name + * @param array cfgRelation relation settings + * @return void + * @access private + */ + private function _editCoordinates($db, $cfgRelation,$query_default_option) + { + for ($i = 0; $i < $this->c_table_rows; $i++) { + $arrvalue = 'c_table_' . $i; + global $$arrvalue; + $arrvalue = $$arrvalue; + if (!isset($arrvalue['x']) || $arrvalue['x'] == '') { + $arrvalue['x'] = 0; + } + if (!isset($arrvalue['y']) || $arrvalue['y'] == '') { + $arrvalue['y'] = 0; + } + if (isset($arrvalue['name']) && $arrvalue['name'] != '--') { + $test_query = 'SELECT * FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) + . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' + . ' AND table_name = \'' . PMA_sqlAddslashes($arrvalue['name']) . '\'' + . ' AND pdf_page_number = \'' . PMA_sqlAddslashes($this->choosenPage) . '\''; + $test_rs = PMA_query_as_controluser($test_query, FALSE, $query_default_option); + //echo $test_query; + if ($test_rs && PMA_DBI_num_rows($test_rs) > 0) { + if (isset($arrvalue['delete']) && $arrvalue['delete'] == 'y') { + $ch_query = 'DELETE FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) + . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' + . ' AND table_name = \'' . PMA_sqlAddslashes($arrvalue['name']) . '\'' + . ' AND pdf_page_number = \'' . PMA_sqlAddslashes($this->choosenPage) . '\''; + } else { + $ch_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) . ' ' + . 'SET x = ' . $arrvalue['x'] . ', y= ' . $arrvalue['y'] + . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' + . ' AND table_name = \'' . PMA_sqlAddslashes($arrvalue['name']) . '\'' + . ' AND pdf_page_number = \'' . PMA_sqlAddslashes($this->choosenPage) . '\''; + } + } else { + $ch_query = 'INSERT INTO ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) . ' ' + . '(db_name, table_name, pdf_page_number, x, y) ' + . 'VALUES (\'' . PMA_sqlAddslashes($db) . '\', \'' . PMA_sqlAddslashes($arrvalue['name']) . '\', \'' . PMA_sqlAddslashes($this->choosenPage) . '\',' . $arrvalue['x'] . ',' . $arrvalue['y'] . ')'; + } + //echo $ch_query; + PMA_query_as_controluser($ch_query, FALSE, $query_default_option); + } // end if + } // end for + } +} +?> diff --git a/libraries/schema/Visio_Relation_Schema.class.php b/libraries/schema/Visio_Relation_Schema.class.php new file mode 100644 index 0000000..e3aaba1 --- /dev/null +++ b/libraries/schema/Visio_Relation_Schema.class.php @@ -0,0 +1,599 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * + * @version $Id$ + * @package phpMyAdmin + */ + +include_once("Export_Relation_Schema.class.php"); + +/** + * This Class inherits the XMLwriter class and + * helps in developing structure of MS Visio Schema Export + * + * @name PMA_VISIO + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + * @access public + * @see http://php.net/manual/en/book.xmlwriter.php + */ + +class PMA_VISIO extends XMLWriter +{ + public $title; + public $author; + public $font; + public $fontSize; + + /** + * The "PMA_VISIO" constructor + * + * Upon instantiation This starts writing the Visio XML .VDX document + * + * @return void + * @see XMLWriter::openMemory(),XMLWriter::setIndent(),XMLWriter::startDocument() + */ + function __construct() + { + $this->openMemory(); + /* + * Set indenting using three spaces, + * so output is formatted + */ + + $this->setIndent(TRUE); + $this->setIndentString(' '); + /* + * Create the XML document + */ + + $this->startDocument('1.0','UTF-8'); + } + + /** + * Starts Visio XML .VDX Document + * + * Visio XML document starts by first initializing VisioDocument tag + * then DocumentProperties & DocumentSettings contains all the + * attributes that needed to define the document. Order of elements + * should be maintained while generating XML of Visio. + * + * @return void + * @access public + * @see XMLWriter::startElement(),XMLWriter::writeAttribute(),_documentProperties,_documentSettings + */ + function startVisioDoc() + { + $this->startElement('VisioDocument'); + $this->writeAttribute('xmlns', 'http://schemas.microsoft.com/visio/2003/core'); + $this->writeAttribute('xmlns:vx', 'http://schemas.microsoft.com/visio/2006/extension'); + $this->writeAttribute('xml:space', 'preserve'); + $this->_documentProperties(); + $this->_documentSettings(); + } + + /** + * Set document title + * + * @param string value sets the title text + * @return void + * @access public + */ + function setTitle($value) + { + $this->title = $value; + } + + /** + * Set document author + * + * @param string value sets the author + * @return void + * @access public + */ + function setAuthor($value) + { + $this->author = $value; + } + + /** + * Sets Visio XML .VDX Document Properties + * + * DocumentProperties tag contains document property elements such as + the document's Title,Subject,Creator and templates tags + * + * @return void + * @access private + * @see XMLWriter::startElement(),XMLWriter::endElement(),XMLWriter::writeRaw() + */ + private function _documentProperties() + { + $this->startElement('DocumentProperties'); + $this->writeRaw('<Title>'.$this->title.'</Title>'); + $this->writeRaw('<Subject>'.$this->title.'</Subject>'); + $this->writeRaw('<Creator>'.$this->author.'</Creator>'); + $this->writeRaw('<Company>phpMyAdmin</Company>'); + $this->writeRaw('<Template>c:\program files\microsoft office\office12\1033\DBMODL_U.VST</Template>'); + $this->endElement(); + } + + /** + * Sets Visio XML .VDX Document Settings + * + * DocumentSettings tag contains elements that specify document settings. + * + * @return void + * @access private + * @see XMLWriter::startElement(),XMLWriter::endElement() + */ + private function _documentSettings() + { + $this->startElement('DocumentSettings'); + $this->endElement(); + } + + /** + * Ends Visio XML Document + * + * @return void + * @access public + * @see XMLWriter::endElement(),XMLWriter::endDocument() + */ + function endVisioDoc() + { + $this->endElement(); + $this->endDocument(); + } + + /** + * Output Visio XML .VDX Document for download + * + * @param string fileName name of the Visio XML document + * @return void + * @access public + * @see XMLWriter::flush() + */ + function showOutput($fileName) + { + //if(ob_get_clean()){ + //ob_end_clean(); + //} + header('Content-type: application/visio'); + header('Content-Disposition: attachment; filename="'.$fileName.'.vdx"'); + $output = $this->flush(); + print $output; + } +} + + +/** + * Draws tables schema + */ +class Table_Stats +{ + /** + * Defines properties + */ + + private $_tableName; + private $_showInfo = false; + + public $width = 0; + public $height; + public $fields = array(); + public $heightCell = 0; + public $currentCell = 0; + public $x, $y; + public $primary = array(); + + /** + * The "Table_Stats" constructor + * + * @param string tableName The table name + * @param integer same_wide_width The max. with among tables + * @param boolean showKeys Whether to display keys or not + * @param boolean showInfo Whether to display table position or not + * @global object The current Visio XML document + * @global integer The current page number (from the + * $cfg['Servers'][$i]['table_coords'] table) + * @global array The relations settings + * @global string The current db name + * @access private + * @see PMA_VISIO, Table_Stats::Table_Stats_setWidth, + Table_Stats::Table_Stats_setHeight + */ + function __construct($tableName, $pageNumber, &$same_wide_width, $showKeys = false, $showInfo = false) + { + global $visio, $cfgRelation, $db; + + $this->_tableName = $tableName; + $sql = 'DESCRIBE ' . PMA_backquote($tableName); + $result = PMA_DBI_try_query($sql, null, PMA_DBI_QUERY_STORE); + if (!$result || !PMA_DBI_num_rows($result)) { + $visio->dieSchema($pageNumber,"VISIO",sprintf(__('The %s table doesn\'t exist!'), $tableName)); + } + + /* + * load fields + * check to see if it will load all fields or only the foreign keys + */ + + if ($showKeys) { + $indexes = PMA_Index::getFromTable($this->_tableName, $db); + $all_columns = array(); + foreach ($indexes as $index) { + $all_columns = array_merge($all_columns, array_flip(array_keys($index->getColumns()))); + } + $this->fields = array_keys($all_columns); + } else { + while ($row = PMA_DBI_fetch_row($result)) { + $this->fields[] = $row[0]; + } + } + + $this->_showInfo = $showInfo; + + // height and width + $this->_setHeightTable($fontSize); + + // setWidth must me after setHeight, because title + // can include table height which changes table width + $this->_setWidthTable($font,$fontSize); + if ($same_wide_width < $this->width) { + $same_wide_width = $this->width; + } + + // x and y + $sql = 'SELECT x, y FROM ' + . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) + . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' + . ' AND table_name = \'' . PMA_sqlAddslashes($tableName) . '\'' + . ' AND pdf_page_number = ' . $pageNumber; + $result = PMA_query_as_controluser($sql, false, PMA_DBI_QUERY_STORE); + + if (!$result || !PMA_DBI_num_rows($result)) { + $visio->dieSchema($pageNumber,"VISIO",sprintf(__('Please configure the coordinates for table %s'), $tableName)); + } + list($this->x, $this->y) = PMA_DBI_fetch_row($result); + $this->x = (double) $this->x; + $this->y = (double) $this->y; + // displayfield + $this->displayfield = PMA_getDisplayField($db, $tableName); + // index + $result = PMA_DBI_query('SHOW INDEX FROM ' . PMA_backquote($tableName) . ';', null, PMA_DBI_QUERY_STORE); + if (PMA_DBI_num_rows($result) > 0) { + while ($row = PMA_DBI_fetch_assoc($result)) { + if ($row['Key_name'] == 'PRIMARY') { + $this->primary[] = $row['Column_name']; + } + } + } + } + + /** + * Returns title of the current table, + * title can have the dimensions/co-ordinates of the table + * + * @access private + */ + private function _getTitle() + { + return ($this->_showInfo ? sprintf('%.0f', $this->width) . 'x' . sprintf('%.0f', $this->heightCell) : '') . ' ' . $this->_tableName; + } + + /** + * Sets the width of the table + * + * @param string font The font name + * @param integer fontSize The font size + * @global object The current Visio XML document + * @access private + * @see PMA_VISIO + */ + function _setWidthTable($font,$fontSize) + { + global $visio; + + } + + /** + * Sets the height of the table + * + * @access private + */ + function _setHeightTable($fontSize) + { + $this->heightCell = $fontSize + 4; + $this->height = (count($this->fields) + 1) * $this->heightCell; + } + + /** + * draw the table + * + * @param boolean showColor Whether to display color + * @global object The current Visio XML document + * @access public + * @see PMA_VISIO + */ + public function tableDraw($showColor) + { + global $visio; + //echo $this->_tableName.'<br />'; + + foreach ($this->fields as $field) { + $this->currentCell += $this->heightCell; + $showColor = 'none'; + if ($showColor) { + if (in_array($field, $this->primary)) { + $showColor = '#0c0'; + } + if ($field == $this->displayfield) { + $showColor = 'none'; + } + } + // code here for drawing table diagrams + } + } +} + +/** + * Draws relation links + * + * @access public + * @see PMA_VISIO + */ +class Relation_Stats +{ + /** + * Defines properties + */ + public $xSrc, $ySrc; + public $srcDir ; + public $destDir; + public $xDest, $yDest; + public $wTick = 10; + + /** + * The "Relation_Stats" constructor + * + * @param string master_table The master table name + * @param string master_field The relation field in the master table + * @param string foreign_table The foreign table name + * @param string foreigh_field The relation field in the foreign table + * @see Relation_Stats::_getXy + */ + function __construct($master_table, $master_field, $foreign_table, $foreign_field) + { + $src_pos = $this->_getXy($master_table, $master_field); + $dest_pos = $this->_getXy($foreign_table, $foreign_field); + /* + * [0] is x-left + * [1] is x-right + * [2] is y + */ + $src_left = $src_pos[0] - $this->wTick; + $src_right = $src_pos[1] + $this->wTick; + $dest_left = $dest_pos[0] - $this->wTick; + $dest_right = $dest_pos[1] + $this->wTick; + + $d1 = abs($src_left - $dest_left); + $d2 = abs($src_right - $dest_left); + $d3 = abs($src_left - $dest_right); + $d4 = abs($src_right - $dest_right); + $d = min($d1, $d2, $d3, $d4); + + if ($d == $d1) { + $this->xSrc = $src_pos[0]; + $this->srcDir = -1; + $this->xDest = $dest_pos[0]; + $this->destDir = -1; + } elseif ($d == $d2) { + $this->xSrc = $src_pos[1]; + $this->srcDir = 1; + $this->xDest = $dest_pos[0]; + $this->destDir = -1; + } elseif ($d == $d3) { + $this->xSrc = $src_pos[0]; + $this->srcDir = -1; + $this->xDest = $dest_pos[1]; + $this->destDir = 1; + } else { + $this->xSrc = $src_pos[1]; + $this->srcDir = 1; + $this->xDest = $dest_pos[1]; + $this->destDir = 1; + } + $this->ySrc = $src_pos[2]; + $this->yDest = $dest_pos[2]; + } + + /** + * Gets arrows coordinates + * + * @param string table The current table name + * @param string column The relation column name + * @return array Arrows coordinates + * @access private + */ + function _getXy($table, $column) + { + $pos = array_search($column, $table->fields); + // x_left, x_right, y + return array($table->x, $table->x + $table->width, $table->y + ($pos + 1.5) * $table->heightCell); + } + + /** + * draws relation links and arrows + * shows foreign key relations + * + * @param boolean changeColor Whether to use one color per relation or not + * @global object The current Visio XML document + * @access public + * @see PMA_VISIO + */ + public function relationDraw($changeColor) + { + global $visio; + + if ($changeColor) { + $listOfColors = array( + 'red', + 'grey', + 'black', + 'yellow', + 'green', + 'cyan', + ' orange' + ); + shuffle($listOfColors); + $color = $listOfColors[0]; + } else { + $color = 'black'; + } + + // code here for making connections b/w relation objects + + } +} +/* +* end of the "Relation_Stats" class +*/ + +/** + * Visio Relation Schema Class + * + * Purpose of this class is to generate the Visio XML .VDX Document + * which is used for representing the database diagrams in any version of MS Visio IDE. + * This class uses Software and Database Template and Database model diagram of Visio + * and with the combination of these objects actually helps in preparing Visio XML .VDX document. + * + * Visio XML is generated by using XMLWriter php extension and this class + * inherits Export_Relation_Schema class has common functionality added + * to this class + * + * @name Visio_Relation_Schema + * @author Muhammad Adnan <hiddenpearls@gmail.com> + * @copyright + * @license + */ +class PMA_Visio_Relation_Schema extends PMA_Export_Relation_Schema +{ + /** + * The "PMA_Visio_Relation_Schema" constructor + * + * Upon instantiation This outputs the Visio XML document + * that user can download + * + * @return void + * @see PMA_VISIO,Table_Stats,Relation_Stats + */ + function __construct() + { + global $visio,$db; + + $this->setPageNumber($_POST['pdf_page_number']); + $this->setShowGrid(isset($_POST['show_grid'])); + $this->setShowColor($_POST['show_color']); + $this->setShowKeys(isset($_POST['show_keys'])); + $this->setOrientation(isset($_POST['orientation'])); + $this->setPaper($_POST['paper']); + $this->setExportType($_POST['export_type']); + + $visio = new PMA_VISIO(); + $visio->setTitle(sprintf(__('Schema of the %s database - Page %s'), $db, $this->pageNumber)); + $visio->SetAuthor('phpMyAdmin ' . PMA_VERSION); + $visio->startVisioDoc(); + $alltables = $this->getAllTables($db,$this->pageNumber); + + foreach ($alltables as $table) { + if (!isset($this->tables[$table])) { + $this->tables[$table] = new Table_Stats($table, $this->pageNumber, $this->showKeys); + } + } + + $seen_a_relation = false; + foreach ($alltables as $one_table) { + $exist_rel = PMA_getForeigners($db, $one_table, '', 'both'); + if ($exist_rel) { + $seen_a_relation = true; + foreach ($exist_rel as $master_field => $rel) { + /* put the foreign table on the schema only if selected + * by the user + * (do not use array_search() because we would have to + * to do a === FALSE and this is not PHP3 compatible) + */ + if (in_array($rel['foreign_table'], $alltables)) { + $this->_addRelation($one_table, $master_field, $rel['foreign_table'], $rel['foreign_field'],$this->showKeys); + } + } + } + } + $this->_drawTables($this->showColor); + + if ($seen_a_relation) { + $this->_drawRelations($this->showColor); + } + $visio->endVisioDoc(); + $visio->showOutput($db.'-'.$this->pageNumber); + exit(); + } + + /** + * Defines relation objects + * + * @param string masterTable The master table name + * @param string masterField The relation field in the master table + * @param string foreignTable The foreign table name + * @param string foreignField The relation field in the foreign table + * @return void + * @access private + * @see Table_Stats::__construct(),Relation_Stats::__construct() + */ + private function _addRelation($masterTable, $masterField, $foreignTable, $foreignField, $showKeys) + { + if (!isset($this->tables[$masterTable])) { + $this->tables[$masterTable] = new Table_Stats($masterTable, $this->pageNumber, $showKeys); + } + if (!isset($this->tables[$foreignTable])) { + $this->tables[$foreignTable] = new Table_Stats($foreignTable, $this->pageNumber, $showKeys); + } + $this->_relations[] = new Relation_Stats($this->tables[$masterTable], $masterField, $this->tables[$foreignTable], $foreignField); + } + + /** + * Draws relation references + * + * connects master table's master field to + * foreign table's forein field. + * + * @param boolean changeColor Whether to use one color per relation or not + * @return void + * @access private + * @see Relation_Stats::relationDraw() + */ + private function _drawRelations($changeColor) + { + foreach ($this->_relations as $relation) { + $relation->relationDraw($changeColor); + } + } + + /** + * Draws tables + * + * + * @param boolean changeColor Whether to show color for tables text or not + * @return void + * @access private + * @see Table_Stats::tableDraw() + */ + private function _drawTables($changeColor) + { + foreach ($this->tables as $table) { + $table->tableDraw($changeColor); + } + } +} +?> \ No newline at end of file diff --git a/libraries/tcpdf/tcpdf.php b/libraries/tcpdf/tcpdf.php index 26f2dc1..a6b707a 100644 --- a/libraries/tcpdf/tcpdf.php +++ b/libraries/tcpdf/tcpdf.php @@ -2980,6 +2980,7 @@ if(!class_exists('TCPDF', false)) { if(ob_get_contents()) { $this->Error('Some data has already been output, can't send PDF file'); } + if(php_sapi_name()!='cli') { //We send to a browser header('Content-Type: application/pdf'); @@ -2997,6 +2998,7 @@ if(!class_exists('TCPDF', false)) { if(ob_get_contents()) { $this->Error('Some data has already been output, can't send PDF file'); } + if(isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'],'MSIE')) { header('Content-Type: application/force-download'); } else { @@ -3005,6 +3007,7 @@ if(!class_exists('TCPDF', false)) { if(headers_sent()) { $this->Error('Some data has already been output to browser, can't send PDF file'); } + header('Content-Type: application/pdf'); header('Content-Length: '.strlen($this->buffer)); header('Content-disposition: attachment; filename="'.$name.'"'); echo $this->buffer; diff --git a/pdf_pages.php b/pdf_pages.php deleted file mode 100644 index 75d4622..0000000 --- a/pdf_pages.php +++ /dev/null @@ -1,559 +0,0 @@ -<?php -/* vim: set expandtab sw=4 ts=4 sts=4: */ -/** - * - * @package phpMyAdmin - */ - -/** - * Gets some core libraries - */ -require_once './libraries/common.inc.php'; -require_once './libraries/db_common.inc.php'; -require './libraries/StorageEngine.class.php'; - -$active_page = 'db_operations.php'; -require_once './libraries/db_common.inc.php'; -$url_query .= '&goto=pdf_pages.php'; -require_once './libraries/db_info.inc.php'; - -/** - * Settings for relation stuff - */ -$cfgRelation = PMA_getRelationsParam(); - -// This is to avoid "Command out of sync" errors. Before switching this to -// a value of 0 (for MYSQLI_USE_RESULT), please check the logic -// to free results wherever needed. -$query_default_option = PMA_DBI_QUERY_STORE; - -/** - * Now in ./libraries/relation.lib.php we check for all tables - * that we need, but if we don't find them we are quiet about it - * so people can work without. - * This page is absolutely useless if you didn't set up your tables - * correctly, so it is a good place to see which tables we can and - * complain ;-) - */ -if (!$cfgRelation['relwork']) { - echo sprintf(__('<b>%s</b> table not found or not set in %s'), 'relation', 'config.inc.php') . '<br />' . "\n" - . PMA_showDocu('relation') . "\n"; - require './libraries/footer.inc.php'; -} - -if (!$cfgRelation['displaywork']) { - echo sprintf(__('<b>%s</b> table not found or not set in %s'), 'table_info', 'config.inc.php') . '<br />' . "\n" - . PMA_showDocu('table_info') . "\n"; - require './libraries/footer.inc.php'; -} - -if (!isset($cfgRelation['table_coords'])){ - echo sprintf(__('<b>%s</b> table not found or not set in %s'), 'table_coords', 'config.inc.php') . '<br />' . "\n" - . PMA_showDocu('table_coords') . "\n"; - require './libraries/footer.inc.php'; -} -if (!isset($cfgRelation['pdf_pages'])) { - echo sprintf(__('<b>%s</b> table not found or not set in %s'), 'pdf_page', 'config.inc.php') . '<br />' . "\n" - . PMA_showDocu('pdf_pages') . "\n"; - require './libraries/footer.inc.php'; -} - -if ($cfgRelation['pdfwork']) { - // Now is the time to work on all changes - if (isset($do)) { - switch ($do) { - case 'choosepage': - if ($action_choose=="1") { - $ch_query = 'DELETE FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) - . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' - . ' AND pdf_page_number = \'' . PMA_sqlAddslashes($chpage) . '\''; - PMA_query_as_controluser($ch_query, FALSE, $query_default_option); - - $ch_query = 'DELETE FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['pdf_pages']) - . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' - . ' AND page_nr = \'' . PMA_sqlAddslashes($chpage) . '\''; - PMA_query_as_controluser($ch_query, FALSE, $query_default_option); - - unset($chpage); - } - break; - case 'createpage': - $pdf_page_number = PMA_REL_create_page($newpage, $cfgRelation, $db, $query_default_option); - - // A u t o m a t i c l a y o u t - // ================================ - if (isset($auto_layout_internal) || isset($auto_layout_foreign)) { - $all_tables = array(); - } - - if (isset($auto_layout_foreign)) { - // get the tables list - $tables = PMA_DBI_get_tables_full($db); - // find the ones who support FOREIGN KEY; it's not - // important that we group together InnoDB tables - // and PBXT tables, as this logic is just to put - // the tables on the layout, not to determine relations - $foreignkey_tables = array(); - foreach($tables as $table_name => $table_properties) { - if (PMA_foreignkey_supported($table_properties['ENGINE'])) { - $foreignkey_tables[] = $table_name; - } - } - $all_tables = $foreignkey_tables; - // could be improved by finding the tables which have the - // most references keys and placing them at the beginning - // of the array (so that they are all center of schema) - unset($tables, $foreignkey_tables); - } // endif auto_layout_foreign - - if (isset($auto_layout_internal)) { - // get the tables that have relations, by descending - // number of links - $master_tables = 'SELECT COUNT(master_table), master_table' - . ' FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['relation']) - . ' WHERE master_db = \'' . $db . '\'' - . ' GROUP BY master_table' - . ' ORDER BY ' . PMA_backquote('COUNT(master_table)') . ' DESC '; - $master_tables_rs = PMA_query_as_controluser($master_tables, FALSE, $query_default_option); - if ($master_tables_rs && PMA_DBI_num_rows($master_tables_rs) > 0) { - // first put all the master tables at beginning - // of the list, so they are near the center of - // the schema - while (list(, $master_table) = PMA_DBI_fetch_row($master_tables_rs)) { - $all_tables[] = $master_table; - } - - // then for each master, add its foreigns into an array - // of foreign tables, if not already there - // (a foreign might be foreign for more than - // one table, and might be a master itself) - - $foreign_tables = array(); - foreach ($all_tables AS $master_table) { - $foreigners = PMA_getForeigners($db, $master_table); - foreach ($foreigners AS $foreigner) { - if (!in_array($foreigner['foreign_table'], $foreign_tables)) { - $foreign_tables[] = $foreigner['foreign_table']; - } - } - } - - // then merge the arrays - foreach ($foreign_tables AS $foreign_table) { - if (!in_array($foreign_table, $all_tables)) { - $all_tables[] = $foreign_table; - } - } - } // endif there are master tables - } // endif auto_layout_internal - - if (isset($auto_layout_internal) || isset($auto_layout_foreign)) { - // now generate the coordinates for the schema, - // in a clockwise spiral - - $pos_x = 300; - $pos_y = 300; - $delta = 110; - $delta_mult = 1.10; - $direction = "right"; - foreach ($all_tables AS $current_table) { - - // save current table's coordinates - $insert_query = 'INSERT INTO ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) . ' ' - . '(db_name, table_name, pdf_page_number, x, y) ' - . 'VALUES (\'' . PMA_sqlAddslashes($db) . '\', \'' . PMA_sqlAddslashes($current_table) . '\',' . $pdf_page_number . ',' . $pos_x . ',' . $pos_y . ')'; - PMA_query_as_controluser($insert_query, FALSE, $query_default_option); - - // compute for the next table - switch ($direction) { - case 'right': - $pos_x += $delta; - $direction = "down"; - $delta *= $delta_mult; - break; - case 'down': - $pos_y += $delta; - $direction = "left"; - $delta *= $delta_mult; - break; - case 'left': - $pos_x -= $delta; - $direction = "up"; - $delta *= $delta_mult; - break; - case 'up': - $pos_y -= $delta; - $direction = "right"; - $delta *= $delta_mult; - break; - } // end switch - } // end foreach - } // end if some auto-layout to do - - $chpage = $pdf_page_number; - - break; - - case 'edcoord': - for ($i = 0; $i < $c_table_rows; $i++) { - $arrvalue = 'c_table_' . $i; - $arrvalue = $$arrvalue; - if (!isset($arrvalue['x']) || $arrvalue['x'] == '') { - $arrvalue['x'] = 0; - } - if (!isset($arrvalue['y']) || $arrvalue['y'] == '') { - $arrvalue['y'] = 0; - } - if (isset($arrvalue['name']) && $arrvalue['name'] != '--') { - $test_query = 'SELECT * FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) - . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' - . ' AND table_name = \'' . PMA_sqlAddslashes($arrvalue['name']) . '\'' - . ' AND pdf_page_number = \'' . PMA_sqlAddslashes($chpage) . '\''; - $test_rs = PMA_query_as_controluser($test_query, FALSE, $query_default_option); - if ($test_rs && PMA_DBI_num_rows($test_rs) > 0) { - if (isset($arrvalue['delete']) && $arrvalue['delete'] == 'y') { - $ch_query = 'DELETE FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) - . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' - . ' AND table_name = \'' . PMA_sqlAddslashes($arrvalue['name']) . '\'' - . ' AND pdf_page_number = \'' . PMA_sqlAddslashes($chpage) . '\''; - } else { - $ch_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) . ' ' - . 'SET x = ' . $arrvalue['x'] . ', y= ' . $arrvalue['y'] - . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' - . ' AND table_name = \'' . PMA_sqlAddslashes($arrvalue['name']) . '\'' - . ' AND pdf_page_number = \'' . PMA_sqlAddslashes($chpage) . '\''; - } - } else { - $ch_query = 'INSERT INTO ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) . ' ' - . '(db_name, table_name, pdf_page_number, x, y) ' - . 'VALUES (\'' . PMA_sqlAddslashes($db) . '\', \'' . PMA_sqlAddslashes($arrvalue['name']) . '\', \'' . PMA_sqlAddslashes($chpage) . '\',' . $arrvalue['x'] . ',' . $arrvalue['y'] . ')'; - } - PMA_query_as_controluser($ch_query, FALSE, $query_default_option); - } // end if - } // end for - break; - case 'deleteCrap': - foreach ($delrow AS $current_row) { - $d_query = 'DELETE FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) . ' ' . "\n" - . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' . "\n" - . ' AND table_name = \'' . PMA_sqlAddslashes($current_row) . '\'' . "\n" - . ' AND pdf_page_number = \'' . PMA_sqlAddslashes($chpage) . '\''; - PMA_query_as_controluser($d_query, FALSE, $query_default_option); - } - break; - } // end switch - } // end if (isset($do)) - - // We will need an array of all tables in this db - $selectboxall = array('--'); - $alltab_rs = PMA_DBI_query('SHOW TABLES FROM ' . PMA_backquote($db) . ';', null, PMA_DBI_QUERY_STORE); - while ($val = @PMA_DBI_fetch_row($alltab_rs)) { - $selectboxall[] = $val[0]; - } - - // Now first show some possibility to choose a page for the pdf - $page_query = 'SELECT * FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['pdf_pages']) - . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\''; - $page_rs = PMA_query_as_controluser($page_query, FALSE, $query_default_option); - - if ($page_rs && PMA_DBI_num_rows($page_rs) > 0) { - ?> -<form method="get" action="pdf_pages.php" name="selpage"> - <fieldset> - <legend> - <?php echo __('Please choose a page to edit') . "\n"; ?> - </legend> - <?php echo PMA_generate_common_hidden_inputs($db, $table); ?> - <input type="hidden" name="do" value="choosepage" /> - <select name="chpage" onchange="this.form.submit()"> - <?php - while ($curr_page = PMA_DBI_fetch_assoc($page_rs)) { - echo "\n" . ' ' - . '<option value="' . $curr_page['page_nr'] . '"'; - if (isset($chpage) && $chpage == $curr_page['page_nr']) { - echo ' selected="selected"'; - } - echo '>' . $curr_page['page_nr'] . ': ' . htmlspecialchars($curr_page['page_descr']) . '</option>'; - } // end while - echo "\n"; - ?> - </select> -<?php - $choices = array( - '0' => __('Edit'), - '1' => __('Delete')); - PMA_display_html_radio('action_choose', $choices, '0', false); - unset($choices); -?> - </fieldset> - <fieldset class="tblFooters"> - <input type="submit" value="<?php echo __('Go'); ?>" /><br /> - </fieldset> -</form> - <?php - } - echo "\n"; - - // Possibility to create a new page: - ?> -<form method="post" action="pdf_pages.php" name="crpage"> - <fieldset> - <legend> - <?php echo __('Create a page') . "\n"; ?> - </legend> - <?php echo PMA_generate_common_hidden_inputs($db, $table); ?> - <input type="hidden" name="do" value="createpage" /> - <table> - <tr> - <td><label for="id_newpage"><?php echo __('Page name'); ?></label></td> - <td><input type="text" name="newpage" id="id_newpage" size="20" maxlength="50" /></td> - </tr> - <tr> - <td><?php echo __('Automatic layout based on'); ?></td> - <td> - <input type="checkbox" name="auto_layout_internal" id="id_auto_layout_internal" /><label for="id_auto_layout_internal"><?php echo __('Internal relations'); ?></label><br /> -<?php - if (PMA_StorageEngine::isValid('InnoDB') || PMA_StorageEngine::isValid('PBXT')) { -?> - <input type="checkbox" name="auto_layout_foreign" id="id_auto_layout_foreign" /><label for="id_auto_layout_foreign">FOREIGN KEY</label><br /> -<?php - } -?> - </td></tr> - </table> - </fieldset> - <fieldset class="tblFooters"> - <input type="submit" value="<?php echo __('Go'); ?>" /> - </fieldset> -</form> - <?php - // Now if we already have chosen a page number then we should show the - // tables involved - if (isset($chpage) && $chpage > 0) { - echo "\n"; - ?> -<hr /> - -<h2><?php echo __('Select Tables') ;?></h2> - -<?php -$page_query = 'SELECT * FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) - . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' - . ' AND pdf_page_number = \'' . PMA_sqlAddslashes($chpage) . '\''; -$page_rs = PMA_query_as_controluser($page_query, FALSE, $query_default_option); -$array_sh_page = array(); -$draginit = ''; -$reset_draginit = ''; -$i = 0; -while ($temp_sh_page = @PMA_DBI_fetch_assoc($page_rs)) { - $array_sh_page[] = $temp_sh_page; -} - -// Display WYSIWYG-PDF parts? -if ($cfg['WYSIWYG-PDF']) { - if (!isset($_POST['with_field_names']) && !isset($_POST['showwysiwyg'])) { - $with_field_names = TRUE; - } -?> -<script type="text/javascript" src="./js/dom-drag.js"></script> -<form method="post" action="pdf_pages.php" name="dragdrop"> -<input type="button" name="dragdrop" value="<?php echo __('Toggle scratchboard'); ?>" onclick="ToggleDragDrop('pdflayout');" /> - <input type="button" name="dragdropreset" value="<?php echo __('Reset'); ?>" onclick="resetDrag();" /> -</form> -<div id="pdflayout" class="pdflayout" style="visibility: hidden;"> -<?php -foreach ($array_sh_page AS $key => $temp_sh_page) { - $drag_x = $temp_sh_page['x']; - $drag_y = $temp_sh_page['y']; - - $draginit .= ' Drag.init(getElement("table_' . $i . '"), null, 0, parseInt(myid.style.width)-2, 0, parseInt(myid.style.height)-5);' . "\n"; - $draginit .= ' getElement("table_' . $i . '").onDrag = function (x, y) { document.edcoord.elements["c_table_' . $i . '[x]"].value = parseInt(x); document.edcoord.elements["c_table_' . $i . '[y]"].value = parseInt(y) }' . "\n"; - $draginit .= ' getElement("table_' . $i . '").style.left = "' . $drag_x . 'px";' . "\n"; - $draginit .= ' getElement("table_' . $i . '").style.top = "' . $drag_y . 'px";' . "\n"; - $reset_draginit .= ' getElement("table_' . $i . '").style.left = "2px";' . "\n"; - $reset_draginit .= ' getElement("table_' . $i . '").style.top = "' . (15 * $i) . 'px";' . "\n"; - $reset_draginit .= ' document.edcoord.elements["c_table_' . $i . '[x]"].value = "2"' . "\n"; - $reset_draginit .= ' document.edcoord.elements["c_table_' . $i . '[y]"].value = "' . (15 * $i) . '"' . "\n"; - - $local_query = 'SHOW FIELDS FROM ' - . PMA_backquote($temp_sh_page['table_name']) - . ' FROM ' . PMA_backquote($db); - $fields_rs = PMA_DBI_query($local_query); - unset($local_query); - $fields_cnt = PMA_DBI_num_rows($fields_rs); - - echo '<div id="table_' . $i . '" class="pdflayout_table"><u>' . $temp_sh_page['table_name'] . '</u>'; - if (isset($with_field_names)) { - while ($row = PMA_DBI_fetch_assoc($fields_rs)) { - echo '<br />' . htmlspecialchars($row['Field']) . "\n"; - } - } - echo '</div>' . "\n"; - PMA_DBI_free_result($fields_rs); - unset($fields_rs); - - $i++; -} -?> -</div> -<script type="text/javascript"> -//<![CDATA[ -function PDFinit() { - refreshLayout(); - myid = getElement('pdflayout'); - <?php echo $draginit; ?> -} - -function resetDrag() { - <?php echo $reset_draginit; ?> -} -//]]> -</script> -<?php -} // end if WYSIWYG-PDF -?> - -<form method="post" action="pdf_pages.php" name="edcoord"> - <?php echo PMA_generate_common_hidden_inputs($db, $table); ?> - <input type="hidden" name="chpage" value="<?php echo htmlspecialchars($chpage); ?>" /> - <input type="hidden" name="do" value="edcoord" /> - <table border="0"> - <tr> - <th><?php echo __('Table'); ?></th> - <th><?php echo __('Delete'); ?></th> - <th>X</th> - <th>Y</th> - </tr> - <?php - if (isset($ctable)) { - unset($ctable); - } - - - $i = 0; - $odd_row = true; - foreach ($array_sh_page AS $dummy_sh_page => $sh_page) { - $_mtab = $sh_page['table_name']; - $tabExist[$_mtab] = FALSE; - echo "\n" . ' <tr class="'; - if ($odd_row) { - echo 'odd'; - } else { - echo 'even'; - } - echo '">'; - $odd_row != $odd_row; - echo "\n" . ' <td>' - . "\n" . ' <select name="c_table_' . $i . '[name]">'; - foreach ($selectboxall AS $key => $value) { - echo "\n" . ' <option value="' . htmlspecialchars($value) . '"'; - if ($value == $sh_page['table_name']) { - echo ' selected="selected"'; - $tabExist[$_mtab] = TRUE; - } - echo '>' . htmlspecialchars($value) . '</option>'; - } // end while - echo "\n" . ' </select>' - . "\n" . ' </td>'; - echo "\n" . ' <td>' - . "\n" . ' <input type="checkbox" name="c_table_' . $i . '[delete]" value="y" />' . __('Delete'); - echo "\n" . ' </td>'; - echo "\n" . ' <td>' - . "\n" . ' <input type="text" ' . ($cfg['WYSIWYG-PDF'] ? 'onchange="dragPlace(' . $i . ', \'x\', this.value)"' : '') . ' name="c_table_' . $i . '[x]" value="' . $sh_page['x'] . '" />'; - echo "\n" . ' </td>'; - echo "\n" . ' <td>' - . "\n" . ' <input type="text" ' . ($cfg['WYSIWYG-PDF'] ? 'onchange="dragPlace(' . $i . ', \'y\', this.value)"' : '') . ' name="c_table_' . $i . '[y]" value="' . $sh_page['y'] . '" />'; - echo "\n" . ' </td>'; - echo "\n" . ' </tr>'; - $i++; - } // end while - // Do one more empty row - echo "\n" . ' <tr class="'; - if ($odd_row) { - echo 'odd'; - } else { - echo 'even'; - } - $odd_row != $odd_row; - echo '">'; - echo "\n" . ' <td>' - . "\n" . ' <select name="c_table_' . $i . '[name]">'; - foreach ($selectboxall AS $key => $value) { - echo "\n" . ' <option value="' . htmlspecialchars($value) . '">' . htmlspecialchars($value) . '</option>'; - } - echo "\n" . ' </select>' - . "\n" . ' </td>'; - echo "\n" . ' <td>' - . "\n" . ' <input type="checkbox" name="c_table_' . $i . '[delete]" value="y" />' . __('Delete'); - echo "\n" . ' </td>'; - echo "\n" . ' <td>' - . "\n" . ' <input type="text" name="c_table_' . $i . '[x]" value="' . (isset($sh_page['x'])?$sh_page['x']:'') . '" />'; - echo "\n" . ' </td>'; - echo "\n" . ' <td>' - . "\n" . ' <input type="text" name="c_table_' . $i . '[y]" value="' . (isset($sh_page['y'])?$sh_page['y']:'') . '" />'; - echo "\n" . ' </td>'; - echo "\n" . ' </tr>'; - echo "\n" . ' </table>' . "\n"; - - echo "\n" . ' <input type="hidden" name="c_table_rows" value="' . ($i + 1) . '" />'; - echo ($cfg['WYSIWYG-PDF'] ? "\n" . ' <input type="hidden" id="showwysiwyg" name="showwysiwyg" value="' . ((isset($showwysiwyg) && $showwysiwyg == '1') ? '1' : '0') . '" />' : ''); - echo "\n" . ' <input type="checkbox" name="with_field_names" ' . (isset($with_field_names) ? 'checked="checked"' : ''). ' />' . __('Column names') . '<br />'; - echo "\n" . ' <input type="submit" value="' . __('Save') . '" />'; - echo "\n" . '</form>' . "\n\n"; - } // end if - - // Check if there are tables that need to be deleted, - // if there are, ask the user for allowance - $_strtrans = ''; - $_strname = ''; - $shoot = FALSE; - if (!empty($tabExist) && is_array($tabExist)) { - foreach ($tabExist AS $key => $value) { - if (!$value) { - $_strtrans .= '<input type="hidden" name="delrow[]" value="' . htmlspecialchars($key) . '" />' . "\n"; - $_strname .= '<li>' . htmlspecialchars($key) . '</li>' . "\n"; - $shoot = TRUE; - } - } - if ($shoot) { - echo '<form action="pdf_pages.php" method="post">' . "\n" - . PMA_generate_common_hidden_inputs($db, $table) - . '<input type="hidden" name="do" value="deleteCrap" />' . "\n" - . '<input type="hidden" name="chpage" value="' . htmlspecialchars($chpage) . '" />' . "\n" - . __('The current page has references to tables that no longer exist. Would you like to delete those references?') - . '<ul>' . "\n" - . $_strname - . '</ul>' . "\n" - . $_strtrans - . '<input type="submit" value="' . __('Go') . '" />' . "\n" - . '</form>'; - } - } - // ------------------------------------ - // d i s p l a y p d f s c h e m a - // ------------------------------------ - - if (isset($do) - && ($do == 'edcoord' - || ($do == 'choosepage' && isset($chpage)) - || ($do == 'createpage' && isset($chpage)))) { - include('./libraries/display_pdf_schema.lib.php'); - if ((isset($showwysiwyg) && $showwysiwyg == '1')) { -?> -<script type="text/javascript"> -//<![CDATA[ -ToggleDragDrop('pdflayout'); -//]]> -</script> -<?php - } - } // end if -} // end if ($cfgRelation['pdfwork']) - - -/** - * Displays the footer - */ -echo "\n"; -require './libraries/footer.inc.php'; -?> diff --git a/pdf_schema.php b/pdf_schema.php deleted file mode 100644 index dd7426f..0000000 --- a/pdf_schema.php +++ /dev/null @@ -1,1404 +0,0 @@ -<?php -/* vim: set expandtab sw=4 ts=4 sts=4: */ -/** - * - * @package phpMyAdmin - */ - -/** - * Gets some core scripts - */ -require_once './libraries/common.inc.php'; - -/** - * Settings for relation stuff - */ -require_once './libraries/transformations.lib.php'; -require_once './libraries/Index.class.php'; - -$cfgRelation = PMA_getRelationsParam(); - -/** - * Now in ./libraries/relation.lib.php we check for all tables - * that we need, but if we don't find them we are quiet about it - * so people can work without. - * This page is absolutely useless if you didn't set up your tables - * correctly, so it is a good place to see which tables we can and - * complain ;-) - */ -if (!$cfgRelation['pdfwork']) { - echo '<font color="red">' . __('Error') . '</font><br />' . "\n"; - $url_to_goto = '<a href="' . $cfg['PmaAbsoluteUri'] . 'chk_rel.php?' . $url_query . '">'; - echo sprintf(__('The phpMyAdmin configuration storage has been deactivated. To find out why click %shere%s.'), $url_to_goto, '</a>') . "\n"; -} - -/** - * Font used in PDF. - * - * @todo Make this configuratble (at least Sans/Serif). - */ -define('PMA_PDF_FONT', 'DejaVuSans'); -require_once './libraries/tcpdf/tcpdf.php'; - -/** - * Extends the "FPDF" class and prepares the work - * - * @access public - * @see FPDF - * @package phpMyAdmin - */ -class PMA_PDF extends TCPDF { - /** - * Defines private properties - */ - var $x_min; - var $y_min; - var $l_marg = 10; - var $t_marg = 10; - var $scale; - var $PMA_links; - var $Outlines = array(); - var $def_outlines; - var $Alias = array(); - var $widths; - - public function getFh() - { - return $this->fh; - } - - public function getFw() - { - return $this->fw; - } - - public function setCMargin($c_margin) - { - $this->cMargin = $c_margin; - } - - function SetAlias($name, $value) - { - $this->Alias[$name] = $value ; - } - - function _putpages() - { - if (count($this->Alias) > 0) { - $nb = $this->page; - foreach ($this->Alias AS $alias => $value) { - for ($n = 1;$n <= $nb;$n++) - $this->pages[$n]=str_replace($alias, $value, $this->pages[$n]); - } - } - parent::_putpages(); - } - - /** - * Sets the scaling factor, defines minimum coordinates and margins - * - * @param float scale The scaling factor - * @param float x_min The minimum X coordinate - * @param float y_min The minimum Y coordinate - * @param float l_marg The left margin - * @param float t_marg The top margin - * @access public - */ - function PMA_PDF_setScale($scale = 1, $x_min = 0, $y_min = 0, $l_marg = -1, $t_marg = -1) - { - $this->scale = $scale; - $this->x_min = $x_min; - $this->y_min = $y_min; - if ($this->l_marg != -1) { - $this->l_marg = $l_marg; - } - if ($this->t_marg != -1) { - $this->t_marg = $t_marg; - } - } // end of the "PMA_PDF_setScale" function - /** - * Outputs a scaled cell - * - * @param float w The cell width - * @param float h The cell height - * @param string txt The text to output - * @param mixed border Whether to add borders or not - * @param integer ln Where to put the cursor once the output is done - * @param string align Align mode - * @param integer fill Whether to fill the cell with a color or not - * @access public - * @see FPDF::Cell() - */ - function PMA_PDF_cellScale($w, $h = 0, $txt = '', $border = 0, $ln = 0, $align = '', $fill = 0, $link = '') - { - $h = $h / $this->scale; - $w = $w / $this->scale; - $this->Cell($w, $h, $txt, $border, $ln, $align, $fill, $link); - } // end of the "PMA_PDF_cellScale" function - /** - * Draws a scaled line - * - * @param float x1 The horizontal position of the starting point - * @param float y1 The vertical position of the starting point - * @param float x2 The horizontal position of the ending point - * @param float y2 The vertical position of the ending point - * @access public - * @see FPDF::Line() - */ - function PMA_PDF_lineScale($x1, $y1, $x2, $y2) - { - $x1 = ($x1 - $this->x_min) / $this->scale + $this->l_marg; - $y1 = ($y1 - $this->y_min) / $this->scale + $this->t_marg; - $x2 = ($x2 - $this->x_min) / $this->scale + $this->l_marg; - $y2 = ($y2 - $this->y_min) / $this->scale + $this->t_marg; - $this->Line($x1, $y1, $x2, $y2); - } // end of the "PMA_PDF_lineScale" function - /** - * Sets x and y scaled positions - * - * @param float x The x position - * @param float y The y position - * @access public - * @see FPDF::SetXY() - */ - function PMA_PDF_setXyScale($x, $y) - { - $x = ($x - $this->x_min) / $this->scale + $this->l_marg; - $y = ($y - $this->y_min) / $this->scale + $this->t_marg; - $this->SetXY($x, $y); - } // end of the "PMA_PDF_setXyScale" function - /** - * Sets the X scaled positions - * - * @param float x The x position - * @access public - * @see FPDF::SetX() - */ - function PMA_PDF_setXScale($x) - { - $x = ($x - $this->x_min) / $this->scale + $this->l_marg; - $this->SetX($x); - } // end of the "PMA_PDF_setXScale" function - /** - * Sets the scaled font size - * - * @param float size The font size (in points) - * @access public - * @see FPDF::SetFontSize() - */ - function PMA_PDF_setFontSizeScale($size) - { - // Set font size in points - $size = $size / $this->scale; - $this->SetFontSize($size); - } // end of the "PMA_PDF_setFontSizeScale" function - /** - * Sets the scaled line width - * - * @param float width The line width - * @access public - * @see FPDF::SetLineWidth() - */ - function PMA_PDF_setLineWidthScale($width) - { - $width = $width / $this->scale; - $this->SetLineWidth($width); - } // end of the "PMA_PDF_setLineWidthScale" function - /** - * Displays an error message - * - * @param string error_message the error mesage - * @global array the PMA configuration array - * @global integer the current server id - * @global string the current language - * @global string the charset to convert to - * @global string the current database name - * @global string the current charset - * @global string the current text direction - * @global string a localized string - * @global string an other localized string - * @access public - */ - function PMA_PDF_die($error_message = '') - { - global $cfg; - global $server, $lang, $db; - global $charset, $text_dir; - - require_once './libraries/header.inc.php'; - - echo '<p><strong>PDF - ' . __('Error') . '</strong></p>' . "\n"; - if (!empty($error_message)) { - $error_message = htmlspecialchars($error_message); - } - echo '<p>' . "\n"; - echo ' ' . $error_message . "\n"; - echo '</p>' . "\n"; - - echo '<a href="db_structure.php?' . PMA_generate_common_url($db) - . '">' . __('Back') . '</a>'; - echo "\n"; - - require './libraries/footer.inc.php'; - } // end of the "PMA_PDF_die()" function - /** - * Aliases the "Error()" function from the FPDF class to the - * "PMA_PDF_die()" one - * - * @param string error_message the error mesage - * @access public - * @see PMA_PDF_die - */ - function Error($error_message = '') - { - $this->PMA_PDF_die($error_message); - } // end of the "Error()" method - function Header() - { - // We only show this if we find something in the new pdf_pages table - - // This function must be named "Header" to work with the FPDF library - global $cfgRelation, $db, $pdf_page_number, $with_doc; - if ($with_doc) { - $test_query = 'SELECT * FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['pdf_pages']) - . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' - . ' AND page_nr = \'' . $pdf_page_number . '\''; - $test_rs = PMA_query_as_controluser($test_query); - $pages = @PMA_DBI_fetch_assoc($test_rs); - $this->SetFont('', 'B', 14); - $this->Cell(0, 6, ucfirst($pages['page_descr']), 'B', 1, 'C'); - $this->SetFont('', ''); - $this->Ln(); - } - } - function Footer() - { - // This function must be named "Footer" to work with the FPDF library - global $with_doc; - if ($with_doc) { - $this->SetY(-15); - $this->SetFont('', '', 14); - $this->Cell(0, 6, __('Page number:') . ' ' . $this->PageNo() . '/{nb}', 'T', 0, 'C'); - $this->Cell(0, 6, PMA_localisedDate(), 0, 1, 'R'); - $this->SetY(20); - } - } - function Bookmark($txt, $level = 0, $y = 0) - { - // Add a bookmark - $this->Outlines[0][] = $level; - $this->Outlines[1][] = $txt; - $this->Outlines[2][] = $this->page; - if ($y == -1) { - $y = $this->GetY(); - } - $this->Outlines[3][] = round($this->hPt - $y * $this->k, 2); - } - - function _putbookmarks() - { - if (count($this->Outlines) > 0) { - // Save object number - $memo_n = $this->n; - // Take the number of sub elements for an outline - $nb_outlines = sizeof($this->Outlines[0]); - $first_level = array(); - $parent = array(); - $parent[0] = 1; - for ($i = 0; $i < $nb_outlines; $i++) { - $level = $this->Outlines[0][$i]; - $kids = 0; - $last = -1; - $prev = -1; - $next = -1; - if ($i > 0) { - $cursor = $i-1; - // Take the previous outline in the same level - while ($this->Outlines[0][$cursor] > $level && $cursor > 0) - $cursor--; - if ($this->Outlines[0][$cursor] == $level) { - $prev = $cursor; - } - } - if ($i < $nb_outlines-1) { - $cursor = $i + 1; - while (isset($this->Outlines[0][$cursor]) && $this->Outlines[0][$cursor] > $level) { - // Take the immediate kid in level + 1 - if ($this->Outlines[0][$cursor] == $level + 1) { - $kids++; - $last = $cursor; - } - $cursor++; - } - $cursor = $i + 1; - // Take the next outline in the same level - while ($this->Outlines[0][$cursor] > $level && ($cursor + 1 < sizeof($this->Outlines[0]))) - $cursor++; - if ($this->Outlines[0][$cursor] == $level) { - $next = $cursor; - } - } - $this->_newobj(); - $parent[$level + 1] = $this->n; - if ($level == 0) { - $first_level[] = $this->n; - } - $this->_out('<<'); - $this->_out('/Title (' . $this->Outlines[1][$i] . ')'); - $this->_out('/Parent ' . $parent[$level] . ' 0 R'); - if ($prev != -1) { - $this->_out('/Prev ' . ($memo_n + $prev + 1) . ' 0 R'); - } - if ($next != -1) { - $this->_out('/Next ' . ($this->n + $next - $i) . ' 0 R'); - } - $this->_out('/Dest [' . (1 + (2 * $this->Outlines[2][$i])) . ' 0 R /XYZ null ' . $this->Outlines[3][$i] . ' null]'); - if ($kids > 0) { - $this->_out('/First ' . ($this->n + 1) . ' 0 R'); - $this->_out('/Last ' . ($this->n + $last - $i) . ' 0 R'); - $this->_out('/Count -' . $kids); - } - $this->_out('>>'); - $this->_out('endobj'); - } - // First page of outlines - $this->_newobj(); - $this->def_outlines = $this->n; - $this->_out('<<'); - $this->_out('/Type'); - $this->_out('/Outlines'); - $this->_out('/First ' . $first_level[0] . ' 0 R'); - $this->_out('/Last ' . $first_level[sizeof($first_level)-1] . ' 0 R'); - $this->_out('/Count ' . sizeof($first_level)); - $this->_out('>>'); - $this->_out('endobj'); - } - } - - function _putresources() - { - parent::_putresources(); - $this->_putbookmarks(); - } - - function _putcatalog() - { - parent::_putcatalog(); - if (count($this->Outlines) > 0) { - $this->_out('/Outlines ' . $this->def_outlines . ' 0 R'); - $this->_out('/PageMode /UseOutlines'); - } - } - function SetWidths($w) - { - // column widths - $this->widths = $w; - } - - function Row($data, $links) - { - // line height - $nb = 0; - $data_cnt = count($data); - for ($i = 0;$i < $data_cnt;$i++) - $nb = max($nb, $this->NbLines($this->widths[$i], $data[$i])); - $il = $this->FontSize; - $h = ($il + 1) * $nb; - // page break if necessary - $this->CheckPageBreak($h); - // draw the cells - $data_cnt = count($data); - for ($i = 0;$i < $data_cnt;$i++) { - $w = $this->widths[$i]; - // save current position - $x = $this->GetX(); - $y = $this->GetY(); - // draw the border - $this->Rect($x, $y, $w, $h); - if (isset($links[$i])) { - $this->Link($x, $y, $w, $h, $links[$i]); - } - // print text - $this->MultiCell($w, $il + 1, $data[$i], 0, 'L'); - // go to right side - $this->SetXY($x + $w, $y); - } - // go to line - $this->Ln($h); - } - - function CheckPageBreak($h) - { - // if height h overflows, manual page break - if ($this->GetY() + $h > $this->PageBreakTrigger) { - $this->AddPage($this->CurOrientation); - } - } - - function NbLines($w, $txt) - { - // compute number of lines used by a multicell of width w - $cw = &$this->CurrentFont['cw']; - if ($w == 0) { - $w = $this->w - $this->rMargin - $this->x; - } - $wmax = ($w-2 * $this->cMargin) * 1000 / $this->FontSize; - $s = str_replace("\r", '', $txt); - $nb = strlen($s); - if ($nb > 0 and $s[$nb-1] == "\n") { - $nb--; - } - $sep = -1; - $i = 0; - $j = 0; - $l = 0; - $nl = 1; - while ($i < $nb) { - $c = $s[$i]; - if ($c == "\n") { - $i++; - $sep = -1; - $j = $i; - $l = 0; - $nl++; - continue; - } - if ($c == ' ') { - $sep = $i; - } - $l += isset($cw[ord($c)])?$cw[ord($c)]:0 ; - if ($l > $wmax) { - if ($sep == -1) { - if ($i == $j) { - $i++; - } - } else { - $i = $sep + 1; - } - $sep = -1; - $j = $i; - $l = 0; - $nl++; - } else { - $i++; - } - } - return $nl; - } -} // end of the "PMA_PDF" class - - -/** - * Draws tables schema - * - * @access private - * @see PMA_RT - * @package phpMyAdmin - */ -class PMA_RT_Table { - /** - * Defines private properties - */ - var $nb_fiels; - var $table_name; - var $width = 0; - var $height; - var $fields = array(); - var $height_cell = 6; - var $x, $y; - var $primary = array(); - var $show_info = false; - - /** - * Returns title of the current table, - * title can have the dimensions of the table - * - * @access private - */ - function getTitle() - { - return ($this->show_info ? sprintf('%.0f', $this->width) . 'x' . sprintf('%.0f', $this->height) : '') . ' ' . $this->table_name; - } // end of the "getTitle" function - /** - * Sets the width of the table - * - * @param integer ff The font size - * @global object The current PDF document - * @access private - * @see PMA_PDF - */ - function PMA_RT_Table_setWidth($ff) - { - global $pdf; - - foreach ($this->fields AS $field) { - $this->width = max($this->width, $pdf->GetStringWidth($field)); - } - $this->width += $pdf->GetStringWidth(' '); - $pdf->SetFont($ff, 'B'); - // it is unknown what value must be added, because - // table title is affected by the tabe width value - while ($this->width < $pdf->GetStringWidth($this->getTitle())) { - $this->width += 5; - } - $pdf->SetFont($ff, ''); - } // end of the "PMA_RT_Table_setWidth()" method - /** - * Sets the height of the table - * - * @access private - */ - function PMA_RT_Table_setHeight() - { - $this->height = (count($this->fields) + 1) * $this->height_cell; - } // end of the "PMA_RT_Table_setHeight()" method - /** - * Do draw the table - * - * @param integer ff The font size - * @param boolean setcolortWhether to display color - * @global object The current PDF document - * @access private - * @see PMA_PDF - */ - function PMA_RT_Table_draw($ff, $setcolor = 0) - { - global $pdf, $with_doc; - - $pdf->PMA_PDF_setXyScale($this->x, $this->y); - $pdf->SetFont($ff, 'B'); - if ($setcolor) { - $pdf->SetTextColor(200); - $pdf->SetFillColor(0, 0, 128); - } - if ($with_doc) { - $pdf->SetLink($pdf->PMA_links['RT'][$this->table_name]['-'], -1); - } else { - $pdf->PMA_links['doc'][$this->table_name]['-'] = ''; - } - - $pdf->PMA_PDF_cellScale($this->width, $this->height_cell, $this->getTitle(), 1, 1, 'C', $setcolor, $pdf->PMA_links['doc'][$this->table_name]['-']); - $pdf->PMA_PDF_setXScale($this->x); - $pdf->SetFont($ff, ''); - $pdf->SetTextColor(0); - $pdf->SetFillColor(255); - - foreach ($this->fields AS $field) { - if ($setcolor) { - if (in_array($field, $this->primary)) { - $pdf->SetFillColor(215, 121, 123); - } - if ($field == $this->displayfield) { - $pdf->SetFillColor(142, 159, 224); - } - } - if ($with_doc) { - $pdf->SetLink($pdf->PMA_links['RT'][$this->table_name][$field], -1); - } else { - $pdf->PMA_links['doc'][$this->table_name][$field] = ''; - } - - $pdf->PMA_PDF_cellScale($this->width, $this->height_cell, ' ' . $field, 1, 1, 'L', $setcolor, $pdf->PMA_links['doc'][$this->table_name][$field]); - $pdf->PMA_PDF_setXScale($this->x); - $pdf->SetFillColor(255); - } // end while - /*if ($pdf->PageNo() > 1) { - $pdf->PMA_PDF_die(__('The scale factor is too small to fit the schema on one page')); - } */ - } // end of the "PMA_RT_Table_draw()" method - /** - * The "PMA_RT_Table" constructor - * - * @param string table_name The table name - * @param integer ff The font size - * @param integer same_width The max. with among tables - * @param boolean show_keys Whether to display keys or not - * @param boolean show_info Whether to display table position or not - * @global object The current PDF document - * @global integer The current page number (from the - * $cfg['Servers'][$i]['table_coords'] table) - * @global array The relations settings - * @global string The current db name - * @access private - * @see PMA_PDF, PMA_RT_Table::PMA_RT_Table_setWidth, - PMA_RT_Table::PMA_RT_Table_setHeight - */ - function __construct($table_name, $ff, &$same_wide_width, $show_keys = false, $show_info = false) - { - global $pdf, $pdf_page_number, $cfgRelation, $db; - - $this->table_name = $table_name; - $sql = 'DESCRIBE ' . PMA_backquote($table_name); - $result = PMA_DBI_try_query($sql, null, PMA_DBI_QUERY_STORE); - if (!$result || !PMA_DBI_num_rows($result)) { - $pdf->PMA_PDF_die(sprintf(__('The %s table doesn\'t exist!'), $table_name)); - } - // load fields - //check to see if it will load all fields or only the foreign keys - if ($show_keys) { - $indexes = PMA_Index::getFromTable($this->table_name, $db); - $all_columns = array(); - foreach ($indexes as $index) { - $all_columns = array_merge($all_columns, array_flip(array_keys($index->getColumns()))); - } - $this->fields = array_keys($all_columns); - } else { - while ($row = PMA_DBI_fetch_row($result)) { - $this->fields[] = $row[0]; - } - } - - $this->show_info = $show_info; - - // height and width - $this->PMA_RT_Table_setHeight(); - // setWidth must me after setHeight, because title - // can include table height which changes table width - $this->PMA_RT_Table_setWidth($ff); - if ($same_wide_width < $this->width) { - $same_wide_width = $this->width; - } - // x and y - $sql = 'SELECT x, y FROM ' - . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) - . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' - . ' AND table_name = \'' . PMA_sqlAddslashes($table_name) . '\'' - . ' AND pdf_page_number = ' . $pdf_page_number; - $result = PMA_query_as_controluser($sql, false, PMA_DBI_QUERY_STORE); - - if (!$result || !PMA_DBI_num_rows($result)) { - $pdf->PMA_PDF_die(sprintf(__('Please configure the coordinates for table %s'), $table_name)); - } - list($this->x, $this->y) = PMA_DBI_fetch_row($result); - $this->x = (double) $this->x; - $this->y = (double) $this->y; - // displayfield - $this->displayfield = PMA_getDisplayField($db, $table_name); - // index - $result = PMA_DBI_query('SHOW INDEX FROM ' . PMA_backquote($table_name) . ';', null, PMA_DBI_QUERY_STORE); - if (PMA_DBI_num_rows($result) > 0) { - while ($row = PMA_DBI_fetch_assoc($result)) { - if ($row['Key_name'] == 'PRIMARY') { - $this->primary[] = $row['Column_name']; - } - } - } // end if - } // end of the "PMA_RT_Table()" method -} // end class "PMA_RT_Table" -/** - * Draws relation links - * - * @access private - * @see PMA_RT - * @package phpMyAdmin - */ -class PMA_RT_Relation { - /** - * Defines private properties - */ - var $x_src, $y_src; - var $src_dir ; - var $dest_dir; - var $x_dest, $y_dest; - var $w_tick = 5; - - /** - * Gets arrows coordinates - * - * @param string table The current table name - * @param string column The relation column name - * @return array Arrows coordinates - * @access private - */ - function PMA_RT_Relation_getXy($table, $column) - { - $pos = array_search($column, $table->fields); - // x_left, x_right, y - return array($table->x, $table->x + + $table->width, $table->y + ($pos + 1.5) * $table->height_cell); - } // end of the "PMA_RT_Relation_getXy()" method - /** - * Do draws relation links - * - * @param boolean change_color Whether to use one color per relation or not - * @param integer i The id of the link to draw - * @global object The current PDF document - * @access private - * @see PMA_PDF - */ - function PMA_RT_Relation_draw($change_color, $i) - { - global $pdf; - - if ($change_color) { - $d = $i % 6; - $j = ($i - $d) / 6; - $j = $j % 4; - $j++; - $case = array( - array(1, 0, 0), - array(0, 1, 0), - array(0, 0, 1), - array(1, 1, 0), - array(1, 0, 1), - array(0, 1, 1) - ); - list ($a, $b, $c) = $case[$d]; - $e = (1 - ($j - 1) / 6); - $pdf->SetDrawColor($a * 255 * $e, $b * 255 * $e, $c * 255 * $e); - } else { - $pdf->SetDrawColor(0); - } // end if... else... - $pdf->PMA_PDF_setLineWidthScale(0.2); - $pdf->PMA_PDF_lineScale($this->x_src, $this->y_src, $this->x_src + $this->src_dir * $this->w_tick, $this->y_src); - $pdf->PMA_PDF_lineScale($this->x_dest + $this->dest_dir * $this->w_tick, $this->y_dest, $this->x_dest, $this->y_dest); - $pdf->PMA_PDF_setLineWidthScale(0.1); - $pdf->PMA_PDF_lineScale($this->x_src + $this->src_dir * $this->w_tick, $this->y_src, $this->x_dest + $this->dest_dir * $this->w_tick, $this->y_dest); - // arrow - $root2 = 2 * sqrt(2); - $pdf->PMA_PDF_lineScale($this->x_src + $this->src_dir * $this->w_tick * 0.75, $this->y_src, $this->x_src + $this->src_dir * (0.75 - 1 / $root2) * $this->w_tick, $this->y_src + $this->w_tick / $root2); - $pdf->PMA_PDF_lineScale($this->x_src + $this->src_dir * $this->w_tick * 0.75, $this->y_src, $this->x_src + $this->src_dir * (0.75 - 1 / $root2) * $this->w_tick, $this->y_src - $this->w_tick / $root2); - - $pdf->PMA_PDF_lineScale($this->x_dest + $this->dest_dir * $this->w_tick / 2, $this->y_dest, $this->x_dest + $this->dest_dir * (0.5 + 1 / $root2) * $this->w_tick, $this->y_dest + $this->w_tick / $root2); - $pdf->PMA_PDF_lineScale($this->x_dest + $this->dest_dir * $this->w_tick / 2, $this->y_dest, $this->x_dest + $this->dest_dir * (0.5 + 1 / $root2) * $this->w_tick, $this->y_dest - $this->w_tick / $root2); - $pdf->SetDrawColor(0); - } // end of the "PMA_RT_Relation_draw()" method - /** - * The "PMA_RT_Relation" constructor - * - * @param string master_table The master table name - * @param string master_field The relation field in the master table - * @param string foreign_table The foreign table name - * @param string foreigh_field The relation field in the foreign table - * @access private - * @see PMA_RT_Relation::PMA_RT_Relation_getXy - */ - function __construct($master_table, $master_field, $foreign_table, $foreign_field) - { - $src_pos = $this->PMA_RT_Relation_getXy($master_table, $master_field); - $dest_pos = $this->PMA_RT_Relation_getXy($foreign_table, $foreign_field); - $src_left = $src_pos[0] - $this->w_tick; - $src_right = $src_pos[1] + $this->w_tick; - $dest_left = $dest_pos[0] - $this->w_tick; - $dest_right = $dest_pos[1] + $this->w_tick; - - $d1 = abs($src_left - $dest_left); - $d2 = abs($src_right - $dest_left); - $d3 = abs($src_left - $dest_right); - $d4 = abs($src_right - $dest_right); - $d = min($d1, $d2, $d3, $d4); - - if ($d == $d1) { - $this->x_src = $src_pos[0]; - $this->src_dir = -1; - $this->x_dest = $dest_pos[0]; - $this->dest_dir = -1; - } elseif ($d == $d2) { - $this->x_src = $src_pos[1]; - $this->src_dir = 1; - $this->x_dest = $dest_pos[0]; - $this->dest_dir = -1; - } elseif ($d == $d3) { - $this->x_src = $src_pos[0]; - $this->src_dir = -1; - $this->x_dest = $dest_pos[1]; - $this->dest_dir = 1; - } else { - $this->x_src = $src_pos[1]; - $this->src_dir = 1; - $this->x_dest = $dest_pos[1]; - $this->dest_dir = 1; - } - $this->y_src = $src_pos[2]; - $this->y_dest = $dest_pos[2]; - } // end of the "PMA_RT_Relation()" method -} // end of the "PMA_RT_Relation" class -/** - * Draws and send the database schema - * - * @access public - * @see PMA_PDF - * @package phpMyAdmin - */ -class PMA_RT { - /** - * Defines private properties - */ - var $tables = array(); - var $relations = array(); - var $ff = PMA_PDF_FONT; - var $x_max = 0; - var $y_max = 0; - var $scale; - var $x_min = 100000; - var $y_min = 100000; - var $t_marg = 10; - var $b_marg = 10; - var $l_marg = 10; - var $r_marg = 10; - var $tablewidth; - var $same_wide = 0; - - /** - * Sets X and Y minimum and maximum for a table cell - * - * @param string table The table name - * @access private - */ - function PMA_RT_setMinMax($table) - { - $this->x_max = max($this->x_max, $table->x + $table->width); - $this->y_max = max($this->y_max, $table->y + $table->height); - $this->x_min = min($this->x_min, $table->x); - $this->y_min = min($this->y_min, $table->y); - } // end of the "PMA_RT_setMinMax()" method - /** - * Defines relation objects - * - * @param string master_table The master table name - * @param string master_field The relation field in the master table - * @param string foreign_table The foreign table name - * @param string foreign_field The relation field in the foreign table - * @param boolean show_info Whether to display table position or not - * @access private - * @see PMA_RT_setMinMax - */ - function PMA_RT_addRelation($master_table, $master_field, $foreign_table, $foreign_field, $show_info) - { - if (!isset($this->tables[$master_table])) { - $this->tables[$master_table] = new PMA_RT_Table($master_table, $this->ff, $this->tablewidth, false, $show_info); - $this->PMA_RT_setMinMax($this->tables[$master_table]); - } - if (!isset($this->tables[$foreign_table])) { - $this->tables[$foreign_table] = new PMA_RT_Table($foreign_table, $this->ff, $this->tablewidth, false, $show_info); - $this->PMA_RT_setMinMax($this->tables[$foreign_table]); - } - $this->relations[] = new PMA_RT_Relation($this->tables[$master_table], $master_field, $this->tables[$foreign_table], $foreign_field); - } // end of the "PMA_RT_addRelation()" method - /** - * Draws the grid - * - * @global object the current PMA_PDF instance - * @access private - * @see PMA_PDF - */ - function PMA_RT_strokeGrid() - { - global $pdf; - - $pdf->SetMargins(0, 0); - $pdf->SetDrawColor(200, 200, 200); - // Draws horizontal lines - for ($l = 0; $l < 21; $l++) { - $pdf->line(0, $l * 10, $pdf->getFh(), $l * 10); - // Avoid duplicates - if ($l > 0) { - $pdf->SetXY(0, $l * 10); - $label = (string) sprintf('%.0f', ($l * 10 - $this->t_marg) * $this->scale + $this->y_min); - $pdf->Cell(5, 5, ' ' . $label); - } // end if - } // end for - // Draws vertical lines - for ($j = 0; $j < 30 ;$j++) { - $pdf->line($j * 10, 0, $j * 10, $pdf->getFw()); - $pdf->SetXY($j * 10, 0); - $label = (string) sprintf('%.0f', ($j * 10 - $this->l_marg) * $this->scale + $this->x_min); - $pdf->Cell(5, 7, $label); - } // end for - } // end of the "PMA_RT_strokeGrid()" method - /** - * Draws relation arrows - * - * @param boolean change_color Whether to use one color per relation or not - * @access private - * @see PMA_RT_Relation::PMA_RT_Relation_draw() - */ - function PMA_RT_drawRelations($change_color) - { - $i = 0; - foreach ($this->relations AS $relation) { - $relation->PMA_RT_Relation_draw($change_color, $i); - $i++; - } // end while - } // end of the "PMA_RT_drawRelations()" method - /** - * Draws tables - * - * @param boolean draw_color Whether to display table position or not - * @access private - * @see PMA_RT_Table::PMA_RT_Table_draw() - */ - function PMA_RT_drawTables($draw_color = 0) - { - foreach ($this->tables AS $table) { - $table->PMA_RT_Table_draw($this->ff, $draw_color); - } - } // end of the "PMA_RT_drawTables()" method - /** - * Ouputs the PDF document to a file - * - * @global object The current PDF document - * @global string The current database name - * @global integer The current page number (from the - * $cfg['Servers'][$i]['table_coords'] table) - * @access private - * @see PMA_PDF - */ - function PMA_RT_showRt() - { - global $pdf, $db, $pdf_page_number, $cfgRelation; - - $pdf->SetFontSize(14); - $pdf->SetLineWidth(0.2); - $pdf->SetDisplayMode('fullpage'); - // Get the name of this pdfpage to use as filename (Mike Beck) - $_name_sql = 'SELECT page_descr FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['pdf_pages']) - . ' WHERE page_nr = ' . $pdf_page_number; - $_name_rs = PMA_query_as_controluser($_name_sql); - if ($_name_rs) { - $_name_row = PMA_DBI_fetch_row($_name_rs); - $filename = $_name_row[0] . '.pdf'; - } - // i don't know if there is a chance for this to happen, but rather be on the safe side: - if (empty($filename)) { - $filename = $pdf_page_number . '.pdf'; - } - // $pdf->Output($db . '_' . $filename, TRUE); - $pdf->Output($db . '_' . $filename, 'I'); // destination: Inline - } // end of the "PMA_RT_showRt()" method - /** - * The "PMA_RT" constructor - * - * @param integer which_rel The page number to draw (from the - * $cfg['Servers'][$i]['table_coords'] table) - * @param boolean show_info Whether to display table position or not - * @param boolean change_color Was originally whether to use one color per - * relation or not, now enables/disables color - * everywhere, due to some problems printing with color - * @param boolean show_grid Whether to draw grids or not - * @param boolean all_tab_same_wide Whether all tables should have the same width or not - * @param boolean show_keys Wheter to show all field or only the keys - * @global object The current PDF document - * @global string The current db name - * @global array The relations settings - * @access private - * @see PMA_PDF - */ - function __construct($which_rel, $show_info = 0, $change_color = 0, $show_grid = 0, $all_tab_same_wide = 0, $orientation = 'L', $paper = 'A4', $show_keys = 0) - { - global $pdf, $db, $cfgRelation, $with_doc; - - $this->same_wide = $all_tab_same_wide; - // Initializes a new document - $pdf = new PMA_PDF('L', 'mm', $paper); - $pdf->SetTitle(sprintf(__('Schema of the %s database - Page %s'), $GLOBALS['db'], $which_rel)); - $pdf->setCMargin(0); - $pdf->Open(); - $pdf->SetAuthor('phpMyAdmin ' . PMA_VERSION); - $pdf->AliasNbPages(); - $pdf->AddFont('DejaVuSans', '', 'dejavusans.php'); - $pdf->AddFont('DejaVuSans', 'B', 'dejavusansb.php'); - $pdf->AddFont('DejaVuSerif', '', 'dejavuserif.php'); - $pdf->AddFont('DejaVuSerif', 'B', 'dejavuserifb.php'); - $this->ff = PMA_PDF_FONT; - $pdf->SetFont($this->ff, '', 14); - $pdf->SetAutoPageBreak('auto'); - // Gets tables on this page - $tab_sql = 'SELECT table_name FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) - . ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' - . ' AND pdf_page_number = ' . $which_rel; - $tab_rs = PMA_query_as_controluser($tab_sql, null, PMA_DBI_QUERY_STORE); - if (!$tab_rs || !PMA_DBI_num_rows($tab_rs) > 0) { - $pdf->PMA_PDF_die(__('No tables')); - // die('No tables'); - } while ($curr_table = @PMA_DBI_fetch_assoc($tab_rs)) { - $alltables[] = PMA_sqlAddslashes($curr_table['table_name']); - // $intable = '\'' . implode('\', \'', $alltables) . '\''; - } - // make doc // - if ($with_doc) { - $pdf->SetAutoPageBreak('auto', 15); - $pdf->setCMargin(1); - PMA_RT_DOC($alltables); - $pdf->SetAutoPageBreak('auto'); - $pdf->setCMargin(0); - } - - $pdf->Addpage(); - - if ($with_doc) { - $pdf->SetLink($pdf->PMA_links['RT']['-'], -1); - $pdf->Bookmark(__('Relational schema')); - $pdf->SetAlias('{00}', $pdf->PageNo()) ; - $this->t_marg = 18; - $this->b_marg = 18; - } - - /* snip */ - - foreach ($alltables AS $table) { - if (!isset($this->tables[$table])) { - $this->tables[$table] = new PMA_RT_Table($table, $this->ff, $this->tablewidth, $show_keys, $show_info); - } - - if ($this->same_wide) { - $this->tables[$table]->width = $this->tablewidth; - } - $this->PMA_RT_setMinMax($this->tables[$table]); - } - // Defines the scale factor - $this->scale = ceil( - max( - ($this->x_max - $this->x_min) / ($pdf->getFh() - $this->r_marg - $this->l_marg), - ($this->y_max - $this->y_min) / ($pdf->getFw() - $this->t_marg - $this->b_marg)) - * 100) / 100; - - $pdf->PMA_PDF_setScale($this->scale, $this->x_min, $this->y_min, $this->l_marg, $this->t_marg); - // Builds and save the PDF document - $pdf->PMA_PDF_setLineWidthScale(0.1); - - if ($show_grid) { - $pdf->SetFontSize(10); - $this->PMA_RT_strokeGrid(); - } - $pdf->PMA_PDF_setFontSizeScale(14); - // $sql = 'SELECT * FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['relation']) - // . ' WHERE master_db = \'' . PMA_sqlAddslashes($db) . '\' ' - // . ' AND foreign_db = \'' . PMA_sqlAddslashes($db) . '\' ' - // . ' AND master_table IN (' . $intable . ')' - // . ' AND foreign_table IN (' . $intable . ')'; - // $result = PMA_query_as_controluser($sql); - - // previous logic was checking master tables and foreign tables - // but I think that looping on every table of the pdf page as a master - // and finding its foreigns is OK (then we can support innodb) - $seen_a_relation = false; - foreach ($alltables AS $one_table) { - $exist_rel = PMA_getForeigners($db, $one_table, '', 'both'); - if ($exist_rel) { - $seen_a_relation = true; - foreach ($exist_rel AS $master_field => $rel) { - // put the foreign table on the schema only if selected - // by the user - // (do not use array_search() because we would have to - // to do a === FALSE and this is not PHP3 compatible) - if (in_array($rel['foreign_table'], $alltables)) { - $this->PMA_RT_addRelation($one_table, $master_field, $rel['foreign_table'], $rel['foreign_field'], $show_info); - } - } // end while - } // end if - } // end while - // also show tables without relations - // $norelations = TRUE; - // if ($result && PMA_DBI_num_rows($result) > 0) { - // $norelations = FALSE; - // while ($row = PMA_DBI_fetch_assoc($result)) { - // $this->PMA_RT_addRelation($row['master_table'], $row['master_field'], $row['foreign_table'], $row['foreign_field']); - // } - // } - // if ($norelations == FALSE) { - if ($seen_a_relation) { - $this->PMA_RT_drawRelations($change_color); - } - - $this->PMA_RT_drawTables($change_color); - - $this->PMA_RT_showRt(); - } // end of the "PMA_RT()" method -} // end of the "PMA_RT" class - -function PMA_RT_DOC($alltables) -{ - global $db, $pdf, $orientation, $paper; - // TOC - $pdf->addpage($GLOBALS['orientation']); - $pdf->Cell(0, 9, __('Table of contents'), 1, 0, 'C'); - $pdf->Ln(15); - $i = 1; - foreach ($alltables AS $table) { - $pdf->PMA_links['doc'][$table]['-'] = $pdf->AddLink(); - $pdf->SetX(10); - // $pdf->Ln(1); - $pdf->Cell(0, 6, __('Page number:') . ' {' . sprintf("%02d", $i + 1) . '}', 0, 0, 'R', 0, $pdf->PMA_links['doc'][$table]['-']); - $pdf->SetX(10); - $pdf->Cell(0, 6, $i . ' ' . $table, 0, 1, 'L', 0, $pdf->PMA_links['doc'][$table]['-']); - // $pdf->Ln(1); - $result = PMA_DBI_query('SHOW FIELDS FROM ' . PMA_backquote($table) . ';'); - while ($row = PMA_DBI_fetch_assoc($result)) { - $pdf->SetX(20); - $field_name = $row['Field']; - $pdf->PMA_links['doc'][$table][$field_name] = $pdf->AddLink(); - // $pdf->Cell(0, 6, $field_name,0,1,'L',0, $pdf->PMA_links['doc'][$table][$field_name]); - } - $lasttable = $table; - $i++; - } - $pdf->PMA_links['RT']['-'] = $pdf->AddLink(); - $pdf->SetX(10); - $pdf->Cell(0, 6, __('Page number:') . ' {' . sprintf("%02d", $i + 1) . '}', 0, 0, 'R', 0, $pdf->PMA_links['doc'][$lasttable]['-']); - $pdf->SetX(10); - $pdf->Cell(0, 6, $i + 1 . ' ' . __('Relational schema'), 0, 1, 'L', 0, $pdf->PMA_links['RT']['-']); - $z = 0; - foreach ($alltables AS $table) { - $z++; - $pdf->addpage($GLOBALS['orientation']); - $pdf->Bookmark($table); - $pdf->SetAlias('{' . sprintf("%02d", $z) . '}', $pdf->PageNo()) ; - $pdf->PMA_links['RT'][$table]['-'] = $pdf->AddLink(); - $pdf->SetLink($pdf->PMA_links['doc'][$table]['-'], -1); - $pdf->SetFont('', 'B', 18); - $pdf->Cell(0, 8, $z . ' ' . $table, 1, 1, 'C', 0, $pdf->PMA_links['RT'][$table]['-']); - $pdf->SetFont('', '', 8); - $pdf->ln(); - - $cfgRelation = PMA_getRelationsParam(); - $comments = PMA_getComments($db, $table); - if ($cfgRelation['mimework']) { - $mime_map = PMA_getMIME($db, $table, true); - } - - /** - * Gets table informations - */ - $showtable = PMA_Table::sGetStatusInfo($db, $table); - $num_rows = (isset($showtable['Rows']) ? $showtable['Rows'] : 0); - $show_comment = (isset($showtable['Comment']) ? $showtable['Comment'] : ''); - $create_time = (isset($showtable['Create_time']) ? PMA_localisedDate(strtotime($showtable['Create_time'])) : ''); - $update_time = (isset($showtable['Update_time']) ? PMA_localisedDate(strtotime($showtable['Update_time'])) : ''); - $check_time = (isset($showtable['Check_time']) ? PMA_localisedDate(strtotime($showtable['Check_time'])) : ''); - - /** - * Gets table keys and retains them - */ - $result = PMA_DBI_query('SHOW KEYS FROM ' . PMA_backquote($table) . ';'); - $primary = ''; - $indexes = array(); - $lastIndex = ''; - $indexes_info = array(); - $indexes_data = array(); - $pk_array = array(); // will be use to emphasis prim. keys in the table - // view - while ($row = PMA_DBI_fetch_assoc($result)) { - // Backups the list of primary keys - if ($row['Key_name'] == 'PRIMARY') { - $primary .= $row['Column_name'] . ', '; - $pk_array[$row['Column_name']] = 1; - } - // Retains keys informations - if ($row['Key_name'] != $lastIndex) { - $indexes[] = $row['Key_name']; - $lastIndex = $row['Key_name']; - } - $indexes_info[$row['Key_name']]['Sequences'][] = $row['Seq_in_index']; - $indexes_info[$row['Key_name']]['Non_unique'] = $row['Non_unique']; - if (isset($row['Cardinality'])) { - $indexes_info[$row['Key_name']]['Cardinality'] = $row['Cardinality']; - } - // I don't know what does following column mean.... - // $indexes_info[$row['Key_name']]['Packed'] = $row['Packed']; - $indexes_info[$row['Key_name']]['Comment'] = $row['Comment']; - - $indexes_data[$row['Key_name']][$row['Seq_in_index']]['Column_name'] = $row['Column_name']; - if (isset($row['Sub_part'])) { - $indexes_data[$row['Key_name']][$row['Seq_in_index']]['Sub_part'] = $row['Sub_part']; - } - } // end while - if ($result) { - PMA_DBI_free_result($result); - } - - /** - * Gets fields properties - */ - $result = PMA_DBI_query('SHOW FIELDS FROM ' . PMA_backquote($table) . ';', null, PMA_DBI_QUERY_STORE); - $fields_cnt = PMA_DBI_num_rows($result); - // Check if we can use Relations (Mike Beck) - if (!empty($cfgRelation['relation'])) { - // Find which tables are related with the current one and write it in - // an array - $res_rel = PMA_getForeigners($db, $table); - - if (count($res_rel) > 0) { - $have_rel = true; - } else { - $have_rel = false; - } - } else { - $have_rel = false; - } // end if - /** - * Displays the comments of the table if MySQL >= 3.23 - */ - - $break = false; - if (!empty($show_comment)) { - $pdf->Cell(0, 3, __('Table comments') . ' : ' . $show_comment, 0, 1); - $break = true; - } - - if (!empty($create_time)) { - $pdf->Cell(0, 3, __('Creation') . ': ' . $create_time, 0, 1); - $break = true; - } - - if (!empty($update_time)) { - $pdf->Cell(0, 3, __('Last update') . ': ' . $update_time, 0, 1); - $break = true; - } - - if (!empty($check_time)) { - $pdf->Cell(0, 3, __('Last check') . ': ' . $check_time, 0, 1); - $break = true; - } - - if ($break == true) { - $pdf->Cell(0, 3, '', 0, 1); - $pdf->Ln(); - } - - $pdf->SetFont('', 'B'); - if (isset($orientation) && $orientation == 'L') { - $pdf->Cell(25, 8, ucfirst(__('Column')), 1, 0, 'C'); - $pdf->Cell(20, 8, ucfirst(__('Type')), 1, 0, 'C'); - $pdf->Cell(20, 8, ucfirst(__('Attributes')), 1, 0, 'C'); - $pdf->Cell(10, 8, ucfirst(__('Null')), 1, 0, 'C'); - $pdf->Cell(20, 8, ucfirst(__('Default')), 1, 0, 'C'); - $pdf->Cell(25, 8, ucfirst(__('Extra')), 1, 0, 'C'); - $pdf->Cell(45, 8, ucfirst(__('Links to')), 1, 0, 'C'); - - if ($paper == 'A4') { - $comments_width = 67; - } else { - // this is really intended for 'letter' - /** - * @todo find optimal width for all formats - */ - $comments_width = 50; - } - $pdf->Cell($comments_width, 8, ucfirst(__('Comments')), 1, 0, 'C'); - $pdf->Cell(45, 8, 'MIME', 1, 1, 'C'); - $pdf->SetWidths(array(25, 20, 20, 10, 20, 25, 45, $comments_width, 45)); - } else { - $pdf->Cell(20, 8, ucfirst(__('Column')), 1, 0, 'C'); - $pdf->Cell(20, 8, ucfirst(__('Type')), 1, 0, 'C'); - $pdf->Cell(20, 8, ucfirst(__('Attributes')), 1, 0, 'C'); - $pdf->Cell(10, 8, ucfirst(__('Null')), 1, 0, 'C'); - $pdf->Cell(15, 8, ucfirst(__('Default')), 1, 0, 'C'); - $pdf->Cell(15, 8, ucfirst(__('Extra')), 1, 0, 'C'); - $pdf->Cell(30, 8, ucfirst(__('Links to')), 1, 0, 'C'); - $pdf->Cell(30, 8, ucfirst(__('Comments')), 1, 0, 'C'); - $pdf->Cell(30, 8, 'MIME', 1, 1, 'C'); - $pdf->SetWidths(array(20, 20, 20, 10, 15, 15, 30, 30, 30)); - } - $pdf->SetFont('', ''); - - while ($row = PMA_DBI_fetch_assoc($result)) { - $type = $row['Type']; - // reformat mysql query output - // set or enum types: slashes single quotes inside options - if (preg_match('@^(set|enum)\((.+)\)$@i', $type, $tmp)) { - $tmp[2] = substr(preg_replace("@([^,])''@", "\\1\\'", ',' . $tmp[2]), 1); - $type = $tmp[1] . '(' . str_replace(',', ', ', $tmp[2]) . ')'; - $type_nowrap = ''; - - $binary = 0; - $unsigned = 0; - $zerofill = 0; - } else { - $type_nowrap = ' nowrap="nowrap"'; - $type = preg_replace('@BINARY@i', '', $type); - $type = preg_replace('@ZEROFILL@i', '', $type); - $type = preg_replace('@UNSIGNED@i', '', $type); - if (empty($type)) { - $type = ' '; - } - - $binary = stristr($row['Type'], 'BINARY'); - $unsigned = stristr($row['Type'], 'UNSIGNED'); - $zerofill = stristr($row['Type'], 'ZEROFILL'); - } - $attribute = ' '; - if ($binary) { - $attribute = 'BINARY'; - } - if ($unsigned) { - $attribute = 'UNSIGNED'; - } - if ($zerofill) { - $attribute = 'UNSIGNED ZEROFILL'; - } - if (!isset($row['Default'])) { - if ($row['Null'] != '' && $row['Null'] != 'NO') { - $row['Default'] = 'NULL'; - } - } - $field_name = $row['Field']; - // $pdf->Ln(); - $pdf->PMA_links['RT'][$table][$field_name] = $pdf->AddLink(); - $pdf->Bookmark($field_name, 1, -1); - $pdf->SetLink($pdf->PMA_links['doc'][$table][$field_name], -1); - $pdf_row = array($field_name, - $type, - $attribute, - ($row['Null'] == '' || $row['Null'] == 'NO') ? __('No') : __('Yes'), - ((isset($row['Default'])) ? $row['Default'] : ''), - $row['Extra'], - ((isset($res_rel[$field_name])) ? $res_rel[$field_name]['foreign_table'] . ' -> ' . $res_rel[$field_name]['foreign_field'] : ''), - ((isset($comments[$field_name])) ? $comments[$field_name] : ''), - ((isset($mime_map) && isset($mime_map[$field_name])) ? str_replace('_', '/', $mime_map[$field_name]['mimetype']) : '') - ); - $links[0] = $pdf->PMA_links['RT'][$table][$field_name]; - if (isset($res_rel[$field_name]['foreign_table']) AND - isset($res_rel[$field_name]['foreign_field']) AND - isset($pdf->PMA_links['doc'][$res_rel[$field_name]['foreign_table']][$res_rel[$field_name]['foreign_field']]) - ) - { - $links[6] = $pdf->PMA_links['doc'][$res_rel[$field_name]['foreign_table']][$res_rel[$field_name]['foreign_field']]; - } else { - unset($links[6]); - } - $pdf->Row($pdf_row, $links); - - /*$pdf->Cell(20, 8, $field_name, 1, 0, 'L', 0, $pdf->PMA_links['RT'][$table][$field_name]); - //echo ' ' . $field_name . ' ' . "\n"; - } - $pdf->Cell(20, 8, $type, 1, 0, 'L'); - $pdf->Cell(20, 8, $attribute, 1, 0, 'L'); - $pdf->Cell(15, 8, , 1, 0, 'L'); - $pdf->Cell(15, 8, ((isset($row['Default'])) ? $row['Default'] : ''),1,0,'L'); - $pdf->Cell(15, 8, $row['Extra'], 1, 0, 'L'); - if ($have_rel) { - if (isset($res_rel[$field_name])) { - $pdf->Cell(30, 8, $res_rel[$field_name]['foreign_table'] . ' -> ' . $res_rel[$field_name]['foreign_field'],1,0,'L'); - } - } - if ($cfgRelation['commwork']) { - if (isset($comments[$field_name])) { - $pdf->Cell(0, 8, $comments[$field_name], 1, 0, 'L'); - } - } */ - } // end while - $pdf->SetFont('', '', 14); - PMA_DBI_free_result($result); - } //end each -} // end function PMA_RT_DOC - -/** - * Main logic - */ -if (!isset($pdf_page_number)) { - $pdf_page_number = 1; -} - -$show_grid = (isset($show_grid) && $show_grid == 'on') ? 1 : 0; -$show_color = (isset($show_color) && $show_color == 'on') ? 1 : 0; -$show_table_dimension = (isset($show_table_dimension) && $show_table_dimension == 'on') ? 1 : 0; -$all_tab_same_wide = (isset($all_tab_same_wide) && $all_tab_same_wide == 'on') ? 1 : 0; -$with_doc = (isset($with_doc) && $with_doc == 'on') ? 1 : 0; -$orientation = (isset($orientation) && $orientation == 'P') ? 'P' : 'L'; -$paper = isset($paper) ? $paper : 'A4'; -$show_keys = (isset($show_keys) && $show_keys == 'on') ? 1 : 0; -PMA_DBI_select_db($db); - -$rt = new PMA_RT($pdf_page_number, $show_table_dimension, $show_color, $show_grid, $all_tab_same_wide, $orientation, $paper, $show_keys); - -?> diff --git a/schema_edit.php b/schema_edit.php new file mode 100644 index 0000000..fb15d00 --- /dev/null +++ b/schema_edit.php @@ -0,0 +1,140 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * + * @version $Id$ + * @package phpMyAdmin + */ + +/** + * Gets some core libraries + */ + +require_once './libraries/common.inc.php'; +require_once './libraries/db_common.inc.php'; +require './libraries/StorageEngine.class.php'; + +$active_page = 'db_operations.php'; +require_once './libraries/db_common.inc.php'; +$url_query .= '&goto=schema_edit.php'; +require_once './libraries/db_info.inc.php'; + +/** + * Includ settings for relation stuff + * get all variables needed for exporting relational schema + * in $cfgRelation + */ +require_once './libraries/relation.lib.php'; +$cfgRelation = PMA_getRelationsParam(); + +/** + * This is to avoid "Command out of sync" errors. Before switching this to + * a value of 0 (for MYSQLI_USE_RESULT), please check the logic + * to free results wherever needed. + */ +$query_default_option = PMA_DBI_QUERY_STORE; + +/** + * Now in ./libraries/relation.lib.php we check for all tables + * that we need, but if we don't find them we are quiet about it + * so people can't work without relational variables. + * This page is absolutely useless if you didn't set up your tables + * correctly, so it is a good place to see which tables we can and + * complain ;-) + */ +if (!$cfgRelation['relwork']) { + echo sprintf(__('<b>%s</b> table not found or not set in %s'), 'relation', 'config.inc.php') . '<br />' . "\n" + . PMA_showDocu('relation') . "\n"; + require_once './libraries/footer.inc.php'; +} + +if (!$cfgRelation['displaywork']) { + echo sprintf(__('<b>%s</b> table not found or not set in %s'), 'table_info', 'config.inc.php') . '<br />' . "\n" + . PMA_showDocu('table_info') . "\n"; + require_once './libraries/footer.inc.php'; +} + +if (!isset($cfgRelation['table_coords'])){ + echo sprintf(__('<b>%s</b> table not found or not set in %s'), 'table_coords', 'config.inc.php') . '<br />' . "\n" + . PMA_showDocu('table_coords') . "\n"; + require_once './libraries/footer.inc.php'; +} +if (!isset($cfgRelation['pdf_pages'])) { + echo sprintf(__('<b>%s</b> table not found or not set in %s'), 'pdf_page', 'config.inc.php') . '<br />' . "\n" + . PMA_showDocu('pdf_pages') . "\n"; + require_once './libraries/footer.inc.php'; +} + +if ($cfgRelation['pdfwork']) { + + /** + * User object created for presenting the HTML options + * so, user can interact with it and perform export of relations schema + */ + + require_once './libraries/schema/User_Schema.class.php'; + $user_schema = new PMA_User_Schema(); + + /** + * This function will process the user defined pages + * and tables which will be exported as Relational schema + * you can set the table positions on the paper via scratchboard + * for table positions, put the x,y co-ordinates + * + * @param string $do It tells what the Schema is supposed to do + * create and select a page, generate schema etc + */ + if(isset($_REQUEST['do'])){ + $user_schema->setAction($_REQUEST['do']); + $user_schema->processUserPreferences(); + } + + /** + * Show some possibility to select a page for the export of relation schema + * Lists all pages created before and can select and edit from them + */ + + $user_schema->selectPage(); + + /** + * Create a new page where relations will be drawn + */ + + $user_schema->createPage($db); + + /** + * After selection of page or creating a page + * It will show you the list of tables + * A dashboard will also be shown where you can position the tables + */ + + $user_schema->showTableDashBoard(); + + if (isset($_REQUEST['do']) + && ($_REQUEST['do'] == 'edcoord' + || ($_REQUEST['do']== 'selectpage' && isset($user_schema->choosenPage) && $user_schema->choosenPage != 0) + || ($_REQUEST['do'] == 'createpage' && isset($user_schema->choosenPage) && $user_schema->choosenPage != 0))) { + + /** + * show Export schema generation options + */ + $user_schema->displaySchemaGenerationOptions(); + + if ((isset($showwysiwyg) && $showwysiwyg == '1')) { + ?> + <script type="text/javascript"> + //<![CDATA[ + ToggleDragDrop('pdflayout'); + //]]> + </script> + <?php + } + } // end if +} // end if ($cfgRelation['pdfwork']) + +/** + * Displays the footer + */ +echo "\n"; +require_once './libraries/footer.inc.php'; +?> diff --git a/schema_export.php b/schema_export.php new file mode 100644 index 0000000..9f74fea --- /dev/null +++ b/schema_export.php @@ -0,0 +1,49 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * + * @version $Id$ + * @package phpMyAdmin + */ + +/** + * Gets some core libraries + */ +require_once './libraries/common.inc.php'; +require './libraries/StorageEngine.class.php'; + +/** + * Include settings for relation stuff + * get all variables needed for exporting relational schema + * in $cfgRelation + */ +require_once './libraries/relation.lib.php'; +$cfgRelation = PMA_getRelationsParam(); + +require_once './libraries/transformations.lib.php'; +require_once './libraries/Index.class.php'; + +/** + * This is to avoid "Command out of sync" errors. Before switching this to + * a value of 0 (for MYSQLI_USE_RESULT), please check the logic + * to free results wherever needed. + */ +$query_default_option = PMA_DBI_QUERY_STORE; + +include_once("./libraries/schema/Export_Relation_Schema.class.php"); + +/** + * get all the export options and verify + * call and include the appropriate Schema Class depending on $export_type + * default is PDF + */ +global $db,$export_type; +$export_type = isset($export_type) ? $export_type : 'pdf'; +PMA_DBI_select_db($db); + +$path = PMA_securePath(ucfirst($export_type)); +if (!file_exists('./libraries/schema/' . $path . '_Relation_Schema.class.php')) { + PMA_Export_Relation_Schema::dieSchema($_POST['chpage'],$export_type,__('File doesn't exist')); +} +include("./libraries/schema/".$path."_Relation_Schema.class.php"); +$obj_schema = eval("new PMA_".$path."_Relation_Schema();"); \ No newline at end of file
hooks/post-receive