]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
First coded version of blog plugin
authorEvan Prodromou <evan@status.net>
Mon, 20 Jun 2011 05:11:35 +0000 (01:11 -0400)
committerEvan Prodromou <evan@status.net>
Mon, 20 Jun 2011 05:11:35 +0000 (01:11 -0400)
A basic blog plugin. Allows posting open-ended HTML with a title. Not yet
tested (even run).

plugins/Blog/BlogEntry.php [new file with mode: 0644]
plugins/Blog/BlogPlugin.php [new file with mode: 0644]
plugins/Blog/blogentryform.php [new file with mode: 0644]
plugins/Blog/blogentrylistitem.php [new file with mode: 0644]
plugins/Blog/newblogentry.php [new file with mode: 0644]
plugins/Blog/showblogentry.php [new file with mode: 0644]

diff --git a/plugins/Blog/BlogEntry.php b/plugins/Blog/BlogEntry.php
new file mode 100644 (file)
index 0000000..54940e0
--- /dev/null
@@ -0,0 +1,233 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * Data structure for blog entries
+ * 
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Blog
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Data structure for blog entries
+ *
+ * @category  Blog
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class BlogEntry extends Managed_DataObject
+{
+    public $__table = 'blog_entry';
+
+    public $id; // UUID
+    public $profile_id; // int
+    public $title; // varchar(255)
+    public $summary; // text
+    public $content; // text
+    public $uri; // text
+    public $url; // text
+    public $created; // datetime
+    public $modified; // datetime
+
+    const TYPE = 'http://activitystrea.ms/schema/1.0/blog-entry';
+    
+    static function staticGet($k, $v=null)
+    {
+        return Managed_DataObject::staticGet('blog_entry', $k, $v);
+    }
+
+    static function schemaDef()
+    {
+        return array(
+            'description' => 'lite blog entry',
+            'fields' => array(
+                'id' => array('type' => 'char',
+                              'length' => 36,
+                              'not null' => true,
+                              'description' => 'Unique ID (UUID)'),
+                'profile_id' => array('type' => 'int',
+                                      'not null' => true,
+                                      'description' => 'Author profile ID'),
+                'title' => array('type' => 'varchar',
+                                 'length' => 255,
+                                 'description' => 'title of the entry'),
+                'summary' => array('type' => 'text',
+                                   'description' => 'initial summary'),
+                'content' => array('type' => 'text',
+                                   'description' => 'HTML content of the entry'),
+                'uri' => array('type' => 'varchar',
+                               'length' => 255,
+                               'description' => 'URI (probably http://) for this entry'),
+                'url' => array('type' => 'varchar',
+                               'length' => 255,
+                               'description' => 'URL (probably http://) for this entry'),
+                'created' => array('type' => 'datetime',
+                                   'not null' => true,
+                                   'description' => 'date this record was created'),
+                'modified' => array('type' => 'datetime',
+                                    'not null' => true,
+                                    'description' => 'date this record was created'),
+            ),
+            'primary key' => array('id'),
+            'foreign keys' => array(
+                'blog_entry_profile_id_fkey' => array('profile', array('profile_id' => 'id')),
+            ),
+            'indexes' => array(
+                'blog_entry_created_idx' => array('created'),
+                'blog_entry_uri_idx' => array('uri'),
+            ),
+        );
+    }
+
+    static function saveNew($profile, $title, $content, $options=null)
+    {
+        if (is_null($options)) {
+            $options = array();
+        }
+        
+        $be             = new BlogEntry();
+        $be->id         = (string) new UUID();
+        $be->profile_id = $profile->id;
+        $be->title      = htmlspecialchars($title);
+        $be->content    = $content;
+        
+        if (array_key_exists('summary', $options)) {
+            $be->summary = $options['summary'];
+        } else {
+            $be->summary = self::summarize($content);
+        }
+
+        $url = common_local_url('showblogentry', array('id' => $be->id));
+
+        if (!array_key_exists('uri', $options)) {
+            $options['uri'] = $url;
+        } 
+
+        $be->uri = $options['uri'];
+
+        if (!array_key_exists('url', $options)) {
+            $options['url'] = $url;
+        }
+
+        $be->url = $options['url'];
+
+        if (!array_key_exists('created', $options)) {
+            $be->created = common_sql_now();
+        }
+        
+        $be->created = $options['created'];
+
+        $be->modified = common_sql_now();
+
+        $be->insert();
+
+        // Use user's preferences for short URLs, if possible
+
+        try {
+            $user = $profile->getUser();
+            $shortUrl = File_redirection::makeShort($url,
+                                                    empty($user) ? null : $user);
+        } catch (Exception $e) {
+            // Don't let this stop us.
+            $shortUrl = $url;
+        }
+
+        // XXX: this might be too long.
+
+        $options['rendered'] = $be->summary . ' ' . 
+            XMLStringer::estring('a', array('href' => $shortUrl,
+                                            'class' => 'blog-entry'),
+                                 _('More...'));
+
+        $summaryText = html_entity_decode(strip_tags($summary), ENT_QUOTES, 'UTF-8');
+
+        if (Notice::contentTooLong($summaryText)) {
+            $summaryText = substr($summaryText, 0, Notice::maxContent() - mb_strlen($shortUrl) - 2) .
+                '… ' . $shortUrl;
+        }
+
+        $content = $summaryText;
+
+        // Override this no matter what.
+        
+        $options['object_type'] = self::TYPE;
+
+        $source = array_key_exists('source', $options) ?
+                                    $options['source'] : 'web';
+        
+        Notice::saveNew($profile->id, $content, $source, $options);
+    }
+
+    /**
+     * Summarize the contents of a blog post
+     *
+     * We take the first div or paragraph of the blog post if there's a hit;
+     * Otherwise we take the whole thing.
+     * 
+     * @param string $html HTML of full content
+     */
+    static function summarize($html)
+    {
+        if (preg_match('#<p>.*?</p>#s', $html, $matches)) {
+            return $matches[0];
+        } else if (preg_match('#<div>.*?</div>#s', $html, $matches)) {
+            return $matches[0];
+        } else {
+            return $html;
+        }
+    }
+
+    static function fromNotice($notice)
+    {
+        return BlogEntry::staticGet('uri', $notice->uri);
+    }
+
+    function getNotice()
+    {
+        return Notice::staticGet('uri', $this->uri);
+    }
+
+    function asActivityObject()
+    {
+        $obj = new ActivityObject();
+
+        $obj->id      = $this->uri;
+        $obj->type    = self::TYPE;
+        $obj->title   = $this->title;
+        $obj->summary = $this->summary;
+        $obj->content = $this->content;
+        $obj->link    = $this->url;
+
+        return $obj;
+    }
+}
diff --git a/plugins/Blog/BlogPlugin.php b/plugins/Blog/BlogPlugin.php
new file mode 100644 (file)
index 0000000..7f8e8fd
--- /dev/null
@@ -0,0 +1,210 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * A microapp to implement lite blogging
+ *
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Blog
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Blog plugin
+ *
+ * Many social systems have a way to write and share long-form texts with
+ * your network. This microapp plugin lets users post blog entries.
+ *
+ * @category  Blog
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class BlogPlugin extends MicroAppPlugin
+{
+    /**
+     * Database schema setup
+     *
+     * @see Schema
+     * @see ColumnDef
+     *
+     * @return boolean hook value; true means continue processing, false means stop.
+     */
+    function onCheckSchema()
+    {
+        $schema = Schema::get();
+
+        $schema->ensureTable('blog_entry', BlogEntry::schemaDef());
+
+        return true;
+    }
+
+    /**
+     * Load related modules when needed
+     *
+     * @param string $cls Name of the class to be loaded
+     *
+     * @return boolean hook value; true means continue processing, false means stop.
+     */
+    function onAutoload($cls)
+    {
+        $dir = dirname(__FILE__);
+
+        switch ($cls)
+        {
+        case 'NewblogentryAction':
+        case 'ShowblogentryAction':
+            include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
+            return false;
+        case 'BlogEntryForm':
+        case 'BlogEntryListItem':
+            include_once $dir . '/'.strtolower($cls).'.php';
+            return false;
+        case 'BlogEntry':
+            include_once $dir . '/'.$cls.'.php';
+            return false;
+        default:
+            return true;
+        }
+    }
+
+    /**
+     * Map URLs to actions
+     *
+     * @param Net_URL_Mapper $m path-to-action mapper
+     *
+     * @return boolean hook value; true means continue processing, false means stop.
+     */
+    function onRouterInitialized($m)
+    {
+        $m->connect('blog/new',
+                    array('action' => 'newblogentry'));
+        $m->connect('blog/:id',
+                    array('action' => 'showblogentry'),
+                    array('id' => UUID::REGEX));
+        return true;
+    }
+
+    function onPluginVersion(&$versions)
+    {
+        $versions[] = array('name' => 'Blog',
+                            'version' => STATUSNET_VERSION,
+                            'author' => 'Evan Prodromou',
+                            'homepage' => 'http://status.net/wiki/Plugin:Blog',
+                            'rawdescription' =>
+                            _m('Let users write and share long-form texts.'));
+        return true;
+    }
+
+    function appTitle()
+    {
+        return _m('Blog');
+    }
+
+    function tag()
+    {
+        return 'blog';
+    }
+
+    function types()
+    {
+        return array(BlogEntry::TYPE);
+    }
+
+    function saveNoticeFromActivity($activity, $actor, $options=array())
+    {
+        if (count($activity->objects) != 1) {
+            // TRANS: Exception thrown when there are too many activity objects.
+            throw new ClientException(_m('Too many activity objects.'));
+        }
+
+        $entryObj = $activity->objects[0];
+
+        if ($entryObj->type != BlogEntry::TYPE) {
+            // TRANS: Exception thrown when blog plugin comes across a non-event type object.
+            throw new ClientException(_m('Wrong type for object.'));
+        }
+
+        $notice = null;
+
+        switch ($activity->verb) {
+        case ActivityVerb::POST:
+            $notice = BlogEntry::saveNew($actor,
+                                         $entryObj->title,
+                                         $entryObj->content,
+                                         $options);
+            break;
+        default:
+            // TRANS: Exception thrown when blog plugin comes across a undefined verb.
+            throw new ClientException(_m('Unknown verb for blog entries.'));
+        }
+
+        return $notice;
+    }
+
+    function activityObjectFromNotice($notice)
+    {
+        $entry = BlogEntry::fromNotice($notice);
+
+        if (empty($entry)) {
+            throw new ClientException(sprintf(_('No blog entry for notice %s'),
+                        $notice->id));
+        }
+
+        return $entry->asActivityObject();
+    }
+
+    function entryForm($out)
+    {
+        return new BlogEntryForm($out);
+    }
+
+    function deleteRelated($notice)
+    {
+        if ($notice->object_type == BlogEntry::TYPE) {
+            $entry = BlogEntry::fromNotice($notice);
+            if (exists($entry)) {
+                $entry->delete();
+            }
+        }
+    }
+
+    function adaptNoticeListItem($nli)
+    {
+        $notice = $nli->notice;
+
+        if ($notice->object_type == BlogEntry::TYPE) {
+            return new BlogEntryListItem($nli);
+        }
+        
+        return null;
+    }
+}
diff --git a/plugins/Blog/blogentryform.php b/plugins/Blog/blogentryform.php
new file mode 100644 (file)
index 0000000..b21e76a
--- /dev/null
@@ -0,0 +1,133 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * Form for creating a blog entry
+ *
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Blog
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Form for creating a blog entry
+ *
+ * @category  Blog
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class BlogEntryForm extends Form
+{
+    /**
+     * ID of the form
+     *
+     * @return int ID of the form
+     */
+    function id()
+    {
+        return 'form_new_blog_entry';
+    }
+
+    /**
+     * class of the form
+     *
+     * @return string class of the form
+     */
+    function formClass()
+    {
+        return 'form_settings ajax-notice';
+    }
+
+    /**
+     * Action of the form
+     *
+     * @return string URL of the action
+     */
+    function action()
+    {
+        return common_local_url('newblogentry');
+    }
+
+    /**
+     * Data elements of the form
+     *
+     * @return void
+     */
+    function formData()
+    {
+        $this->out->elementStart('fieldset', array('id' => 'new_blog_entry_data'));
+        $this->out->elementStart('ul', 'form_data');
+
+        $this->li();
+        $this->out->input('blog-entry-title',
+                          // TRANS: Field label on blog entry form.
+                          _m('LABEL','Title'),
+                          null,
+                          // TRANS: Field title on blog entry form.
+                          _m('Title of the blog entry.'),
+                          'title');
+        $this->unli();
+        
+        $this->li();
+        $this->out->textarea('blog-entry-content',
+                             // TRANS: Field label on event form.
+                             _m('LABEL','Text'),
+                            null,
+                            // TRANS: Field title on event form.
+                            _m('Text of the blog entry.'),
+                            'content');
+        $this->unli();
+
+        $this->out->elementEnd('ul');
+
+        $toWidget = new ToSelector($this->out,
+                                   common_current_user(),
+                                   null);
+        $toWidget->show();
+
+        $this->out->elementEnd('fieldset');
+    }
+
+    /**
+     * Action elements
+     *
+     * @return void
+     */
+    function formActions()
+    {
+        // TRANS: Button text to save an event..
+        $this->out->submit('blog-entry-submit',
+                           _m('BUTTON', 'Save'),
+                           'submit',
+                           'submit');
+    }
+}
diff --git a/plugins/Blog/blogentrylistitem.php b/plugins/Blog/blogentrylistitem.php
new file mode 100644 (file)
index 0000000..44775d8
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * NoticeListItem adapter for blog entries
+ * 
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Blog
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * NoticeListItem adapter for blog entries
+ *
+ * @category  General
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class BlogEntryListItem extends NoticeListItemAdapter
+{
+    function showNotice()
+    {
+        $this->out->elementStart('div', 'entry-title');
+        $this->showAuthor();
+        $this->showContent();
+        $this->out->elementEnd('div');
+    }
+
+    function showContent()
+    {
+        $notice = $this->nli->notice;
+        $out    = $this->nli->out;
+
+        $entry  = BlogEntry::fromNotice($notice);
+
+        if (empty($entry)) {
+            throw new Exception('BlogEntryListItem used for non-blog notice.');
+        }
+
+        $out->elementStart('h4', array('class' => 'blog-entry-title'));
+        $out->element('a', array('href' => $notice->bestUrl()), $entry->title);
+        $out->elementEnd('h4');
+
+        $out->element('div', 'blog-entry-summary', $entry->summary);
+
+        // XXX: hide content initially; click More... for full text.
+
+        $out->element('div', 'blog-entry-content', $entry->content);
+    }
+}
diff --git a/plugins/Blog/newblogentry.php b/plugins/Blog/newblogentry.php
new file mode 100644 (file)
index 0000000..94988c5
--- /dev/null
@@ -0,0 +1,138 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * Save a new blog entry
+ * 
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Blog
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Save a new blog entry
+ *
+ * @category  Action
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class NewblogentryAction extends Action
+{
+    protected $user;
+    protected $title;
+    protected $content;
+    
+    /**
+     * For initializing members of the class.
+     *
+     * @param array $argarray misc. arguments
+     *
+     * @return boolean true
+     */
+
+    function prepare($argarray)
+    {
+        parent::prepare($argarray);
+
+        if (!$this->isPost()) {
+            throw new ClientException(_('Must be a POST.'), 405);
+        }
+
+        $this->user = common_current_user();
+
+        if (empty($this->user)) {
+            // TRANS: Client exception thrown when trying to post a blog entry while not logged in.
+            throw new ClientException(_m('Must be logged in to post a blog entry.'),
+                                      403);
+        }
+
+        $this->checkSessionToken();
+        
+        $this->title = $this->trimmed('title');
+
+        if (empty($this->title)) {
+            // TRANS: Client exception thrown when trying to post a blog entry without providing a title.
+            throw new ClientException(_m('Title required.'));
+        }
+
+        $this->content = $this->trimmed('content');
+
+        if (empty($this->content)) {
+            // TRANS: Client exception thrown when trying to post a blog entry without providing content.
+            throw new ClientException(_m('Content required.'));
+        }
+        
+        return true;
+    }
+
+    /**
+     * Handler method
+     *
+     * @param array $argarray is ignored since it's now passed in in prepare()
+     *
+     * @return void
+     */
+
+    function handle($argarray=null)
+    {
+        $options = array();
+
+        // Does the heavy-lifting for getting "To:" information
+
+        ToSelector::fillOptions($this, $options);
+
+        $options['source'] = 'web';
+            
+        $profile = $this->user->getProfile();
+
+        $saved = BlogEntry::saveNew($profile,
+                                    $this->title,
+                                    $this->content,
+                                    $options);
+        
+        if ($this->boolean('ajax')) {
+            header('Content-Type: text/xml; charset=utf-8');
+            $this->xw->startDocument('1.0', 'UTF-8');
+            $this->elementStart('html');
+            $this->elementStart('head');
+            // TRANS: Page title after sending a notice.
+            $this->element('title', null, _m('Blog entry saved'));
+            $this->elementEnd('head');
+            $this->elementStart('body');
+            $this->showNotice($saved);
+            $this->elementEnd('body');
+            $this->elementEnd('html');
+        } else {
+            common_redirect($saved->bestUrl(), 303);
+        }
+    }
+}
diff --git a/plugins/Blog/showblogentry.php b/plugins/Blog/showblogentry.php
new file mode 100644 (file)
index 0000000..4ddf796
--- /dev/null
@@ -0,0 +1,86 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * Show a blog entry
+ * 
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Blog
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Show a blog entry
+ *
+ * @category  Blog
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class ShowblogentryAction extends ShownoticeAction
+{
+    protected $id;
+    protected $entry;
+    
+    function getNotice()
+    {
+        $this->id = $this->trimmed('id');
+
+        $this->entry = BlogEntry::staticGet('id', $this->id);
+
+        if (empty($this->entry)) {
+            // TRANS: Client exception thrown when referring to a non-existing blog entry.
+            throw new ClientException(_m('No such entry.'), 404);
+        }
+
+        $notice = $this->entry->getNotice();
+
+        if (empty($notice)) {
+            // TRANS: Client exception thrown when referring to a non-existing blog entry.
+            throw new ClientException(_m('No such entry.'), 404);
+        }
+
+        return $notice;
+    }
+
+    /**
+     * Title of the page
+     *
+     * Used by Action class for layout.
+     *
+     * @return string page tile
+     */
+    function title()
+    {
+        // XXX: check for double-encoding
+        return (empty($this->entry->title)) ? _m('Untitled') : $this->entry->title;
+    }
+}