Example #1
0
 /**
  * Filters the current content set down based on the filters given
  *
  * @param array  $filters  Filters to use to narrow down content
  * @return void
  * @throws Exception
  */
 public function filter($filters)
 {
     $hash = Debug::markStart('content', 'filtering');
     $filters = Helper::ensureArray($filters);
     // nothing to filter, abort
     if (!$this->count()) {
         return;
     }
     $since_date = null;
     $until_date = null;
     $remove_hidden = null;
     $remove_drafts = null;
     $keep_type = "all";
     $folders = null;
     $conditions = null;
     $located = false;
     $where = null;
     // standardize filters
     // -------------------
     $given_filters = $filters;
     $filters = array('show_hidden' => isset($given_filters['show_hidden']) ? $given_filters['show_hidden'] : null, 'show_drafts' => isset($given_filters['show_drafts']) ? $given_filters['show_drafts'] : null, 'since' => isset($given_filters['since']) ? $given_filters['since'] : null, 'until' => isset($given_filters['until']) ? $given_filters['until'] : null, 'show_past' => isset($given_filters['show_past']) ? $given_filters['show_past'] : null, 'show_future' => isset($given_filters['show_future']) ? $given_filters['show_future'] : null, 'type' => isset($given_filters['type']) ? strtolower($given_filters['type']) : null, 'folders' => isset($given_filters['folders']) ? $given_filters['folders'] : null, 'conditions' => isset($given_filters['conditions']) ? $given_filters['conditions'] : null, 'located' => isset($given_filters['located']) ? $given_filters['located'] : null, 'where' => isset($given_filters['where']) ? $given_filters['where'] : null);
     // determine filters
     // -----------------
     if (!is_null($filters['show_hidden'])) {
         $remove_hidden = !(bool) $filters['show_hidden'];
     }
     if (!is_null($filters['show_drafts'])) {
         $remove_drafts = !(bool) $filters['show_drafts'];
     }
     if ($filters['since']) {
         $since_date = Date::resolve($filters['since']);
     }
     if ($filters['show_past'] === false && (!$since_date || $since_date < time())) {
         $since_date = Config::getEntryTimestamps() ? time() : Date::resolve("today midnight");
     }
     if ($filters['until']) {
         $until_date = Date::resolve($filters['until']);
     }
     if ($filters['show_future'] === false && (!$until_date || $until_date > time())) {
         $until_date = Config::getEntryTimestamps() ? time() : Date::resolve("tomorrow midnight") - 1;
     }
     if ($filters['type'] === "entries" || $filters['type'] === "pages") {
         $keep_type = $filters['type'];
     }
     if ($filters['folders']) {
         $folders = Parse::pipeList($filters['folders']);
     }
     if ($filters['conditions']) {
         $conditions = Parse::conditions($filters['conditions']);
     }
     if ($filters['located']) {
         $located = true;
     }
     if ($filters['where']) {
         $where = $filters['where'];
     }
     // before we run filters, we need to look through conditions if they
     // were set to see if we're going to need content or content_raw
     // -----------
     if ($conditions) {
         // check for conditions involving content
         $uses_content = false;
         foreach ($conditions as $field => $instructions) {
             if (strtolower($field) === 'content') {
                 $uses_content = true;
                 break;
             }
         }
         // this uses content, which means we need to load it for all content
         if ($uses_content) {
             $this->prepare(true, false);
             $this->content_parsed = false;
         }
     }
     // run filters
     // -----------
     foreach ($this->content as $key => $data) {
         // entry or page removal
         if ($keep_type === "pages" && !$data['_is_page']) {
             unset($this->content[$key]);
             continue;
         } elseif ($keep_type === "entries" && !$data['_is_entry']) {
             unset($this->content[$key]);
             continue;
         }
         // check for non-public content
         if ($remove_drafts && $data['_is_draft']) {
             unset($this->content[$key]);
             continue;
         }
         if ($remove_hidden && $data['_is_hidden']) {
             unset($this->content[$key]);
             continue;
         }
         // folder
         if ($folders) {
             $keep = false;
             foreach ($folders as $folder) {
                 if ($folder === "*" || $folder === "/*") {
                     // include all
                     $keep = true;
                     break;
                 } elseif (substr($folder, -1) === "*") {
                     // wildcard check
                     if (strpos($data['_folder'], substr($folder, 0, -1)) === 0) {
                         $keep = true;
                         break;
                     }
                 } else {
                     // plain check
                     if ($folder == $data['_folder']) {
                         $keep = true;
                         break;
                     }
                 }
             }
             if (!$keep) {
                 unset($this->content[$key]);
                 continue;
             }
         }
         // since & show past
         if ($since_date && $data['datestamp'] && $data['datestamp'] < $since_date) {
             unset($this->content[$key]);
             continue;
         }
         // until & show future
         if ($until_date && $data['datestamp'] && $data['datestamp'] > $until_date) {
             unset($this->content[$key]);
             continue;
         }
         // where
         if ($where && !(bool) Parse::template("{{ if " . $where . " }}1{{ else }}0{{ endif }}", $data)) {
             unset($this->content[$key]);
             continue;
         }
         // conditions
         if ($conditions) {
             $case_sensitive_taxonomies = Config::getTaxonomyCaseSensitive();
             foreach ($conditions as $field => $instructions) {
                 $optional = substr($field, -1, 1) == '?';
                 $field = $optional ? trim(substr($field, 0, -1)) : $field;
                 try {
                     // are we looking for existence?
                     if ($instructions['kind'] === "existence") {
                         if ($instructions['type'] === "has") {
                             if (!isset($data[$field]) || !$data[$field]) {
                                 throw new Exception("Does not fit condition");
                             }
                         } elseif ($instructions['type'] === "lacks") {
                             if (isset($data[$field]) && $data[$field]) {
                                 throw new Exception("Does not fit condition");
                             }
                         } else {
                             throw new Exception("Unknown existence type");
                         }
                         // are we looking for a comparison?
                     } elseif ($instructions['kind'] === "comparison") {
                         $is_taxonomy = Taxonomy::isTaxonomy($field);
                         $case_sensitive = $is_taxonomy && $case_sensitive_taxonomies;
                         if (!isset($data[$field])) {
                             $field = false;
                             $values = null;
                         } else {
                             if ($case_sensitive) {
                                 $field = $data[$field];
                                 $values = $instructions['value'];
                             } else {
                                 $field = is_array($data[$field]) ? array_map('strtolower', $data[$field]) : strtolower($data[$field]);
                                 $values = is_array($instructions['value']) ? array_map('strtolower', $instructions['value']) : strtolower($instructions['value']);
                             }
                         }
                         // convert boolean-like statements to boolean values
                         if (is_array($values)) {
                             foreach ($values as $item => $value) {
                                 if ($value == "true" || $value == "yes") {
                                     $values[$item] = true;
                                 } elseif ($value == "false" || $value == "no") {
                                     $values[$item] = false;
                                 }
                             }
                         } else {
                             if ($values == "true" || $values == "yes") {
                                 $values = true;
                             } elseif ($values == "false" || $values == "no") {
                                 $values = false;
                             }
                         }
                         // convert date-like statements to timestamps for qualitative comparisons (not equals)
                         if (in_array($instructions['type'], array('greater than or equal to', 'greater than', 'less than or equal to', 'less than'))) {
                             if (!is_array($field) && !is_numeric($field) && Date::resolve($field) !== false) {
                                 $field = Date::resolve($field);
                             }
                             if (!is_array($values) && !is_numeric($values) && Date::resolve($values) !== false) {
                                 $values = Date::resolve($values);
                             }
                         }
                         // equal comparisons
                         if ($instructions['type'] == "equal") {
                             // if this isn't set, it's not equal
                             if (!$field) {
                                 throw new Exception("Field not set", 1);
                             }
                             if (!is_array($field)) {
                                 if ($field != $values) {
                                     throw new Exception("Does not fit condition", 0);
                                 }
                             } elseif (!in_array($values, $field)) {
                                 throw new Exception("Does not fit condition", 0);
                             }
                             // greater than or equal to comparisons
                         } elseif ($instructions['type'] == "greater than or equal to") {
                             // if this isn't set, it's not greater than or equal to
                             if (!$field) {
                                 throw new Exception("Field not set", 1);
                             }
                             if (is_array($field) || is_array($values)) {
                                 throw new Exception("Does not fit condition", 0);
                             }
                             if (!is_numeric($field) && Date::resolve($field) !== false) {
                                 $field = Date::resolve($field);
                             }
                             if (!is_numeric($values) && Date::resolve($values) !== false) {
                                 $values = Date::resolve($values);
                             }
                             if (!is_numeric($field) || !is_numeric($values) || $this->toNumber($field) < $this->toNumber($values)) {
                                 throw new Exception("Does not fit condition", 0);
                             }
                             // greater than to comparisons
                         } elseif ($instructions['type'] == "greater than") {
                             // if this isn't set, it's not less than
                             if (!$field) {
                                 throw new Exception("Field not set", 1);
                             }
                             if (is_array($field) || is_array($values)) {
                                 throw new Exception("Does not fit condition", 0);
                             }
                             if (!is_numeric($field) && Date::resolve($field) !== false) {
                                 $field = Date::resolve($field);
                             }
                             if (!is_numeric($values) && Date::resolve($values) !== false) {
                                 $values = Date::resolve($values);
                             }
                             if (!is_numeric($field) || !is_numeric($values) || $this->toNumber($field) <= $this->toNumber($values)) {
                                 throw new Exception("Does not fit condition", 0);
                             }
                             // less than or equal to comparisons
                         } elseif ($instructions['type'] == "less than or equal to") {
                             // if this isn't set, it's not less than or equal to
                             if (!$field) {
                                 throw new Exception("Field not set", 1);
                             }
                             if (is_array($field) || is_array($values)) {
                                 throw new Exception("Does not fit condition", 0);
                             }
                             if (!is_numeric($field) && Date::resolve($field) !== false) {
                                 $field = Date::resolve($field);
                             }
                             if (!is_numeric($values) && Date::resolve($values) !== false) {
                                 $values = Date::resolve($values);
                             }
                             if (!is_numeric($field) || !is_numeric($values) || $this->toNumber($field) > $this->toNumber($values)) {
                                 throw new Exception("Does not fit condition", 0);
                             }
                             // less than to comparisons
                         } elseif ($instructions['type'] == "less than") {
                             // if this isn't set, it's not less than
                             if (!$field) {
                                 throw new Exception("Field not set", 1);
                             }
                             if (is_array($field) || is_array($values)) {
                                 throw new Exception("Does not fit condition", 0);
                             }
                             if (!is_numeric($field) && Date::resolve($field) !== false) {
                                 $field = Date::resolve($field);
                             }
                             if (!is_numeric($values) && Date::resolve($values) !== false) {
                                 $values = Date::resolve($values);
                             }
                             if (!is_numeric($field) || !is_numeric($values) || $this->toNumber($field) >= $this->toNumber($values)) {
                                 throw new Exception("Does not fit condition", 0);
                             }
                             // not-equal comparisons
                         } elseif ($instructions['type'] == "not equal") {
                             // if this isn't set, it's not equal, continue
                             if (!$field) {
                                 continue;
                             }
                             if (!is_array($field)) {
                                 if ($field == $values) {
                                     throw new Exception("Does not fit condition", 0);
                                 }
                             } elseif (in_array($values, $field)) {
                                 throw new Exception("Does not fit condition", 0);
                             }
                             // contains array comparisons
                         } elseif ($instructions['type'] == "in") {
                             if (!$field) {
                                 throw new Exception("Field not set", 1);
                             }
                             if (!count(array_intersect(Helper::ensureArray($field), $values))) {
                                 throw new Exception("Does not fit condition", 0);
                             }
                             // doesn't contain array comparisons
                         } elseif ($instructions['type'] == "not in") {
                             if (!$field) {
                                 throw new Exception("Field not set", 1);
                             }
                             if (count(array_intersect(Helper::ensureArray($field), $values))) {
                                 throw new Exception("Does not fit condition", 0);
                             }
                             // contains contains-text comparisons
                         } elseif ($instructions['type'] == 'contains text') {
                             if (!$field) {
                                 throw new Exception("Field not set", 1);
                             }
                             $field = Helper::ensureArray($field);
                             $found = false;
                             foreach ($field as $option) {
                                 // do we need to loop through values?
                                 if (is_array($values)) {
                                     // we do
                                     foreach ($values as $value) {
                                         if (strpos($option, strtolower($value)) !== false) {
                                             $found = true;
                                             break;
                                         }
                                     }
                                     if ($found) {
                                         break;
                                     }
                                 } else {
                                     // we don't
                                     if (strpos($option, strtolower($values)) !== false) {
                                         $found = true;
                                         break;
                                     }
                                 }
                             }
                             if (!$found) {
                                 throw new Exception("Does not fit condition", 0);
                             }
                         }
                         // we don't know what this is
                     } else {
                         throw new Exception("Unknown kind of condition", -1);
                     }
                 } catch (Exception $e) {
                     if ($optional && $e->getCode() === 1) {
                         // we were only making the comparison if the field exists,
                         // otherwise, this is ok
                         continue;
                     }
                     // this was not an optional field, and something went wrong
                     unset($this->content[$key]);
                     continue;
                 }
             }
         }
         // located
         if ($located && !isset($data['coordinates'])) {
             unset($this->content[$key]);
             continue;
         }
     }
     Debug::markEnd($hash);
 }
    ?>
