Example #1
0
    public static function finalize()
    {
        if (!file_exists('nodes.csv')) {
            return false;
        }
        fclose(static::$fp_rels);
        fclose(static::$fp_nodes);
        $config = \Exakat\Config::factory();
        $res = shell_exec(<<<SHELL

cd ./batch-import
java -server -Dfile.encoding=UTF-8 -Xmx4G -jar target/batch-import-jar-with-dependencies.jar {$config->neo4j_folder}/data/graph.db ../nodes.csv ../rels.csv 2>/dev/null
cd {$config->neo4j_folder}
./bin/neo4j restart
sleep 1

SHELL
);
        $context_options = array('http' => array('method' => 'GET', 'ignore_errors' => true, 'header' => <<<HEADER
Content-type: application/json
Accept: application/json
User-Agent: Exakat v 1.0

HEADER
));
        $context = stream_context_create($context_options);
        $config = \Exakat\Config::factory();
        $response = file_get_contents('http://' . $config->neo4j_host . ':' . $config->neo4j_port . '/db/data/', false, $context);
        if (strpos($response, 'NOT_FOUND') !== false) {
            $response = file_get_contents('http://' . $config->neo4j_host . ':' . $config->neo4j_port . '/db/data/', false, $context);
        }
        preg_match("/Importing (\\d+) Nodes/is", $res, $nodes);
        preg_match("/Importing (\\d+) Relationships/is", $res, $relations);
        $fnodes = -1;
        $fp = fopen('nodes.csv', 'r');
        while (fgetcsv($fp, 100000, "\t", '"')) {
            ++$fnodes;
        }
        fclose($fp);
        $frels = -1;
        $fp = fopen('rels.csv', 'r');
        while (fgetcsv($fp, 1000, "\t", '"')) {
            ++$frels;
        }
        fclose($fp);
        if ($fnodes != $nodes[1]) {
            display("Warning : didn't import enough nodes : {$fnodes} expected, {$nodes[1]} actually imported\n");
        } else {
            display("{$nodes[1]} nodes imported\n");
            display(number_format(filesize('nodes.csv') / 1024, 0) . " ko imported\n");
            unlink('nodes.csv');
        }
        if ($frels != $relations[1]) {
            display("Warning : didn't import enough relations : {$frels} expected, {$relations[1]} actually imported\n");
        } else {
            display("{$relations[1]} relations imported\n");
            unlink('rels.csv');
        }
        return true;
    }
Example #2
0
 public function __construct()
 {
     $this->config = Config::factory();
     $analyzers = Analyzer::getThemeAnalyzers($this->config->thema);
     $this->themesList = '("' . implode('", "', $analyzers) . '")';
     $this->sqlite = new \Sqlite3($this->config->projects_root . '/projects/' . $this->config->project . '/dump.sqlite', \SQLITE3_OPEN_READONLY);
     $this->datastore = new Datastore($this->config);
 }
Example #3
0
 public function __construct($analyzer)
 {
     $config = Config::factory();
     $this->analyzer = $analyzer;
     $filename = $config->dir_root . '/human/' . $this->language . '/' . str_replace('\\', '/', str_replace('Exakat\\Analyzer\\', '', $analyzer)) . '.ini';
     if (file_exists($filename)) {
         $this->ini = parse_ini_file($filename) + $this->ini;
     }
     // else is the default values already defined above
 }
Example #4
0
function display_r($object)
{
    static $config;
    if ($config === null) {
        $config = \Exakat\Config::factory();
    }
    if ($config->verbose) {
        print_r($object);
    }
}
Example #5
0
 public function hasResults()
 {
     $config = Config::factory();
     foreach ($config->other_php_versions as $version) {
         $r = Analyzer::$datastore->getRow('compilation' . $version);
         if (count($r) > 0) {
             return true;
         }
     }
     return false;
 }
Example #6
0
 public function __construct()
 {
     $config = Config::factory();
     if ($config->is_phar) {
         $this->phar_tmp = tempnam(sys_get_temp_dir(), 'exzendf2') . '.sqlite';
         copy($config->dir_root . '/data/zendf2.sqlite', $this->phar_tmp);
         $docPath = $this->phar_tmp;
     } else {
         $docPath = $config->dir_root . '/data/zendf2.sqlite';
     }
     $this->sqlite = new \Sqlite3($docPath, SQLITE3_OPEN_READONLY);
 }
