]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Merge branch 'nightly' of gitorious.org:social/mainline into nightly
authorRoland Haeder <roland@mxchange.org>
Tue, 10 Mar 2015 17:17:50 +0000 (18:17 +0100)
committerRoland Haeder <roland@mxchange.org>
Tue, 10 Mar 2015 17:18:38 +0000 (18:18 +0100)
Signed-off-by: Roland Haeder <roland@mxchange.org>
19 files changed:
classes/Notice.php
lib/activityverb.php
lib/default.php
lib/installer.php
lib/noticelistitem.php
plugins/ActivityVerb/ActivityVerbPlugin.php [new file with mode: 0644]
plugins/ActivityVerb/actions/activityverb.php [new file with mode: 0644]
plugins/ActivityVerb/lib/activityverbhandlerplugin.php [new file with mode: 0644]
plugins/AnonymousFave/actions/anonfavor.php
plugins/Favorite/FavoritePlugin.php
plugins/Favorite/actions/apifavoritecreate.php
plugins/Favorite/actions/disfavor.php [deleted file]
plugins/Favorite/actions/favor.php [deleted file]
plugins/Favorite/classes/Fave.php
plugins/Favorite/forms/disfavor.php
plugins/Favorite/forms/favor.php
plugins/Favorite/lib/favcommand.php
plugins/SiteNoticeInSidebar/lib/sitenoticesection.php
theme/base/css/display.css

index 86eee49321a22ec89ec56e9edb3f29359a767b6a..0ef25476caae583b220c9cc5bcbf43e1f31d5934 100644 (file)
@@ -313,6 +313,16 @@ class Notice extends Managed_DataObject
         return $notice;
     }
 
+    public static function getById($id)
+    {
+        $notice = new Notice();
+        $notice->id = $id;
+        if (!$notice->find(true)) {
+            throw new NoResultException($notice);
+        }
+        return $notice;
+    }
+
     /**
      * Extract #hashtags from this notice's content and save them to the database.
      */
index 513605b620a84356e7c82e2e3ad7c4bf05ff35de..dc6f9c93f4719b50b733c021ff1b83ed08613084 100644 (file)
@@ -48,6 +48,7 @@ class ActivityVerb
     const SHARE    = 'http://activitystrea.ms/schema/1.0/share';
     const SAVE     = 'http://activitystrea.ms/schema/1.0/save';
     const FAVORITE = 'http://activitystrea.ms/schema/1.0/favorite';
+    const LIKE     = 'http://activitystrea.ms/schema/1.0/like'; // This is a synonym of favorite
     const PLAY     = 'http://activitystrea.ms/schema/1.0/play';
     const FOLLOW   = 'http://activitystrea.ms/schema/1.0/follow';
     const FRIEND   = 'http://activitystrea.ms/schema/1.0/make-friend';
@@ -56,7 +57,8 @@ class ActivityVerb
 
     // Custom OStatus verbs for the flipside until they're standardized
     const DELETE     = 'http://ostatus.org/schema/1.0/unfollow';
-    const UNFAVORITE = 'http://ostatus.org/schema/1.0/unfavorite';
+    const UNFAVORITE = 'http://activitystrea.ms/schema/1.0/unfavorite';
+    const UNLIKE     = 'http://activitystrea.ms/schema/1.0/unlike'; // This is a synonym of unfavorite
     const UNFOLLOW   = 'http://ostatus.org/schema/1.0/unfollow';
     const LEAVE      = 'http://ostatus.org/schema/1.0/leave';
     const UNTAG      = 'http://ostatus.org/schema/1.0/untag';
