mirror of
https://github.com/LBRYFoundation/lbry.com.git
synced 2025-08-23 17:47:26 +00:00
rss feed for news, better header handling
This commit is contained in:
parent
af8c4869e5
commit
67ff1018c3
13 changed files with 253 additions and 33 deletions
|
@ -1,12 +1,9 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Description of Controller
|
||||
*
|
||||
* @author jeremy
|
||||
*/
|
||||
class Controller
|
||||
{
|
||||
const HEADER_STATUS = 'Status';
|
||||
|
||||
public static function dispatch($uri)
|
||||
{
|
||||
try
|
||||
|
@ -14,6 +11,9 @@ class Controller
|
|||
$viewAndParams = static::execute($uri);
|
||||
$viewTemplate = $viewAndParams[0];
|
||||
$viewParameters = isset($viewAndParams[1]) ? $viewAndParams[1] : [];
|
||||
$headers = isset($viewAndParams[2]) ? $viewAndParams[2] : [];
|
||||
|
||||
static::sendHeaders($headers);
|
||||
|
||||
if ($viewTemplate === null)
|
||||
{
|
||||
|
@ -25,9 +25,15 @@ class Controller
|
|||
throw new LogicException('All execute methods must return a template.');
|
||||
}
|
||||
|
||||
echo View::render('layout/basic', [
|
||||
'content' => View::render($viewTemplate, $viewParameters + ['fullPage' => true])
|
||||
]);
|
||||
$layout = !(isset($viewParameters['_no_layout']) && $viewParameters['_no_layout']);
|
||||
unset($viewParameters['_no_layout']);
|
||||
|
||||
$layoutParams = isset($viewParameters[View::LAYOUT_PARAMS]) ? $viewParameters[View::LAYOUT_PARAMS] : [];
|
||||
unset($viewParameters[View::LAYOUT_PARAMS]);
|
||||
|
||||
$content = View::render($viewTemplate, $viewParameters + ['fullPage' => true]);
|
||||
|
||||
echo $layout ? View::render('layout/basic', ['content' => $content] + $layoutParams) : $content;
|
||||
}
|
||||
catch (StopException $e)
|
||||
{
|
||||
|
@ -59,7 +65,7 @@ class Controller
|
|||
case '/LBRY-deck.pdf':
|
||||
return static::redirect('https://s3.amazonaws.com/files.lbry.io/LBRY-deck.pdf', 307);
|
||||
case '/dl/lbry_setup.sh':
|
||||
return static::redirect('https://raw.githubusercontent.com/lbryio/lbry-setup/master/lbry_setup.sh', 307);
|
||||
return ['internal/dl-not-supported', ['_no_layout' => true]];
|
||||
case '/lbry-osx-latest.dmg':
|
||||
return static::redirect('https://github.com/lbryio/lbry/releases/download/v0.2.4/lbry.0.2.4.dmg', 307);
|
||||
case '/lbry-linux-latest.deb':
|
||||
|
@ -67,10 +73,14 @@ class Controller
|
|||
case '/art':
|
||||
return static::redirect('/what');
|
||||
default:
|
||||
$blogPattern = '#^/news(/|$)#';
|
||||
$blogPattern = '#^' . BlogActions::URL_STEM . '(/|$)#';
|
||||
if (preg_match($blogPattern, $uri))
|
||||
{
|
||||
$slug = preg_replace($blogPattern, '', $uri);
|
||||
if ($slug == BlogActions::RSS_SLUG)
|
||||
{
|
||||
return BlogActions::executeRss();
|
||||
}
|
||||
return $slug ? BlogActions::executePost($slug) : BlogActions::executeIndex();
|
||||
}
|
||||
$noSlashUri = ltrim($uri, '/');
|
||||
|
@ -80,29 +90,102 @@ class Controller
|
|||
}
|
||||
else
|
||||
{
|
||||
return ['page/404', []];
|
||||
return ['page/404', [], [static::HEADER_STATUS => 404]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function redirect($url, $statusCode = 302)
|
||||
{
|
||||
if (empty($url))
|
||||
if (!$url)
|
||||
{
|
||||
throw new InvalidArgumentException('Cannot redirect to an empty URL.');
|
||||
}
|
||||
|
||||
$url = str_replace('&', '&', $url);
|
||||
|
||||
$headers = [static::HEADER_STATUS => $statusCode];
|
||||
|
||||
|
||||
if ($statusCode == 201 || ($statusCode >= 300 && $statusCode < 400))
|
||||
{
|
||||
header('Location: ' . $url, true, $statusCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
echo sprintf('<html><head><meta http-equiv="refresh" content="0;url=%s"/></head></html>', htmlspecialchars($url, ENT_QUOTES));
|
||||
$headers['Location'] = $url;
|
||||
}
|
||||
|
||||
throw new StopException('Time to redirect');
|
||||
return ['internal/redirect', ['url' => $url], $headers];
|
||||
}
|
||||
|
||||
protected static function sendHeaders(array $headers)
|
||||
{
|
||||
if (isset($headers[static::HEADER_STATUS]))
|
||||
{
|
||||
$status = 'HTTP/1.0 ' . $headers[static::HEADER_STATUS] . ' ' . static::getStatusTextForCode($headers[static::HEADER_STATUS]);
|
||||
header($status);
|
||||
|
||||
if (substr(php_sapi_name(), 0, 3) == 'cgi')
|
||||
{
|
||||
// fastcgi servers cannot send this status information because it was sent by them already due to the HTT/1.0 line
|
||||
// so we can safely unset them. see ticket #3191
|
||||
unset($headers[static::HEADER_STATUS]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach($headers as $name => $value)
|
||||
{
|
||||
header($name . ': ' . $value);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getStatusTextForCode($code)
|
||||
{
|
||||
$statusTexts = [
|
||||
'100' => 'Continue',
|
||||
'101' => 'Switching Protocols',
|
||||
'200' => 'OK',
|
||||
'201' => 'Created',
|
||||
'202' => 'Accepted',
|
||||
'203' => 'Non-Authoritative Information',
|
||||
'204' => 'No Content',
|
||||
'205' => 'Reset Content',
|
||||
'206' => 'Partial Content',
|
||||
'300' => 'Multiple Choices',
|
||||
'301' => 'Moved Permanently',
|
||||
'302' => 'Found',
|
||||
'303' => 'See Other',
|
||||
'304' => 'Not Modified',
|
||||
'305' => 'Use Proxy',
|
||||
'306' => '(Unused)',
|
||||
'307' => 'Temporary Redirect',
|
||||
'400' => 'Bad Request',
|
||||
'401' => 'Unauthorized',
|
||||
'402' => 'Payment Required',
|
||||
'403' => 'Forbidden',
|
||||
'404' => 'Not Found',
|
||||
'405' => 'Method Not Allowed',
|
||||
'406' => 'Not Acceptable',
|
||||
'407' => 'Proxy Authentication Required',
|
||||
'408' => 'Request Timeout',
|
||||
'409' => 'Conflict',
|
||||
'410' => 'Gone',
|
||||
'411' => 'Length Required',
|
||||
'412' => 'Precondition Failed',
|
||||
'413' => 'Request Entity Too Large',
|
||||
'414' => 'Request-URI Too Long',
|
||||
'415' => 'Unsupported Media Type',
|
||||
'416' => 'Requested Range Not Satisfiable',
|
||||
'417' => 'Expectation Failed',
|
||||
'419' => 'Authentication Timeout',
|
||||
'422' => 'Unprocessable Entity',
|
||||
'426' => 'Upgrade Required',
|
||||
'429' => 'Too Many Requests',
|
||||
'500' => 'Internal Server Error',
|
||||
'501' => 'Not Implemented',
|
||||
'502' => 'Bad Gateway',
|
||||
'503' => 'Service Unavailable',
|
||||
'504' => 'Gateway Timeout',
|
||||
'505' => 'HTTP Version Not Supported',
|
||||
];
|
||||
|
||||
return isset($statusTexts[$code]) ? $statusTexts[$code] : null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
class BlogActions extends Actions
|
||||
{
|
||||
const URL_STEM = '/news';
|
||||
const RSS_SLUG = 'rss.xml';
|
||||
|
||||
public static function executeIndex()
|
||||
{
|
||||
|
@ -13,7 +14,24 @@ class BlogActions extends Actions
|
|||
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
|
||||
return ['blog/index', [
|
||||
'posts' => $posts,
|
||||
'page' => $page
|
||||
'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'
|
||||
]];
|
||||
}
|
||||
|
||||
|
@ -25,7 +43,10 @@ class BlogActions extends Actions
|
|||
return ['page/404', []];
|
||||
}
|
||||
return ['blog/post', [
|
||||
'post' => $post
|
||||
'post' => $post,
|
||||
View::LAYOUT_PARAMS => [
|
||||
'showRssLink' => true
|
||||
]
|
||||
]];
|
||||
}
|
||||
|
||||
|
|
2
dev.sh
2
dev.sh
|
@ -1,3 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
php --server localhost:8000 --docroot web/
|
||||
php --server localhost:8000 --docroot web/ web/index.php
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
class Post
|
||||
{
|
||||
protected $slug, $title, $author, $date, $contentHtml, $cover;
|
||||
protected $slug, $title, $author, $date, $markdown, $contentText, $contentHtml, $cover;
|
||||
protected $isCoverLight = false;
|
||||
|
||||
public static function fromFile($filename)
|
||||
|
@ -14,10 +14,10 @@ class Post
|
|||
public function __construct($slug, $frontMatter, $markdown)
|
||||
{
|
||||
$this->slug = $slug;
|
||||
$this->markdown = $markdown;
|
||||
$this->title = isset($frontMatter['title']) ? $frontMatter['title'] : null;
|
||||
$this->author = isset($frontMatter['author']) ? $frontMatter['author'] : null;
|
||||
$this->date = isset($frontMatter['date']) ? new DateTime($frontMatter['date']) : null;
|
||||
$this->contentHtml = ParsedownExtra::instance()->text(trim($markdown));
|
||||
$this->cover = isset($frontMatter['cover']) ? $frontMatter['cover'] : null;
|
||||
$this->isCoverLight = isset($frontMatter['cover-light']) && $frontMatter['cover-light'] == 'true';
|
||||
}
|
||||
|
@ -57,8 +57,23 @@ class Post
|
|||
return $this->isCoverLight;
|
||||
}
|
||||
|
||||
public function getContentText($wordLimit = null, $appendEllipsis = false)
|
||||
{
|
||||
if ($this->markdown && !$this->contentText)
|
||||
{
|
||||
// $this->contentText = $this->markdownToText(trim($this->markdown));
|
||||
$this->contentText = html_entity_decode(str_replace(' ', ' ', strip_tags($this->getContentHtml())), ENT_COMPAT, 'utf-8');
|
||||
}
|
||||
|
||||
return $wordLimit === null ? $this->contentText : $this->limitWords($this->contentText, $wordLimit, $appendEllipsis);
|
||||
}
|
||||
|
||||
public function getContentHtml()
|
||||
{
|
||||
if ($this->markdown && !$this->contentHtml)
|
||||
{
|
||||
$this->contentHtml = ParsedownExtra::instance()->text(trim($this->markdown));
|
||||
}
|
||||
return $this->contentHtml;
|
||||
}
|
||||
|
||||
|
@ -99,6 +114,24 @@ class Post
|
|||
}
|
||||
}
|
||||
|
||||
public function getAuthorEmail()
|
||||
{
|
||||
switch(strtolower($this->author))
|
||||
{
|
||||
case 'jeremy':
|
||||
return 'jeremy@lbry.io';
|
||||
case 'mike':
|
||||
return 'mike@lbry.io';
|
||||
case 'jimmy':
|
||||
return 'jimmy@lbry.io';
|
||||
case 'jack':
|
||||
return 'jack@lbry.io';
|
||||
case 'lbry':
|
||||
default:
|
||||
return 'hello@lbry.io';
|
||||
}
|
||||
}
|
||||
|
||||
public function getAuthorPhoto()
|
||||
{
|
||||
switch(strtolower($this->author))
|
||||
|
@ -138,4 +171,54 @@ class Post
|
|||
{
|
||||
return $this->getPostNum() % $maxStyles + 1;
|
||||
}
|
||||
|
||||
protected function markdownToText($markdown)
|
||||
{
|
||||
$replacements = [
|
||||
// '/<(.*?)>/' => '$1', // HTML tags
|
||||
'/^[=\-]{2,}\s*$/' => '', // setext-style headers
|
||||
'/\[\^.+?\](\: .*?$)?/' => '', // footnotes
|
||||
'/\s{0,2}\[.*?\]: .*?$/' => '', // footnotes
|
||||
'/\!\[.*?\][\[\(].*?[\]\)]/' => '', // images
|
||||
'/\[(.*?)\][\[\(].*?[\]\)]/' => '$1', // inline links
|
||||
'/^\s*>/' => '', // blockquotes
|
||||
'/^\s{1,2}\[(.*?)\]: (\S+)( ".*?")?\s*$/' => '', // reference-style links
|
||||
|
||||
'/\n={2,}/' => '\n', // underlined headers
|
||||
'/^\#{1,6}\s*([^#]*)\s*(\#{1,6})?/m' => '$1', // atx-style headers
|
||||
'/([\*_]{1,3})(\S.*?\S)\1/' => '$2', // bold/italics
|
||||
'/~~/' => '', // strikethrough
|
||||
'/(`{3,})(.*?)\1/m' => '$2', // codeblocks
|
||||
// '/`{3}.*\n/' => '', // fenced codeblocks
|
||||
'/^-{3,}\s*$/' => '', // hr
|
||||
'/`(.+?)`/' => '$1', // inline code
|
||||
'/\n{2,}/' => '\n\n', // multiple newlines
|
||||
];
|
||||
|
||||
return preg_replace(array_keys($replacements), array_values($replacements), strip_tags($markdown));
|
||||
}
|
||||
|
||||
protected function limitWords($string, $wordLimit, $appendEllipsis = false)
|
||||
{
|
||||
$regexp = '/\s+/u';
|
||||
$words = preg_split($regexp, $string, $wordLimit + 1);
|
||||
$numWords = count($words);
|
||||
|
||||
# TBB: if there are $wordLimit words or less, this check is necessary
|
||||
# to prevent the last word from being lost.
|
||||
if ($numWords > $wordLimit)
|
||||
{
|
||||
array_pop($words);
|
||||
}
|
||||
|
||||
$string = implode(' ', $words);
|
||||
|
||||
if ($appendEllipsis && $numWords > $wordLimit)
|
||||
{
|
||||
$ellipsis = '…';
|
||||
$string .= $ellipsis;
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
}
|
|
@ -10,13 +10,10 @@ function js_end()
|
|||
ob_end_flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Description of View
|
||||
*
|
||||
* @author jeremy
|
||||
*/
|
||||
class View
|
||||
{
|
||||
const LAYOUT_PARAMS = '_layout_params';
|
||||
|
||||
protected static $metaDescription = '',
|
||||
$metaImg = '';
|
||||
|
||||
|
|
|
@ -17,4 +17,4 @@ We believe cryptocurrencies and blockchain technology are the key to solving thi
|
|||
|
||||
Want to help us get LBRY launched and get in on the crypto action? [Test the LBRY Alpha and fill out our survey to earn 1,000 LBC](https://lbry.io/get).
|
||||
|
||||
If you have a strong interest in getting involved in LBRY, [join our Slack channel](https://lbry-slackin.herokuapp.com). Come and join the fun!
|
||||
If you have a strong interest in getting involved in LBRY, [join our Slack channel](http://slack.lbry.io). Come and join the fun!
|
||||
|
|
25
view/template/blog/rss.php
Normal file
25
view/template/blog/rss.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>
|
||||
<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="http://lbry.io<?php echo BlogActions::URL_STEM . '/' . BlogActions::RSS_SLUG ?>" rel="self" type="application/rss+xml" />
|
||||
<?php foreach ($posts as $post): ?>
|
||||
<item>
|
||||
<title><?php echo htmlspecialchars($post->getTitle()) ?></title>
|
||||
<link>https://lbry.io<?php echo $post->getRelativeUrl() ?></link>
|
||||
<guid>https://lbry.io<?php echo $post->getRelativeUrl() ?></guid>
|
||||
<pubDate><?php echo $post->getDate()->format('r') ?></pubDate>
|
||||
<author><?php echo htmlspecialchars($post->getAuthorEmail()) ?> (<?php echo htmlspecialchars($post->getAuthorName()) ?>)</author>
|
||||
<description><?php echo htmlspecialchars($post->getContentText(50, true)) ?></description>
|
||||
<content:encoded><![CDATA[
|
||||
<?php echo $post->getContentHtml() ?>
|
||||
]]></content:encoded>
|
||||
</item>
|
||||
<?php endforeach ?>
|
||||
</channel>
|
||||
</rss>
|
2
view/template/internal/dl-not-supported.php
Normal file
2
view/template/internal/dl-not-supported.php
Normal file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/bash
|
||||
echo "This install method is no longer supported. Please see https://github.com/lbryio/lbry for more information."
|
1
view/template/internal/redirect.php
Normal file
1
view/template/internal/redirect.php
Normal file
|
@ -0,0 +1 @@
|
|||
<html><head><meta http-equiv="refresh" content="0;url=<?php echo htmlspecialchars($url, ENT_QUOTES, 'utf-8')?>"/></head></html>
|
|
@ -12,7 +12,7 @@
|
|||
'LBRY' ?>
|
||||
<title><?php echo $title ?></title>
|
||||
|
||||
<link href='https://fonts.googleapis.com/css?family=Merriweather:300,300italic,700,700italic|Raleway:300,300italic,400,400italic,700' rel='stylesheet' type='text/css'>
|
||||
<link href='https://fonts.googleapis.com/css?family=Raleway:300,300italic,400,400italic,700' rel='stylesheet' type='text/css'>
|
||||
<link href="/css/all.css" rel="stylesheet" type="text/css" media="screen,print" />
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="/img/fav/apple-touch-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="/img/fav/apple-touch-icon-114x114.png">
|
||||
|
@ -25,6 +25,9 @@
|
|||
<link rel="icon" type="image/png" href="/img/fav/android-chrome-192x192.png" sizes="192x192">
|
||||
<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 ?>" />
|
||||
<?php endif ?>
|
||||
|
||||
<meta name="description" content="<?php echo Response::getMetaDescription() ?>">
|
||||
<meta name="msapplication-TileColor" content="#155B4A">
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
</div>
|
||||
*/ ?>
|
||||
<div class="spacer1">
|
||||
<a href="//github.com/lbryio" class="link-primary"><span class="icon-github icon-fw"></span><span class="btn-label">GitHub (source code)</span></a>
|
||||
<a href="https://github.com/lbryio" class="link-primary"><span class="icon-github icon-fw"></span><span class="btn-label">GitHub (source code)</span></a>
|
||||
</div>
|
||||
<div class="spacer1">
|
||||
<a href="https://lbry-slackin.herokuapp.com" class="link-primary"><span class="icon-slack icon-fw"></span><span class="btn-label">Slack (chat)</span></a>
|
||||
<a href="http://slack.lbry.io" class="link-primary"><span class="icon-slack icon-fw"></span><span class="btn-label">Slack (chat)</span></a>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
<?php
|
||||
|
||||
# Enable PHP dev cli-server
|
||||
if (php_sapi_name() === 'cli-server' && is_file(__DIR__.preg_replace('#(\?.*)$#', '', $_SERVER['REQUEST_URI'])))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
include __DIR__ . '/../bootstrap.php';
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue