Exakat\Tasks\Dump::collectStructures PHP Метод

collectStructures() приватный Метод

private collectStructures ( $sqlite )
    private function collectStructures($sqlite)
    {
        // Name spaces
        $sqlite->query('DROP TABLE IF EXISTS namespaces');
        $sqlite->query('CREATE TABLE namespaces (  id INTEGER PRIMARY KEY AUTOINCREMENT,
                                                   namespace STRING
                                                 )');
        $sqlite->query('INSERT INTO namespaces VALUES ( 1, "Global")');
        $sqlQuery = <<<SQL
INSERT INTO namespaces ("id", "namespace") 
             VALUES ( NULL, :namespace)
SQL;
        $stmt = $sqlite->prepare($sqlQuery);
        $query = <<<GREMLIN
g.V().hasLabel("Namespace").out("NAME").map{ ['name' : it.get().value("fullcode")] };
GREMLIN;
        $res = $this->gremlin->query($query);
        $res = $res->results;
        $namespacesId = array('' => 1);
        $total = 0;
        foreach ($res as $row) {
            if (isset($namespacesId['\\' . $row->name])) {
                continue;
            }
            $stmt->bindValue(':namespace', $row->name, \SQLITE3_TEXT);
            $stmt->execute();
            $namespacesId['\\' . strtolower($row->name)] = $sqlite->lastInsertRowID();
            ++$total;
        }
        display("{$total} namespaces\n");
        // Ids for Classes, Interfaces and Traits
        $citId = array();
        // Classes
        $sqlite->query('DROP TABLE IF EXISTS cit');
        $sqlite->query('CREATE TABLE cit (  id INTEGER PRIMARY KEY AUTOINCREMENT,
                                                   name STRING,
                                                   abstract INTEGER,
                                                   final INTEGER,
                                                   type TEXT,
                                                   extends TEXT DEFAULT "",
                                                   namespaceId INTEGER DEFAULT 1
                                                 )');
        $sqlite->query('CREATE TABLE cit_implements (  id INTEGER PRIMARY KEY AUTOINCREMENT,
                                                       implementing INTEGER,
                                                       implements INTEGER,
                                                       type    TEXT
                                                 )');
        $sqlQuery = <<<SQL
INSERT INTO cit ("id", "name", "namespaceId", "abstract", "final", "extends", "type") 
             VALUES ( NULL, :class, :namespaceId, :abstract, :final, :extends, "class")
SQL;
        $stmt = $sqlite->prepare($sqlQuery);
        $query = <<<GREMLIN
g.V().hasLabel("Class")
.sideEffect{ extendList = ''; }.where(__.out("EXTENDS").sideEffect{ extendList = it.get().value("fullnspath"); }.fold() )
.sideEffect{ implementList = []; }.where(__.out("IMPLEMENTS").sideEffect{ implementList.push( it.get().value("fullnspath"));}.fold() )
.sideEffect{ useList = []; }.where(__.out("BLOCK").out("ELEMENT").hasLabel("Use").out("USE").sideEffect{ useList.push( it.get().value("fullnspath"));}.fold() )
.map{ 
        ['fullnspath':it.get().value("fullnspath"),
         'name': it.get().vertices(OUT, "NAME").next().value("code"),
         'abstract':it.get().vertices(OUT, "ABSTRACT").any(),
         'final':it.get().vertices(OUT, "FINAL").any(),
         'extends':extendList,
         'implements':implementList,
         'uses':useList
         ];
}

GREMLIN;
        $res = $this->gremlin->query($query);
        $res = $res->results;
        $total = 0;
        $extendsId = array();
        $implementsId = array();
        $usesId = array();
        foreach ($res as $row) {
            $namespace = preg_replace('#\\\\[^\\\\]*?$#is', '', $row->fullnspath);
            if (isset($namespacesId[$namespace])) {
                $namespaceId = $namespacesId[$namespace];
            } else {
                $namespaceId = 1;
            }
            $stmt->bindValue(':class', $row->name, \SQLITE3_TEXT);
            $stmt->bindValue(':namespaceId', $namespaceId, \SQLITE3_INTEGER);
            $stmt->bindValue(':abstract', (int) $row->abstract, \SQLITE3_INTEGER);
            $stmt->bindValue(':final', (int) $row->final, \SQLITE3_INTEGER);
            $stmt->execute();
            $citId[$row->fullnspath] = $sqlite->lastInsertRowID();
            // Get extends
            if (!empty($row->extends)) {
                if (isset($extendsId[$row->extends[0]])) {
                    $extendsId[$row->extends[0]][] = $citId[$row->fullnspath];
                } else {
                    $extendsId[$row->extends[0]] = array($citId[$row->fullnspath]);
                }
            }
            // Get implements
            if (!empty($row->implements)) {
                $implementsId[$citId[$row->fullnspath]] = $row->implements;
            }
            // Get use
            if (!empty($row->uses)) {
                $usesId[$citId[$row->fullnspath]] = $row->uses;
            }
            ++$total;
        }
        display("{$total} classes\n");
        // Interfaces
        $sqlQuery = <<<SQL
INSERT INTO cit ("id", "name", "namespaceId", "abstract", "final", "type") 
             VALUES ( NULL, :name, :namespaceId, 0, 0, "interface")
SQL;
        $stmt = $sqlite->prepare($sqlQuery);
        $query = <<<GREMLIN
g.V().hasLabel("Interface")
.sideEffect{ extendList = ''; }.where(__.out("EXTENDS").sideEffect{ extendList = it.get().value("fullnspath"); }.fold() )
.sideEffect{ implementList = []; }.where(__.out("IMPLEMENTS").sideEffect{ implementList.push( it.get().value("fullnspath"));}.fold() )
.map{ 
        ['fullnspath':it.get().value("fullnspath"),
         'name': it.get().vertices(OUT, "NAME").next().value("code"),
         'extends':extendList,
         'implements':implementList
         ];
}
GREMLIN;
        $res = $this->gremlin->query($query);
        $res = $res->results;
        $total = 0;
        foreach ($res as $row) {
            $namespace = preg_replace('#\\\\[^\\\\]*?$#is', '', $row->fullnspath);
            if (isset($namespacesId[$namespace])) {
                $namespaceId = $namespacesId[$namespace];
            } else {
                $namespaceId = 1;
            }
            $stmt->bindValue(':name', $row->name, \SQLITE3_TEXT);
            $stmt->bindValue(':namespaceId', $namespaceId, \SQLITE3_INTEGER);
            $stmt->execute();
            $citId[$row->fullnspath] = $sqlite->lastInsertRowID();
            // Get extends
            if (!empty($row->extends)) {
                if (isset($extendsId[$row->extends[0]])) {
                    $extendsId[$row->extends[0]][] = $citId[$row->fullnspath];
                } else {
                    $extendsId[$row->extends[0]] = array($citId[$row->fullnspath]);
                }
            }
            // Get implements
            if (!empty($row->implements)) {
                $implementsId[$citId[$row->fullnspath]] = $row->implements;
            }
            ++$total;
        }
        display("{$total} interfaces\n");
        // Traits
        $sqlQuery = <<<SQL
INSERT INTO cit ("id", "name", "namespaceId", "abstract", "final", "type") 
             VALUES ( NULL, :name, :namespaceId, 0, 0, "trait")
SQL;
        $stmt = $sqlite->prepare($sqlQuery);
        $query = <<<GREMLIN
g.V().hasLabel("Trait")
.sideEffect{ useList = []; }.where(__.out("BLOCK").out("ELEMENT").hasLabel("Use").out("USE").sideEffect{ useList.push( it.get().value("fullnspath"));}.fold() )
.map{ 
        ['fullnspath':it.get().value("fullnspath"),
         'name': it.get().vertices(OUT, "NAME").next().value("code"),
         'uses':useList
         ];
}

GREMLIN;
        $res = $this->gremlin->query($query);
        $res = $res->results;
        $total = 0;
        foreach ($res as $row) {
            $namespace = preg_replace('#\\\\[^\\\\]*?$#is', '', $row->fullnspath);
            if (isset($namespacesId[$namespace])) {
                $namespaceId = $namespacesId[$namespace];
            } else {
                $namespaceId = 1;
            }
            $stmt->bindValue(':name', $row->name, \SQLITE3_TEXT);
            $stmt->bindValue(':namespaceId', $namespaceId, \SQLITE3_INTEGER);
            $stmt->execute();
            $citId[$row->fullnspath] = $sqlite->lastInsertRowID();
            ++$total;
        }
        display("{$total} traits\n");
        // Manage extends
        $sqlQuery = <<<SQL
UPDATE cit SET extends = :class WHERE id = :id
SQL;
        $stmt = $sqlite->prepare($sqlQuery);
        $total = 0;
        foreach ($extendsId as $exId => $ids) {
            if (isset($citId[$exId])) {
                foreach ($ids as $id) {
                    $stmt->bindValue(':id', $id, \SQLITE3_INTEGER);
                    $stmt->bindValue(':class', $citId[$exId], \SQLITE3_INTEGER);
                    $stmt->execute();
                    ++$total;
                }
            }
            // Else ignore. Not in the project
        }
        display("{$total} extends \n");
        // Manage implements
        $sqlQuery = <<<SQL
INSERT INTO cit_implements ("id", "implementing", "implements", "type") 
             VALUES ( NULL, :implementing, :implements, :type)
SQL;
        $stmtImplements = $sqlite->prepare($sqlQuery);
        $total = 0;
        $stmtImplements->bindValue(':type', 'implements', \SQLITE3_TEXT);
        foreach ($implementsId as $id => $implementsFNP) {
            foreach ($implementsFNP as $fnp) {
                $stmtImplements->bindValue(':implementing', $id, \SQLITE3_INTEGER);
                if (isset($citId[$fnp])) {
                    $stmtImplements->bindValue(':implements', $citId[$fnp], \SQLITE3_INTEGER);
                    $stmtImplements->execute();
                    ++$total;
                }
                // Else ignore. Not in the project
            }
        }
        display("{$total} implements \n");
        // Manage use (traits)
        // Same SQL than for implements
        $total = 0;
        $stmtImplements->bindValue(':type', 'use', \SQLITE3_TEXT);
        foreach ($usesId as $id => $usesFNP) {
            foreach ($usesFNP as $fnp) {
                $stmtImplements->bindValue(':implementing', $id, \SQLITE3_INTEGER);
                if (substr($fnp, 0, 2) == '\\\\') {
                    $fnp = substr($fnp, 2);
                }
                if (isset($citId[$fnp])) {
                    $stmtImplements->bindValue(':implements', $citId[$fnp], \SQLITE3_INTEGER);
                    $stmtImplements->execute();
                    ++$total;
                }
                // Else ignore. Not in the project
            }
        }
        display("{$total} uses \n");
        // Methods
        $sqlite->query('DROP TABLE IF EXISTS methods');
        $sqlite->query('CREATE TABLE methods (  id INTEGER PRIMARY KEY AUTOINCREMENT,
                                                method INTEGER,
                                                citId INTEGER,
                                                static INTEGER,
                                                final INTEGER,
                                                abstract INTEGER,
                                                visibility INTEGER
                                                 )');
        $sqlQuery = <<<SQL
INSERT INTO methods ("id", "method", "citId", "static", "final", "abstract", "visibility") 
             VALUES ( NULL, :method, :citId, :static, :final, :abstract, :visibility)
SQL;
        $stmt = $sqlite->prepare($sqlQuery);
        $query = <<<GREMLIN
g.V().hasLabel("Function")
.where( __.out("NAME").hasLabel("Void").count().is(eq(0)) )
.sideEffect{ classe = ''; }.where(__.in("ELEMENT").in("BLOCK").hasLabel("Class", "Interface", "Trait").sideEffect{ classe = it.get().value("fullnspath"); }.fold() )
.filter{ classe != '';} // Removes functions, keeps methods
.map{ 
    x = ['name': it.get().value("fullcode"),
         'abstract':it.get().vertices(OUT, "ABSTRACT").any(),
         'final':it.get().vertices(OUT, "FINAL").any(),
         'static':it.get().vertices(OUT, "STATIC").any(),

         'public':it.get().vertices(OUT, "PUBLIC").any(),
         'protected':it.get().vertices(OUT, "PROTECTED").any(),
         'private':it.get().vertices(OUT, "PRIVATE").any(),         
         'class': classe
         ];
}

GREMLIN;
        $res = $this->gremlin->query($query);
        $res = $res->results;
        $total = 0;
        foreach ($res as $row) {
            if ($row->public) {
                $visibility = 'public';
            } elseif ($row->protected) {
                $visibility = 'protected';
            } elseif ($row->private) {
                $visibility = 'private';
            } else {
                $visibility = '';
            }
            $stmt->bindValue(':method', $row->name, \SQLITE3_TEXT);
            $stmt->bindValue(':citId', $citId[$row->class], \SQLITE3_INTEGER);
            $stmt->bindValue(':static', (int) $row->static, \SQLITE3_INTEGER);
            $stmt->bindValue(':final', (int) $row->final, \SQLITE3_INTEGER);
            $stmt->bindValue(':abstract', (int) $row->abstract, \SQLITE3_INTEGER);
            $stmt->bindValue(':visibility', $visibility, \SQLITE3_TEXT);
            $result = $stmt->execute();
            ++$total;
        }
        display("{$total} methods\n");
        // Properties
        $sqlite->query('DROP TABLE IF EXISTS properties');
        $sqlite->query('CREATE TABLE properties (  id INTEGER PRIMARY KEY AUTOINCREMENT,
                                                property INTEGER,
                                                citId INTEGER,
                                                visibility INTEGER,
                                                static INTEGER,
                                                value TEXT
                                                 )');
        $sqlQuery = <<<SQL
INSERT INTO properties ("id", "property", "citId", "visibility", "value", "static") 
             VALUES ( NULL, :property, :citId, :visibility, :value, :static)
SQL;
        $stmt = $sqlite->prepare($sqlQuery);
        $query = <<<GREMLIN

g.V().hasLabel("Ppp")
.sideEffect{ classe = ''; }.where(__.in("ELEMENT").in("BLOCK").hasLabel("Class", "Interface").sideEffect{ classe = it.get().value("fullnspath"); }.fold() )
.filter{ classe != '';} // Removes functions, keeps methods
.out('PPP')
.map{ 
    if (it.get().label() == 'Variable') { 
        name = it.get().value("code");
        v = ''; 
    } else { 
        name = it.get().vertices(OUT, 'LEFT').next().value("code");
        v = it.get().vertices(OUT, 'RIGHT').next().value("code");
    }

    x = ['name': name,
         'value': v,
         'static':it.get().vertices(OUT, "STATIC").any(),

         'public':it.get().vertices(OUT, "PUBLIC").any(),
         'protected':it.get().vertices(OUT, "PROTECTED").any(),
         'private':it.get().vertices(OUT, "PRIVATE").any(),
         'var':it.get().vertices(OUT, "VAR").any(),
         
         'class': classe

         ];
}

GREMLIN;
        $res = $this->gremlin->query($query);
        $res = $res->results;
        $total = 0;
        foreach ($res as $row) {
            if ($row->public) {
                $visibility = 'public';
            } elseif ($row->protected) {
                $visibility = 'protected';
            } elseif ($row->private) {
                $visibility = 'private';
            } else {
                $visibility = '';
            }
            $stmt->bindValue(':property', $row->name, \SQLITE3_TEXT);
            $stmt->bindValue(':citId', $citId[$row->class], \SQLITE3_INTEGER);
            $stmt->bindValue(':value', $row->value, \SQLITE3_TEXT);
            $stmt->bindValue(':static', (int) $row->static, \SQLITE3_INTEGER);
            $stmt->bindValue(':visibility', $visibility, \SQLITE3_TEXT);
            $result = $stmt->execute();
            ++$total;
        }
        display("{$total} properties\n");
        // Constants
        $sqlite->query('DROP TABLE IF EXISTS constants');
        $sqlite->query('CREATE TABLE constants (  id INTEGER PRIMARY KEY AUTOINCREMENT,
                                                constant INTEGER,
                                                citId INTEGER,
                                                value TEXT
                                                 )');
        $sqlQuery = <<<SQL
INSERT INTO constants ("id", "constant", "citId", "value") 
             VALUES ( NULL, :constant, :citId, :value)
SQL;
        $stmt = $sqlite->prepare($sqlQuery);
        $query = <<<GREMLIN
g.V().hasLabel("Const")
.sideEffect{ classe = ''; }.where(__.in("ELEMENT").in("BLOCK").hasLabel("Class", "Interface").sideEffect{ classe = it.get().value("fullnspath"); }.fold() )
.filter{ classe != '';} // Removes functions, keeps methods
.out('CONST')
.map{ 
    x = ['name': it.get().vertices(OUT, 'LEFT').next().value("code"),
         'value': it.get().vertices(OUT, 'RIGHT').next().value("code"),
         
         'class': classe
         ];
}

GREMLIN;
        $res = $this->gremlin->query($query);
        $res = $res->results;
        $total = 0;
        foreach ($res as $row) {
            $stmt->bindValue(':constant', $row->name, \SQLITE3_TEXT);
            $stmt->bindValue(':citId', $citId[$row->class], \SQLITE3_INTEGER);
            $stmt->bindValue(':value', $row->value, \SQLITE3_TEXT);
            $result = $stmt->execute();
            ++$total;
        }
        display("{$total} constants\n");
    }