forked from Chaospott/site
727 lines
32 KiB
PHP
727 lines
32 KiB
PHP
|
<?php
|
||
|
|
||
|
require_once(dirname(__FILE__) . '/Post.php');
|
||
|
require_once(dirname(__FILE__) . '/Hook.php');
|
||
|
|
||
|
class Updater
|
||
|
{
|
||
|
public static $source_path;
|
||
|
public static $dest_path;
|
||
|
public static $cache_path;
|
||
|
public static $post_extension = '.md';
|
||
|
|
||
|
// This option writes each draft preview into (web root)/drafts/whatever-slug
|
||
|
// Without it, drafts only reside in the (source)/drafts/_previews folder
|
||
|
// and are not accessible publicly.
|
||
|
public static $write_public_drafts = false;
|
||
|
|
||
|
public static $frontpage_post_limit = 4;
|
||
|
public static $frontpage_template = 'front.php';
|
||
|
public static $frontpage_tag_filter = '!rss-only';
|
||
|
public static $frontpage_type_filter = false;
|
||
|
public static $frontpage_paginate = false;
|
||
|
|
||
|
public static $logbuch_post_limit = 20;
|
||
|
public static $logbuch_template = 'main.php';
|
||
|
public static $logbuch_tag_filter = '!rss-only';
|
||
|
public static $logbuch_type_filter = false;
|
||
|
public static $logbuch_paginate = false;
|
||
|
|
||
|
public static $rss_post_limit = 20;
|
||
|
public static $rss_template = 'rss.php';
|
||
|
public static $rss_tag_filter = '!site-only';
|
||
|
public static $rss_type_filter = false;
|
||
|
|
||
|
public static $archive_month_template = 'main.php';
|
||
|
public static $archive_year_template = 'main.php';
|
||
|
public static $archive_tag_filter = '!rss-only';
|
||
|
public static $archive_type_filter = '!ad';
|
||
|
|
||
|
public static $tag_page_post_limit = 20;
|
||
|
|
||
|
public static $permalink_template = 'main.php';
|
||
|
public static $tag_page_template = 'main.php';
|
||
|
public static $type_page_template = 'main.php';
|
||
|
public static $page_template = 'main.php';
|
||
|
|
||
|
public static $api_blog_id = 1;
|
||
|
public static $api_blog_username = '';
|
||
|
public static $api_blog_password = '';
|
||
|
|
||
|
public static $changes_were_written = false;
|
||
|
|
||
|
private static $index_to_be_updated = false;
|
||
|
private static $index_months_to_be_updated = array();
|
||
|
private static $tags_to_be_updated = array();
|
||
|
private static $types_to_be_updated = array();
|
||
|
private static $posts_to_be_updated = array();
|
||
|
private static $pages_to_be_updated = array();
|
||
|
|
||
|
public static function posts_in_year_month($year, $month, $require_tag = false, $require_type = false)
|
||
|
{
|
||
|
$month = str_pad($month, 2, '0', STR_PAD_LEFT);
|
||
|
$cache_fname = self::$cache_path . "/posts-$year-$month-" . md5($require_tag . ' ' . $require_type);
|
||
|
if (file_exists($cache_fname)) {
|
||
|
$files = unserialize(file_get_contents($cache_fname));
|
||
|
} else {
|
||
|
$all_files = self::filelist(self::$source_path . "/posts/$year/$month", true);
|
||
|
ksort($all_files);
|
||
|
$in_month = false;
|
||
|
$files = array();
|
||
|
foreach ($all_files as $fname => $info) {
|
||
|
if (substr($fname, -(strlen(self::$post_extension))) != self::$post_extension) continue;
|
||
|
|
||
|
// Tag/type filtering
|
||
|
list($ignored_hash, $type, $tags) = explode('|', $info, 3);
|
||
|
$include = true;
|
||
|
if ($require_type) {
|
||
|
if ($require_type[0] == '!' && $type == $require_type) $include = false;
|
||
|
else if ($require_type[0] != '!' && $type != $require_type) $include = false;
|
||
|
}
|
||
|
if ($require_tag) {
|
||
|
if ($require_tag[0] == '!' && in_array($require_tag, Post::parse_tag_str($tags))) $include = false;
|
||
|
else if ($require_tag[0] != '!' && ! in_array($require_tag, Post::parse_tag_str($tags))) $include = false;
|
||
|
}
|
||
|
if (! $include) continue;
|
||
|
|
||
|
list($y, $m, $d) = array_map('intval', array_slice(explode('/', $fname), -3, 3));
|
||
|
$d = intval(substr($d, 6));
|
||
|
if ($year == $y && $month == $m) {
|
||
|
if (isset($files[$d])) $files[$d][] = $fname;
|
||
|
else $files[$d] = array($fname);
|
||
|
} else {
|
||
|
if ($in_month) break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (! file_exists(self::$cache_path)) mkdir_as_parent_owner(self::$cache_path, 0755, true);
|
||
|
file_put_contents_as_dir_owner($cache_fname, serialize($files));
|
||
|
}
|
||
|
return $files;
|
||
|
}
|
||
|
|
||
|
public static function post_filenames_in_year_month($year, $month, $require_tag = false, $require_type = false)
|
||
|
{
|
||
|
$out = array();
|
||
|
foreach (self::posts_in_year_month($year, $month, $require_tag, $require_type) as $day) {
|
||
|
foreach ($day as $filename) $out[] = $filename;
|
||
|
}
|
||
|
return $out;
|
||
|
}
|
||
|
|
||
|
private static function resequence_post_offsets($year, $month, $day)
|
||
|
{
|
||
|
$month = str_pad($month, 2, '0', STR_PAD_LEFT);
|
||
|
$day = str_pad($day, 2, '0', STR_PAD_LEFT);
|
||
|
|
||
|
error_log("Resequencing post offsets for $year-$month-$day");
|
||
|
|
||
|
$prefix = self::$source_path . "/posts/$year/$month/$year$month$day-";
|
||
|
$files = glob($prefix . '*' . self::$post_extension);
|
||
|
if (count($files) > 99) {
|
||
|
error_log("Cannot resequence offsets for $year-$month-$day: too many posts (" . count($files) . ')');
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$timestamps = array();
|
||
|
foreach ($files as $filename) {
|
||
|
$p = new Post($filename, false);
|
||
|
if (in_array($p->timestamp, $timestamps)) {
|
||
|
// Multiple posts with identical timestamp. No good way to handle this. Abort resequencing.
|
||
|
error_log("Cannot resequence offsets for $year-$month-$day: multiple identical timestamps");
|
||
|
return false;
|
||
|
}
|
||
|
$timestamps[$filename] = $p->timestamp;
|
||
|
}
|
||
|
asort($timestamps);
|
||
|
|
||
|
$offset = 0;
|
||
|
$slugs = array();
|
||
|
$out_files = array();
|
||
|
$made_changes = false;
|
||
|
foreach ($timestamps as $filename => $timestamp) {
|
||
|
$offset++;
|
||
|
|
||
|
$slug = preg_replace('/-p[0-9]{1,2}$/ms', '', substr(basename($filename), 12, -(strlen(self::$post_extension))));
|
||
|
if (! isset($slugs[$slug])) $slugs[$slug] = 1;
|
||
|
else $slugs[$slug]++;
|
||
|
|
||
|
$correct_filename =
|
||
|
$prefix .
|
||
|
str_pad($offset, 2, '0', STR_PAD_LEFT) . '-' .
|
||
|
$slug . ($slugs[$slug] < 2 ? '' : '-p' .$slugs[$slug]) .
|
||
|
self::$post_extension
|
||
|
;
|
||
|
if ($filename != $correct_filename) {
|
||
|
error_log("file [$filename] should be [$correct_filename]");
|
||
|
if (isset($out_files[$correct_filename])) throw new Exception("Target-filename collision for [$correct_filename], this should never happen");
|
||
|
$made_changes = true;
|
||
|
$out_files[$correct_filename] = array(file_get_contents($filename), $timestamp);
|
||
|
safe_unlink($filename);
|
||
|
}
|
||
|
|
||
|
foreach ($out_files as $correct_filename => $a) {
|
||
|
list($contents, $timestamp) = $a;
|
||
|
file_put_contents_as_dir_owner($correct_filename, $contents);
|
||
|
@touch($correct_filename, $timestamp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $made_changes;
|
||
|
}
|
||
|
|
||
|
private static function filelist($dir, $parse_info_in_text_files = true, $use_cached_info = array(), &$deleted_files = array())
|
||
|
{
|
||
|
$out = array();
|
||
|
if (is_dir($dir)) {
|
||
|
if ($dh = opendir($dir)) {
|
||
|
while ( ($file = readdir($dh) ) !== false) {
|
||
|
if ($file[0] == '.') continue;
|
||
|
$fullpath = $dir . '/' . $file;
|
||
|
if (is_dir($fullpath)) {
|
||
|
$out = array_merge($out, self::filelist($fullpath, $parse_info_in_text_files, $use_cached_info, $deleted_files));
|
||
|
} else {
|
||
|
if (isset($deleted_files[$fullpath])) unset($deleted_files[$fullpath]);
|
||
|
|
||
|
$new_stat_prefix = filemtime($fullpath) . '-' . filesize($fullpath);
|
||
|
|
||
|
if (isset($use_cached_info[$fullpath])) {
|
||
|
$stat_prefix = substr($use_cached_info[$fullpath], 0, strpos($use_cached_info[$fullpath], '|'));
|
||
|
if ($stat_prefix == $new_stat_prefix) continue;
|
||
|
}
|
||
|
|
||
|
$tags = '';
|
||
|
$type = '';
|
||
|
if ($parse_info_in_text_files && substr($fullpath, -(strlen(self::$post_extension))) == self::$post_extension) {
|
||
|
$post = new Post($fullpath);
|
||
|
$tags = implode(',', $post->tags);
|
||
|
$type = $post->type;
|
||
|
$expected_fname = $post->expected_source_filename();
|
||
|
if ($expected_fname != $fullpath && ! $post->is_draft) {
|
||
|
rename($fullpath, $expected_fname);
|
||
|
$fullpath = $expected_fname;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$out[$fullpath] = $new_stat_prefix . '|' . $type . '|' . $tags;
|
||
|
}
|
||
|
}
|
||
|
closedir($dh);
|
||
|
}
|
||
|
}
|
||
|
return $out;
|
||
|
}
|
||
|
|
||
|
public static function changed_files_in_directory($directory)
|
||
|
{
|
||
|
$cache_fname = self::$cache_path . '/dir-' . md5($directory);
|
||
|
$changed = array();
|
||
|
if (file_exists($cache_fname)) {
|
||
|
$fileinfo = unserialize(file_get_contents($cache_fname));
|
||
|
$doesnt_exist_anymore = $fileinfo;
|
||
|
foreach (self::filelist($directory, true, $fileinfo, $doesnt_exist_anymore) as $filename => $new_info) {
|
||
|
if (! isset($fileinfo[$filename]) || $fileinfo[$filename] != $new_info) {
|
||
|
$changed[$filename] = array(isset($fileinfo[$filename]) ? $fileinfo[$filename] : '||', $new_info);
|
||
|
$fileinfo[$filename] = $new_info;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
foreach ($doesnt_exist_anymore as $deleted_fname => $old_info) {
|
||
|
error_log("Deleted file: $deleted_fname");
|
||
|
$changed[$deleted_fname] = array($old_info, '||');
|
||
|
unset($fileinfo[$deleted_fname]);
|
||
|
}
|
||
|
} else {
|
||
|
$fileinfo = self::filelist($directory, true);
|
||
|
foreach ($fileinfo as $filename => $new_info) $changed[$filename] = array('||', $new_info);
|
||
|
if (! file_exists(self::$cache_path)) mkdir_as_parent_owner(self::$cache_path, 0755, true);
|
||
|
}
|
||
|
if ($changed) file_put_contents_as_dir_owner($cache_fname, serialize($fileinfo));
|
||
|
return $changed;
|
||
|
}
|
||
|
|
||
|
public static function most_recent_post_filenames($limit = 0, $require_tag = false, $require_type = false)
|
||
|
{
|
||
|
$cache_fname = self::$cache_path . '/dir-' . md5(self::$source_path . '/posts');
|
||
|
if (! file_exists($cache_fname)) throw new Exception('Cache files not found, expected in [' . self::$cache_path . ']');
|
||
|
$fileinfo = unserialize(file_get_contents($cache_fname));
|
||
|
krsort($fileinfo); // reverse-chrono
|
||
|
|
||
|
$posts = array();
|
||
|
foreach ($fileinfo as $filename => $info) {
|
||
|
if (substr($filename, -(strlen(self::$post_extension))) != self::$post_extension) continue;
|
||
|
list($ignored_hash, $type, $tags) = explode('|', $info, 3);
|
||
|
$include = true;
|
||
|
if ($require_type) {
|
||
|
if ($require_type[0] == '!' && $type == substr($require_type, 1)) $include = false;
|
||
|
else if ($require_type[0] != '!' && $type != $require_type) $include = false;
|
||
|
}
|
||
|
|
||
|
if ($require_tag) {
|
||
|
if ($require_tag[0] == '!' && in_array(substr($require_tag, 1), Post::parse_tag_str($tags))) $include = false;
|
||
|
else if ($require_tag[0] != '!' && ! in_array($require_tag, Post::parse_tag_str($tags))) $include = false;
|
||
|
}
|
||
|
|
||
|
if (! $include) continue;
|
||
|
$posts[] = $filename;
|
||
|
if ($limit && count($posts) >= $limit) break;
|
||
|
}
|
||
|
return $posts;
|
||
|
}
|
||
|
|
||
|
public static function set_has_posts_for_month($year, $month, $scope = '')
|
||
|
{
|
||
|
$cache_fname = self::$cache_path . "/months-with-posts-$scope";
|
||
|
if (file_exists($cache_fname)) {
|
||
|
$existing = unserialize(file_get_contents($cache_fname));
|
||
|
} else {
|
||
|
$existing = array();
|
||
|
}
|
||
|
|
||
|
$changed = false;
|
||
|
if (! isset($existing[$year])) {
|
||
|
$existing[$year] = array($month => true);
|
||
|
$changed = true;
|
||
|
} else if (! isset($existing[$year][$month])) {
|
||
|
$existing[$year][$month] = true;
|
||
|
$changed = true;
|
||
|
}
|
||
|
|
||
|
if ($changed) {
|
||
|
if (! file_exists(self::$cache_path)) mkdir_as_parent_owner(self::$cache_path, 0755, true);
|
||
|
file_put_contents_as_dir_owner($cache_fname, serialize($existing));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static function months_with_posts($scope = '')
|
||
|
{
|
||
|
$cache_fname = self::$cache_path . "/months-with-posts-$scope";
|
||
|
if (! file_exists($cache_fname)) throw new Exception('Cache files not found, expected ' . $cache_fname);
|
||
|
return unserialize(file_get_contents($cache_fname));
|
||
|
}
|
||
|
|
||
|
public static function archive_array($scope = '')
|
||
|
{
|
||
|
$out = array();
|
||
|
foreach (self::months_with_posts($scope) as $year => $months) {
|
||
|
foreach ($months as $month => $x) {
|
||
|
$ts = mktime(0, 0, 0, $month, 15, $year);
|
||
|
$out[$year . str_pad($month, 2, '0', STR_PAD_LEFT)] = array(
|
||
|
'archives-uri' => "/$year/" . str_pad($month, 2, '0', STR_PAD_LEFT) . '/' . $scope,
|
||
|
'archives-year' => $year,
|
||
|
'archives-month-number' => intval($month),
|
||
|
'archives-month-name' => date('F', $ts),
|
||
|
'archives-month-short-name' => date('M', $ts),
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
arsort($out);
|
||
|
return $out;
|
||
|
}
|
||
|
|
||
|
public static function update_drafts()
|
||
|
{
|
||
|
foreach (self::changed_files_in_directory(self::$source_path . '/drafts') as $filename => $info) {
|
||
|
self::$changes_were_written = true;
|
||
|
|
||
|
if (contains($filename, '/_publish-now/') && file_exists($filename)) {
|
||
|
$post = new Post($filename, false);
|
||
|
$expected_fname = $post->expected_source_filename(true);
|
||
|
error_log("Publishing draft $filename");
|
||
|
$dir = dirname($expected_fname);
|
||
|
if (! file_exists($dir)) mkdir_as_parent_owner($dir, 0755, true);
|
||
|
if (file_put_contents_as_dir_owner($expected_fname, $post->normalized_source())) safe_unlink($filename);
|
||
|
self::post_hooks($post);
|
||
|
}
|
||
|
|
||
|
if (! file_exists($filename)) {
|
||
|
if (ends_with($filename, self::$post_extension)) {
|
||
|
error_log("Deleted draft $filename");
|
||
|
$slug = substring_before(basename($filename), '.', true);
|
||
|
$html_preview_filename = self::$source_path . '/drafts/_previews/' . $slug . '.html';
|
||
|
$webroot_preview_filename = self::$dest_path . '/drafts/' . $slug;
|
||
|
if (file_exists($html_preview_filename)) safe_unlink($html_preview_filename);
|
||
|
if (file_exists($webroot_preview_filename)) safe_unlink($webroot_preview_filename);
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (substr($filename, -(strlen(self::$post_extension))) == self::$post_extension) {
|
||
|
$post = new Post($filename, true);
|
||
|
if ($post->publish_now) {
|
||
|
$post = new Post($filename, false);
|
||
|
$expected_fname = $post->expected_source_filename(true);
|
||
|
error_log("Publishing draft $filename");
|
||
|
$dir = dirname($expected_fname);
|
||
|
if (! file_exists($dir)) mkdir_as_parent_owner($dir, 0755, true);
|
||
|
if (file_put_contents_as_dir_owner($expected_fname, $post->normalized_source())) safe_unlink($filename);
|
||
|
self::post_hooks($post);
|
||
|
} else {
|
||
|
$post->write_permalink_page(true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static function update_styles()
|
||
|
{
|
||
|
foreach (self::changed_files_in_directory(self::$source_path . '/templates') as $filename => $info) {
|
||
|
$file_info = pathinfo($filename);
|
||
|
if ($file_info['extension'] != 'css') continue;
|
||
|
|
||
|
error_log("Changed style file: $filename");
|
||
|
$uri = substring_after($filename, self::$source_path . '/templates');
|
||
|
$dest_filename = self::$dest_path . $uri;
|
||
|
$output_path = dirname($dest_filename);
|
||
|
if (! file_exists($output_path)) mkdir_as_parent_owner($output_path, 0755, true);
|
||
|
copy($filename, $dest_filename);
|
||
|
self::$changes_were_written = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static function post_hooks($post)
|
||
|
{
|
||
|
$dir = self::$source_path . '/hooks';
|
||
|
if (is_dir($dir)) {
|
||
|
if ( ($dh = opendir($dir)) ) {
|
||
|
while ( ($file = readdir($dh) ) !== false) {
|
||
|
if ($file[0] == '.') continue;
|
||
|
if (substr($file, 0, 5) == 'post_') {
|
||
|
$fullpath = $dir . '/' . $file;
|
||
|
require_once($fullpath);
|
||
|
$className = ucfirst(substr($file, 5, strlen($file) - 9));
|
||
|
$hook = new $className;
|
||
|
$hook->doHook($post);
|
||
|
}
|
||
|
}
|
||
|
closedir($dh);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static function update_pages()
|
||
|
{
|
||
|
foreach (self::changed_files_in_directory(self::$source_path . '/pages') as $filename => $info) {
|
||
|
self::$changes_were_written = true;
|
||
|
|
||
|
if (! file_exists($filename)) {
|
||
|
if (ends_with($filename, self::$post_extension)) {
|
||
|
error_log("Deleted page $filename");
|
||
|
$dest_filename = self::$dest_path . '/' . substring_before(basename($filename), '.', true);
|
||
|
if (file_exists($dest_filename)) safe_unlink($dest_filename);
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (substr($filename, -(strlen(self::$post_extension))) == self::$post_extension) {
|
||
|
$post = new Post($filename, true);
|
||
|
$post->slug = basename($filename, self::$post_extension);
|
||
|
error_log("Writing page [{$post->slug}]");
|
||
|
$post->write_page(true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const RESEQUENCED_POSTS = -1;
|
||
|
public static function update()
|
||
|
{
|
||
|
if (! file_exists(self::$cache_path)) {
|
||
|
// Starting fresh, probably multiple resequences to do.
|
||
|
// Let them all happen at once.
|
||
|
$status = self::_update(false);
|
||
|
}
|
||
|
|
||
|
do {
|
||
|
$status = self::_update();
|
||
|
} while ($status == self::RESEQUENCED_POSTS);
|
||
|
|
||
|
return $status;
|
||
|
}
|
||
|
|
||
|
private static function _update($restart_if_resequenced = true)
|
||
|
{
|
||
|
if (! file_exists(self::$dest_path)) mkdir_as_parent_owner(self::$dest_path, 0755, true);
|
||
|
if (! file_exists(self::$dest_path . '/.htaccess')) copy(dirname(__FILE__) . '/default.htaccess', self::$dest_path . '/.htaccess');
|
||
|
|
||
|
if (! file_exists(self::$source_path . '/drafts/_publish-now')) mkdir_as_parent_owner(self::$source_path . '/drafts/_publish-now', 0755, true);
|
||
|
if (! file_exists(self::$source_path . '/drafts/_previews')) mkdir_as_parent_owner(self::$source_path . '/drafts/_previews', 0755, true);
|
||
|
if (! file_exists(self::$source_path . '/pages')) mkdir_as_parent_owner(self::$source_path . '/pages', 0755, true);
|
||
|
|
||
|
self::update_pages();
|
||
|
self::update_drafts();
|
||
|
self::update_styles();
|
||
|
|
||
|
foreach (self::changed_files_in_directory(self::$source_path . '/media') as $filename => $info) {
|
||
|
error_log("Changed media file: $filename");
|
||
|
$uri = substring_after($filename, self::$source_path);
|
||
|
$dest_filename = self::$dest_path . $uri;
|
||
|
$output_path = dirname($dest_filename);
|
||
|
if (! file_exists($output_path)) mkdir_as_parent_owner($output_path, 0755, true);
|
||
|
copy($filename, $dest_filename);
|
||
|
self::$changes_were_written = true;
|
||
|
}
|
||
|
|
||
|
$resequence_days = array();
|
||
|
|
||
|
foreach (self::changed_files_in_directory(self::$source_path . '/posts') as $filename => $info) {
|
||
|
self::$posts_to_be_updated[$filename] = true;
|
||
|
|
||
|
if (substr($filename, -(strlen(self::$post_extension))) == self::$post_extension) {
|
||
|
list($old_info, $new_info) = $info;
|
||
|
list($old_hash, $old_type, $old_tags) = explode('|', $old_info, 3);
|
||
|
list($new_hash, $new_type, $new_tags) = explode('|', $new_info, 3);
|
||
|
|
||
|
if ($old_type) self::$types_to_be_updated[$old_type] = true;
|
||
|
if ($new_type) self::$types_to_be_updated[$new_type] = true;
|
||
|
|
||
|
foreach (Post::parse_tag_str($old_tags) as $tag) self::$tags_to_be_updated[$tag] = true;
|
||
|
foreach (Post::parse_tag_str($new_tags) as $tag) self::$tags_to_be_updated[$tag] = true;
|
||
|
}
|
||
|
|
||
|
$yearpos = strpos($filename, '/posts/') + 7;
|
||
|
$year = substr($filename, $yearpos, 4);
|
||
|
$month = substr($filename, $yearpos + 5, 2);
|
||
|
$day = substr($filename, $yearpos + 14, 2);
|
||
|
$resequence_days[$year . $month . $day] = array($year, $month, $day);
|
||
|
self::$index_months_to_be_updated[$year . '-' . $month] = true;
|
||
|
self::$index_to_be_updated = true;
|
||
|
}
|
||
|
|
||
|
foreach (self::$posts_to_be_updated as $filename => $x) {
|
||
|
if (! file_exists($filename)) {
|
||
|
// This file was deleted. Delete corresponding output file
|
||
|
$filename_datestr = substr(basename($filename), 0, 8);
|
||
|
if (is_numeric($filename_datestr)) {
|
||
|
$year = substr($filename_datestr, 0, 4);
|
||
|
$month = substr($filename_datestr, 4, 2);
|
||
|
$day = substr($filename_datestr, 6, 2);
|
||
|
$slug = substr(basename($filename), 12, -(strlen(self::$post_extension)));
|
||
|
$target_filename = self::$dest_path . "/$year/$month/$day/$slug";
|
||
|
if ($year && $month && $day && $slug && file_exists($target_filename)) {
|
||
|
error_log("Deleting abandoned target file: $target_filename");
|
||
|
safe_unlink($target_filename);
|
||
|
}
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
error_log("Updating post: $filename");
|
||
|
self::$changes_were_written = true;
|
||
|
|
||
|
if (substr($filename, -(strlen(self::$post_extension))) == self::$post_extension) {
|
||
|
$post = new Post($filename);
|
||
|
$post->write_permalink_page();
|
||
|
|
||
|
self::set_has_posts_for_month($post->year, $post->month);
|
||
|
foreach ($post->tags as $tag) self::set_has_posts_for_month($post->year, $post->month, 'tagged-' . $tag);
|
||
|
if ($post->type) self::set_has_posts_for_month($post->year, $post->month, 'type-' . $post->type);
|
||
|
|
||
|
} else {
|
||
|
$filename_datestr = substr(basename($filename), 0, 8);
|
||
|
if (is_numeric($filename_datestr)) {
|
||
|
$year = intval(substr($filename_datestr, 0, 4));
|
||
|
$month = intval(substr($filename_datestr, 4, 2));
|
||
|
$day = intval(substr($filename_datestr, 6, 2));
|
||
|
if ($year && $month && $day) {
|
||
|
$output_path = self::$dest_path . "/$year/" . str_pad($month, 2, '0', STR_PAD_LEFT) . '/' . str_pad($day, 2, '0', STR_PAD_LEFT);
|
||
|
if (! file_exists($output_path)) mkdir_as_parent_owner($output_path, 0755, true);
|
||
|
$output_filename = $output_path . '/' . basename($filename);
|
||
|
copy($filename, $output_filename);
|
||
|
$resequence_days[$year . $month . $day] = array($year, $month, $day);
|
||
|
} else {
|
||
|
error_log("Can't figure out where to put unrecognized numeric filename [$filename]");
|
||
|
}
|
||
|
} else {
|
||
|
error_log("Can't figure out where to put unrecognized filename [$filename]");
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$sequence_changed = false;
|
||
|
foreach ($resequence_days as $a) {
|
||
|
list($year, $month, $day) = array_map('intval', $a);
|
||
|
if (self::resequence_post_offsets($year, $month, $day)) $sequence_changed = true;
|
||
|
}
|
||
|
|
||
|
if ($sequence_changed && $restart_if_resequenced) {
|
||
|
self::$changes_were_written = true;
|
||
|
error_log("Resequencing was performed. Restarting update...");
|
||
|
return self::RESEQUENCED_POSTS;
|
||
|
}
|
||
|
|
||
|
if (! self::$index_to_be_updated) self::$index_to_be_updated = self::$index_months_to_be_updated || self::$tags_to_be_updated || self::$types_to_be_updated || self::$posts_to_be_updated;
|
||
|
|
||
|
if (self::$index_to_be_updated) {
|
||
|
error_log("Updating frontpage...");
|
||
|
self::$changes_were_written = true;
|
||
|
|
||
|
$seq_count = 0;
|
||
|
if (self::$frontpage_paginate) {
|
||
|
$seq_count = Post::write_index_sequence(
|
||
|
self::$dest_path . "/index",
|
||
|
Post::$blog_title,
|
||
|
'frontpage',
|
||
|
Post::from_files(self::most_recent_post_filenames(0, self::$frontpage_tag_filter, self::$frontpage_type_filter)),
|
||
|
self::$frontpage_template,
|
||
|
self::archive_array(),
|
||
|
self::$frontpage_post_limit
|
||
|
);
|
||
|
}
|
||
|
|
||
|
Post::write_index(
|
||
|
self::$dest_path . "/index.html",
|
||
|
Post::$blog_title,
|
||
|
'frontpage',
|
||
|
Post::from_files(self::most_recent_post_filenames(self::$frontpage_post_limit, self::$frontpage_tag_filter, self::$frontpage_type_filter)),
|
||
|
self::$frontpage_template,
|
||
|
self::archive_array(),
|
||
|
$seq_count
|
||
|
);
|
||
|
|
||
|
$seq_count = 0;
|
||
|
if (self::$logbuch_paginate) {
|
||
|
$seq_count = Post::write_index_sequence(
|
||
|
self::$dest_path . "/logbuch",
|
||
|
Post::$blog_title,
|
||
|
'frontpage',
|
||
|
Post::from_files(self::most_recent_post_filenames(0, self::$logbuch_tag_filter, self::$flogbuch_type_filter)),
|
||
|
self::$logbuch_template,
|
||
|
self::archive_array(),
|
||
|
self::$logbuch_post_limit
|
||
|
);
|
||
|
}
|
||
|
|
||
|
Post::write_index(
|
||
|
self::$dest_path . "/logbuch.html",
|
||
|
Post::$blog_title,
|
||
|
'frontpage',
|
||
|
Post::from_files(self::most_recent_post_filenames(self::$logbuch_post_limit, self::$logbuch_tag_filter, self::$logbuch_type_filter)),
|
||
|
self::$logbuch_template,
|
||
|
self::archive_array(),
|
||
|
$seq_count
|
||
|
);
|
||
|
|
||
|
error_log("Updating RSS...");
|
||
|
Post::write_index(
|
||
|
self::$dest_path . "/rss.xml",
|
||
|
Post::$blog_title,
|
||
|
'rss',
|
||
|
Post::from_files(self::most_recent_post_filenames(self::$rss_post_limit, self::$rss_tag_filter, self::$rss_type_filter)),
|
||
|
self::$rss_template
|
||
|
);
|
||
|
}
|
||
|
|
||
|
foreach (self::$index_months_to_be_updated as $ym => $x) {
|
||
|
error_log("Updating month index: $ym");
|
||
|
self::$changes_were_written = true;
|
||
|
|
||
|
list($year, $month) = explode('-', $ym);
|
||
|
$posts = Post::from_files(self::post_filenames_in_year_month($year, $month, self::$archive_tag_filter, self::$archive_type_filter));
|
||
|
$ts = mktime(0, 0, 0, $month, 15, $year);
|
||
|
Post::write_index(
|
||
|
self::$dest_path . "/$year/$month/index.html",
|
||
|
date('F Y', $ts),
|
||
|
'archive',
|
||
|
$posts,
|
||
|
self::$archive_month_template,
|
||
|
self::archive_array()
|
||
|
);
|
||
|
}
|
||
|
|
||
|
foreach (self::$tags_to_be_updated as $tag => $x) {
|
||
|
if (! strlen($tag)) continue;
|
||
|
error_log("Updating tag: $tag");
|
||
|
self::$changes_were_written = true;
|
||
|
|
||
|
$seq_count = Post::write_index_sequence(
|
||
|
self::$dest_path . "/tagged-$tag",
|
||
|
Post::$blog_title,
|
||
|
'tag',
|
||
|
Post::from_files(self::most_recent_post_filenames(0, $tag, self::$archive_tag_filter)),
|
||
|
self::$tag_page_template,
|
||
|
self::archive_array(),
|
||
|
self::$tag_page_post_limit
|
||
|
);
|
||
|
|
||
|
Post::write_index(
|
||
|
self::$dest_path . "/tagged-$tag.html",
|
||
|
Post::$blog_title,
|
||
|
'tag',
|
||
|
Post::from_files(self::most_recent_post_filenames(self::$frontpage_post_limit, $tag, self::$archive_tag_filter)),
|
||
|
self::$tag_page_template,
|
||
|
self::archive_array('tagged-' . $tag),
|
||
|
$seq_count
|
||
|
);
|
||
|
|
||
|
Post::write_index(
|
||
|
self::$dest_path . "/tagged-$tag.xml",
|
||
|
Post::$blog_title,
|
||
|
'tag',
|
||
|
Post::from_files(self::most_recent_post_filenames(self::$rss_post_limit, $tag, self::$archive_tag_filter)),
|
||
|
self::$rss_template,
|
||
|
self::archive_array('tagged-' . $tag)
|
||
|
);
|
||
|
|
||
|
$months_with_posts = self::months_with_posts('tagged-' . $tag);
|
||
|
foreach (self::$index_months_to_be_updated as $ym => $x) {
|
||
|
list($year, $month) = explode('-', $ym);
|
||
|
if (! isset($months_with_posts[$year]) || ! isset($months_with_posts[$year][intval($month)])) continue;
|
||
|
error_log("Updating month index: $ym for tag: $tag");
|
||
|
$posts = Post::from_files(self::post_filenames_in_year_month($year, $month, $tag, self::$archive_type_filter));
|
||
|
$ts = mktime(0, 0, 0, $month, 15, $year);
|
||
|
Post::write_index(
|
||
|
self::$dest_path . "/$year/$month/tagged-$tag.html",
|
||
|
date('F Y', $ts),
|
||
|
'tag',
|
||
|
$posts,
|
||
|
self::$tag_page_template,
|
||
|
self::archive_array('tagged-' . $tag)
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
foreach (self::$types_to_be_updated as $type => $x) {
|
||
|
if (! strlen($type)) continue;
|
||
|
error_log("Updating type: $type");
|
||
|
self::$changes_were_written = true;
|
||
|
|
||
|
Post::write_index(
|
||
|
self::$dest_path . "/type-$type.html",
|
||
|
Post::$blog_title,
|
||
|
'type',
|
||
|
Post::from_files(self::most_recent_post_filenames(self::$frontpage_post_limit, self::$archive_type_filter, $type)),
|
||
|
self::$type_page_template,
|
||
|
self::archive_array('type-' . $type)
|
||
|
);
|
||
|
|
||
|
Post::write_index(
|
||
|
self::$dest_path . "/type-$type.xml",
|
||
|
Post::$blog_title,
|
||
|
'type',
|
||
|
Post::from_files(self::most_recent_post_filenames(self::$rss_post_limit, self::$archive_type_filter, $type)),
|
||
|
self::$rss_template,
|
||
|
self::archive_array('type-' . $type)
|
||
|
);
|
||
|
|
||
|
$months_with_posts = self::months_with_posts('type-' . $type);
|
||
|
foreach (self::$index_months_to_be_updated as $ym => $x) {
|
||
|
list($year, $month) = explode('-', $ym);
|
||
|
if (! isset($months_with_posts[$year]) || ! isset($months_with_posts[$year][intval($month)])) continue;
|
||
|
error_log("Updating month index: $ym for type: $type");
|
||
|
$posts = Post::from_files(self::post_filenames_in_year_month($year, $month, self::$archive_tag_filter, $type));
|
||
|
$ts = mktime(0, 0, 0, $month, 15, $year);
|
||
|
Post::write_index(
|
||
|
self::$dest_path . "/$year/$month/type-$type.html",
|
||
|
date('F Y', $ts),
|
||
|
'type',
|
||
|
$posts,
|
||
|
self::$type_page_template,
|
||
|
self::archive_array('type-' . $type)
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|