Example #7
0
 public function generate($folder, $name = 'txt')
 {
     $config = Config::factory();
     $themes = $config->thema;
     $analyzers = array();
     foreach ($themes as $theme) {
         $analyzers[] = Analyzer::getThemeAnalyzers($theme);
     }
     $analyzers = call_user_func_array('array_merge', $analyzers);
     display(count($analyzers) . " analyzers\n");
     $res = $this->sqlite->query('SELECT distinct analyzer FROM results WHERE analyzer IN ("' . implode('","', $analyzers) . '") ORDER BY analyzer');
     $skeleton = array();
     while ($row = $res->fetchArray(SQLITE3_ASSOC)) {
         $skeleton[$row['analyzer']] = 0;
     }
     display(count($skeleton) . " distinct analyzers\n");
     $titles = array();
     foreach ($skeleton as $analyzer => $foo) {
         if ($analyzer == 'total') {
             continue;
         }
         $ini = parse_ini_file($this->config->dir_root . '/human/en/' . $analyzer . '.ini');
         $titles[$analyzer] = '"' . $ini['name'] . '"';
     }
     $all = array();
     $res = $this->sqlite->query('SELECT * FROM results WHERE analyzer IN ("' . implode('","', $analyzers) . '") ORDER BY file');
     $total = 0;
     while ($row = $res->fetchArray(SQLITE3_ASSOC)) {
         if (!isset($all[$row['file']])) {
             $all[$row['file']] = $skeleton;
         }
         ++$all[$row['file']][$row['analyzer']];
         ++$total;
     }
     display($total . " issues read\n");
     $txt = " \t" . implode("\t", array_values($titles)) . "\n";
     foreach ($all as $file => $values) {
         $txt .= "{$file}\t" . implode("\t", array_values($values)) . "\n";
     }
     file_put_contents($folder . '/' . $name . '.' . self::FILE_EXTENSION, $txt);
     display(count($all) . " issues reported\n");
     print "Upload " . $name . '.' . self::FILE_EXTENSION . " on http://amp.pharm.mssm.edu/clustergrammer/\n";
 }
Example #8
0
function run($test, $number)
{
    print "{$test}.{$number}\n";
    $ini = parse_ini_file('../../projects/test/config.ini');
    $phpversion = empty($ini['phpversion']) ? phpversion() : $ini['phpversion'];
    include_once '../../library/Exakat/Phpexec.php';
    include_once '../../library/Exakat/Config.php';
    $config = \Exakat\Config::factory(array('foo', '-p', 'test'));
    $versionPHP = 'php' . str_replace('.', '', $phpversion);
    $shell = $config->{$versionPHP} . ' -l ./source/' . $test . '.' . $number . '.php';
    $res = shell_exec($shell);
    if (strpos('No syntax errors detected in', $res) !== false) {
        print "This script doesn't compile with " . PHP_VERSION . " .\n";
        return;
    }
    $shell = 'cd ../..; php exakat cleandb; php exakat load -f ./tests/tokenizer/source/' . $test . '.' . $number . '.php -p test; php exakat export -text -f ./tests/tokenizer/exp/' . "{$test}.{$number}" . '.txt';
    $res = shell_exec($shell);
    if (preg_match("/Warning : (.*?)\n/is", $res, $r) !== 0) {
        print "{$test} {$number} has some warning : {$r['1']}\n";
        return;
    }
    if (!file_exists('./exp/' . "{$test}.{$number}" . '.txt')) {
        print "This script has no exp file.\n";
        return;
    }
    if (filesize('./exp/' . "{$test}.{$number}" . '.txt') == 0) {
        unlink('./exp/' . "{$test}.{$number}" . '.txt');
        print "This script has an empty exp file.\n";
        return;
    }
    $exp = file_get_contents('./exp/' . "{$test}.{$number}" . '.txt');
    if (strpos($exp, 'Parse error') !== false) {
        print "This script doesn't compile.\n";
        return;
    }
    if (strpos($exp, 'Label : NEXT') !== false) {
        print "There are some unprocessed link in this script\n";
        return;
    }
}
Example #9
0
 public function query($query, $params = array(), $load = array())
 {
     $fields = array('query' => $query);
     if (isset($params) && !empty($params)) {
         $fields['params'] = $params;
     }
     $fields_string = json_encode($fields);
     $ch = curl_init();
     static $neo4j_host, $neo4j_auth;
     if (!isset($neo4j_host)) {
         $config = \Exakat\Config::factory();
         $neo4j_host = $config->neo4j_host . ':' . $config->neo4j_port;
         if ($config->neo4j_login !== '') {
             $neo4j_auth = base64_encode($config->neo4j_login . ':' . $config->neo4j_password);
         } else {
             $neo4j_auth = '';
         }
     }
     //set the url, number of POST vars, POST data
     $headers = array('Accept: application/json;stream=true', 'Content-type: application/json', 'Content-Length: ' . strlen($fields_string));
     if (!empty($neo4j_auth)) {
         $headers[] = 'Authorization: Basic ' . $neo4j_auth;
     }
     curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
     curl_setopt($ch, CURLOPT_URL, 'http://' . $neo4j_host . '/db/data/cypher');
     curl_setopt($ch, CURLOPT_POST, true);
     curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
     curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
     //execute post
     $result = curl_exec($ch);
     //close connection
     curl_close($ch);
     if (isset($result->message)) {
         throw new \Exception($result->message);
     }
     return json_decode($result);
 }
