faq and blog refactor

This commit is contained in:
Jeremy Kauffman 2016-05-27 16:11:46 -04:00
parent e8acb4144b
commit 87c3e9f9de
51 changed files with 199 additions and 140 deletions

View file

@ -73,15 +73,21 @@ class Controller
case '/art':
return static::redirect('/what');
default:
$blogPattern = '#^' . BlogActions::URL_STEM . '(/|$)#';
if (preg_match($blogPattern, $uri))
$newsPattern = '#^' . ContentActions::URL_NEWS . '(/|$)#';
if (preg_match($newsPattern, $uri))
{
$slug = preg_replace($blogPattern, '', $uri);
if ($slug == BlogActions::RSS_SLUG)
$slug = preg_replace($newsPattern, '', $uri);
if ($slug == ContentActions::RSS_SLUG)
{
return BlogActions::executeRss();
return ContentActions::executeRss();
}
return $slug ? BlogActions::executePost($slug) : BlogActions::executeIndex();
return $slug ? ContentActions::executePost($uri) : ContentActions::executeNews();
}
$faqPattern = '#^' . ContentActions::URL_FAQ . '(/|$)#';
if (preg_match($faqPattern, $uri))
{
$slug = preg_replace($faqPattern, '', $uri);
return $slug ? ContentActions::executePost($uri) : ContentActions::executeFaq();
}
$noSlashUri = ltrim($uri, '/');
if (View::exists('page/' . $noSlashUri))

View file

@ -1,62 +0,0 @@
<?php
class BlogActions extends Actions
{
const URL_STEM = '/news';
const RSS_SLUG = 'rss.xml';
public static function executeIndex()
{
$posts = Blog::getPosts();
usort($posts, function(Post $a, Post $b) {
return strcasecmp($b->getDate()->format('Y-m-d'), $a->getDate()->format('Y-m-d'));
});
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
return ['blog/index', [
'posts' => $posts,
'page' => $page,
View::LAYOUT_PARAMS => [
'showRssLink' => true
]
]];
}
public static function executeRss()
{
$posts = Blog::getPosts();
usort($posts, function(Post $a, Post $b) {
return strcasecmp($b->getDate()->format('Y-m-d'), $a->getDate()->format('Y-m-d'));
});
return ['blog/rss', [
'posts' => array_slice($posts, 0, 10),
'_no_layout' => true
], [
'Content-Type' => 'text/xml; charset=utf-8'
]];
}
public static function executePost($slug)
{
$post = Blog::getPost($slug);
if (!$post)
{
return ['page/404', []];
}
return ['blog/post', [
'post' => $post,
View::LAYOUT_PARAMS => [
'showRssLink' => true
]
]];
}
public static function prepareAuthorPartial(array $vars)
{
$post = $vars['post'];
return [
'authorName' => $post->getAuthorName(),
'photoImgSrc' => $post->getAuthorPhoto(),
'authorBioHtml' => $post->getAuthorBioHtml()
];
}
}

View file

@ -7,6 +7,12 @@
*/
class ContentActions extends Actions
{
const RSS_SLUG = 'rss.xml',
URL_NEWS = '/news',
URL_FAQ = '/faq',
VIEW_FOLDER_NEWS = ROOT_DIR . '/posts/news',
VIEW_FOLDER_FAQ = ROOT_DIR . '/posts/faq';
public static function executeHome()
{
return ['page/home', [
@ -14,4 +20,60 @@ class ContentActions extends Actions
'totalPeople' => CreditApi::getTotalPeople()
]];
}
public static function executeFaq()
{
$posts = Post::find(static::VIEW_FOLDER_FAQ);
return ['content/faq', [
'posts' => $posts
]];
}
public static function executeNews()
{
$posts = Post::find(static::VIEW_FOLDER_NEWS, Post::SORT_DATE_DESC);
return ['content/news', [
'posts' => $posts,
View::LAYOUT_PARAMS => [
'showRssLink' => true
]
]];
}
public static function executeRss()
{
$posts = Post::find(static::VIEW_FOLDER_NEWS, Post::SORT_DATE_DESC);
return ['content/rss', [
'posts' => array_slice($posts, 0, 10),
'_no_layout' => true
], [
'Content-Type' => 'text/xml; charset=utf-8'
]];
}
public static function executePost($relativeUri)
{
$post = Post::load(ltrim($relativeUri, '/'));
if (!$post)
{
return ['page/404', []];
}
return ['content/post', [
'post' => $post,
View::LAYOUT_PARAMS => [
'showRssLink' => true
]
]];
}
public static function preparePostAuthorPartial(array $vars)
{
$post = $vars['post'];
return [
'authorName' => $post->getAuthorName(),
'photoImgSrc' => $post->getAuthorPhoto(),
'authorBioHtml' => $post->getAuthorBioHtml()
];
}
}

View file

