Merge branch 'master' of git://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin

This commit is contained in:
Pootle server 2010-08-23 11:20:44 +02:00
commit 93d18894f1
18 changed files with 5775 additions and 2078 deletions

View File

@ -104,7 +104,11 @@ $Id$
thanks to Isaac Bennetch - ibennetch
- patch #3038312 [export] JSON export,
thanks to Hauke Henningsen - blubberkeks152
- rfe #1494550 [interface] Editor for SET/ENUM fields.
- rfe #2649375 [interface] Simplified interface to backup/restore.
- rfe #2973909 Users preferences
- [relations] Dropped WYSIWYG-PDF configuration variable.
- rfe #806035, #686260 [relations] Export relations to Dia, SVG and others
3.3.6.0 (not yet released)
- bug #3033063 [core] Navi gets wrong db name

View File

@ -2138,32 +2138,6 @@ setfacl -d -m "g:www-data:rwx" tmp
any row counting.
</dd>
<dt id="wysiwyg">
<span id="cfg_WYSIWYG-PDF">$cfg['WYSIWYG-PDF'] </span>boolean</dt>
<dd>Utilizes a WYSIWYG editing control to easily place elements of a
<abbr title="Portable Document Format">PDF</abbr>
page. By clicking on the button 'toggle scratchboard' on the page
where you edit x/y coordinates of those elements you can activate a
scratchboard where all your elements are placed. By clicking on an
element, you can move them around in the pre-defined area and the x/y
coordinates will get updated dynamically. Likewise, when entering a
new position directly into the input field, the new position in the
scratchboard changes after your cursor leaves the input field.<br />
You have to click on the 'OK'-button below the tables to save the new
positions. If you want to place a new element, first add it to the
table of elements and then you can drag the new element around.<br />
By changing the paper size and the orientation you can change the size
of the scratchboard as well. You can do so by just changing the
dropdown field below, and the scratchboard will resize automatically,
without interfering with the current placement of the elements.<br />
If ever an element gets out of range you can either enlarge the paper
size or click on the 'reset' button to place all elements below each
other.<br />
<b>NOTE:</b> You have to use a recent browser like IE6 or Mozilla to
get this control to work. The basic Drag&amp;Drop script functionality
was kindly borrowed from www.youngpup.net and is underlying so
specific license.</dd>
<dt id="cfg_NaturalOrder">$cfg['NaturalOrder'] boolean</dt>
<dd>Sorts database and table names according to natural order (for example,
t1, t2, t10). Currently implemented in the left panel (Light mode)
@ -4362,6 +4336,35 @@ chmod o+rwx tmp
<dd>phpMyAdmin with version</dd>
</dl>
<h4 id="wysiwyg">
<a href="#wysiwyg">6.28 How can I easily edit relational schema for export?</a></h4>
<p>
By clicking on the button 'toggle scratchboard' on the page
where you edit x/y coordinates of those elements you can activate a
scratchboard where all your elements are placed. By clicking on an
element, you can move them around in the pre-defined area and the x/y
coordinates will get updated dynamically. Likewise, when entering a
new position directly into the input field, the new position in the
scratchboard changes after your cursor leaves the input field.
</p>
<p>
You have to click on the 'OK'-button below the tables to save the new
positions. If you want to place a new element, first add it to the
table of elements and then you can drag the new element around.
</p>
<p>
By changing the paper size and the orientation you can change the size
of the scratchboard as well. You can do so by just changing the
dropdown field below, and the scratchboard will resize automatically,
without interfering with the current placement of the elements.
</p>
<p>
If ever an element gets out of range you can either enlarge the paper
size or click on the 'reset' button to place all elements below each
other.
<p>
<h3 id="faqproject">phpMyAdmin project</h3>
<h4 id="faq7_1">
@ -4858,6 +4861,18 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
<li>Replication support</li>
</ul></li>
<li>Muhammad Adnan (Google Summer of Code 2010)
<ul>
<li>Relation schema export to multiple formats</li>
</ul></li>
<li>Lori Lee (Google Summer of Code 2010)
<ul>
<li>User interface improvements</li>
<li>ENUM/SET editor</li>
<li>Simplified interface for export/import</li>
</ul></li>
<li>Barrie Leslie
<ul>
<li>BLOBstreaming support with PBMS PHP extension</li>

View File