Example #10
0
    public function generate($dirName, $fileName = null)
    {
        $sqlite = new \sqlite3($dirName . '/dump.sqlite', \SQLITE3_OPEN_READONLY);
        $sqlQuery = <<<SQL
SELECT  id AS id,
        fullcode AS code, 
        file AS file, 
        line AS line,
        analyzer AS analyzer
    FROM results 
    WHERE analyzer IN {$this->themesList}

SQL;
        $res = $sqlite->query($sqlQuery);
        $config = Config::factory();
        $datastore = new Datastore($config);
        $items = array();
        while ($row = $res->fetchArray(SQLITE3_ASSOC)) {
            $ini = parse_ini_file($config->dir_root . '/human/en/' . $row['analyzer'] . '.ini');
            $row['error'] = $ini['name'];
            $a = Analyzer::getInstance($row['analyzer']);
            $row['severity'] = $a->getSeverity();
            $row['impact'] = $a->getTimeToFix();
            $row['recipes'] = $a->getThemes();
            $items[] = $row;
            $this->count();
        }
        if ($fileName === null) {
            $json = json_encode($items, JSON_PARTIAL_OUTPUT_ON_ERROR);
            // @todo Log if $json == false
            return $json;
        } else {
            file_put_contents($dirName . '/' . $fileName . '.' . self::FILE_EXTENSION, json_encode($items));
            return true;
        }
    }
