Skip to content

Instantly share code, notes, and snippets.

@poef
Last active January 31, 2016 12:31
Show Gist options
  • Save poef/153a9c69b72ddb0e21ff to your computer and use it in GitHub Desktop.
Save poef/153a9c69b72ddb0e21ff to your computer and use it in GitHub Desktop.
A RSS feeds list using ARC components
html, body {
background: #EEE;
height: 100%;
overflow: auto;
font-family: arial, helvetica, sans-serif;
padding: 0;
}
section {
background-color: white;
border-radius: 3px;
box-shadow: 0 0 3px #888;
float: left;
max-width: 300px;
margin: 0 1em 1em 0;
}
section header {
background-color: #EEE;
overflow: hidden;
position: relative;
}
section header h2 {
margin: 0;
padding: 10px;
font-size: 1rem
}
section header button {
position: absolute;
right: 10px;
top: 5px;
width: 1em;
text-indent: 2em;
overflow: hidden;
border: 0;
background: transparent;
font-size: 1.2em;
}
section header button::before {
content: "X";
display: block;
position: absolute;
left: -2em;
top: 0;
}
.article-body {
height: 400px;
overflow: auto;
color: #666;
}
article h3 {
margin: 0;
padding: 5px 10px 10px 10px;
}
article h3 a {
text-decoration: none;
color: #333;
}
section footer {
background-color: #EEE;
padding: 10px
}
.body {
padding: 0px 10px 10px 10px;
border-bottom: 1px solid #ccc;
}
body > footer {
position: absolute;
left: 0;
bottom: 0;
background-color: #AAA;
padding: 10px;
box-sizing: border-box;
width: 100%;
}
<?php
/**
* This is a simple demo showing how you can use different components from ARC together
* You can get arc at https://github.com/Ariadne-CMS/arc-arc/ or with composer:
*
* composer create-project arc/arc
*
* See this gist for a simpler demo printing a single feed:
* https://gist.github.com/poef/dd977430dbf922d7555f
*/
// load the composer autoloader
require __DIR__ . '/vendor/autoload.php';
// set shorter aliases for the html and xml writer/parser
use \arc\html as h;
use \arc\xml as x;
// create a http proxy with caching based on the cache headers of each request
$client = \arc\cache::proxy( \arc\http::client(), function($params) {
return ( \arc\http\headers::parseCacheTime( $params['target']->responseHeaders ) );
});
// read a list of feeds
$feeds = json_decode(file_get_contents('feeds.json'),true) ?: [];
// create an adhoc object to render the html
$agg = \arc\lambda::prototype();
$agg->renderItem = function($item) {
return h::article(
h::h3( h::a( [ 'href' => $item->link->nodeValue ], $item->title->nodeValue ) ),
h::div( [ 'class' => 'body' ], $item->description->nodeValue )
);
};
$agg->renderItems = function($items) {
$itemsString = '';
if ( count($items) ) {
foreach ($items as $item ) {
$itemsString .= $this->renderItem($item);
}
} else {
$itemsString = h::div(['class' => 'warning'], 'No articles in this feed.');
}
// h::raw makes sure the $itemsString isn't encoded/escaped when printed later
return h::raw($itemsString);
};
$agg->renderFeed = function($title, $link, $index, $items) {
return h::section(['class' => 'feed'],
h::header(
h::h2( $title ),
// this button removes this feed when pressed
h::form(['class' => 'remove', 'method' => 'POST'],
h::button(['name' => 'removeFeed', 'value' => $index], 'Remove' )
)
),
h::div(['class' => 'article-body'], $this->renderItems($items) ),
h::footer(
h::a( ['href' => $link], $link )
)
);
};
// retrieves the contents and renders them, naming is hard...
$agg->getFeed = function($url, $index) use ($client) {
$feed = $client->get($url);
try {
$rss = \arc\xml::parse($feed);
} catch( \Exception $e ) {
$rss = \arc\html::parse($feed);
}
$items = $rss->find('item');
return $this->renderFeed(
$rss->channel->title->nodeValue,
$rss->channel->link->nodeValue,
$index,
$items
);
};
// runs getFeed on all feeds and concatenates the results
$agg->render = function($feeds) {
return implode(
array_map(
function($feed, $index) {
return $this->getFeed($feed, $index);
},
$feeds,
array_keys($feeds)
)
);
};
// check if a new feed is added
$newFeed = \arc\hash::get('/newFeed/', $_POST);
if ( isset($newFeed) ) {
$feeds[] = $newFeed;
}
// check if a feed has been removed
$removeFeed = \arc\hash::get('/removeFeed/', $_POST);
if ( isset($removeFeed) ) {
unset($feeds[ $removeFeed ]);
}
// if the feeds list has changed, write it to disk
// this is a very unsafe way to do this, but it keeps this example short
if ( isset($removeFeed) || isset($newFeed) ) {
file_put_contents('data/feeds.json', json_encode($feeds,true));
}
// print the full html output
echo h::doctype()
.h::html(
h::head(
h::title('RSS Aggregator'),
h::link(['href' => 'rsslist.css', 'rel' => 'stylesheet'])
),
h::body(
h::raw($aggregator->render($feeds)),
h::footer(
h::form(
['method' => 'POST'],
h::input(['name' => 'newFeed']),
h::button(['ype' => 'submit'], 'Add feed')
)
)
)
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment