summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorEvan Prodromou <evan@status.net>2010-03-17 09:38:39 -0500
committerEvan Prodromou <evan@status.net>2010-03-17 09:38:39 -0500
commit4761c07ad8d76f7c34d4db53d32d15e806ba1e88 (patch)
treeeb3d78ccde1778037165c92b6ec36c7465b54345 /lib
parentf21f78364a9cbde2ca535a3983b384707ad097ae (diff)
parentf62b8a80cf33ac8529d0736c51dc060a9d235369 (diff)
Merge branch 'testing' of git@gitorious.org:statusnet/mainline into testing
Diffstat (limited to 'lib')
-rw-r--r--lib/activity.php29
-rw-r--r--lib/common.php12
-rw-r--r--lib/deluserqueuehandler.php95
-rw-r--r--lib/queuemanager.php3
-rw-r--r--lib/router.php6
-rw-r--r--lib/userprofile.php11
6 files changed, 131 insertions, 25 deletions
diff --git a/lib/activity.php b/lib/activity.php
index 125d391b0..d84eabf7c 100644
--- a/lib/activity.php
+++ b/lib/activity.php
@@ -457,13 +457,13 @@ class ActivityUtils
// slavishly following http://atompub.org/rfc4287.html#rfc.section.4.1.3.3
- if ($type == 'text') {
+ if (empty($type) || $type == 'text') {
return $contentEl->textContent;
} else if ($type == 'html') {
$text = $contentEl->textContent;
return htmlspecialchars_decode($text, ENT_QUOTES);
} else if ($type == 'xhtml') {
- $divEl = ActivityUtils::child($contentEl, 'div');
+ $divEl = ActivityUtils::child($contentEl, 'div', 'http://www.w3.org/1999/xhtml');
if (empty($divEl)) {
return null;
}
@@ -476,7 +476,7 @@ class ActivityUtils
$text .= $doc->saveXML($child);
}
return trim($text);
- } else if (in_array(array('text/xml', 'application/xml'), $type) ||
+ } else if (in_array($type, array('text/xml', 'application/xml')) ||
preg_match('#(+|/)xml$#', $type)) {
throw new ClientException(_("Can't handle embedded XML content yet."));
} else if (strncasecmp($type, 'text/', 5)) {
@@ -681,9 +681,16 @@ class ActivityObject
if ($this->type == self::PERSON || $this->type == self::GROUP) {
$this->displayName = $this->title;
- $avatars = ActivityUtils::getLinks($element, 'avatar');
- foreach ($avatars as $link) {
- $this->avatarLinks[] = new AvatarLink($link);
+ $photos = ActivityUtils::getLinks($element, 'photo');
+ if (count($photos)) {
+ foreach ($photos as $link) {
+ $this->avatarLinks[] = new AvatarLink($link);
+ }
+ } else {
+ $avatars = ActivityUtils::getLinks($element, 'avatar');
+ foreach ($avatars as $link) {
+ $this->avatarLinks[] = new AvatarLink($link);
+ }
}
$this->poco = new PoCo($element);
@@ -1076,15 +1083,11 @@ class Activity
$this->entry = $entry;
- // @fixme Don't send in a DOMDocument
+ // Insist on a feed's root DOMElement; don't allow a DOMDocument
if ($feed instanceof DOMDocument) {
- common_log(
- LOG_WARNING,
- 'Activity::__construct() - '
- . 'DOMDocument passed in for feed by mistake. '
- . "Expecting a 'feed' DOMElement."
+ throw new ClientException(
+ _("Expecting a root feed element but got a whole XML document.")
);
- $feed = $feed->getElementsByTagName('feed')->item(0);
}
$this->feed = $feed;
diff --git a/lib/common.php b/lib/common.php
index 047dc5a7b..5d53270e3 100644
--- a/lib/common.php
+++ b/lib/common.php
@@ -71,7 +71,6 @@ if (!function_exists('dl')) {
# global configuration object
require_once('PEAR.php');
-require_once('PEAR/Exception.php');
require_once('DB/DataObject.php');
require_once('DB/DataObject/Cast.php'); # for dates
@@ -129,17 +128,6 @@ require_once INSTALLDIR.'/lib/activity.php';
require_once INSTALLDIR.'/lib/clientexception.php';
require_once INSTALLDIR.'/lib/serverexception.php';
-
-//set PEAR error handling to use regular PHP exceptions
-function PEAR_ErrorToPEAR_Exception($err)
-{
- if ($err->getCode()) {
- throw new PEAR_Exception($err->getMessage(), $err->getCode());
- }
- throw new PEAR_Exception($err->getMessage());
-}
-PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'PEAR_ErrorToPEAR_Exception');
-
try {
StatusNet::init(@$server, @$path, @$conffile);
} catch (NoConfigException $e) {
diff --git a/lib/deluserqueuehandler.php b/lib/deluserqueuehandler.php
new file mode 100644
index 000000000..4a1233a5e
--- /dev/null
+++ b/lib/deluserqueuehandler.php
@@ -0,0 +1,95 @@
+<?php
+/*
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2010, 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/>.
+ */
+
+/**
+ * Background job to delete prolific users without disrupting front-end too much.
+ *
+ * Up to 50 messages are deleted on each run through; when all messages are gone,
+ * the actual account is deleted.
+ *
+ * @package QueueHandler
+ * @maintainer Brion Vibber <brion@status.net>
+ */
+
+class DelUserQueueHandler extends QueueHandler
+{
+ const DELETION_WINDOW = 50;
+
+ public function transport()
+ {
+ return 'deluser';
+ }
+
+ public function handle($user)
+ {
+ if (!($user instanceof User)) {
+ common_log(LOG_ERR, "Got a bogus user, not deleting");
+ return true;
+ }
+
+ $user = User::staticGet('id', $user->id);
+ if (!$user) {
+ common_log(LOG_INFO, "User {$user->nickname} was deleted before we got here.");
+ return true;
+ }
+
+ if (!$user->hasRole(Profile_role::DELETED)) {
+ common_log(LOG_INFO, "User {$user->nickname} is not pending deletion; aborting.");
+ return true;
+ }
+
+ $notice = $this->getNextBatch($user);
+ if ($notice->N) {
+ common_log(LOG_INFO, "Deleting next {$notice->N} notices by {$user->nickname}");
+ while ($notice->fetch()) {
+ $del = clone($notice);
+ $del->delete();
+ }
+
+ // @todo improve reliability in case we died during the above deletions
+ // with a fatal error. If the job is lost, we should perform some kind
+ // of garbage collection later.
+
+ // Queue up the next batch.
+ $qm = QueueManager::get();
+ $qm->enqueue($user, 'deluser');
+ } else {
+ // Out of notices? Let's finish deleting this guy!
+ $user->delete();
+ common_log(LOG_INFO, "User $user->id $user->nickname deleted.");
+ return true;
+ }
+
+ return true;
+ }
+
+ /**
+ * Fetch the next self::DELETION_WINDOW messages for this user.
+ * @return Notice
+ */
+ protected function getNextBatch(User $user)
+ {
+ $notice = new Notice();
+ $notice->profile_id = $user->id;
+ $notice->limit(self::DELETION_WINDOW);
+ $notice->find();
+ return $notice;
+ }
+
+}
diff --git a/lib/queuemanager.php b/lib/queuemanager.php
index 87bd356aa..0829c8a8b 100644
--- a/lib/queuemanager.php
+++ b/lib/queuemanager.php
@@ -264,6 +264,9 @@ abstract class QueueManager extends IoManager
$this->connect('sms', 'SmsQueueHandler');
}
+ // Background user management tasks...
+ $this->connect('deluser', 'DelUserQueueHandler');
+
// Broadcasting profile updates to OMB remote subscribers
$this->connect('profile', 'ProfileQueueHandler');
diff --git a/lib/router.php b/lib/router.php
index 706120e0b..a48ee875e 100644
--- a/lib/router.php
+++ b/lib/router.php
@@ -628,6 +628,12 @@ class Router
array('action' => 'ApiTimelineTag',
'format' => '(xmljson|rss|atom)'));
+ // media related
+ $m->connect(
+ 'api/statusnet/media/upload',
+ array('action' => 'ApiMediaUpload')
+ );
+
// search
$m->connect('api/search.atom', array('action' => 'twitapisearchatom'));
$m->connect('api/search.json', array('action' => 'twitapisearchjson'));
diff --git a/lib/userprofile.php b/lib/userprofile.php
index 8464c2446..2c3b1ea45 100644
--- a/lib/userprofile.php
+++ b/lib/userprofile.php
@@ -228,6 +228,17 @@ class UserProfile extends Widget
function showEntityActions()
{
+ if ($this->profile->hasRole(Profile_role::DELETED)) {
+ $this->out->elementStart('div', 'entity_actions');
+ $this->out->element('h2', null, _('User actions'));
+ $this->out->elementStart('ul');
+ $this->out->elementStart('p', array('class' => 'profile_deleted'));
+ $this->out->text(_('User deletion in progress...'));
+ $this->out->elementEnd('p');
+ $this->out->elementEnd('ul');
+ $this->out->elementEnd('div');
+ return;
+ }
if (Event::handle('StartProfilePageActionsSection', array(&$this->out, $this->profile))) {
$cur = common_current_user();