Example #11
0
        }
    }
    public static function autoload_test($name)
    {
        $path = dirname(__DIR__);
        $file = $path . '/tests/analyzer/' . str_replace('\\', DIRECTORY_SEPARATOR, $name) . '.php';
        if (file_exists($file)) {
            include $file;
        }
        $file = $path . '/tests/tokenizer/' . str_replace('\\', DIRECTORY_SEPARATOR, $name) . '.php';
        if (file_exists($file)) {
            include $file;
        }
    }
    public static function autoload_phpunit($name)
    {
        $file = 'Test/' . str_replace('_', '/', str_replace('Test\\', '', $name)) . '.php';
        if (file_exists($file)) {
            include $file;
        }
    }
}
spl_autoload_register('Autoload::autoload_library');
require_once __DIR__ . '/../vendor/autoload.php';
// depending on your project this may not be necessary
if (isset($argv)) {
    $config = \Exakat\Config::factory($argv);
} else {
    $config = \Exakat\Config::factory($GLOBALS['argv']);
}
include 'helpers.php';
Example #12
0
    private function init_project($project, $repositoryURL)
    {
        if (!file_exists($this->config->projects_root . '/projects/' . $project)) {
            mkdir($this->config->projects_root . '/projects/' . $project, 0755);
        } else {
            display($this->config->projects_root . '/projects/' . $project . ' already exists. Reusing' . "\n");
        }
        if (!file_exists($this->config->projects_root . '/projects/' . $project . '/log/')) {
            mkdir($this->config->projects_root . '/projects/' . $project . '/log/', 0755);
        } else {
            display($this->config->projects_root . '/projects/' . $project . '/log/ already exists. Ignoring' . "\n");
            return null;
        }
        $this->datastore = new Datastore(Config::factory(), Datastore::CREATE);
        if (!file_exists($this->config->projects_root . '/projects/' . $project . '/config.ini')) {
            if ($this->config->symlink === true) {
                $vcs = 'symlink';
            } elseif ($this->config->svn === true) {
                $vcs = 'svn';
            } elseif ($this->config->git === true) {
                $vcs = 'git';
            } elseif ($this->config->copy === true) {
                $vcs = 'copy';
            } elseif ($this->config->bzr === true) {
                $vcs = 'bzr';
            } elseif ($this->config->hg === true) {
                $vcs = 'hg';
            } elseif ($this->config->composer === true) {
                $vcs = 'composer';
            } else {
                $vcs = 'git';
            }
            // default initial config. Found in test project.
            $configIni = <<<INI
phpversion = 7.1

ignore_dirs[] = /test
ignore_dirs[] = /tests
ignore_dirs[] = /Tests
ignore_dirs[] = /Test
ignore_dirs[] = /example
ignore_dirs[] = /examples
ignore_dirs[] = /docs
ignore_dirs[] = /doc
ignore_dirs[] = /tmp
ignore_dirs[] = /version
ignore_dirs[] = /vendor
ignore_dirs[] = /js
ignore_dirs[] = /lang
ignore_dirs[] = /data
ignore_dirs[] = /css
ignore_dirs[] = /cache
ignore_dirs[] = /vendor
ignore_dirs[] = /assets
ignore_dirs[] = /spec
ignore_dirs[] = /sql

file_extensions =

project_name        = "{$project}";
project_url         = "{$repositoryURL}";
project_vcs         = "{$vcs}";
project_description = "";
project_packagist   = "";

INI;
            file_put_contents($this->config->projects_root . '/projects/' . $project . '/config.ini', $configIni);
        } else {
            display($this->config->projects_root . '/projects/' . $project . '/config.ini already exists. Ignoring' . "\n");
        }
        shell_exec('chmod -R g+w ' . $this->config->projects_root . '/projects/' . $project);
        $repositoryDetails = parse_url($repositoryURL);
        $skipFiles = false;
        if (!file_exists($this->config->projects_root . '/projects/' . $project . '/code/')) {
            switch (true) {
                // Symlink
                case $this->config->symlink === true:
                    display('Symlink initialization : ' . realpath($repositoryURL));
                    symlink(realpath($repositoryURL), $this->config->projects_root . '/projects/' . $project . '/code');
                    break 1;
                    // Empty initialization
                // Empty initialization
                case $this->config->copy === true:
                    display('Copy initialization');
                    $total = copyDir(realpath($repositoryURL), $this->config->projects_root . '/projects/' . $project . '/code');
                    display($total . ' files were copied');
                    break 1;
                    // Empty initialization
                // Empty initialization
                case $repositoryURL === '' || $repositoryURL === false:
                    display('Empty initialization');
                    break 1;
                    // composer archive (early in the list, as this won't have 'scheme'
                // composer archive (early in the list, as this won't have 'scheme'
                case $this->config->composer === true:
                    display('Initialization with composer');
                    $res = shell_exec('composer --version');
                    if (strpos($res, 'Composer') === false) {
                        throw new HelperException('Composer');
                    }
                    // composer install
                    $composer = new \stdClass();
                    $composer->require = new \stdClass();
                    $composer->require->{$repositoryURL} = 'dev-master';
                    $json = json_encode($composer);
                    mkdir($this->config->projects_root . '/projects/' . $project . '/code', 0755);
                    file_put_contents($this->config->projects_root . '/projects/' . $project . '/code/composer.json', $json);
                    shell_exec('cd ' . $this->config->projects_root . '/projects/' . $project . '/code; composer -q install');
                    break 1;
                    // SVN
                // SVN
                case isset($repositoryDetails['scheme']) && $repositoryDetails['scheme'] == 'svn' || $this->config->svn === true:
                    $res = shell_exec('svn --version');
                    if (strpos($res, 'svn') === false) {
                        throw new HelperException('SVN');
                    }
                    display('SVN initialization');
                    shell_exec('cd ' . $this->config->projects_root . '/projects/' . $project . '; svn checkout ' . escapeshellarg($repositoryURL) . ' code');
                    break 1;
                    // Bazaar
                // Bazaar
                case $this->config->bzr === true:
                    $res = shell_exec('bzr --version');
                    if (strpos($res, 'Bazaar') === false) {
                        throw new HelperException('Bazar');
                    }
                    display('Bazaar initialization');
                    shell_exec('cd ' . $this->config->projects_root . '/projects/' . $project . '; bzr branch ' . escapeshellarg($repositoryURL) . ' code');
                    break 1;
                    // HG
                // HG
                case $this->config->hg === true:
                    $res = shell_exec('hg --version');
                    if (strpos($res, 'Mercurial') === false) {
                        throw new HelperException('Mercurial');
                    }
                    display('Mercurial initialization');
                    shell_exec('cd ' . $this->config->projects_root . '/projects/' . $project . '; hg clone ' . escapeshellarg($repositoryURL) . ' code');
                    break 1;
                    // Tbz archive
                // Tbz archive
                case $this->config->tbz === true:
                    display('Download the tar.bz2');
                    $binary = file_get_contents($repositoryURL);
                    display('Saving');
                    $archiveFile = tempnam(sys_get_temp_dir(), 'archiveTgz') . '.tgz';
                    file_put_contents($archiveFile, $binary);
                    display('Unarchive');
                    shell_exec('tar -jxf ' . $archiveFile . ' --directory ' . $this->config->projects_root . '/projects/' . $project . '/code/');
                    display('Cleanup');
                    unlink($archiveFile);
                    break 1;
                    // tgz archive
                // tgz archive
                case $this->config->tgz === true:
                    display('Download the tar.gz');
                    $binary = file_get_contents($repositoryURL);
                    display('Saving');
                    $archiveFile = tempnam(sys_get_temp_dir(), 'archiveTgz') . '.tgz';
                    file_put_contents($archiveFile, $binary);
                    display('Unarchive');
                    mkdir($this->config->projects_root . '/projects/' . $project . '/code/');
                    shell_exec('tar -zxf ' . $archiveFile . ' -C ' . $this->config->projects_root . '/projects/' . $project . '/code/');
                    display('Cleanup');
                    unlink($archiveFile);
                    break 1;
                    // zip archive
                // zip archive
                case $this->config->zip === true:
                    $res = shell_exec('zip --version');
                    if (strpos($res, 'Zip') === false) {
                        throw new HelperException('zip');
                    }
                    display('Download the zip');
                    $binary = file_get_contents($repositoryURL);
                    display('Saving');
                    $archiveFile = tempnam(sys_get_temp_dir(), 'archiveZip') . '.zip';
                    file_put_contents($archiveFile, $binary);
                    display('Unzip');
                    shell_exec('unzip ' . $archiveFile . ' -d ' . $this->config->projects_root . '/projects/' . $project . '/code/');
                    display('Cleanup');
                    unlink($archiveFile);
                    break 1;
                    // Git
                    // Git is last, as it will act as a default
                // Git
                // Git is last, as it will act as a default
                case isset($repositoryDetails['scheme']) && $repositoryDetails['scheme'] == 'git' || $this->config->git === true:
                    $res = shell_exec('git --version');
                    if (strpos($res, 'git') === false) {
                        throw new HelperException('git');
                    }
                    display('Git initialization');
                    $res = shell_exec('cd ' . $this->config->projects_root . '/projects/' . $project . '; git clone -q ' . $repositoryURL . ' code 2>&1 ');
                    if (($offset = strpos($res, 'fatal: ')) !== false) {
                        $this->datastore->addRow('hash', array('init error' => trim(substr($res, $offset + 7))));
                        display("An error prevented code initialization : " . trim(substr($res, $offset + 7)) . "\nNo code was loaded.\n");
                        $skipFiles = true;
                    }
                    break 1;
                default:
                    display('No Initialization');
            }
        } elseif (file_exists($this->config->projects_root . '/projects/' . $project . '/code/')) {
            display("Code folder is already there. Leaving it intact.\n");
        }
        display("Counting files\n");
        $this->datastore->addRow('hash', array('status' => 'Initproject'));
        if (!$skipFiles) {
            display("Running files\n");
            $analyze = new Files($this->gremlin, $this->config);
            $analyze->run();
            unset($analyze);
        }
    }