index 239260f28bae20b9c355758cf37498c65b8ad717..1427c2d28b3424a20926988f144ec492c1dc2afa 100644 (file)
@@ -299,6 +299,7 @@ $default =
         array('disabled' => true),
         'plugins' =>
         array('core' => array(
+                            'ActivityVerb' => array(),
                             'AuthCrypt' => array(),
                             'Cronish' => array(),
                             'Favorite' => array(),
index bfb56021682c09e0466296f17eab2d469b60fd8b..6b0278ee0b81b8dc83b97795dec26ea1d7c578b4 100644 (file)
@@ -224,7 +224,7 @@ abstract class Installer
         }
         // @fixme hardcoded list; should use Nickname::isValid()
         // if/when it's safe to have loaded the infrastructure here
-        $blacklist = array('main', 'panel', 'twitter', 'settings', 'rsd.xml', 'favorited', 'featured', 'favoritedrss', 'featuredrss', 'rss', 'getfile', 'api', 'groups', 'group', 'peopletag', 'tag', 'user', 'message', 'conversation', 'notice', 'attachment', 'search', 'index.php', 'doc', 'opensearch', 'robots.txt', 'xd_receiver.html', 'facebook');
+        $blacklist = array('main', 'panel', 'twitter', 'settings', 'rsd.xml', 'favorited', 'featured', 'favoritedrss', 'featuredrss', 'rss', 'getfile', 'api', 'groups', 'group', 'peopletag', 'tag', 'user', 'message', 'conversation', 'notice', 'attachment', 'search', 'index.php', 'doc', 'opensearch', 'robots.txt', 'xd_receiver.html', 'facebook', 'activity');
         if (in_array($this->adminNick, $blacklist)) {
             $this->updateStatus('The user nickname "' . htmlspecialchars($this->adminNick) .
                          '" is reserved.', true);
index 49e11e513a010bfa59398b002056a171f87c4c8a..dda16507e473fbe4b3c6fdd0c663b536f94e7888 100644 (file)
@@ -63,6 +63,7 @@ class NoticeListItem extends Widget
     protected $id_prefix = null;
     protected $options = true;
     protected $maxchars = 0;   // if <= 0 it means use full posts
+    protected $item_tag = 'li';
 
     /**
      * constructor
@@ -101,7 +102,7 @@ class NoticeListItem extends Widget
             }
         }
         // string preferences
-        foreach(array('id_prefix') as $key) {
+        foreach(array('id_prefix', 'item_tag') as $key) {
             if (array_key_exists($key, $prefs)) {
                 $this->$key = $prefs[$key];
             }
@@ -221,7 +222,7 @@ class NoticeListItem extends Widget
                 $class .= ' notice-source-'.$this->notice->source;
             }
             $id_prefix = (strlen($this->id_prefix) ? $this->id_prefix . '-' : '');
-            $this->out->elementStart('li', array('class' => $class,
+            $this->out->elementStart($this->item_tag, array('class' => $class,
                                                  'id' => "${id_prefix}notice-${id}"));
             Event::handle('EndOpenNoticeListItemElement', array($this));
         }
diff --git a/plugins/ActivityVerb/ActivityVerbPlugin.php b/plugins/ActivityVerb/ActivityVerbPlugin.php
new file mode 100644 (file)
index 0000000..dab4cb4
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+/**
+ * GNU social - a federating social network
+ *
+ * Plugin that handles activity verb interact (like 'favorite' etc.)
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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  Plugin
+ * @package   GNUsocial
+ * @author    Mikael Nordfeldth <mmn@hethane.se>
+ * @copyright 2014 Free Software Foundation http://fsf.org
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      https://www.gnu.org/software/social/
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+class ActivityVerbPlugin extends Plugin
+{
+
+    public function onRouterInitialized(URLMapper $m)
+    {
+        $m->connect('notice/:id/:verb',
+                    array('action' => 'activityverb'),
+                    array('id'     => '[0-9]+',
+                          'verb'   => '[a-z]+'));
+        $m->connect('activity/:id/:verb',
+                    array('action' => 'activityverb'),
+                    array('id'     => '[0-9]+',
+                          'verb'   => '[a-z]+'));
+    }
+
+    public function onPluginVersion(&$versions)
+    {
+        $versions[] = array('name' => 'Activity Verb',
+                            'version' => GNUSOCIAL_VERSION,
+                            'author' => 'Mikael Nordfeldth',
+                            'homepage' => 'https://www.gnu.org/software/social/',
+                            'rawdescription' =>
+                            // TRANS: Plugin description.
+                            _m('Adds more standardized verb handling for activities.'));
+        return true;
+    }
+}
diff --git a/plugins/ActivityVerb/actions/activityverb.php b/plugins/ActivityVerb/actions/activityverb.php
new file mode 100644 (file)
index 0000000..0abfacd
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/**
+ * GNU social - a federating social network
+ *
+ * Class for deleting a notice
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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  Plugin
+ * @package   GNUsocial
+ * @author    Mikael Nordfeldth <mmn@hethane.se>
+ * @copyright 2015 Free Software Foundaction, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      https://gnu.io/social
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+class ActivityverbAction extends ManagedAction
+{
+    protected $needLogin = true;
+    protected $canPost   = true;
+
+    protected $verb      = null;
+
+    public function title()
+    {
+        $title = null;
+        Event::handle('ActivityVerbTitle', array($this, $this->verb, $this->notice, $this->scoped, &$title));
+        return $title;
+    }
+
+    protected function doPreparation()
+    {
+        $this->verb = $this->trimmed('verb');
+        if (empty($this->verb)) {
+            throw new ServerException('A verb has not been specified.');
+        }
+
+        $this->notice = Notice::getById($this->trimmed('id'));
+
+        if (!$this->notice->inScope($this->scoped)) {
+            // TRANS: %1$s is a user nickname, %2$d is a notice ID (number).
+            throw new ClientException(sprintf(_('%1$s has no access to notice %2$d.'),
+                                        $this->scoped->getNickname(), $this->notice->getID()), 403);
+        }
+
+        Event::handle('ActivityVerbDoPreparation', array($this, $this->verb, $this->notice, $this->scoped));
+    }
+
+    protected function doPost()
+    {
+        if (Event::handle('ActivityVerbDoPost', array($this, $this->verb, $this->notice, $this->scoped))) {
+            // TRANS: Error when a POST method for an activity verb has not been handled by a plugin.
+            throw new ClientException(sprintf(_('Could not handle POST for verb "%1$s".'), $this->verb));
+        }
+    }
+
+    protected function showContent()
+    {
+        if (Event::handle('ActivityVerbShowContent', array($this, $this->verb, $this->notice, $this->scoped))) {
+            // TRANS: Error when a page for an activity verb has not been handled by a plugin.
+            $this->element('div', 'error', sprintf(_('Could not show content for verb "%1$s".'), $this->verb));
+        }
+    }
+}
diff --git a/plugins/ActivityVerb/lib/activityverbhandlerplugin.php b/plugins/ActivityVerb/lib/activityverbhandlerplugin.php
new file mode 100644 (file)
index 0000000..0d06266
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+/*
+ * GNU Social - a federating social network
+ * Copyright (C) 2014, Free Software Foundation, Inc.
+ *
+ * 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/>.
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+/**
+ * @package     Activity
+ * @maintainer  Mikael Nordfeldth <mmn@hethane.se>
+ */
+abstract class ActivityVerbHandlerPlugin extends ActivityHandlerPlugin
+{
+    public function onActivityVerbTitle(ManagedAction $action, $verb, Notice $target, Profile $scoped, &$title)
+    {
+        if (!$this->isMyVerb($verb)) {
+            return true;
+        }
+
+        $title = $this->getActionTitle($action, $verb, $target, $scoped);
+        return false;
+    }
+    abstract protected function getActionTitle(ManagedAction $action, $verb, Notice $target, Profile $scoped);
+
+    public function onActivityVerbShowContent(ManagedAction $action, $verb, Notice $target, Profile $scoped)
+    {
+        if (!$this->isMyVerb($verb)) {
+            return true;
+        }
+
+        return $this->showActionContent($action, $verb, $target, $scoped);
+    }
+    protected function showActionContent(ManagedAction $action, $verb, Notice $target, Profile $scoped)
+    {
+        if (!GNUsocial::isAjax()) {
+            $nl = new NoticeListItem($target, $action, array('options'=>false, 'attachments'=>false,
+                                                             'item_tag'=>'div', 'id_prefix'=>'fave'));
+            $nl->show();
+        }
+
+        $form = $this->getActivityForm($action, $verb, $target, $scoped);
+        $form->show();
+
+        return false;
+    }
+
+    public function onActivityVerbDoPreparation(ManagedAction $action, $verb, Notice $target, Profile $scoped)
+    {
+        if (!$this->isMyVerb($verb)) {
+            return true;
+        }
+
+        return $this->doActionPreparation($action, $verb, $target, $scoped);
+    }
+    abstract protected function doActionPreparation(ManagedAction $action, $verb, Notice $target, Profile $scoped);
+
+    public function onActivityVerbDoPost(ManagedAction $action, $verb, Notice $target, Profile $scoped)
+    {
+        if (!$this->isMyVerb($verb)) {
+            return true;
+        }
+
+        return $this->doActionPost($action, $verb, $target, $scoped);
+    }
+    abstract protected function doActionPost(ManagedAction $action, $verb, Notice $target, Profile $scoped);
+
+    abstract protected function getActivityForm(ManagedAction $action, $verb, Notice $target, Profile $scoped);
+}
index eacd7753310f4753d1f0607b44ea6015e397f3a9..6ce0e84a16d76347b7d3438eda68d51bbc03c152 100644 (file)
@@ -62,11 +62,6 @@ class AnonFavorAction extends RedirectingAction
         $notice = Notice::getKV($id);
         $token  = $this->checkSessionToken();
 
-        if (Fave::existsForProfile($notice, $profile)) {
-            // TRANS: Client error.
-            throw new AlreadyFulfilledException(_m('This notice is already a favorite!'));
-        }
-
         // Throws exception
         $stored = Fave::addNew($profile, $notice);
 
index 49ba2b684515b425a93c791b49cb026f07ed47b1..f298fc3e928b8fca1a20c642569f4f863bac550f 100644 (file)
@@ -23,7 +23,7 @@ if (!defined('GNUSOCIAL')) { exit(1); }
  * @package     Activity
  * @maintainer  Mikael Nordfeldth <mmn@hethane.se>
  */
-class FavoritePlugin extends ActivityHandlerPlugin
+class FavoritePlugin extends ActivityVerbHandlerPlugin
 {
     protected $email_notify_fave = 1;
 
@@ -39,9 +39,10 @@ class FavoritePlugin extends ActivityHandlerPlugin
 
     public function verbs()
     {
-        return array(ActivityVerb::FAVORITE);
+        return array(ActivityVerb::FAVORITE, ActivityVerb::LIKE,
+                    ActivityVerb::UNFAVORITE, ActivityVerb::UNLIKE);
     }
-    
+
     public function onCheckSchema()
     {
         $schema = Schema::get();
@@ -78,14 +79,14 @@ class FavoritePlugin extends ActivityHandlerPlugin
             printfnq("DONE.\n");
         }
     }
-    
+
     public function onEndUpgrade()
     {
         printfnq("Ensuring all faves have a URI...");
-    
+
         $fave = new Fave();
         $fave->whereAdd('uri IS NULL');
-    
+
         if ($fave->find()) {
             while ($fave->fetch()) {
                 try {
@@ -104,7 +105,7 @@ class FavoritePlugin extends ActivityHandlerPlugin
                 }
             }
         }
-    
+
         printfnq("DONE.\n");
     }
 
@@ -138,28 +139,28 @@ class FavoritePlugin extends ActivityHandlerPlugin
 
         // Favorites for API
         $m->connect('api/favorites/create.:format',
-                    array('action' => 'ApiFavoriteCreate',
-                          'format' => '(xml|json)'));
+                    array('action' => 'ApiFavoriteCreate'),
+                    array('format' => '(xml|json)'));
         $m->connect('api/favorites/destroy.:format',
-                    array('action' => 'ApiFavoriteDestroy',
-                          'format' => '(xml|json)'));
+                    array('action' => 'ApiFavoriteDestroy'),
+                    array('format' => '(xml|json)'));
         $m->connect('api/favorites/list.:format',
-                    array('action' => 'ApiTimelineFavorites',
-                          'format' => '(xml|json|rss|atom|as)'));
+                    array('action' => 'ApiTimelineFavorites'),
+                    array('format' => '(xml|json|rss|atom|as)'));
         $m->connect('api/favorites/:id.:format',
-                    array('action' => 'ApiTimelineFavorites',
-                          'id' => Nickname::INPUT_FMT,
+                    array('action' => 'ApiTimelineFavorites'),
+                    array('id' => Nickname::INPUT_FMT,
                           'format' => '(xml|json|rss|atom|as)'));
         $m->connect('api/favorites.:format',
-                    array('action' => 'ApiTimelineFavorites',
-                          'format' => '(xml|json|rss|atom|as)'));
+                    array('action' => 'ApiTimelineFavorites'),
+                    array('format' => '(xml|json|rss|atom|as)'));
         $m->connect('api/favorites/create/:id.:format',
-                    array('action' => 'ApiFavoriteCreate',
-                          'id' => '[0-9]+',
+                    array('action' => 'ApiFavoriteCreate'),
+                    array('id' => '[0-9]+',
                           'format' => '(xml|json)'));
         $m->connect('api/favorites/destroy/:id.:format',
-                    array('action' => 'ApiFavoriteDestroy',
-                          'id' => '[0-9]+',
+                    array('action' => 'ApiFavoriteDestroy'),
+                    array('id' => '[0-9]+',
                           'format' => '(xml|json)'));
 
         // AtomPub API
@@ -174,13 +175,13 @@ class FavoritePlugin extends ActivityHandlerPlugin
 
         // Required for qvitter API
         $m->connect('api/statuses/favs/:id.:format',
-                    array('action' => 'ApiStatusesFavs',
-                          'id' => '[0-9]+',
+                    array('action' => 'ApiStatusesFavs'),
+                    array('id' => '[0-9]+',
                           'format' => '(xml|json)'));
     }
 
     // FIXME: Set this to abstract public in lib/activityhandlerplugin.php ddwhen all plugins have migrated!
-    protected function saveObjectFromActivity(Activity $act, Notice $stored, array $options=array())  
+    protected function saveObjectFromActivity(Activity $act, Notice $stored, array $options=array())
     {
         assert($this->isMyActivity($act));
 
@@ -263,7 +264,7 @@ class FavoritePlugin extends ActivityHandlerPlugin
         }
         return true;
     }
-    
+
     public function onNoticeDeleteRelated(Notice $notice)
     {
         parent::onNoticeDeleteRelated($notice);
@@ -284,13 +285,14 @@ class FavoritePlugin extends ActivityHandlerPlugin
         $fave->free();
     }
 
-    public function onUserDeleteRelated(User $user, array &$related)
+    public function onProfileDeleteRelated(Profile $profile, array &$related)
     {
         $fave = new Fave();
-        $fave->user_id = $user->id;
+        $fave->user_id = $profile->id;
         $fave->delete();    // Will perform a DELETE matching "user_id = {$user->id}"
+        $fave->free();
 
-        Fave::blowCacheForProfileId($user->id);
+        Fave::blowCacheForProfileId($profile->id);
         return true;
     }
 
@@ -502,6 +504,62 @@ class FavoritePlugin extends ActivityHandlerPlugin
         }
     }
 