@ -1,53 +0,0 @@
<?php
class Blog
{
protected static $slugMap = [];
public static function getPosts()
{
$posts = [];
foreach(static::getAllPostPaths() as $file)
{
$posts[] = Post::fromFile($file);
}
return $posts;
}
public static function getPost($slug)
{
static::initSlugMap();
if (isset(static::$slugMap[$slug]) && is_readable(static::$slugMap[$slug]))
{
return Post::fromFile(static::$slugMap[$slug]);
}
return null;
}
public static function getSlugFromFilename($filename)
{
return strtolower(preg_replace('#^\d+\-#', '', basename(trim($filename), '.md')));
}
protected static function initSlugMap()
{
if (!static::$slugMap)
{
foreach(static::getAllPostPaths() as $file)
{
static::$slugMap[static::getSlugFromFilename($file)] = $file;
}
}
}
protected static function getAllPostPaths()
{
return glob(ROOT_DIR . '/view/posts/*.md');
}
public static function getSlugMap()
{
static::initSlugMap();
return static::$slugMap;
}
}

View file

@ -2,17 +2,47 @@
class Post
{
protected $slug, $title, $author, $date, $markdown, $contentText, $contentHtml, $cover;
const SORT_DATE_DESC = 'sort_date_desc';
protected static $slugMap = [];
protected $slug, $title, $author, $date, $markdown, $contentText, $contentHtml, $cover, $category;
protected $isCoverLight = false;
public static function fromFile($filename)
public static function load($relativeOrAbsolutePath)
{
list($ignored, $frontMatter, $content) = explode('---', file_get_contents($filename), 3);
return new static(Blog::getSlugFromFilename($filename), Spyc::YAMLLoadString(trim($frontMatter)), trim($content));
$pathTokens = explode('/', $relativeOrAbsolutePath);
if (count($pathTokens) <= 1)
{
throw new LogicException('Cannot load a post without a path.');
}
$category = $pathTokens[count($pathTokens) - 2];
$filename = $pathTokens[count($pathTokens) - 1];
$isRelative = $relativeOrAbsolutePath[0] != '/';
$slug = static::getSlugFromFilename($filename);
$path = ($isRelative ? ROOT_DIR . '/posts/' : '') .
$relativeOrAbsolutePath .
(substr($filename, -3) !== '.md' ? '.md' : '');
if (!file_exists($path) && $isRelative) //may have come in without a post number
{
if ($isRelative)
{
$slugMap = static::getSlugMap($category);
if (isset($slugMap[$slug]))
{
return static::load($slugMap[$slug]);
}
}
throw new InvalidArgumentException('No post found for path: ' . $relativeOrAbsolutePath);
}
list($ignored, $frontMatter, $content) = explode('---', file_get_contents($path), 3);
return new static($category, $slug, Spyc::YAMLLoadString(trim($frontMatter)), trim($content));
}
public function __construct($slug, $frontMatter, $markdown)
public function __construct($category, $slug, $frontMatter, $markdown)
{
$this->category = $category;
$this->slug = $slug;
$this->markdown = $markdown;
$this->title = isset($frontMatter['title']) ? $frontMatter['title'] : null;
@ -22,9 +52,30 @@ class Post
$this->isCoverLight = isset($frontMatter['cover-light']) && $frontMatter['cover-light'] == 'true';
}
public static function find($folder, $sort = null)
{
$posts = [];
foreach(glob(rtrim($folder, '/') . '/*.md') as $file)
{
$posts[] = static::load($file);
}
if ($sort)
{
switch ($sort)
{
case static::SORT_DATE_DESC:
usort($posts, function(Post $a, Post $b) {
return strcasecmp($b->getDate()->format('Y-m-d'), $a->getDate()->format('Y-m-d'));
});
break;
}
}
return $posts;
}
public function getRelativeUrl()
{
return BlogActions::URL_STEM . '/' . $this->slug;
return $this->category . '/' . $this->slug;
}
public function getSlug()
@ -79,21 +130,26 @@ class Post
public function getPostNum()
{
return array_search($this->getSlug(), array_keys(Blog::getSlugMap()));
return array_search($this->getSlug(), array_keys(static::getSlugMap($this->category)));
}
public function getPrevPost()
{
$slugs = array_keys(Blog::getSlugMap());
$slugs = array_keys(Post::getSlugMap($this->category));
$postNum = $this->getPostNum();
return $postNum === false || $postNum === 0 ? null : Blog::getPost($slugs[$postNum-1]);
return $postNum === false || $postNum === 0 ? null : Post::load($this->category . '/' . $slugs[$postNum-1]);
}
public function getNextPost()
{
$slugs = array_keys(Blog::getSlugMap());
$slugs = array_keys(Post::getSlugMap($this->category));
$postNum = $this->getPostNum();
return $postNum === false || $postNum >= count($slugs)-1 ? null : Blog::getPost($slugs[$postNum+1]);
return $postNum === false || $postNum >= count($slugs)-1 ? null : Post::load($this->category . '/' . $slugs[$postNum+1]);
}
public function hasAuthor()
{
return $this->author !== null;
}
public function getAuthorName()
@ -108,6 +164,9 @@ class Post
return 'Jimmy Kiselak';
case 'jack':
return 'Jack Robison';
case null:
case '':
return '';
case 'lbry':
default:
return 'Samuel Bryan';
@ -221,4 +280,22 @@ class Post
return $string;
}
public static function getSlugFromFilename($filename)
{
return strtolower(preg_replace('#^\d+\-#', '', basename(trim($filename), '.md')));
}
public static function getSlugMap($category)
{
if (!isset(static::$slugMap[$category]))
{
static::$slugMap[$category] = [];
foreach(glob(ROOT_DIR . '/posts/' . $category . '/*.md') as $file)
{
static::$slugMap[$category][static::getSlugFromFilename($file)] = $file;
}
}
return static::$slugMap[$category];
}
}

