diff --git a/.gitignore b/.gitignore index 910c0ff1..f03762d1 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ src-tmp/ .phpunit.result.cache ./qit _tests/**/*.zip -_tests/**/*.txt \ No newline at end of file +_tests/**/*.txt +dev/ \ No newline at end of file diff --git a/qit b/qit index 0c1f100a..22164073 100755 Binary files a/qit and b/qit differ diff --git a/src/src/Config.php b/src/src/Config.php index b97e2358..f4a4443d 100644 --- a/src/src/Config.php +++ b/src/src/Config.php @@ -166,56 +166,42 @@ public static function get_qit_dir(): string { // Allow override. if ( ! empty( getenv( 'QIT_HOME' ) ) ) { - if ( ! file_exists( getenv( 'QIT_HOME' ) ) ) { - throw new \RuntimeException( sprintf( 'The QIT_HOME environment variable is defined, but points to a non-existing directory: %s', getenv( 'QIT_CLI_CONFIG_DIR' ) ) ); - } - - return $normalize_path( getenv( 'QIT_HOME' ) ); - } - - // Windows. - if ( is_windows() ) { + $parent_config_dir = getenv( 'QIT_HOME' ); + } elseif ( is_windows() ) { if ( empty( getenv( 'APPDATA' ) ) ) { - throw new \RuntimeException( 'The APPDATA or QIT_HOME environment variables must be defined.' ); + throw new \RuntimeException( 'The APPDATA or QIT_HOME environment variables must be defined in Windows.' ); } - - return $normalize_path( getenv( 'APPDATA' ) ) . 'woo-qit-cli'; - } - - if ( empty( getenv( 'HOME' ) ) ) { - throw new \RuntimeException( 'The HOME or QIT_HOME environment variables must be defined.' ); - } - - $home = $normalize_path( getenv( 'HOME' ) ); - $dirs = []; - - if ( static::use_xdg() ) { - $xdg_config = getenv( 'XDG_CONFIG_HOME' ); - if ( ! $xdg_config ) { - $xdg_config = $home . '.config'; + $parent_config_dir = getenv( 'APPDATA' ); + } elseif ( ! empty( getenv( 'HOME' ) ) ) { + $home = $normalize_path( getenv( 'HOME' ) ); + if ( static::use_xdg() ) { + $xdg_config = getenv( 'XDG_CONFIG_HOME' ) ?: $home . '.config'; + $parent_config_dir = $xdg_config; + } else { + $parent_config_dir = $home; } - - $dirs[] = $xdg_config . '/woo-qit-cli/'; + } else { + throw new \RuntimeException( 'The HOME, APPDATA, or QIT_HOME environment variables must be defined.' ); } - $dirs[] = $home . 'woo-qit-cli/'; - - foreach ( $dirs as $dir ) { - if ( is_dir( $dir ) ) { - return $dir; - } + // Normalize and append 'woo-qit-cli/' to the parent directory. + $qit_dir = $normalize_path( $parent_config_dir ) . 'woo-qit-cli/'; - $dir_created = mkdir( $dir, 0700, true ); - - if ( $dir_created ) { - return $dir; - } + // Create the directory if it does not exist. + if ( ! is_dir( $qit_dir ) && ! mkdir( $qit_dir, 0700, true ) ) { + throw new \RuntimeException( "Unable to create the QIT CLI directory: $qit_dir" ); } - throw new \RuntimeException( "You need to set an environment variable 'QIT_HOME' pointing to a writable directory where the QIT CLI can write it's config file. Do NOT use a directory inside your plugin, as the config file will hold sensitive information that should not be included in your plugin." ); + return $qit_dir; } + protected static function use_xdg(): bool { + if ( defined( 'UNIT_TESTS' ) && UNIT_TESTS ) { + if ( App::getVar( 'MIMICK_XDG' ) ) { + return true; + } + } foreach ( array_keys( $_SERVER ) as $key ) { if ( strpos( $key, 'XDG_' ) === 0 ) { return true; diff --git a/src/src/helpers.php b/src/src/helpers.php index 9c9a576a..ed27292e 100644 --- a/src/src/helpers.php +++ b/src/src/helpers.php @@ -3,6 +3,11 @@ namespace QIT_CLI; function is_windows(): bool { + if ( defined( 'UNIT_TESTS' ) && UNIT_TESTS ) { + if ( App::getVar( 'MIMICK_WINDOWS' ) ) { + return true; + } + } return defined( 'PHP_WINDOWS_VERSION_BUILD' ); } diff --git a/src/tests/ConfigTest.php b/src/tests/ConfigTest.php new file mode 100644 index 00000000..bea0db26 --- /dev/null +++ b/src/tests/ConfigTest.php @@ -0,0 +1,110 @@ + getenv( 'QIT_HOME' ), + 'APPDATA' => getenv( 'APPDATA' ), + 'HOME' => getenv( 'HOME' ), + 'XDG_CONFIG_HOME' => getenv( 'XDG_CONFIG_HOME' ), + ]; + } + + // Reset environment variables to a default state for testing. + putenv( 'QIT_HOME=' ); + putenv( 'APPDATA=' ); + putenv( 'HOME=' ); + putenv( 'XDG_CONFIG_HOME=' ); + + $this->testDir = __DIR__ . '/data/config/'; + } + + protected function tearDown(): void { + // Restore original environment variables. + foreach ( static::$originalEnvVars as $var => $value ) { + if ( $value === false ) { + putenv( $var ); + } else { + putenv( "$var=$value" ); + } + } + App::offsetUnset( 'MIMICK_WINDOWS' ); + App::offsetUnset( 'MIMICK_XDG' ); + } + + public function test_get_qit_dir_with_qit_home_override(): void { + $expectedDir = $this->testDir . 'woo-qit-cli/'; + + foreach ( [ 'windows', 'unix' ] as $os ) { + if ( $os === 'windows' ) { + App::setVar( 'MIMICK_WINDOWS', true ); + } else { + App::offsetUnset( 'MIMICK_WINDOWS' ); + } + + // Regular. + putenv( 'QIT_HOME=' . $this->testDir ); + $this->assertEquals( $expectedDir, Config::get_qit_dir() ); + + // Missing trailing slash. + putenv( 'QIT_HOME=' . rtrim( $this->testDir, '/' ) ); + $this->assertEquals( $expectedDir, Config::get_qit_dir() ); + + // Windows directory separator - Non windows. + putenv( 'QIT_HOME=' . str_replace( '/', '\\', $this->testDir ) ); + $this->assertEquals( $expectedDir, Config::get_qit_dir() ); + + // Windows directory separator missing trailing slash - Non windows. + putenv( 'QIT_HOME=' . rtrim( str_replace( '/', '\\', $this->testDir ), '\\' ) ); + $this->assertEquals( $expectedDir, Config::get_qit_dir() ); + } + } + + public function test_get_qit_dir_on_windows(): void { + App::setVar( 'MIMICK_WINDOWS', true ); + + putenv( 'APPDATA=' . $this->testDir ); + $expectedDir = $this->testDir . 'woo-qit-cli/'; + $this->assertEquals( $expectedDir, Config::get_qit_dir() ); + + // Simulate Windows environment + putenv( 'APPDATA=' . str_replace( '/', '\\', $this->testDir ) ); + $this->assertEquals( $expectedDir, Config::get_qit_dir() ); + } + + public function test_get_qit_dir_with_home(): void { + putenv( 'HOME=' . $this->testDir ); + $expectedDir = $this->testDir . 'woo-qit-cli/'; + $this->assertEquals( $expectedDir, Config::get_qit_dir() ); + + // Simulate Windows separator. + putenv( 'HOME=' . str_replace( '/', '\\', $this->testDir ) ); + $this->assertEquals( $expectedDir, Config::get_qit_dir() ); + } + + public function test_get_qit_dir_with_home_and_xdg(): void { + putenv( 'HOME=' . $this->testDir ); + putenv( 'XDG_CONFIG_HOME=' . $this->testDir . '.config' ); + App::setVar( 'MIMICK_XDG', true ); + $expectedDir = $this->testDir . '.config/woo-qit-cli/'; + $this->assertEquals( $expectedDir, Config::get_qit_dir() ); + } + + public function test_get_qit_dir_throws_if_needed(): void { + putenv( 'QIT_HOME' ); + putenv( 'APPDATA' ); + putenv( 'HOME' ); + putenv( 'XDG_CONFIG_HOME' ); + + $this->expectException( \RuntimeException::class ); + Config::get_qit_dir(); + } +}