diff --git a/tools/modelGraph.php b/tools/modelGraph.php new file mode 100755 index 0000000..0a8f084 --- /dev/null +++ b/tools/modelGraph.php @@ -0,0 +1,166 @@ +#!/usr/bin/php + + */ + +require_once ("domframework/dblayeroo.php"); + +/** modelGraph + * Allow to create the relational graph of an existing database + * Use GraphViz to generate the graph + * Request the database DSN to operate + */ +class modelgraph +{ + // PROPERTIES + /** The connected object dblayeroo + */ + private $db; + /** The output file + */ + private $output; + + /** The constructor wait for $dsn + * @param string $dsn The DSN to connect to database + * @param string $output The output file to generate + */ + public function __construct ($dsn, $username, $password, $output) + // {{{ + { + $this->output = $output; + $this->db = new \dblayeroo ($dsn, $username, $password); + $this->graphvizCommande (); + } + // }}} + + /** Generate the output file + */ + public function generate () + // {{{ + { + $tables = array (); + foreach ($this->db->listTables () as $table) + { + $tables[$table] = $this->db->getTableSchema ($table); + } + $d = "digraph G {\n"; + $d .= " node [shape=box];\n"; + $d .= " rankdir=RL\n"; + + // Generate the tables objects with the fields + foreach ($tables as $table => $schema) + { + $d .= " /** TABLE '$table' */\n"; + $d .= " \"$table\" [\n"; + $d .= " shape = \"plaintext\"\n"; + $d .= " label = <"; + $d .= "\n"; + // Display the name of the table as title + $d .= " \n"; + // Display the fields + $i = 0; + foreach ($schema["fields"] as $field => $params) + { + $d .= " \n"; + $d .= "\n"; + $d .= "\n"; + $d .= "\n"; + $d .= "\n"; + $i++; + } + $d .= "
"; + $d .= "$table
"; + if (key_exists ($field, $schema["foreign"])) + { + // Foreign Key + $d .= "!"; + } + elseif (key_exists ("primary", $schema) && + $field === $schema["primary"]) + $d .= "🔑"; // Primary key found + elseif (in_array ("not null", $params)) + $d .= ""; // NOT NULL + else + $d .= "◇"; + $d .= ""; + $d .= $field; + $d .= ""; + $d .= $params[0]; + $d .= "
>\n"; + $d .= " ];\n"; + } + // Generate the links between the tables + foreach ($tables as $table => $schema) + { + // "node1":"f2" -> "node5":"f0" []; + foreach ($schema["foreign"] as $field => $params) + { + $d .= "\"$table\":\"OUT-$field\" -> \"". $params[0]. + "\":\"IN-".$params[1]."\" "; + $d .= "[];\n"; + } + } + $d .= "}\n"; + //echo $d; + $this->createJPG ($d); + } + // }}} + + /** Look for the dot command + * @return the full path of 'dot' command + */ + private function graphvizCommande () + // {{{ + { + foreach (explode (":", getenv ("PATH")) as $path) + { + if (file_exists ("$path/dot")) + return "$path/dot"; + } + throw new \Exception ("Can not find 'dot' executable. Install graphviz", + 500); + } + // }}} + + /** Generate the JPEG file with graphviz + * @param string $content The content of the GV file + */ + private function createJPG ($content) + // {{{ + { + $tmp = tempnam ("/tmp", "modelgraph_"); + file_put_contents ($tmp, $content); + $cmd = $this->graphvizCommande (). " -T jpeg $tmp ". + "-o ".escapeshellarg ($this->output)." 2>&1"; + exec ($cmd, $output); + unlink ($tmp); + if (!empty ($output)) + { + echo "ERROR : ".implode ("\n", $output); + exit (2); + } + } + // }}} +} + + +// MAIN PROGRAM +if (isset ($argv[1]) && $argv[1] === "-h") +{ + echo "Create the ER Diagram of a SQL database\n"; + echo "Usage : \n"; + echo $argv[0]." DSN username password outputfile.jpg\n"; + echo "DSN Examples : 'mysql:dbname=databaseName'\n"; +} +if (! isset ($argv[1])) + die ("No DSN provided\n"); +if (! isset ($argv[2])) + die ("No username provided\n"); +if (! isset ($argv[3])) + die ("No password provided\n"); +if (! isset ($argv[4])) + die ("No output file provided\n"); +$modelgraph = new modelgraph ($argv[1], $argv[2], $argv[3], $argv[4]); +$modelgraph->generate ();