daux.io/libs/Daux.php

280 regels
8.0 KiB
PHP

<?php namespace Todaymade\Daux;
2015-07-17 18:34:00 +02:00
use Symfony\Component\Console\Output\NullOutput;
use Todaymade\Daux\Tree\Builder;
use Todaymade\Daux\Tree\Root;
2015-04-22 12:23:57 +02:00
2015-04-23 00:32:30 +02:00
class Daux
{
const STATIC_MODE = 'DAUX_STATIC';
const LIVE_MODE = 'DAUX_LIVE';
2015-07-18 21:45:38 +02:00
/** @var string */
2015-04-23 00:32:30 +02:00
public $local_base;
2015-07-18 21:45:38 +02:00
/** @var string */
2015-07-14 23:35:47 +02:00
public $internal_base;
2015-07-18 21:45:38 +02:00
/** @var string */
2015-04-23 00:32:30 +02:00
private $docs_path;
2015-07-18 21:45:38 +02:00
/** @var Processor */
2015-07-17 18:34:00 +02:00
protected $processor;
2015-07-18 21:45:38 +02:00
/** @var Tree\Root */
2015-04-23 00:32:30 +02:00
public $tree;
2015-07-17 23:38:06 +02:00
2015-07-18 21:45:38 +02:00
/** @var Config */
2015-04-23 00:32:30 +02:00
public $options;
2015-07-18 21:45:38 +02:00
/** @var string */
2015-04-23 00:32:30 +02:00
private $mode;
2015-07-19 14:05:12 +02:00
/** @var bool */
private $merged_defaults = false;
/** @var bool */
private $merged_tree = false;
2015-07-18 21:45:38 +02:00
/**
* @param string $mode
*/
2015-04-23 00:32:30 +02:00
public function __construct($mode)
{
2015-04-23 00:32:30 +02:00
$this->mode = $mode;
2015-07-14 23:35:47 +02:00
$this->local_base = $this->internal_base = dirname(__DIR__);
2015-07-18 21:45:38 +02:00
// In case we're inside the phar archive
// we save the path to the directory
// in which it is contained
2015-07-14 23:35:47 +02:00
if (defined('PHAR_DIR')) {
$this->local_base = PHAR_DIR;
}
2015-04-23 00:32:30 +02:00
}
2015-04-23 00:32:30 +02:00
public static function initConstants()
{
define("DS", DIRECTORY_SEPARATOR);
}
2015-07-18 21:45:38 +02:00
/**
* @param string $override_file
* @throws Exception
*/
public function initialize($override_file = 'config.json')
2015-04-23 00:32:30 +02:00
{
//global.json (docs dir, markdown files)
$this->loadConfig();
//config.json
$this->loadConfigOverrides($override_file);
2015-04-23 00:32:30 +02:00
}
2015-07-18 21:45:38 +02:00
/**
* Load and validate the global configuration
*
* @throws Exception
*/
private function loadConfig()
2015-04-23 00:32:30 +02:00
{
$default_config = [
'docs_directory' => 'docs',
2015-07-19 16:36:34 +02:00
'valid_content_extensions' => ['md', 'markdown']
];
$global_config_file = $this->local_base . DS . 'global.json';
2015-04-23 00:32:30 +02:00
if (!file_exists($global_config_file)) {
throw new Exception('The Global Config file is missing. Requested File : ' . $global_config_file);
}
$default_config = array_merge($default_config, json_decode(file_get_contents($global_config_file), true));
if (!isset($default_config)) {
2015-04-23 00:32:30 +02:00
throw new Exception('The Global Config file is corrupt. Check that the JSON encoding is correct');
}
$this->docs_path = $default_config['docs_directory'];
2015-04-23 00:32:30 +02:00
if (!is_dir($this->docs_path) && !is_dir($this->docs_path = $this->local_base . DS . $this->docs_path)) {
throw new Exception('The Docs directory does not exist. Check the path again : ' . $this->docs_path);
}
$this->options = new Config();
$this->options->merge($default_config);
2015-04-23 00:32:30 +02:00
}
2015-07-17 23:38:06 +02:00
/**
* Load the configuration files, first, "config.json"
* in the documentation and then the file specified
* when running the configuration
*
* @param string $override_file
* @throws Exception
*/
2015-05-21 18:04:57 +02:00
private function loadConfigOverrides($override_file)
2015-04-23 00:32:30 +02:00
{
2015-05-21 18:04:57 +02:00
// Read documentation overrides
$config_file = $this->docs_path . DS . 'config.json';
if (file_exists($config_file)) {
$config = json_decode(file_get_contents($config_file), true);
if (!isset($config)) {
throw new Exception('The local config file is missing. Check path : ' . $config_file);
}
$this->options->merge($config);
2015-04-23 00:32:30 +02:00
}
2015-05-21 18:04:57 +02:00
// Read command line overrides
$config_file = $this->local_base . DS . $override_file;
if (!is_null($override_file) && file_exists($config_file)) {
2015-04-23 00:32:30 +02:00
$config = json_decode(file_get_contents($config_file), true);
if (!isset($config)) {
2015-05-21 18:04:57 +02:00
throw new Exception('The local config file is missing. Check path : ' . $config_file);
}
$this->options->merge($config);
2015-04-23 00:32:30 +02:00
}
2015-04-23 00:32:30 +02:00
if (isset($this->options['timezone'])) {
date_default_timezone_set($this->options['timezone']);
} elseif (!ini_get('date.timezone')) {
date_default_timezone_set('GMT');
}
2015-04-23 00:32:30 +02:00
}
2015-07-18 21:45:38 +02:00
/**
* Generate the tree that will be used
*/
2015-07-19 23:17:57 +02:00
public function generateTree()
2015-04-23 00:32:30 +02:00
{
$this->tree = new Root($this->getParams(), $this->docs_path);
Builder::build($this->tree, $this->options['ignore']);
2015-04-23 00:32:30 +02:00
if (!empty($this->options['languages'])) {
foreach ($this->options['languages'] as $key => $node) {
2015-07-18 21:45:38 +02:00
$this->tree->getEntries()[$key]->setTitle($node);
}
}
2015-04-23 00:32:30 +02:00
}
/**
2015-07-14 23:35:47 +02:00
* @return Config
*/
2015-04-23 00:32:30 +02:00
public function getParams()
{
2015-07-19 14:05:12 +02:00
if (!$this->merged_defaults) {
$default = [
//Features
'multilanguage' => !empty($this->options['languages']),
//Paths and tree
'mode' => $this->mode,
'local_base' => $this->local_base,
'docs_path' => $this->docs_path,
'templates' => $this->internal_base . DS . 'templates',
];
$this->options->conservativeMerge($default);
$this->options['index_key'] = 'index.html';
$this->options['base_page'] = $this->options['base_url'] = '';
$this->merged_defaults = true;
}
2015-04-23 00:32:30 +02:00
2015-07-19 14:05:12 +02:00
if ($this->tree && !$this->merged_tree) {
$this->options['tree'] = $this->tree;
$this->options['index'] = $this->tree->getIndexPage() ?: $this->tree->getFirstPage();
if ($this->options['multilanguage']) {
2015-04-22 12:23:57 +02:00
foreach ($this->options['languages'] as $key => $name) {
$this->options['entry_page'][$key] = $this->tree->getEntries()[$key]->getFirstPage();
2015-04-22 12:23:57 +02:00
}
} else {
$this->options['entry_page'] = $this->tree->getFirstPage();
}
2015-07-19 14:05:12 +02:00
$this->merged_tree = true;
}
return $this->options;
2015-04-22 12:23:57 +02:00
}
2015-07-17 18:34:00 +02:00
/**
* @return Processor
*/
public function getProcessor()
{
if (!$this->processor) {
$this->processor = new Processor($this, new NullOutput(), 0);
}
return $this->processor;
}
/**
* @param Processor $processor
*/
public function setProcessor(Processor $processor)
{
$this->processor = $processor;
// This is not the cleanest but it's
// the best i've found to use the
// processor in very remote places
$this->options['processor_instance'] = $processor;
}
public function getGenerators()
{
$default = [
'confluence' => '\Todaymade\Daux\Format\Confluence\Generator',
'html' => '\Todaymade\Daux\Format\HTML\Generator',
];
$extended = $this->getProcessor()->addGenerators();
return array_replace($default, $extended);
2015-07-17 18:34:00 +02:00
}
public function getProcessorClass()
{
$processor = $this->getParams()['processor'];
if (empty($processor)) {
return null;
}
$class = "\\Todaymade\\Daux\\Extension\\" . $processor;
if (!class_exists($class)) {
throw new \RuntimeException("Class '$class' not found. We cannot use it as a Processor");
}
//TODO :: check that it implements processor
return $class;
}
/**
* @return \Todaymade\Daux\Format\Base\Generator
*/
public function getGenerator()
{
$generators = $this->getGenerators();
$format = $this->getParams()['format'];
if (!array_key_exists($format, $generators)) {
throw new \RuntimeException("The format '$format' doesn't exist, did you forget to set your processor ?");
}
$class = $generators[$format];
if (!class_exists($class)) {
throw new \RuntimeException("Class '$class' not found. We cannot use it as a Generator");
}
$interface = 'Todaymade\Daux\Format\Base\Generator';
if (!in_array('Todaymade\Daux\Format\Base\Generator', class_implements($class))) {
throw new \RuntimeException("The class '$class' does not implement the '$interface' interface");
}
return new $class($this);
}
2015-04-23 00:32:30 +02:00
}