/** * Helper to get instance of AutoloadBuilder with cli options applied * * @throws \RuntimeException * @return \TheSeer\Autoload\AutoloadBuilder|\TheSeer\Autoload\StaticBuilder */ public function getBuilder(ClassFinder $finder) { $isStatic = $this->config->isStaticMode(); $isPhar = $this->config->isPharMode(); $isCompat = $this->config->isCompatMode(); $noLower = !$this->config->isLowercaseMode(); $isOnce = $this->config->isOnceMode(); $tplType = $noLower ? 'cs' : 'ci'; if ($isStatic === TRUE) { $builder = new StaticBuilder($finder->getMerged()); $builder->setDependencies($finder->getDependencies()); $builder->setPharMode($isPhar); $builder->setRequireOnce($isOnce); } else { $builder = new AutoloadBuilder($finder->getMerged()); } $builder->setCompat($isCompat); $basedir = $this->config->getBaseDirectory(); if (!$basedir || !is_dir($basedir)) { throw new \RuntimeException("Given basedir '{$basedir}' does not exist or is not a directory"); } $builder->setBaseDir($basedir); $template = $this->config->getTemplate(); if ($template !== NULL) { if (!file_exists($template)) { $alternative = __DIR__ . '/templates/' . $tplType . '/' . $template; if (file_exists($alternative)) { $template = $alternative; } } $builder->setTemplateFile($template); } else { // determine auto template to use $tplFile = 'default.php.tpl'; if ($isCompat) { $tplFile = 'php52.php.tpl'; } if ($isPhar) { if ($isStatic) { $tplFile = 'staticphar.php.tpl'; } else { $tplFile = 'phar.php.tpl'; } } elseif ($isStatic) { $tplFile = 'static.php.tpl'; $tplType = '.'; } $builder->setTemplateFile(__DIR__ . '/templates/' . $tplType . '/' . $tplFile); } $format = $this->config->getDateFormat(); if ($format) { $builder->setDateTimeFormat($format); } $builder->setIndent($this->config->getIndent()); $builder->setLineBreak($this->config->getLinebreak()); foreach ($this->config->getVariables() as $name => $value) { $builder->setVariable($name, $value); } return $builder; }
public function index($value, $parameters = array()) { $use_smart_relative = !empty($parameters[0]) && $parameters[0] == 'smart'; if ($use_smart_relative) { // find today, yesterday, and beyond $today = Date::resolve('today midnight'); $yesterday = Date::resolve('yesterday midnight'); $tomorrow = Date::resolve('tomorrow midnight'); $two_days = Date::resolve('+2 days midnight'); $hour_ago = Date::resolve('-1 hour'); $in_an_hour = Date::resolve('+1 hour'); $now = time(); // normalize date $timestamp = Date::resolve($value); // now check if ($timestamp > $two_days || $timestamp < $yesterday) { // this is outside of an immediate window, just return date return Date::format(Config::getDateFormat(), $timestamp) . ' ' . __('at') . ' ' . Date::format(Config::getTimeFormat(), $timestamp); } elseif ($timestamp > $hour_ago && $timestamp < $in_an_hour) { // this is very near by, return relative date return Carbon::createFromTimestamp($timestamp)->diffForHumans(); } elseif ($timestamp < $now) { if ($timestamp > $today) { // this is today return __('today') . ' ' . __('at') . ' ' . Date::format(Config::getTimeFormat(), $timestamp); } else { // this is yesterday return __('yesterday') . ' ' . __('at') . ' ' . Date::format(Config::getTimeFormat(), $timestamp); } } else { // this is tomorrow return __('tomorrow') . ' ' . __('at') . ' ' . Date::format(Config::getTimeFormat(), $timestamp); } } else { if (is_numeric($value)) { // this is a timestamp return Carbon::createFromTimestamp($value)->diffForHumans(); } // this is a string return Carbon::parse($value)->diffForHumans(); } }
/** * Add to the top of the publish form * * @return string */ public function control_panel__add_to_publish_form_header() { // master switch for revisions if (!$this->core->isEnabled()) { return false; } $app = \Slim\Slim::getInstance(); // hidden message field $html = '<input type="hidden" name="revisions__commit_message" id="revision-message">'; $html .= '<div id="revision-default-serialized" style="display: none !important;"></div>'; if ($this->blink->get('is_revision') && !$this->blink->get('is_latest_revision')) { // get the revision data $timestamp = $this->core->getRevisionTimestamp($this->core->getPath(), $this->blink->get('current_revision')); $html .= '<div class="revisions-feedback">'; $html .= ' <span class="ss-icon">help</span>'; $html .= ' ' . sprintf(__('viewing_revision'), Date::format(Config::getDateFormat(), $timestamp)) . ' '; $html .= ' <a href="' . $app->urlFor('publish') . '?path=' . URL::sanitize(Request::get('path')) . '">' . __('viewing_revision_link') . '.'; $html .= '</div>'; } return $html; }
/** * Helper to get instance of AutoloadRenderer with cli options applied * * @throws \RuntimeException * @return \TheSeer\Autoload\AutoloadRenderer|\TheSeer\Autoload\StaticRenderer */ public function getRenderer(CollectorResult $result) { $isStatic = $this->config->isStaticMode(); $isPhar = $this->config->isPharMode(); $isCompat = $this->config->isCompatMode(); $isOnce = $this->config->isOnceMode(); if ($isStatic === TRUE) { $renderer = new StaticRenderer($result->getUnits()); $renderer->setDependencies($result->getDependencies()); $renderer->setPharMode($isPhar); $renderer->setRequireOnce($isOnce); } else { $renderer = new AutoloadRenderer($result->getUnits()); if ($this->config->usePrepend()) { $renderer->prependAutoloader(); } if ($this->config->useExceptions()) { $renderer->enableExceptions(); } } $renderer->setCompat($isCompat); $basedir = $this->config->getBaseDirectory(); if (!$basedir || !is_dir($basedir)) { throw new \RuntimeException("Given basedir '{$basedir}' does not exist or is not a directory"); } $renderer->setBaseDir($basedir); $format = $this->config->getDateFormat(); if ($format) { $renderer->setDateTimeFormat($format); } $renderer->setIndent($this->config->getIndent()); $renderer->setLineBreak($this->config->getLinebreak()); foreach ($this->config->getVariables() as $name => $value) { $renderer->setVariable($name, $value); } return $renderer; }
public function index($value, $parameters = array()) { $format = isset($parameters[0]) ? $parameters[0] : Config::getDateFormat(); return Date::format($format, $value); }
public static function get_content_meta($slug, $folder = null, $raw = false, $parse = true) { $app = \Slim\Slim::getInstance(); $site_root = Config::getSiteRoot(); $content_root = Config::getContentRoot(); $content_type = Config::getContentType(); $file = $folder ? "{$content_root}/{$folder}/{$slug}.{$content_type}" : "{$content_root}/{$slug}.{$content_type}"; $file = Path::tidy($file); $meta_raw = File::exists($file) ? file_get_contents($file) : ''; if (Pattern::endsWith($meta_raw, "---")) { $meta_raw .= "\n"; # prevent parse failure } # Parse YAML Front Matter if (strpos($meta_raw, "---") === false) { $meta = self::loadYamlCached($meta_raw); if (is_array($meta)) { $meta = array_merge($meta, $app->config); } $meta['content'] = ""; if ($raw) { $meta['content_raw'] = ""; } } else { list($yaml, $content) = preg_split("/\n---/", $meta_raw, 2, PREG_SPLIT_NO_EMPTY); $meta = self::loadYamlCached($yaml); if ($raw) { $meta['content_raw'] = $content; } // Parse the content if necessary //$meta['content'] = $parse ? Content::parse($content, $meta) : $content; $meta['content'] = $content; } if (File::exists($file)) { $meta['last_modified'] = filemtime($file); } if (!$raw) { $meta['homepage'] = Config::getSiteRoot(); $meta['raw_url'] = Request::getResourceURI(); $meta['page_url'] = Request::getResourceURI(); # Is date formatted correctly? if (Config::getEntryTimestamps() && Slug::isDateTime($slug)) { $datetimestamp = Slug::getTimestamp($slug); $datestamp = Slug::getTimestamp($slug); $meta['datetimestamp'] = $datetimestamp; $meta['datestamp'] = $datestamp; $meta['date'] = Date::format(Config::getDateFormat(), $datestamp); $meta['time'] = Date::format(Config::getTimeFormat(), $datetimestamp); $meta['page_url'] = preg_replace(Pattern::DATETIME, '', $meta['page_url']); # clean url override } elseif (Slug::isDate($slug)) { $datestamp = Slug::getTimestamp($slug); $meta['datestamp'] = $datestamp; $meta['date'] = Date::format(Config::getDateFormat(), $datestamp); $meta['page_url'] = preg_replace(Pattern::DATE, '', $meta['page_url']); # clean url override } elseif (Slug::isNumeric($slug)) { $meta['numeric'] = Slug::getOrderNumber($slug); } $meta['permalink'] = Path::tidy(Config::getSiteURL() . '/' . $meta['page_url']); $taxonomy_slugify = isset($app->config['_taxonomy_slugify']) && $app->config['_taxonomy_slugify']; # Jam it all together, brother. # @todo: functionize/abstract this method for more flexibility and readability foreach ($meta as $key => $value) { if (!is_array($value) && Taxonomy::isTaxonomy($key)) { $value = array($value); $meta[$key] = $value; } if (is_array($value)) { $list = array(); $url_list = array(); $i = 1; $total_results = count($meta[$key]); foreach ($meta[$key] as $k => $v) { $url = null; if (Taxonomy::isTaxonomy($key) && !is_array($v)) { // DO NOT DO numerical regex replace on the actual taxonomy item $url = Path::tidy(strtolower($site_root . '/' . $folder . '/' . $key)); $url = preg_replace(Pattern::NUMERIC, '', $url); if ($taxonomy_slugify) { $url .= "/" . strtolower(Slug::make($v)); } else { $url .= "/" . strtolower($v); } $list[] = array('name' => $v, 'count' => $i, 'url' => $url, 'total_results' => $total_results, 'first' => $i == 1 ? true : false, 'last' => $i == $total_results ? true : false); $url_list[] = '<a href="' . $url . '">' . $v . '</a>'; } elseif (!is_array($v)) { $list[] = array('name' => $v, 'count' => $i, 'url' => $url, 'total_results' => $total_results, 'first' => $i == 1 ? true : false, 'last' => $i == $total_results ? true : false); } // account for known structure // - // name: something // url: http://example.com if (is_array($v) && isset($v['name']) && isset($v['url'])) { $url_list[] = '<a href="' . $v['url'] . '">' . $v['name'] . '</a>'; } $i++; } if (isset($url) || count($url_list)) { $meta[$key . '_url_list'] = implode(', ', $url_list); $meta[$key . '_spaced_url_list'] = join(" ", $url_list); $meta[$key . '_ordered_url_list'] = "<ol><li>" . join("</li><li>", $url_list) . "</li></ol>"; $meta[$key . '_unordered_url_list'] = "<ul><li>" . join("</li><li>", $url_list) . "</li></ul>"; $meta[$key . '_sentence_url_list'] = Helper::makeSentenceList($url_list); $meta[$key . '_ampersand_sentence_url_list'] = Helper::makeSentenceList($url_list, "&", false); } if (isset($meta[$key][0]) && !is_array($meta[$key][0])) { $meta[$key . '_list'] = implode(', ', $meta[$key]); $meta[$key . '_option_list'] = implode('|', $meta[$key]); $meta[$key . '_spaced_list'] = implode(' ', $meta[$key]); $meta[$key . '_ordered_list'] = "<ol><li>" . join("</li><li>", $meta[$key]) . "</li></ol>"; $meta[$key . '_unordered_list'] = "<ul><li>" . join("</li><li>", $meta[$key]) . "</li></ul>"; $meta[$key . '_sentence_list'] = Helper::makeSentenceList($meta[$key]); $meta[$key . '_ampersand_sentence_list'] = Helper::makeSentenceList($meta[$key], "&", false); $meta[$key] = $list; } } } } return $meta; }
?> "><?php print isset($entry['title']) && $entry['title'] != '' ? $entry['title'] : Slug::prettify($entry['slug']); ?> </a> </td> <?php if ($type == 'date') { ?> <td data-fulldate="<?php echo $entry['datestamp']; ?> "> <?php echo Date::format(Config::getDateFormat('Y/m/d'), $entry['datestamp']); ?> </td> <?php } elseif ($type == 'number') { ?> <td><?php print $entry['numeric']; ?> </td> <?php } ?> <td class="margin status status-<?php print $status; ?>
if (is_writable($data['path'])) { $data['logs_writable'] = TRUE; } // do any logs exist here? try { $filename_regex = "/^" . $data['prefix'] . "_(\\d{4})-(\\d{2})-(\\d{2})/i"; $dir = opendir($data['path']); if (!$dir) { throw new Exception("Directory not found"); } while (FALSE !== ($file = readdir($dir))) { if (!preg_match($filename_regex, $file, $matches)) { // no match, nothing to see here continue; } $data['logs'][$matches[1] . "-" . $matches[2] . "-" . $matches[3]] = array("date" => Date::format(Config::getDateFormat(), $matches[1] . "-" . $matches[2] . "-" . $matches[3]), "raw_date" => $matches[1] . "-" . $matches[2] . "-" . $matches[3], "filename" => $file, "full_path" => $data['path'] . DIRECTORY_SEPARATOR . $file); // we have found at least one valid log $data['logs_exist'] = TRUE; } ksort($data['logs']); closedir($dir); // flip the order of logs $data['logs'] = array_reverse($data['logs']); } catch (Exception $e) { // no logs exist $data['logs_exist'] = FALSE; } // filter $match = array('DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL'); $filter = filter_input(INPUT_GET, 'filter'); if ($filter) {
/** * Updates the internal content cache * * @return boolean */ public static function update() { // track if any files have changed $files_changed = false; // grab length of content type extension $content_type = Config::getContentType(); $full_content_root = rtrim(Path::tidy(BASE_PATH . "/" . Config::getContentRoot()), "/"); $content_type_length = strlen($content_type) + 1; // the cache file we'll use $cache_file = BASE_PATH . "/_cache/_app/content/content.php"; $time_file = BASE_PATH . "/_cache/_app/content/last.php"; $now = time(); // grab the existing cache $cache = unserialize(File::get($cache_file)); if (!is_array($cache)) { $cache = array("urls" => array(), "content" => array(), "taxonomies" => array()); } $last = File::get($time_file); // grab a list of all files $finder = new Finder(); $files = $finder->files()->name("*." . Config::getContentType())->in(Config::getContentRoot()); // grab a separate list of files that have changed since last check $updated_files = clone $files; $updated = array(); if ($last) { $updated_files->date(">= " . Date::format("Y-m-d H:i:s", $last)); foreach ($updated_files as $file) { // we don't want directories, they may show up as being modified // if a file inside them has changed or been renamed if (is_dir($file)) { continue; } // this isn't a directory, add it to the list $updated[] = Path::trimFilesystem(Path::standardize($file->getRealPath())); } } // loop over current files $current_files = array(); foreach ($files as $file) { $current_files[] = Path::trimFilesystem(Path::standardize($file->getRealPath())); } // get a diff of files we know about and files currently existing $new_files = array_diff($current_files, $cache['urls']); // create a master list of files that need updating $changed_files = array_unique(array_merge($new_files, $updated)); // add to the cache if files have been updated if (count($changed_files)) { $files_changed = true; // build content cache foreach ($changed_files as $file) { $file = $full_content_root . $file; $local_path = Path::trimFilesystem($file); $local_filename = Path::clean($local_path); // file parsing $content = substr(File::get($file), 3); $divide = strpos($content, "\n---"); $front_matter = trim(substr($content, 0, $divide)); // parse data $data = YAML::parse($front_matter); // set additional information $data['_file'] = $file; $data['_local_path'] = $local_path; $data['_order_key'] = null; $data['datetimestamp'] = null; // legacy $data['datestamp'] = null; $data['date'] = null; $data['time'] = null; $data['numeric'] = null; $data['last_modified'] = filemtime($file); $data['_is_hidden'] = false; $data['_is_draft'] = false; // folder $data['_folder'] = preg_replace(Pattern::ORDER_KEY, "", str_replace($full_content_root, "", $data['_file'])); $slash = strrpos($data['_folder'], "/"); $data['_folder'] = $slash === 0 ? "" : substr($data['_folder'], 1, $slash - 1); // fix hidden/draft files $slug = basename($file, "." . $content_type); if (substr($slug, 0, 2) === "__") { $data['_is_hidden'] = true; $data['slug'] = substr($slug, 2); } elseif (substr($slug, 0, 1) === "_") { $data['_is_draft'] = true; $data['slug'] = substr($slug, 1); } else { $data['slug'] = $slug; } $data['_basename'] = $data['slug'] . "." . $content_type; $data['_filename'] = $data['slug']; $data['_is_entry'] = preg_match(Pattern::ENTRY_FILEPATH, $data['_basename']); $data['_is_page'] = preg_match(Pattern::PAGE_FILEPATH, $data['_basename']); // 404 is special if ($data['_local_path'] === "/404.{$content_type}") { $local_filename = $local_path; // order key } elseif (preg_match(Pattern::DATE_OR_DATETIME, $data['_basename'], $matches)) { $date = $matches[1] . '-' . $matches[2] . '-' . $matches[3]; $time = NULL; if (isset($matches[4])) { $time = substr($matches[4], 0, 2) . ":" . substr($matches[4], 2); $date = $date . " " . $time; $data['slug'] = substr($data['slug'], 16); $data['datetimestamp'] = $data['_order_key']; } else { $data['slug'] = substr($data['slug'], 11); } $data['_order_key'] = strtotime($date); $data['datestamp'] = $data['_order_key']; $data['date'] = Date::format(Config::getDateFormat(), $data['_order_key']); $data['time'] = $time ? Date::format(Config::getTimeFormat(), $data['_order_key']) : NULL; } elseif (preg_match(Pattern::NUMERIC, $data['_basename'], $matches)) { $data['_order_key'] = $matches[1]; $data['numeric'] = $data['_order_key']; $data['slug'] = substr($data['slug'], strlen($matches[1]) + 1); } else { $data['_order_key'] = $data['_basename']; } // determine url $data['url'] = preg_replace("/\\/__?/", "/", $local_filename); // remove any content type extensions from the end of filename if (substr($data['url'], -$content_type_length) === "." . $content_type) { $data['url'] = substr($data['url'], 0, strlen($data['url']) - $content_type_length); } // remove any base pages from filename if (substr($data['url'], -5) == "/page") { $data['url'] = substr($data['url'], 0, strlen($data['url']) - 5); } // add the site root $data['url'] = Path::tidy(Config::getSiteRoot() . $data['url']); // add the site URL to get the permalink $data['permalink'] = Path::tidy(Config::getSiteURL() . $data['url']); // add to cache file $cache['content'][$local_path] = $data; $cache['urls'][$data['url']] = $local_path; } } // loop through all cached content for deleted files // this isn't as expensive as you'd think in real-world situations foreach ($cache['content'] as $local_path => $data) { if (File::exists($full_content_root . $local_path)) { continue; } $files_changed = TRUE; // remove from content cache unset($cache['content'][$local_path]); // remove from url cache $url = array_search($local_path, $cache['urls']); if ($url !== FALSE) { unset($cache['urls'][$url]); } } // build taxonomy cache // only happens if files were added, updated, or deleted above if ($files_changed) { $taxonomies = Config::getTaxonomies(); $force_lowercase = Config::getTaxonomyForceLowercase(); $case_sensitive = Config::getTaxonomyCaseSensitive(); $cache['taxonomies'] = array(); if (count($taxonomies)) { // set up taxonomy array foreach ($taxonomies as $taxonomy) { $cache['taxonomies'][$taxonomy] = array(); } // loop through content to build cached array foreach ($cache['content'] as $file => $data) { // do not grab anything not public if (array_get($data, '_is_hidden', FALSE) || array_get($data, '_is_draft', FALSE)) { continue; } // loop through the types of taxonomies foreach ($taxonomies as $taxonomy) { // if this file contains this type of taxonomy if (isset($data[$taxonomy])) { $values = Helper::ensureArray($data[$taxonomy]); // add the file name to the list of found files for a given taxonomy value foreach ($values as $value) { if (!$value) { continue; } $key = !$case_sensitive ? strtolower($value) : $value; if (!isset($cache['taxonomies'][$taxonomy][$key])) { $cache['taxonomies'][$taxonomy][$key] = array("name" => $force_lowercase ? strtolower($value) : $value, "files" => array()); } array_push($cache['taxonomies'][$taxonomy][$key]['files'], $data['url']); } } } } } if (File::put($cache_file, serialize($cache)) === false) { if (!File::isWritable($cache_file)) { Log::fatal("Cache folder is not writable.", "core", "content-cache"); } Log::fatal("Could not write to the cache.", "core", "content-cache"); return false; } } File::put($time_file, $now); return true; }
/** * Updates the internal content cache * * @return boolean */ public static function update() { // start measuring $content_hash = Debug::markStart('caching', 'content'); // track if any files have changed $files_changed = false; $settings_changed = false; $members_changed = false; // grab length of content type extension $content_type = Config::getContentType(); $full_content_root = rtrim(Path::tidy(BASE_PATH . "/" . Config::getContentRoot()), "/"); $content_type_length = strlen($content_type) + 1; // the cache files we'll use $cache_file = BASE_PATH . '/_cache/_app/content/content.php'; $settings_file = BASE_PATH . '/_cache/_app/content/settings.php'; $structure_file = BASE_PATH . '/_cache/_app/content/structure.php'; $time_file = BASE_PATH . '/_cache/_app/content/last.php'; $members_file = BASE_PATH . '/_cache/_app/members/members.php'; $now = time(); // start measuring settings hash $settings_hash = Debug::markStart('caching', 'settings'); // check for current and new settings $settings = unserialize(File::get($settings_file)); if (!is_array($settings)) { $settings = array('site_root' => '', 'site_url' => '', 'timezone' => '', 'date_format' => '', 'time_format' => '', 'content_type' => '', 'taxonomy' => '', 'taxonomy_case_sensitive' => '', 'taxonomy_force_lowercase' => '', 'entry_timestamps' => '', 'base_path' => '', 'app_version' => ''); } // look up current settings $current_settings = array('site_root' => Config::getSiteRoot(), 'site_url' => Config::getSiteURL(), 'timezone' => Config::get('timezone'), 'date_format' => Config::get('date_format'), 'time_format' => Config::get('time_format'), 'content_type' => Config::get('content_type'), 'taxonomy' => Config::getTaxonomies(), 'taxonomy_case_sensitive' => Config::getTaxonomyCaseSensitive(), 'taxonomy_force_lowercase' => Config::getTaxonomyForceLowercase(), 'entry_timestamps' => Config::getEntryTimestamps(), 'base_path' => BASE_PATH, 'app_version' => STATAMIC_VERSION); // have cache-altering settings changed? if ($settings !== $current_settings) { // settings have changed $settings_changed = true; // clear the cache and set current settings $cache = self::getCleanCacheArray(); $settings = $current_settings; $last = null; } else { // grab the existing cache $cache = unserialize(File::get($cache_file)); if (!is_array($cache)) { $cache = self::getCleanCacheArray(); } $last = File::get($time_file); } // mark end of settings hash measuring Debug::markEnd($settings_hash); // grab a list of all content files $files = File::globRecursively(Path::tidy(BASE_PATH . '/' . Config::getContentRoot() . '/*'), Config::getContentType()); // grab a separate list of files that have changed since last check $updated = array(); $current_files = array(); // loop through files, getting local paths and checking for updated files foreach ($files as $file) { $local_file = Path::trimFilesystemFromContent(Path::standardize($file)); // add to current files $current_files[] = $local_file; // is this updated? if ($last && File::getLastModified($file) >= $last) { $updated[] = $local_file; } } // get a diff of files we know about and files currently existing $known_files = array(); foreach ($cache['urls'] as $url_data) { array_push($known_files, $url_data['path']); } $new_files = array_diff($current_files, $known_files); // create a master list of files that need updating $changed_files = array_unique(array_merge($new_files, $updated)); // store a list of changed URLs $changed_urls = array(); // add to the cache if files have been updated if (count($changed_files)) { $files_changed = true; // build content cache foreach ($changed_files as $file) { $file = $full_content_root . $file; $local_path = Path::trimFilesystemFromContent($file); // before cleaning anything, check for hidden or draft content $is_hidden = Path::isHidden($local_path); $is_draft = Path::isDraft($local_path); // now clean up the path $local_filename = Path::clean($local_path); // file parsing $content = substr(File::get($file), 3); $divide = strpos($content, "\n---"); $front_matter = trim(substr($content, 0, $divide)); $content_raw = trim(substr($content, $divide + 4)); // parse data $data = YAML::parse($front_matter); if ($content_raw) { $data['content'] = 'true'; $data['content_raw'] = 'true'; } // set additional information $data['_file'] = $file; $data['_local_path'] = $local_path; $data['_order_key'] = null; $data['datetimestamp'] = null; // legacy $data['datestamp'] = null; $data['date'] = null; $data['time'] = null; $data['numeric'] = null; $data['last_modified'] = filemtime($file); $data['_is_hidden'] = $is_hidden; $data['_is_draft'] = $is_draft; // get initial slug (may be changed below) $data['slug'] = ltrim(basename($file, "." . $content_type), "_"); // folder $instance = $data['slug'] == 'page' ? 1 : 0; $data['_folder'] = Path::clean($data['_local_path']); $slash = Helper::strrpos_count($data['_folder'], '/', $instance); $data['_folder'] = !$slash ? '' : substr($data['_folder'], 1, $slash - 1); $data['_folder'] = !strlen($data['_folder']) ? "/" : $data['_folder']; $data['_basename'] = $data['slug'] . '.' . $content_type; $data['_filename'] = $data['slug']; $data['_is_entry'] = preg_match(Pattern::ENTRY_FILEPATH, $data['_basename']); $data['_is_page'] = preg_match(Pattern::PAGE_FILEPATH, $data['_basename']); // 404 is special if ($data['_local_path'] === "/404.{$content_type}") { $local_filename = $local_path; // order key: date or datetime } elseif (preg_match(Pattern::DATE_OR_DATETIME, $data['_basename'], $matches)) { // order key: date or datetime $date = $matches[1] . '-' . $matches[2] . '-' . $matches[3]; $time = null; if (Config::getEntryTimestamps() && isset($matches[4])) { $time = substr($matches[4], 0, 2) . ":" . substr($matches[4], 2); $date = $date . " " . $time; $data['slug'] = substr($data['slug'], 16); $data['datetimestamp'] = $data['_order_key']; } else { $data['slug'] = substr($data['slug'], 11); } $data['_order_key'] = strtotime($date); $data['datestamp'] = $data['_order_key']; $data['date'] = Date::format(Config::getDateFormat(), $data['_order_key']); $data['time'] = $time ? Date::format(Config::getTimeFormat(), $data['_order_key']) : null; // order key: slug is page, back up a level } elseif ($data['slug'] == 'page' && preg_match(Pattern::NUMERIC, substr($data['_local_path'], Helper::strrpos_count($data['_local_path'], '/', 1)), $matches)) { // order key: slug is page, back up a level $data['_order_key'] = $matches[1]; $data['numeric'] = $data['_order_key']; // order key: numeric } elseif (preg_match(Pattern::NUMERIC, $data['_basename'], $matches)) { // order key: numeric $data['_order_key'] = $matches[1]; $data['numeric'] = $data['_order_key']; $data['slug'] = substr($data['slug'], strlen($matches[1]) + 1); // order key: other } else { // order key: other $data['_order_key'] = $data['_basename']; } // determine url $data['url'] = preg_replace('#/__?#', '/', $local_filename); // remove any content type extensions from the end of filename if (substr($data['url'], -$content_type_length) === '.' . $content_type) { $data['url'] = substr($data['url'], 0, strlen($data['url']) - $content_type_length); } // remove any base pages from filename if (substr($data['url'], -5) == '/page') { $data['url'] = substr($data['url'], 0, strlen($data['url']) - 5); } // add the site root $data['url'] = Path::tidy(Config::getSiteRoot() . $data['url']); // add the site URL to get the permalink $data['permalink'] = Path::tidy(Config::getSiteURL() . $data['url']); // new content if (!isset($cache['content'][$data['_folder']]) || !is_array($cache['content'][$data['_folder']])) { $cache['content'][$data['_folder']] = array(); } $slug_with_extension = $data['_filename'] == 'page' ? substr($data['url'], strrpos($data['url'], '/') + 1) . '/' . $data['_filename'] . "." . $content_type : $data['_filename'] . "." . $content_type; $cache['content'][$data['_folder']][$slug_with_extension] = array('folder' => $data['_folder'], 'path' => $local_path, 'file' => $slug_with_extension, 'url' => $data['url'], 'data' => $data); $cache['urls'][$data['url']] = array('folder' => $data['_folder'], 'path' => $local_path, 'file' => $slug_with_extension); $changed_urls[$data['url']] = true; } } // loop through all cached content for deleted files // this isn't as expensive as you'd think in real-world situations foreach ($cache['content'] as $folder => $folder_contents) { foreach ($folder_contents as $path => $data) { if (File::exists($full_content_root . $data['path'])) { // still here, keep it continue; } $files_changed = true; // get URL $url = isset($cache['content'][$folder][$path]['url']) ? $cache['content'][$folder][$path]['url'] : null; // only remove from URLs list if not in changed URLs list if (!isset($changed_urls[$url]) && !is_null($url)) { // remove from url cache unset($cache['urls'][$url]); } // remove from content cache unset($cache['content'][$folder][$path]); } } // build taxonomy cache // only happens if files were added, updated, or deleted above if ($files_changed) { $taxonomies = Config::getTaxonomies(); $force_lowercase = Config::getTaxonomyForceLowercase(); $case_sensitive = Config::getTaxonomyCaseSensitive(); $cache['taxonomies'] = array(); // rebuild taxonomies if (count($taxonomies)) { // set up taxonomy array foreach ($taxonomies as $taxonomy) { $cache['taxonomies'][$taxonomy] = array(); } // loop through content to build cached array foreach ($cache['content'] as $pages) { foreach ($pages as $item) { $data = $item['data']; // loop through the types of taxonomies foreach ($taxonomies as $taxonomy) { // if this file contains this type of taxonomy if (isset($data[$taxonomy])) { $values = Helper::ensureArray($data[$taxonomy]); // add the file name to the list of found files for a given taxonomy value foreach ($values as $value) { if (!$value) { continue; } $key = !$case_sensitive ? strtolower($value) : $value; if (!isset($cache['taxonomies'][$taxonomy][$key])) { $cache['taxonomies'][$taxonomy][$key] = array('name' => $force_lowercase ? strtolower($value) : $value, 'files' => array()); } array_push($cache['taxonomies'][$taxonomy][$key]['files'], $data['url']); } } } } } } // build structure cache $structure = array(); $home = Path::tidy('/' . Config::getSiteRoot() . '/'); foreach ($cache['content'] as $pages) { foreach ($pages as $item) { // set up base variables $parent = null; // Trim off home and any /page.md ending so that all URLs are treated // equally regardless of page type. $order_key = str_replace('/page.md', '', str_replace($home, '', $item['path'])); $sub_order_key = $item['data']['_order_key']; // does this have a parent (and if so, what is it?) if ($item['url'] !== $home) { $parent = $home; $depth = substr_count(str_replace($home, '/', $item['url']), '/'); $last_slash = strrpos($item['url'], '/', 1); $last_order_slash = strrpos($order_key, '/', 0); if ($last_slash !== false) { $parent = substr($item['url'], 0, $last_slash); } if ($last_order_slash !== false) { $order_key = substr($order_key, 0, $last_order_slash); } if ($item['data']['_is_page']) { $type = $item['data']['slug'] == 'page' ? 'folder' : 'page'; } else { $type = 'entry'; } } else { $depth = 0; $type = 'folder'; $order_key = $home; } $structure[$item['url']] = array('parent' => $parent, 'is_entry' => $item['data']['_is_entry'], 'is_page' => $item['data']['_is_page'], 'is_hidden' => $item['data']['_is_hidden'], 'is_draft' => $item['data']['_is_draft'], 'depth' => $depth, 'order_key' => $order_key ? $order_key : $sub_order_key, 'sub_order_key' => $sub_order_key, 'type' => $type); } } } // mark ending of content cache measuring Debug::markEnd($content_hash); if (!Config::get('disable_member_cache')) { // build member cache // ---------------------------------------------------------------- // start measuring $member_hash = Debug::markStart('caching', 'member'); // grab a list of existing members $users = File::globRecursively(Path::tidy(Config::getConfigPath() . '/users/*'), 'yaml'); // clone for reuse, set up our list of updated users $updated = array(); $current_users = array(); foreach ($users as $user) { $local_file = Path::trimFilesystemFromContent(Path::standardize($user)); // add to current users $current_users[] = $local_file; // is this updated? if ($last && File::getLastModified($user) >= $last) { $updated[] = $local_file; } } // get users from the file $members = unserialize(File::get($members_file)); // get a diff of users we know about and files currently existing $known_users = array(); if (!empty($members)) { foreach ($members as $username => $member_data) { $known_users[$username] = $member_data['_path']; } } // create a master list of users that need updating $changed_users = array_unique(array_merge(array_diff($current_users, $known_users), $updated)); $removed_users = array_diff($known_users, $current_users); if (count($changed_users)) { $members_changed = true; foreach ($changed_users as $user_file) { // file parsing $last_slash = strrpos($user_file, '/') + 1; $last_dot = strrpos($user_file, '.'); $username = substr($user_file, $last_slash, $last_dot - $last_slash); $content = substr(File::get($user_file), 3); $divide = strpos($content, "\n---"); $data = YAML::parse(trim(substr($content, 0, $divide))); $bio_raw = trim(substr($content, $divide + 4)); $data['_path'] = $user_file; if ($bio_raw) { $data['biography'] = 'true'; $data['biography_raw'] = 'true'; } $members[$username] = $data; } } // loop through all cached content for deleted files // this isn't as expensive as you'd think in real-world situations if (!empty($removed_users)) { $members_changed = true; $members = array_diff_key($members, $removed_users); } // mark ending of member cache measuring Debug::markEnd($member_hash); } // write to caches // -------------------------------------------------------------------- // add file-writing to content-cache actions $content_hash = Debug::markStart('caching', 'content'); if ($files_changed) { // store the content cache if (File::put($cache_file, serialize($cache)) === false) { if (!File::isWritable($cache_file)) { Log::fatal('Cache folder is not writable.', 'core', 'content-cache'); } Log::fatal('Could not write to the cache.', 'core', 'content-cache'); return false; } // store the structure cache if (File::put($structure_file, serialize($structure)) === false) { if (!File::isWritable($structure_file)) { Log::fatal('Structure cache file is not writable.', 'core', 'structure-cache'); } Log::fatal('Could not write to the structure cache.', 'core', 'structure-cache'); return false; } } // mark ending of content cache file write measuring Debug::markEnd($content_hash); // add file-writing to settings-cache actions $settings_hash = Debug::markStart('caching', 'settings'); // store the settings cache if ($settings_changed) { if (File::put($settings_file, serialize($settings)) === false) { if (!File::isWritable($settings_file)) { Log::fatal('Settings cache file is not writable.', 'core', 'settings-cache'); } Log::fatal('Could not write to the settings cache file.', 'core', 'settings-cache'); return false; } } // mark ending of settings cache file write measuring Debug::markEnd($settings_hash); if (!Config::get('disable_member_cache')) { // add file-writing to settings-cache actions $member_hash = Debug::markStart('caching', 'member'); // store the members cache if ($members_changed) { if (File::put($members_file, serialize($members)) === false) { if (!File::isWritable($members_file)) { Log::fatal('Member cache file is not writable.', 'core', 'member-cache'); } Log::fatal('Could not write to the member cache file.', 'core', 'member-cache'); return false; } } // mark ending of member cache file write measuring Debug::markEnd($member_hash); } File::put($time_file, $now - 1); return true; }