Skip to content

Instantly share code, notes, and snippets.

@barnabywalters
Last active August 29, 2015 14:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save barnabywalters/1640f384112ddebba2bf to your computer and use it in GitHub Desktop.
Save barnabywalters/1640f384112ddebba2bf to your computer and use it in GitHub Desktop.
<?php namespace Taproot; use DateTime; ?>
<?= '<?xml version="1.0" encoding="utf-8"?>'; ?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
<title><?= $title ?></title>
<link href="<?= $url ?>" rel="alternate" title="<?= $title ?>" type="text/html"/>
<link href="<?= $feedUrl ?>" rel="self"/>
<id><?= $feedUrl ?></id>
<author>
<name><?= $author['name'] ?></name>
<uri><?= $author['url'] ?></uri>
</author>
<?php foreach ($items as $item): ?>
<entry xmlns:activity="http://activitystrea.ms/spec/1.0/">
<id><?= $item['url'] ?></id>
<title><?= htmlspecialchars(strip_tags($item['name'])) ?></title>
<published><?= Text\toDateTime($item['published'])->format(DateTime::ATOM); ?></published>
<updated><?= isset($item['updated'])
? Text\toDateTime($item['updated'])->format(DateTime::ATOM)
: Text\toDateTime($item['published'])->format(DateTime::ATOM) ?></updated>
<link rel="alternate" type="text/html" href="<?= $item['url'] ?>" />
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><?= $item['content'] ?></div></content>
<activity:object-type>http://activitystrea.ms/schema/1.0/article</activity:object-type>
</entry>
<?php endforeach ?>
</feed>
<?php
namespace Taproot;
use Guzzle;
use DateTime;
use BarnabyWalters\Mf2 as M;
use Mf2;
use HTMLPurifier, HTMLPurifier_Config;
function getPurifier() {
$purifierConfig = HTMLPurifier_Config::createDefault();
return new HTMLPurifier($purifierConfig);
}
function flattenFirstHEntry($mf, $url=null, $published=null) {
$hEntries = flattenHEntries($mf, $url, $published);
if (count($hEntries) == 0)
return null;
return $hEntries[0];
}
function flattenHEntries($mf, $url=null, $published=null) {
$hEntries = M\findMicroformatsByType($mf, 'h-entry');
$hEntries = array_map(function ($hEntry) use ($mf, $url, $published) {
return flattenHEntryWithContext($hEntry, $url, $published, $mf);
}, $hEntries);
return $hEntries;
}
function purifyValue($value, $purifier) {
if (is_array($value)) {
foreach ($value as $key => $val) {
$value[$key] = purifyValue($val, $purifier);
}
return $value;
}
return $purifier->purify($value);
}
function flattenHEntryWithContext($hEntry, $url, $published, $mf) {
$purifier = getPurifier();
if ($published === null)
$published = new DateTime;
$entry = ['type' => 'h-entry'];
$entry['name'] = M\getHtml($hEntry, 'name');
$entry['content'] = M\getHtml($hEntry, 'content', M\getHtml($hEntry, 'summary', M\getHtml($hEntry, 'name', '')));
$entry['summary'] = M\getPlaintext($hEntry, 'summary', M\getPlaintext($hEntry, 'summary', M\getPlaintext($hEntry, 'name', '')));
$entry['published'] = M\getPublished($hEntry, true, $published->format(DateTime::W3C));
$entry['url'] = M\getHtml($hEntry, 'url', $url);
if (M\hasProp($hEntry, 'like') or M\hasProp($hEntry, 'like-of'))
$entry['like-of'] = M\getHtml($hEntry, 'like-of', M\getHtml($hEntry, 'like', null));
foreach (['in-reply-to' => null, 'rsvp' => null, 'repost-of' => null] as $propName => $fallback) {
if (M\hasProp($hEntry, $propName))
$entry[$propName] = M\getHtml($hEntry, $propName, $fallback);
}
foreach ($entry as $key => $value)
$entry[$key] = $purifier->purify($value);
$entry['syndication'] = M\hasProp($hEntry, 'syndication') ? M\getPlaintextArray($hEntry, 'syndication') : [];
if (!empty($mf['rels']['syndication']))
$entry['syndication'] = array_merge($entry['syndication'], $mf['rels']['syndication']);
$entry['syndication'] = array_map([$purifier, 'purify'], array_unique($entry['syndication']));
// TODO: actual authorship implementation here, or at least somewhere
$author = ['type' => 'h-card'];
$mfAuthor = M\getAuthor($hEntry, $mf, $url);
if (is_string($mfAuthor)) {
$author['name'] = $mfAuthor;
$author['url'] = Url\origin($url);
} elseif (M\isMicroformat($mfAuthor)) {
foreach ($mfAuthor['properties'] as $name => $val) {
if (!empty($val))
$author[$name] = $val[0];
}
}
foreach ($author as $key => $value) {
$author[$key] = purifyValue($value, $purifier);
}
$entry['author'] = $author;
return $entry;
}
<?php
// $services is a Silex application or RouteCollection
// See http://silex.sensiolabs.org/
$services->get('/microformats-to-atom/', function (Http\Request $request) use ($app) {
if (!$request->query->has('url')) {
return $app['render']('services/microformats-to-atom.html', [
'pageClass' => 'form',
'title' => 'Convert microformats2 to ATOM',
'url' => ''
]);
}
$url = $request->query->get('url');
$client = $app['http.client'];
try {
$html = $client->get($url)->send()->getBody(true);
} catch (Guzzle\Common\Exception\GuzzleException $e) {
return $app['render']('services/microformats-to-atom.html', [
'pageClass' => 'form',
'title' => 'Convert microformats2 to ATOM',
'error' => 'That URL couldn’t be fetched!',
'url' => $url
]);
}
$parser = new Mf2\Parser($html, $url);
$mf = $parser->parse();
$hEntries = Taproot\flattenHEntries($mf, $url);
$hFeeds = M\findMicroformatsByType($mf, 'h-feed');
$hFeed = count($hFeeds) > 0 ? $hFeeds[0] : [];
foreach ($hEntries as &$hEntry) {
ob_start();
$hEntry['name'] = ellipsize_to_word($hEntry['name'], 64, '…', 55);
ob_end_clean();
}
$author = @($hEntries[0]['author'] ?: ['name' => '', 'url' => '']);
$title = strlen(M\getPlaintext($hFeed, 'name')) < 100 ? M\getPlaintext($hFeed, 'name') : $parser->query('//title')->item(0)->nodeValue;
return $app['render']('services/feed.atom', [
'items' => $hEntries,
'author' => $author,
'title' => $title,
'url' => $url,
'feedUrl' => $app['url_generator']->generate('services.microformats-to-atom', ['url' => $url], true)
]);
})->bind('services.microformats-to-atom');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment