X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=classes%2FSubscription.php;h=e83621eb86ba3bac099f61504c62bc2905276a9c;hb=513c54fa89085fde783a73c298d61576f834b131;hp=0225ed4df97b9282bc8b5efd6d2175f8e216e8f2;hpb=125ff142e871d4cde780335d6a4f16d5f59bca83;p=quix0rs-gnu-social.git diff --git a/classes/Subscription.php b/classes/Subscription.php index 0225ed4df9..e83621eb86 100644 --- a/classes/Subscription.php +++ b/classes/Subscription.php @@ -26,6 +26,9 @@ require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; class Subscription extends Memcached_DataObject { + const CACHE_WINDOW = 201; + const FORCE = true; + ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ @@ -56,11 +59,12 @@ class Subscription extends Memcached_DataObject * * @param Profile $subscriber party to receive new notices * @param Profile $other party sending notices; publisher + * @param bool $force pass Subscription::FORCE to override local subscription approval * - * @return Subscription new subscription + * @return mixed Subscription or Subscription_queue: new subscription info */ - static function start($subscriber, $other) + static function start($subscriber, $other, $force=false) { // @fixme should we enforce this as profiles in callers instead? if ($subscriber instanceof User) { @@ -86,32 +90,39 @@ class Subscription extends Memcached_DataObject } if (Event::handle('StartSubscribe', array($subscriber, $other))) { - $sub = self::saveNew($subscriber->id, $other->id); - $sub->notify(); - - self::blow('user:notices_with_friends:%d', $subscriber->id); - - $subscriber->blowSubscriptionCount(); - $other->blowSubscriberCount(); - $otherUser = User::staticGet('id', $other->id); - - if (!empty($otherUser) && - $otherUser->autosubscribe && - !self::exists($other, $subscriber) && - !$subscriber->hasBlocked($other)) { - - try { - self::start($other, $subscriber); - } catch (Exception $e) { - common_log(LOG_ERR, "Exception during autosubscribe of {$other->nickname} to profile {$subscriber->id}: {$e->getMessage()}"); + if ($otherUser && $otherUser->subscribe_policy == User::SUBSCRIBE_POLICY_MODERATE && !$force) { + $sub = Subscription_queue::saveNew($subscriber, $other); + $sub->notify(); + } else { + $sub = self::saveNew($subscriber->id, $other->id); + $sub->notify(); + + self::blow('user:notices_with_friends:%d', $subscriber->id); + + self::blow('subscription:by-subscriber:'.$subscriber->id); + self::blow('subscription:by-subscribed:'.$other->id); + + $subscriber->blowSubscriptionCount(); + $other->blowSubscriberCount(); + + if (!empty($otherUser) && + $otherUser->autosubscribe && + !self::exists($other, $subscriber) && + !$subscriber->hasBlocked($other)) { + + try { + self::start($other, $subscriber); + } catch (Exception $e) { + common_log(LOG_ERR, "Exception during autosubscribe of {$other->nickname} to profile {$subscriber->id}: {$e->getMessage()}"); + } } } Event::handle('EndSubscribe', array($subscriber, $other)); } - return true; + return $sub; } /** @@ -141,9 +152,9 @@ class Subscription extends Memcached_DataObject function notify() { - # XXX: add other notifications (Jabber, SMS) here - # XXX: queue this and handle it offline - # XXX: Whatever happens, do it in Twitter-like API, too + // XXX: add other notifications (Jabber, SMS) here + // XXX: queue this and handle it offline + // XXX: Whatever happens, do it in Twitter-like API, too $this->notifyEmail(); } @@ -187,29 +198,6 @@ class Subscription extends Memcached_DataObject assert(!empty($sub)); - // @todo: move this block to EndSubscribe handler for - // OMB plugin when it exists. - - if (!empty($sub->token)) { - - $token = new Token(); - - $token->tok = $sub->token; - - if ($token->find(true)) { - - $result = $token->delete(); - - if (!$result) { - common_log_db_error($token, 'DELETE', __FILE__); - // TRANS: Exception thrown when the OMB token for a subscription could not deleted on the server. - throw new Exception(_('Could not delete subscription OMB token.')); - } - } else { - common_log(LOG_ERR, "Couldn't find credentials with token {$token->tok}"); - } - } - $result = $sub->delete(); if (!$result) { @@ -220,6 +208,9 @@ class Subscription extends Memcached_DataObject self::blow('user:notices_with_friends:%d', $subscriber->id); + self::blow('subscription:by-subscriber:'.$subscriber->id); + self::blow('subscription:by-subscribed:'.$other->id); + $subscriber->blowSubscriptionCount(); $other->blowSubscriberCount(); @@ -235,4 +226,182 @@ class Subscription extends Memcached_DataObject 'subscribed' => $other->id)); return (empty($sub)) ? false : true; } + + function asActivity() + { + $subscriber = Profile::staticGet('id', $this->subscriber); + $subscribed = Profile::staticGet('id', $this->subscribed); + + $act = new Activity(); + + $act->verb = ActivityVerb::FOLLOW; + + // XXX: rationalize this with the URL + + $act->id = TagURI::mint('follow:%d:%d:%s', + $subscriber->id, + $subscribed->id, + common_date_iso8601($this->created)); + + $act->time = strtotime($this->created); + // TRANS: Activity title when subscribing to another person. + $act->title = _m('TITLE','Follow'); + // TRANS: Notification given when one person starts following another. + // TRANS: %1$s is the subscriber, %2$s is the subscribed. + $act->content = sprintf(_('%1$s is now following %2$s.'), + $subscriber->getBestName(), + $subscribed->getBestName()); + + $act->actor = ActivityObject::fromProfile($subscriber); + $act->objects[] = ActivityObject::fromProfile($subscribed); + + $url = common_local_url('AtomPubShowSubscription', + array('subscriber' => $subscriber->id, + 'subscribed' => $subscribed->id)); + + $act->selfLink = $url; + $act->editLink = $url; + + return $act; + } + + /** + * Stream of subscriptions with the same subscriber + * + * Useful for showing pages that list subscriptions in reverse + * chronological order. Has offset & limit to make paging + * easy. + * + * @param integer $subscriberId Profile ID of the subscriber + * @param integer $offset Offset from latest + * @param integer $limit Maximum number to fetch + * + * @return Subscription stream of subscriptions; use fetch() to iterate + */ + static function bySubscriber($subscriberId, + $offset = 0, + $limit = PROFILES_PER_PAGE) + { + if ($offset + $limit > self::CACHE_WINDOW) { + return new ArrayWrapper(self::realBySubscriber($subscriberId, + $offset, + $limit)); + } else { + $key = 'subscription:by-subscriber:'.$subscriberId; + $window = self::cacheGet($key); + if ($window === false) { + $window = self::realBySubscriber($subscriberId, + 0, + self::CACHE_WINDOW); + self::cacheSet($key, $window); + } + return new ArrayWrapper(array_slice($window, + $offset, + $limit)); + } + } + + private static function realBySubscriber($subscriberId, + $offset, + $limit) + { + $sub = new Subscription(); + + $sub->subscriber = $subscriberId; + + $sub->whereAdd('subscribed != ' . $subscriberId); + + $sub->orderBy('created DESC'); + $sub->limit($offset, $limit); + + $sub->find(); + + $subs = array(); + + while ($sub->fetch()) { + $subs[] = clone($sub); + } + + return $subs; + } + + /** + * Stream of subscriptions with the same subscribed profile + * + * Useful for showing pages that list subscribers in reverse + * chronological order. Has offset & limit to make paging + * easy. + * + * @param integer $subscribedId Profile ID of the subscribed + * @param integer $offset Offset from latest + * @param integer $limit Maximum number to fetch + * + * @return Subscription stream of subscriptions; use fetch() to iterate + */ + static function bySubscribed($subscribedId, + $offset = 0, + $limit = PROFILES_PER_PAGE) + { + if ($offset + $limit > self::CACHE_WINDOW) { + return new ArrayWrapper(self::realBySubscribed($subscribedId, + $offset, + $limit)); + } else { + $key = 'subscription:by-subscribed:'.$subscribedId; + $window = self::cacheGet($key); + if ($window === false) { + $window = self::realBySubscribed($subscribedId, + 0, + self::CACHE_WINDOW); + self::cacheSet($key, $window); + } + return new ArrayWrapper(array_slice($window, + $offset, + $limit)); + } + } + + private static function realBySubscribed($subscribedId, + $offset, + $limit) + { + $sub = new Subscription(); + + $sub->subscribed = $subscribedId; + + $sub->whereAdd('subscriber != ' . $subscribedId); + + $sub->orderBy('created DESC'); + $sub->limit($offset, $limit); + + $sub->find(); + + $subs = array(); + + while ($sub->fetch()) { + $subs[] = clone($sub); + } + + return $subs; + } + + /** + * Flush cached subscriptions when subscription is updated + * + * Because we cache subscriptions, it's useful to flush them + * here. + * + * @param mixed $orig Original version of object + * + * @return boolean success flag. + */ + function update($orig=null) + { + $result = parent::update($orig); + + self::blow('subscription:by-subscriber:'.$this->subscriber); + self::blow('subscription:by-subscribed:'.$this->subscribed); + + return $result; + } }