</label>
          <div class="field">
            <span class="ss-icon">calendar</span>
            <input name="page[meta][publish-date]" tabindex="<?php 
    print tabindex();
    ?>
" type="text" id="publish-date"  value="<?php 
    print date("Y-m-d", $datestamp);
    ?>
" class="datepicker" />
          </div>
        </div>

        <?php 
    if (Config::getEntryTimestamps()) {
        ?>
        <div class="input-block input-time time required bootstrap-timepicker<?php 
        if (array_get($fields, 'time:hide', false) === true) {
            ?>
 hidden<?php 
        }
        ?>
" data-date="<?php 
        print date("h:i a", $timestamp);
        ?>
" data-date-format="h:i a">
          <label><?php 
        echo Localization::fetch('publish_time');
        ?>
</label>
Example #3
0
 /**
  * Cleans up a given $path, removing any order keys (date-based or number-based)
  *
  * @param string  $path  Path to clean
  * @return string
  */
 public static function clean($path)
 {
     // remove draft and hidden flags
     $path = preg_replace("#/_[_]?#", "/", $path);
     // if we don't want entry timestamps, handle things manually
     if (!Config::getEntryTimestamps()) {
         $file = substr($path, strrpos($path, "/"));
         // trim path if needed
         if (-strlen($file) + 1 !== 0) {
             $path = substr($path, 0, -strlen($file) + 1);
         }
         $path = preg_replace(Pattern::ORDER_KEY, "", $path);
         $pattern = preg_match(Pattern::DATE, $file) ? Pattern::DATE : Pattern::ORDER_KEY;
         $file = preg_replace($pattern, "", $file);
         return Path::tidy($path . $file);
     }
     // otherwise, just remove all order-keys
     return preg_replace(Pattern::ORDER_KEY, "", $path);
 }
Example #4
0
 public static function get_content_tree($directory = '/', $depth = 1, $max_depth = 5, $folders_only = false, $include_entries = false, $hide_hidden = true, $include_content = false, $site_root = false)
 {
     // $folders_only = true only page.md
     // folders_only = false includes any numbered or non-numbered page (excluding anything with a fields.yaml file)
     // if include_entries is true then any numbered files are included
     $content_root = Config::getContentRoot();
     $content_type = Config::getContentType();
     $site_root = $site_root ? $site_root : Config::getSiteRoot();
     $current_url = Path::tidy($site_root . '/' . Request::getResourceURI());
     $taxonomy_url = false;
     if (Taxonomy::isTaxonomyURL($current_url)) {
         list($taxonomy_type, $taxonomy_name) = Taxonomy::getCriteria($current_url);
         $taxonomy_url = self::remove_taxonomy_from_path($current_url, $taxonomy_type, $taxonomy_name);
     }
     $directory = '/' . $directory . '/';
     #ensure proper slashing
     if ($directory != '/') {
         $base = Path::tidy("{$content_root}/{$directory}");
     } elseif ($directory == '/') {
         $base = "{$content_root}";
     } else {
         $base = "{$content_root}";
     }
     $files = glob("{$base}/*");
     $data = array();
     if ($files) {
         foreach ($files as $path) {
             $current_name = basename($path);
             if (!Pattern::endsWith($current_name, '.yaml')) {
                 // Hidden page that should be removed
                 if ($hide_hidden && Pattern::startsWith($current_name, '_')) {
                     continue;
                 }
                 $node = array();
                 $file = substr($path, strlen($base) + 1, strlen($path) - strlen($base) - strlen($content_type) - 2);
                 if (is_dir($path)) {
                     $folder = substr($path, strlen($base) + 1);
                     $node['type'] = 'folder';
                     $node['slug'] = basename($folder);
                     $node['title'] = ucwords(basename($folder));
                     $node['numeric'] = Slug::getOrderNumber($folder);
                     $node['file_path'] = Path::tidy($site_root . '/' . $directory . '/' . $folder . '/page');
                     if (Slug::isNumeric($folder)) {
                         $pos = strpos($folder, ".");
                         if ($pos !== false) {
                             $node['raw_url'] = Path::tidy(Path::clean($site_root . '/' . $directory . '/' . $folder));
                             $node['url'] = Path::clean($node['raw_url']);
                             $node['title'] = ucwords(basename(substr($folder, $pos + 1)));
                         } else {
                             $node['title'] = ucwords(basename($folder));
                             $node['raw_url'] = Path::tidy($site_root . '/' . $directory . '/' . $folder);
                             $node['url'] = Path::clean($node['raw_url']);
                         }
                     } else {
                         $node['title'] = ucwords(basename($folder));
                         $node['raw_url'] = Path::tidy($site_root . '/' . $directory . '/' . $folder);
                         $node['url'] = Path::clean($node['raw_url']);
                     }
                     $node['depth'] = $depth;
                     $node['children'] = $depth < $max_depth ? self::get_content_tree($directory . $folder . '/', $depth + 1, $max_depth, $folders_only, $include_entries, $hide_hidden, $include_content, $site_root) : null;
                     $node['is_current'] = $node['raw_url'] == $current_url || $node['url'] == $current_url ? true : false;
                     $node['is_parent'] = false;
                     if ($node['url'] == URL::popLastSegment($current_url) || $taxonomy_url && $node['url'] == $taxonomy_url) {
                         $node['is_parent'] = true;
                     }
                     $node['has_children'] = $node['children'] ? true : false;
                     // has entries?
                     if (File::exists(Path::tidy($path . "/fields.yaml"))) {
                         $node['has_entries'] = true;
                     } else {
                         $node['has_entries'] = false;
                     }
                     $meta = self::get_content_meta("page", Path::tidy($directory . "/" . $folder), false, true);
                     //$meta = self::get_content_meta("page", Statamic_Helper::reduce_double_slashes($directory."/".$folder));
                     if (isset($meta['title'])) {
                         $node['title'] = $meta['title'];
                     }
                     if (isset($meta['last_modified'])) {
                         $node['last_modified'] = $meta['last_modified'];
                     }
                     if ($hide_hidden === true && (isset($meta['status']) && ($meta['status'] == 'hidden' || $meta['status'] == 'draft'))) {
                         // placeholder condition
                     } else {
                         $data[] = $include_content ? array_merge($meta, $node) : $node;
                         // print_r($data);
                     }
                 } else {
                     if (Pattern::endsWith($path, $content_type)) {
                         if ($folders_only == false) {
                             if ($file == 'page' || $file == 'feed' || $file == '404') {
                                 // $node['url'] = $directory;
                                 // $node['title'] = basename($directory);
                                 // $meta = self::get_content_meta('page', substr($directory, 1));
                                 // $node['depth'] = $depth;
                             } else {
                                 $include = true;
                                 // date based is never included
                                 if (Config::getEntryTimestamps() && Slug::isDateTime(basename($path))) {
                                     $include = false;
                                 } elseif (Slug::isDate(basename($path))) {
                                     $include = false;
                                 } elseif (Slug::isNumeric(basename($path))) {
                                     if ($include_entries == false) {
                                         if (File::exists(Path::tidy(dirname($path) . "/fields.yaml"))) {
                                             $include = false;
                                         }
                                     }
                                 }
                                 if ($include) {
                                     $node['type'] = 'file';
                                     $node['raw_url'] = Path::tidy($directory) . basename($path);
                                     $pretty_url = Path::clean($node['raw_url']);
                                     $node['url'] = substr($pretty_url, 0, -1 * (strlen($content_type) + 1));
                                     $node['is_current'] = $node['url'] == $current_url || $node['url'] == $current_url ? true : false;
                                     $node['slug'] = substr(basename($path), 0, -1 * (strlen($content_type) + 1));
                                     $meta = self::get_content_meta(substr(basename($path), 0, -1 * (strlen($content_type) + 1)), substr($directory, 1), false, true);
                                     //$node['meta'] = $meta;
                                     if (isset($meta['title'])) {
                                         $node['title'] = $meta['title'];
                                     }
                                     $node['depth'] = $depth;
                                     if ($hide_hidden === true && (isset($meta['status']) && ($meta['status'] == 'hidden' || $meta['status'] == 'draft'))) {
                                     } else {
                                         $data[] = $include_content ? array_merge($meta, $node) : $node;
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     return $data;
 }
Example #5
0
     $data['fields'] = $fieldset_data['fields'];
 } else {
     # not set.
     $data['fields'] = array();
 }
 $data['type'] = isset($fields_data['type']) && !is_array($fields_data['type']) ? $fields_data['type'] : $fields_data['type']['prefix'];
 // Slug
 if (Slug::isDraft($page)) {
     $slug = substr($page, 2);
 } elseif (Slug::isHidden($page)) {
     $slug = substr($page, 1);
 } else {
     $slug = $page;
 }
 if ($data['type'] == 'date') {
     if (Config::getEntryTimestamps() && Slug::isDateTime($page)) {
         $data['full_slug'] = $folder;
         $data['original_slug'] = substr($slug, 16);
         $data['slug'] = substr($slug, 16);
         $data['original_datestamp'] = substr($slug, 0, 10);
         $data['original_timestamp'] = substr($slug, 11, 4);
         if (!$new) {
             $data['datestamp'] = strtotime(substr($slug, 0, 10));
             $data['timestamp'] = strtotime(substr($slug, 0, 10) . " " . substr($slug, 11, 4));
             $data['full_slug'] = $folder . "/" . $data['original_slug'];
         }
     } else {
         $data['full_slug'] = $folder;
         $data['original_slug'] = substr($slug, 11);
         $data['slug'] = substr($slug, 11);
         $data['original_datestamp'] = substr($slug, 0, 10);
 /**
  * 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;
 }
Example #7
0
File: path.php Project: nob/joi
 /**
  * Finds a given path on the server, adding in any ordering elements missing
  *
  * @param string  $path  Path to resolve
  * @return string
  */
 public static function resolve($path)
 {
     $content_root = Config::getContentRoot();
     $content_type = Config::getContentType();
     if (strpos($path, "/") === 0) {
         $parts = explode("/", substr($path, 1));
     } else {
         $parts = explode("/", $path);
     }
     $fixedpath = "/";
     foreach ($parts as $part) {
         if (!File::exists(URL::assemble($content_root, $path . '.' . $content_type)) && !is_dir(URL::assemble($content_root, $part))) {
             // check folders
             $list = Statamic::get_content_tree($fixedpath, 1, 1, FALSE, TRUE, FALSE);
             foreach ($list as $item) {
                 $t = basename($item['slug']);
                 if (Slug::isNumeric($t)) {
                     $nl = strlen(Slug::getOrderNumber($t)) + 1;
                     if (strlen($part) >= strlen($item['slug']) - $nl && Pattern::endsWith($item['slug'], $part)) {
                         $part = $item['slug'];
                         break;
                     }
                 } else {
                     if (Pattern::endsWith($item['slug'], $part)) {
                         if (strlen($part) >= strlen($t)) {
                             $part = $item['slug'];
                             break;
                         }
                     }
                 }
             }
             // check files
             $list = Statamic::get_file_list($fixedpath);
             foreach ($list as $key => $item) {
                 if (Pattern::endsWith($key, $part)) {
                     $t = basename($item);
                     $offset = 0;
                     if (Pattern::startsWith($key, '__')) {
                         $offset = 2;
                     } elseif (Pattern::startsWith($key, '_')) {
                         $offset = 1;
                     }
                     if (Config::getEntryTimestamps() && Slug::isDateTime($t)) {
                         if (strlen($part) >= strlen($key) - 16 - $offset) {
                             $part = $key;
                             break;
                         }
                     } elseif (Slug::isDate($t)) {
                         if (strlen($part) >= strlen($key) - 12 - $offset) {
                             $part = $key;
                             break;
                         }
                     } elseif (Slug::isNumeric($t)) {
                         $nl = strlen(Slug::getOrderNumber($key)) + 1;
                         if (strlen($part) >= strlen($key) - $nl - $offset) {
                             $part = $key;
                             break;
                         }
                     } else {
                         $t = basename($item);
                         if (strlen($part) >= strlen($t) - $offset) {
                             $part = $key;
                             break;
                         }
                     }
                 }
             }
         }
         if ($fixedpath != '/') {
             $fixedpath .= '/';
         }
         $fixedpath .= $part;
     }
     // /2-blog/hidden
     return $fixedpath;
 }