src/Component.php

Summary

Maintainability
C
7 hrs
Test Coverage
<?php

namespace BootPress\Blog;

use BootPress\Page\Component as Page;
use BootPress\Sitemap\Component as Sitemap;
use BootPress\Hierarchy\Component as Hierarchy;

/**
 * A flat file Blog and CMS that doesn't skimp on features, and can be utilized in any website.
 */
class Component extends Blog
{
    /**
     * Determine if there is any Blog content associated with the current url path.
     * 
     * @return mixed Either ``false`` if there is not a corresponding ``$page->url['path']`` Twig template, a string if ``$page->url['format'] != 'html'``, or an array suitable for passing to ``$blog->theme->renderTwig($file)`` with the following keys:
     *
     * - '**file**' => The appropriate Twig template that is equipped to deal with these '**type**' of '**vars**'.
     * - '**type**' => The kind of Blog page you are working with.  Either *'page'*, *'post'*, *'category'*, *'index'*, *'archives'*, *'authors'*, or *'tags'*.
     * - '**vars**' => For the Twig template to utilize.
     * - '**default**' => An alternate '**file**' to use if it's missing in your theme.
     *
     * ```php
     * if (is_array($file = $blog->page())) { // An 'index.html.twig' file
     *     $html = $blog->theme->renderTwig($file);
     * } elseif ($file !== false) { // A 'txt', 'json', 'xml', 'rdf', 'rss', or 'atom' page
     *     $page->send(Asset::dispatch($page->url['format'], $file));
     * }
     * ```
     */
    public function page()
    {
        $page = Page::html();
        $listings = $this->config('blog', 'listings');
        if ($page->url['format'] != 'html') {
            $file = (preg_match('/\.(txt|json|xml|rdf|rss|atom)$/', $page->url['path'])) ? $this->folder.'content/'.$page->url['path'].'.twig' : null;

            return (is_file($file)) ? trim($this->theme->renderTwig($file)) : false;
        } elseif ($id = $this->file($page->url['path'])) {
            $params = array('id' => $id, 'path' => $page->url['path']);
            $method = 'blog';
        } elseif ($route = $page->routes(array(
            $listings,
            $listings.'/[archives:path]/[i:year]?/[i:month]?/[i:day]?',
            $listings.'/[authors|tags:path]/[:name]?',
            '[**:category]',
        ))) {
            $params = $route['params'];
            $method = (isset($params['path'])) ? $params['path'] : 'listings';
            if ($method == 'listings' && $search = $page->request->query->get('search')) {
                $params['search'] = $search;
            }
        }
        if (!isset($method) || (isset($params['category']) && !is_dir($this->folder.'content/'.$params['category']))) {
            $template = false;
        } elseif ($template = $this->$method($params)) {
            $template = array_combine(array('file', 'type', 'vars'), $template);
            $template['default'] = __DIR__.'/templates/';
            $this->theme->vars['blog']->properties['page'] = $template['type'];
        }

        return $template;
    }

    private function blog($params, array $vars = array())
    {
        $page = Page::html();
        extract($params); // 'id' and 'path'
        $page->enforce($path);
        $info = $this->info($id);
        if (is_bool($info['published'])) {
            return array('blog-page.html.twig', 'post', $info);
        }
        $vars['post'] = $info;
        if ($search = $page->request->query->get('search')) {
            $sitemap = new Sitemap();
            if ($docid = $sitemap->db->value('SELECT docid FROM sitemap WHERE path = ?', $path)) {
                $words = $sitemap->words($search, $docid);
                if (!empty($words)) {
                    $vars['search'] = $words;
                }
            }
            unset($sitemap);
        }
        $vars['breadcrumbs'] = $this->breadcrumbs();
        foreach ($vars['post']['categories'] as $category) {
            $vars['breadcrumbs'][$category['name']] = $category['url'];
        }
        $vars['breadcrumbs'][$vars['post']['title']] = $vars['post']['url'];

        return array('blog-post.html.twig', 'post', $vars);
    }

    private function listings($params, array $vars = array())
    {
        $page = Page::html();
        extract($params); // 'path'?, 'category'? and 'search'?
        if (isset($category)) {
            $url = $page->url('base', $category);
        } else {
            $url = $page->url('blog/listings');
        }
        $page->enforce($url);
        $type = (isset($category)) ? 'category' : 'index';
        $vars['listings'] = array();
        $vars['breadcrumbs'] = $this->breadcrumbs();
        if (isset($category)) {
            $hier = new Hierarchy($this->db, 'categories');
            $path = $hier->path('path', $category, array('path', 'name'));
            if (empty($path)) {
                return false;
            }
            $tree = $hier->tree(array('path', 'name'), 'path', $category);
            $counts = $hier->counts('blog', 'category_id');
            foreach ($tree as $id => $fields) {
                $tree[$id]['count'] = (isset($counts[$id])) ? $counts[$id] : 0;
            }
            foreach ($path as $row) {
                $vars['category'][] = $row['name'];
                $vars['breadcrumbs'][$row['name']] = $page->url('base', $row['path']);
            }
            $vars['categories'] = $this->query('categories', array('nest' => $hier->nestify($tree), 'tree' => $tree));
            $vars['listings']['categories'] = array_keys($tree);
        }
        if (isset($search) && !empty($search)) {
            $vars['search'] = $search;
            $vars['breadcrumbs']['Search'] = $page->url('add', $url, 'search', $search);
            $vars['listings']['search'] = $search;
        }

        return array('blog-listings.html.twig', $type, $vars);
    }