@ -520,15 +520,15 @@ if ($cfgRelation['pdfwork'] && $num_tables > 0) { ?>
WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'';
$test_rs = PMA_query_as_controluser($test_query, null, PMA_DBI_QUERY_STORE);
if ($test_rs && PMA_DBI_num_rows($test_rs) > 0) {
include('./libraries/display_pdf_schema.lib.php');
} // end if
echo '<fieldset><a href="pdf_pages.php?' . $url_query . '">';
/*
* Export Relational Schema View
*/
echo '<fieldset><a href="schema_edit.php?' . $url_query . '">';
if ($cfg['PropertiesIconic']) {
echo '<img class="icon" src="' . $pmaThemeImage . 'b_edit.png"'
.' alt="" width="16" height="16" />';
}
echo __('Edit PDF Pages') . '</a></fieldset>';
echo __('Export Relational Schema View') . '</a></fieldset>';
} // end if
/**

View File

@ -1421,7 +1421,7 @@ function getElement(e,f){
}
/**
* Refresh the WYSIWYG-PDF scratchboard after changes have been made
* Refresh the WYSIWYG scratchboard after changes have been made
*/
function refreshDragOption(e) {
var elm = $('#' + e);
@ -1431,13 +1431,16 @@ function refreshDragOption(e) {
}
/**
* Refresh/resize the WYSIWYG-PDF scratchboard
* Refresh/resize the WYSIWYG scratchboard
*/
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';
@ -1450,7 +1453,7 @@ function refreshLayout() {
}
/**
* Show/hide the WYSIWYG-PDF scratchboard
* Show/hide the WYSIWYG scratchboard
*/
function ToggleDragDrop(e) {
var elm = $('#' + e);
@ -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() == '') {

View File

@ -2332,14 +2332,6 @@ $cfg['MaxExactCount'] = 20000;
*/
$cfg['MaxExactCountViews'] = 0;
/**
* Utilize DHTML/JS capabilities to allow WYSIWYG editing of
* the PDF page editor. Requires an IE6/Gecko based browser.
*
* @global boolean $cfg['WYSIWYG-PDF']
*/
$cfg['WYSIWYG-PDF'] = true;
/**
* Sort table and database in natural order
*

View File

@ -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>

View File

@ -0,0 +1,779 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
*
* @version $Id$
* @package phpMyAdmin
*/
include_once("Export_Relation_Schema.class.php");
/**
* This Class inherits the XMLwriter class and
* helps in developing structure of DIA Schema Export
*
* @name PMA_DIA
* @author Muhammad Adnan <hiddenpearls@gmail.com>
* @copyright
* @license
* @access public
* @see http://php.net/manual/en/book.xmlwriter.php
*/
class PMA_DIA extends XMLWriter
{
public $title;
public $author;
public $font;
public $fontSize;
/**
* The "PMA_DIA" constructor
*
* Upon instantiation This starts writing the Dia XML document
*
* @return void
* @see XMLWriter::openMemory(),XMLWriter::setIndent(),XMLWriter::startDocument()
*/
function __construct()
{
$this->openMemory();
/*
* Set indenting using three spaces,
* so output is formatted
*/
$this->setIndent(TRUE);
$this->setIndentString(' ');
/*
* Create the XML document
*/
$this->startDocument('1.0','UTF-8');
}
/**
* Starts Dia Document
*
* dia document starts by first initializing dia:diagram tag
* then dia:diagramdata contains all the attributes that needed
* to define the document, then finally a Layer starts which
* holds all the objects.
*
* @param string paper The size of the paper/document
* @param float topMargin top margin of the paper/document in cm
* @param float bottomMargin bottom margin of the paper/document in cm
* @param float leftMargin left margin of the paper/document in cm
* @param float rightMargin right margin of the paper/document in cm
* @param string portrait document will be portrait or landscape
* @return void
* @access public
* @see XMLWriter::startElement(),XMLWriter::writeAttribute(),XMLWriter::writeRaw()
*/
function startDiaDoc($paper,$topMargin,$bottomMargin,$leftMargin,$rightMargin,$portrait)
{
if($portrait == 'P'){
$isPortrait='true';
}else{
$isPortrait='false';
}
$this->startElement('dia:diagram');
$this->writeAttribute('xmlns:dia', 'http://www.lysator.liu.se/~alla/dia/');
$this->startElement('dia:diagramdata');
$this->writeRaw (
'<dia:attribute name="background">
<dia:color val="#ffffff"/>
</dia:attribute>
<dia:attribute name="pagebreak">
<dia:color val="#000099"/>
</dia:attribute>
<dia:attribute name="paper">
<dia:composite type="paper">
<dia:attribute name="name">
<dia:string>#'.$paper.'#</dia:string>
</dia:attribute>
<dia:attribute name="tmargin">
<dia:real val="'.$topMargin.'"/>
</dia:attribute>
<dia:attribute name="bmargin">
<dia:real val="'.$bottomMargin.'"/>
</dia:attribute>
<dia:attribute name="lmargin">
<dia:real val="'.$leftMargin.'"/>
</dia:attribute>
<dia:attribute name="rmargin">
<dia:real val="'.$rightMargin.'"/>
</dia:attribute>
<dia:attribute name="is_portrait">
<dia:boolean val="'.$isPortrait.'"/>
</dia:attribute>
<dia:attribute name="scaling">
<dia:real val="1"/>
</dia:attribute>
<dia:attribute name="fitto">
<dia:boolean val="false"/>
</dia:attribute>
</dia:composite>
</dia:attribute>
<dia:attribute name="grid">
<dia:composite type="grid">
<dia:attribute name="width_x">
<dia:real val="1"/>
</dia:attribute>
<dia:attribute name="width_y">
<dia:real val="1"/>
</dia:attribute>
<dia:attribute name="visible_x">
<dia:int val="1"/>
</dia:attribute>
<dia:attribute name="visible_y">
<dia:int val="1"/>
</dia:attribute>
<dia:composite type="color"/>
</dia:composite>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#d8e5e5"/>
</dia:attribute>
<dia:attribute name="guides">
<dia:composite type="guides">
<dia:attribute name="hguides"/>
<dia:attribute name="vguides"/>
</dia:composite>
</dia:attribute>');
$this->endElement();
$this->startElement('dia:layer');
$this->writeAttribute('name', 'Background');
$this->writeAttribute('visible', 'true');
$this->writeAttribute('active', 'true');
}
/**
* Ends Dia Document
*
* @return void
* @access public
* @see XMLWriter::endElement(),XMLWriter::endDocument()
*/
function endDiaDoc()
{
$this->endElement();
$this->endDocument();
}
/**
* Output Dia Document for download
*
* @param string fileName name of the dia document
* @return void
* @access public
* @see XMLWriter::flush()
*/
function showOutput($fileName)
{
if(ob_get_clean()){
ob_end_clean();
}
header('Content-type: application/x-dia-diagram');
header('Content-Disposition: attachment; filename="'.$fileName.'.dia"');
$output = $this->flush();
print $output;
}
}
/**
* Table preferences/statistics
*
* This class preserves the table co-ordinates,fields
* and helps in drawing/generating the Tables in dia XML document.
*
* @name Table_Stats
* @author Muhammad Adnan <hiddenpearls@gmail.com>
* @copyright
* @license
* @see PMA_DIA
*/
class Table_Stats
{
/**
* Defines properties
*/
public $tableName;
public $fields = array();
public $x, $y;
public $primary = array();
public $tableId;
public $tableColor;
/**
* The "Table_Stats" constructor
*
* @param string table_name The table name
* @param integer pageNumber The current page number (from the
* $cfg['Servers'][$i]['table_coords'] table)
* @param boolean showKeys Whether to display ONLY keys or not
* @return void
* @global object The current dia document
* @global array The relations settings
* @global string The current db name
* @see PMA_DIA
*/
function __construct($tableName, $pageNumber, $showKeys = false)
{
global $dia, $cfgRelation, $db;
$this->tableName = $tableName;
$sql = 'DESCRIBE ' . PMA_backquote($tableName);
$result = PMA_DBI_try_query($sql, null, PMA_DBI_QUERY_STORE);
if (!$result || !PMA_DBI_num_rows($result)) {
$dia->dieSchema($pageNumber,"DIA",sprintf(__('The %s table doesn\'t exist!'), $tableName));
}
/*
* load fields
* check to see if it will load all fields or only the foreign keys
*/
if ($showKeys) {
$indexes = PMA_Index::getFromTable($this->tableName, $db);
$all_columns = array();
foreach ($indexes as $index) {
$all_columns = array_merge($all_columns, array_flip(array_keys($index->getColumns())));
}
$this->fields = array_keys($all_columns);
} else {
while ($row = PMA_DBI_fetch_row($result)) {
$this->fields[] = $row[0];
}
}
$sql = 'SELECT x, y FROM '
. PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords'])
. ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\''
. ' AND table_name = \'' . PMA_sqlAddslashes($tableName) . '\''
. ' AND pdf_page_number = ' . $pageNumber;
$result = PMA_query_as_controluser($sql, false, PMA_DBI_QUERY_STORE);
if (!$result || !PMA_DBI_num_rows($result)) {
$dia->dieSchema($pageNumber,"DIA",sprintf(__('Please configure the coordinates for table %s'), $tableName));
}
list($this->x, $this->y) = PMA_DBI_fetch_row($result);
$this->x = (double) $this->x;
$this->y = (double) $this->y;
/*
* displayfield
*/
$this->displayfield = PMA_getDisplayField($db, $tableName);
/*
* index
*/
$result = PMA_DBI_query('SHOW INDEX FROM ' . PMA_backquote($tableName) . ';', null, PMA_DBI_QUERY_STORE);
if (PMA_DBI_num_rows($result) > 0) {
while ($row = PMA_DBI_fetch_assoc($result)) {
if ($row['Key_name'] == 'PRIMARY') {
$this->primary[] = $row['Column_name'];
}
}
}
/**
* Every object in Dia document needs an ID to identify
* so, we used a static variable to keep the things unique
*/
PMA_Dia_Relation_Schema::$objectId += 1;
$this->tableId = PMA_Dia_Relation_Schema::$objectId;
}
/**
* Do draw the table
*
* Tables are generated using object type Database - Table
* primary fields are underlined in tables. Dia object
* is used to generate the XML of Dia Document. Database Table
* Object and their attributes are involved in the combination
* of displaing Database - Table on Dia Document.
* @param boolean changeColor Whether to show color for tables text or not
if changeColor is true then an array of $listOfColors
will be used to choose the random colors for tables text
we can change/add more colors to this array
@return void
* @global object The current Dia document
* @access public
* @see PMA_DIA
*/
public function tableDraw($changeColor)
{
global $dia;
if ($changeColor) {
$listOfColors = array(
'FF0000',
'000099',
'00FF00'
);
shuffle($listOfColors);
$this->tableColor = '#'.$listOfColors[0].'';
} else {
$this->tableColor = '#000000';
}
$factor = 0.1;
$dia->startElement('dia:object');
$dia->writeAttribute('type', 'Database - Table');
$dia->writeAttribute('version', '0');
$dia->writeAttribute('id', ''.$this->tableId.'');
$dia->writeRaw(
'<dia:attribute name="obj_pos">
<dia:point val="'.($this->x * $factor).','.($this->y * $factor).'"/>
</dia:attribute>
<dia:attribute name="obj_bb">
<dia:rectangle val="'.($this->x * $factor).','.($this->y * $factor).';9.97,9.2"/>
</dia:attribute>
<dia:attribute name="meta">
<dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="'.($this->x * $factor).','.($this->y * $factor).'"/>
</dia:attribute>
<dia:attribute name="elem_width">
<dia:real val="5.9199999999999999"/>
</dia:attribute>
<dia:attribute name="elem_height">
<dia:real val="3.5"/>
</dia:attribute>
<dia:attribute name="text_colour">
<dia:color val="'.$this->tableColor.'"/>
</dia:attribute>
<dia:attribute name="line_colour">
<dia:color val="#000000"/>
</dia:attribute>
<dia:attribute name="fill_colour">
<dia:color val="#ffffff"/>
</dia:attribute>
<dia:attribute name="line_width">
<dia:real val="0.10000000000000001"/>
</dia:attribute>
<dia:attribute name="name">
<dia:string>#'.$this->tableName.'#</dia:string>
</dia:attribute>
<dia:attribute name="comment">
<dia:string>##</dia:string>
</dia:attribute>
<dia:attribute name="visible_comment">
<dia:boolean val="false"/>
</dia:attribute>
<dia:attribute name="tagging_comment">
<dia:boolean val="false"/>
</dia:attribute>
<dia:attribute name="underline_primary_key">
<dia:boolean val="true"/>
</dia:attribute>
<dia:attribute name="bold_primary_keys">
<dia:boolean val="true"/>
</dia:attribute>
<dia:attribute name="normal_font">
<dia:font family="monospace" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="name_font">
<dia:font family="sans" style="80" name="Helvetica-Bold"/>
</dia:attribute>
<dia:attribute name="comment_font">
<dia:font family="sans" style="0" name="Helvetica"/>
</dia:attribute>
<dia:attribute name="normal_font_height">
<dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="name_font_height">
<dia:real val="0.69999999999999996"/>
</dia:attribute>
<dia:attribute name="comment_font_height">
<dia:real val="0.69999999999999996"/>
</dia:attribute>'
);
$dia->startElement('dia:attribute');
$dia->writeAttribute('name', 'attributes');
foreach ($this->fields as $field) {
$dia->writeRaw(
'<dia:composite type="table_attribute">
<dia:attribute name="name">
<dia:string>#'.$field.'#</dia:string>
</dia:attribute>
<dia:attribute name="type">
<dia:string>##</dia:string>
</dia:attribute>
<dia:attribute name="comment">
<dia:string>##</dia:string>
</dia:attribute>'
);
unset($pm);
$pm = 'false';
if (in_array($field, $this->primary)) {
$pm = 'true';
}
if ($field == $this->displayfield) {
$pm = 'false';
}
$dia->writeRaw(
'<dia:attribute name="primary_key">
<dia:boolean val="'.$pm.'"/>
</dia:attribute>
<dia:attribute name="nullable">
<dia:boolean val="false"/>
</dia:attribute>
<dia:attribute name="unique">
<dia:boolean val="'.$pm.'"/>
</dia:attribute>
</dia:composite>'
);
}
$dia->endElement();
$dia->endElement();
}
}
/**
* Relation preferences/statistics
*
* This class fetches the table master and foreign fields positions
* and helps in generating the Table references and then connects
* master table's master field to foreign table's foreign key
* in dia XML document.
*
* @name Relation_Stats
* @author Muhammad Adnan <hiddenpearls@gmail.com>
* @copyright
* @license
* @see PMA_DIA
*/
class Relation_Stats
{
/**
* Defines properties
*/
public $srcConnPointsRight;
public $srcConnPointsLeft;
public $destConnPointsRight;
public $destConnPointsLeft;
public $masterTableId;
public $foreignTableId;
public $masterTablePos;
public $foreignTablePos;
public $referenceColor;
/**
* The "Relation_Stats" constructor
*
* @param string master_table The master table name
* @param string master_field The relation field in the master table
* @param string foreign_table The foreign table name
* @param string foreigh_field The relation field in the foreign table
* @return void
* @see Relation_Stats::_getXy
*/
function __construct($master_table, $master_field, $foreign_table, $foreign_field)
{
$src_pos = $this->_getXy($master_table, $master_field);
$dest_pos = $this->_getXy($foreign_table, $foreign_field);
$this->srcConnPointsLeft = $src_pos[0];
$this->srcConnPointsRight = $src_pos[1];
$this->destConnPointsLeft = $dest_pos[0];
$this->destConnPointsRight = $dest_pos[1];
$this->masterTablePos = $src_pos[2];
$this->foreignTablePos = $dest_pos[2];
$this->masterTableId = $master_table->tableId;
$this->foreignTableId = $foreign_table->tableId;
}
/**
* Each Table object have connection points
* which is used to connect to other objects in Dia
* we detect the position of key in fields and
* then determines its left and right connection
* points.
*
* @param string table The current table name
* @param string column The relation column name
* @return array Table right,left connection points and key position
* @access private
*/
private function _getXy($table, $column)
{
$pos = array_search($column, $table->fields);
// left, right, position
$value = 12;
if($pos != 0)
{
return array($pos + $value + $pos, $pos + $value + $pos + 1, $pos);
}
return array($pos + $value , $pos + $value + 1, $pos);
}
/**
* Draws relation references
*
* connects master table's master field to foreign table's
* forein field using Dia object type Database - Reference
* Dia object is used to generate the XML of Dia Document.
* Database reference Object and their attributes are involved
* in the combination of displaing Database - reference on Dia Document.
*
* @param boolean changeColor Whether to use one color per relation or not
if changeColor is true then an array of $listOfColors
will be used to choose the random colors for references
lines. we can change/add more colors to this array
* @return void
* @global object The current Dia document
* @access public
* @see PMA_PDF
*/
public function relationDraw($changeColor)
{
global $dia;
PMA_Dia_Relation_Schema::$objectId += 1;
/*
* if source connection points and destination connection
* points are same then return it false and don't draw that
* relation
*/
if ( $this->srcConnPointsRight == $this->destConnPointsRight ){
if ( $this->srcConnPointsLeft == $this->destConnPointsLeft ){
return false;
}
}
if ($changeColor) {
$listOfColors = array(
'FF0000',
'000099',
'00FF00'
);
shuffle($listOfColors);
$this->referenceColor = '#'.$listOfColors[0].'';
} else {
$this->referenceColor = '#000000';
}
$dia->writeRaw(
'<dia:object type="Database - Reference" version="0" id="'.PMA_Dia_Relation_Schema::$objectId.'">
<dia:attribute name="obj_pos">
<dia:point val="3.27,18.9198"/>
</dia:attribute>
<dia:attribute name="obj_bb">
<dia:rectangle val="2.27,8.7175;17.7679,18.9198"/>
</dia:attribute>
<dia:attribute name="meta">
<dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="orth_points">
<dia:point val="3.27,18.9198"/>
<dia:point val="2.27,18.9198"/>
<dia:point val="2.27,14.1286"/>
<dia:point val="17.7679,14.1286"/>
<dia:point val="17.7679,9.3375"/>
<dia:point val="16.7679,9.3375"/>
</dia:attribute>
<dia:attribute name="orth_orient">
<dia:enum val="0"/>
<dia:enum val="1"/>
<dia:enum val="0"/>
<dia:enum val="1"/>
<dia:enum val="0"/>
</dia:attribute>
<dia:attribute name="orth_autoroute">
<dia:boolean val="true"/>
</dia:attribute>
<dia:attribute name="text_colour">
<dia:color val="#000000"/>
</dia:attribute>
<dia:attribute name="line_colour">
<dia:color val="'.$this->referenceColor.'"/>
</dia:attribute>
<dia:attribute name="line_width">
<dia:real val="0.10000000000000001"/>
</dia:attribute>
<dia:attribute name="line_style">
<dia:enum val="0"/>
<dia:real val="1"/>
</dia:attribute>
<dia:attribute name="corner_radius">
<dia:real val="0"/>
</dia:attribute>
<dia:attribute name="end_arrow">
<dia:enum val="22"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
<dia:real val="0.5"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
<dia:real val="0.5"/>
</dia:attribute>
<dia:attribute name="start_point_desc">
<dia:string>#1#</dia:string>
</dia:attribute>
<dia:attribute name="end_point_desc">
<dia:string>#n#</dia:string>
</dia:attribute>
<dia:attribute name="normal_font">
<dia:font family="monospace" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="normal_font_height">
<dia:real val="0.59999999999999998"/>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="'.$this->masterTableId.'" connection="'.$this->srcConnPointsRight.'"/>
<dia:connection handle="1" to="'.$this->foreignTableId.'" connection="'.$this->destConnPointsRight.'"/>
</dia:connections>
</dia:object>'
);
}
}
/**
* Dia Relation Schema Class
*
* Purpose of this class is to generate the Dia XML Document
* which is used for representing the database diagrams in Dia IDE
* This class uses Database Table and Reference Objects of Dia and with
* the combination of these objects actually helps in preparing Dia XML.
*
* Dia XML is generated by using XMLWriter php extension and this class
* inherits Export_Relation_Schema class has common functionality added
* to this class
*
* @name Dia_Relation_Schema
* @author Muhammad Adnan <hiddenpearls@gmail.com>
* @copyright
* @license
*/
class PMA_Dia_Relation_Schema extends PMA_Export_Relation_Schema
{
/**
* Defines properties
*/
private $_tables = array();
private $_relations = array();
private $_topMargin = 2.8222000598907471;
private $_bottomMargin = 2.8222000598907471;
private $_leftMargin = 2.8222000598907471;
private $_rightMargin = 2.8222000598907471;
public static $objectId = 0;
/**
* The "PMA_Dia_Relation_Schema" constructor
*
* Upon instantiation This outputs the Dia XML document
* that user can download
*
* @return void
* @see PMA_DIA,Table_Stats,Relation_Stats
*/
function __construct()
{
global $dia,$db;
$this->setPageNumber($_POST['pdf_page_number']);
$this->setShowGrid(isset($_POST['show_grid']));
$this->setShowColor($_POST['show_color']);
$this->setShowKeys(isset($_POST['show_keys']));
$this->setOrientation(isset($_POST['orientation']));
$this->setPaper($_POST['paper']);
$this->setExportType($_POST['export_type']);
$dia = new PMA_DIA();
$dia->startDiaDoc($this->paper,$this->_topMargin,$this->_bottomMargin,$this->_leftMargin,$this->_rightMargin,$this->orientation);
$alltables = $this->getAllTables($db,$this->pageNumber);
foreach ($alltables as $table) {
if (!isset($this->tables[$table])) {
$this->tables[$table] = new Table_Stats($table, $this->pageNumber, $this->showKeys);
}
}
$seen_a_relation = false;
foreach ($alltables as $one_table) {
$exist_rel = PMA_getForeigners($db, $one_table, '', 'both');
if ($exist_rel) {
$seen_a_relation = true;
foreach ($exist_rel as $master_field => $rel) {
/* put the foreign table on the schema only if selected
* by the user
* (do not use array_search() because we would have to
* to do a === FALSE and this is not PHP3 compatible)
*/
if (in_array($rel['foreign_table'], $alltables)) {
$this->_addRelation($one_table, $master_field, $rel['foreign_table'], $rel['foreign_field'],$this->showKeys);
}
}
}
}
$this->_drawTables($this->showColor);
if ($seen_a_relation) {
$this->_drawRelations($this->showColor);
}
$dia->endDiaDoc();
$dia->showOutput($db.'-'.$this->pageNumber);
exit();
}
/**
* Defines relation objects
*
* @param string masterTable The master table name
* @param string masterField The relation field in the master table
* @param string foreignTable The foreign table name
* @param string foreignField The relation field in the foreign table
* @return void
* @access private
* @see Table_Stats::__construct(),Relation_Stats::__construct()
*/
private function _addRelation($masterTable, $masterField, $foreignTable, $foreignField, $showKeys)
{
if (!isset($this->tables[$masterTable])) {
$this->tables[$masterTable] = new Table_Stats($masterTable, $this->pageNumber, $showKeys);
}
if (!isset($this->tables[$foreignTable])) {
$this->tables[$foreignTable] = new Table_Stats($foreignTable, $this->pageNumber, $showKeys);
}
$this->_relations[] = new Relation_Stats($this->tables[$masterTable], $masterField, $this->tables[$foreignTable], $foreignField);
}
/**
* Draws relation references
*
* connects master table's master field to
* foreign table's forein field using Dia object
* type Database - Reference
*
* @param boolean changeColor Whether to use one color per relation or not
* @return void
* @access private
* @see Relation_Stats::relationDraw()
*/
private function _drawRelations($changeColor)
{
foreach ($this->_relations as $relation) {
$relation->relationDraw($changeColor);
}
}
/**
* Draws tables
*
* Tables are generated using Dia object type Database - Table
* primary fields are underlined and bold in tables
*
* @param boolean changeColor Whether to show color for tables text or not
* @return void
* @access private
* @see Table_Stats::tableDraw()
*/
private function _drawTables($changeColor)
{
foreach ($this->tables as $table) {
$table->tableDraw($changeColor);
}
}
}
?>

View 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);
}
}
}
?>

