Some stuff for search.
type: type of search. Ignored if PostgreSQL or Sphinx are enabled. Can either
- be 'fulltext' (default) or 'like'. The former is faster and more efficient
+ be 'fulltext' or 'like' (default). The former is faster and more efficient
but requires the lame old MyISAM engine for MySQL. The latter
will work with InnoDB but could be miserably slow on large
systems. We'll probably add another type sometime in the future,
$self = $this->getSelfUri();
- $link = common_local_url(
- 'ApiTimelineGroup',
- array('nickname' => $this->group->nickname)
- );
+ $link = common_local_url('showgroup',
+ array('nickname' => $this->group->nickname));
switch($this->format) {
case 'xml':
try {
$cur->leaveGroup($this->group);
} catch (Exception $e) {
+ common_log(LOG_ERR, "Error when {$cur->nickname} tried to leave {$this->group->nickname}: " . $e->getMessage());
// TRANS: Server error displayed when leaving a group failed in the database.
// TRANS: %1$s is the leaving user's nickname, $2$s is the group nickname for which the leave failed.
$this->serverError(sprintf(_('Could not remove user %1$s from group %2$s.'),
*/
class ShowstreamAction extends ProfileAction
{
+ var $notice;
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $p = Profile::current();
+
+ if (empty($this->tag)) {
+ $stream = new ProfileNoticeStream($this->profile, $p);
+ } else {
+ $stream = new TaggedProfileNoticeStream($this->profile, $this->tag, $p);
+ }
+
+ $this->notice = $stream->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
+
+ return true;
+ }
+
function isReadOnly($args)
{
return true;
function showNotices()
{
- $notice = empty($this->tag)
- ? $this->user->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1)
- : $this->user->getTaggedNotices($this->tag, ($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1, 0, 0, null);
-
$pnl = null;
- if (Event::handle('ShowStreamNoticeList', array($notice, $this, &$pnl))) {
- $pnl = new ProfileNoticeList($notice, $this);
+ if (Event::handle('ShowStreamNoticeList', array($this->notice, $this, &$pnl))) {
+ $pnl = new ProfileNoticeList($this->notice, $this);
}
$cnt = $pnl->show();
if (0 == $cnt) {
class TagAction extends Action
{
var $notice;
+ var $tag;
+ var $page;
function prepare($args)
{
public static function schemaDef()
{
- return array(
+ $def = array(
'fields' => array(
'id' => array('type' => 'serial', 'not null' => true, 'description' => 'unique identifier'),
'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'who made the update'),
'notice_repeatof_idx' => array('repeat_of'),
)
);
+
+ if (common_config('search', 'type') == 'fulltext') {
+ $def['fulltext indexes'] = array('content' => array('content'));
+ }
+
+ return $def;
}
function multiGet($kc, $kvs, $skipNulls=true)
public static function schemaDef()
{
- return array(
+ $def = array(
'description' => 'local and remote users have profiles',
'fields' => array(
'id' => array('type' => 'serial', 'not null' => true, 'description' => 'unique identifier'),
'profile_nickname_idx' => array('nickname'),
)
);
+
+ // Add a fulltext index
+
+ if (common_config('search', 'type') == 'fulltext') {
+ $def['fulltext indexes'] = array('nickname' => array('nickname', 'fullname', 'location', 'bio', 'homepage'));
+ }
+
+ return $def;
}
function multiGet($keyCol, $keyVals, $skipNulls=true)
$profile->_fillAvatar($width, $avatars[$profile->id]);
}
}
+
+ // Can't seem to find how to fix this.
+
+ function getProfile()
+ {
+ return $this;
+ }
}
$items = array();
while ($this->groups->fetch()) {
- $items[] = array('showgroup',
- array('nickname' => $this->groups->nickname),
+ $items[] = array('placeholder',
+ array('nickname' => $this->groups->nickname,
+ 'mainpage' => $this->groups->homeUrl()),
$this->groups->getBestName(),
$this->groups->getBestName()
);
_('See all groups you belong to.'));
}
+ function item($actionName, $args, $label, $description, $id=null, $cls=null)
+ {
+ if ($actionName != 'placeholder') {
+ return parent::item($actionName, $args, $label, $description, $id, $cls);
+ }
+
+ if (empty($id)) {
+ $id = $this->menuItemID('showgroup', array('nickname' => $args['nickname']));
+ }
+
+ $url = $args['mainpage'];
+
+ $this->out->menuItem($url,
+ $label,
+ $description,
+ $this->isCurrent($actionName, $args),
+ $id,
+ $cls);
+ }
}
array('action' => 'attachment_thumbnail'),
array('attachment' => '[0-9]+'));
- $m->connect('notice/new', array('action' => 'newnotice'));
- $m->connect('notice/new?replyto=:replyto',
- array('action' => 'newnotice'),
- array('replyto' => Nickname::DISPLAY_FMT));
$m->connect('notice/new?replyto=:replyto&inreplyto=:inreplyto',
array('action' => 'newnotice'),
array('replyto' => Nickname::DISPLAY_FMT),
array('inreplyto' => '[0-9]+'));
+ $m->connect('notice/new?replyto=:replyto',
+ array('action' => 'newnotice'),
+ array('replyto' => Nickname::DISPLAY_FMT));
+
+ $m->connect('notice/new', array('action' => 'newnotice'));
+
$m->connect('notice/:notice/file',
array('action' => 'file'),
array('notice' => '[0-9]+'));
$m->connect('notice/:notice',
array('action' => 'shownotice'),
array('notice' => '[0-9]+'));
- $m->connect('notice/delete', array('action' => 'deletenotice'));
+
$m->connect('notice/delete/:notice',
array('action' => 'deletenotice'),
array('notice' => '[0-9]+'));
+ $m->connect('notice/delete', array('action' => 'deletenotice'));
+
$m->connect('bookmarklet/new', array('action' => 'bookmarklet'));
// conversation
array('action' => 'ApiTimelinePublic',
'format' => '(xml|json|rss|atom|as)'));
- $m->connect('api/statuses/friends_timeline.:format',
- array('action' => 'ApiTimelineFriends',
- 'format' => '(xml|json|rss|atom|as)'));
-
$m->connect('api/statuses/friends_timeline/:id.:format',
array('action' => 'ApiTimelineFriends',
'id' => Nickname::INPUT_FMT,
'format' => '(xml|json|rss|atom|as)'));
- $m->connect('api/statuses/home_timeline.:format',
- array('action' => 'ApiTimelineHome',
+ $m->connect('api/statuses/friends_timeline.:format',
+ array('action' => 'ApiTimelineFriends',
'format' => '(xml|json|rss|atom|as)'));
$m->connect('api/statuses/home_timeline/:id.:format',
'id' => Nickname::INPUT_FMT,
'format' => '(xml|json|rss|atom|as)'));
- $m->connect('api/statuses/user_timeline.:format',
- array('action' => 'ApiTimelineUser',
+ $m->connect('api/statuses/home_timeline.:format',
+ array('action' => 'ApiTimelineHome',
'format' => '(xml|json|rss|atom|as)'));
$m->connect('api/statuses/user_timeline/:id.:format',
'id' => Nickname::INPUT_FMT,
'format' => '(xml|json|rss|atom|as)'));
- $m->connect('api/statuses/mentions.:format',
- array('action' => 'ApiTimelineMentions',
+ $m->connect('api/statuses/user_timeline.:format',
+ array('action' => 'ApiTimelineUser',
'format' => '(xml|json|rss|atom|as)'));
$m->connect('api/statuses/mentions/:id.:format',
'id' => Nickname::INPUT_FMT,
'format' => '(xml|json|rss|atom|as)'));
- $m->connect('api/statuses/replies.:format',
+ $m->connect('api/statuses/mentions.:format',
array('action' => 'ApiTimelineMentions',
'format' => '(xml|json|rss|atom|as)'));
'id' => Nickname::INPUT_FMT,
'format' => '(xml|json|rss|atom|as)'));
+ $m->connect('api/statuses/replies.:format',
+ array('action' => 'ApiTimelineMentions',
+ 'format' => '(xml|json|rss|atom|as)'));
+
$m->connect('api/statuses/retweeted_by_me.:format',
array('action' => 'ApiTimelineRetweetedByMe',
'format' => '(xml|json|atom|as)'));
array('action' => 'ApiTimelineRetweetsOfMe',
'format' => '(xml|json|atom|as)'));
- $m->connect('api/statuses/friends.:format',
- array('action' => 'ApiUserFriends',
- 'format' => '(xml|json)'));
-
$m->connect('api/statuses/friends/:id.:format',
array('action' => 'ApiUserFriends',
'id' => Nickname::INPUT_FMT,
'format' => '(xml|json)'));
- $m->connect('api/statuses/followers.:format',
- array('action' => 'ApiUserFollowers',
+ $m->connect('api/statuses/friends.:format',
+ array('action' => 'ApiUserFriends',
'format' => '(xml|json)'));
$m->connect('api/statuses/followers/:id.:format',
'id' => Nickname::INPUT_FMT,
'format' => '(xml|json)'));
- $m->connect('api/statuses/show.:format',
- array('action' => 'ApiStatusesShow',
- 'format' => '(xml|json|atom)'));
+ $m->connect('api/statuses/followers.:format',
+ array('action' => 'ApiUserFollowers',
+ 'format' => '(xml|json)'));
$m->connect('api/statuses/show/:id.:format',
array('action' => 'ApiStatusesShow',
'id' => '[0-9]+',
'format' => '(xml|json|atom)'));
+ $m->connect('api/statuses/show.:format',
+ array('action' => 'ApiStatusesShow',
+ 'format' => '(xml|json|atom)'));
+
$m->connect('api/statuses/update.:format',
array('action' => 'ApiStatusesUpdate',
'format' => '(xml|json)'));
- $m->connect('api/statuses/destroy.:format',
+ $m->connect('api/statuses/destroy/:id.:format',
array('action' => 'ApiStatusesDestroy',
+ 'id' => '[0-9]+',
'format' => '(xml|json)'));
- $m->connect('api/statuses/destroy/:id.:format',
+ $m->connect('api/statuses/destroy.:format',
array('action' => 'ApiStatusesDestroy',
- 'id' => '[0-9]+',
'format' => '(xml|json)'));
$m->connect('api/statuses/retweet/:id.:format',
// users
- $m->connect('api/users/show.:format',
+ $m->connect('api/users/show/:id.:format',
array('action' => 'ApiUserShow',
+ 'id' => Nickname::INPUT_FMT,
'format' => '(xml|json)'));
- $m->connect('api/users/show/:id.:format',
+ $m->connect('api/users/show.:format',
array('action' => 'ApiUserShow',
- 'id' => Nickname::INPUT_FMT,
'format' => '(xml|json)'));
$m->connect('api/users/profile_image/:screen_name.:format',
array('action' => 'ApiFriendshipsExists',
'format' => '(xml|json)'));
- $m->connect('api/friendships/create.:format',
+ $m->connect('api/friendships/create/:id.:format',
array('action' => 'ApiFriendshipsCreate',
+ 'id' => Nickname::INPUT_FMT,
'format' => '(xml|json)'));
- $m->connect('api/friendships/destroy.:format',
- array('action' => 'ApiFriendshipsDestroy',
- 'format' => '(xml|json)'));
-
- $m->connect('api/friendships/create/:id.:format',
+ $m->connect('api/friendships/create.:format',
array('action' => 'ApiFriendshipsCreate',
- 'id' => Nickname::INPUT_FMT,
'format' => '(xml|json)'));
$m->connect('api/friendships/destroy/:id.:format',
'id' => Nickname::INPUT_FMT,
'format' => '(xml|json)'));
+ $m->connect('api/friendships/destroy.:format',
+ array('action' => 'ApiFriendshipsDestroy',
+ 'format' => '(xml|json)'));
+
// Social graph
$m->connect('api/friends/ids/:id.:format',
// favorites
- $m->connect('api/favorites.:format',
+ $m->connect('api/favorites/:id.:format',
array('action' => 'ApiTimelineFavorites',
+ 'id' => Nickname::INPUT_FMT,
'format' => '(xml|json|rss|atom|as)'));
- $m->connect('api/favorites/:id.:format',
+ $m->connect('api/favorites.:format',
array('action' => 'ApiTimelineFavorites',
- 'id' => Nickname::INPUT_FMT,
'format' => '(xml|json|rss|atom|as)'));
$m->connect('api/favorites/create/:id.:format',
'format' => '(xml|json)'));
// blocks
- $m->connect('api/blocks/create.:format',
- array('action' => 'ApiBlockCreate',
- 'format' => '(xml|json)'));
-
$m->connect('api/blocks/create/:id.:format',
array('action' => 'ApiBlockCreate',
'id' => Nickname::INPUT_FMT,
'format' => '(xml|json)'));
- $m->connect('api/blocks/destroy.:format',
- array('action' => 'ApiBlockDestroy',
+ $m->connect('api/blocks/create.:format',
+ array('action' => 'ApiBlockCreate',
'format' => '(xml|json)'));
$m->connect('api/blocks/destroy/:id.:format',
array('action' => 'ApiBlockDestroy',
'id' => Nickname::INPUT_FMT,
'format' => '(xml|json)'));
+
+ $m->connect('api/blocks/destroy.:format',
+ array('action' => 'ApiBlockDestroy',
+ 'format' => '(xml|json)'));
+
// help
$m->connect('api/help/test.:format',
'id' => Nickname::INPUT_FMT,
'format' => '(xml|json|rss|atom|as)'));
- $m->connect('api/statusnet/groups/show.:format',
- array('action' => 'ApiGroupShow',
- 'format' => '(xml|json)'));
-
$m->connect('api/statusnet/groups/show/:id.:format',
array('action' => 'ApiGroupShow',
'id' => Nickname::INPUT_FMT,
'format' => '(xml|json)'));
- $m->connect('api/statusnet/groups/join.:format',
- array('action' => 'ApiGroupJoin',
- 'id' => Nickname::INPUT_FMT,
+ $m->connect('api/statusnet/groups/show.:format',
+ array('action' => 'ApiGroupShow',
'format' => '(xml|json)'));
$m->connect('api/statusnet/groups/join/:id.:format',
array('action' => 'ApiGroupJoin',
'format' => '(xml|json)'));
- $m->connect('api/statusnet/groups/leave.:format',
- array('action' => 'ApiGroupLeave',
+ $m->connect('api/statusnet/groups/join.:format',
+ array('action' => 'ApiGroupJoin',
'id' => Nickname::INPUT_FMT,
'format' => '(xml|json)'));
array('action' => 'ApiGroupLeave',
'format' => '(xml|json)'));
+ $m->connect('api/statusnet/groups/leave.:format',
+ array('action' => 'ApiGroupLeave',
+ 'id' => Nickname::INPUT_FMT,
+ 'format' => '(xml|json)'));
+
$m->connect('api/statusnet/groups/is_member.:format',
array('action' => 'ApiGroupIsMember',
'format' => '(xml|json)'));
- $m->connect('api/statusnet/groups/list.:format',
+ $m->connect('api/statusnet/groups/list/:id.:format',
array('action' => 'ApiGroupList',
+ 'id' => Nickname::INPUT_FMT,
'format' => '(xml|json|rss|atom)'));
- $m->connect('api/statusnet/groups/list/:id.:format',
+ $m->connect('api/statusnet/groups/list.:format',
array('action' => 'ApiGroupList',
- 'id' => Nickname::INPUT_FMT,
'format' => '(xml|json|rss|atom)'));
$m->connect('api/statusnet/groups/list_all.:format',
array('action' => 'ApiGroupListAll',
'format' => '(xml|json|rss|atom)'));
- $m->connect('api/statusnet/groups/membership.:format',
+ $m->connect('api/statusnet/groups/membership/:id.:format',
array('action' => 'ApiGroupMembership',
+ 'id' => Nickname::INPUT_FMT,
'format' => '(xml|json)'));
- $m->connect('api/statusnet/groups/membership/:id.:format',
+ $m->connect('api/statusnet/groups/membership.:format',
array('action' => 'ApiGroupMembership',
- 'id' => Nickname::INPUT_FMT,
'format' => '(xml|json)'));
$m->connect('api/statusnet/groups/create.:format',
array('action' => 'ApiListSubscriptions',
'user' => '[a-zA-Z0-9]+',
'format' => '(xml|json)'));
- $m->connect('api/lists.:format',
- array('action' => 'ApiLists',
- 'format' => '(xml|json)'));
- $m->connect('api/:user/lists.:format',
+ $m->connect('api/lists.:format',
array('action' => 'ApiLists',
- 'user' => '[a-zA-Z0-9]+',
'format' => '(xml|json)'));
$m->connect('api/:user/lists/:id.:format',
'id' => '[a-zA-Z0-9]+',
'format' => '(xml|json)'));
+ $m->connect('api/:user/lists.:format',
+ array('action' => 'ApiLists',
+ 'user' => '[a-zA-Z0-9]+',
+ 'format' => '(xml|json)'));
+
$m->connect('api/:user/lists/:id/statuses.:format',
array('action' => 'ApiTimelineList',
'user' => '[a-zA-Z0-9]+',
'id' => '[a-zA-Z0-9]+',
'format' => '(xml|json|rss|atom)'));
- $m->connect('api/:user/:list_id/members.:format',
- array('action' => 'ApiListMembers',
+ $m->connect('api/:user/:list_id/members/:id.:format',
+ array('action' => 'ApiListMember',
'user' => '[a-zA-Z0-9]+',
'list_id' => '[a-zA-Z0-9]+',
+ 'id' => '[a-zA-Z0-9]+',
'format' => '(xml|json)'));
- $m->connect('api/:user/:list_id/subscribers.:format',
- array('action' => 'ApiListSubscribers',
+ $m->connect('api/:user/:list_id/members.:format',
+ array('action' => 'ApiListMembers',
'user' => '[a-zA-Z0-9]+',
'list_id' => '[a-zA-Z0-9]+',
'format' => '(xml|json)'));
- $m->connect('api/:user/:list_id/members/:id.:format',
- array('action' => 'ApiListMember',
+ $m->connect('api/:user/:list_id/subscribers/:id.:format',
+ array('action' => 'ApiListSubscriber',
'user' => '[a-zA-Z0-9]+',
'list_id' => '[a-zA-Z0-9]+',
'id' => '[a-zA-Z0-9]+',
'format' => '(xml|json)'));
- $m->connect('api/:user/:list_id/subscribers/:id.:format',
- array('action' => 'ApiListSubscriber',
+ $m->connect('api/:user/:list_id/subscribers.:format',
+ array('action' => 'ApiListSubscribers',
'user' => '[a-zA-Z0-9]+',
'list_id' => '[a-zA-Z0-9]+',
- 'id' => '[a-zA-Z0-9]+',
'format' => '(xml|json)'));
// Tags
{
$td = $this->getTableDef($table);
- foreach ($td->columns as $cd) {
- if ($cd->name == $column) {
- return $cd;
+ if (!empty($td) && !empty($td->columns)) {
+ foreach ($td->columns as $cd) {
+ if ($cd->name == $column) {
+ return $cd;
+ }
}
}
$uniques = $this->diffArrays($old, $def, 'unique keys');
$indexes = $this->diffArrays($old, $def, 'indexes');
$foreign = $this->diffArrays($old, $def, 'foreign keys');
+ $fulltext = $this->diffArrays($old, $def, 'fulltext indexes');
// Drop any obsolete or modified indexes ahead...
foreach ($indexes['del'] + $indexes['mod'] as $indexName) {
$this->appendDropIndex($statements, $tableName, $indexName);
}
+ // Drop any obsolete or modified fulltext indexes ahead...
+ foreach ($fulltext['del'] + $fulltext['mod'] as $indexName) {
+ $this->appendDropIndex($statements, $tableName, $indexName);
+ }
+
// For efficiency, we want this all in one
// query, instead of using our methods.
$this->appendCreateIndex($statements, $tableName, $indexName, $def['indexes'][$indexName]);
}
+ foreach ($fulltext['mod'] + $fulltext['add'] as $indexName) {
+ $colDef = $def['fulltext indexes'][$indexName];
+ $this->appendCreateFulltextIndex($statements, $tableName, $indexName, $colDef);
+ }
+
return $statements;
}
class TaggedProfileNoticeStream extends ScopingNoticeStream
{
- function __construct($profile, $tag, $userProfile)
+ function __construct($profile, $tag, $userProfile=-1)
{
if (is_int($userProfile) && $userProfile == -1) {
$userProfile = Profile::current();
class ActivityPlugin extends Plugin
{
const VERSION = '0.1';
- const SOURCE = 'system';
+ const SOURCE = 'activity';
// Flags to switch off certain activity notices
public $StartFollowUser = true;
function _showLogo($action)
{
$action->elementStart('address', 'vcard');
+ if (common_config('singleuser', 'enabled')) {
+ $user = User::singleUser();
+ $url = common_local_url('showstream', array('nickname' => $user->nickname));
+ } else {
+ $url = common_local_url('public');
+ }
+
$action->elementStart('a', array('class' => 'url home bookmark',
- 'href' => common_local_url('public')));
+ 'href' => $url));
+
if (common_config('site', 'mobilelogo') ||
file_exists(Theme::file('logo.png')) ||
file_exists(Theme::file('mobilelogo.png'))) {
// Discovery actions
$m->connect('main/ownerxrd',
array('action' => 'ownerxrd'));
- $m->connect('main/ostatus',
- array('action' => 'ostatusinit'));
$m->connect('main/ostatustag',
array('action' => 'ostatustag'));
$m->connect('main/ostatustag?nickname=:nickname',
array('action' => 'ostatustag'), array('nickname' => '[A-Za-z0-9_-]+'));
- $m->connect('main/ostatus?nickname=:nickname',
+ $m->connect('main/ostatus/nickname/:nickname',
array('action' => 'ostatusinit'), array('nickname' => '[A-Za-z0-9_-]+'));
- $m->connect('main/ostatus?group=:group',
+ $m->connect('main/ostatus/group/:group',
array('action' => 'ostatusinit'), array('group' => '[A-Za-z0-9_-]+'));
- $m->connect('main/ostatus?peopletag=:peopletag&tagger=:tagger',
+ $m->connect('main/ostatus/peopletag/:peopletag/tagger/:tagger',
array('action' => 'ostatusinit'), array('tagger' => '[A-Za-z0-9_-]+',
'peopletag' => '[A-Za-z0-9_-]+'));
+ $m->connect('main/ostatus',
+ array('action' => 'ostatusinit'));
// Remote subscription actions
$m->connect('main/ostatussub',
if (empty($cur)) {
$widget->out->elementStart('li', 'entity_subscribe');
- $profile = $peopletag->getTagger();
+
$url = common_local_url('ostatusinit',
array('group' => $group->nickname));
$widget->out->element('a', array('href' => $url,
- 'class' => 'entity_remote_subscribe'),
+ 'class' => 'entity_remote_subscribe'),
// TRANS: Link to subscribe to a remote entity.
_m('Subscribe'));
* deny the join.
*
* @param User_group $group
- * @param User $user
+ * @param Profile $profile
*
* @return mixed hook return value
*/
- function onStartJoinGroup($group, $user)
+ function onStartJoinGroup($group, $profile)
{
$oprofile = Ostatus_profile::staticGet('group_id', $group->id);
if ($oprofile) {
// NOTE: we don't use Group_member::asActivity() since that record
// has not yet been created.
- $member = Profile::staticGet($user->id);
-
$act = new Activity();
$act->id = TagURI::mint('join:%d:%d:%s',
- $member->id,
+ $profile->id,
$group->id,
common_date_iso8601(time()));
- $act->actor = ActivityObject::fromProfile($member);
+ $act->actor = ActivityObject::fromProfile($profile);
$act->verb = ActivityVerb::JOIN;
$act->object = $oprofile->asActivityObject();
// TRANS: Success message for subscribe to group attempt through OStatus.
// TRANS: %1$s is the member name, %2$s is the subscribed group's name.
$act->content = sprintf(_m('%1$s has joined group %2$s.'),
- $member->getBestName(),
+ $profile->getBestName(),
$oprofile->getBestName());
- if ($oprofile->notifyActivity($act, $member)) {
+ if ($oprofile->notifyActivity($act, $profile)) {
return true;
} else {
$oprofile->garbageCollect();
* it'll be left with a stray membership record.
*
* @param User_group $group
- * @param Profile $user
+ * @param Profile $profile
*
* @return mixed hook return value
*/
- function onEndLeaveGroup($group, $user)
+ function onEndLeaveGroup($group, $profile)
{
$oprofile = Ostatus_profile::staticGet('group_id', $group->id);
if ($oprofile) {
// Drop the PuSH subscription if there are no other subscribers.
$oprofile->garbageCollect();
- $member = Profile::staticGet($user->id);
+ $member = $profile;
$act = new Activity();
$act->id = TagURI::mint('leave:%d:%d:%s',
$this->notice = $notice;
$this->user = User::staticGet('id', $notice->profile_id);
+ try {
+ $profile = $this->notice->getProfile();
+ } catch (Exception $e) {
+ common_log(LOG_ERR, "Can't get profile for notice; skipping: " . $e->getMessage());
+ return true;
+ }
+
$this->pushUser();
foreach ($notice->getGroups() as $group) {
// root url from page output
$action->elementStart('address');
+
+ if (common_config('singleuser', 'enabled')) {
+ $user = User::singleUser();
+ $url = common_local_url('showstream', array('nickname' => $user->nickname));
+ } else {
+ $url = common_local_url('public');
+ }
+
$action->element('a', array('class' => 'url',
- 'href' => common_local_url('public')),
+ 'href' => $url),
'');
+
$action->elementEnd('address');
$action->showContentBlock();
break;
case 'tag':
$tag = $action->trimmed('tag');
- if (empty($tag)) {
+ if (!empty($tag)) {
$arg1 = $tag;
} else {
$this->log(LOG_NOTICE, "Unexpected 'tag' action without tag argument");
$m->connect('search/:search/unsubscribe',
array('action' => 'searchunsub'),
array('search' => Router::REGEX_TAG));
-
$m->connect(':nickname/search-subscriptions',
array('action' => 'searchsubs'),
array('nickname' => Nickname::DISPLAY_FMT));
$id = $this->menuItemID($actionName, $args);
}
- // Add 'q' as a search param, not part of the url path
-
- $url = common_local_url($actionName, array(), $args);
+ if ($actionName == 'noticesearch') {
+ // Add 'q' as a search param, not part of the url path
+ $url = common_local_url($actionName, array(), $args);
+ } else {
+ $url = common_local_url($actionName, $args);
+ }
$this->out->menuItem($url,
$label,
$m->connect('sitemapindex.xml',
array('action' => 'sitemapindex'));
- $m->connect('/notice-sitemap-:year-:month-:day-:index.xml',
+ $m->connect('notice-sitemap-:year-:month-:day-:index.xml',
array('action' => 'noticesitemap'),
array('year' => '[0-9]{4}',
'month' => '[01][0-9]',
'day' => '[0123][0-9]',
'index' => '[1-9][0-9]*'));
- $m->connect('/user-sitemap-:year-:month-:day-:index.xml',
+ $m->connect('user-sitemap-:year-:month-:day-:index.xml',
array('action' => 'usersitemap'),
array('year' => '[0-9]{4}',
'month' => '[01][0-9]',
null, false),
new ColumnDef('modified', 'timestamp')));
- $userCreated = $schema->getColumnDef('user', 'created');
-
- if (empty($userCreated) || $userCreated->key != 'MUL') {
- $schema->createIndex('user', 'created');
- }
-
return true;
}
/**
* Filter group joins to see if they're coming too fast.
*
- * @param Group $group The group being joined
- * @param User $user The user joining
+ * @param Group $group The group being joined
+ * @param Profile $profile The profile joining
*
* @return boolean hook value
*/
- function onStartJoinGroup($group, $user)
+ function onStartJoinGroup($group, $profile)
{
foreach ($this->groupLimits as $seconds => $limit) {
- $mem = $this->_getNthMem($user, $limit);
+ $mem = $this->_getNthMem($profile, $limit);
if (!empty($mem)) {
$jointime = strtotime($mem->created);
/**
* Get the Nth most recent group membership for this user
*
- * @param User $user The user to get memberships for
- * @param integer $n How far to count back
+ * @param Profile $profile The user to get memberships for
+ * @param integer $n How far to count back
*
* @return Group_member a membership or null
*/
- private function _getNthMem($user, $n)
+ private function _getNthMem($profile, $n)
{
$mem = new Group_member();
- $mem->profile_id = $user->id;
+ $mem->profile_id = $profile->id;
$mem->orderBy('created DESC');
$mem->limit($n - 1, 1);
+++ /dev/null
-<?php
-/**
- * Plugin to render old skool templates
- *
- * Captures rendered parts from the output buffer, passes them through a template file: tpl/index.html
- * Adds an API method at index.php/template/update which lets you overwrite the template file
- * Requires username/password and a single POST parameter called "template"
- * The method is disabled unless the user is #1, the first user of the system
- *
- * @category Plugin
- * @package StatusNet
- * @author Brian Hendrickson <brian@megapump.com>
- * @copyright 2009 Megapump, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://megapump.com/
- */
-
-if (!defined('STATUSNET')) {
- exit(1);
-}
-
-define('TEMPLATEPLUGIN_VERSION', '0.1');
-
-class TemplatePlugin extends Plugin {
- var $blocks = array();
-
- function __construct() {
- parent::__construct();
- }
-
- // capture the RouterInitialized event
- // and connect a new API method
- // for updating the template
- function onRouterInitialized( $m ) {
- $m->connect( 'template/update', array(
- 'action' => 'template',
- ));
- }
-
- /**
- <%styles%>
- <%scripts%>
- <%search%>
- <%feeds%>
- <%description%>
- <%head%>
- */
- function onStartShowHead( &$act ) {
- $this->clear_xmlWriter($act);
- $act->extraHead();
- $this->blocks['head'] = $act->xw->flush();
- $act->showStylesheets();
- $this->blocks['styles'] = $act->xw->flush();
- $act->showScripts();
- $this->blocks['scripts'] = $act->xw->flush();
- $act->showFeeds();
- $this->blocks['feeds'] = $act->xw->flush();
- $act->showOpenSearch();
- $this->blocks['search'] = $act->xw->flush();
- $act->showDescription();
- $this->blocks['description'] = $act->xw->flush();
- return false;
- }
-
- // <%bodytext%>
- function onStartShowContentBlock( &$act ) {
- $this->clear_xmlWriter($act);
- return true;
- }
- function onEndShowContentBlock( &$act ) {
- $this->blocks['bodytext'] = $act->xw->flush();
- }
-
- // <%localnav%>
- function onStartShowLocalNavBlock( &$act ) {
- $this->clear_xmlWriter($act);
- return true;
- }
- function onEndShowLocalNavBlock( &$act ) {
- $this->blocks['localnav'] = $act->xw->flush();
- }
-
- // <%export%>
- function onStartShowExportData( &$act ) {
- $this->clear_xmlWriter($act);
- return true;
- }
- function onEndShowExportData( &$act ) {
- $this->blocks['export'] = $act->xw->flush();
- }
-
- // <%subscriptions%>
- // <%subscribers%>
- // <%groups%>
- // <%statistics%>
- // <%cloud%>
- // <%groupmembers%>
- // <%groupstatistics%>
- // <%groupcloud%>
- // <%popular%>
- // <%groupsbyposts%>
- // <%featuredusers%>
- // <%groupsbymembers%>
- function onStartShowSections( &$act ) {
- global $action;
- $this->clear_xmlWriter($act);
- switch ($action) {
- case "showstream":
- $act->showSubscriptions();
- $this->blocks['subscriptions'] = $act->xw->flush();
- $act->showSubscribers();
- $this->blocks['subscribers'] = $act->xw->flush();
- $act->showGroups();
- $this->blocks['groups'] = $act->xw->flush();
- $act->showStatistics();
- $this->blocks['statistics'] = $act->xw->flush();
- $cloud = new PersonalTagCloudSection($act, $act->user);
- $cloud->show();
- $this->blocks['cloud'] = $act->xw->flush();
- break;
- case "showgroup":
- $act->showMembers();
- $this->blocks['groupmembers'] = $act->xw->flush();
- $act->showStatistics();
- $this->blocks['groupstatistics'] = $act->xw->flush();
- $cloud = new GroupTagCloudSection($act, $act->group);
- $cloud->show();
- $this->blocks['groupcloud'] = $act->xw->flush();
- break;
- case "public":
- $pop = new PopularNoticeSection($act);
- $pop->show();
- $this->blocks['popular'] = $act->xw->flush();
- $gbp = new GroupsByPostsSection($act);
- $gbp->show();
- $this->blocks['groupsbyposts'] = $act->xw->flush();
- $feat = new FeaturedUsersSection($act);
- $feat->show();
- $this->blocks['featuredusers'] = $act->xw->flush();
- break;
- case "groups":
- $gbp = new GroupsByPostsSection($act);
- $gbp->show();
- $this->blocks['groupsbyposts'] = $act->xw->flush();
- $gbm = new GroupsByMembersSection($act);
- $gbm->show();
- $this->blocks['groupsbymembers'] = $act->xw->flush();
- break;
- }
- return false;
- }
-
- // <%logo%>
- // <%nav%>
- // <%notice%>
- // <%noticeform%>
- function onStartShowHeader( &$act ) {
- $this->clear_xmlWriter($act);
- $act->showLogo();
- $this->blocks['logo'] = $act->xw->flush();
- $act->showPrimaryNav();
- $this->blocks['nav'] = $act->xw->flush();
- $act->showSiteNotice();
- $this->blocks['notice'] = $act->xw->flush();
- if (common_logged_in()) {
- $act->showNoticeForm();
- } else {
- $act->showAnonymousMessage();
- }
- $this->blocks['noticeform'] = $act->xw->flush();
- return false;
- }
-
- // <%secondarynav%>
- // <%licenses%>
- function onStartShowFooter( &$act ) {
- $this->clear_xmlWriter($act);
- $act->showSecondaryNav();
- $this->blocks['secondarynav'] = $act->xw->flush();
- $act->showLicenses();
- $this->blocks['licenses'] = $act->xw->flush();
- return false;
- }
-
- // capture the EndHTML event
- // and include the template
- function onEndEndHTML($act) {
- global $action, $tags;
-
- // set the action and title values
- $vars = array(
- 'action'=>$action,
- 'title'=>$act->title(). " - ". common_config('site', 'name')
- );
-
- // use the PHP template
- // unless statusnet config:
- // $config['template']['mode'] = 'html';
- if (!(common_config('template', 'mode') == 'html')) {
- $tpl_file = $this->templateFolder() . '/index.php';
- $tags = array_merge($vars,$this->blocks);
- include $tpl_file;
- return;
- }
-
- $tpl_file = $this->templateFolder() . '/index.html';
-
- // read the static template
- $output = file_get_contents( $tpl_file );
-
- $tags = array();
-
- // get a list of the <%tags%> in the template
- $pattern='/<%([a-z]+)%>/';
-
- if ( 1 <= preg_match_all( $pattern, $output, $found ))
- $tags[] = $found;
-
- // for each found tag, set its value from the rendered blocks
- foreach( $tags[0][1] as $pos=>$tag ) {
- if (isset($this->blocks[$tag]))
- $vars[$tag] = $this->blocks[$tag];
-
- // didn't find a block for the tag
- elseif (!isset($vars[$tag]))
- $vars[$tag] = '';
- }
-
- // replace the tags in the template
- foreach( $vars as $key=>$val )
- $output = str_replace( '<%'.$key.'%>', $val, $output );
-
- echo $output;
-
- return true;
-
- }
- function templateFolder() {
- return 'tpl';
- }
-
- // catching the StartShowHTML event to halt the rendering
- function onStartShowHTML( &$act ) {
- $this->clear_xmlWriter($act);
- return true;
- }
-
- // clear the xmlWriter
- function clear_xmlWriter( &$act ) {
- $act->xw->openMemory();
- $act->xw->setIndent(true);
- }
-}
-
-/**
- * Action for updating the template remotely
- *
- * "template/update" -- a POST method that requires a single
- * parameter "template", containing the new template code
- *
- * @category Plugin
- * @package StatusNet
- * @author Brian Hendrickson <brian@megapump.com>
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://megapump.com/
- *
- */
-class TemplateAction extends Action
-{
- function prepare($args) {
- parent::prepare($args);
- return true;
- }
-
- function handle($args) {
- parent::handle($args);
-
- if (!isset($_SERVER['PHP_AUTH_USER'])) {
- // not authenticated, show login form
- header('WWW-Authenticate: Basic realm="StatusNet API"');
-
- // cancelled the browser login form
- $this->clientError(_m('Authentication error!'), $code = 401);
- } else {
- $nick = $_SERVER['PHP_AUTH_USER'];
- $pass = $_SERVER['PHP_AUTH_PW'];
-
- // check username and password
- $user = common_check_user($nick,$pass);
-
- if ($user) {
- // verify that user is admin
- if (!($user->id == 1))
- $this->clientError(_m('Only User #1 can update the template.'), $code = 401);
-
- // open the old template
- $tpl_file = $this->templateFolder() . '/index.html';
- $fp = fopen( $tpl_file, 'w+' );
-
- // overwrite with the new template
- fwrite($fp, $this->arg('template'));
- fclose($fp);
-
- header('HTTP/1.1 200 OK');
- header('Content-type: text/plain');
- print "Template Updated!";
- } else {
- // bad username and password
- $this->clientError(_m('Authentication error!'), $code = 401);
- }
-
- }
- }
- function onPluginVersion(&$versions)
- {
- $versions[] = array('name' => 'Template',
- 'version' => TEMPLATEPLUGIN_VERSION,
- 'author' => 'Brian Hendrickson',
- 'homepage' => 'http://status.net/wiki/Plugin:Template',
- 'rawdescription' =>
- // TRANS: Plugin description.
- _m('Use an HTML template for Web output.'));
- return true;
- }
-
-}
-
-/**
- * Function for retrieving a statusnet display section
- *
- * requires one parameter, the name of the section
- * section names are listed in the comments of the TemplatePlugin class
- *
- * @category Plugin
- * @package StatusNet
- * @author Brian Hendrickson <brian@megapump.com>
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://megapump.com/
- *
- */
-function section($tagname) {
- global $tags;
- if (isset($tags[$tagname]))
- return $tags[$tagname];
-}
$options['scope'] |= Notice::SITE_SCOPE;
}
- $notice = Notice::saveNew($user->id, $content, 'system', $options);
+ $notice = Notice::saveNew($user->id, $content, 'createsim', $options);
}
function newSub($i)
font-size:150%;
}
-#content .notice-source-system div.entry-title, .notice-source-system div.entry-content {
+#content .notice-source-activity div.entry-title, .notice-source-activity div.entry-content {
margin-left: 0;
}
-#content .notice-source-system div.entry-title {
+#content .notice-source-activity div.entry-title {
font-style: italic;
min-height: 0;
}
-#content .notice-source-system .notice div.entry-title {
+#content .notice-source-activity .notice div.entry-title {
font-style: normal;
}
+++ /dev/null
-<?php echo '<?';?>xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
- <head>
- <title><?php echo section('title'); ?></title>
- <?php echo section('styles'); ?>
- <?php echo section('scripts'); ?>
- <?php echo section('search'); ?>
- <?php echo section('feeds'); ?>
- <?php echo section('description'); ?>
- <?php echo section('head'); ?>
- </head>
- <body id="<?php echo section('action'); ?>">
- <div id="wrap">
- <div id="header">
- <?php echo section('logo'); ?>
- <?php echo section('nav'); ?>
- <?php echo section('notice'); ?>
- <?php echo section('noticeform'); ?>
- </div>
- <div id="core">
- <?php echo section('localnav'); ?>
- <?php echo section('bodytext'); ?>
- <div id="aside_primary" class="aside">
- <?php echo section('export'); ?>
- <?php echo section('subscriptions'); ?>
- <?php echo section('subscribers'); ?>
- <?php echo section('groups'); ?>
- <?php echo section('statistics'); ?>
- <?php echo section('cloud'); ?>
- <?php echo section('groupmembers'); ?>
- <?php echo section('groupstatistics'); ?>
- <?php echo section('groupcloud'); ?>
- <?php echo section('popular'); ?>
- <?php echo section('groupsbyposts'); ?>
- <?php echo section('featuredusers'); ?>
- <?php echo section('groupsbymembers'); ?>
- </div>
- </div>
- <div id="footer">
- <?php echo section('secondarynav'); ?>
- <?php echo section('licenses'); ?>
- </div>
- </div>
- </body>
- </html>