Posted by ruxkor on Wed 17 Dec 16:10 (modification of post by ruxkor view diff)
report abuse | download | new post
- <?php
- /**
- * Visualize console task
- *
- * This task can be used to generate a graphical representation of your tables or models.
- *
- * PHP versions 4 and 5
- *
- * Copyright (c) Tomenko Yevgeny
- *
- * Licensed under The MIT License
- * Redistributions of files must retain the above copyright notice.
- *
- * @version 1.2.0
- * @modifiedby Andy Dawson
- * @lastmodified 2007-12-20 23:39:02 +0100 (Thu, 16 Aug 2007) $
- * @license http://www.opensource.org/licenses/mit-license.php The MIT License
- */
- uses('Folder','File','model'.DS.'connection_manager');
- class VisualizeShell extends Shell {
- var $DOC_DIR ;
- var $PREFIX = APP_DIR;
- var $graphToolPath = 'dot.exe'; // cake visualize -tool C:\dev\_tools_\graphviz-2.16\bin\dot.exe
- function help() {
- $this->out('CakePHP visualise, Usage examples:');
- $this->out('cake visualize help');
- $this->out(' - this text');
- $this->out('cake visualize tables');
- $this->out(' - generate graphic based on table structure');
- $this->out('cake visualize models');
- $this->out(' - generate graphic based on model association definitions');
- $this->out('cake visualise [-tool graphVizTool]');
- $this->hr();
- }
- function initialize() {
- if (DS == '/') {
- 'dot',
- 'dot -Gmode=heir',
- 'neato',
- 'neato -Gmodel=subset'
- );
- }
- $this->DOC_DIR = APP . 'config' . DS . 'sql';
- $this->PREFIX= 'img_';
- $this->graphToolPath = $this->params['tool'];
- }
- return true;
- }
- function main() {
- $this->args[0] = 'filtered';
- }
- if ($this->args[0] == 'help') {
- $this->help();
- return;
- } elseif ($this->args[0] == 'tables') {
- $mode = 't';
- $this->generateDataFromTables();
- } elseif ($this->args[0] == 'models') {
- $mode = 'm';
- $this->generateDataFromModels();
- } elseif ($this->args[0] == 'combined') {
- $mode = 'combined';
- $this->generateDataFromTables();
- $this->generateDataFromModels();
- } elseif ($this->args[0] == 'filtered') {
- $mode = 'filtered';
- $this->generateDataFromTables();
- $this->generateDataFromModels();
- $this->filterPotentialDuplicates();
- }
- $this->writeDotFile($this->DOC_DIR, $mode);
- }
- function generateDataFromModels() {
- foreach($this->getAllModels() as $model) {
- $this->out("Looking at model: {$model}");
- $model = new $model();
- if (!$model->useTable) {
- continue;
- }
- $this->data['tables'][$model->name] = $model->schema(true);
- foreach ($this->data['tables'][$model->name] as $attrname => $attr) {
- $attr['type'] .= "[{$attr['length']}]";
- }
- $this->data['nodes'][$model->name][$attrname] = $attr['type'];
- $this->data['nodes'][$model->name][$attrname] .= ", default: \\\"{$attr['default']}\\\"";
- }
- }
- foreach($model->__associations as $type) {
- foreach ($model->$type as $alias => $association) {
- $otherModel = $association['className'];
- if ($type == 'belongsTo') {
- $this->data['associations'][$model->name.$otherModel] =
- 'label'=> $model->name . '->' . $alias,
- 'node1'=> $model->name,
- 'node2'=> $otherModel,
- 'foreignKey' => $association['foreignKey'],
- 'assType'=>'n:1'
- );
- $this->data['associations'][$otherModel.$model->name] =
- 'label'=> $otherModel . '->' . $model->name,
- 'node1'=> $otherModel,
- 'node2'=> $model->name,
- 'foreignKey' => $association['foreignKey'],
- 'assType'=>($type=='hasOne')?'1:1':'n:1'
- );
- } elseif ($type == 'hasAndBelongsToMany') {
- $names[] = $model->name;
- $names[] = $otherModel;
- $this->data['tables'][$modelName] = $DynamicModel->schema(true);
- foreach ($this->data['tables'][$modelName] as $attrname => $attr) {
- $attr['type'] .= "[{$attr['length']}]";
- }
- $this->data['nodes'][$modelName][$attrname] = $attr['type'];
- $attrtype = $attr['type'];
- $this->data['nodes'][$modelName][$attrname] .= ", default: \\\"{$attr['default']}\\\"";
- }
- }
- $this->data['associations'][$model->name.$otherModel] =
- 'label'=> $model->name . '->' . $modelName,
- 'node1'=> $model->name,
- 'node2'=> $modelName,
- 'foreignKey' => $association['foreignKey'],
- 'assType'=>'1:n'
- );
- $this->data['associations'][$otherModel.$model->name] =
- 'label'=> $otherModel . '->' . $modelName,
- 'node1'=> $otherModel,
- 'node2'=> $modelName,
- 'foreignKey' => $association['foreignKey'],
- 'assType'=>'1:n'
- );
- }
- }
- }
- }
- }
- }
- function generateDataFromTables() {
- foreach($this->getAllTables() as $table_name) {
- $this->out("Looking at table: {$table_name}");
- $modelName=$this->_modelName($table_name);
- $this->data['tables'][$modelName] = $this->getSchemaInfo($modelName,$table_name);
- }
- foreach ($this->data['tables'] as $table => $attributes) {
- foreach ($attributes as $attrname => $attr) {
- # Create an association to other table
- $otherTable = Inflector::camelize(r('_id','',$attrname));
- $other_table = $this->data['tables'][$otherTable];
- $this->data['associations'][] = array('label'=> $attrname, 'node1'=> $table, 'node2'=> $otherTable);
- }
- }
- $attr['type'] .= "[{$attr['length']}]";
- }
- $this->data['nodes'][$table][$attrname] = $attr['type'];
- $attrtype = $attr['type'];
- $this->data['nodes'][$table][$attrname] .= ", default: \\\"{$attr['default']}\\\"";
- }
- }
- }
- }
- }
- function getAllModels() {
- $Inflector =& Inflector::getInstance();
- uses('Folder');
- $folder = new Folder(MODELS);
- $models = $folder->findRecursive('.*php');
- $folder = new Folder(BEHAVIORS);
- $behaviors = $folder->findRecursive('.*php');
- foreach ($models as $id => $model) {
- $models[$id] = $file->name();
- }
- App::import('Model', $models);
- return $models;
- }
- function getAllTables($useDbConfig = 'default') {
- $db =& ConnectionManager::getDataSource($useDbConfig);
- if ($usePrefix) {
- foreach ($db->listSources() as $table) {
- }
- }
- } else {
- $tables = $db->listSources();
- }
- $this->__tables = $tables;
- return $tables;
- }
- function getSchemaInfo($modelName,$table_name) {
- if (App::import('model',$modelName)) {
- $model = & new $modelName();
- $attrs=$model->schema();
- return $attrs;
- } else {
- $attrs=$DynamicModel->schema();
- return $attrs;
- }
- return false;
- }
- function writeDotFile($target_dir, $mode) {
- $this->out("Creating directory \"{$target_dir}\"�");
- $folder = & new Folder($target_dir, true);
- }
- $version=0;
- if ($version > 0) {
- $header .= "\\nSchema version $version";
- }
- $dotFile = $target_dir .DS. 'mode_' . $mode . '.dot';
- $f->delete();
- }
- // Define a graph and some global settings
- $f->append("digraph G {\n");
- $f->append("\toverlap=false;\n");
- $f->append("\tsplines=true;\n");
- $f->append("\tnode [fontname=\"Helvetica\",fontsize=9];\n");
- $f->append("\tedge [fontname=\"Helvetica\",fontsize=8];\n");
- $f->append("\tranksep=0.1;\n");
- $f->append("\tnodesep=0.1;\n");
- // $f->append("\tedge [decorate=\"true\"];\n");
- // Write header info
- $f->append("\t_schema_info [shape=\"plaintext\", label=\"{$header}\", fontname=\"Helvetica\",fontsize=8];\n");
- // Draw the tables as boxes
- foreach ($this->data['nodes'] as $table=>$attributes) {
- $f->append("\t\"{$table}\" [label=\"{{$table}|");
- foreach ($attributes as $field=>$label) {
- $f->append("{$field} : {$label}\\n");
- }
- $f->append("}\" shape=\"record\"];\n");
- }
- // Draw the relations
- foreach ($this->data['associations'] as $assoc) {
- $f->append("\t\"{$assoc['node1']}\" -> \"{$assoc['node2']}\" [label=\"{$assoc['label']}\"]\n");
- }
- // Close the graph
- $f->append("}\n");
- $f->close(); // Create the images by using dot and neato (grapviz tools)
- $this->out("Generated {$dotFile}\n");
- $this->createImgs($dotFile, $target_dir, $mode);
- // Remove the .dot file // Keep it for debugging and general info
- $f->delete();
- }
- function createImgs($dotFile, $path, $mode) {
- } else {
- $commands = $this->graphToolPath;
- }
- uses ('Sanitize');
- foreach ($commands as $command) {
- $imgFile = $path . DS . 'schematic_' . $mode . '_' . Sanitize::paranoid($command) . ".png";
- $f->delete();
- }
- if ($this->createImg($command, $dotFile, $imgFile)) {
- $this->out("Generated {$imgFile}\n");
- } else {
- break;
- }
- }
- }
- function createImg($command, $dotFile, $imgFile) {
- $command = $command.' -v -Tpng -o"'.$imgFile.'" "'.$dotFile.'"';
- if ($return != 0) {
- $this->out("Command Error ($return):\n");
- $this->out("$command\n");
- return false;
- }
- return true;
- }
- function filterPotentialDuplicates() {
- $associations =& $this->data['associations'];
- foreach ($associations as $k=>$v) {
- foreach ($associations as $ik=>$iv) {
- if (
- ($iv['node1']==$v['node1']) &&
- ($iv['node2']==$v['node2']) &&
- ($iv['foreignKey']==$v['label'])
- ) {
- $duplicates[] = $k;
- }
- }
- }
- }
- foreach ($duplicates as $k) {
- }
- }
- }
- ?>
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.