Commit bdd9f6ce authored by Sean Murphy's avatar Sean Murphy

Merge commit 'upstream/0.7.x' into 0.7.x

parents f6705f06 32744124
......@@ -9,3 +9,4 @@ dataobject.ini
*.bak
*.orig
*.rej
.#*
InitializePlugin: a chance to initialize a plugin in a complete
environment
CleanupPlugin: a chance to cleanup a plugin at the end of a program
StartPrimaryNav: Showing the primary nav menu
- $action: the current action
EndPrimaryNav: At the end of the primary nav menu
- $action: the current action
StartSecondaryNav: Showing the secondary nav menu
- $action: the current action
EndSecondaryNav: At the end of the secondary nav menu
- $action: the current action
StartShowScripts: Showing JavaScript links
- $action: the current action
EndShowScripts: End showing JavaScript links; good place to add custom
links like Google Analytics
- $action: the current action
StartShowJQueryScripts: Showing JQuery script links (use this to link to e.g. Google mirrors)
- $action: the current action
EndShowJQueryScripts: End showing JQuery script links
- $action: the current action
StartShowLaconicaScripts: Showing Laconica script links (use this to link to a CDN or something)
- $action: the current action
EndShowLaconicaScripts: End showing Laconica script links
- $action: the current action
StartShowSections: Start the list of sections in the sidebar
- $action: the current action
EndShowSections: End the list of sections in the sidebar
- $action: the current action
......@@ -191,13 +191,13 @@ class EditgroupAction extends Action
array('http', 'https')))) {
$this->showForm(_('Homepage is not a valid URL.'));
return;
} else if (!is_null($fullname) && strlen($fullname) > 255) {
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
$this->showForm(_('Full name is too long (max 255 chars).'));
return;
} else if (!is_null($description) && strlen($description) > 140) {
} else if (!is_null($description) && mb_strlen($description) > 140) {
$this->showForm(_('description is too long (max 140 chars).'));
return;
} else if (!is_null($location) && strlen($location) > 255) {
} else if (!is_null($location) && mb_strlen($location) > 255) {
$this->showForm(_('Location is too long (max 255 chars).'));
return;
}
......
......@@ -71,13 +71,13 @@ class FacebookinviteAction extends FacebookAction
common_config('site', 'name')));
$this->element('p', null, _('Invitations have been sent to the following users:'));
$friend_ids = $_POST['ids']; // XXX: Hmm... is this the best way to acces the list?
$friend_ids = $_POST['ids']; // XXX: Hmm... is this the best way to access the list?
$this->elementStart('ul', array('id' => 'facebook-friends'));
foreach ($friend_ids as $friend) {
$this->elementStart('li');
$this->element('fb:profile-pic', array('uid' => $friend));
$this->element('fb:profile-pic', array('uid' => $friend, 'size' => 'square'));
$this->element('fb:name', array('uid' => $friend,
'capitalize' => 'true'));
$this->elementEnd('li');
......@@ -92,6 +92,12 @@ class FacebookinviteAction extends FacebookAction
// Get a list of users who are already using the app for exclusion
$exclude_ids = $this->facebook->api_client->friends_getAppUsers();
$exclude_ids_csv = null;
// fbml needs these as a csv string, not an array
if ($exclude_ids) {
$exclude_ids_csv = implode(',', $exclude_ids);
}
$content = sprintf(_('You have been invited to %s'), common_config('site', 'name')) .
htmlentities('<fb:req-choice url="' . $this->app_uri . '" label="Add"/>');
......@@ -103,10 +109,17 @@ class FacebookinviteAction extends FacebookAction
'content' => $content));
$this->hidden('invite', 'true');
$actiontext = sprintf(_('Invite your friends to use %s'), common_config('site', 'name'));
$this->element('fb:multi-friend-selector', array('showborder' => 'false',
'actiontext' => $actiontext,
'exclude_ids' => implode(',', $exclude_ids),
'bypass' => 'cancel'));
$multi_params = array('showborder' => 'false');
$multi_params['actiontext'] = $actiontext;
if ($exclude_ids_csv) {
$multi_params['exclude_ids'] = $exclude_ids_csv;
}
$multi_params['bypass'] = 'cancel';
$this->element('fb:multi-friend-selector', $multi_params);
$this->elementEnd('fb:request-form');
......
......@@ -242,7 +242,7 @@ class FinishopenidloginAction extends Action
}
}
if ($sreg['fullname'] && strlen($sreg['fullname']) <= 255) {
if ($sreg['fullname'] && mb_strlen($sreg['fullname']) <= 255) {
$fullname = $sreg['fullname'];
}
......
......@@ -142,13 +142,13 @@ class NewgroupAction extends Action
array('http', 'https')))) {
$this->showForm(_('Homepage is not a valid URL.'));
return;
} else if (!is_null($fullname) && strlen($fullname) > 255) {
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
$this->showForm(_('Full name is too long (max 255 chars).'));
return;
} else if (!is_null($description) && strlen($description) > 140) {
} else if (!is_null($description) && mb_strlen($description) > 140) {
$this->showForm(_('description is too long (max 140 chars).'));
return;
} else if (!is_null($location) && strlen($location) > 255) {
} else if (!is_null($location) && mb_strlen($location) > 255) {
$this->showForm(_('Location is too long (max 255 chars).'));
return;
}
......
......@@ -201,7 +201,7 @@ class NewmessageAction extends Action
function showNoticeForm()
{
$message_form = new MessageForm($this, $this->to, $this->content);
$message_form = new MessageForm($this, $this->other, $this->content);
$message_form->show();
}
}
<?php
/*
* Laconica - a distributed open-source microblogging tool
* Copyright (C) 2008, Controlez-Vous, Inc.
/**
* Laconica, the distributed open-source microblogging tool
*
* This program is free software: you can redistribute it and/or modify
* Action for showing profiles self-tagged with a given tag
*
* PHP version 5
*
* LICENCE: 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.
......@@ -15,78 +18,131 @@
*
* 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/>.
*
* @category Action
* @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca>
* @author Zach Copley <zach@controlyourself.ca>
* @copyright 2009 Control Yourself, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
*/
if (!defined('LACONICA')) { exit(1); }
if (!defined('LACONICA')) {
exit(1);
}
require_once INSTALLDIR.'/lib/profilelist.php';
/**
* This class outputs a paginated list of profiles self-tagged with a given tag
*
* @category Output
* @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca>
* @author Zach Copley <zach@controlyourself.ca>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
*
* @see Action
*/
class PeopletagAction extends Action
{
var $tag = null;
var $tag = null;
var $page = null;
function handle($args)
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
{
parent::handle($args);
parent::prepare($args);
parent::prepare($argarray);
$this->tag = $this->trimmed('tag');
if (!common_valid_profile_tag($this->tag)) {
$this->clientError(sprintf(_('Not a valid people tag: %s'), $this->tag));
$this->clientError(sprintf(_('Not a valid people tag: %s'),
$this->tag));
return;
}
$this->page = $this->trimmed('page');
$this->page = ($this->arg('page')) ? $this->arg('page') : 1;
if (!$this->page) {
$this->page = 1;
}
common_set_returnto($this->selfUrl());
return true;
}
/**
* Handler method
*
* @param array $argarray is ignored since it's now passed in in prepare()
*
* @return boolean is read only action?
*/
function handle($argarray)
{
parent::handle($argarray);
$this->showPage();
}
/**
* Whips up a query to get a list of profiles based on the provided
* people tag and page, initalizes a ProfileList widget, and displays
* it to the user.
*
* @return nothing
*/
function showContent()
{
$profile = new Profile();
$offset = ($page-1)*PROFILES_PER_PAGE;
$limit = PROFILES_PER_PAGE + 1;
if (common_config('db','type') == 'pgsql') {
$offset = ($this->page - 1) * PROFILES_PER_PAGE;
$limit = PROFILES_PER_PAGE + 1;
if (common_config('db', 'type') == 'pgsql') {
$lim = ' LIMIT ' . $limit . ' OFFSET ' . $offset;
} else {
$lim = ' LIMIT ' . $offset . ', ' . $limit;
}
# XXX: memcached this
// XXX: memcached this
$qry = 'SELECT profile.* ' .
'FROM profile JOIN profile_tag ' .
'ON profile.id = profile_tag.tagger ' .
'WHERE profile_tag.tagger = profile_tag.tagged ' .
'AND tag = "%s" ' .
'ORDER BY profile_tag.modified DESC';
'ORDER BY profile_tag.modified DESC%s';
$profile->query(sprintf($qry, $this->tag, $lim));
$pl = new ProfileList($profile, null, $this);
$pl = new ProfileList($profile, null, $this);
$cnt = $pl->show();
$this->pagination($this->page > 1,
$cnt > PROFILES_PER_PAGE,
$this->page,
$this->trimmed('action'),
'peopletag',
array('tag' => $this->tag));
}
function title()
/**
* Returns the page title
*
* @return string page title
*/
function title()
{
return sprintf( _('Users self-tagged with %s - page %d'), $this->tag, $this->page);
return sprintf(_('Users self-tagged with %s - page %d'),
$this->tag, $this->page);
}
}
......@@ -198,13 +198,13 @@ class ProfilesettingsAction extends AccountSettingsAction
!Validate::uri($homepage, array('allowed_schemes' => array('http', 'https')))) {
$this->showForm(_('Homepage is not a valid URL.'));
return;
} else if (!is_null($fullname) && strlen($fullname) > 255) {
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
$this->showForm(_('Full name is too long (max 255 chars).'));
return;
} else if (!is_null($bio) && strlen($bio) > 140) {
} else if (!is_null($bio) && mb_strlen($bio) > 140) {
$this->showForm(_('Bio is too long (max 140 chars).'));
return;
} else if (!is_null($location) && strlen($location) > 255) {
} else if (!is_null($location) && mb_strlen($location) > 255) {
$this->showForm(_('Location is too long (max 255 chars).'));
return;
} else if (is_null($timezone) || !in_array($timezone, DateTimeZone::listIdentifiers())) {
......
......@@ -167,13 +167,13 @@ class RegisterAction extends Action
array('http', 'https')))) {
$this->showForm(_('Homepage is not a valid URL.'));
return;
} else if (!is_null($fullname) && strlen($fullname) > 255) {
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
$this->showForm(_('Full name is too long (max 255 chars).'));
return;
} else if (!is_null($bio) && strlen($bio) > 140) {
} else if (!is_null($bio) && mb_strlen($bio) > 140) {
$this->showForm(_('Bio is too long (max 140 chars).'));
return;
} else if (!is_null($location) && strlen($location) > 255) {
} else if (!is_null($location) && mb_strlen($location) > 255) {
$this->showForm(_('Location is too long (max 255 chars).'));
return;
} else if (strlen($password) < 6) {
......
......@@ -111,7 +111,7 @@ class ShowstreamAction extends Action
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
common_set_returnto($this->selfUrl());
return true;
}
......@@ -178,21 +178,21 @@ class ShowstreamAction extends Action
function showFeeds()
{
$this->element('link', array('rel' => 'alternate',
'type' => 'application/rss+xml',
'href' => common_local_url('userrss',
array('nickname' => $this->user->nickname)),
'title' => sprintf(_('Notice feed for %s (RSS)'),
$this->user->nickname)));
$this->element('link',
array('rel' => 'alternate',
'href' => common_local_url('api',
array('apiaction' => 'statuses',
'method' => 'user_timeline.atom',
'argument' => $this->user->nickname)),
'type' => 'application/atom+xml',
'title' => sprintf(_('Notice feed for %s (Atom)'),
$this->user->nickname)));
'type' => 'application/rss+xml',
'href' => common_local_url('userrss',
array('nickname' => $this->user->nickname)),
'title' => sprintf(_('Notice feed for %s (RSS)'),
$this->user->nickname)));
$this->element('link',
array('rel' => 'alternate',
'href' => common_local_url('api',
array('apiaction' => 'statuses',
'method' => 'user_timeline.atom',
'argument' => $this->user->nickname)),
'type' => 'application/atom+xml',
'title' => sprintf(_('Notice feed for %s (Atom)'),
$this->user->nickname)));
}
function extraHead()
......@@ -206,7 +206,7 @@ class ShowstreamAction extends Action
// for remote subscriptions etc.
$this->element('meta', array('http-equiv' => 'X-XRDS-Location',
'content' => common_local_url('xrds', array('nickname' =>
$this->user->nickname))));
$this->user->nickname))));
if ($this->profile->bio) {
$this->element('meta', array('name' => 'description',
......@@ -248,7 +248,7 @@ class ShowstreamAction extends Action
'height' => AVATAR_PROFILE_SIZE,
'alt' => $this->profile->nickname));
$this->elementEnd('dd');
$user = User::staticGet('id', $this->profile->id);
$cur = common_current_user();
if ($cur && $cur->id == $user->id) {
......@@ -256,7 +256,7 @@ class ShowstreamAction extends Action
$this->element('a', array('href' => common_local_url('avatarsettings')), _('Edit Avatar'));
$this->elementEnd('dd');
}
$this->elementEnd('dl');
$this->elementStart('dl', 'entity_nickname');
......@@ -265,7 +265,7 @@ class ShowstreamAction extends Action
$hasFN = ($this->profile->fullname) ? 'nickname url uid' : 'fn nickname url uid';
$this->element('a', array('href' => $this->profile->profileurl,
'rel' => 'me', 'class' => $hasFN),
$this->profile->nickname);
$this->profile->nickname);
$this->elementEnd('dd');
$this->elementEnd('dl');
......@@ -333,7 +333,7 @@ class ShowstreamAction extends Action
$this->elementStart('li', 'entity_edit');
$this->element('a', array('href' => common_local_url('profilesettings'),
'title' => _('Edit profile settings')),
_('Edit'));
_('Edit'));
$this->elementEnd('li');
}
......@@ -356,7 +356,7 @@ class ShowstreamAction extends Action
}
if ($cur && $cur->id != $user->id && $cur->mutuallySubscribed($user)) {
$this->elementStart('li', 'entity_send-a-message');
$this->elementStart('li', 'entity_send-a-message');
$this->element('a', array('href' => common_local_url('newmessage', array('to' => $user->id)),
'title' => _('Send a direct message to this user')),
_('Message'));
......@@ -498,7 +498,7 @@ class ShowstreamAction extends Action
$this->elementStart('dl', 'entity_member-since');
$this->element('dt', null, _('Member since'));
$this->element('dd', null, date('j M Y',
strtotime($this->profile->created)));
strtotime($this->profile->created)));
$this->elementEnd('dl');
$this->elementStart('dl', 'entity_subscriptions');
......
......@@ -56,7 +56,7 @@ class TwitapiaccountAction extends TwitterapiAction
$location = trim($this->arg('location'));
if (!is_null($location) && strlen($location) > 255) {
if (!is_null($location) && mb_strlen($location) > 255) {
// XXX: But Twitter just truncates and runs with it. -- Zach
$this->clientError(_('That\'s too long. Max notice size is 255 chars.'), 406, $apidate['content-type']);
......
......@@ -93,22 +93,22 @@ class UpdateprofileAction extends Action
}
# optional stuff
$fullname = $req->get_parameter('omb_listenee_fullname');
if ($fullname && strlen($fullname) > 255) {
if ($fullname && mb_strlen($fullname) > 255) {
$this->clientError(_("Full name is too long (max 255 chars)."));
return false;
}
$homepage = $req->get_parameter('omb_listenee_homepage');
if ($homepage && (!common_valid_http_url($homepage) || strlen($homepage) > 255)) {
if ($homepage && (!common_valid_http_url($homepage) || mb_strlen($homepage) > 255)) {
$this->clientError(sprintf(_("Invalid homepage '%s'"), $homepage));
return false;
}
$bio = $req->get_parameter('omb_listenee_bio');
if ($bio && strlen($bio) > 140) {
if ($bio && mb_strlen($bio) > 140) {
$this->clientError(_("Bio is too long (max 140 chars)."));
return false;
}
$location = $req->get_parameter('omb_listenee_location');
if ($location && strlen($location) > 255) {
if ($location && mb_strlen($location) > 255) {
$this->clientError(_("Location is too long (max 255 chars)."));
return false;
}
......
......@@ -469,19 +469,19 @@ class UserauthorizationAction extends Action
}
# optional stuff
$fullname = $req->get_parameter('omb_listenee_fullname');
if ($fullname && strlen($fullname) > 255) {
if ($fullname && mb_strlen($fullname) > 255) {
throw new OAuthException("Full name '$fullname' too long.");
}
$homepage = $req->get_parameter('omb_listenee_homepage');
if ($homepage && (!common_valid_http_url($homepage) || strlen($homepage) > 255)) {
if ($homepage && (!common_valid_http_url($homepage) || mb_strlen($homepage) > 255)) {
throw new OAuthException("Invalid homepage '$homepage'");
}
$bio = $req->get_parameter('omb_listenee_bio');
if ($bio && strlen($bio) > 140) {
if ($bio && mb_strlen($bio) > 140) {
throw new OAuthException("Bio too long '$bio'");
}
$location = $req->get_parameter('omb_listenee_location');
if ($location && strlen($location) > 255) {
if ($location && mb_strlen($location) > 255) {
throw new OAuthException("Location too long '$location'");
}
$avatar = $req->get_parameter('omb_listenee_avatar');
......
......@@ -142,3 +142,7 @@ $config['sphinx']['port'] = 3312;
# config section for the built-in Facebook application
#$config['facebook']['apikey'] = 'APIKEY';
#$config['facebook']['secret'] = 'SECRET';
# Add Google Analytics
# require_once('plugins/GoogleAnalyticsPlugin.php');
# $ga = new GoogleAnalyticsPlugin('your secret code');
......@@ -258,7 +258,8 @@ create table notice_tag (
created datetime not null comment 'date this record was created',
constraint primary key (tag, notice_id),
index notice_tag_created_idx (created)
index notice_tag_created_idx (created),
index notice_tag_notice_id_idx (notice_id)
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
/* Synching with foreign services */
......@@ -356,7 +357,8 @@ create table profile_tag (
constraint primary key (tagger, tagged, tag),
index profile_tag_modified_idx (modified),
index profile_tag_tagger_tag_idx (tagger, tag)
index profile_tag_tagger_tag_idx (tagger, tag),
index profile_tag_tagged_idx (tagged)
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
create table profile_block (
......@@ -400,7 +402,9 @@ create table group_member (
created datetime not null comment 'date this record was created',
modified timestamp comment 'date this record was modified',
constraint primary key (group_id, profile_id)
constraint primary key (group_id, profile_id),
index group_member_profile_id_idx (profile_id),
index group_member_created_idx (created)
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
......
......@@ -22,6 +22,8 @@ define('LACONICA', true);
require_once INSTALLDIR . '/lib/common.php';
// XXX: we need a little more structure in this script
// get and cache current user
$user = common_current_user();
......@@ -45,16 +47,16 @@ if (!$user && common_config('site', 'private') &&
common_redirect(common_local_url('login'));
}
$actionfile = INSTALLDIR."/actions/$action.php";
if (file_exists($actionfile)) {
include_once $actionfile;
$action_class = ucfirst($action).'Action';
$action_class = ucfirst($action).'Action';
if (!class_exists($action_class)) {
$cac = new ClientErrorAction(_('Unknown action'), 404);
$cac->showPage();
} else {
$action_obj = new $action_class();
// XXX: find somewhere for this little block to live
if ($config['db']['mirror'] && $action_obj->isReadOnly()) {
if (is_array($config['db']['mirror'])) {
// "load balancing", ha ha
......@@ -66,9 +68,24 @@ if (file_exists($actionfile)) {
}
$config['db']['database'] = $mirror;
}
if (call_user_func(array($action_obj, 'prepare'), $_REQUEST)) {
call_user_func(array($action_obj, 'handle'), $_REQUEST);
try {
if ($action_obj->prepare($_REQUEST)) {
$action_obj->handle($_REQUEST);
}
} catch (ClientException $cex) {
$cac = new ClientErrorAction($cex->getMessage(), $cex->getCode());
$cac->showPage();
} catch (ServerException $sex) { // snort snort guffaw
$sac = new ServerErrorAction($sex->getMessage(), $sex->getCode());
$sac->showPage();
} catch (Exception $ex) {
$sac = new ServerErrorAction($ex->getMessage());
$sac->showPage();
}
} else {
common_user_error(_('Unknown action'));
}
\ No newline at end of file
}
// XXX: cleanup exit() calls or add an exit handler so
// this always gets called
Event::handle('CleanupPlugin');
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -179,18 +179,27 @@ class Action extends HTMLOutputter // lawsuit
*/
function showScripts()
{
$this->element('script', array('type' => 'text/javascript',
'src' => common_path('js/jquery.min.js')),
' ');
$this->element('script', array('type' => 'text/javascript',
'src' => common_path('js/jquery.form.js')),
' ');
$this->element('script', array('type' => 'text/javascript',
'src' => common_path('js/xbImportNode.js')),
' ');
$this->element('script', array('type' => 'text/javascript',
'src' => common_path('js/util.js?version='.LACONICA_VERSION)),
' ');
if (Event::handle('StartShowScripts', array($this))) {
if (Event::handle('StartShowJQueryScripts', array($this))) {
$this->element('script', array('type' => 'text/javascript',
'src' => common_path('js/jquery.min.js')),
' ');
$this->element('script', array('type' => 'text/javascript',
'src' => common_path('js/jquery.form.js')),
' ');
Event::handle('EndShowJQueryScripts', array($this));
}
if (Event::handle('StartShowLaconicaScripts', array($this))) {
$this->element('script', array('type' => 'text/javascript',
'src' => common_path('js/xbImportNode.js')),
' ');
$this->element('script', array('type' => 'text/javascript',
'src' => common_path('js/util.js?version='.LACONICA_VERSION)),
' ');
Event::handle('EndShowLaconicaScripts', array