View 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="schema_edit.php?' . PMA_generate_common_url($db).'&do=selectpage&chpage='.$pageNumber.'&action_choose=0'
. '">' . __('Back') . '</a>';
echo "\n";
require_once './libraries/footer.inc.php';
exit();
}
}
?>

File diff suppressed because it is too large Load Diff

View 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);
}
}
}
?>

View File

@ -0,0 +1,819 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
*
* @version $Id$
* @package phpMyAdmin
*/
/**
* This Class interacts with the user to gather the information
* about their tables for which they want to export the relational schema
* export options are shown to user from they can choose
*
* @name User_Schema
* @author Muhammad Adnan <hiddenpearls@gmail.com>
* @copyright
* @license
*/
class PMA_User_Schema
{
public $choosenPage;
public $autoLayoutForeign;
public $autoLayoutInternal;
public $pageNumber;
public $c_table_rows;
public $action;
public function setAction($value)
{
$this->action = $value;
}
/**
* This function will process the user defined pages
* and tables which will be exported as Relational schema
* you can set the table positions on the paper via scratchboard
* for table positions, put the x,y co-ordinates
*
* @param string $this->action It tells what the Schema is supposed to do
* create and select a page, generate schema etc
* @access public
*/
public function processUserPreferences()
{
global $action_choose,$db,$cfgRelation,$cfg,$query_default_option;
if (isset($this->action)) {
switch ($this->action) {
case 'selectpage':
$this->choosenPage = $_REQUEST['chpage'];
if ($action_choose=="1") {
$this->deleteCoordinates($db, $cfgRelation, $this->choosenPage, $query_default_option);
$this->deletePages($db, $cfgRelation, $this->choosenPage, $query_default_option);
$this->choosenPage = 0;
}
break;
case 'createpage':
$this->pageNumber = PMA_REL_create_page($_POST['newpage'], $cfgRelation, $db, $query_default_option);
$this->autoLayoutForeign = isset($_POST['auto_layout_foreign']) ? "1":NULL;
$this->autoLayoutInternal = isset($_POST['auto_layout_internal']) ? "1":NULL;
$this->processRelations($db, $this->pageNumber,$cfgRelation,$query_default_option);
break;
case 'edcoord':
$this->choosenPage = $_POST['chpage'];
$this->c_table_rows = $_POST['c_table_rows'];
$this->_editCoordinates($db, $cfgRelation,$query_default_option);
break;
case 'deleteCrap':
$this->_deleteTableRows($delrow,$cfgRelation,$db,$this->choosenPage);
break;
case 'process_export':
$this->_processExportSchema();
break;
} // end switch
} // end if (isset($do))
}
/**
* shows/displays the HTML FORM to create the page
*
* @param string db name of the selected database
* @return void
* @access public
*/
public function createPage($db)
{
?>
<form method="post" action="schema_edit.php" name="frm_create_page">
<fieldset>
<legend>
<?php echo __('Create a page') . "\n"; ?>
</legend>
<?php echo PMA_generate_common_hidden_inputs($db); ?>
<input type="hidden" name="do" value="createpage" />
<table>
<tr>
<td><label for="id_newpage"><?php echo __('Page name'); ?></label></td>
<td><input type="text" name="newpage" id="id_newpage" size="20" maxlength="50" /></td>
</tr>
<tr>
<td><?php echo __('Automatic layout based on'); ?></td>
<td>
<input type="checkbox" name="auto_layout_internal" id="id_auto_layout_internal" /><label for="id_auto_layout_internal">
<?php echo __('Internal relations'); ?></label><br />
<?php
/*
* Check to see whether INNODB and PBXT storage engines are Available in MYSQL PACKAGE
* If available, then provide AutoLayout for Foreign Keys in Schema View
*/
if (PMA_StorageEngine::isValid('InnoDB') || PMA_StorageEngine::isValid('PBXT')) {
?>
<input type="checkbox" name="auto_layout_foreign" id="id_auto_layout_foreign" /><label for="id_auto_layout_foreign">
<?php echo __('FOREIGN KEY'); ?></label><br />
<?php
}
?>
</td></tr>
</table>
</fieldset>
<fieldset class="tblFooters">
<input type="submit" value="<?php echo __('Go'); ?>" />
</fieldset>
</form>
<?php
}
/**
* shows/displays the created page names in a drop down list
* User can select any page number and edit it using dashboard etc
*
* @return void
* @access public
*/
public function selectPage()
{
global $db,$table,$query_default_option,$cfgRelation;
$page_query = 'SELECT * FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['pdf_pages'])
. ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'';
$page_rs = PMA_query_as_controluser($page_query, FALSE, $query_default_option);
if ($page_rs && PMA_DBI_num_rows($page_rs) > 0) {
?>
<form method="get" action="schema_edit.php" name="frm_select_page">
<fieldset>
<legend>
<?php echo __('Please choose a page to edit') . "\n"; ?>
</legend>
<?php echo PMA_generate_common_hidden_inputs($db, $table); ?>
<input type="hidden" name="do" value="selectpage" />
<select name="chpage" id="chpage" onchange="this.form.submit()">
<option value="0"><?php echo __('Select page'); ?></option>
<?php
while ($curr_page = PMA_DBI_fetch_assoc($page_rs)) {
echo "\n" . ' '
. '<option value="' . $curr_page['page_nr'] . '"';
if (isset($this->choosenPage) && $this->choosenPage == $curr_page['page_nr']) {
echo ' selected="selected"';
}
echo '>' . $curr_page['page_nr'] . ': ' . htmlspecialchars($curr_page['page_descr']) . '</option>';
} // end while
echo "\n";
?>
</select>
<?php
$choices = array(
'0' => __('Edit'),
'1' => __('Delete')
);
PMA_display_html_radio('action_choose', $choices, '0', false);
unset($choices);
?>
</fieldset>
<fieldset class="tblFooters">
<input type="submit" value="<?php echo __('Go'); ?>" /><br />
</fieldset>
</form>
<?php
} // end IF
echo "\n";
} // end function
/**
* A dashboard is displayed to AutoLayout the position of tables
* users can drag n drop the tables and change their positions
*
* @return void
* @access public
*/
public function showTableDashBoard()
{
global $db,$cfgRelation,$table,$cfg,$with_field_names,$query_default_option;
/*
* We will need an array of all tables in this db
*/
$selectboxall = array('--');
$alltab_rs = PMA_DBI_query('SHOW TABLES FROM ' . PMA_backquote($db) . ';', null, PMA_DBI_QUERY_STORE);
while ($val = @PMA_DBI_fetch_row($alltab_rs)) {
$selectboxall[] = $val[0];
}
/*
* Now if we already have chosen a page number then we should
* show the tables involved
*/
if (isset($this->choosenPage) && $this->choosenPage > 0) {
echo "\n";
?>
<h2><?php echo __('Select Tables') ;?></h2>
<?php
$page_query = 'SELECT * FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords'])
. ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\''
. ' AND pdf_page_number = \'' . PMA_sqlAddslashes($this->choosenPage) . '\'';
$page_rs = PMA_query_as_controluser($page_query, FALSE, $query_default_option);
$array_sh_page = array();
$draginit = '';
$reset_draginit = '';
$i = 0;
while ($temp_sh_page = @PMA_DBI_fetch_assoc($page_rs)) {
$array_sh_page[] = $temp_sh_page;
}
/*
* Display WYSIWYG parts
*/
if (!isset($_POST['with_field_names']) && !isset($_POST['showwysiwyg'])) {
$with_field_names = TRUE;
}
$this->_displayScratchboardTables($array_sh_page,$draginit,$reset_draginit);
?>
<form method="post" action="schema_edit.php" name="edcoord">
<?php echo PMA_generate_common_hidden_inputs($db, $table); ?>
<input type="hidden" name="chpage" value="<?php echo htmlspecialchars($this->choosenPage); ?>" />
<input type="hidden" name="do" value="edcoord" />
<table border="0">
<tr>
<th><?php echo __('Table'); ?></th>
<th><?php echo __('Delete'); ?></th>
<th>X</th>
<th>Y</th>
</tr>
<?php
if (isset($ctable)) {
unset($ctable);
}
$i = 0;
$odd_row = true;
foreach ($array_sh_page as $dummy_sh_page => $sh_page) {
$_mtab = $sh_page['table_name'];
$tabExist[$_mtab] = FALSE;
echo "\n" . ' <tr class="';
if ($odd_row) {
echo 'odd';
} else {
echo 'even';
}
echo '">';
$odd_row != $odd_row;
echo "\n" . ' <td>'
. "\n" . ' <select name="c_table_' . $i . '[name]">';
foreach ($selectboxall as $key => $value) {
echo "\n" . ' <option value="' . htmlspecialchars($value) . '"';
if ($value == $sh_page['table_name']) {
echo ' selected="selected"';
$tabExist[$_mtab] = TRUE;
}
echo '>' . htmlspecialchars($value) . '</option>';
}
echo "\n" . ' </select>'
. "\n" . ' </td>';
echo "\n" . ' <td>'
. "\n" . ' <input type="checkbox" name="c_table_' . $i . '[delete]" value="y" />' . __('Delete');
echo "\n" . ' </td>';
echo "\n" . ' <td>'
. "\n" . ' <input type="text" 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" 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 "\n" . ' <input type="hidden" id="showwysiwyg" name="showwysiwyg" value="' . ((isset($showwysiwyg) && $showwysiwyg == '1') ? '1' : '0') . '" />';
echo "\n" . ' <input type="checkbox" name="with_field_names" ' . (isset($with_field_names) ? 'checked="checked"' : ''). ' />' . __('Column names') . '<br />';
echo "\n" . ' <input type="submit" value="' . __('Save') . '" />';
echo "\n" . '</form>' . "\n\n";
} // end if
$this->_deleteTables($db, $this->choosenPage, isset($tabExist));
}
/**
* show Export relational schema generation options
* user can select export type of his own choice
* and the attributes related to it
*
* @return void
* @access public
*/
public function displaySchemaGenerationOptions()
{
global $cfg,$pmaThemeImage,$db,$test_rs,$chpage;
?>
<form method="post" action="schema_export.php">
<fieldset>
<legend>
<?php
echo PMA_generate_common_hidden_inputs($db);
if ($cfg['PropertiesIconic']) {
echo '<img class="icon" src="' . $pmaThemeImage . 'b_view.png"'
.' alt="" width="16" height="16" />';
}
echo __('Display relational schema');
?>:
</legend>
<select name="export_type" id="export_type">
<option value="pdf" selected="selected"><?php echo __('PDF');?></option>
<option value="svg"><?php echo __('SVG');?></option>
<option value="dia"><?php echo __('DIA');?></option>
<option value="visio"><?php echo __('VISIO');?></option>
<option value="eps"><?php echo __('EPS');?></option>
</select>
<label><?php echo __('Select Export Relational Type');?></label><br />
<?php
if (isset($test_rs)) {
?>
<label for="pdf_page_number_opt"><?php echo __('Page number:'); ?></label>
<select name="pdf_page_number" id="pdf_page_number_opt">
<?php
while ($pages = @PMA_DBI_fetch_assoc($test_rs)) {
echo ' <option value="' . $pages['page_nr'] . '">'
. $pages['page_nr'] . ': ' . htmlspecialchars($pages['page_descr']) . '</option>' . "\n";
} // end while
PMA_DBI_free_result($test_rs);
unset($test_rs);
?>
</select><br />
<?php } else { ?>
<input type="hidden" name="pdf_page_number" value="<?php echo htmlspecialchars($this->choosenPage); ?>" />
<?php } ?>
<input type="hidden" name="do" value="process_export" />
<input type="hidden" name="chpage" value="<?php echo $chpage; ?>" />
<input type="checkbox" name="show_grid" id="show_grid_opt" />
<label for="show_grid_opt"><?php echo __('Show grid'); ?></label><br />
<input type="checkbox" name="show_color" id="show_color_opt" checked="checked" />
<label for="show_color_opt"><?php echo __('Show color'); ?></label><br />
<input type="checkbox" name="show_table_dimension" id="show_table_dim_opt" />
<label for="show_table_dim_opt"><?php echo __('Show dimension of tables'); ?>
</label><br />
<input type="checkbox" name="all_table_same_wide" id="all_table_same_wide" />
<label for="all_table_same_wide"><?php echo __('Display all tables with the same width'); ?>
</label><br />
<input type="checkbox" name="with_doc" id="with_doc" checked="checked" />
<label for="with_doc"><?php echo __('Data Dictionary'); ?></label><br />
<input type="checkbox" name="show_keys" id="show_keys" />
<label for="show_keys"><?php echo __('Only show keys'); ?></label><br />
<select name="orientation" id="orientation_opt">
<option value="L"><?php echo __('Landscape');?></option>
<option value="P"><?php echo __('Portrait');?></option>
</select>
<label for="orientation_opt"><?php echo __('Orientation'); ?></label>
<br />
<select name="paper" id="paper_opt">
<?php
foreach ($cfg['PDFPageSizes'] as $key => $val) {
echo '<option value="' . $val . '"';
if ($val == $cfg['PDFDefaultPageSize']) {
echo ' selected="selected"';
}
echo ' >' . $val . '</option>' . "\n";
}
?>
</select>
<label for="paper_opt"><?php echo __('Paper size'); ?></label>
</fieldset>
<fieldset class="tblFooters">
<input type="submit" value="<?php echo __('Go'); ?>" />
</fieldset>
</form>
<?php
}
/**
* Check if there are tables that need to be deleted in dashboard,
* if there are, ask the user for allowance
*
* @param string db name of database selected
* @param integer chpage selected page
* @param array tabExist
* @return void
* @access private
*/
private function _deleteTables($db, $chpage, $tabExist)
{
$_strtrans = '';
$_strname = '';
$shoot = FALSE;
if (!empty($tabExist) && is_array($tabExist)) {
foreach ($tabExist as $key => $value) {
if (!$value) {
$_strtrans .= '<input type="hidden" name="delrow[]" value="' . htmlspecialchars($key) . '" />' . "\n";
$_strname .= '<li>' . htmlspecialchars($key) . '</li>' . "\n";
$shoot = TRUE;
}
}
if ($shoot) {
echo '<form action="schema_edit.php" method="post">' . "\n"
. PMA_generate_common_hidden_inputs($db, $table)
. '<input type="hidden" name="do" value="deleteCrap" />' . "\n"
. '<input type="hidden" name="chpage" value="' . htmlspecialchars($chpage) . '" />' . "\n"
. __('The current page has references to tables that no longer exist. Would you like to delete those references?')
. '<ul>' . "\n"
. $_strname
. '</ul>' . "\n"
. $_strtrans
. '<input type="submit" value="' . __('Go') . '" />' . "\n"
. '</form>';
}
}
}
/**
* Check if there are tables that need to be deleted in dashboard,
* if there are, ask the user for allowance
*
* @return void
* @access private
*/
private function _displayScratchboardTables($array_sh_page,$draginit,$reset_draginit)
{
global $with_field_names,$cfg,$db;
?>
<script type="text/javascript" src="./js/dom-drag.js"></script>
<form method="post" action="schema_edit.php" name="dragdrop">
<input type="button" name="dragdrop" value="<?php echo __('Toggle scratchboard'); ?>" onclick="ToggleDragDrop('pdflayout');" />
<input type="button" name="dragdropreset" value="<?php echo __('Reset'); ?>" onclick="resetDrag();" />
</form>
<div id="pdflayout" class="pdflayout" style="visibility: hidden;">
<?php
$i = 0;
foreach ($array_sh_page as $key => $temp_sh_page) {
$drag_x = $temp_sh_page['x'];
$drag_y = $temp_sh_page['y'];
$draginit .= ' Drag.init(getElement("table_' . $i . '"), null, 0, parseInt(myid.style.width)-2, 0, parseInt(myid.style.height)-5);' . "\n";
$draginit .= ' getElement("table_' . $i . '").onDrag = function (x, y) { document.edcoord.elements["c_table_' . $i . '[x]"].value = parseInt(x); document.edcoord.elements["c_table_' . $i . '[y]"].value = parseInt(y) }' . "\n";
$draginit .= ' getElement("table_' . $i . '").style.left = "' . $drag_x . 'px";' . "\n";
$draginit .= ' getElement("table_' . $i . '").style.top = "' . $drag_y . 'px";' . "\n";
$reset_draginit .= ' getElement("table_' . $i . '").style.left = "2px";' . "\n";
$reset_draginit .= ' getElement("table_' . $i . '").style.top = "' . (15 * $i) . 'px";' . "\n";
$reset_draginit .= ' document.edcoord.elements["c_table_' . $i . '[x]"].value = "2"' . "\n";
$reset_draginit .= ' document.edcoord.elements["c_table_' . $i . '[y]"].value = "' . (15 * $i) . '"' . "\n";
$local_query = 'SHOW FIELDS FROM '
. PMA_backquote($temp_sh_page['table_name'])
. ' FROM ' . PMA_backquote($db);
$fields_rs = PMA_DBI_query($local_query);
unset($local_query);
$fields_cnt = PMA_DBI_num_rows($fields_rs);
echo '<div id="table_' . $i . '" class="pdflayout_table"><u>' . $temp_sh_page['table_name'] . '</u>';
if (isset($with_field_names)) {
while ($row = PMA_DBI_fetch_assoc($fields_rs)) {
echo '<br />' . htmlspecialchars($row['Field']) . "\n";
}
}
echo '</div>' . "\n";
PMA_DBI_free_result($fields_rs);
unset($fields_rs);
$i++;
}
?>
</div>
<script type="text/javascript">
//<![CDATA[
function PDFinit() {
refreshLayout();
myid = getElement('pdflayout');
<?php echo $draginit; ?>
}
function resetDrag() {
<?php echo $reset_draginit; ?>
}
//]]>
</script>
<?php
}
/**
* delete the table rows with table co-ordinates
*
* @param int delrow delete selected table from list of tables
* @param array cfgRelation relation settings
* @param string db database name
* @param integer chpage selected page for adding relations etc
* @return void
* @access private
*/
private function _deleteTableRows($delrow,$cfgRelation,$db,$chpage)
{
foreach ($delrow as $current_row) {
$del_query = 'DELETE FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) . ' ' . "\n"
. ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\'' . "\n"
. ' AND table_name = \'' . PMA_sqlAddslashes($current_row) . '\'' . "\n"
. ' AND pdf_page_number = \'' . PMA_sqlAddslashes($chpage) . '\'';
echo $del_query;
PMA_query_as_controluser($del_query, FALSE, $query_default_option);
}
}
/**
* get all the export options and verify
* call and include the appropriate Schema Class depending on $export_type
*
* @return void
* @access private
*/
private function _processExportSchema()
{
/**
* Settings for relation stuff
*/
require_once './libraries/transformations.lib.php';
require_once './libraries/Index.class.php';
/**
* default is PDF
*/
global $db,$export_type;
$export_type = isset($export_type) ? $export_type : 'pdf';
PMA_DBI_select_db($db);
include("./libraries/schema/".ucfirst($export_type)."_Relation_Schema.class.php");
$obj_schema = eval("new PMA_".ucfirst($export_type)."_Relation_Schema();");
}
/**
* delete X and Y coordinates
*
* @param string db The database name
* @param array cfgRelation relation settings
* @param integer choosePage selected page for adding relations etc
* @return void
* @access private
*/
public function deleteCoordinates($db, $cfgRelation, $choosePage, $query_default_option)
{
$query = 'DELETE FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords'])
. ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\''
. ' AND pdf_page_number = \'' . PMA_sqlAddslashes($choosePage) . '\'';
PMA_query_as_controluser($query, FALSE, $query_default_option);
}
/**
* delete pages
*
* @param string db The database name
* @param array cfgRelation relation settings
* @param integer choosePage selected page for adding relations etc
* @return void
* @access private
*/
public function deletePages($db, $cfgRelation, $choosePage, $query_default_option)
{
$query = 'DELETE FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['pdf_pages'])
. ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\''
. ' AND page_nr = \'' . PMA_sqlAddslashes($choosePage) . '\'';
PMA_query_as_controluser($query, FALSE, $query_default_option);
}
/**
* process internal and foreign key relations
*
* @param string db The database name
* @param array cfgRelation relation settings
* @param integer pageNumber document number/Id
* @return void
* @access private
*/
public function processRelations($db, $pageNumber, $cfgRelation, $query_default_option)
{
/*
* A u t o m a t i c l a y o u t
*
* There are 2 kinds of relations in PMA
* 1) Internal Relations 2) Foreign Key Relations
*/
if (isset($this->autoLayoutInternal) || isset($this->autoLayoutForeign)) {
$all_tables = array();
}
if (isset($this->autoLayoutForeign)) {
/*
* get the tables list
* who support FOREIGN KEY, it's not
* important that we group together InnoDB tables
* and PBXT tables, as this logic is just to put
* the tables on the layout, not to determine relations
*/
$tables = PMA_DBI_get_tables_full($db);
$foreignkey_tables = array();
foreach($tables as $table_name => $table_properties) {
if (PMA_foreignkey_supported($table_properties['ENGINE'])) {
$foreignkey_tables[] = $table_name;
}
}
$all_tables = $foreignkey_tables;
/*
* could be improved by finding the tables which have the
* most references keys and placing them at the beginning
* of the array (so that they are all center of schema)
*/
unset($tables, $foreignkey_tables);
}
if (isset($this->autoLayoutInternal)) {
/*
* get the tables list who support Internal Relations;
* This type of relations will be created when
* you setup the PMA tables correctly
*/
$master_tables = 'SELECT COUNT(master_table), master_table'
. ' FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['relation'])
. ' WHERE master_db = \'' . $db . '\''
. ' GROUP BY master_table'
. ' ORDER BY ' . PMA_backquote('COUNT(master_table)') . ' DESC ';
$master_tables_rs = PMA_query_as_controluser($master_tables, FALSE, $query_default_option);
if ($master_tables_rs && PMA_DBI_num_rows($master_tables_rs) > 0) {
/* first put all the master tables at beginning
* of the list, so they are near the center of
* the schema
*/
while (list(, $master_table) = PMA_DBI_fetch_row($master_tables_rs)) {
$all_tables[] = $master_table;
}
/* Now for each master, add its foreigns into an array
* of foreign tables, if not already there
* (a foreign might be foreign for more than
* one table, and might be a master itself)
*/
$foreign_tables = array();
foreach ($all_tables as $master_table) {
$foreigners = PMA_getForeigners($db, $master_table);
foreach ($foreigners as $foreigner) {
if (!in_array($foreigner['foreign_table'], $foreign_tables)) {
$foreign_tables[] = $foreigner['foreign_table'];
}
}
}
/*
* Now merge the master and foreign arrays/tables
*/
foreach ($foreign_tables as $foreign_table) {
if (!in_array($foreign_table, $all_tables)) {
$all_tables[] = $foreign_table;
}
}
}
}
if (isset($this->autoLayoutInternal) || isset($this->autoLayoutForeign)) {
$this->addRelationCoordinates($all_tables,$pageNumber,$db, $cfgRelation,$query_default_option);
}
$this->choosenPage = $pageNumber;
}
/**
* Add X and Y coordinates for a table
*
* @param string db The database name
* @param array cfgRelation relation settings
* @param integer pageNumber document number/Id
* @param array all_tables A list of all tables involved
* @return void
* @access private
*/
public function addRelationCoordinates($all_tables,$pageNumber,$db, $cfgRelation,$query_default_option)
{
/*
* Now generate the coordinates for the schema
* in a clockwise spiral and add to co-ordinates table
*/
$pos_x = 300;
$pos_y = 300;
$delta = 110;
$delta_mult = 1.10;
$direction = "right";
foreach ($all_tables as $current_table) {
/*
* save current table's coordinates
*/
$insert_query = 'INSERT INTO ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) . ' '
. '(db_name, table_name, pdf_page_number, x, y) '
. 'VALUES (\'' . PMA_sqlAddslashes($db) . '\', \'' . PMA_sqlAddslashes($current_table) . '\',' . $pageNumber . ',' . $pos_x . ',' . $pos_y . ')';
PMA_query_as_controluser($insert_query, FALSE, $query_default_option);
/*
* compute for the next table
*/
switch ($direction) {
case 'right':
$pos_x += $delta;
$direction = "down";
$delta *= $delta_mult;
break;
case 'down':
$pos_y += $delta;
$direction = "left";
$delta *= $delta_mult;
break;
case 'left':
$pos_x -= $delta;
$direction = "up";
$delta *= $delta_mult;
break;
case 'up':
$pos_y -= $delta;
$direction = "right";
$delta *= $delta_mult;
break;
}
}
}
/**
* update X and Y coordinates for a table
*
* @param string db The database name
* @param array cfgRelation relation settings
* @return void
* @access private
*/
private function _editCoordinates($db, $cfgRelation,$query_default_option)
{
for ($i = 0; $i < $this->c_table_rows; $i++) {
$arrvalue = 'c_table_' . $i;
global $$arrvalue;
$arrvalue = $$arrvalue;
if (!isset($arrvalue['x']) || $arrvalue['x'] == '') {
$arrvalue['x'] = 0;
}
if (!isset($arrvalue['y']) || $arrvalue['y'] == '') {
$arrvalue['y'] = 0;
}
if (isset($arrvalue['name']) && $arrvalue['name'] != '--') {
$test_query = 'SELECT * FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords'])
. ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\''
. ' AND table_name = \'' . PMA_sqlAddslashes($arrvalue['name']) . '\''
. ' AND pdf_page_number = \'' . PMA_sqlAddslashes($this->choosenPage) . '\'';
$test_rs = PMA_query_as_controluser($test_query, FALSE, $query_default_option);
//echo $test_query;
if ($test_rs && PMA_DBI_num_rows($test_rs) > 0) {
if (isset($arrvalue['delete']) && $arrvalue['delete'] == 'y') {
$ch_query = 'DELETE FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords'])
. ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\''
. ' AND table_name = \'' . PMA_sqlAddslashes($arrvalue['name']) . '\''
. ' AND pdf_page_number = \'' . PMA_sqlAddslashes($this->choosenPage) . '\'';
} else {
$ch_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) . ' '
. 'SET x = ' . $arrvalue['x'] . ', y= ' . $arrvalue['y']
. ' WHERE db_name = \'' . PMA_sqlAddslashes($db) . '\''
. ' AND table_name = \'' . PMA_sqlAddslashes($arrvalue['name']) . '\''
. ' AND pdf_page_number = \'' . PMA_sqlAddslashes($this->choosenPage) . '\'';
}
} else {
$ch_query = 'INSERT INTO ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($cfgRelation['table_coords']) . ' '
. '(db_name, table_name, pdf_page_number, x, y) '
. 'VALUES (\'' . PMA_sqlAddslashes($db) . '\', \'' . PMA_sqlAddslashes($arrvalue['name']) . '\', \'' . PMA_sqlAddslashes($this->choosenPage) . '\',' . $arrvalue['x'] . ',' . $arrvalue['y'] . ')';
}
//echo $ch_query;
PMA_query_as_controluser($ch_query, FALSE, $query_default_option);
} // end if
} // end for
}
}
?>

