forked from GNUsocial/gnu-social
		
	
		
			
				
	
	
		
			90 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			90 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env php
 | |
| 
 | |
| <?php
 | |
| 
 | |
| define('INSTALL_DIR', dirname(__DIR__));
 | |
| 
 | |
| require INSTALL_DIR . '/vendor/autoload.php';
 | |
| 
 | |
| use App\Util\Formatting;
 | |
| use App\Util\HTML as H;
 | |
| use Functional as F;
 | |
| 
 | |
| $template = '
 | |
| graph database {
 | |
| 
 | |
| %tables%
 | |
| 
 | |
| %edges%
 | |
| 
 | |
| }
 | |
| ';
 | |
| 
 | |
| $files = glob(INSTALL_DIR . '/src/Entity/*.php');
 | |
| 
 | |
| $tables = [];
 | |
| $edges  = [];
 | |
| $classes = [];
 | |
| foreach ($files as $file) {
 | |
|     require_once $file;
 | |
| 
 | |
|     $class = '';
 | |
|     $declared = get_declared_classes();
 | |
|     foreach ($declared as $dc) {
 | |
|         if (preg_match('/^(App|(Component|Plugin)\\\\[^\\\\]+)\\\\Entity/', $dc) && !in_array($dc, $classes)) {
 | |
|             $class = $dc;
 | |
|             $classes[] = $class;
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     $schema   = $class::schemaDef();
 | |
|     $table    = preg_replace(',`?([^`]+)`?,', '$1', $schema['name']);
 | |
|     $fields   = [['name' => $table, 'type' => '']];
 | |
|     foreach ($schema['fields'] as $name => $opts) {
 | |
|         $fields[] = [
 | |
|             'name' => $name,
 | |
|             'type' => ": {$opts['type']}" . ($opts['type'] == 'varchar' ? "({$opts['length']})" : ''),
 | |
|         ];
 | |
|     }
 | |
| 
 | |
|     foreach ($schema['fields'] as $field => $opts) {
 | |
|         if (isset($opts['foreign key'])) {
 | |
|             [$foreign_entity, $foreign_key] = explode('.', $opts['target']);
 | |
|             $foreign_table = Formatting::camelCaseToSnakeCase(preg_replace('/Actor/', 'actor', $foreign_entity));
 | |
|             $edges[]     = "{$table}:{$field} -- {$foreign_table}:{$foreign_key}";
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     $cell = function ($field) {
 | |
|         $def = $field['name'] . $field['type'];
 | |
|         return ['tr' => ['td' => ['attrs' => ['port' => $field['name']], $def]]];
 | |
|     };
 | |
|     $html = ['table' => array_merge(
 | |
|               ['attrs' => ['border' => '0', 'cellborder' => '1', 'cellspacing' => '0']],
 | |
|               F\map($fields, $cell)),
 | |
|     ];
 | |
| 
 | |
|     $tables[] = Formatting::indent("{$table} [shape=none, label=<\n" . Formatting::indent(H::html($html)) . "\n>]");
 | |
| }
 | |
| 
 | |
| $replace = [
 | |
|     '/%tables%/' => Formatting::indent(implode("\n", $tables)),
 | |
|     '/%edges%/'  => Formatting::indent(implode("\n", $edges)),
 | |
|     // '/_/'        => '\textunderscore ',
 | |
| ];
 | |
| 
 | |
| $out = $template;
 | |
| foreach ($replace as $from => $to) {
 | |
|     $out = preg_replace($from, $to, $out);
 | |
| }
 | |
| 
 | |
| $path = dirname(__DIR__) . '/docs/developer/src/database';
 | |
| 
 | |
| $outfile = $path . '/database.dot';
 | |
| file_put_contents($outfile, $out);
 | |
| 
 | |
| system("neato -Goverlap=false -Gsplines=true -Tpdf {$path}/database.dot -o {$path}/database.pdf");
 | |
| 
 | |
| echo "Generated database diagram. See {$path}/database.pdf\n";
 |