public function generate($folder, $name = 'dependencies') { $graph = new Gremlin3(Config::factory()); $links = array(); $nodes = array('class' => array(), 'trait' => array(), 'interface' => array(), 'unknown' => array()); $fullcode = array(); $query = <<<GREMLIN g.V().hasLabel("Class").map{[it.get().value("fullnspath"), it.get().value("fullcode")]} GREMLIN; $res = $graph->query($query); foreach ($res->results as $v) { $names[$v[0]] = $v[1]; $nodes['class'][] = $v[0]; } $query = <<<GREMLIN g.V().hasLabel("Trait").map{[it.get().value("fullnspath"), it.get().value("fullcode")]} GREMLIN; $res = $graph->query($query); foreach ($res->results as $v) { $names[$v[0]] = $v[1]; $nodes['trait'][] = $v[0]; } $query = <<<GREMLIN g.V().hasLabel("Interface").map{[it.get().value("fullnspath"), it.get().value("fullcode")]} GREMLIN; $res = $graph->query($query); foreach ($res->results as $v) { $names[$v[0]] = $v[1]; $nodes['interface'][] = $v[0]; } $nodesId = array_flip(call_user_func_array('array_merge', array_values($nodes))); // static constants $query = <<<GREMLIN g.V().hasLabel("Staticconstant").as('fullcode') .out('CLASS').as('destination') .repeat(__.in()).until(hasLabel("Class", "Trait", "Interface")).as('origin') .select('origin', 'destination', 'fullcode').by('fullnspath').by('fullnspath').by('fullcode') GREMLIN; $res = $graph->query($query); $total = 0; foreach ($res->results as $v) { if (!isset($nodesId[$v->origin])) { $nodes['unknown'][] = $v->origin; $nodesId[$v->origin] = count($nodes) - 1; } if (!isset($nodesId[$v->destination])) { $nodes['unknown'][] = $v->destination; $nodesId[$v->destination] = count($nodes) - 1; } $links[$nodesId[$v->destination] . ' -> ' . $nodesId[$v->origin]][] = 'staticconstant'; $fullcode[$nodesId[$v->destination] . ' -> ' . $nodesId[$v->origin]][] = $v->fullcode; ++$total; } print "{$total} Static constants\n"; // static property $query = <<<GREMLIN g.V().hasLabel("Staticproperty").as('fullcode') .out('CLASS').as('destination') .repeat(__.in()).until(hasLabel("Class", "Trait", "Interface")).as('origin') .select('origin', 'destination', 'fullcode').by('fullnspath').by('fullnspath').by('fullcode') GREMLIN; $res = $graph->query($query); $total = 0; foreach ($res->results as $v) { if (!isset($nodesId[$v->origin])) { $nodes['unknown'][] = $v->origin; $nodesId[$v->origin] = count($nodes) - 1; } if (!isset($nodesId[$v->destination])) { $nodes['unknown'][] = $v->destination; $nodesId[$v->destination] = count($nodes) - 1; } $links[$nodesId[$v->destination] . ' -> ' . $nodesId[$v->origin]][] = 'staticproperty'; $fullcode[$nodesId[$v->destination] . ' -> ' . $nodesId[$v->origin]][] = $v->fullcode; ++$total; } print "{$total} Static property\n"; // Instantiation $query = <<<GREMLIN g.V().hasLabel("New").as('fullcode') .out('NEW').as('destination') .repeat(__.in()).until(hasLabel("Class", "Trait", "Interface")).as('origin') .select('origin', 'destination', 'fullcode').by('fullnspath').by('fullnspath').by('fullcode') GREMLIN; $res = $graph->query($query); $total = 0; foreach ($res->results as $v) { if (!isset($nodesId[$v->origin])) { $nodes['unknown'][] = $v->origin; $nodesId[$v->origin] = count($nodes) - 1; } if (!isset($nodesId[$v->destination])) { $nodes['unknown'][] = $v->destination; $nodesId[$v->destination] = count($nodes) - 1; } $links[$nodesId[$v->destination] . ' -> ' . $nodesId[$v->origin]][] = 'instanciation'; $fullcode[$nodesId[$v->destination] . ' -> ' . $nodesId[$v->origin]][] = $v->fullcode; ++$total; } print "{$total} New\n"; // Typehint $query = <<<GREMLIN g.V().hasLabel("Function").as('fullcode') .out('ARGUMENTS').out("ARGUMENT").out("TYPEHINT").as('destination') .repeat(__.in()).until(hasLabel("Class", "Trait", "Interface")).as('origin') .select('origin', 'destination', 'fullcode').by('fullnspath').by('fullnspath').by('fullcode') GREMLIN; $res = $graph->query($query); $total = 0; foreach ($res->results as $v) { if (!isset($nodesId[$v->origin])) { $nodes['unknown'][] = $v->origin; $nodesId[$v->origin] = count($nodes) - 1; } if (!isset($nodesId[$v->destination])) { $nodes['unknown'][] = $v->destination; $nodesId[$v->destination] = count($nodes) - 1; } $links[$nodesId[$v->destination] . ' -> ' . $nodesId[$v->origin]][] = 'typehint'; $fullcode[$nodesId[$v->destination] . ' -> ' . $nodesId[$v->origin]][] = $v->fullcode; ++$total; } print "{$total} Typehint\n"; // instanceof $query = <<<GREMLIN g.V().hasLabel("Instanceof").as('fullcode') .out('CLASS').as('destination') .repeat(__.in()).until(hasLabel("Class", "Trait", "Interface")).as('origin') .select('origin', 'destination', 'fullcode').by('fullnspath').by('fullnspath').by('fullcode') GREMLIN; $res = $graph->query($query); $total = 0; foreach ($res->results as $v) { if (!isset($nodesId[$v[0]])) { $nodes['unknown'][] = $v[0]; $nodesId[$v[0]] = count($nodes) - 1; } if (!isset($nodesId[$v[1]])) { $nodes['unknown'][] = $v[1]; $nodesId[$v[1]] = count($nodes) - 1; } $links[$nodesId[$v[1]] . ' -> ' . $nodesId[$v[0]]][] = 'instanceof'; $fullcode[$nodesId[$v[1]] . ' -> ' . $nodesId[$v[0]]][] = $v[2]; ++$total; } print "{$total} Instanceof\n"; // static methods $query = <<<GREMLIN g.V().hasLabel("Staticmethodcall").as('fullcode') .out('CLASS').as('destination') .repeat(__.in()).until(hasLabel("Class", "Trait", "Interface")).as('origin') .select('origin', 'destination', 'fullcode').by('fullnspath').by('fullnspath').by('fullcode') GREMLIN; $res = $graph->query($query); $total = 0; foreach ($res->results as $v) { if (!isset($nodesId[$v->origin])) { $nodes['unknown'][] = $v->origin; $nodesId[$v->origin] = count($nodes) - 1; } if (!isset($nodesId[$v->destination])) { $nodes['unknown'][] = $v->destination; $nodesId[$v->destination] = count($nodes) - 1; } $links[$nodesId[$v->destination] . ' -> ' . $nodesId[$v->origin]][] = 'staticmethodcall'; $fullcode[$nodesId[$v->destination] . ' -> ' . $nodesId[$v->origin]][] = $v->fullcode; ++$total; } print "{$total} Static methods\n"; // Final preparation // Nodes $colors = array('class' => 'darkorange', 'trait' => 'gold', 'interface' => 'skyblue', 'unknown' => 'gray'); foreach ($nodes as $type => &$someNodes) { foreach ($someNodes as $id => &$n) { $n = <<<DOT {$nodesId[$n]} [label=<<table color='white' BORDER='0' CELLBORDER='1' CELLSPACING='0' > <tr> <td bgcolor='{$colors[$type]}'>{$n}</td> </tr> </table>> shape="none"]; DOT; } unset($n); } unset($someNodes); // print_r($nodes); // Links $colors = array('staticmethodcall' => 'firebrick2', 'staticconstant' => 'firebrick2', 'staticproperty' => 'firebrick2', 'instanceof' => 'chartreuse4', 'typehint' => 'chartreuse4', 'use' => 'darkgoldenrod2', 'instanciation' => 'black'); $linksDot = array(); foreach ($links as $link => $type) { foreach ($type as $id => $t) { $linksDot[] = $link . ' [shape="none" color="' . $colors[$t] . '" label="' . str_replace('"', '\\"', $fullcode[$link][$id]) . '"];'; } } unset($type); $dot = "digraph graphname {\n \n fontname = \"Bitstream Vera Sans\"\n fontsize = 14\n colorscheme = \"bugn9\"\n\n node [\n fontname = \"Bitstream Vera Sans\"\n fontsize = 14\n shape = \"record\"\n ]\n\n edge [\n fontname = \"Bitstream Vera Sans\"\n fontsize = 8\n arrowhead = \"empty\"\n width = \"2\"\n ]\n \n " . implode("\n", $nodes['class']) . "\n" . implode("\n", $nodes['trait']) . "\n" . implode("\n", $nodes['interface']) . "\n" . implode("\n", $nodes['unknown']) . "\n\n" . implode("\n", $linksDot) . "\n}\n"; print strlen($dot); print $folder . '/' . $name . '.' . self::FILE_EXTENSION; file_put_contents($folder . '/' . $name . '.' . self::FILE_EXTENSION, $dot); }