Example #13
0
 public function getTimeToFix()
 {
     if (Analyzer::$docs === null) {
         $config = Config::factory();
         Analyzer::$docs = new Docs($config->dir_root . '/data/analyzers.sqlite');
     }
     return Analyzer::$docs->getTimeToFix($this->analyzer);
 }
Example #14
0
    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);
    }
Example #15
0
    public function run()
    {
        $progress = 0;
        $project = $this->config->project;
        $this->project_dir = $this->config->projects_root . '/projects/' . $project;
        if ($this->config->project == "default") {
            throw new ProjectNeeded();
        }
        if (!file_exists($this->config->projects_root . '/projects/' . $project)) {
            throw new NoSuchProject($this->config->project);
        }
        // cleaning log directory (possibly logs)
        $logs = glob($this->config->projects_root . '/projects/' . $project . '/log/*');
        foreach ($logs as $log) {
            unlink($log);
        }
        $this->logTime('Start');
        $this->addSnitch(array('step' => 'Start', 'project' => $this->config->project));
        // cleaning datastore
        $this->datastore = new Datastore($this->config, Datastore::CREATE);
        $audit_start = time();
        $this->datastore->addRow('hash', array('audit_start' => $audit_start, 'exakat_version' => Exakat::VERSION, 'exakat_build' => Exakat::BUILD));
        display("Running project '{$project}'\n");
        display("Cleaning DB\n");
        $analyze = new CleanDb($this->gremlin, $this->config, Tasks::IS_SUBTASK);
        $analyze->run();
        unset($analyze);
        $this->logTime('CleanDb');
        $this->addSnitch(array('step' => 'Clean DB', 'project' => $this->config->project));
        display("Search for external libraries\n");
        $args = array(1 => 'findextlib', 2 => '-p', 3 => $this->config->project, 4 => '-u');
        $configThema = Config::push($args);
        $analyze = new FindExternalLibraries($this->gremlin, $configThema, Tasks::IS_SUBTASK);
        $analyze->run();
        $this->addSnitch(array('step' => 'External lib', 'project' => $this->config->project));
        Config::pop();
        unset($analyze);
        display("Running files\n");
        $analyze = new Files($this->gremlin, $this->config, Tasks::IS_SUBTASK);
        $analyze->run();
        unset($analyze);
        $this->logTime('Files');
        $this->addSnitch(array('step' => 'Files', 'project' => $this->config->project));
        $this->checkTokenLimit();
        $analyze = new Load($this->gremlin, $this->config, Tasks::IS_SUBTASK);
        $analyze->run();
        unset($analyze);
        display("Project loaded\n");
        $this->logTime('Loading');
        // paralell running
        exec($this->config->php . ' ' . $this->config->executable . ' magicnumber -p ' . $this->config->project . '   > /dev/null &');
        $this->addSnitch(array('step' => 'Magic Numbers', 'project' => $this->config->project));
        // Dump is a child process
        shell_exec($this->config->php . ' ' . $this->config->executable . ' dump -p ' . $this->config->project);
        foreach ($this->themes as $theme) {
            $this->addSnitch(array('step' => 'Analyze : ' . $theme, 'project' => $this->config->project));
            $themeForFile = strtolower(str_replace(' ', '_', trim($theme, '"')));
            $args = array(1 => 'analyze', 2 => '-p', 3 => $this->config->project, 4 => '-T', 5 => trim($theme, '"'), 6 => '-norefresh', 7 => '-u');
            try {
                $configThema = Config::push($args);
                $analyze = new Analyze($this->gremlin, $configThema, Tasks::IS_SUBTASK);
                $analyze->run();
                unset($analyze);
                rename($this->config->projects_root . '/projects/' . $project . '/log/analyze.log', $this->config->projects_root . '/projects/' . $project . '/log/analyze.' . $themeForFile . '.log');
                Config::pop();
                $args = array(1 => 'dump', 2 => '-p', 3 => $this->config->project, 4 => '-T', 5 => trim($theme, '"'), 6 => '-u');
                $configThema = Config::push($args);
                $dump = new Dump($this->gremlin, $configThema, Tasks::IS_SUBTASK);
                $dump->run();
                unset($dump);
                Config::pop();
            } catch (\Exception $e) {
                echo "Error while running the Analyze {$theme} \n", $e->getMessage(), "\nTrying next analysis\n";
                file_put_contents($this->config->projects_root . '/projects/' . $project . '/log/analyze.' . $themeForFile . '.final.log', $e->getMessage());
            }
        }
        display("Analyzed project\n");
        $this->logTime('Analyze');
        $this->addSnitch(array('step' => 'Analyzed', 'project' => $this->config->project));
        $this->logTime('Analyze');
        $oldConfig = Config::factory();
        foreach ($this->reports as $reportName => $formats) {
            foreach ($formats as $format => $fileName) {
                display("Reporting {$reportName} in {$format}\n");
                $this->addSnitch(array('step' => 'Report : ' . $format, 'project' => $this->config->project));
                $args = array(1 => 'report', 2 => '-p', 3 => $this->config->project, 4 => '-file', 5 => $fileName, 6 => '-format', 7 => $format);
                $this->config = Config::factory($args);
                try {
                    $report = new Report2($this->gremlin, $this->config, Tasks::IS_SUBTASK);
                    $report->run();
                    unset($report);
                } catch (\Exception $e) {
                    echo "Error while building {$reportName} in {$format} \n", $e->getMessage(), "\nTrying next report\n";
                }
            }
        }
        Config::factory($oldConfig);
        display("Reported project\n");
        $audit_end = time();
        // measure Neo4j's final size
        $res = shell_exec('du -sh ' . $this->config->neo4j_folder . ' 2>/dev/null');
        $neo4jSize = trim(str_replace(basename($this->config->neo4j_folder), '', $res));
        $this->datastore->addRow('hash', array('audit_end' => $audit_end, 'audit_length' => $audit_end - $audit_start, 'neo4jSize' => $neo4jSize));
        $query = <<<GREMLIN
g.V().where( __.sideEffect{x = []; }.in('ANALYZED').sideEffect{ x.add(it.get().value('analyzer')); }.barrier().sideEffect{ y = x.groupBy().findAll{ i,j -> j.size() > 1;};} )
.filter{ y.size() > 0; }
.map{ y; };
GREMLIN;
        $res = $this->gremlin->query($query);
        if (!empty($res)) {
            file_put_contents($this->config->projects_root . '/projects/' . $project . '/log/doublons.log', var_export($res, true));
        }
        $this->logTime('Final');
        $this->removeSnitch();
        display("End\n");
    }
