* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
* @link http://status.net/
*/
-
class Activity
{
const SPEC = 'http://activitystrea.ms/spec/1.0/';
const CREATOR = 'creator';
const CONTENTNS = 'http://purl.org/rss/1.0/modules/content/';
+ const ENCODED = 'encoded';
public $actor; // an ActivityObject
public $verb; // a string (the URL)
* @param DOMElement $entry Atom entry to poke at
* @param DOMElement $feed Atom feed, for context
*/
-
function __construct($entry = null, $feed = null)
{
if (is_null($entry)) {
// Insist on a feed's root DOMElement; don't allow a DOMDocument
if ($feed instanceof DOMDocument) {
throw new ClientException(
- _("Expecting a root feed element but got a whole XML document.")
+ // TRANS: Client exception thrown when a feed instance is a DOMDocument.
+ _('Expecting a root feed element but got a whole XML document.')
);
}
$entry->localName == 'item') {
$this->_fromRssItem($entry, $feed);
} else {
+ // Low level exception. No need for i18n.
throw new Exception("Unknown DOM element: {$entry->namespaceURI} {$entry->localName}");
}
}
$this->title = ActivityUtils::childContent($item, ActivityObject::TITLE, self::RSS);
- $contentEl = ActivityUtils::child($item, ActivityUtils::CONTENT, self::CONTENTNS);
+ $contentEl = ActivityUtils::child($item, self::ENCODED, self::CONTENTNS);
if (!empty($contentEl)) {
- $this->content = htmlspecialchars_decode($contentEl->textContent, ENT_QUOTES);
+ // <content:encoded> XML node's text content is HTML; no further processing needed.
+ $this->content = $contentEl->textContent;
} else {
$descriptionEl = ActivityUtils::child($item, self::DESCRIPTION, self::RSS);
if (!empty($descriptionEl)) {
- $this->content = htmlspecialchars_decode($descriptionEl->textContent, ENT_QUOTES);
+ // Per spec, <description> must be plaintext.
+ // In practice, often there's HTML... but these days good
+ // feeds are using <content:encoded> which is explicitly
+ // real HTML.
+ // We'll treat this following spec, and do HTML escaping
+ // to convert from plaintext to HTML.
+ $this->content = htmlspecialchars($descriptionEl->textContent);
}
}
*
* @return DOMElement Atom entry
*/
-
function toAtomEntry()
{
return null;
}
- function asString($namespace=false)
+ function asString($namespace=false, $author=true)
{
$xs = new XMLStringer(true);
$xs->element('id', null, $this->id);
$xs->element('title', null, $this->title);
- $xs->element('published', null, common_date_iso8601($this->time));
+ $xs->element('published', null, self::iso8601Date($this->time));
$xs->element('content', array('type' => 'html'), $this->content);
if (!empty($this->summary)) {
// XXX: add context
- $xs->elementStart('author');
- $xs->element('uri', array(), $this->actor->id);
- if ($this->actor->title) {
- $xs->element('name', array(), $this->actor->title);
+ if ($author) {
+ $xs->elementStart('author');
+ $xs->element('uri', array(), $this->actor->id);
+ if ($this->actor->title) {
+ $xs->element('name', array(), $this->actor->title);
+ }
+ $xs->elementEnd('author');
+ $xs->raw($this->actor->asString('activity:actor'));
}
- $xs->elementEnd('author');
- $xs->raw($this->actor->asString('activity:actor'));
$xs->element('activity:verb', null, $this->verb);
{
return ActivityUtils::child($element, $tag, $namespace);
}
-}
+ static function iso8601Date($tm)
+ {
+ $dateStr = date('d F Y H:i:s', $tm);
+ $d = new DateTime($dateStr, new DateTimeZone('UTC'));
+ $d->setTimezone(new DateTimeZone(common_timezone()));
+ return $d->format('c');
+ }
+}