diff --git a/RoboFile.php b/RoboFile.php new file mode 100644 index 0000000..8ff0e4b --- /dev/null +++ b/RoboFile.php @@ -0,0 +1,332 @@ +prepare(); + $this->lint(); + $this->phploc(TRUE); + $this->phpcs(TRUE); + $this->dependencyReport(); + $this->phpcpdReport(); + } + + /** + * Run all tests, generate coverage, generate docs, generate code statistics + */ + public function build() + { + $this->analyze(); + $this->coverage(); + $this->docs(); + } + + /** + * Cleanup temporary files + */ + public function clean() + { + $cleanFiles = [ + 'build/humbug.json', + 'build/humbug-log.txt', + ]; + array_map(function ($file) { + @unlink($file); + }, $cleanFiles); + + // So the task doesn't complain, + // make any 'missing' dirs to cleanup + array_map(function ($dir) { + if ( ! is_dir($dir)) + { + `mkdir -p {$dir}`; + } + }, $this->cleanDirs); + + $this->_cleanDir($this->cleanDirs); + $this->_deleteDir($this->cleanDirs); + } + + /** + * Run unit tests and generate coverage reports + */ + public function coverage() + { + $this->taskPhpUnit() + ->configFile('build/phpunit.xml') + ->printed(true) + ->run(); + } + + /** + * Generate documentation with phpdox + */ + public function docs() + { + $cmd_parts = [ + 'cd build', + '../vendor/bin/phpdox', + 'cd ..' + ]; + $this->_run($cmd_parts, ' && '); + } + + /** + * Verify that source files are valid + */ + public function lint() + { + $files = $this->getAllSourceFiles(); + + $chunks = array_chunk($files, (int)`getconf _NPROCESSORS_ONLN`); + + foreach($chunks as $chunk) + { + $this->parallelLint($chunk); + } + } + + + /** + * Run mutation tests with humbug + * + * @param bool $stats - if true, generates stats rather than running mutation tests + */ + public function mutate($stats = FALSE) + { + $test_parts = [ + 'vendor/bin/humbug' + ]; + + $stat_parts = [ + 'vendor/bin/humbug', + '--skip-killed=yes', + '-v', + './build/humbug.json' + ]; + + $cmd_parts = ($stats) ? $stat_parts : $test_parts; + $this->_run($cmd_parts); + } + + /** + * Run the phpcs tool + * + * @param bool $report - if true, generates reports instead of direct output + */ + public function phpcs($report = FALSE) + { + $dir = __DIR__; + + $report_cmd_parts = [ + 'vendor/bin/phpcs', + "--standard=./build/CodeIgniter", + "--report-checkstyle=./build/logs/phpcs.xml", + ]; + + $normal_cmd_parts = [ + 'vendor/bin/phpcs', + "--standard=./build/CodeIgniter", + ]; + + $cmd_parts = ($report) ? $report_cmd_parts : $normal_cmd_parts; + + $this->_run($cmd_parts); + } + + /** + * Run the phploc tool + * + * @param bool $report - if true, generates reports instead of direct output + */ + public function phploc($report = FALSE) + { + // Command for generating reports + $report_cmd_parts = [ + 'vendor/bin/phploc', + '--count-tests', + '--log-csv=build/logs/phploc.csv', + '--log-xml=build/logs/phploc.xml', + 'src', + 'tests' + ]; + + // Command for generating direct output + $normal_cmd_parts = [ + 'vendor/bin/phploc', + '--count-tests', + 'src', + 'tests' + ]; + + $cmd_parts = ($report) ? $report_cmd_parts : $normal_cmd_parts; + + $this->_run($cmd_parts); + } + + /** + * Create temporary directories + */ + public function prepare() + { + array_map([$this, '_mkdir'], $this->taskDirs); + } + + /** + * Lint php files and run unit tests + */ + public function test() + { + $this->lint(); + $this->taskPHPUnit() + ->configFile('phpunit.xml') + ->printed(true) + ->run(); + } + + /** + * Watches for file updates, and automatically runs appropriate actions + */ + public function watch() + { + $this->taskWatch() + ->monitor('composer.json', function() { + $this->taskComposerUpdate()->run(); + }) + ->monitor('src', function () { + $this->taskExec('test')->run(); + }) + ->monitor('tests', function () { + $this->taskExec('test')->run(); + }) + ->run(); + } + + /** + * Create pdepend reports + */ + protected function dependencyReport() + { + $cmd_parts = [ + 'vendor/bin/pdepend', + '--jdepend-xml=build/logs/jdepend.xml', + '--jdepend-chart=build/pdepend/dependencies.svg', + '--overview-pyramid=build/pdepend/overview-pyramid.svg', + 'src' + ]; + $this->_run($cmd_parts); + } + + /** + * Get the total list of source files, including tests + * + * @return array + */ + protected function getAllSourceFiles() + { + $files = array_merge( + glob_recursive('build/*.php'), + glob_recursive('src/*.php'), + glob_recursive('tests/*.php'), + glob('*.php') + ); + + sort($files); + + return $files; + } + + /** + * Run php's linter in one parallel task for the passed chunk + * + * @param array $chunk + */ + protected function parallelLint(array $chunk) + { + $task = $this->taskParallelExec() + ->timeout(5) + ->printed(FALSE); + + foreach($chunk as $file) + { + $task = $task->process("php -l {$file}"); + } + + $task->run(); + } + + /** + * Generate copy paste detector report + */ + protected function phpcpdReport() + { + $cmd_parts = [ + 'vendor/bin/phpcpd', + '--log-pmd build/logs/pmd-cpd.xml', + 'src' + ]; + $this->_run($cmd_parts); + } + + /** + * Shortcut for joining an array of command arguments + * and then running it + * + * @param array $cmd_parts - command arguments + * @param string $join_on - what to join the command arguments with + */ + protected function _run(array $cmd_parts, $join_on = ' ') + { + $this->taskExec(implode($join_on, $cmd_parts))->run(); + } +} \ No newline at end of file diff --git a/autoload.php b/autoload.php deleted file mode 100644 index 405933b..0000000 --- a/autoload.php +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/build/CodeIgniter/ruleset.xml b/build/CodeIgniter/ruleset.xml new file mode 100644 index 0000000..e943a4b --- /dev/null +++ b/build/CodeIgniter/ruleset.xml @@ -0,0 +1,84 @@ + + + A variation of the CodeIgniter standard + + ../../src/ + + utf-8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build/docker_install.sh b/build/docker_install.sh index 5c25333..63e1fe3 100644 --- a/build/docker_install.sh +++ b/build/docker_install.sh @@ -10,7 +10,7 @@ set -xe # Install git (the php image doesn't have it) which is required by composer apt-get update -yqq -apt-get install git libpq-dev libmysqlclient18 unzip -yqq +apt-get install git libpq-dev libmysqlclient18 unzip firebird2.5-superclassic -yqq # Install phpunit, the tool that we will use for testing curl -Lo /usr/local/bin/phpunit https://phar.phpunit.de/phpunit.phar @@ -25,4 +25,5 @@ mv "$DIR/../tests/settings-ci.json" "$DIR/../tests/settings.json" docker-php-ext-install pdo_mysql docker-php-ext-install pdo_pgsql #docker-php-ext-install pdo_oci -#docker-php-ext-install interbase +docker-php-ext-install interbase +docker-php-ext-install pdo_firebird diff --git a/build/header_comment.txt b/build/header_comment.txt new file mode 100644 index 0000000..6fd37bc --- /dev/null +++ b/build/header_comment.txt @@ -0,0 +1,13 @@ +/** + * Query + * + * SQL Query Builder / Database Abstraction Layer + * + * PHP version 5.4 + * + * @package Query + * @author Timothy J. Warren + * @copyright 2012 - 2015 Timothy J. Warren + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link https://git.timshomepage.net/aviat4ion/Query + */ diff --git a/build/phpdox.xml b/build/phpdox.xml index a5f4e9c..edcdc07 100644 --- a/build/phpdox.xml +++ b/build/phpdox.xml @@ -99,6 +99,7 @@ + diff --git a/build/phpunit.xml b/build/phpunit.xml index 87e74da..bebea28 100644 --- a/build/phpunit.xml +++ b/build/phpunit.xml @@ -31,16 +31,15 @@ ../tests/databases/firebird/FirebirdTest.php ../tests/databases/firebird/FirebirdQBTest.php - + - - + \ No newline at end of file diff --git a/composer.json b/composer.json index 1cfe787..b0bddb1 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,28 @@ "require": { "php": ">=5.4" }, + "require-dev": { + "consolidation/robo": "1.0.0-RC2", + "humbug/humbug": "1.0.0-alpha2", + "monolog/monolog": "^1.21", + "nikic/php-parser": "v3.0.0alpha1", + "pdepend/pdepend": "^2.2", + "phploc/phploc": "^3.0", + "phpmd/phpmd": "^2.4", + "phpunit/phpunit": "^5.5", + "sebastian/phpcpd": "^2.0", + "squizlabs/php_codesniffer": "^3.0.0@RC", + "theseer/phpdox": "^0.9.0" + }, "autoload": { - "files": ["autoload.php"] + "psr-4": { + "Query\\": "src/Query" + }, + "files": ["src/common.php"] + }, + "autoload-dev": { + "psr-4" : { + "CodeIgniter\\": "build/CodeIgniter" + } } } diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..4a660aa --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,39 @@ + + + + + src + autoload.php + + + + + tests/core/core_test.php + tests/core/query_parser_test.php + tests/core/connection_manager_test.php + + + tests/databases/mysql/MySQLTest.php + tests/databases/mysql/MySQLQBTest.php + + + tests/databases/pgsql/PgSQLTest.php + tests/databases/pgsql/PgSQLQBTest.php + + + tests/databases/sqlite/SQLiteTest.php + tests/databases/sqlite/SQLiteQBTest.php + + + tests/databases/firebird/FirebirdTest.php + tests/databases/firebird/FirebirdQBTest.php + + + + \ No newline at end of file diff --git a/src/common.php b/src/common.php index 8e39a72..af45910 100644 --- a/src/common.php +++ b/src/common.php @@ -12,6 +12,10 @@ * @license http://philsturgeon.co.uk/code/dbad-license */ +use Query\ConnectionManager; + +require __DIR__ . '/../vendor/autoload.php'; + // -------------------------------------------------------------------------- /** @@ -64,7 +68,7 @@ if ( ! function_exists('db_filter')) */ function db_filter($array, $index) { - $new_array = array(); + $new_array = []; foreach($array as $a) { @@ -87,7 +91,8 @@ if ( ! function_exists('from_camel_case')) * @param string $input * @return string */ - function from_camel_case($input) { + function from_camel_case($input) + { preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches); $ret = $matches[0]; foreach ($ret as &$match) { @@ -112,7 +117,7 @@ if ( ! function_exists('array_zipper')) */ function array_zipper(Array $zipper_input) { - $output = array(); + $output = []; foreach($zipper_input as $append_key => $values) { @@ -120,7 +125,7 @@ if ( ! function_exists('array_zipper')) { if ( ! isset($output[$index])) { - $output[$index] = array(); + $output[$index] = []; } $output[$index][$append_key] = $value; } @@ -144,7 +149,7 @@ if ( ! function_exists('array_column')) */ function array_column(Array $array, $key) { - $output = array(); + $output = []; // No point iterating over an empty array if (empty($array)) @@ -208,24 +213,26 @@ if ( ! function_exists('Query')) * connection created. * * @param string|object|array $params - * @return Query\Query_Builder|null + * @return Query\QueryBuilder|null */ function Query($params = '') { - $cmanager = \Query\ConnectionManager::get_instance(); + $manager = ConnectionManager::get_instance(); // If you are getting a previously created connection if (is_scalar($params)) { - return $cmanager->get_connection($params); + return $manager->get_connection($params); } elseif ( ! is_scalar($params) && ! is_null($params)) { $params_object = (object) $params; // Otherwise, return a new connection - return $cmanager->connect($params_object); + return $manager->connect($params_object); } + + return NULL; } } // End of common.php \ No newline at end of file diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 2927f3e..c080b03 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -11,6 +11,18 @@ * @license http://philsturgeon.co.uk/code/dbad-license */ +use PHPUnit\Framework\TestCase; + +/** + * Unit test bootstrap - Using phpunit + */ +define('QTEST_DIR', realpath(__DIR__)); +define('QBASE_DIR', realpath(QTEST_DIR.'/../') . '/'); +define('QDS', DIRECTORY_SEPARATOR); + +// Set up autoloader +require_once(QBASE_DIR . 'vendor/autoload.php'); + // -------------------------------------------------------------------------- /** @@ -30,16 +42,6 @@ if ( ! defined('IS_QUERCUS')) } } -/** - * Unit test bootstrap - Using phpunit - */ -define('QTEST_DIR', realpath(__DIR__)); -define('QBASE_DIR', realpath(QTEST_DIR.'/../') . '/'); -define('QDS', DIRECTORY_SEPARATOR); - -// Include db classes -require_once(QBASE_DIR . 'autoload.php'); - function get_json_config() { $files = array( @@ -61,7 +63,7 @@ function get_json_config() /** * Base class for TestCases */ -class Query_TestCase extends PHPUnit_Framework_TestCase { +class Query_TestCase extends TestCase { /** * Wrapper for Simpletest's assertEqual @@ -117,9 +119,7 @@ $path = QTEST_DIR.QDS.'db_files'.QDS.'test_sqlite.db'; @unlink($path); // Require base testing classes -//require_once(QTEST_DIR . '/core/core_test.php'); require_once(QTEST_DIR . '/core/base_db_test.php'); -//require_once(QTEST_DIR . '/core/query_parser_test.php'); require_once(QTEST_DIR . '/core/base_query_builder_test.php');