summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--classes/Profile.php54
-rw-r--r--classes/Session.php12
-rw-r--r--classes/Subscription.php151
3 files changed, 179 insertions, 38 deletions
diff --git a/classes/Profile.php b/classes/Profile.php
index 8dbdcbd97..239c368ca 100644
--- a/classes/Profile.php
+++ b/classes/Profile.php
@@ -380,54 +380,32 @@ class Profile extends Memcached_DataObject
function getSubscriptions($offset=0, $limit=null)
{
- $qry =
- 'SELECT profile.* ' .
- 'FROM profile JOIN subscription ' .
- 'ON profile.id = subscription.subscribed ' .
- 'WHERE subscription.subscriber = %d ' .
- 'AND subscription.subscribed != subscription.subscriber ' .
- 'ORDER BY subscription.created DESC ';
-
- if ($offset>0 && !is_null($limit)){
- if (common_config('db','type') == 'pgsql') {
- $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
- } else {
- $qry .= ' LIMIT ' . $offset . ', ' . $limit;
- }
- }
+ $subs = Subscription::bySubscriber($this->id,
+ $offset,
+ $limit);
- $profile = new Profile();
+ $profiles = array();
- $profile->query(sprintf($qry, $this->id));
+ while ($subs->fetch()) {
+ $profiles[] = Profile::staticGet($subs->subscribed);
+ }
- return $profile;
+ return new ArrayWrapper($profiles);
}
function getSubscribers($offset=0, $limit=null)
{
- $qry =
- 'SELECT profile.* ' .
- 'FROM profile JOIN subscription ' .
- 'ON profile.id = subscription.subscriber ' .
- 'WHERE subscription.subscribed = %d ' .
- 'AND subscription.subscribed != subscription.subscriber ' .
- 'ORDER BY subscription.created DESC ';
-
- if ($offset>0 && !is_null($limit)){
- if ($offset) {
- if (common_config('db','type') == 'pgsql') {
- $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
- } else {
- $qry .= ' LIMIT ' . $offset . ', ' . $limit;
- }
- }
- }
+ $subs = Subscription::bySubscribed($this->id,
+ $offset,
+ $limit);
- $profile = new Profile();
+ $profiles = array();
- $cnt = $profile->query(sprintf($qry, $this->id));
+ while ($subs->fetch()) {
+ $profiles[] = Profile::staticGet($subs->subscriber);
+ }
- return $profile;
+ return new ArrayWrapper($profiles);
}
function getConnectedApps($offset = 0, $limit = null)
diff --git a/classes/Session.php b/classes/Session.php
index 2422f8b68..e1c83ad4d 100644
--- a/classes/Session.php
+++ b/classes/Session.php
@@ -178,6 +178,18 @@ class Session extends Memcached_DataObject
$result = session_set_save_handler('Session::open', 'Session::close', 'Session::read',
'Session::write', 'Session::destroy', 'Session::gc');
self::logdeb("save handlers result = $result");
+
+ // PHP 5.3 with APC ends up destroying a bunch of object stuff before the session
+ // save handlers get called on request teardown.
+ // Registering an explicit shutdown function should take care of this before
+ // everything breaks on us.
+ register_shutdown_function('Session::cleanup');
+
return $result;
}
+
+ static function cleanup()
+ {
+ session_write_close();
+ }
}
diff --git a/classes/Subscription.php b/classes/Subscription.php
index d41349412..1d4f37929 100644
--- a/classes/Subscription.php
+++ b/classes/Subscription.php
@@ -26,6 +26,8 @@ require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
class Subscription extends Memcached_DataObject
{
+ const CACHE_WINDOW = 201;
+
###START_AUTOCODE
/* the code below is auto generated do not remove the above tag */
@@ -91,6 +93,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();
@@ -220,6 +225,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();
@@ -273,4 +281,147 @@ class Subscription extends Memcached_DataObject
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;
+ }
}