<commit_before><?php

namespace Platformsh\Cli\Service;

use Platformsh\Cli\Util\NestedArrayUtil;
use Symfony\Component\Yaml\Yaml;

/**
 * Configuration used throughout the CLI.
 */
class Config
{
    private $config;
    private $defaultsFile;
    private $env;
    private $fs;
    private $version;
    private $homeDir;

    /**
     * @param array|null  $env
     * @param string|null $defaultsFile
     */
    public function __construct(array $env = null, $defaultsFile = null)
    {
        $this->env = $env !== null ? $env : $this->getDefaultEnv();

        $this->defaultsFile = $defaultsFile ?: CLI_ROOT . '/config.yaml';
        $this->config = $this->loadConfigFromFile($this->defaultsFile);

        // Load the session ID from a file.
        $sessionIdFile = $this->getSessionIdFile();
        if (\file_exists($sessionIdFile)) {
            $id = \file_get_contents($sessionIdFile);
            if ($id !== false) {
                try {
                    $this->validateSessionId(\trim($id));
                } catch (\InvalidArgumentException $e) {
                    throw new \InvalidArgumentException('Invalid session ID in file: ' . $sessionIdFile);
                }
                $this->config['api']['session_id'] = \trim($id);
            }
        }

        $this->applyUserConfigOverrides();
        $this->applyEnvironmentOverrides();

        // Validate the session ID.
        if (isset($this->config['api']['session_id'])) {
            $this->validateSessionId($this->config['api']['session_id']);
        }
    }

    /**
     * Find all current environment variables.
     *
     * @return array
     */
    private function getDefaultEnv()
    {
        return PHP_VERSION_ID >= 70100 ? getenv() : $_ENV;
    }

    /**
     * Check if a configuration value is defined.
     *
     * @param string $name    The configuration name (e.g. 'application.name').
     * @param bool   $notNull Set false to treat null configuration values as
     *                        defined.
     *
     * @return bool
     */
    public function has($name, $notNull = true)
    {
        $value = NestedArrayUtil::getNestedArrayValue($this->config, explode('.', $name), $exists);

        return $exists && (!$notNull || $value !== null);
    }

    /**
     * Get a configuration value.
     *
     * @param string $name The configuration name (e.g. 'application.name').
     *
     * @throws \RuntimeException if the configuration is not defined.
     *
     * @return null|string|bool|array
     */
    public function get($name)
    {
        $value = NestedArrayUtil::getNestedArrayValue($this->config, explode('.', $name), $exists);
        if (!$exists) {
            throw new \RuntimeException('Configuration not defined: ' . $name);
        }

        return $value;
    }

    /**
     * Get a configuration value, specifying a default if it does not exist.
     *
     * @param string $name
     * @param mixed  $default
     *
     * @return mixed
     */
    public function getWithDefault($name, $default)
    {
        $value = NestedArrayUtil::getNestedArrayValue($this->config, explode('.', $name), $exists);
        if (!$exists) {
            return $default;
        }

        return $value;
    }

    /**
     * Returns the user's home directory.
     *
     * @param bool $reset Reset the static cache.
     *
     * @return string The absolute path to the user's home directory
     */
    public function getHomeDirectory($reset = false)
    {
        if (!$reset && isset($this->homeDir)) {
            return $this->homeDir;
        }
        $prefix = isset($this->config['application']['env_prefix']) ? $this->config['application']['env_prefix'] : '';
        $envVars = [$prefix . 'HOME', 'HOME', 'USERPROFILE'];
        foreach ($envVars as $envVar) {
            $value = getenv($envVar);
            if (array_key_exists($envVar, $this->env)) {
                $value = $this->env[$envVar];
            }
            if (is_string($value) && $value !== '') {
                if (!is_dir($value)) {
                    throw new \RuntimeException(
                        sprintf('Invalid environment variable %s: %s (not a directory)', $envVar, $value)
                    );
                }
                $this->homeDir = realpath($value) ?: $value;
                return $this->homeDir;
            }
        }

        throw new \RuntimeException(sprintf('Could not determine home directory. Set the %s environment variable.', $prefix . 'HOME'));
    }

    /**
     * Get the directory where the CLI is normally installed and configured.
     *
     * @param bool $absolute Whether to return an absolute path. If false,
     *                       the path will be relative to the home directory.
     *
     * @return string
     */
    public function getUserConfigDir($absolute = true)
    {
        $path = $this->get('application.user_config_dir');

        return $absolute ? $this->getHomeDirectory() . DIRECTORY_SEPARATOR . $path : $path;
    }

    /**
     * @return \Platformsh\Cli\Service\Filesystem
     */
    private function fs()
    {
        return $this->fs ?: new Filesystem();
    }

