daux.io/libs/Tree/Builder.php

253 regels
6.8 KiB
PHP

<?php namespace Todaymade\Daux\Tree;
use RuntimeException;
use SplFileInfo;
2015-07-17 18:28:54 +02:00
use Todaymade\Daux\DauxHelper;
2015-04-23 00:32:30 +02:00
class Builder
{
protected static $IGNORED = [
// Popular VCS Systems
'.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg',
// Operating system files
'.DS_Store', 'Thumbs.db',
];
2015-08-16 22:26:00 +02:00
protected static function isIgnored(\SplFileInfo $file, $ignore)
{
$filename = $file->getFilename();
if (in_array($filename, static::$IGNORED)) {
return true;
}
if (array_key_exists('folders', $ignore) && $file->isDir() && in_array($filename, $ignore['folders'])) {
return true;
}
if (array_key_exists('files', $ignore) && !$file->isDir() && in_array($filename, $ignore['files'])) {
return true;
}
return false;
}
/**
* Get name for a file
*
* @param string $path
* @return string
*/
protected static function getName($path)
{
// ['dir' => 1, 'basename' => 2, 'filename' => 3, 'extension' => 5]
preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $m);
if (!isset($m[3])) {
2016-07-27 21:32:51 +02:00
throw new RuntimeException('Name not found');
}
return $m[3];
}
2015-07-17 23:38:06 +02:00
/**
* Build the initial tree
*
* @param Directory $node
2015-07-17 23:38:06 +02:00
* @param array $ignore
*/
public static function build($node, $ignore)
2015-04-23 00:32:30 +02:00
{
if (($it = new \FilesystemIterator($node->getPath())) == false) {
return;
}
if ($node instanceof Root) {
// Ignore config.json in the root directory
$ignore['files'][] = 'config.json';
}
/** @var \SplFileInfo $file */
foreach ($it as $file) {
if (static::isIgnored($file, $ignore)) {
continue;
}
if ($file->isDir()) {
$title = static::removeSortingInformations($file->getFilename());
$new = new Directory($node, $title, $file);
$new->setName(static::getName($file->getPathName()));
2015-10-28 00:01:41 +01:00
$new->setTitle(str_replace('_', ' ', static::removeSortingInformations($new->getName())));
static::build($new, $ignore);
$index = $new->getLocalIndexPage();
if ($index && $index->getTitle() != $title) {
$new->setTitle($index->getTitle());
}
} else {
static::createContent($node, $file);
}
}
$node->sort();
}
/**
* @param Directory $parent
* @param SplFileInfo $file
* @return Content|Raw
*/
public static function createContent(Directory $parent, SplFileInfo $file)
{
$name = static::getName($file->getPathname());
2015-07-19 16:36:34 +02:00
$config = $parent->getConfig();
if (!in_array($file->getExtension(), $config['valid_content_extensions'])) {
$uri = $file->getFilename();
2015-08-02 15:42:23 +02:00
$entry = new Raw($parent, $uri, $file);
2015-10-28 00:01:41 +01:00
$entry->setTitle(str_replace('_', ' ', static::removeSortingInformations($name)));
$entry->setName($name);
return $entry;
}
2015-07-20 15:59:52 +02:00
$uri = static::removeSortingInformations($name);
if ($config->isStatic()) {
$uri .= '.html';
}
$entry = new Content($parent, $uri, $file);
if ($entry->getUri() == $config['index_key']) {
if ($parent instanceof Root) {
$entry->setTitle($config->getTitle());
} else {
$entry->setTitle($parent->getTitle());
}
} else {
2015-10-28 00:01:41 +01:00
$entry->setTitle(str_replace('_', ' ', static::removeSortingInformations($name)));
}
$entry->setName($name);
return $entry;
}
/**
* @param string $filename
* @return string
*/
2015-10-28 00:01:41 +01:00
public static function removeSortingInformations($filename)
{
preg_match('/^[-+]?[0-9]*_?(.*)/', $filename, $matches);
2015-10-28 00:01:41 +01:00
// Remove the numeric part
// of the filename, only if
// there is something after
2016-07-27 21:32:51 +02:00
return empty($matches[1]) ? $matches[0] : $matches[1];
}
2015-07-17 18:28:54 +02:00
2015-07-17 23:38:06 +02:00
/**
* @param Directory $parent
2016-07-27 21:32:51 +02:00
* @param string $title
2015-07-17 23:38:06 +02:00
* @return Directory
*/
public static function getOrCreateDir(Directory $parent, $title)
2015-07-17 23:38:06 +02:00
{
2015-07-17 18:28:54 +02:00
$slug = DauxHelper::slug($title);
if (array_key_exists($slug, $parent->getEntries())) {
return $parent->getEntries()[$slug];
2015-07-17 18:28:54 +02:00
}
$dir = new Directory($parent, $slug);
2015-07-17 18:28:54 +02:00
$dir->setTitle($title);
return $dir;
}
2015-07-17 23:38:06 +02:00
/**
* @param Directory $parent
* @param string $path
2016-07-29 22:38:03 +02:00
* @return ContentAbstract
2015-07-17 23:38:06 +02:00
*/
public static function getOrCreatePage(Directory $parent, $path)
2015-07-17 23:38:06 +02:00
{
$extension = pathinfo($path, PATHINFO_EXTENSION);
// If the file doesn't have an extension, set .md as a default
if ($extension == '') {
$extension = 'md';
$path .= '.md';
}
$raw = !in_array($extension, $parent->getConfig()['valid_content_extensions']);
$title = $uri = $path;
if (!$raw) {
$title = static::getName($path);
$uri = DauxHelper::slug($title);
if ($parent->getConfig()->isStatic()) {
2016-07-27 21:32:51 +02:00
$uri .= '.html';
}
2015-07-21 09:51:55 +02:00
}
2015-07-17 18:28:54 +02:00
if (array_key_exists($uri, $parent->getEntries())) {
return $parent->getEntries()[$uri];
2015-07-17 18:28:54 +02:00
}
2016-07-27 21:32:51 +02:00
$page = $raw ? new ComputedRaw($parent, $uri) : new Content($parent, $uri);
$page->setContent('-'); //set an almost empty content to avoid problems
$page->setName($path);
$page->setTitle($title);
2015-07-17 18:28:54 +02:00
if ($title == 'index' || $title == '_index') {
$page->setTitle($parent->getTitle());
2015-07-17 18:28:54 +02:00
}
return $page;
}
2017-11-07 22:44:27 +01:00
/**
* Sort the tree recursively
*
* @param Directory $current
*/
public static function sortTree(Directory $current) {
$current->sort();
foreach ($current->getEntries() as $entry) {
if ($entry instanceof Directory) {
Builder::sortTree($entry);
}
}
}
/**
* Calculate next and previous for all pages
*
* @param Directory $current
* @param null|Content $prev
* @return null|Content
*/
public static function finalizeTree(Directory $current, $prev = null)
{
foreach ($current->getEntries() as $entry) {
if ($entry instanceof Directory) {
$prev = Builder::finalizeTree($entry, $prev);
} elseif ($entry instanceof Content) {
if ($prev) {
$prev->setNext($entry);
$entry->setPrevious($prev);
}
$prev = $entry;
}
}
return $prev;
}
}