+    protected function getActionTitle(ManagedAction $action, $verb, Notice $target, Profile $scoped)
+    {
+        return Fave::existsForProfile($target, $scoped)
+                // TRANS: Page/dialog box title when a notice is marked as favorite already
+                ? _m('TITLE', 'Unmark notice as favorite')
+                // TRANS: Page/dialog box title when a notice is not marked as favorite
+                : _m('TITLE', 'Mark notice as favorite');
+    }
+
+    protected function doActionPreparation(ManagedAction $action, $verb, Notice $target, Profile $scoped)
+    {
+        if ($action->isPost()) {
+            // The below tests are only for presenting to the user. POSTs which inflict
+            // duplicate favorite entries are handled with AlreadyFulfilledException. 
+            return false;
+        }
+
+        $exists = Fave::existsForProfile($target, $scoped);
+        $expected_verb = $exists ? ActivityVerb::UNFAVORITE : ActivityVerb::FAVORITE;
+
+        switch (true) {
+        case $exists && ActivityUtils::compareTypes($verb, array(ActivityVerb::FAVORITE, ActivityVerb::LIKE)):
+        case !$exists && ActivityUtils::compareTypes($verb, array(ActivityVerb::UNFAVORITE, ActivityVerb::UNLIKE)):
+            common_redirect(common_local_url('activityverb',
+                                array('id'   => $target->getID(),
+                                      'verb' => ActivityUtils::resolveUri($expected_verb, true))));
+            break;
+        default:
+            // No need to redirect as we are on the correct action already.
+        }
+
+        return false;
+    }
+
+    protected function doActionPost(ManagedAction $action, $verb, Notice $target, Profile $scoped)
+    {
+        switch (true) {
+        case ActivityUtils::compareTypes($verb, array(ActivityVerb::FAVORITE, ActivityVerb::LIKE)):
+            Fave::addNew($scoped, $target);
+            break;
+        case ActivityUtils::compareTypes($verb, array(ActivityVerb::UNFAVORITE, ActivityVerb::UNLIKE)):
+            Fave::removeEntry($scoped, $target);
+            break;
+        default:
+            throw new ServerException('ActivityVerb POST not handled by plugin that was supposed to do it.');
+        }
+        return false;
+    }
+
+    protected function getActivityForm(ManagedAction $action, $verb, Notice $target, Profile $scoped)
+    {
+        return Fave::existsForProfile($target, $scoped)
+                ? new DisfavorForm($action, $target)
+                : new FavorForm($action, $target);
+    }
+
     public function onPluginVersion(array &$versions)
     {
         $versions[] = array('name' => 'Favorite',
index 8a273740534c639b6f681a78cbd2677681b23c2f..7ff8f391b2466309df4d109866c1e16df438cf49 100644 (file)
@@ -101,20 +101,13 @@ class ApiFavoriteCreateAction extends ApiAuthAction
             );
         }
 