    /**
     * @return string
     */
    public function getWritableUserDir()<commit_msg>Clarify home directory environment variables on error<commit_after><?php

namespace Platformsh\Cli\Service;

use Platformsh\Cli\Util\NestedArrayUtil;
use Symfony\Component\Yaml\Yaml;

/**
 * Configuration used throughout the CLI.
 */
class Config
{
    private $config;
    private $defaultsFile;
    private $env;
    private $fs;
    private $version;
    private $homeDir;

    /**
     * @param array|null  $env
     * @param string|null $defaultsFile
     */
    public function __construct(array $env = null, $defaultsFile = null)
    {
        $this->env = $env !== null ? $env : $this->getDefaultEnv();

        $this->defaultsFile = $defaultsFile ?: CLI_ROOT . '/config.yaml';
        $this->config = $this->loadConfigFromFile($this->defaultsFile);

        // Load the session ID from a file.
        $sessionIdFile = $this->getSessionIdFile();
        if (\file_exists($sessionIdFile)) {
            $id = \file_get_contents($sessionIdFile);
            if ($id !== false) {
                try {
                    $this->validateSessionId(\trim($id));
                } catch (\InvalidArgumentException $e) {
                    throw new \InvalidArgumentException('Invalid session ID in file: ' . $sessionIdFile);
                }
                $this->config['api']['session_id'] = \trim($id);
            }
        }

        $this->applyUserConfigOverrides();
        $this->applyEnvironmentOverrides();

        // Validate the session ID.
        if (isset($this->config['api']['session_id'])) {
            $this->validateSessionId($this->config['api']['session_id']);
        }
    }

    /**
     * Find all current environment variables.
     *
     * @return array
     */
    private function getDefaultEnv()
    {
        return PHP_VERSION_ID >= 70100 ? getenv() : $_ENV;
    }

    /**
     * Check if a configuration value is defined.
     *
     * @param string $name    The configuration name (e.g. 'application.name').
     * @param bool   $notNull Set false to treat null configuration values as
     *                        defined.
     *
     * @return bool
     */
    public function has($name, $notNull = true)
    {
        $value = NestedArrayUtil::getNestedArrayValue($this->config, explode('.', $name), $exists);

        return $exists && (!$notNull || $value !== null);
    }

    /**
     * Get a configuration value.
     *
     * @param string $name The configuration name (e.g. 'application.name').
     *
     * @throws \RuntimeException if the configuration is not defined.
     *
     * @return null|string|bool|array
     */
    public function get($name)
    {
        $value = NestedArrayUtil::getNestedArrayValue($this->config, explode('.', $name), $exists);
        if (!$exists) {
            throw new \RuntimeException('Configuration not defined: ' . $name);
        }

        return $value;
    }

    /**
     * Get a configuration value, specifying a default if it does not exist.
     *
     * @param string $name
     * @param mixed  $default
     *
     * @return mixed
     */
    public function getWithDefault($name, $default)
    {
        $value = NestedArrayUtil::getNestedArrayValue($this->config, explode('.', $name), $exists);
        if (!$exists) {
            return $default;
        }

        return $value;
    }

    /**
     * Returns the user's home directory.
     *
     * @param bool $reset Reset the static cache.
     *
     * @return string The absolute path to the user's home directory
     */
    public function getHomeDirectory($reset = false)
    {
        if (!$reset && isset($this->homeDir)) {
            return $this->homeDir;
        }
        $prefix = isset($this->config['application']['env_prefix']) ? $this->config['application']['env_prefix'] : '';
        $envVars = [$prefix . 'HOME', 'HOME', 'USERPROFILE'];
        foreach ($envVars as $envVar) {
            $value = getenv($envVar);
            if (array_key_exists($envVar, $this->env)) {
                $value = $this->env[$envVar];
            }
            if (is_string($value) && $value !== '') {
                if (!is_dir($value)) {
                    throw new \RuntimeException(
                        sprintf('Invalid environment variable %s: %s (not a directory)', $envVar, $value)
                    );
                }
                $this->homeDir = realpath($value) ?: $value;
                return $this->homeDir;
            }
        }

        throw new \RuntimeException(sprintf('Could not determine home directory (environment variables checked: %s)', implode(', ', $envVars)));
    }

    /**
     * Get the directory where the CLI is normally installed and configured.
     *
     * @param bool $absolute Whether to return an absolute path. If false,
     *                       the path will be relative to the home directory.
     *
     * @return string
     */
    public function getUserConfigDir($absolute = true)
    {
        $path = $this->get('application.user_config_dir');

        return $absolute ? $this->getHomeDirectory() . DIRECTORY_SEPARATOR . $path : $path;
    }

    /**
     * @return \Platformsh\Cli\Service\Filesystem
     */
    private function fs()
    {
        return $this->fs ?: new Filesystem();
    }

    /**
     * @return string
     */
    public function getWritableUserDir()
{'fraction_non_alphanumeric': 0.13547472838923005, 'fraction_numerical': 0.000944733112895607, 'mean_word_length': 2.0048254328697133, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2449617', 'n_tokens_mistral': 2954, 'n_tokens_neox': 2882, 'n_words': 744}