From: Mikael Nordfeldth Date: Mon, 5 May 2014 21:57:41 +0000 (+0200) Subject: More modern coding, stuff related to subscriptions X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;ds=sidebyside;h=fc3125cf28fbcf072194be4465a145d54a044877;p=quix0rs-gnu-social.git More modern coding, stuff related to subscriptions Also trying to use the newly implemented AlreadyFulfilledException --- diff --git a/classes/Subscription.php b/classes/Subscription.php index 4f27537f27..12f4e86f10 100644 --- a/classes/Subscription.php +++ b/classes/Subscription.php @@ -17,21 +17,16 @@ * along with this program. If not, see . */ -if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } +if (!defined('GNUSOCIAL')) { exit(1); } /** * Table Definition for subscription */ -require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; - class Subscription extends Managed_DataObject { const CACHE_WINDOW = 201; const FORCE = true; - ###START_AUTOCODE - /* the code below is auto generated do not remove the above tag */ - public $__table = 'subscription'; // table name public $subscriber; // int(4) primary_key not_null public $subscribed; // int(4) primary_key not_null @@ -88,7 +83,7 @@ class Subscription extends Managed_DataObject if (self::exists($subscriber, $other)) { // TRANS: Exception thrown when trying to subscribe while already subscribed. - throw new Exception(_('Already subscribed!')); + throw new AlreadyFulfilledException(_('Already subscribed!')); } if ($other->hasBlocked($subscriber)) { @@ -98,7 +93,7 @@ class Subscription extends Managed_DataObject if (Event::handle('StartSubscribe', array($subscriber, $other))) { $otherUser = User::getKV('id', $other->id); - if ($otherUser && $otherUser->subscribe_policy == User::SUBSCRIBE_POLICY_MODERATE && !$force) { + if ($otherUser instanceof User && $otherUser->subscribe_policy == User::SUBSCRIBE_POLICY_MODERATE && !$force) { $sub = Subscription_queue::saveNew($subscriber, $other); $sub->notify(); } else { @@ -113,13 +108,16 @@ class Subscription extends Managed_DataObject $subscriber->blowSubscriptionCount(); $other->blowSubscriberCount(); - if (!empty($otherUser) && + if ($otherUser instanceof User && $otherUser->autosubscribe && !self::exists($other, $subscriber) && !$subscriber->hasBlocked($other)) { try { self::start($other, $subscriber); + } catch (AlreadyFulfilledException $e) { + // This shouldn't happen due to !self::exists above + common_debug('Tried to autosubscribe a user to its new subscriber.'); } catch (Exception $e) { common_log(LOG_ERR, "Exception during autosubscribe of {$other->nickname} to profile {$subscriber->id}: {$e->getMessage()}"); } @@ -151,7 +149,7 @@ class Subscription extends Managed_DataObject $result = $sub->insert(); - if (!$result) { + if ($result===false) { common_log_db_error($sub, 'INSERT', __FILE__); // TRANS: Exception thrown when a subscription could not be stored on the server. throw new Exception(_('Could not save subscription.')); @@ -173,7 +171,7 @@ class Subscription extends Managed_DataObject { $subscribedUser = User::getKV('id', $this->subscribed); - if (!empty($subscribedUser)) { + if ($subscribedUser instanceof User) { $subscriber = Profile::getKV('id', $this->subscriber); @@ -189,7 +187,7 @@ class Subscription extends Managed_DataObject { if (!self::exists($subscriber, $other)) { // TRANS: Exception thrown when trying to unsibscribe without a subscription. - throw new Exception(_('Not subscribed!')); + throw new AlreadyFulfilledException(_('Not subscribed!')); } // Don't allow deleting self subs @@ -234,7 +232,7 @@ class Subscription extends Managed_DataObject { $sub = Subscription::pkeyGet(array('subscriber' => $subscriber->id, 'subscribed' => $other->id)); - return (empty($sub)) ? false : true; + return ($sub instanceof Subscription); } function asActivity() @@ -242,12 +240,12 @@ class Subscription extends Managed_DataObject $subscriber = Profile::getKV('id', $this->subscriber); $subscribed = Profile::getKV('id', $this->subscribed); - if (empty($subscriber)) { - throw new Exception(sprintf(_('No profile for the subscriber: %d'), $this->subscriber)); + if (!$subscriber instanceof Profile) { + throw new NoProfileException($this->subscriber); } - if (empty($subscribed)) { - throw new Exception(sprintf(_('No profile for the subscribed: %d'), $this->subscribed)); + if (!$subscribed instanceof Profile) { + throw new NoProfileException($this->subscribed); } $act = new Activity(); diff --git a/classes/Subscription_queue.php b/classes/Subscription_queue.php index ea0e906d43..405eca93fd 100644 --- a/classes/Subscription_queue.php +++ b/classes/Subscription_queue.php @@ -1,22 +1,18 @@ $subscriber->id, 'subscribed' => $other->id)); - return (empty($sub)) ? false : true; + return ($sub instanceof Subscription_queue); } /** @@ -64,9 +60,11 @@ class Subscription_queue extends Managed_DataObject { $subscriber = Profile::getKV('id', $this->subscriber); $subscribed = Profile::getKV('id', $this->subscribed); - $sub = Subscription::start($subscriber, $subscribed, Subscription::FORCE); - if ($sub) { + try { + $sub = Subscription::start($subscriber, $subscribed, Subscription::FORCE); $this->delete(); + } catch (AlreadyFulfilledException $e) { + common_debug('Tried to start a subscription which already existed.'); } return $sub; } diff --git a/plugins/OStatus/actions/salmon.php b/plugins/OStatus/actions/salmon.php deleted file mode 100644 index 2a6fc15edd..0000000000 --- a/plugins/OStatus/actions/salmon.php +++ /dev/null @@ -1,227 +0,0 @@ -. - */ - -/** - * @package OStatusPlugin - * @author James Walker - */ - -if (!defined('GNUSOCIAL')) { exit(1); } - -class SalmonAction extends Action -{ - var $xml = null; - var $activity = null; - var $target = null; - - protected function prepare(array $args=array()) - { - StatusNet::setApi(true); // Send smaller error pages - - parent::prepare($args); - - if ($_SERVER['REQUEST_METHOD'] != 'POST') { - // TRANS: Client error. POST is a HTTP command. It should not be translated. - $this->clientError(_m('This method requires a POST.')); - } - - if (empty($_SERVER['CONTENT_TYPE']) || $_SERVER['CONTENT_TYPE'] != 'application/magic-envelope+xml') { - // TRANS: Client error. Do not translate "application/magic-envelope+xml". - $this->clientError(_m('Salmon requires "application/magic-envelope+xml".')); - } - - $xml = file_get_contents('php://input'); - - // Check the signature - $salmon = new Salmon; - if (!$salmon->verifyMagicEnv($xml)) { - common_log(LOG_DEBUG, "Salmon signature verification failed."); - // TRANS: Client error. - $this->clientError(_m('Salmon signature verification failed.')); - } else { - $magic_env = new MagicEnvelope(); - $env = $magic_env->parse($xml); - $xml = $magic_env->unfold($env); - } - - $dom = DOMDocument::loadXML($xml); - if ($dom->documentElement->namespaceURI != Activity::ATOM || - $dom->documentElement->localName != 'entry') { - common_log(LOG_DEBUG, "Got invalid Salmon post: $xml"); - // TRANS: Client error. - $this->clientError(_m('Salmon post must be an Atom entry.')); - } - - $this->activity = new Activity($dom->documentElement); - return true; - } - - /** - * Check the posted activity type and break out to appropriate processing. - */ - - protected function handle() - { - parent::handle(); - - common_log(LOG_DEBUG, "Got a " . $this->activity->verb); - if (Event::handle('StartHandleSalmonTarget', array($this->activity, $this->target)) && - Event::handle('StartHandleSalmon', array($this->activity))) { - switch ($this->activity->verb) - { - case ActivityVerb::POST: - $this->handlePost(); - break; - case ActivityVerb::SHARE: - $this->handleShare(); - break; - case ActivityVerb::FAVORITE: - $this->handleFavorite(); - break; - case ActivityVerb::UNFAVORITE: - $this->handleUnfavorite(); - break; - case ActivityVerb::FOLLOW: - case ActivityVerb::FRIEND: - $this->handleFollow(); - break; - case ActivityVerb::UNFOLLOW: - $this->handleUnfollow(); - break; - case ActivityVerb::JOIN: - $this->handleJoin(); - break; - case ActivityVerb::LEAVE: - $this->handleLeave(); - break; - case ActivityVerb::TAG: - $this->handleTag(); - break; - case ActivityVerb::UNTAG: - $this->handleUntag(); - break; - case ActivityVerb::UPDATE_PROFILE: - $this->handleUpdateProfile(); - break; - default: - // TRANS: Client exception. - throw new ClientException(_m('Unrecognized activity type.')); - } - Event::handle('EndHandleSalmon', array($this->activity)); - Event::handle('EndHandleSalmonTarget', array($this->activity, $this->target)); - } - } - - function handlePost() - { - // TRANS: Client exception. - throw new ClientException(_m('This target does not understand posts.')); - } - - function handleFollow() - { - // TRANS: Client exception. - throw new ClientException(_m('This target does not understand follows.')); - } - - function handleUnfollow() - { - // TRANS: Client exception. - throw new ClientException(_m('This target does not understand unfollows.')); - } - - function handleFavorite() - { - // TRANS: Client exception. - throw new ClientException(_m('This target does not understand favorites.')); - } - - function handleUnfavorite() - { - // TRANS: Client exception. - throw new ClientException(_m('This target does not understand unfavorites.')); - } - - function handleShare() - { - // TRANS: Client exception. - throw new ClientException(_m('This target does not understand share events.')); - } - - function handleJoin() - { - // TRANS: Client exception. - throw new ClientException(_m('This target does not understand joins.')); - } - - function handleLeave() - { - // TRANS: Client exception. - throw new ClientException(_m('This target does not understand leave events.')); - } - - function handleTag() - { - // TRANS: Client exception. - throw new ClientException(_m('This target does not understand list events.')); - } - - function handleUntag() - { - // TRANS: Client exception. - throw new ClientException(_m('This target does not understand unlist events.')); - } - - /** - * Remote user sent us an update to their profile. - * If we already know them, accept the updates. - */ - function handleUpdateProfile() - { - $oprofile = Ostatus_profile::getActorProfile($this->activity); - if ($oprofile) { - common_log(LOG_INFO, "Got a profile-update ping from $oprofile->uri"); - $oprofile->updateFromActivityObject($this->activity->actor); - } else { - common_log(LOG_INFO, "Ignoring profile-update ping from unknown " . $this->activity->actor->id); - } - } - - /** - * @return Ostatus_profile - */ - function ensureProfile() - { - $actor = $this->activity->actor; - if (empty($actor->id)) { - common_log(LOG_ERR, "broken actor: " . var_export($actor, true)); - common_log(LOG_ERR, "activity with no actor: " . var_export($this->activity, true)); - // TRANS: Exception. - throw new Exception(_m('Received a salmon slap from unidentified actor.')); - } - - return Ostatus_profile::ensureActivityObjectProfile($actor); - } - - function saveNotice() - { - $oprofile = $this->ensureProfile(); - return $oprofile->processPost($this->activity, 'salmon'); - } -} diff --git a/plugins/OStatus/actions/usersalmon.php b/plugins/OStatus/actions/usersalmon.php index 40577a7d6e..550c034e49 100644 --- a/plugins/OStatus/actions/usersalmon.php +++ b/plugins/OStatus/actions/usersalmon.php @@ -134,7 +134,11 @@ class UsersalmonAction extends SalmonAction $oprofile = $this->ensureProfile(); if ($oprofile instanceof Ostatus_profile) { common_log(LOG_INFO, sprintf('Canceling subscription from remote %s to local %s', $oprofile->getUri(), $this->user->getNickname())); - Subscription::cancel($oprofile->localProfile(), $this->user->getProfile()); + try { + Subscription::cancel($oprofile->localProfile(), $this->user->getProfile()); + } catch (AlreadyFulfilledException $e) { + common_debug('Subscription did not exist, so there was nothing to cancel'); + } } else { common_log(LOG_ERR, "Can't cancel subscription from remote, didn't find the profile"); } diff --git a/plugins/OStatus/lib/salmonaction.php b/plugins/OStatus/lib/salmonaction.php new file mode 100644 index 0000000000..af6aaaa195 --- /dev/null +++ b/plugins/OStatus/lib/salmonaction.php @@ -0,0 +1,227 @@ +. + */ + +/** + * @package OStatusPlugin + * @author James Walker + */ + +if (!defined('GNUSOCIAL')) { exit(1); } + +class SalmonAction extends Action +{ + var $xml = null; + var $activity = null; + var $target = null; + + protected function prepare(array $args=array()) + { + StatusNet::setApi(true); // Send smaller error pages + + parent::prepare($args); + + if ($_SERVER['REQUEST_METHOD'] != 'POST') { + // TRANS: Client error. POST is a HTTP command. It should not be translated. + $this->clientError(_m('This method requires a POST.')); + } + + if (empty($_SERVER['CONTENT_TYPE']) || $_SERVER['CONTENT_TYPE'] != 'application/magic-envelope+xml') { + // TRANS: Client error. Do not translate "application/magic-envelope+xml". + $this->clientError(_m('Salmon requires "application/magic-envelope+xml".')); + } + + $xml = file_get_contents('php://input'); + + // Check the signature + $salmon = new Salmon; + if (!$salmon->verifyMagicEnv($xml)) { + common_log(LOG_DEBUG, "Salmon signature verification failed."); + // TRANS: Client error. + $this->clientError(_m('Salmon signature verification failed.')); + } else { + $magic_env = new MagicEnvelope(); + $env = $magic_env->parse($xml); + $xml = $magic_env->unfold($env); + } + + $dom = DOMDocument::loadXML($xml); + if ($dom->documentElement->namespaceURI != Activity::ATOM || + $dom->documentElement->localName != 'entry') { + common_log(LOG_DEBUG, "Got invalid Salmon post: $xml"); + // TRANS: Client error. + $this->clientError(_m('Salmon post must be an Atom entry.')); + } + + $this->activity = new Activity($dom->documentElement); + return true; + } + + /** + * Check the posted activity type and break out to appropriate processing. + */ + + protected function handle() + { + parent::handle(); + + common_log(LOG_DEBUG, "Got a " . $this->activity->verb); + if (Event::handle('StartHandleSalmonTarget', array($this->activity, $this->target)) && + Event::handle('StartHandleSalmon', array($this->activity))) { + switch ($this->activity->verb) + { + case ActivityVerb::POST: + $this->handlePost(); + break; + case ActivityVerb::SHARE: + $this->handleShare(); + break; + case ActivityVerb::FAVORITE: + $this->handleFavorite(); + break; + case ActivityVerb::UNFAVORITE: + $this->handleUnfavorite(); + break; + case ActivityVerb::FOLLOW: + case ActivityVerb::FRIEND: + $this->handleFollow(); + break; + case ActivityVerb::UNFOLLOW: + $this->handleUnfollow(); + break; + case ActivityVerb::JOIN: + $this->handleJoin(); + break; + case ActivityVerb::LEAVE: + $this->handleLeave(); + break; + case ActivityVerb::TAG: + $this->handleTag(); + break; + case ActivityVerb::UNTAG: + $this->handleUntag(); + break; + case ActivityVerb::UPDATE_PROFILE: + $this->handleUpdateProfile(); + break; + default: + // TRANS: Client exception. + throw new ClientException(_m('Unrecognized activity type.')); + } + Event::handle('EndHandleSalmon', array($this->activity)); + Event::handle('EndHandleSalmonTarget', array($this->activity, $this->target)); + } + } + + function handlePost() + { + // TRANS: Client exception. + throw new ClientException(_m('This target does not understand posts.')); + } + + function handleFollow() + { + // TRANS: Client exception. + throw new ClientException(_m('This target does not understand follows.')); + } + + function handleUnfollow() + { + // TRANS: Client exception. + throw new ClientException(_m('This target does not understand unfollows.')); + } + + function handleFavorite() + { + // TRANS: Client exception. + throw new ClientException(_m('This target does not understand favorites.')); + } + + function handleUnfavorite() + { + // TRANS: Client exception. + throw new ClientException(_m('This target does not understand unfavorites.')); + } + + function handleShare() + { + // TRANS: Client exception. + throw new ClientException(_m('This target does not understand share events.')); + } + + function handleJoin() + { + // TRANS: Client exception. + throw new ClientException(_m('This target does not understand joins.')); + } + + function handleLeave() + { + // TRANS: Client exception. + throw new ClientException(_m('This target does not understand leave events.')); + } + + function handleTag() + { + // TRANS: Client exception. + throw new ClientException(_m('This target does not understand list events.')); + } + + function handleUntag() + { + // TRANS: Client exception. + throw new ClientException(_m('This target does not understand unlist events.')); + } + + /** + * Remote user sent us an update to their profile. + * If we already know them, accept the updates. + */ + function handleUpdateProfile() + { + $oprofile = Ostatus_profile::getActorProfile($this->activity); + if ($oprofile instanceof Ostatus_profile) { + common_log(LOG_INFO, "Got a profile-update ping from $oprofile->uri"); + $oprofile->updateFromActivityObject($this->activity->actor); + } else { + common_log(LOG_INFO, "Ignoring profile-update ping from unknown " . $this->activity->actor->id); + } + } + + /** + * @return Ostatus_profile + */ + function ensureProfile() + { + $actor = $this->activity->actor; + if (empty($actor->id)) { + common_log(LOG_ERR, "broken actor: " . var_export($actor, true)); + common_log(LOG_ERR, "activity with no actor: " . var_export($this->activity, true)); + // TRANS: Exception. + throw new Exception(_m('Received a salmon slap from unidentified actor.')); + } + + return Ostatus_profile::ensureActivityObjectProfile($actor); + } + + function saveNotice() + { + $oprofile = $this->ensureProfile(); + return $oprofile->processPost($this->activity, 'salmon'); + } +}