summaryrefslogtreecommitdiff
path: root/plugins/SocialObject/SocialObject.php
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/SocialObject/SocialObject.php')
-rw-r--r--plugins/SocialObject/SocialObject.php324
1 files changed, 324 insertions, 0 deletions
diff --git a/plugins/SocialObject/SocialObject.php b/plugins/SocialObject/SocialObject.php
new file mode 100644
index 000000000..2d740c836
--- /dev/null
+++ b/plugins/SocialObject/SocialObject.php
@@ -0,0 +1,324 @@
+<?php
+/**
+ * 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('STATUSNET')) {
+ exit(1);
+}
+
+# Abstract class for social-objects
+
+require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
+
+class SocialObject extends Memcached_DataObject
+{
+ var $slug=null; # used in cache key
+
+ # save a new object
+ static function saveNew($args)
+ {
+ # save everything, add a
+ # Notice entry too.
+ # call Notice::saveNew with options
+ # like replies, groups and tags.
+ # and, cache blowing action.
+ }
+
+ function delete()
+ {
+ # delete me and my associated Notice
+ # more cache blowing action
+ parent::delete();
+ }
+
+ # make an atom entry
+ function asAtomEntry()
+ {
+ }
+
+ # make a json object
+ function asJson()
+ {
+ }
+
+ # return an array for Schema::ensureTable to define the table
+ static function tableDef()
+ {
+ return array();
+ }
+
+ # give out a stream, and cache it!
+ static function stream($fn, $args, $cachekey, $offset=0, $limit=20, $since_id=0, $max_id=0)
+ {
+ Notice::stream($fn, $args, $cachekey, $offset, $limit, $since_id, $max_id);
+ }
+
+ # try to fetch public stream from the cache if it is there
+ # or hit the DB, notice objects FIXME: make this return both
+ # notices and social-objects
+ function publicStream($offset=0, $limit=20, $since_id=0, $max_id=0)
+ {
+ $ids = self::stream(array($this, '_publicStreamDirect'),
+ array(),
+ 'public:'.self::$slug,
+ $offset, $limit, $since_id, $max_id);
+ return self::getStreamByIds($ids);
+ }
+
+ # fetch public stream from the db and
+ # return the ids of the notices
+ # see also: Notice::_publicStreamDirect
+ function _publicStreamDirect($offset=0, $limit=20, $since_id=0, $max_id=0)
+ {
+ # make the code look nice :)
+ $table = $this->__table;
+ $id = $table.'.id';
+
+ $notice = new Notice();
+
+ $this->joinAdd();
+ $this->joinAdd($notice); # join notice table
+
+ $this->selectAdd(); // clears it
+ $this->selectAdd($id.' as id');
+
+ $this->orderBy($id.' DESC');
+
+ if (!is_null($offset)) {
+ $this->limit($offset, $limit);
+ }
+
+ if (common_config('public', 'localonly')) {
+ $this->whereAdd('notice.is_local = ' . Notice::LOCAL_PUBLIC);
+ } else {
+ # -1 == blacklisted, -2 == gateway (i.e. Twitter)
+ $this->whereAdd('notice.is_local !='. Notice::LOCAL_NONPUBLIC);
+ $this->whereAdd('notice.is_local !='. Notice::GATEWAY);
+ }
+
+ if ($since_id != 0) {
+ $this->whereAdd($id. ' > ' . $since_id);
+ }
+
+ if ($max_id != 0) {
+ $this->whereAdd($id. ' <= ' . $max_id);
+ }
+
+ $ids = array();
+
+ if ($this->find()) {
+ while ($this->fetch()) {
+ $ids[] = $this->id;
+ }
+ }
+
+ $this->free();
+ $this = NULL;
+
+ return $ids;
+ }
+
+ # get all social-objects by user
+ function userStream($user, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0)
+ {
+ // XXX: I'm not sure this is going to be any faster. It probably isn't.
+ $ids = self::stream(array($user, '_userSreamDirect'),
+ array($user),
+ 'profile:'.$this->slug.':notice_ids:' . $user->id,
+ $offset, $limit, $since_id, $max_id);
+
+ return self::getStreamByIds($ids);
+ }
+
+ # some scary, scary (hacked) upstream code follows.
+ function _userStreamDirect($user, $offset, $limit, $since_id, $max_id)
+ {
+ $table = $this->__table;
+ $id = $table.'.id';
+
+ $notice = new Notice();
+
+ // Temporary hack until notice_profile_id_idx is updated
+ // to (profile_id, id) instead of (profile_id, created, id).
+ // It's been falling back to PRIMARY instead, which is really
+ // very inefficient for a profile that hasn't posted in a few
+ // months. Even though forcing the index will cause a filesort,
+ // it's usually going to be better.
+ if (common_config('db', 'type') == 'mysql') {
+ $index = '';
+ $query = # join me
+ "select $id as id from notice join $table on ($id = notice.id) ".
+ "force index (notice_profile_id_idx) ".
+ "where notice.profile_id=" . $notice->escape($user->id);
+
+ if ($since_id != 0) {
+ $query .= " and $id > $since_id";
+ }
+
+ if ($max_id != 0) {
+ $query .= " and $id < $max_id";
+ }
+
+ $query .= " order by $id DESC";
+
+ if (!is_null($offset)) {
+ $query .= " LIMIT $limit OFFSET $offset";
+ }
+
+ $this->query($query);
+ } else {
+ $index = '';
+
+ $notice->profile_id = $user->id;
+
+ $this->joinAdd();
+ $this->joinAdd($notice);
+
+ $this->selectAdd();
+ $this->selectAdd("$id as id");
+
+ if ($since_id != 0) {
+ $this->whereAdd("$id > $since_id");
+ }
+
+ if ($max_id != 0) {
+ $this->whereAdd("$id <= $max_id");
+ }
+
+ $this->orderBy("$id DESC");
+
+ if (!is_null($offset)) {
+ $this->limit($offset, $limit);
+ }
+
+ $this->find();
+ }
+
+ $ids = array();
+
+ while ($this->fetch()) {
+ $ids[] = $this->id;
+ }
+
+ return $ids;
+ }
+
+ # get all social-objects in the group
+ function groupStream($group, $offset, $limit, $since_id=null, $max_id=null)
+ {
+ $ids = self::stream(array($this, '_groupStreamDirect'),
+ array($group),
+ 'user_group:'.$this->slug.':notice_ids:' . $group->id,
+ $offset, $limit, $since_id, $max_id);
+
+ return self::getStreamByIds($ids);
+ }
+
+ function _groupStreamDirect($group, $offset, $limit, $since_id, $max_id)
+ {
+ $table = $this->__table;
+
+ $inbox = new Group_inbox();
+
+ $inbox->group_id = $group->id;
+
+ $inbox->joinAdd();
+ $inbox->joinAdd($this);
+
+ $inbox->selectAdd();
+ $inbox->selectAdd('group_inbox.notice_id as id');
+
+ if ($since_id != 0) {
+ $inbox->whereAdd('group_inbox.notice_id > ' . $since_id);
+ }
+
+ if ($max_id != 0) {
+ $inbox->whereAdd('group_inbox.notice_id <= ' . $max_id);
+ }
+
+ $inbox->orderBy('group_inbox.notice_id DESC');
+
+ if (!is_null($offset)) {
+ $inbox->limit($offset, $limit);
+ }
+
+ $ids = array();
+
+ if ($inbox->find()) {
+ while ($inbox->fetch()) {
+ $ids[] = $inbox->notice_id;
+ }
+ }
+
+ return $ids;
+ }
+
+ # param: array of ids
+ # returns: array($notices, $social_objects)
+ # an example on how to use this:
+ #
+ # list($notices, $objects) = SocialObject::getStreamByIds($ids);
+ # while($notices->fetch()) {
+ # $obj = $objects[$notices->id];
+ # if(!empty($obj)) {
+ # # now use $notices and $obj,
+ # # they are associated.
+ # }
+ # }
+ #
+ static function getStreamByIds($ids, $classname=null) {
+ $notices = Notice::getSteamByIds($ids);
+ $objects = array();
+ if(empty($classname) && function_exists('get_called_class')) {
+ $classname = get_called_class(); # works in php 5.3 +
+ }
+
+ $cache = common_memcache();
+
+ # don't put array wrapper around $objects
+ # keep the id as key
+ if (!empty($cache)) {
+ $objects = array();
+ foreach ($ids as $id) {
+ $n = $classname::staticGet('id', $id);
+ if (!empty($n)) {
+ $objects[$id] = $n;
+ }
+ }
+ return array($notices, $objects);
+ } else {
+ $object = new $classname();
+ if (empty($ids)) {
+ return array($notices, array());
+ }
+ $objects->whereAdd('id in (' . implode(', ', $ids) . ')');
+
+ $objects->find();
+
+ $objects = array();
+
+ while ($object->fetch()) {
+ $objects[$notice->id] = clone($object);
+ }
+
+ # just return the $objects array, we can then use $notices->id
+ # each time to get the object associated
+ return new array($notices, $objects);
+ }
+ }
+}