View file

@ -0,0 +1,6 @@
---
title: Is LBRY Open Source?
date: '2015-05-24 16:00:00'
---
All of the code we have written for LBRY is open source - even this very website! You can access it on [GitHub](https://github.com/lbryio/).

View file

@ -0,0 +1,13 @@
<?php Response::setMetaDescription('Frequently asked questions about LBRY.') ?>
<?php echo View::render('nav/header', ['isDark' => false]) ?>
<main>
<section class="content content-readable spacer2">
<h1>Frequently Asked Questions</h1>
<?php foreach($posts as $post): ?>
<div class="spacer1">
<a href="<?php echo $post->getRelativeUrl() ?>" class="link-primary"><?php echo $post->getTitle() ?></a>
</div>
<?php endforeach ?>
</section>>
</main>
<?php echo View::render('nav/footer') ?>

View file

@ -9,7 +9,7 @@
<h1><?php echo htmlentities($post->getTitle()) ?></h1>
<div class="meta spacer1">
<?php echo $post->getAuthorName() ?>
&bull;
<?php echo $post->hasAuthor() ? '&bull;' : '' ?>
<span title="<?php echo $post->getDate()->format('F jS, Y') ?>"><?php echo $post->getDate()->format('M j') ?></span>
</div>
</div>
@ -51,9 +51,11 @@
</nav>
</div>
<?php echo View::render('blog/_author', [
'post' => $post
]) ?>
<?php if ($post->hasAuthor()): ?>
<?php echo View::render('content/_postAuthor', [
'post' => $post
]) ?>
<?php endif ?>
</main>
<?php echo View::render('nav/footer') ?>

View file

@ -2,12 +2,12 @@
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>LBRY News</title>
<link>https://lbry.io<?php echo BlogActions::URL_STEM ?></link>
<link>https://lbry.io<?php echo ContentActions::URL_NEWS ?></link>
<description>Recent news about LBRY</description>
<generator>https://github.com/lbryio/lbry.io</generator>
<language>en</language>
<?php //<lastBuildDate>Sat, 07 Sep 2002 09:42:31 GMT</lastBuildDate> ?>
<atom:link href="https://lbry.io<?php echo BlogActions::URL_STEM . '/' . BlogActions::RSS_SLUG ?>" rel="self" type="application/rss+xml" />
<atom:link href="https://lbry.io<?php echo ContentActions::URL_NEWS . '/' . ContentActions::RSS_SLUG ?>" rel="self" type="application/rss+xml" />
<?php foreach ($posts as $post): ?>
<item>
<title><?php echo htmlspecialchars($post->getTitle()) ?></title>

View file

@ -26,7 +26,7 @@
<link rel="icon" type="image/png" href="/img/fav/favicon-16x16.png" sizes="16x16">
<link rel="manifest" href="/img/fav/manifest.json">
<?php if(isset($showRssLink) && $showRssLink): ?>
<link rel="alternate" type="application/rss+xml" title="LBRY News" href="<?php echo BlogActions::URL_STEM . '/' . BlogActions::RSS_SLUG ?>" />
<link rel="alternate" type="application/rss+xml" title="LBRY News" href="<?php echo ContentActions::URL_NEWS . '/' . ContentActions::RSS_SLUG ?>" />
<?php endif ?>
<meta name="description" content="<?php echo Response::getMetaDescription() ?>">

View file

@ -19,7 +19,6 @@
.post-header
{
margin-bottom: $spacing-vertical * 2;
min-height: 100vh;
&.no-cover1 { // diagonal stripes
background-color: $color-primary;
@ -79,6 +78,15 @@
@media (min-height: 500px) {
.post-header {
min-height: 500px;
&:not(.with-cover)
{
min-height: 250px;
}
}
}
@media (max-height: 500px) {
.post-header {
min-height: 100vh;
}
}