summaryrefslogtreecommitdiff
path: root/classes
diff options
context:
space:
mode:
Diffstat (limited to 'classes')
-rw-r--r--classes/Fave.php6
-rw-r--r--classes/File.php13
-rw-r--r--classes/Foreign_link.php17
-rw-r--r--classes/Group_alias.php2
-rw-r--r--classes/Inbox.php8
-rw-r--r--classes/Local_group.php46
-rw-r--r--classes/Notice.php118
-rw-r--r--classes/Notice_inbox.php4
-rw-r--r--classes/Notice_tag.php6
-rw-r--r--classes/Profile.php50
-rw-r--r--classes/Profile_role.php17
-rw-r--r--classes/Reply.php10
-rw-r--r--classes/Subscription.php22
-rw-r--r--classes/User.php67
-rw-r--r--classes/User_group.php162
-rw-r--r--classes/User_username.php2
-rw-r--r--classes/statusnet.ini33
17 files changed, 404 insertions, 179 deletions
diff --git a/classes/Fave.php b/classes/Fave.php
index 0b6eec2bc..a04f15e9c 100644
--- a/classes/Fave.php
+++ b/classes/Fave.php
@@ -77,7 +77,7 @@ class Fave extends Memcached_DataObject
return $ids;
}
- function _streamDirect($user_id, $own, $offset, $limit, $since_id, $max_id, $since)
+ function _streamDirect($user_id, $own, $offset, $limit, $since_id, $max_id)
{
$fav = new Fave();
$qry = null;
@@ -100,10 +100,6 @@ class Fave extends Memcached_DataObject
$qry .= 'AND notice_id <= ' . $max_id . ' ';
}
- if (!is_null($since)) {
- $qry .= 'AND modified > \'' . date('Y-m-d H:i:s', $since) . '\' ';
- }
-
// NOTE: we sort by fave time, not by notice time!
$qry .= 'ORDER BY modified DESC ';
diff --git a/classes/File.php b/classes/File.php
index 189e04ce0..4ecd3b959 100644
--- a/classes/File.php
+++ b/classes/File.php
@@ -169,7 +169,11 @@ class File extends Memcached_DataObject
{
require_once 'MIME/Type/Extension.php';
$mte = new MIME_Type_Extension();
- $ext = $mte->getExtension($mimetype);
+ try {
+ $ext = $mte->getExtension($mimetype);
+ } catch ( Exception $e) {
+ $ext = strtolower(preg_replace('/\W/', '', $mimetype));
+ }
$nickname = $profile->nickname;
$datestamp = strftime('%Y%m%dT%H%M%S', time());
$random = strtolower(common_confirmation_code(32));
@@ -286,5 +290,12 @@ class File extends Memcached_DataObject
}
return $enclosure;
}
+
+ // quick back-compat hack, since there's still code using this
+ function isEnclosure()
+ {
+ $enclosure = $this->getEnclosure();
+ return !empty($enclosure);
+ }
}
diff --git a/classes/Foreign_link.php b/classes/Foreign_link.php
index ae8c22fd8..e47b2e309 100644
--- a/classes/Foreign_link.php
+++ b/classes/Foreign_link.php
@@ -113,4 +113,21 @@ class Foreign_link extends Memcached_DataObject
return User::staticGet($this->user_id);
}
+ // Make sure we only ever delete one record at a time
+ function safeDelete()
+ {
+ if (!empty($this->user_id)
+ && !empty($this->foreign_id)
+ && !empty($this->service))
+ {
+ return $this->delete();
+ } else {
+ common_debug(LOG_WARNING,
+ 'Foreign_link::safeDelete() tried to delete a '
+ . 'Foreign_link without a fully specified compound key: '
+ . var_export($this, true));
+ return false;
+ }
+ }
+
}
diff --git a/classes/Group_alias.php b/classes/Group_alias.php
index be3d0a6c6..c5a1895a1 100644
--- a/classes/Group_alias.php
+++ b/classes/Group_alias.php
@@ -34,7 +34,7 @@ class Group_alias extends Memcached_DataObject
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
/* Static get */
- function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('Group_alias',$k,$v); }
+ function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Group_alias',$k,$v); }
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
diff --git a/classes/Inbox.php b/classes/Inbox.php
index be62611a1..014ba3d82 100644
--- a/classes/Inbox.php
+++ b/classes/Inbox.php
@@ -137,7 +137,7 @@ class Inbox extends Memcached_DataObject
}
}
- function stream($user_id, $offset, $limit, $since_id, $max_id, $since, $own=false)
+ function stream($user_id, $offset, $limit, $since_id, $max_id, $own=false)
{
$inbox = Inbox::staticGet('user_id', $user_id);
@@ -195,15 +195,15 @@ class Inbox extends Memcached_DataObject
* @param int $limit
* @param mixed $since_id return only notices after but not including this id
* @param mixed $max_id return only notices up to and including this id
- * @param mixed $since obsolete/ignored
* @param mixed $own ignored?
* @return array of Notice objects
*
* @todo consider repacking the inbox when this happens?
+ * @fixme reimplement $own if we need it?
*/
- function streamNotices($user_id, $offset, $limit, $since_id, $max_id, $since, $own=false)
+ function streamNotices($user_id, $offset, $limit, $since_id, $max_id, $own=false)
{
- $ids = self::stream($user_id, $offset, self::MAX_NOTICES, $since_id, $max_id, $since, $own);
+ $ids = self::stream($user_id, $offset, self::MAX_NOTICES, $since_id, $max_id, $own);
// Do a bulk lookup for the first $limit items
// Fast path when nothing's deleted.
diff --git a/classes/Local_group.php b/classes/Local_group.php
new file mode 100644
index 000000000..42312ec63
--- /dev/null
+++ b/classes/Local_group.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Table Definition for local_group
+ */
+
+class Local_group extends Memcached_DataObject
+{
+ ###START_AUTOCODE
+ /* the code below is auto generated do not remove the above tag */
+
+ public $__table = 'local_group'; // table name
+ public $group_id; // int(4) primary_key not_null
+ public $nickname; // varchar(64) unique_key
+ public $created; // datetime not_null default_0000-00-00%2000%3A00%3A00
+ public $modified; // timestamp not_null default_CURRENT_TIMESTAMP
+
+ /* Static get */
+ function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Local_group',$k,$v); }
+
+ /* the code above is auto generated do not remove the tag below */
+ ###END_AUTOCODE
+
+ function sequenceKey()
+ {
+ return array(false, false, false);
+ }
+
+ function setNickname($nickname)
+ {
+ $this->decache();
+ $qry = 'UPDATE local_group set nickname = "'.$nickname.'" where group_id = ' . $this->group_id;
+
+ $result = $this->query($qry);
+
+ if ($result) {
+ $this->nickname = $nickname;
+ $this->fixupTimestamps();
+ $this->encache();
+ } else {
+ common_log_db_error($local, 'UPDATE', __FILE__);
+ throw new ServerException(_('Could not update local group.'));
+ }
+
+ return $result;
+ }
+}
diff --git a/classes/Notice.php b/classes/Notice.php
index e8d5c45cb..4c7e6ab4b 100644
--- a/classes/Notice.php
+++ b/classes/Notice.php
@@ -121,6 +121,9 @@ class Notice extends Memcached_DataObject
$result = parent::delete();
}
+ /**
+ * Extract #hashtags from this notice's content and save them to the database.
+ */
function saveTags()
{
/* extract all #hastags */
@@ -129,14 +132,22 @@ class Notice extends Memcached_DataObject
return true;
}
+ /* Add them to the database */
+ return $this->saveKnownTags($match[1]);
+ }
+
+ /**
+ * Record the given set of hash tags in the db for this notice.
+ * Given tag strings will be normalized and checked for dupes.
+ */
+ function saveKnownTags($hashtags)
+ {
//turn each into their canonical tag
//this is needed to remove dupes before saving e.g. #hash.tag = #hashtag
- $hashtags = array();
- for($i=0; $i<count($match[1]); $i++) {
- $hashtags[] = common_canonical_tag($match[1][$i]);
+ for($i=0; $i<count($hashtags); $i++) {
+ $hashtags[$i] = common_canonical_tag($hashtags[$i]);
}
- /* Add them to the database */
foreach(array_unique($hashtags) as $hashtag) {
/* elide characters we don't want in the tag */
$this->saveTag($hashtag);
@@ -145,6 +156,10 @@ class Notice extends Memcached_DataObject
return true;
}
+ /**
+ * Record a single hash tag as associated with this notice.
+ * Tag format and uniqueness must be validated by caller.
+ */
function saveTag($hashtag)
{
$tag = new Notice_tag();
@@ -194,6 +209,10 @@ class Notice extends Memcached_DataObject
* place of extracting @-replies from content.
* array 'groups' list of group IDs to deliver to, in place of
* extracting ! tags from content
+ * array 'tags' list of hashtag strings to save with the notice
+ * in place of extracting # tags from content
+ * array 'urls' list of attached/referred URLs to save with the
+ * notice in place of extracting links from content
* @fixme tag override
*
* @return Notice
@@ -265,12 +284,6 @@ class Notice extends Memcached_DataObject
$notice->content = $final;
- if (!empty($rendered)) {
- $notice->rendered = $rendered;
- } else {
- $notice->rendered = common_render_content($final, $notice);
- }
-
$notice->source = $source;
$notice->uri = $uri;
$notice->url = $url;
@@ -298,6 +311,12 @@ class Notice extends Memcached_DataObject
$notice->location_ns = $location_ns;
}
+ if (!empty($rendered)) {
+ $notice->rendered = $rendered;
+ } else {
+ $notice->rendered = common_render_content($final, $notice);
+ }
+
if (Event::handle('StartNoticeSave', array(&$notice))) {
// XXX: some of these functions write to the DB
@@ -343,6 +362,8 @@ class Notice extends Memcached_DataObject
$notice->blowOnInsert();
+ // Save per-notice metadata...
+
if (isset($replies)) {
$notice->saveKnownReplies($replies);
} else {
@@ -355,6 +376,19 @@ class Notice extends Memcached_DataObject
$notice->saveGroups();
}
+ if (isset($tags)) {
+ $notice->saveKnownTags($tags);
+ } else {
+ $notice->saveTags();
+ }
+
+ if (isset($urls)) {
+ $notice->saveKnownUrls($urls);
+ } else {
+ $notice->saveUrls();
+ }
+
+ // Prepare inbox delivery, may be queued to background.
$notice->distribute();
return $notice;
@@ -398,6 +432,25 @@ class Notice extends Memcached_DataObject
common_replace_urls_callback($this->content, array($this, 'saveUrl'), $this->id);
}
+ /**
+ * Save the given URLs as related links/attachments to the db
+ *
+ * follow redirects and save all available file information
+ * (mimetype, date, size, oembed, etc.)
+ *
+ * @return void
+ */
+ function saveKnownUrls($urls)
+ {
+ // @fixme validation?
+ foreach ($urls as $url) {
+ File::processNew($url, $this->id);
+ }
+ }
+
+ /**
+ * @private callback
+ */
function saveUrl($data) {
list($url, $notice_id) = $data;
File::processNew($url, $notice_id);
@@ -530,17 +583,17 @@ class Notice extends Memcached_DataObject
}
}
- function publicStream($offset=0, $limit=20, $since_id=0, $max_id=0, $since=null)
+ function publicStream($offset=0, $limit=20, $since_id=0, $max_id=0)
{
$ids = Notice::stream(array('Notice', '_publicStreamDirect'),
array(),
'public',
- $offset, $limit, $since_id, $max_id, $since);
+ $offset, $limit, $since_id, $max_id);
return Notice::getStreamByIds($ids);
}
- function _publicStreamDirect($offset=0, $limit=20, $since_id=0, $max_id=0, $since=null)
+ function _publicStreamDirect($offset=0, $limit=20, $since_id=0, $max_id=0)
{
$notice = new Notice();
@@ -569,10 +622,6 @@ class Notice extends Memcached_DataObject
$notice->whereAdd('id <= ' . $max_id);
}
- if (!is_null($since)) {
- $notice->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\'');
- }
-
$ids = array();
if ($notice->find()) {
@@ -587,17 +636,17 @@ class Notice extends Memcached_DataObject
return $ids;
}
- function conversationStream($id, $offset=0, $limit=20, $since_id=0, $max_id=0, $since=null)
+ function conversationStream($id, $offset=0, $limit=20, $since_id=0, $max_id=0)
{
$ids = Notice::stream(array('Notice', '_conversationStreamDirect'),
array($id),
'notice:conversation_ids:'.$id,
- $offset, $limit, $since_id, $max_id, $since);
+ $offset, $limit, $since_id, $max_id);
return Notice::getStreamByIds($ids);
}
- function _conversationStreamDirect($id, $offset=0, $limit=20, $since_id=0, $max_id=0, $since=null)
+ function _conversationStreamDirect($id, $offset=0, $limit=20, $since_id=0, $max_id=0)
{
$notice = new Notice();
@@ -620,10 +669,6 @@ class Notice extends Memcached_DataObject
$notice->whereAdd('id <= ' . $max_id);
}
- if (!is_null($since)) {
- $notice->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\'');
- }
-
$ids = array();
if ($notice->find()) {
@@ -832,7 +877,7 @@ class Notice extends Memcached_DataObject
foreach (array_unique($match[1]) as $nickname) {
/* XXX: remote groups. */
- $group = User_group::getForNickname($nickname);
+ $group = User_group::getForNickname($nickname, $profile);
if (empty($group)) {
continue;
@@ -915,6 +960,8 @@ class Notice extends Memcached_DataObject
$reply->profile_id = $user->id;
$id = $reply->insert();
+
+ self::blow('reply:stream:%d', $user->id);
}
}
@@ -942,7 +989,10 @@ class Notice extends Memcached_DataObject
$sender = Profile::staticGet($this->profile_id);
- $mentions = common_find_mentions($this->profile_id, $this->content);
+ // @todo ideally this parser information would only
+ // be calculated once.
+
+ $mentions = common_find_mentions($this->content, $this);
$replied = array();
@@ -1056,7 +1106,7 @@ class Notice extends Memcached_DataObject
return $groups;
}
- function asAtomEntry($namespace=false, $source=false)
+ function asAtomEntry($namespace=false, $source=false, $author=true)
{
$profile = $this->getProfile();
@@ -1067,6 +1117,7 @@ class Notice extends Memcached_DataObject
'xmlns:thr' => 'http://purl.org/syndication/thread/1.0',
'xmlns:georss' => 'http://www.georss.org/georss',
'xmlns:activity' => 'http://activitystrea.ms/spec/1.0/',
+ 'xmlns:media' => 'http://purl.org/syndication/atommedia',
'xmlns:poco' => 'http://portablecontacts.net/spec/1.0',
'xmlns:ostatus' => 'http://ostatus.org/schema/1.0');
} else {
@@ -1099,10 +1150,11 @@ class Notice extends Memcached_DataObject
}
$xs->element('title', null, $this->content);
- $xs->element('summary', null, $this->content);
- $xs->raw($profile->asAtomAuthor());
- $xs->raw($profile->asActivityActor());
+ if ($author) {
+ $xs->raw($profile->asAtomAuthor());
+ $xs->raw($profile->asActivityActor());
+ }
$xs->element('link', array('rel' => 'alternate',
'type' => 'text/html',
@@ -1235,16 +1287,16 @@ class Notice extends Memcached_DataObject
}
}
- function stream($fn, $args, $cachekey, $offset=0, $limit=20, $since_id=0, $max_id=0, $since=null)
+ function stream($fn, $args, $cachekey, $offset=0, $limit=20, $since_id=0, $max_id=0)
{
$cache = common_memcache();
if (empty($cache) ||
- $since_id != 0 || $max_id != 0 || (!is_null($since) && $since > 0) ||
+ $since_id != 0 || $max_id != 0 ||
is_null($limit) ||
($offset + $limit) > NOTICE_CACHE_WINDOW) {
return call_user_func_array($fn, array_merge($args, array($offset, $limit, $since_id,
- $max_id, $since)));
+ $max_id)));
}
$idkey = common_cache_key($cachekey);
diff --git a/classes/Notice_inbox.php b/classes/Notice_inbox.php
index c27dcdfd6..47ed6b22d 100644
--- a/classes/Notice_inbox.php
+++ b/classes/Notice_inbox.php
@@ -49,12 +49,12 @@ class Notice_inbox extends Memcached_DataObject
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
- function stream($user_id, $offset, $limit, $since_id, $max_id, $since, $own=false)
+ function stream($user_id, $offset, $limit, $since_id, $max_id, $own=false)
{
throw new Exception('Notice_inbox no longer used; use Inbox');
}
- function _streamDirect($user_id, $own, $offset, $limit, $since_id, $max_id, $since)
+ function _streamDirect($user_id, $own, $offset, $limit, $since_id, $max_id)
{
throw new Exception('Notice_inbox no longer used; use Inbox');
}
diff --git a/classes/Notice_tag.php b/classes/Notice_tag.php
index 4fd76e8ea..a5d0716a7 100644
--- a/classes/Notice_tag.php
+++ b/classes/Notice_tag.php
@@ -46,7 +46,7 @@ class Notice_tag extends Memcached_DataObject
return Notice::getStreamByIds($ids);
}
- function _streamDirect($tag, $offset, $limit, $since_id, $max_id, $since)
+ function _streamDirect($tag, $offset, $limit, $since_id, $max_id)
{
$nt = new Notice_tag();
@@ -63,10 +63,6 @@ class Notice_tag extends Memcached_DataObject
$nt->whereAdd('notice_id < ' . $max_id);
}
- if (!is_null($since)) {
- $nt->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\'');
- }
-
$nt->orderBy('notice_id DESC');
if (!is_null($offset)) {
diff --git a/classes/Profile.php b/classes/Profile.php
index 78223b34a..0322c9358 100644
--- a/classes/Profile.php
+++ b/classes/Profile.php
@@ -163,27 +163,27 @@ class Profile extends Memcached_DataObject
return null;
}
- function getTaggedNotices($tag, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, $since=null)
+ function getTaggedNotices($tag, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0)
{
$ids = Notice::stream(array($this, '_streamTaggedDirect'),
array($tag),
'profile:notice_ids_tagged:' . $this->id . ':' . $tag,
- $offset, $limit, $since_id, $max_id, $since);
+ $offset, $limit, $since_id, $max_id);
return Notice::getStreamByIds($ids);
}
- function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, $since=null)
+ function getNotices($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 = Notice::stream(array($this, '_streamDirect'),
array(),
'profile:notice_ids:' . $this->id,
- $offset, $limit, $since_id, $max_id, $since);
+ $offset, $limit, $since_id, $max_id);
return Notice::getStreamByIds($ids);
}
- function _streamTaggedDirect($tag, $offset, $limit, $since_id, $max_id, $since)
+ function _streamTaggedDirect($tag, $offset, $limit, $since_id, $max_id)
{
// XXX It would be nice to do this without a join
@@ -202,10 +202,6 @@ class Profile extends Memcached_DataObject
$query .= " and id < $max_id";
}
- if (!is_null($since)) {
- $query .= " and created > '" . date('Y-m-d H:i:s', $since) . "'";
- }
-
$query .= ' order by id DESC';
if (!is_null($offset)) {
@@ -223,7 +219,7 @@ class Profile extends Memcached_DataObject
return $ids;
}
- function _streamDirect($offset, $limit, $since_id, $max_id, $since = null)
+ function _streamDirect($offset, $limit, $since_id, $max_id)
{
$notice = new Notice();
@@ -240,10 +236,6 @@ class Profile extends Memcached_DataObject
$notice->whereAdd('id <= ' . $max_id);
}
- if (!is_null($since)) {
- $notice->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\'');
- }
-
$notice->orderBy('id DESC');
if (!is_null($offset)) {
@@ -290,6 +282,32 @@ class Profile extends Memcached_DataObject
}
}
+ function getGroups($offset=0, $limit=null)
+ {
+ $qry =
+ 'SELECT user_group.* ' .
+ 'FROM user_group JOIN group_member '.
+ 'ON user_group.id = group_member.group_id ' .
+ 'WHERE group_member.profile_id = %d ' .
+ 'ORDER BY group_member.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;
+ }
+ }
+ }
+
+ $groups = new User_group();
+
+ $cnt = $groups->query(sprintf($qry, $this->id));
+
+ return $groups;
+ }
+
function avatarUrl($size=AVATAR_PROFILE_SIZE)
{
$avatar = $this->getAvatar($size);
@@ -725,6 +743,10 @@ class Profile extends Memcached_DataObject
case Right::CONFIGURESITE:
$result = $this->hasRole(Profile_role::ADMINISTRATOR);
break;
+ case Right::GRANTROLE:
+ case Right::REVOKEROLE:
+ $result = $this->hasRole(Profile_role::OWNER);
+ break;
case Right::NEWNOTICE:
case Right::NEWMESSAGE:
case Right::SUBSCRIBE:
diff --git a/classes/Profile_role.php b/classes/Profile_role.php
index bf2c453ed..d0a0b31f0 100644
--- a/classes/Profile_role.php
+++ b/classes/Profile_role.php
@@ -53,4 +53,21 @@ class Profile_role extends Memcached_DataObject
const ADMINISTRATOR = 'administrator';
const SANDBOXED = 'sandboxed';
const SILENCED = 'silenced';
+
+ public static function isValid($role)
+ {
+ // @fixme could probably pull this from class constants
+ $known = array(self::OWNER,
+ self::MODERATOR,
+ self::ADMINISTRATOR,
+ self::SANDBOXED,
+ self::SILENCED);
+ return in_array($role, $known);
+ }
+
+ public static function isSettable($role)
+ {
+ $allowedRoles = array('administrator', 'moderator');
+ return self::isValid($role) && in_array($role, $allowedRoles);
+ }
}
diff --git a/classes/Reply.php b/classes/Reply.php
index 49b1e05e5..659e04c92 100644
--- a/classes/Reply.php
+++ b/classes/Reply.php
@@ -22,16 +22,16 @@ class Reply extends Memcached_DataObject
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
- function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, $since=null)
+ function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0)
{
$ids = Notice::stream(array('Reply', '_streamDirect'),
array($user_id),
'reply:stream:' . $user_id,
- $offset, $limit, $since_id, $max_id, $since);
+ $offset, $limit, $since_id, $max_id);
return $ids;
}
- function _streamDirect($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, $since=null)
+ function _streamDirect($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0)
{
$reply = new Reply();
$reply->profile_id = $user_id;
@@ -44,10 +44,6 @@ class Reply extends Memcached_DataObject
$reply->whereAdd('notice_id < ' . $max_id);
}
- if (!is_null($since)) {
- $reply->whereAdd('modified > \'' . date('Y-m-d H:i:s', $since) . '\'');
- }
-
$reply->orderBy('notice_id DESC');
if (!is_null($offset)) {
diff --git a/classes/Subscription.php b/classes/Subscription.php
index d6fb3fcbd..9cef2df1a 100644
--- a/classes/Subscription.php
+++ b/classes/Subscription.php
@@ -172,6 +172,28 @@ 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__);
+ throw new Exception(_('Couldn\'t delete subscription OMB token.'));
+ }
+ } else {
+ common_log(LOG_ERR, "Couldn't find credentials with token {$token->tok}");
+ }
+ }
+
$result = $sub->delete();
if (!$result) {
diff --git a/classes/User.php b/classes/User.php
index 0f84ed813..15ec4ad94 100644
--- a/classes/User.php
+++ b/classes/User.php
@@ -201,6 +201,7 @@ class User extends Memcached_DataObject
if(! User::allowed_nickname($nickname)){
common_log(LOG_WARNING, sprintf("Attempted to register a nickname that is not allowed: %s", $profile->nickname),
__FILE__);
+ return false;
}
$profile->profileurl = common_profile_url($nickname);
@@ -451,28 +452,28 @@ class User extends Memcached_DataObject
return $user;
}
- function getReplies($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
+ function getReplies($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0)
{
- $ids = Reply::stream($this->id, $offset, $limit, $since_id, $before_id, $since);
+ $ids = Reply::stream($this->id, $offset, $limit, $since_id, $before_id);
return Notice::getStreamByIds($ids);
}
- function getTaggedNotices($tag, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) {
+ function getTaggedNotices($tag, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0) {
$profile = $this->getProfile();
if (!$profile) {
return null;
} else {
- return $profile->getTaggedNotices($tag, $offset, $limit, $since_id, $before_id, $since);
+ return $profile->getTaggedNotices($tag, $offset, $limit, $since_id, $before_id);
}
}
- function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
+ function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0)
{
$profile = $this->getProfile();
if (!$profile) {
return null;
} else {
- return $profile->getNotices($offset, $limit, $since_id, $before_id, $since);
+ return $profile->getNotices($offset, $limit, $since_id, $before_id);
}
}
@@ -482,24 +483,24 @@ class User extends Memcached_DataObject
return Notice::getStreamByIds($ids);
}
- function noticesWithFriends($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
+ function noticesWithFriends($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0)
{
- return Inbox::streamNotices($this->id, $offset, $limit, $since_id, $before_id, $since, false);
+ return Inbox::streamNotices($this->id, $offset, $limit, $since_id, $before_id, false);
}
- function noticeInbox($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
+ function noticeInbox($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0)
{
- return Inbox::streamNotices($this->id, $offset, $limit, $since_id, $before_id, $since, true);
+ return Inbox::streamNotices($this->id, $offset, $limit, $since_id, $before_id, true);
}
- function friendsTimeline($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
+ function friendsTimeline($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0)
{
- return Inbox::streamNotices($this->id, $offset, $limit, $since_id, $before_id, $since, false);
+ return Inbox::streamNotices($this->id, $offset, $limit, $since_id, $before_id, false);
}
- function ownFriendsTimeline($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
+ function ownFriendsTimeline($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0)
{
- return Inbox::streamNotices($this->id, $offset, $limit, $since_id, $before_id, $since, true);
+ return Inbox::streamNotices($this->id, $offset, $limit, $since_id, $before_id, true);
}
function blowFavesCache()
@@ -607,28 +608,8 @@ class User extends Memcached_DataObject
function getGroups($offset=0, $limit=null)
{
- $qry =
- 'SELECT user_group.* ' .
- 'FROM user_group JOIN group_member '.
- 'ON user_group.id = group_member.group_id ' .
- 'WHERE group_member.profile_id = %d ' .
- 'ORDER BY group_member.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;
- }
- }
- }
-
- $groups = new User_group();
-
- $cnt = $groups->query(sprintf($qry, $this->id));
-
- return $groups;
+ $profile = $this->getProfile();
+ return $profile->getGroups($offset, $limit);
}
function getSubscriptions($offset=0, $limit=null)
@@ -784,7 +765,7 @@ class User extends Memcached_DataObject
return Notice::getStreamByIds($ids);
}
- function _repeatedByMeDirect($offset, $limit, $since_id, $max_id, $since)
+ function _repeatedByMeDirect($offset, $limit, $since_id, $max_id)
{
$notice = new Notice();
@@ -808,10 +789,6 @@ class User extends Memcached_DataObject
$notice->whereAdd('id <= ' . $max_id);
}
- if (!is_null($since)) {
- $notice->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\'');
- }
-
$ids = array();
if ($notice->find()) {
@@ -831,12 +808,12 @@ class User extends Memcached_DataObject
$ids = Notice::stream(array($this, '_repeatsOfMeDirect'),
array(),
'user:repeats_of_me:'.$this->id,
- $offset, $limit, $since_id, $max_id, null);
+ $offset, $limit, $since_id, $max_id);
return Notice::getStreamByIds($ids);
}
- function _repeatsOfMeDirect($offset, $limit, $since_id, $max_id, $since)
+ function _repeatsOfMeDirect($offset, $limit, $since_id, $max_id)
{
$qry =
'SELECT DISTINCT original.id AS id ' .
@@ -851,10 +828,6 @@ class User extends Memcached_DataObject
$qry .= 'AND original.id <= ' . $max_id . ' ';
}
- if (!is_null($since)) {
- $qry .= 'AND original.modified > \'' . date('Y-m-d H:i:s', $since) . '\' ';
- }
-
// NOTE: we sort by fave time, not by notice time!
$qry .= 'ORDER BY original.id DESC ';
diff --git a/classes/User_group.php b/classes/User_group.php
index 1382aa407..7be55163a 100644
--- a/classes/User_group.php
+++ b/classes/User_group.php
@@ -10,21 +10,23 @@ class User_group extends Memcached_DataObject
public $__table = 'user_group'; // table name
public $id; // int(4) primary_key not_null
- public $nickname; // varchar(64) unique_key
+ public $nickname; // varchar(64)
public $fullname; // varchar(255)
public $homepage; // varchar(255)
- public $description; // text()
+ public $description; // text
public $location; // varchar(255)
public $original_logo; // varchar(255)
public $homepage_logo; // varchar(255)
public $stream_logo; // varchar(255)
public $mini_logo; // varchar(255)
public $design_id; // int(4)
- public $created; // datetime() not_null
- public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
+ public $created; // datetime not_null default_0000-00-00%2000%3A00%3A00
+ public $modified; // timestamp not_null default_CURRENT_TIMESTAMP
+ public $uri; // varchar(255) unique_key
+ public $mainpage; // varchar(255)
/* Static get */
- function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('User_group',$k,$v); }
+ function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('User_group',$k,$v); }
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
@@ -41,13 +43,33 @@ class User_group extends Memcached_DataObject
{
$url = null;
if (Event::handle('StartUserGroupHomeUrl', array($this, &$url))) {
- $url = common_local_url('showgroup',
- array('nickname' => $this->nickname));
+ // normally stored in mainpage, but older ones may be null
+ if (!empty($this->mainpage)) {
+ $url = $this->mainpage;
+ } else {
+ $url = common_local_url('showgroup',
+ array('nickname' => $this->nickname));
+ }
}
Event::handle('EndUserGroupHomeUrl', array($this, &$url));
return $url;
}
+ function getUri()
+ {
+ $uri = null;
+ if (Event::handle('StartUserGroupGetUri', array($this, &$uri))) {
+ if (!empty($this->uri)) {
+ $uri = $this->uri;
+ } else {
+ $uri = common_local_url('groupbyid',
+ array('id' => $this->id));
+ }
+ }
+ Event::handle('EndUserGroupGetUri', array($this, &$uri));
+ return $uri;
+ }
+
function permalink()
{
$url = null;
@@ -69,7 +91,7 @@ class User_group extends Memcached_DataObject
return Notice::getStreamByIds($ids);
}
- function _streamDirect($offset, $limit, $since_id, $max_id, $since)
+ function _streamDirect($offset, $limit, $since_id, $max_id)
{
$inbox = new Group_inbox();
@@ -86,10 +108,6 @@ class User_group extends Memcached_DataObject
$inbox->whereAdd('notice_id <= ' . $max_id);
}
- if (!is_null($since)) {
- $inbox->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\'');
- }
-
$inbox->orderBy('notice_id DESC');
if (!is_null($offset)) {
@@ -261,12 +279,26 @@ class User_group extends Memcached_DataObject
return true;
}
- static function getForNickname($nickname)
+ static function getForNickname($nickname, $profile=null)
{
$nickname = common_canonical_nickname($nickname);
- $group = User_group::staticGet('nickname', $nickname);
+
+ // Are there any matching remote groups this profile's in?
+ if ($profile) {
+ $group = $profile->getGroups();
+ while ($group->fetch()) {
+ if ($group->nickname == $nickname) {
+ // @fixme is this the best way?
+ return clone($group);
+ }
+ }
+ }
+
+ // If not, check local groups.
+
+ $group = Local_group::staticGet('nickname', $nickname);
if (!empty($group)) {
- return $group;
+ return User_group::staticGet('id', $group->group_id);
}
$alias = Group_alias::staticGet('alias', $nickname);
if (!empty($alias)) {
@@ -377,25 +409,41 @@ class User_group extends Memcached_DataObject
return $xs->getString();
}
+ /**
+ * Returns an XML string fragment with group information as an
+ * Activity Streams <activity:subject> element.
+ *
+ * Assumes that 'activity' namespace has been previously defined.
+ *
+ * @return string
+ */
function asActivitySubject()
{
- $xs = new XMLStringer(true);
+ return $this->asActivityNoun('subject');
+ }
- $xs->elementStart('activity:subject');
- $xs->element('activity:object', null, 'http://activitystrea.ms/schema/1.0/group');
- $xs->element('id', null, $this->permalink());
- $xs->element('title', null, $this->getBestName());
- $xs->element(
- 'link', array(
- 'rel' => 'avatar',
- 'href' => empty($this->homepage_logo)
- ? User_group::defaultLogo(AVATAR_PROFILE_SIZE)
- : $this->homepage_logo
- )
- );
- $xs->elementEnd('activity:subject');
+ /**
+ * Returns an XML string fragment with group information as an
+ * Activity Streams noun object with the given element type.
+ *
+ * Assumes that 'activity', 'georss', and 'poco' namespace has been
+ * previously defined.
+ *
+ * @param string $element one of 'actor', 'subject', 'object', 'target'
+ *
+ * @return string
+ */
+ function asActivityNoun($element)
+ {
+ $noun = ActivityObject::fromGroup($this);
+ return $noun->asString('activity:' . $element);
+ }
- return $xs->getString();
+ function getAvatar()
+ {
+ return empty($this->homepage_logo)
+ ? User_group::defaultLogo(AVATAR_PROFILE_SIZE)
+ : $this->homepage_logo;
}
static function register($fields) {
@@ -407,34 +455,42 @@ class User_group extends Memcached_DataObject
$group = new User_group();
$group->query('BEGIN');
+
+ if (empty($uri)) {
+ // fill in later...
+ $uri = null;
+ }
$group->nickname = $nickname;
$group->fullname = $fullname;
$group->homepage = $homepage;
$group->description = $description;
$group->location = $location;
+ $group->uri = $uri;
+ $group->mainpage = $mainpage;
$group->created = common_sql_now();
$result = $group->insert();
if (!$result) {
common_log_db_error($group, 'INSERT', __FILE__);
- $this->serverError(
- _('Could not create group.'),
- 500,
- $this->format
- );
- return;
+ throw new ServerException(_('Could not create group.'));
+ }
+
+ if (!isset($uri) || empty($uri)) {
+ $orig = clone($group);
+ $group->uri = common_local_url('groupbyid', array('id' => $group->id));
+ $result = $group->update($orig);
+ if (!$result) {
+ common_log_db_error($group, 'UPDATE', __FILE__);
+ throw new ServerException(_('Could not set group URI.'));
+ }
}
+
$result = $group->setAliases($aliases);
if (!$result) {
- $this->serverError(
- _('Could not create aliases.'),
- 500,
- $this->format
- );
- return;
+ throw new ServerException(_('Could not create aliases.'));
}
$member = new Group_member();
@@ -448,12 +504,22 @@ class User_group extends Memcached_DataObject
if (!$result) {
common_log_db_error($member, 'INSERT', __FILE__);
- $this->serverError(
- _('Could not set group membership.'),
- 500,
- $this->format
- );
- return;
+ throw new ServerException(_('Could not set group membership.'));
+ }
+
+ if ($local) {
+ $local_group = new Local_group();
+
+ $local_group->group_id = $group->id;
+ $local_group->nickname = $nickname;
+ $local_group->created = common_sql_now();
+
+ $result = $local_group->insert();
+
+ if (!$result) {
+ common_log_db_error($local_group, 'INSERT', __FILE__);
+ throw new ServerException(_('Could not save local group info.'));
+ }
}
$group->query('COMMIT');
diff --git a/classes/User_username.php b/classes/User_username.php
index 853fd5cb8..8d99cddd3 100644
--- a/classes/User_username.php
+++ b/classes/User_username.php
@@ -55,7 +55,7 @@ class User_username extends Memcached_DataObject
// now define the keys.
function keys() {
- return array('provider_name', 'username');
+ return array('provider_name' => 'K', 'username' => 'K');
}
}
diff --git a/classes/statusnet.ini b/classes/statusnet.ini
index d116b16a3..473bd6ff5 100644
--- a/classes/statusnet.ini
+++ b/classes/statusnet.ini
@@ -245,13 +245,6 @@ modified = 384
group_id = K
profile_id = K
-[invitation]
-code = 130
-user_id = 129
-address = 130
-address_type = 130
-created = 142
-
[inbox]
user_id = 129
notice_ids = 66
@@ -259,9 +252,26 @@ notice_ids = 66
[inbox__keys]
user_id = K
+[invitation]
+code = 130
+user_id = 129
+address = 130
+address_type = 130
+created = 142
+
[invitation__keys]
code = K
+[local_group]
+group_id = 129
+nickname = 2
+created = 142
+modified = 384
+
+[local_group__keys]
+group_id = K
+nickname = U
+
[location_namespace]
id = 129
description = 2
@@ -369,7 +379,7 @@ icon = 130
source_url = 2
organization = 2
homepage = 2
-callback_url = 130
+callback_url = 2
type = 17
access_type = 17
created = 142
@@ -440,13 +450,13 @@ tag = K
[queue_item]
id = 129
-frame = 66
+frame = 194
transport = 130
created = 142
claimed = 14
[queue_item__keys]
-id = K
+id = N
[related_group]
group_id = 129
@@ -587,10 +597,11 @@ mini_logo = 2
design_id = 1
created = 142
modified = 384
+uri = 2
+mainpage = 2
[user_group__keys]
id = N
-nickname = U
[user_openid]
canonical = 130