    private function archives($params, array $vars = array())
    {
        $page = Page::html();
        list($path, $Y, $m, $d) = array_pad(array_values($params), 4, '');
        if (!empty($d)) {
            list($from, $to) = $this->range($Y, $m, $d);
            $page->enforce($page->url('blog/listings', $path, date('/Y/m/d', $from)));
            $vars['archive'] = array_combine(array('date', 'year', 'month', 'day'), explode(' ', date($from.' Y F j', $from)));
            $vars['breadcrumbs'] = $this->breadcrumbs(array(
                'Archives' => $path,
                $vars['archive']['year'] => $Y,
                $vars['archive']['month'] => $m,
                $vars['archive']['day'] => $d,
            ));
        } elseif (!empty($m)) {
            list($from, $to) = $this->range($Y, $m);
            $page->enforce($page->url('blog/listings', $path, date('/Y/m', $from)));
            $vars['archive'] = array_combine(array('date', 'year', 'month'), explode(' ', date($from.' Y F', $from)));
            $vars['breadcrumbs'] = $this->breadcrumbs(array(
                'Archives' => $path,
                $vars['archive']['year'] => $Y,
                $vars['archive']['month'] => $m,
            ));
        } elseif (!empty($Y)) {
            list($from, $to) = $this->range($Y);
            $page->enforce($page->url('blog/listings', $path, date('/Y', $from)));
            $vars['archive'] = array_combine(array('date', 'year'), explode(' ', date($from.' Y', $from)));
            $vars['breadcrumbs'] = $this->breadcrumbs(array(
                'Archives' => $path,
                $vars['archive']['year'] => $Y,
            ));
        } else {
            $page->enforce($page->url('blog/listings', $path));
            $vars['archives'] = $this->query('archives');
            $vars['breadcrumbs'] = $this->breadcrumbs(array(
                'Archives' => $path,
            ));

            return array('blog-archives.html.twig', 'archives', $vars);
        }
        $vars['listings']['archives'] = array($from, $to);

        return array('blog-listings.html.twig', 'archives', $vars);
    }

    private function authors($params, array $vars = array())
    {
        $page = Page::html();
        extract($params); // 'path' and 'name'?
        $vars['breadcrumbs'] = $this->breadcrumbs(array('Authors' => $path));
        if (!isset($name)) { // just authors, no posts
            $page->enforce($page->url('blog/listings', $path));
            $vars['authors'] = $this->query('authors');

            return array('blog-authors.html.twig', 'authors', $vars);
        }
        $vars['author'] = $this->query('authors', $name);
        if (empty($vars['author'])) {
            $page->eject($page->url('blog/listings', $path));

            return false;
        }
        $vars['breadcrumbs'][$vars['author']['name']] = $page->url('blog/listings', $path, $vars['author']['path']);
        $vars['listings']['count'] = $vars['author']['count'];
        $vars['listings']['authors'] = $name;

        return array('blog-listings.html.twig', 'authors', $vars);
    }

    private function tags($params, array $vars = array())
    {
        $page = Page::html();
        extract($params); // 'path' and 'name'?
        $vars['breadcrumbs'] = $this->breadcrumbs(array('Tags' => $path));
        if (!isset($name)) { // search all tags and get a frequency count
            $page->enforce($page->url('blog/listings', $path));
            $vars['tags'] = $this->query('tags');

            return array('blog-tags.html.twig', 'tags', $vars);
        }
        $vars['tag'] = $this->query('tags', $name);
        if (empty($vars['tag'])) {
            $page->eject($page->url('blog/listings', $path));

            return false;
        }
        $vars['breadcrumbs'][$vars['tag']['name']] = $page->url('blog/listings', $path, $vars['tag']['path']);
        $vars['listings']['count'] = $vars['tag']['count'];
        $vars['listings']['tags'] = $vars['tag']['path'];

        return array('blog-listings.html.twig', 'tags', $vars);
    }

    private function breadcrumbs(array $links = array())
    {
        $breadcrumbs = array();
        $breadcrumbs[$this->config('blog', 'breadcrumb')] = Page::html()->url('blog/listings');
        $previous = '';
        foreach ($links as $name => $path) {
            $breadcrumbs[$name] = Page::html()->url('blog/listings', $previous.$path);
            $previous .= $path.'/';
        }

        return $breadcrumbs;
    }

    private function range($Y, $m = null, $d = null)
    {
        if (!empty($d)) {
            $from = mktime(0, 0, 0, (int) $m, (int) $d, (int) $Y);
            $to = mktime(23, 59, 59, (int) $m, (int) $d, (int) $Y);
        } elseif (!empty($m)) {
            $from = mktime(0, 0, 0, (int) $m, 1, (int) $Y);
            $to = mktime(23, 59, 59, (int) $m + 1, 0, (int) $Y);
        } else {
            $from = mktime(0, 0, 0, 1, 1, (int) $Y);
            $to = mktime(23, 59, 59, 1, 0, (int) $Y + 1);
        }

        return array($from, $to);
    }
}