Merge remote branch 'adnan/export_branch'
This commit is contained in:
@@ -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="export_relation_schema.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
|
||||
|
||||
/**
|
||||
|
140
export_relation_schema.php
Normal file
140
export_relation_schema.php
Normal file
@@ -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=export_relation_schema.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';
|
||||
?>
|
49
handle_relation_schema.php
Normal file
49
handle_relation_schema.php
Normal file
@@ -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();");
|
@@ -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() == '') {
|
||||
|
@@ -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>
|
||||
|
777
libraries/schema/Dia_Relation_Schema.class.php
Normal file
777
libraries/schema/Dia_Relation_Schema.class.php
Normal file
@@ -0,0 +1,777 @@
|
||||
<?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';
|
||||
}
|
||||
|
||||
$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 * .05).','.($this->y * .05).'"/>
|
||||
</dia:attribute>
|
||||
<dia:attribute name="obj_bb">
|
||||
<dia:rectangle val="'.($this->x * .05).','.($this->y * .05).';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 * .05).','.($this->y * .05).'"/>
|
||||
</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);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
858
libraries/schema/Eps_Relation_Schema.class.php
Normal file
858
libraries/schema/Eps_Relation_Schema.class.php
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
223
libraries/schema/Export_Relation_Schema.class.php
Normal file
223
libraries/schema/Export_Relation_Schema.class.php
Normal file
@@ -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="export_relation_schema.php?' . PMA_generate_common_url($db).'&do=selectpage&chpage='.$pageNumber.'&action_choose=0'
|
||||
. '">' . __('Back') . '</a>';
|
||||
echo "\n";
|
||||
require_once './libraries/footer.inc.php';
|
||||
exit();
|
||||
}
|
||||
}
|
||||
?>
|
1352
libraries/schema/Pdf_Relation_Schema.class.php
Normal file
1352
libraries/schema/Pdf_Relation_Schema.class.php
Normal file
File diff suppressed because it is too large
Load Diff
854
libraries/schema/Svg_Relation_Schema.class.php
Normal file
854
libraries/schema/Svg_Relation_Schema.class.php
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
821
libraries/schema/User_Schema.class.php
Normal file
821
libraries/schema/User_Schema.class.php
Normal file
@@ -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="export_relation_schema.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="export_relation_schema.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="export_relation_schema.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="handle_relation_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 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="export_relation_schema.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="export_relation_schema.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
|
||||
}
|
||||
}
|
||||
?>
|
599
libraries/schema/Visio_Relation_Schema.class.php
Normal file
599
libraries/schema/Visio_Relation_Schema.class.php
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
@@ -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;
|
||||
|
559
pdf_pages.php
559
pdf_pages.php
@@ -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';
|
||||
?>
|
1404
pdf_schema.php
1404
pdf_schema.php
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user