config = new Config(); $this->config['mode'] = $mode; $this->config['local_base'] = dirname(__DIR__); } public static function fromFile($file): Config { return unserialize(file_get_contents($file)); } public static function withMode($mode = Daux::STATIC_MODE): ConfigBuilder { $builder = new ConfigBuilder($mode); $builder->loadBaseConfiguration(); return $builder; } public function with(array $values): ConfigBuilder { $this->config->merge($values); return $this; } private function setValue(&$array, $key, $value) { if (is_null($key)) { return $array = $value; } $keys = explode('.', $key); while (count($keys) > 1) { $key = array_shift($keys); if (!isset($array[$key]) || !is_array($array[$key])) { $array[$key] = []; } $array = &$array[$key]; } $array[array_shift($keys)] = $value; return $array; } public function withValues(array $values): ConfigBuilder { foreach ($values as $value) { $this->setValue($this->config, $value[0], $value[1]); } return $this; } public function withDocumentationDirectory($dir): ConfigBuilder { $this->config['docs_directory'] = $dir; return $this; } public function withValidContentExtensions(array $value): ConfigBuilder { $this->config['valid_content_extensions'] = $value; return $this; } public function withThemesPath($themePath): ConfigBuilder { $this->config['themes_path'] = $themePath; return $this; } public function withThemesDirectory($directory): ConfigBuilder { $this->config['themes_directory'] = $directory; return $this; } public function withCache(bool $value): ConfigBuilder { $this->config['cache'] = $value; return $this; } public function withFormat($format): ConfigBuilder { $this->config['format'] = $format; return $this; } public function withConfigurationOverride($file): ConfigBuilder { $this->configuration_override_file = $file; return $this; } public function withProcessor($value): ConfigBuilder { $this->config['processor'] = $value; return $this; } public function withConfluenceDelete($value): ConfigBuilder { $this->config['confluence']['delete'] = $value; return $this; } public function build(): Config { $this->initializeConfiguration(); return $this->config; } private function resolveThemeVariant() { $theme = $this->config->getHTML()->getTheme(); $themesPath = $this->config->getThemesPath() . DIRECTORY_SEPARATOR; // If theme directory exists, we're good with that if (is_dir(realpath(($themesPath . $theme)))) { return [$theme, '']; } $themePieces = explode('-', $theme); $variant = ''; // Do we have a variant or only a theme ? if (count($themePieces) > 1) { $variant = array_pop($themePieces); $theme = implode('-', $themePieces); } if (!is_dir(realpath($themesPath . $theme))) { throw new \RuntimeException("Theme '{$theme}' not found"); } return [$theme, $variant]; } /** * @param string $override_file * * @throws Exception */ private function initializeConfiguration() { // Validate and set theme path $docs_path = $this->normalizeDocumentationPath($this->config->getDocumentationDirectory()); $this->config['docs_directory'] = $docs_path; // Read documentation overrides $this->loadConfiguration($docs_path . DIRECTORY_SEPARATOR . 'config.json'); // Read command line overrides $override_file = $this->getConfigurationOverride($this->configuration_override_file); if ($override_file !== null) { $this->loadConfiguration($override_file); } // Validate and set theme path $this->withThemesPath($this->normalizeThemePath($this->config->getThemesDirectory())); // Resolve variant once $theme = $this->resolveThemeVariant(); $this->config['html']['theme'] = $theme[0]; $this->config['html']['theme-variant'] = $theme[1]; // Set a valid default timezone if ($this->config->hasTimezone()) { date_default_timezone_set($this->config->getTimezone()); } elseif (!ini_get('date.timezone')) { date_default_timezone_set('GMT'); } // Text search would be too slow on live server if ($this->config->isLive()) { $this->config['html']['search'] = false; } } private function normalizeThemePath($path) { $validPath = $this->findLocation($path, $this->config->getLocalBase(), 'dir'); if (!$validPath) { throw new Exception('The Themes directory does not exist. Check the path again : ' . $path); } return $validPath; } private function normalizeDocumentationPath($path) { $validPath = $this->findLocation($path, $this->config->getLocalBase(), 'dir'); if (!$validPath) { throw new Exception('The Docs directory does not exist. Check the path again : ' . $path); } return $validPath; } /** * Load and validate the global configuration. * * @throws Exception */ private function loadBaseConfiguration() { // Set the default configuration $this->config->merge([ 'docs_directory' => 'docs', 'valid_content_extensions' => ['md', 'markdown'], //Paths and tree 'templates' => 'templates', 'base_url' => '', ]); // Load the global configuration $this->loadConfiguration($this->config->getLocalBase() . DIRECTORY_SEPARATOR . 'global.json', false); } /** * @param string $config_file * @param bool $optional * * @throws Exception */ private function loadConfiguration($config_file, $optional = true) { if (!file_exists($config_file)) { if ($optional) { return; } throw new Exception('The configuration file is missing. Check path : ' . $config_file); } $config = json_decode(file_get_contents($config_file), true); if (!isset($config)) { throw new Exception('The configuration file "' . $config_file . '" is corrupt. Is your JSON well-formed ?'); } $this->config->merge($config); } /** * Get the file requested for configuration overrides. * * @param null|string $path * * @throws Exception * * @return null|string the path to a file to load for configuration overrides */ private function getConfigurationOverride($path) { $validPath = $this->findLocation($path, $this->config->getLocalBase(), 'file'); if ($validPath === null) { return null; } if (!$validPath) { throw new Exception('The configuration override file does not exist. Check the path again : ' . $path); } return $validPath; } /** * @param null|string $path * @param string $basedir * @param string $type * * @return null|false|string */ private function findLocation($path, $basedir, $type) { // If Path is explicitly null, it's useless to go further if ($path === null) { return null; } // VFS, used only in tests if (substr($path, 0, 6) == 'vfs://') { return $path; } // Check if it's relative to the current directory or an absolute path if (DauxHelper::is($path, $type)) { return DauxHelper::getAbsolutePath($path); } // Check if it exists relative to Daux's root $newPath = $basedir . DIRECTORY_SEPARATOR . $path; if (DauxHelper::is($newPath, $type)) { return $newPath; } return false; } }