Example #16
0
 public static function findFiles($path, &$files, &$ignoredFiles)
 {
     $config = Config::factory();
     $ignore_dirs = $config->ignore_dirs;
     $dir = $config->project;
     // Actually finding the files
     $ignoreDirs = array();
     foreach ($ignore_dirs as $ignore) {
         if ($ignore[0] == '/') {
             $d = $config->projects_root . '/projects/' . $dir . '/code' . $ignore;
             if (!file_exists($d)) {
                 continue;
             }
             $ignoreDirs[] = $ignore . '.*';
         } else {
             $ignoreDirs[] = '.*' . $ignore . '.*';
         }
     }
     if (empty($ignoreDirs)) {
         $regex = '';
     } else {
         $regex = '#^(' . implode('|', $ignoreDirs) . ')#';
     }
     $php = new Phpexec();
     $ignoredFiles = array();
     $d = getcwd();
     if (!file_exists($path)) {
         display("No such file as " . $path . " when looking for files\n");
         $files = array();
         $ignoredFiles = array();
         return;
     }
     chdir($path);
     $files = rglob('.');
     chdir($d);
     $exts = $config->file_extensions;
     foreach ($files as $id => &$file) {
         $file = substr($file, 1);
         $ext = pathinfo($file, PATHINFO_EXTENSION);
         if (empty($ext)) {
             // it's OK.
         } elseif (!in_array($ext, $exts)) {
             // selection of extensions
             unset($files[$id]);
             $ignoredFiles[$file] = "Ignored extension ({$ext})";
         } elseif (!empty($regex) && preg_match($regex, $file)) {
             // Matching the 'ignored dir' pattern
             unset($files[$id]);
             $ignoredFiles[$file] = 'Ignored dir';
         } elseif ($php->countTokenFromFile($path . $file) < 2) {
             unset($files[$id]);
             $ignoredFiles[$file] = 'Not a PHP File';
         }
     }
 }
