diff --git a/actions/accesstoken.php b/actions/accesstoken.php index ad03b70190..65c67c64ed 100644 --- a/actions/accesstoken.php +++ b/actions/accesstoken.php @@ -1,5 +1,16 @@ + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * * Laconica - a distributed open-source microblogging tool * Copyright (C) 2008, Controlez-Vous, Inc. * @@ -17,12 +28,31 @@ * along with this program. If not, see . */ -if (!defined('LACONICA')) { exit(1); } +if (!defined('LACONICA')) { + exit(1); +} -require_once(INSTALLDIR.'/lib/omb.php'); +require_once INSTALLDIR.'/lib/omb.php'; +/** + * Access token class. + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ class AccesstokenAction extends Action { + /** + * Class handler. + * + * @param array $args query arguments + * + * @return boolean false if user doesn't exist + */ function handle($args) { parent::handle($args); @@ -34,7 +64,7 @@ class AccesstokenAction extends Action $server = omb_oauth_server(); common_debug('fetching the access token', __FILE__); $token = $server->fetch_access_token($req); - common_debug('got this token: "'.print_r($token,true).'"', __FILE__); + common_debug('got this token: "'.print_r($token, true).'"', __FILE__); common_debug('printing the access token', __FILE__); print $token; } catch (OAuthException $e) { diff --git a/actions/allrss.php b/actions/allrss.php index 56818d605c..e357d12f02 100644 --- a/actions/allrss.php +++ b/actions/allrss.php @@ -1,5 +1,17 @@ + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * * Laconica - a distributed open-source microblogging tool * Copyright (C) 2008, Controlez-Vous, Inc. * @@ -17,20 +29,37 @@ * along with this program. If not, see . */ -if (!defined('LACONICA')) { exit(1); } +if (!defined('LACONICA')) { + exit(1); +} -require_once(INSTALLDIR.'/lib/rssaction.php'); - -// Formatting of RSS handled by Rss10Action +require_once INSTALLDIR.'/lib/rssaction.php'; +/** + * RSS feed for user and friends timeline. + * + * Formatting of RSS handled by Rss10Action + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ class AllrssAction extends Rss10Action { var $user = null; + /** + * Initialization. + * + * @return boolean false if user doesn't exist + */ function init() { - $nickname = $this->trimmed('nickname'); + $nickname = $this->trimmed('nickname'); $this->user = User::staticGet('nickname', $nickname); if (!$this->user) { @@ -41,11 +70,16 @@ class AllrssAction extends Rss10Action } } - function get_notices($limit=0) + /** + * Get notices + * + * @param integer $limit max number of notices to return + * + * @return array notices + */ + function getNotices($limit=0) { - - $user = $this->user; - + $user = $this->user; $notice = $user->noticesWithFriends(0, $limit); while ($notice->fetch()) { @@ -55,10 +89,15 @@ class AllrssAction extends Rss10Action return $notices; } - function get_channel() + /** + * Get channel. + * + * @return array associative array on channel information + */ + function getChannel() { $user = $this->user; - $c = array('url' => common_local_url('allrss', + $c = array('url' => common_local_url('allrss', array('nickname' => $user->nickname)), 'title' => sprintf(_('%s and friends'), $user->nickname), @@ -69,14 +108,20 @@ class AllrssAction extends Rss10Action return $c; } - function get_image() + /** + * Get image. + * + * @return string user avatar URL or null + */ + function getImage() { - $user = $this->user; + $user = $this->user; $profile = $user->getProfile(); if (!$profile) { return null; } $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); - return ($avatar) ? $avatar->url : null; + return $avatar ? $avatar->url : null; } -} \ No newline at end of file +} + diff --git a/actions/avatarbynickname.php b/actions/avatarbynickname.php index d2d078b61f..fec202016e 100644 --- a/actions/avatarbynickname.php +++ b/actions/avatarbynickname.php @@ -1,5 +1,16 @@ + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * * Laconica - a distributed open-source microblogging tool * Copyright (C) 2008, Controlez-Vous, Inc. * @@ -17,10 +28,29 @@ * along with this program. If not, see . */ -if (!defined('LACONICA')) { exit(1); } +if (!defined('LACONICA')) { + exit(1); +} +/** + * Retrieve user avatar by nickname action class. + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ class AvatarbynicknameAction extends Action { + /** + * Class handler. + * + * @param array $args query arguments + * + * @return boolean false if nickname or user isn't found + */ function handle($args) { parent::handle($args); @@ -68,3 +98,4 @@ class AvatarbynicknameAction extends Action common_redirect($url, 302); } } + diff --git a/actions/avatarsettings.php b/actions/avatarsettings.php index b303fd2fde..2c7af9b7a8 100644 --- a/actions/avatarsettings.php +++ b/actions/avatarsettings.php @@ -37,12 +37,13 @@ require_once INSTALLDIR.'/lib/accountsettingsaction.php'; /** * Upload an avatar * - * We use jQuery to crop the image after upload. + * We use jCrop plugin for jQuery to crop the image after upload. * * @category Settings * @package Laconica * @author Evan Prodromou * @author Zach Copley + * @author Sarven Capadisli * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://laconi.ca/ */ @@ -94,42 +95,43 @@ class AvatarsettingsAction extends AccountSettingsAction $original = $profile->getOriginalAvatar(); $this->elementStart('form', array('enctype' => 'multipart/form-data', - 'method' => 'POST', - 'id' => 'avatar', + 'method' => 'post', + 'id' => 'form_settings_avatar', + 'class' => 'form_settings', 'action' => common_local_url('avatarsettings'))); + $this->elementStart('fieldset'); + $this->element('legend', null, _('Avatar settings')); $this->hidden('token', common_session_token()); + $this->elementStart('ul', 'form_data'); if ($original) { - $this->elementStart('div', + $this->elementStart('li', array('id' => 'avatar_original', 'class' => 'avatar_view')); - $this->element('h3', null, _("Original:")); + $this->element('h2', null, _("Original")); $this->elementStart('div', array('id'=>'avatar_original_view')); $this->element('img', array('src' => $original->url, - 'class' => 'avatar original', 'width' => $original->width, 'height' => $original->height, 'alt' => $user->nickname)); $this->elementEnd('div'); - $this->elementEnd('div'); + $this->elementEnd('li'); } $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); if ($avatar) { - $this->elementStart('div', + $this->elementStart('li', array('id' => 'avatar_preview', 'class' => 'avatar_view')); - $this->element('h3', null, _("Preview:")); + $this->element('h2', null, _("Preview")); $this->elementStart('div', array('id'=>'avatar_preview_view')); $this->element('img', array('src' => $original->url,//$avatar->url, - 'class' => 'avatar profile', 'width' => AVATAR_PROFILE_SIZE, 'height' => AVATAR_PROFILE_SIZE, 'alt' => $user->nickname)); $this->elementEnd('div'); - $this->elementEnd('div'); foreach (array('avatar_crop_x', 'avatar_crop_y', 'avatar_crop_w', 'avatar_crop_h') as $crop_info) { @@ -138,21 +140,28 @@ class AvatarsettingsAction extends AccountSettingsAction 'id' => $crop_info)); } $this->submit('crop', _('Crop')); + + $this->elementEnd('li'); } + $this->elementStart('li', array ('id' => 'settings_attach')); + $this->element('input', array('name' => 'avatarfile', + 'type' => 'file', + 'id' => 'avatarfile')); $this->element('input', array('name' => 'MAX_FILE_SIZE', 'type' => 'hidden', 'id' => 'MAX_FILE_SIZE', 'value' => MAX_AVATAR_SIZE)); + $this->elementEnd('li'); + $this->elementEnd('ul'); - $this->elementStart('p'); - - $this->element('input', array('name' => 'avatarfile', - 'type' => 'file', - 'id' => 'avatarfile')); - $this->elementEnd('p'); - + $this->elementStart('ul', 'form_actions'); + $this->elementStart('li'); $this->submit('upload', _('Upload')); + $this->elementEnd('li'); + $this->elementEnd('ul'); + + $this->elementEnd('fieldset'); $this->elementEnd('form'); } @@ -250,7 +259,7 @@ class AvatarsettingsAction extends AccountSettingsAction { parent::showStylesheets(); $jcropStyle = - common_path('js/jcrop/jquery.Jcrop.css?version='.LACONICA_VERSION); + common_path('theme/base/css/jquery.Jcrop.css?version='.LACONICA_VERSION); $this->element('link', array('rel' => 'stylesheet', 'type' => 'text/css', diff --git a/actions/block.php b/actions/block.php index 738cbfbf71..64bd97a4fe 100644 --- a/actions/block.php +++ b/actions/block.php @@ -1,5 +1,16 @@ + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * * Laconica - a distributed open-source microblogging tool * Copyright (C) 2008, Controlez-Vous, Inc. * @@ -17,121 +28,135 @@ * along with this program. If not, see . */ -if (!defined('LACONICA')) { exit(1); } +if (!defined('LACONICA')) { + exit(1); +} +/** + * Block a user action class. + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ class BlockAction extends Action { - var $profile = null; - + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ function prepare($args) { - parent::prepare($args); - if (!common_logged_in()) { $this->clientError(_('Not logged in.')); return false; } - $token = $this->trimmed('token'); - if (!$token || $token != common_session_token()) { $this->clientError(_('There was a problem with your session token. Try again, please.')); return; } - $id = $this->trimmed('blockto'); - if (!$id) { $this->clientError(_('No profile specified.')); return false; } - $this->profile = Profile::staticGet('id', $id); - if (!$this->profile) { $this->clientError(_('No profile with that ID.')); return false; } - return true; } + /** + * Handle request + * + * Shows a page with list of favorite notices + * + * @param array $args $_REQUEST args; handled in prepare() + * + * @return void + */ function handle($args) { parent::handle($args); if ($_SERVER['REQUEST_METHOD'] == 'POST') { if ($this->arg('block')) { - $this->are_you_sure_form(); + $this->areYouSureForm(); } else if ($this->arg('no')) { $cur = common_current_user(); - common_redirect(common_local_url('subscribers', - array('nickname' => $cur->nickname))); + common_redirect(common_local_url('subscribers', array('nickname' => $cur->nickname))); } else if ($this->arg('yes')) { - $this->block_profile(); + $this->blockProfile(); } } } - function are_you_sure_form() + /** + * Confirm with user. + * + * Shows a confirmation form. + * + * @return void + */ + function areYouSureForm() { - $id = $this->profile->id; - common_show_header(_('Block user')); - $this->element('p', null, _('Are you sure you want to block this user? '. 'Afterwards, they will be unsubscribed from you, '. 'unable to subscribe to you in the future, and '. 'you will not be notified of any @-replies from them.')); - $this->elementStart('form', array('id' => 'block-' . $id, 'method' => 'post', 'class' => 'block', 'action' => common_local_url('block'))); - $this->hidden('token', common_session_token()); - $this->element('input', array('id' => 'blockto-' . $id, 'name' => 'blockto', 'type' => 'hidden', 'value' => $id)); - foreach ($this->args as $k => $v) { if (substr($k, 0, 9) == 'returnto-') { $this->hidden($k, $v); } } - $this->submit('no', _('No')); $this->submit('yes', _('Yes')); - $this->elementEnd('form'); - common_show_footer(); } - function block_profile() + /** + * Actually block a user. + * + * @return void + */ + function blockProfile() { - $cur = common_current_user(); if ($cur->hasBlocked($this->profile)) { $this->clientError(_('You have already blocked this user.')); return; } - $result = $cur->block($this->profile); - if (!$result) { $this->serverError(_('Failed to save block information.')); return; } - # Now, gotta figure where we go back to - + // Now, gotta figure where we go back to foreach ($this->args as $k => $v) { if ($k == 'returnto-action') { $action = $v; @@ -148,3 +173,4 @@ class BlockAction extends Action } } } + diff --git a/actions/clienterror.php b/actions/clienterror.php new file mode 100644 index 0000000000..ef6fd51dff --- /dev/null +++ b/actions/clienterror.php @@ -0,0 +1,94 @@ + + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * + * Laconica - a distributed open-source microblogging tool + * Copyright (C) 2008, Controlez-Vous, 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 . + */ + +if (!defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR.'/lib/error.php'; + +/** + * Class for displaying HTTP client errors + * + * @category Action + * @package Laconica + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ +class ClientErrorAction extends ErrorAction +{ + function __construct($message='Error', $code=400) + { + parent::__construct($message, $code); + + $this->status = array(400 => 'Bad Request', + 401 => 'Unauthorized', + 402 => 'Payment Required', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Timeout', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed'); + $this->default = 400; + } + + // XXX: Should these error actions even be invokable via URI? + + function handle($args) + { + parent::handle($args); + + $this->code = $this->trimmed('code'); + + if (!$this->code || $code < 400 || $code > 499) { + $this->code = $this->default; + } + + $this->message = $this->trimmed('message'); + + if (!$this->message) { + $this->message = "Client Error $this->code"; + } + + $this->showPage(); + } +} diff --git a/actions/disfavor.php b/actions/disfavor.php index d4a189d196..09b3bf18d3 100644 --- a/actions/disfavor.php +++ b/actions/disfavor.php @@ -1,5 +1,17 @@ + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * * Laconica - a distributed open-source microblogging tool * Copyright (C) 2008, Controlez-Vous, Inc. * @@ -17,59 +29,65 @@ * along with this program. If not, see . */ -if (!defined('LACONICA')) { exit(1); } +if (!defined('LACONICA')) { + exit(1); +} require_once INSTALLDIR.'/lib/favorform.php'; +/** + * Disfavor class. + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ class DisfavorAction extends Action { - + /** + * Class handler. + * + * @param array $args query arguments + * + * @return void + */ function handle($args) { - parent::handle($args); - if (!common_logged_in()) { $this->clientError(_('Not logged in.')); return; } - $user = common_current_user(); - if ($_SERVER['REQUEST_METHOD'] != 'POST') { - common_redirect(common_local_url('showfavorites', array('nickname' => $user->nickname))); + common_redirect(common_local_url('showfavorites', + array('nickname' => $user->nickname))); return; } - - $id = $this->trimmed('notice'); - + $id = $this->trimmed('notice'); $notice = Notice::staticGet($id); - - $token = $this->trimmed('token-'.$notice->id); - + $token = $this->trimmed('token-'.$notice->id); if (!$token || $token != common_session_token()) { $this->clientError(_("There was a problem with your session token. Try again, please.")); return; } - - $fave = new Fave(); - $fave->user_id = $this->id; + $fave = new Fave(); + $fave->user_id = $this->id; $fave->notice_id = $notice->id; if (!$fave->find(true)) { $this->clientError(_('This notice is not a favorite!')); return; } - $result = $fave->delete(); - if (!$result) { common_log_db_error($fave, 'DELETE', __FILE__); $this->serverError(_('Could not delete favorite.')); return; } - $user->blowFavesCache(); - if ($this->boolean('ajax')) { $this->startHTML('text/xml;charset=utf-8', true); $this->elementStart('head'); @@ -86,3 +104,4 @@ class DisfavorAction extends Action } } } + diff --git a/actions/doc.php b/actions/doc.php index aaf006f071..3755bb051d 100644 --- a/actions/doc.php +++ b/actions/doc.php @@ -67,6 +67,25 @@ class DocAction extends Action $this->showPage(); } + // overrrided to add entry-title class + function showPageTitle() { + $this->element('h1', array('class' => 'entry-title'), $this->title()); + } + + // overrided to add hentry, and content-inner classes + function showContentBlock() + { + $this->elementStart('div', array('id' => 'content', 'class' => 'hentry')); + $this->showPageTitle(); + $this->showPageNoticeBlock(); + $this->elementStart('div', array('id' => 'content_inner', + 'class' => 'entry-content')); + // show the actual content (forms, lists, whatever) + $this->showContent(); + $this->elementEnd('div'); + $this->elementEnd('div'); + } + /** * Display content. * @@ -89,4 +108,3 @@ class DocAction extends Action return ucfirst($this->title); } } - diff --git a/actions/editgroup.php b/actions/editgroup.php index 82b78cc5c7..98ebcb87ac 100644 --- a/actions/editgroup.php +++ b/actions/editgroup.php @@ -88,7 +88,12 @@ class EditgroupAction extends Action return false; } - $this->group = User_group::staticGet('nickname', $nickname); + $groupid = $this->trimmed('groupid'); + if ($groupid) { + $this->group = User_group::staticGet('id', $groupid); + } else { + $this->group = User_group::staticGet('nickname', $nickname); + } if (!$this->group) { $this->clientError(_('No such group'), 404); @@ -97,7 +102,7 @@ class EditgroupAction extends Action $cur = common_current_user(); - if (!$cur->isAdmin($group)) { + if (!$cur->isAdmin($this->group)) { $this->clientError(_('You must be an admin to edit the group'), 403); return false; } @@ -155,6 +160,13 @@ class EditgroupAction extends Action function trySave() { + $cur = common_current_user(); + if (!$cur->isAdmin($this->group)) { + $this->clientError(_('You must be an admin to edit the group'), 403); + return; + } + + $nickname = common_canonical_nickname($this->trimmed('nickname')); $fullname = $this->trimmed('fullname'); $homepage = $this->trimmed('homepage'); @@ -222,4 +234,5 @@ class EditgroupAction extends Action $group != false && $group->id != $this->group->id); } -} \ No newline at end of file +} + diff --git a/actions/favor.php b/actions/favor.php index 92756366d9..8ecde4b116 100644 --- a/actions/favor.php +++ b/actions/favor.php @@ -1,4 +1,18 @@ + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * + /* * Laconica - a distributed open-source microblogging tool * Copyright (C) 2008, Controlez-Vous, Inc. @@ -17,57 +31,63 @@ * along with this program. If not, see . */ -if (!defined('LACONICA')) { exit(1); } +if (!defined('LACONICA')) { + exit(1); +} -require_once(INSTALLDIR.'/lib/mail.php'); +require_once INSTALLDIR.'/lib/mail.php'; require_once INSTALLDIR.'/lib/disfavorform.php'; +/** + * Favor class. + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ class FavorAction extends Action { - + /** + * Class handler. + * + * @param array $args query arguments + * + * @return void + */ function handle($args) { parent::handle($args); - if (!common_logged_in()) { $this->clientError(_('Not logged in.')); return; } - $user = common_current_user(); - if ($_SERVER['REQUEST_METHOD'] != 'POST') { - common_redirect(common_local_url('showfavorites', array('nickname' => $user->nickname))); + common_redirect(common_local_url('showfavorites', + array('nickname' => $user->nickname))); return; } - - $id = $this->trimmed('notice'); - + $id = $this->trimmed('notice'); $notice = Notice::staticGet($id); - - # CSRF protection - - $token = $this->trimmed('token-'.$notice->id); + $token = $this->trimmed('token-'.$notice->id); if (!$token || $token != common_session_token()) { $this->clientError(_("There was a problem with your session token. Try again, please.")); return; } - if ($user->hasFave($notice)) { $this->clientError(_('This notice is already a favorite!')); return; } - $fave = Fave::addNew($user, $notice); - if (!$fave) { $this->serverError(_('Could not create favorite.')); return; } - - $this->notify($fave, $notice, $user); + $this->notify($notice, $user); $user->blowFavesCache(); - if ($this->boolean('ajax')) { $this->startHTML('text/xml;charset=utf-8', true); $this->elementStart('head'); @@ -84,16 +104,24 @@ class FavorAction extends Action } } - function notify($fave, $notice, $user) + /** + * Notifies a user when his notice is favorited. + * + * @param class $notice favorited notice + * @param class $user user declaring a favorite + * + * @return void + */ + function notify($notice, $user) { $other = User::staticGet('id', $notice->profile_id); if ($other && $other->id != $user->id) { if ($other->email && $other->emailnotifyfav) { mail_notify_fave($other, $user, $notice); } - # XXX: notify by IM - # XXX: notify by SMS + // XXX: notify by IM + // XXX: notify by SMS } } - } + diff --git a/actions/leavegroup.php b/actions/leavegroup.php index 587208b36a..c7152e3c0e 100644 --- a/actions/leavegroup.php +++ b/actions/leavegroup.php @@ -57,12 +57,12 @@ class LeavegroupAction extends Action parent::prepare($args); if (!common_config('inboxes','enabled')) { - $this->serverError(_('Inboxes must be enabled for groups to work')); + $this->serverError(_('Inboxes must be enabled for groups to work.')); return false; } if (!common_logged_in()) { - $this->clientError(_('You must be logged in to join a group.')); + $this->clientError(_('You must be logged in to leave a group.')); return false; } @@ -78,24 +78,30 @@ class LeavegroupAction extends Action } if (!$nickname) { - $this->clientError(_('No nickname'), 404); + $this->clientError(_('No nickname.'), 404); return false; } $this->group = User_group::staticGet('nickname', $nickname); if (!$this->group) { - $this->clientError(_('No such group'), 404); + $this->clientError(_('No such group.'), 404); return false; } $cur = common_current_user(); - if (!$cur->isMember($group)) { - $this->clientError(_('You are not a member of that group'), 403); + if (!$cur->isMember($this->group)) { + $this->clientError(_('You are not a member of that group.'), 403); return false; } + if ($cur->isAdmin($this->group)) { + $this->clientError(_('You may not leave a group while you are its administrator.'), 403); + return false; + + } + return true; } @@ -150,4 +156,4 @@ class LeavegroupAction extends Action $this->group->nickname))); } } -} \ No newline at end of file +} diff --git a/actions/newgroup.php b/actions/newgroup.php index 41c095ec0b..42fd380dfe 100644 --- a/actions/newgroup.php +++ b/actions/newgroup.php @@ -201,4 +201,5 @@ class NewgroupAction extends Action $group = User_group::staticGet('nickname', $nickname); return (!is_null($group) && $group != false); } -} \ No newline at end of file +} + diff --git a/actions/nudge.php b/actions/nudge.php index 4561064594..ca6fd37612 100644 --- a/actions/nudge.php +++ b/actions/nudge.php @@ -42,6 +42,7 @@ require_once INSTALLDIR.'/lib/mail.php'; * @package Laconica * @author Evan Prodromou * @author Robin Millette + * @author Sarven Capadisli * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @link http://laconi.ca/ */ @@ -93,7 +94,7 @@ class NudgeAction extends Action $this->element('title', null, _('Nudge sent')); $this->elementEnd('head'); $this->elementStart('body'); - common_nudge_response(); + $this->element('p', array('id' => 'nudge_response'), _('Nudge sent!')); $this->elementEnd('body'); $this->elementEnd('html'); } else { diff --git a/actions/opensearch.php b/actions/opensearch.php index 6e6e794e96..d7705972f0 100644 --- a/actions/opensearch.php +++ b/actions/opensearch.php @@ -1,5 +1,17 @@ + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * * Laconica - a distributed open-source microblogging tool * Copyright (C) 2008, Controlez-Vous, Inc. * @@ -17,32 +29,46 @@ * along with this program. If not, see . */ -if (!defined('LACONICA')) { exit(1); } +if (!defined('LACONICA')) { + exit(1); +} +/** + * Opensearch action class. + * + * Formatting of RSS handled by Rss10Action + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ class OpensearchAction extends Action { - + /** + * Class handler. + * + * @param array $args query arguments + * + * @return boolean false if user doesn't exist + */ function handle($args) { - parent::handle($args); - - $type = $this->trimmed('type'); - + $type = $this->trimmed('type'); $short_name = ''; if ($type == 'people') { - $type = 'peoplesearch'; + $type = 'peoplesearch'; $short_name = _('People Search'); } else { + $type = 'noticesearch'; $short_name = _('Notice Search'); - $type = 'noticesearch'; } - header('Content-Type: text/html'); - common_start_xml(); $this->elementStart('OpenSearchDescription', array('xmlns' => 'http://a9.com/-/spec/opensearch/1.1/')); - $short_name = common_config('site', 'name').' '.$short_name; $this->element('ShortName', null, $short_name); $this->element('Contact', null, common_config('site', 'email')); @@ -54,8 +80,8 @@ class OpensearchAction extends Action $this->element('Language', null, common_language()); $this->element('OutputEncoding', null, 'UTF-8'); $this->element('InputEncoding', null, 'UTF-8'); - $this->elementEnd('OpenSearchDescription'); common_end_xml(); } } + diff --git a/actions/passwordsettings.php b/actions/passwordsettings.php index f96da13bda..17b2de4e86 100644 --- a/actions/passwordsettings.php +++ b/actions/passwordsettings.php @@ -81,21 +81,35 @@ class PasswordsettingsAction extends AccountSettingsAction { $user = common_current_user(); $this->elementStart('form', array('method' => 'POST', - 'id' => 'password', + 'id' => 'form_password', + 'class' => 'form_settings', 'action' => common_local_url('profilesettings'))); - + $this->elementStart('fieldset'); + $this->element('legend', null, _('Password change')); $this->hidden('token', common_session_token()); + + $this->elementStart('ul', 'form_data'); // Users who logged in with OpenID won't have a pwd if ($user->password) { + $this->elementStart('li'); $this->password('oldpassword', _('Old password')); + $this->elementEnd('li'); } + $this->elementStart('li'); $this->password('newpassword', _('New password'), _('6 or more characters')); + $this->elementEnd('li'); + $this->elementStart('li'); $this->password('confirm', _('Confirm'), _('same as password above')); + $this->elementEnd('li'); + $this->elementEnd('ul'); + $this->submit('changepass', _('Change')); + + $this->elementEnd('fieldset'); $this->elementEnd('form'); } @@ -158,4 +172,4 @@ class PasswordsettingsAction extends AccountSettingsAction $this->showForm(_('Password saved.'), true); } -} \ No newline at end of file +} diff --git a/actions/publicrss.php b/actions/publicrss.php index b98c272053..844c334bea 100644 --- a/actions/publicrss.php +++ b/actions/publicrss.php @@ -36,6 +36,8 @@ if (!defined('LACONICA')) { require_once INSTALLDIR.'/lib/rssaction.php'; /** + * RSS feed for public timeline. + * * Formatting of RSS handled by Rss10Action * * @category Action diff --git a/actions/register.php b/actions/register.php index 159daaa737..a63da2e0fd 100644 --- a/actions/register.php +++ b/actions/register.php @@ -248,6 +248,25 @@ class RegisterAction extends Action return ($user !== false); } + // overrrided to add entry-title class + function showPageTitle() { + $this->element('h1', array('class' => 'entry-title'), $this->title()); + } + + // overrided to add hentry, and content-inner class + function showContentBlock() + { + $this->elementStart('div', array('id' => 'content', 'class' => 'hentry')); + $this->showPageTitle(); + $this->showPageNoticeBlock(); + $this->elementStart('div', array('id' => 'content_inner', + 'class' => 'entry-content')); + // show the actual content (forms, lists, whatever) + $this->showContent(); + $this->elementEnd('div'); + $this->elementEnd('div'); + } + /** * Instructions or a notice for the page * diff --git a/actions/requesttoken.php b/actions/requesttoken.php index 5058deedb5..ca253b97aa 100644 --- a/actions/requesttoken.php +++ b/actions/requesttoken.php @@ -1,5 +1,17 @@ + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * * Laconica - a distributed open-source microblogging tool * Copyright (C) 2008, Controlez-Vous, Inc. * @@ -17,29 +29,53 @@ * along with this program. If not, see . */ -if (!defined('LACONICA')) { exit(1); } +if (!defined('LACONICA')) { + exit(1); +} -require_once(INSTALLDIR.'/lib/omb.php'); +require_once INSTALLDIR.'/lib/omb.php'; +/** + * Request token action class. + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ class RequesttokenAction extends Action { - + /** + * Is read only? + * + * @return boolean false + */ function isReadOnly() { return false; } + /** + * Class handler. + * + * @param array $args array of arguments + * + * @return void + */ function handle($args) { parent::handle($args); try { common_remove_magic_from_request(); - $req = OAuthRequest::from_request(); + $req = OAuthRequest::from_request(); $server = omb_oauth_server(); - $token = $server->fetch_request_token($req); + $token = $server->fetch_request_token($req); print $token; } catch (OAuthException $e) { $this->serverError($e->getMessage()); } } } + diff --git a/actions/servererror.php b/actions/servererror.php new file mode 100644 index 0000000000..a398865915 --- /dev/null +++ b/actions/servererror.php @@ -0,0 +1,92 @@ + + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * + * Laconica - a distributed open-source microblogging tool + * Copyright (C) 2008, Controlez-Vous, 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 . + */ + +if (!defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR.'/lib/error.php'; + +/** + * Class for displaying HTTP server errors + * + * Note: The older util.php class simply printed a string, but the spec + * says that 500 errors should be treated similarly to 400 errors, and + * it's easier to give an HTML response. Maybe we can customize these + * to display some funny animal cartoons. If not, we can probably role + * these classes up into a single class. + * + * See: http://tools.ietf.org/html/rfc2616#section-10 + * + * @category Action + * @package Laconica + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ +class ServerErrorAction extends ErrorAction +{ + function __construct($message='Error', $code=500) + { + parent::__construct($message, $code); + + $this->status = array(500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported'); + + $this->default = 500; + } + + // XXX: Should these error actions even be invokable via URI? + + function handle($args) + { + parent::handle($args); + + $this->code = $this->trimmed('code'); + + if (!$this->code || $code < 500 || $code > 599) { + $this->code = $this->default; + } + + $this->message = $this->trimmed('message'); + + if (!$this->message) { + $this->message = "Server Error $this->code"; + } + + $this->showPage(); + } + +} diff --git a/actions/showgroup.php b/actions/showgroup.php index c0359f5023..534043c242 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -201,13 +201,12 @@ class ShowgroupAction extends Action function showGroupProfile() { - $this->elementStart('div', array('id' => 'group_profile', - 'class' => 'vcard author')); + $this->elementStart('div', 'entity_profile vcard author'); $this->element('h2', null, _('Group profile')); - $this->elementStart('dl', 'group_depiction'); - $this->element('dt', null, _('Photo')); + $this->elementStart('dl', 'entity_depiction'); + $this->element('dt', null, _('Avatar')); $this->elementStart('dd'); $logo = ($this->group->homepage_logo) ? @@ -221,10 +220,10 @@ class ShowgroupAction extends Action $this->elementEnd('dd'); $this->elementEnd('dl'); - $this->elementStart('dl', 'group_nickname'); + $this->elementStart('dl', 'entity_nickname'); $this->element('dt', null, _('Nickname')); $this->elementStart('dd'); - $hasFN = ($this->group->fullname) ? 'nickname url uid' : 'fn nickname url uid'; + $hasFN = ($this->group->fullname) ? 'nickname url uid' : 'fn org nickname url uid'; $this->element('a', array('href' => $this->group->homeUrl(), 'rel' => 'me', 'class' => $hasFN), $this->group->nickname); @@ -232,23 +231,23 @@ class ShowgroupAction extends Action $this->elementEnd('dl'); if ($this->group->fullname) { - $this->elementStart('dl', 'group_fn'); + $this->elementStart('dl', 'entity_fn'); $this->element('dt', null, _('Full name')); $this->elementStart('dd'); - $this->element('span', 'fn', $this->group->fullname); + $this->element('span', 'fn org', $this->group->fullname); $this->elementEnd('dd'); $this->elementEnd('dl'); } if ($this->group->location) { - $this->elementStart('dl', 'group_location'); + $this->elementStart('dl', 'entity_location'); $this->element('dt', null, _('Location')); $this->element('dd', 'location', $this->group->location); $this->elementEnd('dl'); } if ($this->group->homepage) { - $this->elementStart('dl', 'group_url'); + $this->elementStart('dl', 'entity_url'); $this->element('dt', null, _('URL')); $this->elementStart('dd'); $this->element('a', array('href' => $this->group->homepage, @@ -259,7 +258,7 @@ class ShowgroupAction extends Action } if ($this->group->description) { - $this->elementStart('dl', 'group_note'); + $this->elementStart('dl', 'entity_note'); $this->element('dt', null, _('Note')); $this->element('dd', 'note', $this->group->description); $this->elementEnd('dl'); @@ -267,15 +266,17 @@ class ShowgroupAction extends Action $this->elementEnd('div'); - $this->elementStart('div', array('id' => 'group_actions')); + $this->elementStart('div', 'entity_actions'); $this->element('h2', null, _('Group actions')); $this->elementStart('ul'); - $this->elementStart('li', array('id' => 'group_subscribe')); + $this->elementStart('li', array('id' => 'entity_subscribe')); $cur = common_current_user(); if ($cur) { if ($cur->isMember($this->group)) { - $lf = new LeaveForm($this, $this->group); - $lf->show(); + if (!$cur->isAdmin($this->group)) { + $lf = new LeaveForm($this, $this->group); + $lf->show(); + } } else { $jf = new JoinForm($this, $this->group); $jf->show(); @@ -348,7 +349,7 @@ class ShowgroupAction extends Action return; } - $this->elementStart('div', array('id' => 'user_subscriptions', + $this->elementStart('div', array('id' => 'entity_subscriptions', 'class' => 'section')); $this->element('h2', null, _('Members')); @@ -367,4 +368,4 @@ class ShowgroupAction extends Action _('All members')); } } -} \ No newline at end of file +} diff --git a/actions/showstream.php b/actions/showstream.php index 9734c29077..1ea84cf218 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -169,14 +169,14 @@ class ShowstreamAction extends Action $this->element('link', array('rel' => 'alternate', 'href' => common_local_url('api', array('apiaction' => 'statuses', - 'method' => 'user_timeline.rss', + 'method' => 'entity_timeline.rss', 'argument' => $this->user->nickname)), 'type' => 'application/rss+xml', 'title' => sprintf(_('Notice feed for %s'), $this->user->nickname))); $this->element('link', array('rel' => 'alternate feed', 'href' => common_local_url('api', array('apiaction' => 'statuses', - 'method' => 'user_timeline.atom', + 'method' => 'entity_timeline.atom', 'argument' => $this->user->nickname)), 'type' => 'application/atom+xml', 'title' => sprintf(_('Notice feed for %s'), $this->user->nickname))); @@ -227,11 +227,11 @@ class ShowstreamAction extends Action function showProfile() { - $this->elementStart('div', array('id' => 'user_profile', 'class' => 'vcard author')); + $this->elementStart('div', 'entity_profile vcard author'); $this->element('h2', null, _('User profile')); $avatar = $this->profile->getAvatar(AVATAR_PROFILE_SIZE); - $this->elementStart('dl', 'user_depiction'); + $this->elementStart('dl', 'entity_depiction'); $this->element('dt', null, _('Photo')); $this->elementStart('dd'); $this->element('img', array('src' => ($avatar) ? common_avatar_display_url($avatar) : common_default_avatar(AVATAR_PROFILE_SIZE), @@ -242,7 +242,7 @@ class ShowstreamAction extends Action $this->elementEnd('dd'); $this->elementEnd('dl'); - $this->elementStart('dl', 'user_nickname'); + $this->elementStart('dl', 'entity_nickname'); $this->element('dt', null, _('Nickname')); $this->elementStart('dd'); $hasFN = ($this->profile->fullname) ? 'nickname url uid' : 'fn nickname url uid'; @@ -253,7 +253,7 @@ class ShowstreamAction extends Action $this->elementEnd('dl'); if ($this->profile->fullname) { - $this->elementStart('dl', 'user_fn'); + $this->elementStart('dl', 'entity_fn'); $this->element('dt', null, _('Full name')); $this->elementStart('dd'); $this->element('span', 'fn', $this->profile->fullname); @@ -262,14 +262,14 @@ class ShowstreamAction extends Action } if ($this->profile->location) { - $this->elementStart('dl', 'user_location'); + $this->elementStart('dl', 'entity_location'); $this->element('dt', null, _('Location')); $this->element('dd', 'location', $this->profile->location); $this->elementEnd('dl'); } if ($this->profile->homepage) { - $this->elementStart('dl', 'user_url'); + $this->elementStart('dl', 'entity_url'); $this->element('dt', null, _('URL')); $this->elementStart('dd'); $this->element('a', array('href' => $this->profile->homepage, @@ -280,7 +280,7 @@ class ShowstreamAction extends Action } if ($this->profile->bio) { - $this->elementStart('dl', 'user_note'); + $this->elementStart('dl', 'entity_note'); $this->element('dt', null, _('Note')); $this->element('dd', 'note', $this->profile->bio); $this->elementEnd('dl'); @@ -288,7 +288,7 @@ class ShowstreamAction extends Action $tags = Profile_tag::getTags($this->profile->id, $this->profile->id); if (count($tags) > 0) { - $this->elementStart('dl', 'user_tags'); + $this->elementStart('dl', 'entity_tags'); $this->element('dt', null, _('Tags')); $this->elementStart('dd'); $this->elementStart('ul', 'tags xoxo'); @@ -307,10 +307,11 @@ class ShowstreamAction extends Action } $this->elementEnd('div'); - $this->elementStart('div', array('id' => 'user_actions')); + //XXX: entity_actions doesn't need to be outputted if entity is looking at their own profile + $this->elementStart('div', 'entity_actions'); $this->element('h2', null, _('User actions')); $this->elementStart('ul'); - $this->elementStart('li', array('id' => 'user_subscribe')); + $this->elementStart('li', array('id' => 'entity_subscribe')); $cur = common_current_user(); if ($cur) { if ($cur->id != $this->profile->id) { @@ -331,14 +332,14 @@ class ShowstreamAction extends Action $user = User::staticGet('id', $this->profile->id); if ($cur && $cur->id != $user->id && $cur->mutuallySubscribed($user)) { - $this->elementStart('li', array('id' => 'user_send-a-message')); + $this->elementStart('li', array('id' => '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')); $this->elementEnd('li'); if ($user->email && $user->emailnotifynudge) { - $this->elementStart('li', array('id' => 'user_nudge')); + $this->elementStart('li', array('id' => 'entity_nudge')); $nf = new NudgeForm($this, $user); $nf->show(); $this->elementEnd('li'); @@ -347,7 +348,7 @@ class ShowstreamAction extends Action if ($cur && $cur->id != $this->profile->id) { $blocked = $cur->hasBlocked($this->profile); - $this->elementStart('li', array('id' => 'user_block')); + $this->elementStart('li', array('id' => 'entity_block')); if ($blocked) { $ubf = new UnblockForm($this, $this->profile); $ubf->show(); @@ -366,7 +367,7 @@ class ShowstreamAction extends Action $url = common_local_url('remotesubscribe', array('nickname' => $this->profile->nickname)); $this->element('a', array('href' => $url, - 'id' => 'user_subscribe_remote'), + 'id' => 'entity_subscribe_remote'), _('Subscribe')); } @@ -383,17 +384,17 @@ class ShowstreamAction extends Action function showSections() { - $this->showStatistics(); $this->showSubscriptions(); $this->showSubscribers(); $this->showGroups(); + $this->showStatistics(); } function showSubscriptions() { $profile = $this->user->getSubscriptions(0, PROFILES_PER_MINILIST + 1); - $this->elementStart('div', array('id' => 'user_subscriptions', + $this->elementStart('div', array('id' => 'entity_subscriptions', 'class' => 'section')); $this->element('h2', null, _('Subscriptions')); @@ -410,7 +411,7 @@ class ShowstreamAction extends Action $this->elementStart('p'); $this->element('a', array('href' => common_local_url('subscriptions', array('nickname' => $this->profile->nickname)), - 'class' => 'mores'), + 'class' => 'more'), _('All subscriptions')); $this->elementEnd('p'); } @@ -422,7 +423,7 @@ class ShowstreamAction extends Action { $profile = $this->user->getSubscribers(0, PROFILES_PER_MINILIST + 1); - $this->elementStart('div', array('id' => 'user_subscribers', + $this->elementStart('div', array('id' => 'entity_subscribers', 'class' => 'section')); $this->element('h2', null, _('Subscribers')); @@ -439,7 +440,7 @@ class ShowstreamAction extends Action $this->elementStart('p'); $this->element('a', array('href' => common_local_url('subscribers', array('nickname' => $this->profile->nickname)), - 'class' => 'mores'), + 'class' => 'more'), _('All subscribers')); $this->elementEnd('p'); } @@ -462,19 +463,19 @@ class ShowstreamAction extends Action $notices->profile_id = $this->profile->id; $notice_count = (int) $notices->count(); - $this->elementStart('div', array('id' => 'user_statistics', + $this->elementStart('div', array('id' => 'entity_statistics', 'class' => 'section')); $this->element('h2', null, _('Statistics')); // Other stats...? - $this->elementStart('dl', 'user_member-since'); + $this->elementStart('dl', 'entity_member-since'); $this->element('dt', null, _('Member since')); $this->element('dd', null, date('j M Y', strtotime($this->profile->created))); $this->elementEnd('dl'); - $this->elementStart('dl', 'user_subscriptions'); + $this->elementStart('dl', 'entity_subscriptions'); $this->elementStart('dt'); $this->element('a', array('href' => common_local_url('subscriptions', array('nickname' => $this->profile->nickname))), @@ -483,7 +484,7 @@ class ShowstreamAction extends Action $this->element('dd', null, (is_int($subs_count)) ? $subs_count : '0'); $this->elementEnd('dl'); - $this->elementStart('dl', 'user_subscribers'); + $this->elementStart('dl', 'entity_subscribers'); $this->elementStart('dt'); $this->element('a', array('href' => common_local_url('subscribers', array('nickname' => $this->profile->nickname))), @@ -492,7 +493,7 @@ class ShowstreamAction extends Action $this->element('dd', 'subscribers', (is_int($subbed_count)) ? $subbed_count : '0'); $this->elementEnd('dl'); - $this->elementStart('dl', 'user_notices'); + $this->elementStart('dl', 'entity_notices'); $this->element('dt', null, _('Notices')); $this->element('dd', null, (is_int($notice_count)) ? $notice_count : '0'); $this->elementEnd('dl'); @@ -504,7 +505,7 @@ class ShowstreamAction extends Action { $groups = $this->user->getGroups(0, GROUPS_PER_MINILIST + 1); - $this->elementStart('div', array('id' => 'user_groups', + $this->elementStart('div', array('id' => 'entity_groups', 'class' => 'section')); $this->element('h2', null, _('Groups')); @@ -521,7 +522,7 @@ class ShowstreamAction extends Action $this->elementStart('p'); $this->element('a', array('href' => common_local_url('usergroups', array('nickname' => $this->profile->nickname)), - 'class' => 'mores'), + 'class' => 'more'), _('All groups')); $this->elementEnd('p'); } diff --git a/js/jcrop/jquery.Jcrop.go.js b/js/jcrop/jquery.Jcrop.go.js new file mode 100644 index 0000000000..b2737407bf --- /dev/null +++ b/js/jcrop/jquery.Jcrop.go.js @@ -0,0 +1,46 @@ + $(function(){ + var x = ($('#avatar_crop_x').val()) ? $('#avatar_crop_x').val() : 0; + var y = ($('#avatar_crop_y').val()) ? $('#avatar_crop_y').val() : 0; + var w = ($('#avatar_crop_w').val()) ? $('#avatar_crop_w').val() : $("#avatar_original img").attr("width"); + var h = ($('#avatar_crop_h').val()) ? $('#avatar_crop_h').val() : $("#avatar_original img").attr("height"); + + jQuery("#avatar_original img").Jcrop({ + onChange: showPreview, + setSelect: [ x, y, w, h ], + onSelect: updateCoords, + aspectRatio: 1, + boxWidth: 480, + boxHeight: 480, + bgColor: '#000', + bgOpacity: .4 + }); + }); + + function showPreview(coords) { + var rx = 96 / coords.w; + var ry = 96 / coords.h; + + var img_width = $("#avatar_original img").attr("width"); + var img_height = $("#avatar_original img").attr("height"); + + $('#avatar_preview img').css({ + width: Math.round(rx *img_width) + 'px', + height: Math.round(ry * img_height) + 'px', + marginLeft: '-' + Math.round(rx * coords.x) + 'px', + marginTop: '-' + Math.round(ry * coords.y) + 'px' + }); + }; + + function updateCoords(c) { + $('#avatar_crop_x').val(c.x); + $('#avatar_crop_y').val(c.y); + $('#avatar_crop_w').val(c.w); + $('#avatar_crop_h').val(c.h); + }; + + function checkCoords() { + if (parseInt($('#avatar_crop_w').val())) return true; + alert('Please select a crop region then press submit.'); + return false; + }; + diff --git a/js/jquery.Jcrop.pack.js b/js/jcrop/jquery.Jcrop.pack.js similarity index 100% rename from js/jquery.Jcrop.pack.js rename to js/jcrop/jquery.Jcrop.pack.js diff --git a/js/jquery.Jcrop.go.js b/js/jquery.Jcrop.go.js deleted file mode 100644 index e5d5873545..0000000000 --- a/js/jquery.Jcrop.go.js +++ /dev/null @@ -1,41 +0,0 @@ - $(function(){ - jQuery("#photo_original img").Jcrop({ - onChange: showPreview, - setSelect: [ 0, 0, $("#photo_original img").attr("width"), $("#photo_original img").attr("height") ], - onSelect: updateCoords, - aspectRatio: 1, - boxWidth: 480, - boxHeight: 480, - bgColor: '#000', - bgOpacity: .4 - }); - }); - - function showPreview(coords) { - var rx = 96 / coords.w; - var ry = 96 / coords.h; - - var img_width = $("#photo_original img").attr("width"); - var img_height = $("#photo_original img").attr("height"); - - $('#photo_preview img').css({ - width: Math.round(rx *img_width) + 'px', - height: Math.round(ry * img_height) + 'px', - marginLeft: '-' + Math.round(rx * coords.x) + 'px', - marginTop: '-' + Math.round(ry * coords.y) + 'px' - }); - }; - - function updateCoords(c) { - $('#photo_crop_x').val(c.x); - $('#photo_crop_y').val(c.y); - $('#photo_crop_w').val(c.w); - $('#photo_crop_h').val(c.h); - }; - - function checkCoords() { - if (parseInt($('#photo_crop_w').val())) return true; - alert('Please select a crop region then press submit.'); - return false; - }; - diff --git a/js/util.js b/js/util.js index bb68c25879..579b4952ae 100644 --- a/js/util.js +++ b/js/util.js @@ -108,16 +108,16 @@ $(document).ready(function(){ $("form.form_group_join").each(addAjaxHidden); $("form.form_group_leave").each(addAjaxHidden); - $("#nudge").ajaxForm ({ dataType: 'xml', - beforeSubmit: function(xml) { $("form#nudge input[type=submit]").attr("disabled", "disabled"); - $("form#nudge input[type=submit]").addClass("disabled"); - }, - success: function(xml) { $("#nudge").replaceWith(document._importNode($("#nudge_response", xml).get(0),true)); - $("#nudge input[type=submit]").removeAttr("disabled"); - $("#nudge input[type=submit]").removeClass("disabled"); - } - }); - $("#nudge").each(addAjaxHidden); + $("#form_user_nudge").ajaxForm ({ dataType: 'xml', + beforeSubmit: function(xml) { $("#form_user_nudge input[type=submit]").attr("disabled", "disabled"); + $("#form_user_nudge input[type=submit]").addClass("disabled"); + }, + success: function(xml) { $("#form_user_nudge").replaceWith(document._importNode($("#nudge_response", xml).get(0),true)); + $("#form_user_nudge input[type=submit]").removeAttr("disabled"); + $("#form_user_nudge input[type=submit]").removeClass("disabled"); + } + }); + $("#form_user_nudge").each(addAjaxHidden); var Subscribe = { dataType: 'xml', beforeSubmit: function(formData, jqForm, options) { $(".form_user_subscribe input[type=submit]").attr("disabled", "disabled"); diff --git a/lib/action.php b/lib/action.php index 5987abf3c3..bf053424f1 100644 --- a/lib/action.php +++ b/lib/action.php @@ -53,7 +53,6 @@ require_once INSTALLDIR.'/lib/htmloutputter.php'; * * @see HTMLOutputter */ - class Action extends HTMLOutputter // lawsuit { var $args; @@ -69,20 +68,30 @@ class Action extends HTMLOutputter // lawsuit * @see XMLOutputter::__construct * @see HTMLOutputter::__construct */ - function __construct($output='php://output', $indent=true) { parent::__construct($output, $indent); } - // For initializing members of the class + /** + * For initializing members of the class. + * + * @param array $argarray misc. arguments + * + * @return boolean true + */ function prepare($argarray) { $this->args =& common_copy_args($argarray); return true; } + /** + * Show page, a template method. + * + * @return nothing + */ function showPage() { $this->startHTML(); @@ -91,6 +100,11 @@ class Action extends HTMLOutputter // lawsuit $this->endHTML(); } + /** + * Show head, a template method. + * + * @return nothing + */ function showHead() { // XXX: attributes (profile?) @@ -105,6 +119,11 @@ class Action extends HTMLOutputter // lawsuit $this->elementEnd('head'); } + /** + * Show title, a template method. + * + * @return nothing + */ function showTitle() { $this->element('title', null, @@ -113,13 +132,24 @@ class Action extends HTMLOutputter // lawsuit common_config('site', 'name'))); } - // SHOULD overload + /** + * Returns the page title + * + * SHOULD overload + * + * @return string page title + */ function title() { return _("Untitled page"); } + /** + * Show stylesheets + * + * @return nothing + */ function showStylesheets() { $this->element('link', array('rel' => 'stylesheet', @@ -145,6 +175,11 @@ class Action extends HTMLOutputter // lawsuit } } + /** + * Show javascript headers + * + * @return nothing + */ function showScripts() { $this->element('script', array('type' => 'text/javascript', @@ -161,38 +196,66 @@ class Action extends HTMLOutputter // lawsuit ' '); } + /** + * Show OpenSearch headers + * + * @return nothing + */ function showOpenSearch() { - $this->element('link', array('rel' => 'search', 'type' => 'application/opensearchdescription+xml', + $this->element('link', array('rel' => 'search', + 'type' => 'application/opensearchdescription+xml', 'href' => common_local_url('opensearch', array('type' => 'people')), 'title' => common_config('site', 'name').' People Search')); - $this->element('link', array('rel' => 'search', 'type' => 'application/opensearchdescription+xml', 'href' => common_local_url('opensearch', array('type' => 'notice')), 'title' => common_config('site', 'name').' Notice Search')); } - // MAY overload - + /** + * Show feed headers + * + * MAY overload + * + * @return nothing + */ function showFeeds() { // does nothing by default } - // SHOULD overload - + /** + * Show description. + * + * SHOULD overload + * + * @return nothing + */ function showDescription() { // does nothing by default } - // MAY overload - + /** + * Show extra stuff in . + * + * MAY overload + * + * @return nothing + */ function extraHead() { // does nothing by default } + + /** + * Show body. + * + * Calls template methods + * + * @return nothing + */ function showBody() { $this->elementStart('body', array('id' => $this->trimmed('action'))); @@ -204,6 +267,13 @@ class Action extends HTMLOutputter // lawsuit $this->elementEnd('body'); } + /** + * Show header of the page. + * + * Calls template methods + * + * @return nothing + */ function showHeader() { $this->elementStart('div', array('id' => 'header')); @@ -218,14 +288,18 @@ class Action extends HTMLOutputter // lawsuit $this->elementEnd('div'); } + /** + * Show configured logo. + * + * @return nothing + */ function showLogo() { $this->elementStart('address', array('id' => 'site_contact', 'class' => 'vcard')); $this->elementStart('a', array('class' => 'url home bookmark', 'href' => common_local_url('public'))); - if (common_config('site', 'logo') || file_exists(theme_file('logo.png'))) - { + if (common_config('site', 'logo') || file_exists(theme_file('logo.png'))) { $this->element('img', array('class' => 'logo photo', 'src' => (common_config('site', 'logo')) ? common_config('site', 'logo') : theme_path('logo.png'), 'alt' => common_config('site', 'name'))); @@ -235,6 +309,11 @@ class Action extends HTMLOutputter // lawsuit $this->elementEnd('address'); } + /** + * Show primary navigation. + * + * @return nothing + */ function showPrimaryNav() { $this->elementStart('dl', array('id' => 'site_nav_global_primary')); @@ -271,10 +350,15 @@ class Action extends HTMLOutputter // lawsuit $this->elementEnd('dd'); $this->elementEnd('dl'); } - - // Revist. Should probably do an hAtom pattern here + + /** + * Show site notice. + * + * @return nothing + */ function showSiteNotice() { + // Revist. Should probably do an hAtom pattern here $text = common_config('site', 'notice'); if ($text) { $this->elementStart('dl', array('id' => 'site_notice', @@ -285,19 +369,38 @@ class Action extends HTMLOutputter // lawsuit } } - // MAY overload if no notice form needed... or direct message box???? - + /** + * Show notice form. + * + * MAY overload if no notice form needed... or direct message box???? + * + * @return nothing + */ function showNoticeForm() { $notice_form = new NoticeForm($this); $notice_form->show(); } - + + /** + * Show anonymous message. + * + * SHOULD overload + * + * @return nothing + */ function showAnonymousMessage() { // needs to be defined by the class } + /** + * Show core. + * + * Shows local navigation, content block and aside. + * + * @return nothing + */ function showCore() { $this->elementStart('div', array('id' => 'core')); @@ -307,6 +410,11 @@ class Action extends HTMLOutputter // lawsuit $this->elementEnd('div'); } + /** + * Show local navigation block. + * + * @return nothing + */ function showLocalNavBlock() { $this->elementStart('dl', array('id' => 'site_nav_local_views')); @@ -317,13 +425,23 @@ class Action extends HTMLOutputter // lawsuit $this->elementEnd('dl'); } - // SHOULD overload - + /** + * Show local navigation. + * + * SHOULD overload + * + * @return nothing + */ function showLocalNav() { // does nothing by default } + /** + * Show content block. + * + * @return nothing + */ function showContentBlock() { $this->elementStart('div', array('id' => 'content')); @@ -336,10 +454,21 @@ class Action extends HTMLOutputter // lawsuit $this->elementEnd('div'); } - function showPageTitle() { - $this->element('h1', NULL, $this->title()); + /** + * Show page title. + * + * @return nothing + */ + function showPageTitle() + { + $this->element('h1', null, $this->title()); } + /** + * Show page notice block. + * + * @return nothing + */ function showPageNoticeBlock() { $this->elementStart('dl', array('id' => 'page_notice', @@ -349,20 +478,35 @@ class Action extends HTMLOutputter // lawsuit $this->showPageNotice(); $this->elementEnd('dd'); $this->elementEnd('dl'); - } - - // SHOULD overload (unless there's not a notice) + } + /** + * Show page notice. + * + * SHOULD overload (unless there's not a notice) + * + * @return nothing + */ function showPageNotice() { } - // MUST overload - + /** + * Show content. + * + * MUST overload (unless there's not a notice) + * + * @return nothing + */ function showContent() { } + /** + * Show Aside. + * + * @return nothing + */ function showAside() { $this->elementStart('div', array('id' => 'aside_primary', @@ -372,8 +516,13 @@ class Action extends HTMLOutputter // lawsuit $this->elementEnd('div'); } - // MAY overload if there are feeds - + /** + * Show export data feeds. + * + * MAY overload if there are feeds + * + * @return nothing + */ function showExportData() { // is there structure to this? @@ -381,12 +530,23 @@ class Action extends HTMLOutputter // lawsuit // can we reuse list of feeds from showFeeds() ? } - // SHOULD overload - - function showSections() { + /** + * Show sections. + * + * SHOULD overload + * + * @return nothing + */ + function showSections() + { // for each section, show it } + /** + * Show footer. + * + * @return nothing + */ function showFooter() { $this->elementStart('div', array('id' => 'footer')); @@ -395,6 +555,11 @@ class Action extends HTMLOutputter // lawsuit $this->elementEnd('div'); } + /** + * Show secondary navigation. + * + * @return nothing + */ function showSecondaryNav() { $this->elementStart('dl', array('id' => 'site_nav_global_secondary')); @@ -418,6 +583,11 @@ class Action extends HTMLOutputter // lawsuit $this->elementEnd('dl'); } + /** + * Show licenses. + * + * @return nothing + */ function showLicenses() { $this->elementStart('dl', array('id' => 'licenses')); @@ -426,6 +596,11 @@ class Action extends HTMLOutputter // lawsuit $this->elementEnd('dl'); } + /** + * Show Laconica license. + * + * @return nothing + */ function showLaconicaLicense() { $this->element('dt', array('id' => 'site_laconica_license'), _('Laconica software license')); @@ -442,6 +617,11 @@ class Action extends HTMLOutputter // lawsuit // do it } + /** + * Show content license. + * + * @return nothing + */ function showContentLicense() { $this->element('dt', array('id' => 'site_content_license'), _('Laconica software license')); @@ -461,24 +641,52 @@ class Action extends HTMLOutputter // lawsuit $this->elementEnd('dd'); } - // For comparison with If-Last-Modified - // If not applicable, return null - + /** + * Return last modified, if applicable. + * + * MAY override + * + * @return string last modified http header + */ function lastModified() { + // For comparison with If-Last-Modified + // If not applicable, return null return null; } + /** + * Return etag, if applicable. + * + * MAY override + * + * @return string etag http header + */ function etag() { return null; } + /** + * Return true if read only. + * + * MAY override + * + * @return boolean is read only action? + */ function isReadOnly() { return false; } + /** + * Returns query argument or default value if not found + * + * @param string $key requested argument + * @param string $def default value to return if $key is not provided + * + * @return boolean is read only action? + */ function arg($key, $def=null) { if (array_key_exists($key, $this->args)) { @@ -488,24 +696,34 @@ class Action extends HTMLOutputter // lawsuit } } + /** + * Returns trimmed query argument or default value if not found + * + * @param string $key requested argument + * @param string $def default value to return if $key is not provided + * + * @return boolean is read only action? + */ function trimmed($key, $def=null) { $arg = $this->arg($key, $def); - return (is_string($arg)) ? trim($arg) : $arg; + return is_string($arg) ? trim($arg) : $arg; } - // Note: argarray ignored, since it's now passed in in prepare() - + /** + * Handler method + * + * @param array $argarray is ignored since it's now passed in in prepare() + * + * @return boolean is read only action? + */ function handle($argarray=null) { - - $lm = $this->lastModified(); + $lm = $this->lastModified(); $etag = $this->etag(); - if ($etag) { header('ETag: ' . $etag); } - if ($lm) { header('Last-Modified: ' . date(DATE_RFC1123, $lm)); $if_modified_since = $_SERVER['HTTP_IF_MODIFIED_SINCE']; @@ -523,11 +741,27 @@ class Action extends HTMLOutputter // lawsuit } } + /** + * HasĀ etag? (private) + * + * @param string $etag etag http header + * @param string $if_none_match ifNoneMatch http header + * + * @return boolean + */ function _hasEtag($etag, $if_none_match) { return ($if_none_match) && in_array($etag, explode(',', $if_none_match)); } + /** + * Boolean understands english (yes, no, true, false) + * + * @param string $key query key we're interested in + * @param string $def default value + * + * @return boolean interprets yes/no strings as boolean + */ function boolean($key, $def=false) { $arg = strtolower($this->trimmed($key)); @@ -543,6 +777,14 @@ class Action extends HTMLOutputter // lawsuit } } + /** + * Server error + * + * @param string $msg error message to display + * @param integer $code http error code, 500 by default + * + * @return nothing + */ function serverError($msg, $code=500) { $action = $this->trimmed('action'); @@ -550,6 +792,14 @@ class Action extends HTMLOutputter // lawsuit common_server_error($msg, $code); } + /** + * Client error + * + * @param string $msg error message to display + * @param integer $code http error code, 400 by default + * + * @return nothing + */ function clientError($msg, $code=400) { $action = $this->trimmed('action'); @@ -557,10 +807,15 @@ class Action extends HTMLOutputter // lawsuit common_user_error($msg, $code); } + /** + * Returns the current URL + * + * @return string current URL + */ function selfUrl() { $action = $this->trimmed('action'); - $args = $this->args; + $args = $this->args; unset($args['action']); foreach (array_keys($_COOKIE) as $cookie) { unset($args[$cookie]); @@ -568,11 +823,21 @@ class Action extends HTMLOutputter // lawsuit return common_local_url($action, $args); } - // Added @id to li for some control. - // XXX: We might want to move this to htmloutputter.php - + /** + * Generate a menu item + * + * @param string $url menu URL + * @param string $text menu name + * @param string $title title attribute, null by default + * @param boolean $is_selected current menu item, false by default + * @param string $id element id, null by default + * + * @return nothing + */ function menuItem($url, $text, $title=null, $is_selected=false, $id=null) { + // Added @id to li for some control. + // XXX: We might want to move this to htmloutputter.php $lattrs = array(); if ($is_selected) { $lattrs['class'] = 'current'; @@ -589,10 +854,20 @@ class Action extends HTMLOutputter // lawsuit $this->elementEnd('li'); } - // Does a little before-after block for next/prev page - + /** + * Generate pagination links + * + * @param boolean $have_before is there something before? + * @param boolean $have_after is there something after? + * @param integer $page current page + * @param string $action current action + * @param array $args rest of query arguments + * + * @return nothing + */ function pagination($have_before, $have_after, $page, $action, $args=null) { + // Does a little before-after block for next/prev page if ($have_before || $have_after) { $this->elementStart('div', array('class' => 'pagination')); $this->elementStart('dl', null); @@ -600,26 +875,22 @@ class Action extends HTMLOutputter // lawsuit $this->elementStart('dd', null); $this->elementStart('ul', array('class' => 'nav')); } - if ($have_before) { - $pargs = array('page' => $page-1); - $newargs = ($args) ? array_merge($args,$pargs) : $pargs; - + $pargs = array('page' => $page-1); + $newargs = $args ? array_merge($args, $pargs) : $pargs; $this->elementStart('li', array('class' => 'nav_prev')); $this->element('a', array('href' => common_local_url($action, $newargs), 'rel' => 'prev'), _('After')); $this->elementEnd('li'); } - if ($have_after) { - $pargs = array('page' => $page+1); - $newargs = ($args) ? array_merge($args,$pargs) : $pargs; + $pargs = array('page' => $page+1); + $newargs = $args ? array_merge($args, $pargs) : $pargs; $this->elementStart('li', array('class' => 'nav_next')); $this->element('a', array('href' => common_local_url($action, $newargs), 'rel' => 'next'), _('Before')); $this->elementEnd('li'); } - if ($have_before || $have_after) { $this->elementEnd('ul'); $this->elementEnd('dd'); diff --git a/lib/blockform.php b/lib/blockform.php index ea22c1cec0..af766b8237 100644 --- a/lib/blockform.php +++ b/lib/blockform.php @@ -150,6 +150,6 @@ class BlockForm extends Form function formActions() { - $this->out->submit('submit', _('block'), 'submit', null, _('Block this user')); + $this->out->submit('submit', _('Block'), 'submit', null, _('Block this user')); } } diff --git a/lib/error.php b/lib/error.php new file mode 100644 index 0000000000..9842053d88 --- /dev/null +++ b/lib/error.php @@ -0,0 +1,136 @@ + + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * + * Laconica - a distributed open-source microblogging tool + * Copyright (C) 2008, Controlez-Vous, 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 . + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Base class for displaying HTTP errors + * + * @category Action + * @package Laconica + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ +class ErrorAction extends Action +{ + var $code = null; + var $message = null; + var $status = null; + var $default = null; + + function __construct($message, $code, $output='php://output', $indent=true) + { + parent::__construct($output, $indent); + + $this->code = $code; + $this->message = $message; + + // XXX: hack alert: usually we aren't going to + // call this page directly, but because it's + // an action it needs an args array anyway + $this->prepare($_REQUEST); + } + + /** + * To specify additional HTTP headers for the action + * + * @return void + */ + function extraHeaders() + { + $status_string = $this->status[$this->code]; + header('HTTP/1.1 '.$this->code.' '.$status_string); + } + + /** + * Display content. + * + * @return nothing + */ + function showContent() + { + $this->element('div', array('class' => 'error'), $this->message); + } + + /** + * Page title. + * + * @return page title + */ + function title() + { + return $this->message; + } + + function isReadOnly() + { + return true; + } + + function showPage() + { + parent::showPage(); + + // We don't want to have any more output after this + exit(); + } + + // Overload a bunch of stuff so the page isn't too bloated + + function showBody() + { + $this->elementStart('body', array('id' => 'error')); + $this->elementStart('div', 'wrap'); + $this->showHeader(); + $this->showCore(); + $this->showFooter(); + $this->elementEnd('div'); + $this->elementEnd('body'); + } + + function showCore() + { + $this->elementStart('div', array('id' => 'core')); + $this->showContentBlock(); + $this->elementEnd('div'); + } + + function showHeader() + { + $this->elementStart('div', array('id' => 'header')); + $this->showLogo(); + $this->elementEnd('div'); + } + +} diff --git a/lib/groupeditform.php b/lib/groupeditform.php index f6e326078a..ca674f3c8e 100644 --- a/lib/groupeditform.php +++ b/lib/groupeditform.php @@ -78,9 +78,9 @@ class GroupEditForm extends Form function id() { if ($this->group) { - return 'group_edit-' . $this->group->id; + return 'form_group_edit-' . $this->group->id; } else { - return 'group_add'; + return 'form_group_add'; } } @@ -92,7 +92,7 @@ class GroupEditForm extends Form function formClass() { - return 'form_group_add'; + return 'form_settings'; } /** @@ -111,6 +111,18 @@ class GroupEditForm extends Form } } + + /** + * Name of the form + * + * @return void + */ + + function formLegend() + { + $this->out->element('legend', null, _('Create a new group')); + } + /** * Data elements of the form * @@ -121,6 +133,7 @@ class GroupEditForm extends Form { $this->out->elementStart('ul', 'form_data'); $this->out->elementStart('li'); + $this->out->hidden('groupid', $this->group->id); $this->out->input('nickname', _('Nickname'), ($this->out->arg('nickname')) ? $this->out->arg('nickname') : $this->group->nickname, _('1-64 lowercase letters or numbers, no punctuation or spaces')); @@ -135,7 +148,7 @@ class GroupEditForm extends Form _('URL of the homepage or blog of the group or topic')); $this->out->elementEnd('li'); $this->out->elementStart('li'); - $this->out->textarea('description', _('description'), + $this->out->textarea('description', _('Description'), ($this->out->arg('description')) ? $this->out->arg('description') : $this->group->description, _('Describe the group or topic in 140 chars')); $this->out->elementEnd('li'); diff --git a/lib/groupminilist.php b/lib/groupminilist.php index e4d4c68fd1..fe38d03403 100644 --- a/lib/groupminilist.php +++ b/lib/groupminilist.php @@ -49,7 +49,7 @@ class GroupMiniList extends GroupList { function show() { - $this->out->elementStart('ul', 'groups'); + $this->out->elementStart('ul', 'entities groups xoxo'); $cnt = 0; @@ -73,7 +73,7 @@ class GroupMiniList extends GroupList $this->group->fullname : $this->group->nickname, 'href' => $this->group->homeUrl(), - 'rel' => 'contact', + 'rel' => 'contact group', 'class' => 'url')); $logo = ($this->group->stream_logo) ? $this->group->stream_logo : User_group::defaultLogo(AVATAR_STREAM_SIZE); @@ -85,7 +85,7 @@ class GroupMiniList extends GroupList 'alt' => ($this->group->fullname) ? $this->group->fullname : $this->group->nickname)); - $this->out->element('span', 'fn nickname', $this->group->nickname); + $this->out->element('span', 'fn org nickname', $this->group->nickname); $this->out->elementEnd('a'); $this->out->elementEnd('li'); } diff --git a/lib/htmloutputter.php b/lib/htmloutputter.php index 1e164933ce..f9245414f2 100644 --- a/lib/htmloutputter.php +++ b/lib/htmloutputter.php @@ -108,6 +108,8 @@ class HTMLOutputter extends XMLOutputter } header('Content-Type: '.$type); + + $this->extraHeaders(); $this->startXML('html', '-//W3C//DTD XHTML 1.0 Strict//EN', @@ -132,6 +134,16 @@ class HTMLOutputter extends XMLOutputter $this->elementEnd('html'); $this->endXML(); } + + /** + * To specify additional HTTP headers for the action + * + * @return void + */ + function extraHeaders() + { + // Needs to be overloaded + } /** * Output an HTML text input element diff --git a/lib/profilelist.php b/lib/profilelist.php index f7ed5d19c6..73c129efe8 100644 --- a/lib/profilelist.php +++ b/lib/profilelist.php @@ -93,8 +93,7 @@ class ProfileList extends Widget $user = common_current_user(); - $this->out->elementStart('div', array('id' => 'user_profile', - 'class' => 'vcard')); + $this->out->elementStart('div', 'entity_profile vcard'); $avatar = $this->profile->getAvatar(AVATAR_STREAM_SIZE); $this->out->elementStart('a', array('href' => $this->profile->profileurl, @@ -113,7 +112,7 @@ class ProfileList extends Widget $this->out->elementEnd('a'); if ($this->profile->fullname) { - $this->out->elementStart('dl', 'user_fn'); + $this->out->elementStart('dl', 'entity_fn'); $this->out->element('dt', null, 'Full name'); $this->out->elementStart('dd'); $this->out->elementStart('span', 'fn'); @@ -123,7 +122,7 @@ class ProfileList extends Widget $this->out->elementEnd('dl'); } if ($this->profile->location) { - $this->out->elementStart('dl', 'user_location'); + $this->out->elementStart('dl', 'entity_location'); $this->out->element('dt', null, _('Location')); $this->out->elementStart('dd', 'location'); $this->out->raw($this->highlight($this->profile->location)); @@ -131,7 +130,7 @@ class ProfileList extends Widget $this->out->elementEnd('dl'); } if ($this->profile->homepage) { - $this->out->elementStart('dl', 'user_url'); + $this->out->elementStart('dl', 'entity_url'); $this->out->element('dt', null, _('URL')); $this->out->elementStart('dd'); $this->out->elementStart('a', array('href' => $this->profile->homepage, @@ -142,7 +141,7 @@ class ProfileList extends Widget $this->out->elementEnd('dl'); } if ($this->profile->bio) { - $this->out->elementStart('dl', 'user_note'); + $this->out->elementStart('dl', 'entity_note'); $this->out->element('dt', null, _('Note')); $this->out->elementStart('dd', 'note'); $this->out->raw($this->highlight($this->profile->bio)); @@ -156,7 +155,7 @@ class ProfileList extends Widget # Get tags $tags = Profile_tag::getTags($this->owner->id, $this->profile->id); - $this->out->elementStart('dl', 'user_tags'); + $this->out->elementStart('dl', 'entity_tags'); $this->out->elementStart('dt'); if ($user->id == $this->owner->id) { $this->out->element('a', array('href' => common_local_url('tagother', diff --git a/lib/profileminilist.php b/lib/profileminilist.php index c6970f8088..56b7684194 100644 --- a/lib/profileminilist.php +++ b/lib/profileminilist.php @@ -49,7 +49,7 @@ class ProfileMiniList extends ProfileList { function show() { - $this->out->elementStart('ul', 'users'); + $this->out->elementStart('ul', 'entities users xoxo'); $cnt = 0; @@ -73,7 +73,7 @@ class ProfileMiniList extends ProfileList $this->profile->fullname : $this->profile->nickname, 'href' => $this->profile->profileurl, - 'rel' => 'contact', + 'rel' => 'contact member', 'class' => 'url')); $avatar = $this->profile->getAvatar(AVATAR_MINI_SIZE); $this->out->element('img', array('src' => (($avatar) ? common_avatar_display_url($avatar) : common_default_avatar(AVATAR_MINI_SIZE)), diff --git a/lib/util.php b/lib/util.php index 4f791a493c..d30a56c77e 100644 --- a/lib/util.php +++ b/lib/util.php @@ -1588,11 +1588,6 @@ function common_session_token() return $_SESSION['token']; } -function common_nudge_response() -{ - common_element('p', array('id' => 'nudge_response'), _('Nudge sent!')); -} - function common_cache_key($extra) { return 'laconica:' . common_keyize(common_config('site', 'name')) . ':' . $extra; diff --git a/theme/base/css/display.css b/theme/base/css/display.css index c16fa4ab07..91789f4f18 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -17,8 +17,8 @@ width:1004px; width:71.714em; } h1,h2,h3,h4,h5,h6 { - text-transform:uppercase; - margin-bottom:7px; +text-transform:uppercase; +margin-bottom:7px; } h1 { font-size:1.4em; @@ -34,8 +34,6 @@ h6 { font-size:0.9em; } caption { font-weight:bold; } -.opened { display: block !important;} -.closed { display: none !important;} legend { font-weight:bold; @@ -56,6 +54,7 @@ border-radius:4px; -moz-border-radius:4px; -webkit-border-radius:4px; } + input.submit { font-weight:bold; } @@ -79,9 +78,6 @@ form label { font-weight:bold; /*margin:0 0 11px 0;*/ } -form ul li input { -} - input.checkbox { position:relative; top:2px; @@ -147,7 +143,11 @@ font-weight:bold; #form_settings_profile legend, #form_login legend, -#form_register legend { +#form_register legend, +#form_password legend, +#form_settings_avatar legend, +#newgroup legend, +#editgroup legend { display:none; } @@ -187,6 +187,8 @@ border-radius:4px; padding:0 7px; } + + /* FORM SETTINGS */ @@ -443,7 +445,7 @@ margin-left:4px; #form_notice .form_note { position:absolute; -top:120px; +top:118px; right:98px; z-index:9; } @@ -455,10 +457,11 @@ display:none; #notice_text-count { font-weight:bold; line-height:1.15; +padding:1px 2px; } #form_notice #notice_data-attach_view { -/*position:absolute;*/ +position:absolute; top:25px; right:30px; margin-left:4px; @@ -502,8 +505,8 @@ float:left; -/* user_profile */ -#user_profile { +/* entity_profile */ +.entity_profile { position:relative; width:475px; min-height:123px; @@ -511,23 +514,23 @@ float:left; margin-bottom:17px; margin-left:0; } -#user_profile dt, -#user_statistics dt { +.entity_profile dt, +#entity_statistics dt { font-weight:bold; } -#user_profile .user_depiction { +.entity_profile .entity_depiction { float:left; position:absolute; top:0; left:0; width:96px; } -#user_profile .user_fn, -#user_profile .user_nickname, -#user_profile .user_location, -#user_profile .user_url, -#user_profile .user_note, -#user_profile .user_tags { +.entity_profile .entity_fn, +.entity_profile .entity_nickname, +.entity_profile .entity_location, +.entity_profile .entity_url, +.entity_profile .entity_note, +.entity_profile .entity_tags { float:left; clear:left; margin-left:113px; @@ -535,84 +538,82 @@ width:322px; margin-bottom:4px; } -#user_profile .user_fn, -#user_profile .user_nickname { +.entity_profile .entity_fn, +.entity_profile .entity_nickname { width:auto; clear:none; } -#user_profile .user_fn { + +.entity_profile .entity_fn { margin-left:11px; margin-right:4px; } -#user_profile .user_fn .fn { +.entity_profile .entity_fn .fn { font-weight:bold; font-style:normal; } -#user_profile .nickname { +.entity_profile .nickname { font-style:italic; font-weight:bold; } -#user_profile .user_fn dd:before { +.entity_profile .entity_fn dd:before { content: "("; font-weight:normal; } -#user_profile .user_fn dd:after { +.entity_profile .entity_fn dd:after { content: ")"; font-weight:normal; } -#user_profile dt { +.entity_profile dt { display:none; } -#user_profile h2 { +.entity_profile h2 { display:none; } -/* user_profile */ +/* entity_profile */ -/*user_actions*/ -#user_actions { -clear:left; -float:left; -position:absolute; -top:0; -right:0; +/*entity_actions*/ +.entity_actions { +float:right; + } -#user_actions h2 { +.entity_actions h2 { display:none; } -#user_actions ul { +.entity_actions ul { list-style-type:none; } -#user_actions li { +.entity_actions li { margin-bottom:4px; } -#user_actions li:first-child { +.entity_actions li:first-child { border-top:0; } -#user_actions fieldset { +.entity_actions fieldset { border:0; padding:0; } -#user_actions legend { +.entity_actions legend { display:none; } -#user_actions input.submit { +.entity_actions input.submit { display:block; text-align:left; cursor:pointer; width:100%; } -#user_actions a { +.entity_actions a, +#entity_nudge p { text-decoration:none; font-weight:bold; -width:100%; display:block; } @@ -620,35 +621,24 @@ display:block; .form_user_block input.submit, .form_user_unblock input.submit, -#user_send-a-message a, -.form_user_nudge input.submit { +#entity_send-a-message a, +.form_user_nudge input.submit, +#entity_nudge p { border:0; padding-left:20px; } -#user_send-a-message a { +#entity_send-a-message a, +#entity_nudge p { padding:4px 4px 4px 23px; - -} - - -#user_subscribe input.submit, -.form_user_subscribe input.submit { - } -#user_send-a-message form { -} - -#user_send-a-message textarea { -} - -.user_tags ul { +.entity_tags ul { list-style-type:none; } -.user_tags li { +.entity_tags li { display:inline; margin-right:1em; float:left; @@ -659,41 +649,43 @@ float:left; .aside .section { margin-bottom:29px; clear:both; +float:left; +width:100%; } .aside .section h2 { text-transform:uppercase; font-size:1em; } -#user_statistics dt, -#user_statistics dd { +#entity_statistics dt, +#entity_statistics dd { display:inline; } -#user_statistics dt:after { +#entity_statistics dt:after { content: ":"; } #user_subscriptions, -#user_subscriptions-common { -float:left; +#user_subscribers, +#user_groups, { + } -#user_subscriptions ul.users { +.section ul.entities { width:220px; float:left; } -#user_subscriptions .users li { +.section .entities li { list-style-type:none; float:left; margin-right:7px; margin-bottom:7px; } -#user_subscriptions .users li .photo { -width:24px; -height:24px; +.section .entities li .photo { margin-right:0; +margin-bottom:0; } -#user_subscriptions .users li .fn { +.section .entities li .fn { display:none; } .aside .section .more { @@ -702,29 +694,36 @@ clear:both; -.profile #user_profile { +.profile .entity_profile { margin-bottom:0; min-height:60px; } +.profile .form_user_subscribe, .profile .form_user_unsubscribe { float:right; } +.profile .form_user_subscribe legend, +.profile .form_user_unsubscribe legend { +display:none; +} + + .profiles { list-style-type:none; } -.profile #user_profile .user_location { +.profile .entity_profile .entity_location { width:auto; clear:none; margin-left:11px; } -.profile #user_profile dl, -.profile #user_profile dd { +.profile .entity_profile dl, +.profile .entity_profile dd { display:inline; float:none; } -.profile #user_profile .user_note, -.profile #user_profile .user_url { +.profile .entity_profile .entity_note, +.profile .entity_profile .entity_url { margin-left:59px; clear:none; display:block; @@ -933,7 +932,7 @@ outline:none; } .notice-options .notice_reply a, -.notice-options form input.submit { +.notice-options input.submit { display:block; border:0; } @@ -1016,18 +1015,18 @@ border-right:0; -/*If there is hentry on #content_inner, this doesn't need to be specific to #doc */ -#doc #content_inner p { +/*If there is hentry on #content_inner, then this doesn't need to be specific to #doc or any other section */ +.hentry .entry-content p { margin-bottom:18px; } -#doc #content_inner ol, -#doc #content_inner ul { +.hentry entry-content ol, +.hentry .entry-content ul { list-style-position:inside; } -#doc #content_inner li { +.hentry .entry-content li { margin-bottom:18px; } -#doc #content_inner li li { +.hentry .entry-content li li { margin-left:18px; } @@ -1049,9 +1048,9 @@ background-color:#D1D9E4; -#user_actions #user_subscribe .form_note, -#user_actions #user_subscribe .form_data, -#user_actions #user_subscribe .form_actions label { +.entity_actions #user_subscribe .form_note, +.entity_actions #user_subscribe .form_data, +.entity_actions #user_subscribe .form_actions label { display:none; } #form_user-relationship .form_note, @@ -1060,7 +1059,7 @@ display:none; display:block; } -#user_actions #user-relationship_submit { +.entity_actions #user-relationship_submit { margin-bottom:0; } #form_user-relationship .form_data li label { @@ -1160,52 +1159,65 @@ clear:both; - -#photo_original, -#photo_preview { +#form_settings_avatar li { +width:auto; +} +#form_settings_avatar input { +margin-left:0; +} +#avatar_original, +#avatar_preview { float:left; } -#photo_preview, -#settings_photo_action-crop { +#avatar_preview { margin-left:29px; } -#photo_preview_view { +#avatar_preview_view { height:96px; width:96px; +margin-bottom:18px; overflow:hidden; } +#settings_attach, +#form_settings_avatar .form_actions { +clear:both; +} + +#form_settings_avatar .form_actions { +margin-bottom:0; +} -.section .groups, +#groups_related ul, #users_featured ul { list-style-type:none; } -.section .groups li, +#groups_related li, #users_featured li { margin-top:11px; float:left; width:100%; } -.section .groups li:first-child, +#groups_related li:first-child, #users_featured li:first-child { margin-top:0; } -.section .groups .vcard, +#groups_related .vcard, #users_featured .vcard { float:left; margin-bottom:-23px; } -.section .groups dl, +#groups_related dl, #users_featured dl { float:left; margin-left:63px; clear:left; } -.section .groups dt, +#groups_related dt, #users_featured dt { display:none; font-weight:bold; diff --git a/theme/base/css/ie.css b/theme/base/css/ie.css index 9baa953b38..08b027b590 100644 --- a/theme/base/css/ie.css +++ b/theme/base/css/ie.css @@ -3,7 +3,7 @@ #aside_primary { padding-left:11px; } -.notice-options form input.submit { +.notice-options input.submit { font-size:0; margin-top:3px; height:16px; @@ -23,4 +23,8 @@ margin-left:-7px; .notice div.entry-content .timestamp a { margin-right:4px; -} \ No newline at end of file +} + +.entity_profile .entity_nickname { +padding-right:3px; +} diff --git a/theme/base/css/ie6.css b/theme/base/css/ie6.css new file mode 100644 index 0000000000..4a2316903d --- /dev/null +++ b/theme/base/css/ie6.css @@ -0,0 +1,8 @@ +/* IE6 specific styles */ +.entity_profile .entity_nickname, +.entity_profile .entity_location, +.entity_profile .entity_url, +.entity_profile .entity_note, +.entity_profile .entity_tags { +margin-left:55px; +} diff --git a/theme/base/css/ie7.css b/theme/base/css/ie7.css index a6e2548ab0..a6ee001e27 100644 --- a/theme/base/css/ie7.css +++ b/theme/base/css/ie7.css @@ -2,4 +2,4 @@ #form_notice textarea { width:370px; -} \ No newline at end of file +} diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index 2b91c55042..1df14a7f14 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -22,6 +22,7 @@ input, textarea, select { border-color:#aaa; } + input.submit, #form_notice.warning #notice_text-count, #nav_register a, @@ -42,8 +43,9 @@ a, div.notice-options input, .form_user_block input.submit, .form_user_unblock input.submit, -#user_send-a-message a, -.form_user_nudge input.submit { +#entity_send-a-message a, +.form_user_nudge input.submit, +#entity_nudge p { color:#002E6E; } @@ -55,7 +57,7 @@ background-color:#fcfffc; } #aside_primary, -#user_subscribe a, +#entity_subscribe a, #TB_window input.submit, .form_user_subscribe input.submit { background-color:#CEE1E9; @@ -132,26 +134,31 @@ background-image:url(../../base/images/icons/icon_vcard.gif); } -#user_send-a-message a, +#entity_send-a-message a, .form_user_nudge input.submit, .form_user_block input.submit, -.form_user_unblock input.submit { +.form_user_unblock input.submit, +#entity_nudge p { background-position: 0 40%; background-repeat: no-repeat; background-color:transparent; } +.form_group_join input.submit, +.form_group_leave input.submit .form_user_subscribe input.submit, .form_user_unsubscribe input.submit { background-color:#A9BF4F; color:#fff; } -.form_user_unsubscribe input.submit { +.form_user_unsubscribe input.submit, +.form_group_leave input.submit { background-color:#97BFD1; } -#user_send-a-message a { +#entity_send-a-message a { background-image:url(../images/icons/twotone/green/quote.gif); } +#entity_nudge p, .form_user_nudge input.submit { background-image:url(../images/icons/twotone/green/mail.gif); }