View 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);
}
}
}
?>

View File

@ -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;

View File

@ -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 .= '&amp;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';
?>

File diff suppressed because it is too large Load Diff

140
schema_edit.php Normal file
View 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 .= '&amp;goto=schema_edit.php';
require_once './libraries/db_info.inc.php';
/**
* Includ settings for relation stuff
* get all variables needed for exporting relational schema
* in $cfgRelation
*/
require_once './libraries/relation.lib.php';
$cfgRelation = PMA_getRelationsParam();
/**
* This is to avoid "Command out of sync" errors. Before switching this to
* a value of 0 (for MYSQLI_USE_RESULT), please check the logic
* to free results wherever needed.
*/
$query_default_option = PMA_DBI_QUERY_STORE;
/**
* Now in ./libraries/relation.lib.php we check for all tables
* that we need, but if we don't find them we are quiet about it
* so people can't work without relational variables.
* This page is absolutely useless if you didn't set up your tables
* correctly, so it is a good place to see which tables we can and
* complain ;-)
*/
if (!$cfgRelation['relwork']) {
echo sprintf(__('<b>%s</b> table not found or not set in %s'), 'relation', 'config.inc.php') . '<br />' . "\n"
. PMA_showDocu('relation') . "\n";
require_once './libraries/footer.inc.php';
}
if (!$cfgRelation['displaywork']) {
echo sprintf(__('<b>%s</b> table not found or not set in %s'), 'table_info', 'config.inc.php') . '<br />' . "\n"
. PMA_showDocu('table_info') . "\n";
require_once './libraries/footer.inc.php';
}
if (!isset($cfgRelation['table_coords'])){
echo sprintf(__('<b>%s</b> table not found or not set in %s'), 'table_coords', 'config.inc.php') . '<br />' . "\n"
. PMA_showDocu('table_coords') . "\n";
require_once './libraries/footer.inc.php';
}
if (!isset($cfgRelation['pdf_pages'])) {
echo sprintf(__('<b>%s</b> table not found or not set in %s'), 'pdf_page', 'config.inc.php') . '<br />' . "\n"
. PMA_showDocu('pdf_pages') . "\n";
require_once './libraries/footer.inc.php';
}
if ($cfgRelation['pdfwork']) {
/**
* User object created for presenting the HTML options
* so, user can interact with it and perform export of relations schema
*/
require_once './libraries/schema/User_Schema.class.php';
$user_schema = new PMA_User_Schema();
/**
* This function will process the user defined pages
* and tables which will be exported as Relational schema
* you can set the table positions on the paper via scratchboard
* for table positions, put the x,y co-ordinates
*
* @param string $do It tells what the Schema is supposed to do
* create and select a page, generate schema etc
*/
if(isset($_REQUEST['do'])){
$user_schema->setAction($_REQUEST['do']);
$user_schema->processUserPreferences();
}
/**
* Show some possibility to select a page for the export of relation schema
* Lists all pages created before and can select and edit from them
*/
$user_schema->selectPage();
/**
* Create a new page where relations will be drawn
*/
$user_schema->createPage($db);
/**
* After selection of page or creating a page
* It will show you the list of tables
* A dashboard will also be shown where you can position the tables
*/
$user_schema->showTableDashBoard();
if (isset($_REQUEST['do'])
&& ($_REQUEST['do'] == 'edcoord'
|| ($_REQUEST['do']== 'selectpage' && isset($user_schema->choosenPage) && $user_schema->choosenPage != 0)
|| ($_REQUEST['do'] == 'createpage' && isset($user_schema->choosenPage) && $user_schema->choosenPage != 0))) {
/**
* show Export schema generation options
*/
$user_schema->displaySchemaGenerationOptions();
if ((isset($showwysiwyg) && $showwysiwyg == '1')) {
?>
<script type="text/javascript">
//<![CDATA[
ToggleDragDrop('pdflayout');
//]]>
</script>
<?php
}
} // end if
} // end if ($cfgRelation['pdfwork'])
/**
* Displays the footer
*/
echo "\n";
require_once './libraries/footer.inc.php';
?>

49
schema_export.php Normal file
View 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();");