Example #17
0
 protected function Dashboard($title)
 {
     $css = new \Stdclass();
     $css->displayTitles = true;
     $css->titles = array('Library', 'Folder', 'Home page');
     $css->readOrder = $css->titles;
     $titles = array('Code Smells' => 'Analyze', 'Dead Code' => 'Dead code', 'Security' => 'Security', 'Performances' => 'Performances');
     $list = Analyzer::getThemeAnalyzers($titles[$title]);
     $where = 'WHERE analyzer in ("' . implode('", "', $list) . '")';
     $res = $this->dump->query('SELECT severity, count(*) AS nb FROM results ' . $where . ' GROUP BY severity ORDER BY severity');
     $severities = array();
     while ($row = $res->fetchArray(\SQLITE3_ASSOC)) {
         $severities[$row['severity']] = array('severity' => $row['severity'], 'count' => $row['nb']);
     }
     $res = $this->dump->query('SELECT analyzer, count(*) AS nb, severity AS severity FROM results ' . $where . ' GROUP BY analyzer');
     $listBySeverity = array();
     $config = Config::factory();
     while ($row = $res->fetchArray(\SQLITE3_ASSOC)) {
         $ini = parse_ini_file($config->dir_root . '/human/en/' . $row['analyzer'] . '.ini');
         $listBySeverity[] = array('name' => $ini['name'], 'severity' => $row['severity'], 'count' => $row['nb']);
     }
     uasort($listBySeverity, function ($a, $b) {
         $s = array('Critical' => 6, 'Major' => 5, 'Middle' => 4, 'Minor' => 3, 'None' => 0);
         if ($s[$a['severity']] > $s[$b['severity']]) {
             return -1;
         } elseif ($s[$a['severity']] < $s[$b['severity']]) {
             return 1;
         } else {
             return 0;
         }
     });
     $listBySeverity = array_slice($listBySeverity, 0, 5);
     $res = $this->dump->query('SELECT file, count(*) AS nb FROM results ' . $where . ' GROUP BY file ORDER BY count(*) DESC LIMIT 5');
     $listByFile = array();
     while ($row = $res->fetchArray(\SQLITE3_ASSOC)) {
         $listByFile[] = array('name' => $row['file'], 'severity' => '', 'count' => $row['nb']);
     }
     $info = array('upLeft' => $severities, 'upRight' => '&nbsp;', 'downLeft' => $listBySeverity, 'downRight' => $listByFile);
     return $this->formatDashboard($info, $css);
 }
Example #18
0
 private static function saveTokenCounts()
 {
     $config = Config::factory();
     $datastore = new Datastore($config);
     $datastore->addRow('tokenCounts', static::$tokenCounts);
 }
Example #19
0
 public function generic_test($file)
 {
     list($analyzer, $number) = explode('.', $file);
     $analyzer = str_replace('_', '/', $analyzer);
     // Test are run with test project.
     $ini = parse_ini_file('../../projects/test/config.ini');
     $phpversion = empty($ini['phpversion']) ? phpversion() : $ini['phpversion'];
     $test_config = str_replace('_', '/', substr(get_class($this), 5));
     // initialize Config (needed by phpexec)
     $config = \Exakat\Config::factory(array('foo', '-p', 'test'));
     $analyzerobject = ExakatAnalyzer::getInstance($test_config);
     if (!$analyzerobject->checkPhpVersion($phpversion)) {
         $this->markTestSkipped('Needs version ' . $analyzerobject->getPhpVersion() . '.');
     }
     require 'exp/' . str_replace('_', '/', $file) . '.php';
     $versionPHP = 'php' . str_replace('.', '', $phpversion);
     $res = shell_exec($config->{$versionPHP} . ' -l ./source/' . str_replace('_', '/', $file) . '.php 2>/dev/null');
     if (strpos($res, 'No syntax errors detected') === false) {
         $this->markTestSkipped('Compilation problem : "' . $res . '".');
     }
     $Php = new Phpexec($phpversion);
     if (!$analyzerobject->checkPhpConfiguration($Php)) {
         $message = array();
         $confs = $analyzerobject->getPhpConfiguration();
         if (is_array($confs)) {
             foreach ($confs as $name => $value) {
                 $confs[] = "{$name} => {$value}";
             }
             $confs = join(', ', $confs);
         }
         $this->markTestSkipped('Needs configuration : ' . $confs . '.');
     }
     $analyzer = escapeshellarg($test_config);
     $source = 'source/' . str_replace('_', '/', $file) . '.php';
     if (is_dir($source)) {
         $shell = 'cd ../..; php exakat test -r -d ./tests/analyzer/' . $source . ' -P ' . $analyzer . ' -p test -q -o -json';
     } else {
         $shell = 'cd ../..; php exakat test    -f ./tests/analyzer/' . $source . ' -P ' . $analyzer . ' -p test -q -o -json';
     }
     $shell_res = shell_exec($shell);
     $res = json_decode($shell_res);
     if ($res === null) {
         $this->assertTrue(false, "Json couldn't be decoded : '{$shell_res}'\n{$shell}");
     }
     if (empty($res)) {
         $list = array();
     } else {
         $list = array();
         foreach ($res as $r) {
             $list[] = $r[0];
         }
         $this->assertNotEquals(count($list), 0, 'No values were read from the analyzer');
     }
     if (isset($expected) && is_array($expected)) {
         $missing = array();
         foreach ($expected as $e) {
             if (($id = array_search($e, $list)) !== false) {
                 unset($list[$id]);
             } else {
                 $missing[] = $e;
             }
         }
         $list = array_map(function ($x) {
             return str_replace("'", "\\'", $x);
         }, $list);
         $this->assertEquals(count($missing), 0, count($missing) . " expected values were not found :\n '" . join("',\n '", $missing) . "'\n\nin the " . count($list) . " received values of \n '" . join("', \n '", $list) . "'\n\nsource/{$file}.php\nexp/{$file}.php\nphpunit --filter={$number} Test/{$analyzer}.php\n\n");
         // also add a phpunit --filter to rerun it easily
     }
     if (isset($expected_not) && is_array($expected)) {
         $extra = array();
         foreach ($expected_not as $e) {
             if ($id = array_search($e, $list)) {
                 $extra[] = $e;
                 unset($list[$id]);
             }
         }
         // the not expected
         $this->assertEquals(count($extra), 0, count($extra) . " values were found and shouldn't be : " . join(', ', $extra) . "");
     }
     // the remainings
     $this->assertEquals(count($list), 0, count($list) . " values were found and are unprocessed : " . join(', ', $list) . "");
 }
