| 
									
										
										
										
											2008-05-07 13:15:42 -04:00
										 |  |  | <?php | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  | // This file is part of GNU social - https://www.gnu.org/software/social
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // GNU social 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.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // GNU social 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 GNU social.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2020-07-31 16:12:48 +03:00
										 |  |  |  * @copyright 2008, 2009 StatusNet, Inc. | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |  * @license   https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later | 
					
						
							| 
									
										
										
										
											2008-05-14 15:26:48 -04:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  | defined('GNUSOCIAL') || die(); | 
					
						
							| 
									
										
										
										
											2008-05-14 15:26:48 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-07 13:15:42 -04:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Table Definition for subscription | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-08-22 17:52:02 -04:00
										 |  |  | class Subscription extends Managed_DataObject | 
					
						
							| 
									
										
										
										
											2008-05-07 13:15:42 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-12-11 11:00:04 -05:00
										 |  |  |     const CACHE_WINDOW = 201; | 
					
						
							| 
									
										
										
										
											2011-03-28 15:13:59 -07:00
										 |  |  |     const FORCE = true; | 
					
						
							| 
									
										
										
										
											2010-12-11 11:00:04 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-07 13:15:42 -04:00
										 |  |  |     public $__table = 'subscription';                    // table name
 | 
					
						
							|  |  |  |     public $subscriber;                      // int(4)  primary_key not_null
 | 
					
						
							|  |  |  |     public $subscribed;                      // int(4)  primary_key not_null
 | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |     public $jabber;                          // bool    default_true
 | 
					
						
							|  |  |  |     public $sms;                             // bool    default_true
 | 
					
						
							| 
									
										
										
										
											2015-02-12 18:18:55 +01:00
										 |  |  |     public $token;                           // varchar(191)   not 255 because utf8mb4 takes more space
 | 
					
						
							|  |  |  |     public $secret;                          // varchar(191)   not 255 because utf8mb4 takes more space
 | 
					
						
							|  |  |  |     public $uri;                             // varchar(191)   not 255 because utf8mb4 takes more space
 | 
					
						
							| 
									
										
										
										
											2020-06-29 01:41:46 +03:00
										 |  |  |     public $created;                         // datetime()
 | 
					
						
							|  |  |  |     public $modified;                        // timestamp()    not_null default_CURRENT_TIMESTAMP
 | 
					
						
							| 
									
										
										
										
											2008-05-07 13:15:42 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-22 17:52:02 -04:00
										 |  |  |     public static function schemaDef() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return array( | 
					
						
							|  |  |  |             'fields' => array( | 
					
						
							|  |  |  |                 'subscriber' => array('type' => 'int', 'not null' => true, 'description' => 'profile listening'), | 
					
						
							|  |  |  |                 'subscribed' => array('type' => 'int', 'not null' => true, 'description' => 'profile being listened to'), | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |                 'jabber' => array('type' => 'bool', 'default' => true, 'description' => 'deliver jabber messages'), | 
					
						
							|  |  |  |                 'sms' => array('type' => 'bool', 'default' => true, 'description' => 'deliver sms messages'), | 
					
						
							| 
									
										
										
										
											2015-02-12 18:18:55 +01:00
										 |  |  |                 'token' => array('type' => 'varchar', 'length' => 191, 'description' => 'authorization token'), | 
					
						
							|  |  |  |                 'secret' => array('type' => 'varchar', 'length' => 191, 'description' => 'token secret'), | 
					
						
							|  |  |  |                 'uri' => array('type' => 'varchar', 'length' => 191, 'description' => 'universally unique identifier'), | 
					
						
							| 
									
										
										
										
											2020-06-29 01:41:46 +03:00
										 |  |  |                 'created' => array('type' => 'datetime', 'description' => 'date this record was created'), | 
					
						
							|  |  |  |                 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'), | 
					
						
							| 
									
										
										
										
											2011-08-22 17:52:02 -04:00
										 |  |  |             ), | 
					
						
							|  |  |  |             'primary key' => array('subscriber', 'subscribed'), | 
					
						
							| 
									
										
										
										
											2011-08-22 18:13:02 -04:00
										 |  |  |             'unique keys' => array( | 
					
						
							|  |  |  |                 'subscription_uri_key' => array('uri'), | 
					
						
							|  |  |  |             ), | 
					
						
							| 
									
										
										
										
											2011-08-22 17:52:02 -04:00
										 |  |  |             'indexes' => array( | 
					
						
							| 
									
										
										
										
											2020-07-31 16:12:48 +03:00
										 |  |  |                 'subscription_subscriber_created_idx' => array('subscriber', 'created'), | 
					
						
							|  |  |  |                 'subscription_subscribed_created_idx' => array('subscribed', 'created'), | 
					
						
							| 
									
										
										
										
											2011-08-22 17:52:02 -04:00
										 |  |  |                 'subscription_token_idx' => array('token'), | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2013-06-08 14:56:57 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-08-22 17:52:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Make a new subscription | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Profile $subscriber party to receive new notices | 
					
						
							|  |  |  |      * @param Profile $other      party sending notices; publisher | 
					
						
							| 
									
										
										
										
											2011-03-28 15:13:59 -07:00
										 |  |  |      * @param bool    $force      pass Subscription::FORCE to override local subscription approval | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2011-03-28 15:13:59 -07:00
										 |  |  |      * @return mixed Subscription or Subscription_queue: new subscription info | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |      */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |     public static function start(Profile $subscriber, Profile $other, $force = false) | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |     { | 
					
						
							|  |  |  |         if (!$subscriber->hasRight(Right::SUBSCRIBE)) { | 
					
						
							| 
									
										
										
										
											2010-07-29 13:36:08 +02:00
										 |  |  |             // TRANS: Exception thrown when trying to subscribe while being banned from subscribing.
 | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |             throw new Exception(_('You have been banned from subscribing.')); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (self::exists($subscriber, $other)) { | 
					
						
							| 
									
										
										
										
											2010-07-29 13:36:08 +02:00
										 |  |  |             // TRANS: Exception thrown when trying to subscribe while already subscribed.
 | 
					
						
							| 
									
										
										
										
											2014-05-05 23:57:41 +02:00
										 |  |  |             throw new AlreadyFulfilledException(_('Already subscribed!')); | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($other->hasBlocked($subscriber)) { | 
					
						
							| 
									
										
										
										
											2010-07-29 13:36:08 +02:00
										 |  |  |             // TRANS: Exception thrown when trying to subscribe to a user who has blocked the subscribing user.
 | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |             throw new Exception(_('User has blocked you.')); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (Event::handle('StartSubscribe', array($subscriber, $other))) { | 
					
						
							| 
									
										
										
										
											2016-01-03 19:33:26 +01:00
										 |  |  |             // unless subscription is forced, the user policy for subscription approvals is tested
 | 
					
						
							|  |  |  |             if (!$force && $other->requiresSubscriptionApproval($subscriber)) { | 
					
						
							| 
									
										
										
										
											2015-03-04 11:49:54 +01:00
										 |  |  |                 try { | 
					
						
							|  |  |  |                     $sub = Subscription_queue::saveNew($subscriber, $other); | 
					
						
							|  |  |  |                     $sub->notify(); | 
					
						
							|  |  |  |                 } catch (AlreadyFulfilledException $e) { | 
					
						
							|  |  |  |                     $sub = Subscription_queue::getSubQueue($subscriber, $other); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2011-03-28 15:13:59 -07:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2016-01-03 19:33:26 +01:00
										 |  |  |                 $otherUser = User::getKV('id', $other->id); | 
					
						
							| 
									
										
										
										
											2015-09-06 02:04:12 +02:00
										 |  |  |                 $sub = self::saveNew($subscriber, $other); | 
					
						
							| 
									
										
										
										
											2011-03-28 15:13:59 -07:00
										 |  |  |                 $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(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-05 23:57:41 +02:00
										 |  |  |                 if ($otherUser instanceof User && | 
					
						
							| 
									
										
										
										
											2011-03-28 15:13:59 -07:00
										 |  |  |                     $otherUser->autosubscribe && | 
					
						
							|  |  |  |                     !self::exists($other, $subscriber) && | 
					
						
							|  |  |  |                     !$subscriber->hasBlocked($other)) { | 
					
						
							|  |  |  |                     try { | 
					
						
							|  |  |  |                         self::start($other, $subscriber); | 
					
						
							| 
									
										
										
										
											2014-05-05 23:57:41 +02:00
										 |  |  |                     } catch (AlreadyFulfilledException $e) { | 
					
						
							|  |  |  |                         // This shouldn't happen due to !self::exists above
 | 
					
						
							|  |  |  |                         common_debug('Tried to autosubscribe a user to its new subscriber.'); | 
					
						
							| 
									
										
										
										
											2011-03-28 15:13:59 -07:00
										 |  |  |                     } catch (Exception $e) { | 
					
						
							|  |  |  |                         common_log(LOG_ERR, "Exception during autosubscribe of {$other->nickname} to profile {$subscriber->id}: {$e->getMessage()}"); | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-04 11:49:54 +01:00
										 |  |  |             if ($sub instanceof Subscription) { // i.e. not Subscription_queue
 | 
					
						
							| 
									
										
										
										
											2014-05-06 00:22:02 +02:00
										 |  |  |                 Event::handle('EndSubscribe', array($subscriber, $other)); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-28 17:06:02 -07:00
										 |  |  |         return $sub; | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |     public static function ensureStart(Profile $subscriber, Profile $other, $force = false) | 
					
						
							| 
									
										
										
										
											2015-03-04 11:38:04 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             $sub = self::start($subscriber, $other, $force); | 
					
						
							|  |  |  |         } catch (AlreadyFulfilledException $e) { | 
					
						
							|  |  |  |             return self::getSubscription($subscriber, $other); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return $sub; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-18 14:26:32 -07:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Low-level subscription save. | 
					
						
							|  |  |  |      * Outside callers should use Subscription::start() | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-09-06 02:04:12 +02:00
										 |  |  |     protected static function saveNew(Profile $subscriber, Profile $other) | 
					
						
							| 
									
										
										
										
											2010-03-18 14:26:32 -07:00
										 |  |  |     { | 
					
						
							|  |  |  |         $sub = new Subscription(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-06 02:04:12 +02:00
										 |  |  |         $sub->subscriber = $subscriber->getID(); | 
					
						
							|  |  |  |         $sub->subscribed = $other->getID(); | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |         $sub->jabber     = true; | 
					
						
							|  |  |  |         $sub->sms        = true; | 
					
						
							| 
									
										
										
										
											2010-03-18 14:26:32 -07:00
										 |  |  |         $sub->created    = common_sql_now(); | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |         $sub->uri        = self::newUri( | 
					
						
							|  |  |  |             $subscriber, | 
					
						
							|  |  |  |             $other, | 
					
						
							|  |  |  |             $sub->created | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2010-03-18 14:26:32 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $result = $sub->insert(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-05 23:57:41 +02:00
										 |  |  |         if ($result===false) { | 
					
						
							| 
									
										
										
										
											2010-03-18 14:26:32 -07:00
										 |  |  |             common_log_db_error($sub, 'INSERT', __FILE__); | 
					
						
							| 
									
										
										
										
											2010-07-29 13:36:08 +02:00
										 |  |  |             // TRANS: Exception thrown when a subscription could not be stored on the server.
 | 
					
						
							| 
									
										
										
										
											2010-03-18 14:26:32 -07:00
										 |  |  |             throw new Exception(_('Could not save subscription.')); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $sub; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |     public function notify() | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-03-22 11:54:23 -04:00
										 |  |  |         // XXX: add other notifications (Jabber, SMS) here
 | 
					
						
							|  |  |  |         // XXX: queue this and handle it offline
 | 
					
						
							|  |  |  |         // XXX: Whatever happens, do it in Twitter-like API, too
 | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $this->notifyEmail(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |     public function notifyEmail() | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2013-08-18 13:04:58 +02:00
										 |  |  |         $subscribedUser = User::getKV('id', $this->subscribed); | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-05 23:57:41 +02:00
										 |  |  |         if ($subscribedUser instanceof User) { | 
					
						
							| 
									
										
										
										
											2013-08-18 13:04:58 +02:00
										 |  |  |             $subscriber = Profile::getKV('id', $this->subscriber); | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             mail_subscribe_notify_profile($subscribedUser, $subscriber); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Cancel a subscription | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |     public static function cancel(Profile $subscriber, Profile $other) | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |     { | 
					
						
							|  |  |  |         if (!self::exists($subscriber, $other)) { | 
					
						
							| 
									
										
										
										
											2010-07-29 13:36:08 +02:00
										 |  |  |             // TRANS: Exception thrown when trying to unsibscribe without a subscription.
 | 
					
						
							| 
									
										
										
										
											2014-05-05 23:57:41 +02:00
										 |  |  |             throw new AlreadyFulfilledException(_('Not subscribed!')); | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Don't allow deleting self subs
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($subscriber->id == $other->id) { | 
					
						
							| 
									
										
										
										
											2010-07-29 13:36:08 +02:00
										 |  |  |             // TRANS: Exception thrown when trying to unsubscribe a user from themselves.
 | 
					
						
							|  |  |  |             throw new Exception(_('Could not delete self-subscription.')); | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (Event::handle('StartUnsubscribe', array($subscriber, $other))) { | 
					
						
							|  |  |  |             $sub = Subscription::pkeyGet(array('subscriber' => $subscriber->id, | 
					
						
							|  |  |  |                                                'subscribed' => $other->id)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // note we checked for existence above
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             assert(!empty($sub)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $result = $sub->delete(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!$result) { | 
					
						
							|  |  |  |                 common_log_db_error($sub, 'DELETE', __FILE__); | 
					
						
							| 
									
										
										
										
											2010-07-29 13:36:08 +02:00
										 |  |  |                 // TRANS: Exception thrown when a subscription could not be deleted on the server.
 | 
					
						
							|  |  |  |                 throw new Exception(_('Could not delete subscription.')); | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self::blow('user:notices_with_friends:%d', $subscriber->id); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-11 11:00:04 -05:00
										 |  |  |             self::blow('subscription:by-subscriber:'.$subscriber->id); | 
					
						
							|  |  |  |             self::blow('subscription:by-subscribed:'.$other->id); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-22 14:22:18 -04:00
										 |  |  |             $subscriber->blowSubscriptionCount(); | 
					
						
							|  |  |  |             $other->blowSubscriberCount(); | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             Event::handle('EndUnsubscribe', array($subscriber, $other)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |     public static function exists(Profile $subscriber, Profile $other) | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-02-17 17:15:47 +01:00
										 |  |  |         try { | 
					
						
							|  |  |  |             $sub = self::getSubscription($subscriber, $other); | 
					
						
							|  |  |  |         } catch (NoResultException $e) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |     public static function getSubscription(Profile $subscriber, Profile $other) | 
					
						
							| 
									
										
										
										
											2015-02-17 17:15:47 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         // This is essentially a pkeyGet but we have an object to return in NoResultException
 | 
					
						
							|  |  |  |         $sub = new Subscription(); | 
					
						
							|  |  |  |         $sub->subscriber = $subscriber->id; | 
					
						
							|  |  |  |         $sub->subscribed = $other->id; | 
					
						
							|  |  |  |         if (!$sub->find(true)) { | 
					
						
							|  |  |  |             throw new NoResultException($sub); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return $sub; | 
					
						
							| 
									
										
										
										
											2010-02-19 08:16:45 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-08-04 12:07:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-10 22:09:51 +02:00
										 |  |  |     public function getSubscriber() | 
					
						
							| 
									
										
										
										
											2010-08-04 12:07:49 -07:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-10-10 22:09:51 +02:00
										 |  |  |         return Profile::getByID($this->subscriber); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-08-04 12:07:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-10 22:09:51 +02:00
										 |  |  |     public function getSubscribed() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return Profile::getByID($this->subscribed); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-06-08 14:56:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |     public function asActivity() | 
					
						
							| 
									
										
										
										
											2015-10-10 22:09:51 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         $subscriber = $this->getSubscriber(); | 
					
						
							|  |  |  |         $subscribed = $this->getSubscribed(); | 
					
						
							| 
									
										
										
										
											2013-06-08 14:56:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-04 12:07:49 -07:00
										 |  |  |         $act = new Activity(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $act->verb = ActivityVerb::FOLLOW; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-09 13:11:02 -05:00
										 |  |  |         // XXX: rationalize this with the URL
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-10 22:09:51 +02:00
										 |  |  |         $act->id   = $this->getUri(); | 
					
						
							| 
									
										
										
										
											2010-08-04 12:07:49 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $act->time    = strtotime($this->created); | 
					
						
							| 
									
										
										
										
											2011-03-29 23:00:29 +02:00
										 |  |  |         // TRANS: Activity title when subscribing to another person.
 | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |         $act->title = _m('TITLE', 'Follow'); | 
					
						
							| 
									
										
										
										
											2010-09-28 23:42:18 +02:00
										 |  |  |         // TRANS: Notification given when one person starts following another.
 | 
					
						
							|  |  |  |         // TRANS: %1$s is the subscriber, %2$s is the subscribed.
 | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |         $act->content = sprintf( | 
					
						
							|  |  |  |             _('%1$s is now following %2$s.'), | 
					
						
							|  |  |  |             $subscriber->getBestName(), | 
					
						
							|  |  |  |             $subscribed->getBestName() | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2010-08-04 12:07:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-02 18:50:28 +02:00
										 |  |  |         $act->actor     = $subscriber->asActivityObject(); | 
					
						
							|  |  |  |         $act->objects[] = $subscribed->asActivityObject(); | 
					
						
							| 
									
										
										
										
											2010-08-04 12:07:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |         $url = common_local_url( | 
					
						
							|  |  |  |             'AtomPubShowSubscription', | 
					
						
							|  |  |  |             [ | 
					
						
							|  |  |  |                 'subscriber' => $subscriber->id, | 
					
						
							|  |  |  |                 'subscribed' => $subscribed->id, | 
					
						
							|  |  |  |             ] | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2010-12-09 13:11:02 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $act->selfLink = $url; | 
					
						
							|  |  |  |         $act->editLink = $url; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-04 12:07:49 -07:00
										 |  |  |         return $act; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-12-11 10:24:46 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * 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. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |      * @param integer $profile_id   ID of the subscriber profile | 
					
						
							| 
									
										
										
										
											2010-12-11 10:24:46 -05:00
										 |  |  |      * @param integer $offset       Offset from latest | 
					
						
							|  |  |  |      * @param integer $limit        Maximum number to fetch | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return Subscription stream of subscriptions; use fetch() to iterate | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |     public static function bySubscriber($profile_id, $offset = 0, $limit = PROFILES_PER_PAGE) | 
					
						
							| 
									
										
										
										
											2010-12-11 11:00:04 -05:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |         // "by subscriber" means it is the list of subscribed users we want
 | 
					
						
							|  |  |  |         $ids = self::getSubscribedIDs($profile_id, $offset, $limit); | 
					
						
							|  |  |  |         return Subscription::listFind('subscribed', $ids); | 
					
						
							| 
									
										
										
										
											2010-12-11 10:24:46 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |      * Stream of subscriptions with the same subscriber | 
					
						
							| 
									
										
										
										
											2010-12-11 10:24:46 -05:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |      * Useful for showing pages that list subscriptions in reverse | 
					
						
							| 
									
										
										
										
											2010-12-11 10:24:46 -05:00
										 |  |  |      * chronological order. Has offset & limit to make paging | 
					
						
							|  |  |  |      * easy. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |      * @param integer $profile_id   ID of the subscribed profile | 
					
						
							| 
									
										
										
										
											2010-12-11 10:24:46 -05:00
										 |  |  |      * @param integer $offset       Offset from latest | 
					
						
							|  |  |  |      * @param integer $limit        Maximum number to fetch | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return Subscription stream of subscriptions; use fetch() to iterate | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |     public static function bySubscribed($profile_id, $offset = 0, $limit = PROFILES_PER_PAGE) | 
					
						
							| 
									
										
										
										
											2010-12-11 11:00:04 -05:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |         // "by subscribed" means it is the list of subscribers we want
 | 
					
						
							|  |  |  |         $ids = self::getSubscriberIDs($profile_id, $offset, $limit); | 
					
						
							|  |  |  |         return Subscription::listFind('subscriber', $ids); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // The following are helper functions to the subscription lists,
 | 
					
						
							|  |  |  |     // notably the public ones get used in places such as Profile
 | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |     public static function getSubscribedIDs($profile_id, $offset, $limit) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |         return self::getSubscriptionIDs('subscribed', $profile_id, $offset, $limit); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |     public static function getSubscriberIDs($profile_id, $offset, $limit) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |         return self::getSubscriptionIDs('subscriber', $profile_id, $offset, $limit); | 
					
						
							| 
									
										
										
										
											2010-12-11 11:00:04 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |     private static function getSubscriptionIDs($get_type, $profile_id, $offset, $limit) | 
					
						
							| 
									
										
										
										
											2010-12-11 10:24:46 -05:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |         switch ($get_type) { | 
					
						
							|  |  |  |         case 'subscribed': | 
					
						
							|  |  |  |             $by_type  = 'subscriber'; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case 'subscriber': | 
					
						
							|  |  |  |             $by_type  = 'subscribed'; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             throw new Exception('Bad type argument to getSubscriptionIDs'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $cacheKey = 'subscription:by-'.$by_type.':'.$profile_id; | 
					
						
							| 
									
										
										
										
											2010-12-11 10:24:46 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |         $queryoffset = $offset; | 
					
						
							|  |  |  |         $querylimit = $limit; | 
					
						
							| 
									
										
										
										
											2010-12-11 10:24:46 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |         if ($offset + $limit <= self::CACHE_WINDOW) { | 
					
						
							|  |  |  |             // Oh, it seems it should be cached
 | 
					
						
							|  |  |  |             $ids = self::cacheGet($cacheKey); | 
					
						
							|  |  |  |             if (is_array($ids)) { | 
					
						
							|  |  |  |                 return array_slice($ids, $offset, $limit); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             // Being here indicates we didn't find anything cached
 | 
					
						
							|  |  |  |             // so we'll have to fill it up simultaneously
 | 
					
						
							|  |  |  |             $queryoffset = 0; | 
					
						
							|  |  |  |             $querylimit  = self::CACHE_WINDOW; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-12-11 10:24:46 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |         $sub = new Subscription(); | 
					
						
							|  |  |  |         $sub->$by_type = $profile_id; | 
					
						
							|  |  |  |         $sub->selectAdd($get_type); | 
					
						
							| 
									
										
										
										
											2019-09-11 13:27:36 +03:00
										 |  |  |         $sub->whereAdd($get_type . ' <> ' . $profile_id); | 
					
						
							| 
									
										
										
										
											2010-12-11 10:24:46 -05:00
										 |  |  |         $sub->orderBy('created DESC'); | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |         $sub->limit($queryoffset, $querylimit); | 
					
						
							| 
									
										
										
										
											2010-12-11 10:24:46 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |         if (!$sub->find()) { | 
					
						
							|  |  |  |             return array(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-12-11 10:24:46 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |         $ids = $sub->fetchAll($get_type); | 
					
						
							| 
									
										
										
										
											2010-12-11 11:00:04 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |         // If we're simultaneously filling up cache, remember to slice
 | 
					
						
							| 
									
										
										
										
											2014-05-30 23:33:38 +02:00
										 |  |  |         if ($queryoffset === 0 && $querylimit === self::CACHE_WINDOW) { | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |             self::cacheSet($cacheKey, $ids); | 
					
						
							|  |  |  |             return array_slice($ids, $offset, $limit); | 
					
						
							| 
									
										
										
										
											2010-12-11 11:00:04 -05:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-21 18:26:58 +02:00
										 |  |  |         return $ids; | 
					
						
							| 
									
										
										
										
											2010-12-11 11:00:04 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Flush cached subscriptions when subscription is updated | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Because we cache subscriptions, it's useful to flush them | 
					
						
							|  |  |  |      * here. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2013-10-28 19:36:05 +01:00
										 |  |  |      * @param mixed $dataObject Original version of object | 
					
						
							| 
									
										
										
										
											2010-12-11 11:00:04 -05:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @return boolean success flag. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2019-09-11 11:25:39 +03:00
										 |  |  |     public function update($dataObject = false) | 
					
						
							| 
									
										
										
										
											2010-12-11 11:00:04 -05:00
										 |  |  |     { | 
					
						
							|  |  |  |         self::blow('subscription:by-subscriber:'.$this->subscriber); | 
					
						
							|  |  |  |         self::blow('subscription:by-subscribed:'.$this->subscribed); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 19:36:05 +01:00
										 |  |  |         return parent::update($dataObject); | 
					
						
							| 
									
										
										
										
											2010-12-11 10:24:46 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-08-22 16:36:23 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-10 22:09:51 +02:00
										 |  |  |     public function getUri() | 
					
						
							| 
									
										
										
										
											2011-08-22 16:36:23 -04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-10-10 22:09:51 +02:00
										 |  |  |         return $this->uri ?: self::newUri($this->getSubscriber(), $this->getSubscribed(), $this->created); | 
					
						
							| 
									
										
										
										
											2011-08-22 16:36:23 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-05-07 13:15:42 -04:00
										 |  |  | } |