-        // Note: Twitter lets you fave things repeatedly via API.
-
-        if (Fave::existsForProfile($this->notice, $this->scoped)) {
-            $this->clientError(
-                // TRANS: Client error displayed when trying to mark a notice favourite that already is a favourite.
-                _('This status is already a favorite.'),
-                403,
-                $this->format
-            );
+        try {
+            $stored = Fave::addNew($this->scoped, $this->notice);
+        } catch (AlreadyFulfilledException $e) {
+            // Note: Twitter lets you fave things repeatedly via API.
+            $this->clientError($e->getMessage(), 403);
         }
 
-        // throws exception on failure
-        $stored = Fave::addNew($this->scoped, $this->notice);
-
         if ($this->format == 'xml') {
             $this->showSingleXmlStatus($this->notice);
         } elseif ($this->format == 'json') {
diff --git a/plugins/Favorite/actions/disfavor.php b/plugins/Favorite/actions/disfavor.php
deleted file mode 100644 (file)
index 926bbec..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-<?php
-/**
- * Disfavor action.
- *
- * PHP version 5
- *
- * @category Action
- * @package  GNUsocial
- * @author   Evan Prodromou <evan@status.net>
- * @author   Robin Millette <millette@status.net>
- * @author   Mikael Nordfeldth <mmn@hethane.se>
- * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
- * @link     http://www.gnu.org/software/social/
- *
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, StatusNet, Inc.
- *
- * 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/>.
- */
-
-if (!defined('GNUSOCIAL')) { exit(1); }
-
-/**
- * DisfavorAction class.
- *
- * @category Action
- * @package  GNUsocial
- * @author   Evan Prodromou <evan@status.net>
- * @author   Robin Millette <millette@status.net>
- * @author   Mikael Nordfeldth <mmn@hethane.se>
- * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
- * @link     http://www.gnu.org/software/social/
- */
-class DisfavorAction extends FormAction
-{
-    protected $needPost = true;
-
-    protected function doPreparation()
-    {
-        $this->target = Notice::getKV($this->trimmed('notice'));
-        if (!$this->target instanceof Notice) {
-            throw new ServerException(_m('No such notice.'));
-        }
-    }
-
-    protected function doPost()
-    {
-        $fave            = new Fave();
-        $fave->user_id   = $this->scoped->getID();
-        $fave->notice_id = $this->target->getID();
-        if (!$fave->find(true)) {
-            // TRANS: Client error displayed when trying to remove a 'favor' when there is none in the first place.
-            throw new AlreadyFulfilledException(_('This is already not favorited.'));
-        }
-        $result = $fave->delete();
-        if ($result === false) {
-            common_log_db_error($fave, 'DELETE', __FILE__);
-            // TRANS: Server error displayed when removing a favorite from the database fails.
-            throw new ServerException(_('Could not delete favorite.'));
-        }
-        Fave::blowCacheForProfileId($this->scoped->getID());
-
-        // TRANS: Message when a disfavor action has been taken for a notice.
-        return _('Disfavored the notice.');
-    }
-
-    protected function showContent()
-    {
-        // We show the 'Favor' form because right now all calls to Disfavor will directly disfavor a notice.
-        $disfavor = new FavorForm($this, $this->target);
-        $disfavor->show();
-    }
-}
diff --git a/plugins/Favorite/actions/favor.php b/plugins/Favorite/actions/favor.php
deleted file mode 100644 (file)
index f659078..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-<?php
-/**
- * Favor action.
- *
- * PHP version 5
- *
- * @category Action
- * @package  GNUsocial
- * @author   Evan Prodromou <evan@status.net>
- * @author   Robin Millette <millette@status.net>
- * @author   Mikael Nordfeldth <mmn@hethane.se>
- * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
- * @link     http://www.gnu.org/software/social/
- *
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, StatusNet, Inc.
- *
- * 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/>.
- */
-
-if (!defined('GNUSOCIAL')) { exit(1); }
-
-/**
- * FavorAction class.
- *
- * @category Action
- * @package  GNUsocial
- * @author   Evan Prodromou <evan@status.net>
- * @author   Robin Millette <millette@status.net>
- * @author   Mikael Nordfeldth <mmn@hethane.se>
- * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
- * @link     http://www.gnu.org/software/social/
- */
-class FavorAction extends FormAction
-{
-    protected $needPost = true;
-
-    protected function doPreparation()
-    {
-        $this->target = Notice::getKV($this->trimmed('notice'));
-        if (!$this->target instanceof Notice) {
-            throw new ServerException(_m('No such notice.'));
-        }
-        if (!$this->target->inScope($this->scoped)) {
-            // TRANS: Client error displayed when trying to interact with a notice a the target has no access to.
-            // TRANS: %1$s is a user nickname, %2$d is a notice ID (number).
-            throw new ClientException(sprintf(_m('%1$s has no right to interact with notice %2$d.'), $this->scoped->getNickname(), $this->target->getID()), 403);
-        }
-    }
-
-    protected function doPost()
-    {
-        if (Fave::existsForProfile($this->target, $this->scoped)) {
-            // TRANS: Client error displayed when trying to mark a notice as favorite that already is a favorite.
-            throw new AlreadyFulfilledException(_('You have already favorited this!'));
-        }
-
-        // throws exception on failure
-        $stored = Fave::addNew($this->scoped, $this->target);
-
-        // TRANS: Message when a favor action has been taken for a notice.
-        return _('Favorited the notice');
-    }
-
-    protected function showContent()
-    {
-        $disfavor = new DisfavorForm($this, $this->target);
-        $disfavor->show();
-    }
-}
index 094b65feaa94fd19b38f6b5dd12e6af5b48ebd10..48ed3ba93bcb3d4a8accae430e4c054e2a0ef9f2 100644 (file)
@@ -48,6 +48,11 @@ class Fave extends Managed_DataObject
      * @throws Exception on failure
      */
     static function addNew(Profile $actor, Notice $target) {
+        if (self::existsForProfile($target, $actor)) {
+            // TRANS: Client error displayed when trying to mark a notice as favorite that already is a favorite.
+            throw new AlreadyFulfilledException(_('You have already favorited this!'));
+        }
+
         $act = new Activity();
         $act->type    = ActivityObject::ACTIVITY;
         $act->verb    = ActivityVerb::FAVORITE;
@@ -74,6 +79,27 @@ class Fave extends Managed_DataObject
         return $stored;
     }
 
+    public function removeEntry(Profile $actor, Notice $target)
+    {
+        $fave            = new Fave();
+        $fave->user_id   = $actor->getID();
+        $fave->notice_id = $target->getID();
+        if (!$fave->find(true)) {
+            // TRANS: Client error displayed when trying to remove a 'favor' when there is none in the first place.
+            throw new AlreadyFulfilledException(_('This is already not favorited.'));
+        }
+
+        $result = $fave->delete();
+        if ($result === false) {
+            common_log_db_error($fave, 'DELETE', __FILE__);
+            // TRANS: Server error displayed when removing a favorite from the database fails.
+            throw new ServerException(_('Could not delete favorite.'));
+        }
+
+        Fave::blowCacheForProfileId($actor->getID());
+        Fave::blowCacheForNoticeId($target->getID());
+    }
+
     // exception throwing takeover!
     public function insert()
     {
index 51903b6cb2d9d61c0f3e0c2bd5e3e9972602199d..f6702ebf29a3d4e11c1f151cedbe6bb112e701e5 100644 (file)
@@ -81,7 +81,9 @@ class DisfavorForm extends Form
      */
     function action()
     {
-        return common_local_url('disfavor');
+        return common_local_url('activityverb',
+                                array('id'   => $this->notice->getID(),
+                                      'verb' => ActivityUtils::resolveUri(ActivityVerb::UNFAVORITE, true)));
     }
 
     /**
index cd956f67ff27ffde0c8876366c21be5fda0ef73d..e7d05ce09729ebe0736d20556d24091db35b5dc7 100644 (file)
@@ -81,7 +81,9 @@ class FavorForm extends Form
      */
     function action()
     {
-        return common_local_url('favor');
+        return common_local_url('activityverb',
+                                array('id'   => $this->notice->getID(),
+                                      'verb' => ActivityUtils::resolveUri(ActivityVerb::FAVORITE, true)));
     }
 
     /**
index cf5ca79218ed293377555b7213ea2d92c37748a7..6c7d0d1946ae1c09c4418ebcabc228937ad1f268 100644 (file)
@@ -14,17 +14,6 @@ class FavCommand extends Command
     { 
         $notice = $this->getNotice($this->other); 
  
-        $fave            = new Fave(); 
-        $fave->user_id   = $this->user->id; 
-        $fave->notice_id = $notice->id; 
-        $fave->find(); 
-        if ($fave->fetch()) { 
-            // TRANS: Error message text shown when a favorite could not be set because it has already been favorited. 
-            $channel->error($this->user, _('Could not create favorite: Already favorited.')); 
-            return; 
-        } 
         try {
             $fave = Fave::addNew($this->user->getProfile(), $notice); 
         } catch (Exception $e) {
index 37c37edaf27d5e61e059ce88b04ea42549c5c9ce..b713ec7c6f815ae20f95a51619120c33285074c0 100644 (file)
@@ -60,6 +60,11 @@ class SiteNoticeSection extends Section
         return _('Site notice');
     }
 
+    function divId()
+    {
+        return 'site_notice';
+    }
+
     function showContent()
     {
         $this->out->raw($this->text);
index 7aee99a31b118c718a28124a4a26aad295fc4789..091a4ad5420cddd12068916ddb1c8eee2c5e791a 100644 (file)
@@ -630,7 +630,7 @@ address .poweredby {
     line-height: 1.36em;
 }
 
-.notice, .profile, .application, #content .peopletag {
+.application, #content .peopletag {
     position:relative;
     clear:both;
     float:left;