Example #20
0
 public function __construct($phpversion = null)
 {
     $config = Config::factory();
     if ($phpversion === null) {
         $phpversion = $config->phpversion;
     }
     $this->requestedVersion = substr($phpversion, 0, 3);
     $this->version = $phpversion;
     $phpversion3 = substr($phpversion, 0, 3);
     $this->isCurrentVersion = substr(PHP_VERSION, 0, 3) === $phpversion3;
     if ($this->isCurrentVersion === true) {
         preg_match('/^(\\d\\.\\d+\\.\\d+)$/', PHP_VERSION, $r);
         $this->actualVersion = $r[1];
         if (substr($this->actualVersion, 0, 3) !== $this->requestedVersion) {
             throw new NoPhpBinary('PHP binary for version ' . $this->requestedVersion . ' (' . $_SERVER['_'] . ') doesn\'t have the right middle version : "' . $this->actualVersion . '". Please, check config/exakat.ini');
         }
     }
     switch ($phpversion3) {
         case '5.2':
             $this->phpexec = $config->php52;
             break 1;
         case '5.3':
             $this->phpexec = $config->php53;
             break 1;
         case '5.4':
             $this->phpexec = $config->php54;
             break 1;
         case '5.5':
             $this->phpexec = $config->php55;
             break 1;
         case '5.6':
             $this->phpexec = $config->php56;
             break 1;
         case '7.0':
             $this->phpexec = $config->php70;
             break 1;
         case '7.1':
             $this->phpexec = $config->php71;
             break 1;
         case '7.2':
             $this->phpexec = $config->php72;
             break 1;
         default:
             $this->phpexec = $config->php;
             // PHP will be always valid if we use the one that is currently executing us
             $this->actualVersion = PHP_VERSION;
     }
     if (preg_match('/^php:(.+?)$/', $this->phpexec)) {
         $folder = $config->projects_root;
         $res = shell_exec('docker run -it --rm --name php4exakat -v "$PWD":' . $folder . ' -w ' . $folder . ' ' . $this->phpexec . ' php -v 2>&1');
         if (substr($res, 0, 4) !== 'PHP ') {
             throw new NoPhpBinary('Error when accessing Docker\'s PHP : "' . $res . '". Please, check config/exakat.ini');
         } else {
             $this->phpexec = 'docker run -it --rm --name php4exakat -v "$PWD":' . $folder . ' -w ' . $folder . ' ' . $this->phpexec . ' php ';
         }
     } else {
         if (empty($this->phpexec)) {
             throw new NoPhpBinary('No PHP binary for version ' . $phpversion . ' is available. Please, check config/exakat.ini');
         }
         if (!file_exists($this->phpexec)) {
             throw new NoPhpBinary('PHP binary for version ' . $phpversion . ' is not valid : "' . $this->phpexec . '". Please, check config/exkat.ini');
         }
         if (!is_executable($this->phpexec)) {
             throw new NoPhpBinary('PHP binary for version ' . $phpversion . ' exists but is not executable : "' . $this->phpexec . '". Please, check config/exakat.ini');
         }
     }
 }