From d92a018cd2b199213cbd66f27dbabb460d3d55c9 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 22:44:01 -0400 Subject: get a design for each page --- lib/action.php | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/action.php b/lib/action.php index 6a69d2651..e8aba5b89 100644 --- a/lib/action.php +++ b/lib/action.php @@ -224,6 +224,16 @@ class Action extends HTMLOutputter // lawsuit 'href="'.theme_path('css/ie.css', null).'?version='.LACONICA_VERSION.'" />getDesign(); + if (!empty($design)) { + $cur = common_current_user(); + if (empty($cur) || $cur->viewdesigns) { + $design->showCSS($this); + } + } + Event::handle('EndShowDesign', array($this, $design)); + } Event::handle('EndShowStyles', array($this)); } } @@ -248,7 +258,6 @@ class Action extends HTMLOutputter // lawsuit 'src' => common_path('js/jquery.joverlay.min.js')), ' '); - Event::handle('EndShowJQueryScripts', array($this)); } if (Event::handle('StartShowLaconicaScripts', array($this))) { @@ -1095,4 +1104,19 @@ class Action extends HTMLOutputter // lawsuit 'title' => _('Previous'))); } } + + /** + * A design for this action + * + * A design (colors and background) for the current page. May be + * the user's design, or a group's design, or a site design. + * + * @return array Feed object to show in head and links + */ + + function getDesign() + { + // XXX: return site design by default + return null; + } } -- cgit v1.2.3-54-g00ecf From 4ec5ea510cd5be39c13c2cf3bc9f9c1c8ac5df82 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:09:01 -0400 Subject: fix return value documentation for getDesign --- lib/action.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/action.php b/lib/action.php index e8aba5b89..55fb7c089 100644 --- a/lib/action.php +++ b/lib/action.php @@ -1111,7 +1111,7 @@ class Action extends HTMLOutputter // lawsuit * A design (colors and background) for the current page. May be * the user's design, or a group's design, or a site design. * - * @return array Feed object to show in head and links + * @return Design a design object to use */ function getDesign() -- cgit v1.2.3-54-g00ecf From eaac0f8e58774a67fd9257ee0cd46c786cb5718b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:09:33 -0400 Subject: add an action base class for actions that show the owner's design --- lib/ownerdesignaction.php | 72 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 lib/ownerdesignaction.php (limited to 'lib') diff --git a/lib/ownerdesignaction.php b/lib/ownerdesignaction.php new file mode 100644 index 000000000..c47633bdb --- /dev/null +++ b/lib/ownerdesignaction.php @@ -0,0 +1,72 @@ +. + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @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); +} + +/** + * Base class for actions that use the page owner's design + * + * Some pages have a clear "owner" -- like the profile page, subscriptions + * pages, etc. This superclass uses that owner's chosen design for the page + * design. + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + * + */ + +class OwnerDesignAction extends Action { + + /** The user for this page. */ + + var $user = null; + + /** + * A design for this action + * + * if the user attribute has been set, returns that user's + * design. + * + * @return Design a design object to use + */ + + function getDesign() + { + if (empty($this->user)) { + return null; + } + + return $this->user->getDesign(); + } +} -- cgit v1.2.3-54-g00ecf From 63ad980767fc10053eea5a5ca009dda65af42de8 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:11:36 -0400 Subject: current user design action --- lib/currentuserdesignaction.php | 69 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 lib/currentuserdesignaction.php (limited to 'lib') diff --git a/lib/currentuserdesignaction.php b/lib/currentuserdesignaction.php new file mode 100644 index 000000000..297525655 --- /dev/null +++ b/lib/currentuserdesignaction.php @@ -0,0 +1,69 @@ +. + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @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); +} + +/** + * Base class for actions that use the current user's design + * + * Some pages (settings in particular) use the current user's chosen + * design. This superclass returns that design. + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + * + */ + +class CurrentUserDesignAction extends Action +{ + /** + * A design for this action + * + * if the user attribute has been set, returns that user's + * design. + * + * @return Design a design object to use + */ + + function getDesign() + { + $cur = common_current_user(); + + if (empty($cur)) { + return null; + } + + return $cur->getDesign(); + } +} -- cgit v1.2.3-54-g00ecf From 9c2f04afc6e70032da5aeb0441e6e0a9b0ffe253 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:35:04 -0400 Subject: make some of the actions show the user's design --- actions/replies.php | 3 +-- actions/showfavorites.php | 5 +---- actions/usergroups.php | 3 +-- lib/galleryaction.php | 3 +-- lib/profileaction.php | 3 +-- 5 files changed, 5 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/actions/replies.php b/actions/replies.php index dfb520d64..5d84f6428 100644 --- a/actions/replies.php +++ b/actions/replies.php @@ -45,9 +45,8 @@ require_once INSTALLDIR.'/lib/feedlist.php'; * @link http://laconi.ca/ */ -class RepliesAction extends Action +class RepliesAction extends OwnerDesignAction { - var $user = null; var $page = null; /** diff --git a/actions/showfavorites.php b/actions/showfavorites.php index eed62a2ab..839f083dd 100644 --- a/actions/showfavorites.php +++ b/actions/showfavorites.php @@ -45,10 +45,8 @@ require_once INSTALLDIR.'/lib/feedlist.php'; * @link http://laconi.ca/ */ -class ShowfavoritesAction extends Action +class ShowfavoritesAction extends OwnerDesignAction { - /** User we're getting the faves of */ - var $user = null; /** Page of the faves we're on */ var $page = null; @@ -161,7 +159,6 @@ class ShowfavoritesAction extends Action $this->page, 'showfavorites', array('nickname' => $this->user->nickname)); } - /** * show the personal group nav * diff --git a/actions/usergroups.php b/actions/usergroups.php index e3088dcbd..7ead6e6e4 100644 --- a/actions/usergroups.php +++ b/actions/usergroups.php @@ -46,9 +46,8 @@ require_once INSTALLDIR.'/lib/grouplist.php'; * @link http://laconi.ca/ */ -class UsergroupsAction extends Action +class UsergroupsAction extends OwnerDesignAction { - var $user = null; var $page = null; var $profile = null; diff --git a/lib/galleryaction.php b/lib/galleryaction.php index 8fa11a756..498c82851 100644 --- a/lib/galleryaction.php +++ b/lib/galleryaction.php @@ -27,10 +27,9 @@ require_once INSTALLDIR.'/lib/profilelist.php'; define('AVATARS_PER_PAGE', 80); -class GalleryAction extends Action +class GalleryAction extends OwnerDesignAction { var $profile = null; - var $user = null; var $page = null; var $tag = null; diff --git a/lib/profileaction.php b/lib/profileaction.php index a3437ff4d..a14d3846e 100644 --- a/lib/profileaction.php +++ b/lib/profileaction.php @@ -47,9 +47,8 @@ require_once INSTALLDIR.'/lib/groupminilist.php'; * @link http://laconi.ca/ */ -class ProfileAction extends Action +class ProfileAction extends OwnerDesignAction { - var $user = null; var $page = null; var $profile = null; var $tag = null; -- cgit v1.2.3-54-g00ecf From 91e088d341bc51a41ec310502f85bf0d2398bd90 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:40:11 -0400 Subject: make some actions CurrentUserDesignActions --- lib/mailbox.php | 8 ++++---- lib/settingsaction.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/mailbox.php b/lib/mailbox.php index 01bbf5721..766510a47 100644 --- a/lib/mailbox.php +++ b/lib/mailbox.php @@ -47,11 +47,11 @@ define('MESSAGES_PER_PAGE', 20); * @see OutboxAction */ -class MailboxAction extends PersonalAction +class MailboxAction extends CurrentUserDesignAction { var $page = null; - function prepare($args) + function prepare($args) { parent::prepare($args); @@ -265,12 +265,12 @@ class MailboxAction extends PersonalAction * Returns either the name (and link) of the API client that posted the notice, * or one of other other channels. * - * @param string $source the source of the message + * @param string $source the source of the message * * @return void */ - function showSource($source) + function showSource($source) { $source_name = _($source); switch ($source) { diff --git a/lib/settingsaction.php b/lib/settingsaction.php index db20c5804..17d3a2f64 100644 --- a/lib/settingsaction.php +++ b/lib/settingsaction.php @@ -43,7 +43,7 @@ if (!defined('LACONICA')) { * @see Widget */ -class SettingsAction extends Action +class SettingsAction extends CurrentUserDesignAction { /** * A message for the user. -- cgit v1.2.3-54-g00ecf From d60c399d825dc373630042d12f90c01886cc32f5 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 23 May 2009 23:40:27 -0400 Subject: remove old, unused PersonalAction and StreamAction --- lib/attachmentlist.php | 2 -- lib/noticelist.php | 2 -- lib/personal.php | 60 -------------------------------------------------- lib/stream.php | 32 --------------------------- 4 files changed, 96 deletions(-) delete mode 100644 lib/personal.php delete mode 100644 lib/stream.php (limited to 'lib') diff --git a/lib/attachmentlist.php b/lib/attachmentlist.php index 9485fe3d6..8d6d19f2a 100644 --- a/lib/attachmentlist.php +++ b/lib/attachmentlist.php @@ -46,7 +46,6 @@ if (!defined('LACONICA')) { * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://laconi.ca/ * @see Notice - * @see StreamAction * @see NoticeListItem * @see ProfileNoticeList */ @@ -203,7 +202,6 @@ class AttachmentListItem extends Widget if ($this->attachment->url !== $this->title()) $this->out->element('span', null, " ({$this->attachment->url})"); - $this->out->elementEnd('h4'); } diff --git a/lib/noticelist.php b/lib/noticelist.php index a52132171..ba3526509 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -49,7 +49,6 @@ require_once INSTALLDIR.'/lib/disfavorform.php'; * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://laconi.ca/ * @see Notice - * @see StreamAction * @see NoticeListItem * @see ProfileNoticeList */ @@ -231,7 +230,6 @@ else $this->out->elementStart('p', array('class' => 'entry-attachments', 'style' => "float: right; width: $width_att; background: url($clip) no-repeat; text-align: right; height: $height;")); $this->out->element('a', array('class' => $att_class, 'style' => "text-decoration: none; padding-top: $top; display: block; height: $height;", 'href' => $href, 'title' => "# of attachments: $count"), $count === 1 ? '' : $count); - $this->out->elementEnd('p'); } diff --git a/lib/personal.php b/lib/personal.php deleted file mode 100644 index f92732375..000000000 --- a/lib/personal.php +++ /dev/null @@ -1,60 +0,0 @@ -. - * - * @category Personal - * @package Laconica - * @author Evan Prodromou - * @author Sarven Capadisli - * @copyright 2008-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); -} - -/** - * Base class for user profile page - * - * @category Personal - * @package Laconica - * @author Evan Prodromou - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ - */ - -class PersonalAction extends Action -{ - - var $user = null; - - function isReadOnly($args) - { - return true; - } - - function handle($args) - { - parent::handle($args); - } - -} diff --git a/lib/stream.php b/lib/stream.php deleted file mode 100644 index 0cb9e0bf4..000000000 --- a/lib/stream.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -if (!defined('LACONICA')) { exit(1); } - -require_once(INSTALLDIR.'/lib/personal.php'); -require_once(INSTALLDIR.'/lib/noticelist.php'); - -class StreamAction extends PersonalAction -{ - function show_notice_list($notice) - { - $nl = new NoticeList($notice); - return $nl->show(); - } -} -- cgit v1.2.3-54-g00ecf From 946d016df2a5e0af5e1b4b983b30c113dd02b4ea Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Sun, 14 Jun 2009 02:03:50 -0700 Subject: Reworked output for design settings page --- actions/designsettings.php | 164 +++++++++++++++++++++++++++++++++++---------- lib/common.php | 7 ++ 2 files changed, 136 insertions(+), 35 deletions(-) (limited to 'lib') diff --git a/actions/designsettings.php b/actions/designsettings.php index 66476e677..8595cbc4c 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -22,6 +22,7 @@ * @category Settings * @package Laconica * @author Sarven Capadisli + * @author Zach Copley * @copyright 2008-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/ @@ -104,42 +105,73 @@ class DesignsettingsAction extends AccountSettingsAction $design = $this->defaultDesign(); } - $labelSwatch = array('Background', - 'Content', - 'Sidebar', - 'Text', - 'Links'); - - foreach($userSwatch as $propertyvalue => $value) { - $foo = array_values($value); - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-'.$s), _($labelSwatch[$s])); - $this->element('input', array('name' => 'swatch-'.$s, //prefer swatch[$s] ? - 'type' => 'text', - 'id' => 'swatch-'.$s, - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => $foo[0])); - $this->elementEnd('li'); - $s++; - } + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-5'), _('Background')); + $this->element('input', array('name' => 'design_background', + 'type' => 'text', + 'id' => 'swatch-5', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => $design->backgroundcolor)); + $this->elementEnd('li'); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-1'), _('Content')); + $this->element('input', array('name' => 'design_content', + 'type' => 'text', + 'id' => 'swatch-1', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => $design->contentcolor)); + $this->elementEnd('li'); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-2'), _('Sidebar')); + $this->element('input', array('name' => 'design_sidebar', + 'type' => 'text', + 'id' => 'swatch-2', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => $design->sidebarcolor)); + $this->elementEnd('li'); - $this->elementEnd('ul'); - $this->elementEnd('fieldset'); + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-3'), _('Text')); + $this->element('input', array('name' => 'design_text', + 'type' => 'text', + 'id' => 'swatch-3', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => $design->textcolor)); + $this->elementEnd('li'); - $this->element('input', array('id' => 'settings_design_reset', - 'type' => 'reset', - 'value' => 'Reset', - 'class' => 'submit form_action-primary', - 'title' => _('Reset back to default'))); - $this->submit('save', _('Save'), 'submit form_action-secondary', 'save', _('Save design')); + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-4'), _('Links')); + $this->element('input', array('name' => 'design_links', + 'type' => 'text', + 'id' => 'swatch-4', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => $design->linkcolor)); - /*TODO: Check submitted form values: - json_encode(form values) - if submitted Swatch == DefaultSwatch, don't store in DB. - else store in BD - */ + $this->elementEnd('li'); + + $this->elementEnd('ul'); + $this->elementEnd('fieldset'); + + $this->element('input', array('id' => 'settings_design_reset', + 'type' => 'reset', + 'value' => 'Reset', + 'class' => 'submit form_action-primary', + 'title' => _('Reset back to default'))); + + $this->submit('save', _('Save'), 'submit form_action-secondary', + 'save', _('Save design')); $this->elementEnd('fieldset'); $this->elementEnd('form'); @@ -156,8 +188,21 @@ class DesignsettingsAction extends AccountSettingsAction function handlePost() { - // TODO: implement this - return; + // CSRF protection + $token = $this->trimmed('token'); + if (!$token || $token != common_session_token()) { + $this->showForm(_('There was a problem with your session token. '. + 'Try again, please.')); + return; + } + + if ($this->arg('save')) { + $this->saveDesign(); + } else if ($this->arg('reset')) { + $this->resetDesign(); + } else { + $this->showForm(_('Unexpected form submission.')); + } } /** @@ -196,4 +241,53 @@ class DesignsettingsAction extends AccountSettingsAction $this->element('script', array('type' => 'text/javascript', 'src' => $farbtasticGo)); } + + /** + * Get a default user design + * + * @return Design design + */ + + function defaultDesign() + { + $defaults = common_config('site', 'design'); + + $design = new Design(); + $design->backgroundcolor = $defaults['backgroundcolor']; + $design->contentcolor = $defaults['contentcolor']; + $design->sidebarcolor = $defaults['sidebarcolor']; + $design->textcolor = $defaults['textcolor']; + $design->linkcolor = $defaults['linkcolor']; + $design->backgroundimage = $defaults['backgroundimage']; + + return $design; + } + + /** + * Save the user's design settings + * + * @return void + */ + + function saveDesign() + { + $user = common_current_user(); + + + + $this->showForm(_('Design preferences saved.'), true); + } + + /** + * Reset design settings to previous saved value if any, or + * the defaults + * + * @return void + */ + + function resetDesign() + { + $this->showForm(_('Design preferences reset.'), true); + } + } diff --git a/lib/common.php b/lib/common.php index 5aafdfe0e..a55fb264e 100644 --- a/lib/common.php +++ b/lib/common.php @@ -72,6 +72,13 @@ $config = 'server' => $_server, 'theme' => 'default', 'skin' => 'default', + 'design' => + array('backgroundcolor' => '#F0F2F5', + 'contentcolor' => '#FFFFFF', + 'sidebarcolor' => '#CEE1E9', + 'textcolor' => '#000000', + 'linkcolor' => '#002E6E', + 'backgroundimage' => null), 'path' => $_path, 'logfile' => null, 'logo' => null, -- cgit v1.2.3-54-g00ecf From 7c772e1d634badcbb9960f5a8c4398ae2f8cdd57 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Sun, 14 Jun 2009 15:48:46 -0400 Subject: Removed another bit of dead (commented out) code. --- lib/noticelist.php | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'lib') diff --git a/lib/noticelist.php b/lib/noticelist.php index fadc238a4..c312292ab 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -206,24 +206,10 @@ class NoticeListItem extends Widget return 'shownotice' !== $this->out->args['action']; } -/* - function attachmentCount($discriminant = true) { - $file_oembed = new File_oembed; - $query = "select count(*) as c from file_oembed join file_to_post on file_oembed.file_id = file_to_post.file_id where post_id=" . $this->notice->id; - $file_oembed->query($query); - $file_oembed->fetch(); - return intval($file_oembed->c); - } -*/ - - function showWithAttachment() { - } - function showNoticeInfo() { $this->out->elementStart('div', 'entry-content'); $this->showNoticeLink(); -// $this->showWithAttachment(); $this->showNoticeSource(); $this->showContext(); $this->out->elementEnd('div'); -- cgit v1.2.3-54-g00ecf From c2dae24701a22cd2362ebe1a96828cd7945c6b5a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 14:52:26 -0700 Subject: Break profilelist into a recipe Expanded the ProfileList class so it worked more like a recipe. This helps to get rid of a lot of special cases and simplifies the code. It also makes it possible to do things like group block. --- actions/groupmembers.php | 14 +++- actions/showgroup.php | 2 +- actions/subscribers.php | 32 ++++++--- actions/subscriptions.php | 34 ++++++++-- lib/peoplesearchresults.php | 15 +++-- lib/profileaction.php | 4 +- lib/profilelist.php | 154 +++++++++++++++++++++++++------------------- lib/profileminilist.php | 23 ++----- 8 files changed, 172 insertions(+), 106 deletions(-) (limited to 'lib') diff --git a/actions/groupmembers.php b/actions/groupmembers.php index 21e5ebbaa..53fee3129 100644 --- a/actions/groupmembers.php +++ b/actions/groupmembers.php @@ -127,7 +127,7 @@ class GroupmembersAction extends Action $members = $this->group->getMembers($offset, $limit); if ($members) { - $member_list = new ProfileList($members, null, $this); + $member_list = new GroupMemberList($members, $this->group, $this); $cnt = $member_list->show(); } @@ -138,3 +138,15 @@ class GroupmembersAction extends Action array('nickname' => $this->group->nickname)); } } + +class GroupMemberList extends ProfileList { + + var $group = null; + + function __construct($profile, $group=null, $action=null) + { + parent::__construct($profile, $action); + + $this->group = $group; + } +} diff --git a/actions/showgroup.php b/actions/showgroup.php index 29b6fa1e6..3ce45adc6 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -344,7 +344,7 @@ class ShowgroupAction extends Action $this->element('h2', null, _('Members')); - $pml = new ProfileMiniList($member, null, $this); + $pml = new ProfileMiniList($member, $this); $cnt = $pml->show(); if ($cnt == 0) { $this->element('p', null, _('(None)')); diff --git a/actions/subscribers.php b/actions/subscribers.php index 4482de9a7..66ac00fb1 100644 --- a/actions/subscribers.php +++ b/actions/subscribers.php @@ -130,18 +130,34 @@ class SubscribersAction extends GalleryAction } } -class SubscribersList extends ProfileList +class SubscribersList extends SubscriptionList { - function showBlockForm() + function newListItem($profile) { - $bf = new BlockForm($this->out, $this->profile, - array('action' => 'subscribers', - 'nickname' => $this->owner->nickname)); - $bf->show(); + return new SubscribersListItem($profile, $this->owner, $this->action); } +} - function isReadOnly($args) +class SubscribersListItem extends SubscriptionListItem +{ + function showActions() { - return true; + $this->startActions(); + $this->showSubscribeButton(); + // Relevant code! + $this->showBlockForm(); + $this->endActions(); + } + + function showBlockForm() + { + $user = common_current_user(); + + if (!empty($user) && $this->owner->id == $user->id) { + $bf = new BlockForm($this->out, $this->profile, + array('action' => 'subscribers', + 'nickname' => $this->owner->nickname)); + $bf->show(); + } } } diff --git a/actions/subscriptions.php b/actions/subscriptions.php index 095b18ad8..4124abea4 100644 --- a/actions/subscriptions.php +++ b/actions/subscriptions.php @@ -137,22 +137,46 @@ class SubscriptionsAction extends GalleryAction } } -class SubscriptionsList extends ProfileList +// XXX SubscriptionsList and SubscriptionList are dangerously close + +class SubscriptionsList extends SubscriptionList { - function showOwnerControls($profile) + function newListItem($profile) + { + return new SubscriptionsListItem($profile, $this->owner, $this->action); + } +} + +class SubscriptionsListItem extends SubscriptionListItem +{ + function showProfile() + { + $this->startProfile(); + $this->showAvatar(); + $this->showFullName(); + $this->showLocation(); + $this->showHomepage(); + $this->showBio(); + $this->showTags(); + // Relevant portion! + $this->showOwnerControls(); + $this->endProfile(); + } + + function showOwnerControls() { $sub = Subscription::pkeyGet(array('subscriber' => $this->owner->id, - 'subscribed' => $profile->id)); + 'subscribed' => $this->profile->id)); if (!$sub) { return; } - $this->out->elementStart('form', array('id' => 'subedit-' . $profile->id, + $this->out->elementStart('form', array('id' => 'subedit-' . $this->profile->id, 'method' => 'post', 'class' => 'form_subscription_edit', 'action' => common_local_url('subedit'))); $this->out->hidden('token', common_session_token()); - $this->out->hidden('profile', $profile->id); + $this->out->hidden('profile', $this->profile->id); $this->out->checkbox('jabber', _('Jabber'), $sub->jabber); $this->out->checkbox('sms', _('SMS'), $sub->sms); $this->out->submit('save', _('Save')); diff --git a/lib/peoplesearchresults.php b/lib/peoplesearchresults.php index d3f840852..9d9d17299 100644 --- a/lib/peoplesearchresults.php +++ b/lib/peoplesearchresults.php @@ -56,20 +56,25 @@ class PeopleSearchResults extends ProfileList function __construct($profile, $terms, $action) { - parent::__construct($profile, $terms, $action); + parent::__construct($profile, $action); + $this->terms = array_map('preg_quote', array_map('htmlspecialchars', $terms)); + $this->pattern = '/('.implode('|',$terms).')/i'; } - function highlight($text) + function newProfileItem($profile) { - return preg_replace($this->pattern, '\\1', htmlspecialchars($text)); + return new PeopleSearchResultItem($profile, $this->action); } +} - function isReadOnly($args) +class PeopleSearchResultItem extends ProfileListItem +{ + function highlight($text) { - return true; + return preg_replace($this->pattern, '\\1', htmlspecialchars($text)); } } diff --git a/lib/profileaction.php b/lib/profileaction.php index a3437ff4d..298f34b22 100644 --- a/lib/profileaction.php +++ b/lib/profileaction.php @@ -110,7 +110,7 @@ class ProfileAction extends Action $this->element('h2', null, _('Subscriptions')); if ($profile) { - $pml = new ProfileMiniList($profile, $this->user, $this); + $pml = new ProfileMiniList($profile, $this); $cnt = $pml->show(); if ($cnt == 0) { $this->element('p', null, _('(None)')); @@ -139,7 +139,7 @@ class ProfileAction extends Action $this->element('h2', null, _('Subscribers')); if ($profile) { - $pml = new ProfileMiniList($profile, $this->user, $this); + $pml = new ProfileMiniList($profile, $this); $cnt = $pml->show(); if ($cnt == 0) { $this->element('p', null, _('(None)')); diff --git a/lib/profilelist.php b/lib/profilelist.php index a4cc23555..e2faf10af 100644 --- a/lib/profilelist.php +++ b/lib/profilelist.php @@ -49,23 +49,19 @@ class ProfileList extends Widget { /** Current profile, profile query. */ var $profile = null; - /** Owner of this list */ - var $owner = null; /** Action object using us. */ var $action = null; - function __construct($profile, $owner=null, $action=null) + function __construct($profile, $action=null) { parent::__construct($action); $this->profile = $profile; - $this->owner = $owner; $this->action = $action; } function show() { - $this->out->elementStart('ul', 'profiles'); $cnt = 0; @@ -75,7 +71,8 @@ class ProfileList extends Widget if($cnt > PROFILES_PER_PAGE) { break; } - $this->showProfile(); + $pli = $this->newListItem($this->profile); + $pli->show(); } $this->out->elementEnd('ul'); @@ -83,16 +80,59 @@ class ProfileList extends Widget return $cnt; } - function showProfile() + function newListItem($profile) + { + return new ProfileListItem($this->profile, $this->action); + } +} + +class ProfileListItem extends Widget +{ + /** Current profile. */ + var $profile = null; + /** Action object using us. */ + var $action = null; + + function __construct($profile, $action) + { + parent::__construct($action); + + $this->profile = $profile; + $this->action = $action; + } + + function show() + { + $this->startItem(); + $this->showProfile(); + $this->showActions(); + $this->endItem(); + } + + function startItem() { $this->out->elementStart('li', array('class' => 'profile', 'id' => 'profile-' . $this->profile->id)); + } - $user = common_current_user(); - $is_own = !is_null($user) && isset($this->owner) && ($user->id === $this->owner->id); + function showProfile() + { + $this->startProfile(); + $this->showAvatar(); + $this->showFullName(); + $this->showLocation(); + $this->showHomepage(); + $this->showBio(); + $this->endProfile(); + } + function startProfile() + { $this->out->elementStart('div', 'entity_profile vcard'); + } + function showAvatar() + { $avatar = $this->profile->getAvatar(AVATAR_STREAM_SIZE); $this->out->elementStart('a', array('href' => $this->profile->profileurl, 'class' => 'url')); @@ -108,7 +148,10 @@ class ProfileList extends Widget $this->out->raw($this->highlight($this->profile->nickname)); $this->out->elementEnd('span'); $this->out->elementEnd('a'); + } + function showFullName() + { if (!empty($this->profile->fullname)) { $this->out->elementStart('dl', 'entity_fn'); $this->out->element('dt', null, 'Full name'); @@ -119,6 +162,10 @@ class ProfileList extends Widget $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); } + } + + function showLocation() + { if (!empty($this->profile->location)) { $this->out->elementStart('dl', 'entity_location'); $this->out->element('dt', null, _('Location')); @@ -127,6 +174,10 @@ class ProfileList extends Widget $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); } + } + + function showHomepage() + { if (!empty($this->profile->homepage)) { $this->out->elementStart('dl', 'entity_url'); $this->out->element('dt', null, _('URL')); @@ -138,6 +189,10 @@ class ProfileList extends Widget $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); } + } + + function showBio() + { if (!empty($this->profile->bio)) { $this->out->elementStart('dl', 'entity_note'); $this->out->element('dt', null, _('Note')); @@ -146,57 +201,33 @@ class ProfileList extends Widget $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); } + } - # If we're on a list with an owner (subscriptions or subscribers)... - - if ($this->owner) { - # Get tags - $tags = Profile_tag::getTags($this->owner->id, $this->profile->id); - - $this->out->elementStart('dl', 'entity_tags'); - $this->out->elementStart('dt'); - if ($is_own) { - $this->out->element('a', array('href' => common_local_url('tagother', - array('id' => $this->profile->id))), - _('Tags')); - } else { - $this->out->text(_('Tags')); - } - $this->out->elementEnd('dt'); - $this->out->elementStart('dd'); - if ($tags) { - $this->out->elementStart('ul', 'tags xoxo'); - foreach ($tags as $tag) { - $this->out->elementStart('li'); - $this->out->element('span', 'mark_hash', '#'); - $this->out->element('a', array('rel' => 'tag', - 'href' => common_local_url($this->action->trimmed('action'), - array('nickname' => $this->owner->nickname, - 'tag' => $tag))), - $tag); - $this->out->elementEnd('li'); - } - $this->out->elementEnd('ul'); - } else { - $this->out->text(_('(none)')); - } - $this->out->elementEnd('dd'); - $this->out->elementEnd('dl'); - } - - if ($is_own) { - $this->showOwnerControls($this->profile); - } - + function endProfile() + { $this->out->elementEnd('div'); + } - $this->out->elementStart('div', 'entity_actions'); + function showActions() + { + $this->startActions(); + $this->showSubscribeButton(); + $this->endActions(); + } + function startActions() + { + $this->out->elementStart('div', 'entity_actions'); $this->out->elementStart('ul'); + } + function showSubscribeButton() + { // Is this a logged-in user, looking at someone else's // profile? + $user = common_current_user(); + if (!empty($user) && $this->profile->id != $user->id) { $this->out->elementStart('li', 'entity_subscribe'); if ($user->isSubscribed($this->profile)) { @@ -207,33 +238,22 @@ class ProfileList extends Widget $sf->show(); } $this->out->elementEnd('li'); - $this->out->elementStart('li', 'entity_block'); - if ($user->id == $this->owner->id) { - $this->showBlockForm(); - } - $this->out->elementEnd('li'); } + } + function endActions() + { $this->out->elementEnd('ul'); - $this->out->elementEnd('div'); - - $this->out->elementEnd('li'); } - /* Override this in subclasses. */ - - function showOwnerControls($profile) + function endItem() { - return; + $this->out->elementEnd('li'); } function highlight($text) { return htmlspecialchars($text); } - - function showBlockForm() - { - } } diff --git a/lib/profileminilist.php b/lib/profileminilist.php index 57496d0e9..f11cae8a5 100644 --- a/lib/profileminilist.php +++ b/lib/profileminilist.php @@ -47,26 +47,15 @@ define('PROFILES_PER_MINILIST', 27); class ProfileMiniList extends ProfileList { - function show() + function newListItem($profile) { - $this->out->elementStart('ul', 'entities users xoxo'); - - $cnt = 0; - - while ($this->profile->fetch()) { - $cnt++; - if($cnt > PROFILES_PER_MINILIST) { - break; - } - $this->showProfile(); - } - - $this->out->elementEnd('ul'); - - return $cnt; + return new ProfileMiniListItem($profile, $this->action); } +} - function showProfile() +class ProfileMiniListItem extends ProfileListItem +{ + function show() { $this->out->elementStart('li', 'vcard'); $this->out->elementStart('a', array('title' => $this->profile->getBestName(), -- cgit v1.2.3-54-g00ecf From b6ef8e735b8deeaf3e11a03574888a479b1679b7 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 14:53:42 -0700 Subject: base class SubscriptionList for some actions --- lib/subscriptionlist.php | 131 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 lib/subscriptionlist.php (limited to 'lib') diff --git a/lib/subscriptionlist.php b/lib/subscriptionlist.php new file mode 100644 index 000000000..23da64cca --- /dev/null +++ b/lib/subscriptionlist.php @@ -0,0 +1,131 @@ +. + * + * @category Public + * @package Laconica + * @author Evan Prodromou + * @copyright 2008-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); +} + +require_once INSTALLDIR.'/lib/profilelist.php'; + +/** + * Widget to show a list of subscriptions + * + * @category Public + * @package Laconica + * @author Zach Copley + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class SubscriptionList extends ProfileList +{ + /** Owner of this list */ + var $owner = null; + + function __construct($profile, $owner=null, $action=null) + { + parent::__construct($profile, $action); + + $this->owner = $owner; + } + + function newListItem($profile) + { + return new SubscriptionListItem($profile, $this->owner, $this->action); + } +} + +class SubscriptionListItem extends ProfileListItem +{ + /** Owner of this list */ + var $owner = null; + + function __construct($profile, $owner, $action) + { + parent::__construct($profile, $action); + + $this->owner = $owner; + } + + function showProfile() + { + $this->startProfile(); + $this->showAvatar(); + $this->showFullName(); + $this->showLocation(); + $this->showHomepage(); + $this->showBio(); + // Relevant portion! + $this->showTags(); + $this->endProfile(); + } + + function isOwn() + { + $user = common_current_user(); + return (!empty($user) && ($this->owner->id == $user->id)); + } + + function showTags() + { + $tags = Profile_tag::getTags($this->owner->id, $this->profile->id); + + $this->out->elementStart('dl', 'entity_tags'); + $this->out->elementStart('dt'); + if ($this->isOwn()) { + $this->out->element('a', array('href' => common_local_url('tagother', + array('id' => $this->profile->id))), + _('Tags')); + } else { + $this->out->text(_('Tags')); + } + $this->out->elementEnd('dt'); + $this->out->elementStart('dd'); + if ($tags) { + $this->out->elementStart('ul', 'tags xoxo'); + foreach ($tags as $tag) { + $this->out->elementStart('li'); + $this->out->element('span', 'mark_hash', '#'); + $this->out->element('a', array('rel' => 'tag', + 'href' => common_local_url($this->action->trimmed('action'), + array('nickname' => $this->owner->nickname, + 'tag' => $tag))), + $tag); + $this->out->elementEnd('li'); + } + $this->out->elementEnd('ul'); + } else { + $this->out->text(_('(none)')); + } + $this->out->elementEnd('dd'); + $this->out->elementEnd('dl'); + } +} -- cgit v1.2.3-54-g00ecf From 1c87532912b63effc047da2913e55a6551d8f629 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 15:47:39 -0700 Subject: The rest of the things necessary to make group block work Link to the group block form. Hide join button if the current user is blocked. --- actions/groupmembers.php | 2 +- actions/joingroup.php | 5 ++++ actions/showgroup.php | 2 +- classes/Group_block.php | 76 ++++++++++++++++++++++++++++++++++++++++++++++-- classes/User_group.php | 5 ++++ lib/grouplist.php | 2 +- lib/router.php | 8 ++--- 7 files changed, 91 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/actions/groupmembers.php b/actions/groupmembers.php index 079dad9e9..150b60a54 100644 --- a/actions/groupmembers.php +++ b/actions/groupmembers.php @@ -180,7 +180,7 @@ class GroupMemberListItem extends ProfileListItem $user = common_current_user(); if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group)) { - $bf = new GroupBlockForm($this->out, $this->profile, + $bf = new GroupBlockForm($this->out, $this->profile, $this->group, array('action' => 'groupmembers', 'nickname' => $this->group->nickname)); $bf->show(); diff --git a/actions/joingroup.php b/actions/joingroup.php index a5d82ddc7..0e4f96eaf 100644 --- a/actions/joingroup.php +++ b/actions/joingroup.php @@ -96,6 +96,11 @@ class JoingroupAction extends Action return false; } + if (Group_block::isBlocked($this->group, $cur->getProfile())) { + $this->clientError(_('You have been blocked from that group by the admin.'), 403); + return false; + } + return true; } diff --git a/actions/showgroup.php b/actions/showgroup.php index 3ce45adc6..537f09278 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -283,7 +283,7 @@ class ShowgroupAction extends Action if ($cur->isMember($this->group)) { $lf = new LeaveForm($this, $this->group); $lf->show(); - } else { + } else if (!Group_block::isBlocked($this->group, $cur->getProfile())) { $jf = new JoinForm($this, $this->group); $jf->show(); } diff --git a/classes/Group_block.php b/classes/Group_block.php index 437046a9c..d945fd57a 100644 --- a/classes/Group_block.php +++ b/classes/Group_block.php @@ -1,10 +1,29 @@ . */ -require_once 'classes/Memcached_DataObject'; -class Group_block extends Memcached_DataObject +if (!defined('LACONICA')) { exit(1); } + +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +class Group_block extends Memcached_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ @@ -20,4 +39,57 @@ class Group_block extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + function &pkeyGet($kv) + { + return Memcached_DataObject::pkeyGet('Group_block', $kv); + } + + static function isBlocked($group, $profile) + { + $block = Group_block::pkeyGet(array('group_id' => $group->id, + 'blocked' => $profile->id)); + return !empty($block); + } + + static function blockProfile($group, $profile, $blocker) + { + // Insert the block + + $block = new Group_block(); + + $block->query('BEGIN'); + + $block->group_id = $group->id; + $block->blocked = $profile->id; + $block->blocker = $blocker->id; + + $result = $block->insert(); + + if (!$result) { + common_log_db_error($block, 'INSERT', __FILE__); + return null; + } + + // Delete membership if any + + $member = new Group_member(); + + $member->group_id = $group->id; + $member->profile_id = $profile->id; + + if ($member->find(true)) { + $result = $member->delete(); + if (!$result) { + common_log_db_error($member, 'DELETE', __FILE__); + return null; + } + } + + // Commit, since both have been done + + $block->query('COMMIT'); + + return $block; + } } diff --git a/classes/User_group.php b/classes/User_group.php index a135015ba..1be34b60b 100644 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -137,4 +137,9 @@ class User_group extends Memcached_DataObject common_debug(common_log_objstring($this)); return $this->update($orig); } + + function getBestName() + { + return ($this->fullname) ? $this->fullname : $this->nickname; + } } diff --git a/lib/grouplist.php b/lib/grouplist.php index 1b8547499..1ded5160b 100644 --- a/lib/grouplist.php +++ b/lib/grouplist.php @@ -166,7 +166,7 @@ class GroupList extends Widget if ($user->isMember($this->group)) { $lf = new LeaveForm($this->out, $this->group); $lf->show(); - } else { + } else if (!Group_block::isBlocked($this->group, $user->getProfile())) { $jf = new JoinForm($this->out, $this->group); $jf->show(); } diff --git a/lib/router.php b/lib/router.php index 456d1793e..469d9a171 100644 --- a/lib/router.php +++ b/lib/router.php @@ -101,7 +101,7 @@ class Router $main = array('login', 'logout', 'register', 'subscribe', 'unsubscribe', 'confirmaddress', 'recoverpassword', 'invite', 'favor', 'disfavor', 'sup', - 'block', 'subedit'); + 'block', 'subedit', 'groupblock'); foreach ($main as $a) { $m->connect('main/'.$a, array('action' => $a)); @@ -164,10 +164,10 @@ class Router array('action' => 'newnotice'), array('replyto' => '[A-Za-z0-9_-]+')); - $m->connect('notice/:notice/file', - array('action' => 'file'), + $m->connect('notice/:notice/file', + array('action' => 'file'), array('notice' => '[0-9]+')); - + $m->connect('notice/:notice', array('action' => 'shownotice'), array('notice' => '[0-9]+')); -- cgit v1.2.3-54-g00ecf From 203a5aba67c3bd9e2848d90b1778240b387aeda3 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 15:54:22 -0700 Subject: Some UI improvements for blocking and unblocking Add unblock to the router table, so unblocking will work at all. Block form and unblock form return to subscribers list, not subscriptions list, by default. showstream action sends its parameters to block and unblock forms to better return to the right page. --- actions/block.php | 2 +- actions/showstream.php | 8 ++++++-- actions/unblock.php | 2 +- lib/router.php | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/actions/block.php b/actions/block.php index 34f991dc6..0efee5932 100644 --- a/actions/block.php +++ b/actions/block.php @@ -180,7 +180,7 @@ class BlockAction extends Action if ($action) { common_redirect(common_local_url($action, $args), 303); } else { - common_redirect(common_local_url('subscriptions', + common_redirect(common_local_url('subscribers', array('nickname' => $cur->nickname)), 303); } diff --git a/actions/showstream.php b/actions/showstream.php index c1a2c337a..641228bc7 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -308,10 +308,14 @@ class ShowstreamAction extends ProfileAction $blocked = $cur->hasBlocked($this->profile); $this->elementStart('li', 'entity_block'); if ($blocked) { - $ubf = new UnblockForm($this, $this->profile); + $ubf = new UnblockForm($this, $this->profile, + array('action' => 'showstream', + 'nickname' => $this->profile->nickname)); $ubf->show(); } else { - $bf = new BlockForm($this, $this->profile); + $bf = new BlockForm($this, $this->profile, + array('action' => 'showstream', + 'nickname' => $this->profile->nickname)); $bf->show(); } $this->elementEnd('li'); diff --git a/actions/unblock.php b/actions/unblock.php index 8573b2a87..6e671c9dd 100644 --- a/actions/unblock.php +++ b/actions/unblock.php @@ -118,7 +118,7 @@ class UnblockAction extends Action if ($action) { common_redirect(common_local_url($action, $args), 303); } else { - common_redirect(common_local_url('subscriptions', + common_redirect(common_local_url('subscribers', array('nickname' => $cur->nickname)), 303); } diff --git a/lib/router.php b/lib/router.php index 12590b790..748966567 100644 --- a/lib/router.php +++ b/lib/router.php @@ -101,7 +101,7 @@ class Router $main = array('login', 'logout', 'register', 'subscribe', 'unsubscribe', 'confirmaddress', 'recoverpassword', 'invite', 'favor', 'disfavor', 'sup', - 'block', 'subedit'); + 'block', 'unblock', 'subedit'); foreach ($main as $a) { $m->connect('main/'.$a, array('action' => $a)); -- cgit v1.2.3-54-g00ecf From f8da15bf41b07a46b1fbe5323e2b8136d42c5b31 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 16:17:44 -0700 Subject: Allow users to be unblocked from a group List users who are blocked from joining a group. Add a form to let them be unblocked. Add an action that removes the block. Includes changes to group and groupblock classes. --- actions/blockedfromgroup.php | 313 +++++++++++++++++++++++++++++++++++++++++++ actions/groupunblock.php | 149 ++++++++++++++++++++ classes/Group_block.php | 20 +++ classes/User_group.php | 23 ++++ lib/groupnav.php | 6 + lib/router.php | 7 +- 6 files changed, 517 insertions(+), 1 deletion(-) create mode 100644 actions/blockedfromgroup.php create mode 100644 actions/groupunblock.php (limited to 'lib') diff --git a/actions/blockedfromgroup.php b/actions/blockedfromgroup.php new file mode 100644 index 000000000..1b7b31784 --- /dev/null +++ b/actions/blockedfromgroup.php @@ -0,0 +1,313 @@ +. + * + * @category Group + * @package Laconica + * @author Evan Prodromou + * @copyright 2008-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); +} + +/** + * List of profiles blocked from this group + * + * @category Group + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class BlockedfromgroupAction extends Action +{ + var $page = null; + + function isReadOnly($args) + { + return true; + } + + function prepare($args) + { + parent::prepare($args); + $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1; + + $nickname_arg = $this->arg('nickname'); + $nickname = common_canonical_nickname($nickname_arg); + + // Permanent redirect on non-canonical nickname + + if ($nickname_arg != $nickname) { + $args = array('nickname' => $nickname); + if ($this->page != 1) { + $args['page'] = $this->page; + } + common_redirect(common_local_url('blockedfromgroup', $args), 301); + return false; + } + + if (!$nickname) { + $this->clientError(_('No nickname'), 404); + return false; + } + + $this->group = User_group::staticGet('nickname', $nickname); + + if (!$this->group) { + $this->clientError(_('No such group'), 404); + return false; + } + + return true; + } + + function title() + { + if ($this->page == 1) { + return sprintf(_('%s blocked profiles'), + $this->group->nickname); + } else { + return sprintf(_('%s blocked profiles, page %d'), + $this->group->nickname, + $this->page); + } + } + + function handle($args) + { + parent::handle($args); + $this->showPage(); + } + + function showPageNotice() + { + $this->element('p', 'instructions', + _('A list of the users blocked from joining this group.')); + } + + function showLocalNav() + { + $nav = new GroupNav($this, $this->group); + $nav->show(); + } + + function showContent() + { + $offset = ($this->page-1) * PROFILES_PER_PAGE; + $limit = PROFILES_PER_PAGE + 1; + + $cnt = 0; + + $blocked = $this->group->getBlocked($offset, $limit); + + if ($blocked) { + $blocked_list = new GroupBlockList($blocked, $this->group, $this); + $cnt = $blocked_list->show(); + } + + $blocked->free(); + + $this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE, + $this->page, 'blockedfromgroup', + array('nickname' => $this->group->nickname)); + } +} + +class GroupBlockList extends ProfileList +{ + var $group = null; + + function __construct($profile, $group, $action) + { + parent::__construct($profile, $action); + + $this->group = $group; + } + + function newListItem($profile) + { + return new GroupBlockListItem($profile, $this->group, $this->action); + } +} + +class GroupBlockListItem extends ProfileListItem +{ + var $group = null; + + function __construct($profile, $group, $action) + { + parent::__construct($profile, $action); + + $this->group = $group; + } + + function showActions() + { + $this->startActions(); + $this->showGroupUnblockForm(); + $this->endActions(); + } + + function showGroupUnblockForm() + { + $user = common_current_user(); + + if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group)) { + $bf = new GroupUnblockForm($this->out, $this->profile, $this->group, + array('action' => 'blockedfromgroup', + 'nickname' => $this->group->nickname)); + $bf->show(); + } + } +} + +/** + * Form for unblocking a user from a group + * + * @category Form + * @package Laconica + * @author Evan Prodromou + * @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/ + * + * @see UnblockForm + */ + +class GroupUnblockForm extends Form +{ + /** + * Profile of user to block + */ + + var $profile = null; + + /** + * Group to block the user from + */ + + var $group = null; + + /** + * Return-to args + */ + + var $args = null; + + /** + * Constructor + * + * @param HTMLOutputter $out output channel + * @param Profile $profile profile of user to block + * @param User_group $group group to block user from + * @param array $args return-to args + */ + + function __construct($out=null, $profile=null, $group=null, $args=null) + { + parent::__construct($out); + + $this->profile = $profile; + $this->group = $group; + $this->args = $args; + } + + /** + * ID of the form + * + * @return int ID of the form + */ + + function id() + { + // This should be unique for the page. + return 'unblock-' . $this->profile->id; + } + + /** + * class of the form + * + * @return string class of the form + */ + + function formClass() + { + return 'form_group_unblock'; + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return common_local_url('groupunblock'); + } + + /** + * Legend of the Form + * + * @return void + */ + function formLegend() + { + $this->out->element('legend', null, _('Unblock user from group')); + } + + /** + * Data elements of the form + * + * @return void + */ + + function formData() + { + $this->out->hidden('unblockto-' . $this->profile->id, + $this->profile->id, + 'unblockto'); + $this->out->hidden('unblockgroup-' . $this->group->id, + $this->group->id, + 'unblockgroup'); + if ($this->args) { + foreach ($this->args as $k => $v) { + $this->out->hidden('returnto-' . $k, $v); + } + } + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->submit('submit', _('Unblock'), 'submit', null, _('Unblock this user')); + } +} diff --git a/actions/groupunblock.php b/actions/groupunblock.php new file mode 100644 index 000000000..a0bcb01f9 --- /dev/null +++ b/actions/groupunblock.php @@ -0,0 +1,149 @@ + + * @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); +} + +/** + * Unlock a user from a group + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ + +class GroupunblockAction extends Action +{ + var $profile = null; + var $group = 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 (empty($token) || $token != common_session_token()) { + $this->clientError(_('There was a problem with your session token. Try again, please.')); + return; + } + $id = $this->trimmed('unblockto'); + if (empty($id)) { + $this->clientError(_('No profile specified.')); + return false; + } + $this->profile = Profile::staticGet('id', $id); + if (empty($this->profile)) { + $this->clientError(_('No profile with that ID.')); + return false; + } + $group_id = $this->trimmed('unblockgroup'); + if (empty($group_id)) { + $this->clientError(_('No group specified.')); + return false; + } + $this->group = User_group::staticGet('id', $group_id); + if (empty($this->group)) { + $this->clientError(_('No such group.')); + return false; + } + $user = common_current_user(); + if (!$user->isAdmin($this->group)) { + $this->clientError(_('Only an admin can unblock group members.'), 401); + return false; + } + if (!Group_block::isBlocked($this->group, $this->profile)) { + $this->clientError(_('User is not blocked from group.')); + return false; + } + return true; + } + + /** + * Handle request + * + * @param array $args $_REQUEST args; handled in prepare() + * + * @return void + */ + + function handle($args) + { + parent::handle($args); + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + $this->unblockProfile(); + } + } + + /** + * Unblock a user. + * + * @return void + */ + + function unblockProfile() + { + $result = Group_block::unblockProfile($this->group, $this->profile); + + if (!$result) { + $this->serverError(_('Error removing the block.')); + return; + } + + foreach ($this->args as $k => $v) { + if ($k == 'returnto-action') { + $action = $v; + } else if (substr($k, 0, 9) == 'returnto-') { + $args[substr($k, 9)] = $v; + } + } + + if ($action) { + common_redirect(common_local_url($action, $args), 303); + } else { + common_redirect(common_local_url('blockedfromgroup', + array('nickname' => $this->group->nickname)), + 303); + } + } +} + diff --git a/classes/Group_block.php b/classes/Group_block.php index d945fd57a..4c583d8e2 100644 --- a/classes/Group_block.php +++ b/classes/Group_block.php @@ -92,4 +92,24 @@ class Group_block extends Memcached_DataObject return $block; } + + static function unblockProfile($group, $profile) + { + $block = Group_block::pkeyGet(array('group_id' => $group->id, + 'blocked' => $profile->id)); + + if (empty($block)) { + return null; + } + + $result = $block->delete(); + + if (!$result) { + common_log_db_error($block, 'DELETE', __FILE__); + return null; + } + + return true; + } + } diff --git a/classes/User_group.php b/classes/User_group.php index 1be34b60b..9f9977755 100644 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -125,6 +125,29 @@ class User_group extends Memcached_DataObject return $members; } + function getBlocked($offset=0, $limit=null) + { + $qry = + 'SELECT profile.* ' . + 'FROM profile JOIN group_block '. + 'ON profile.id = group_block.blocked ' . + 'WHERE group_block.group_id = %d ' . + 'ORDER BY group_block.modified DESC '; + + if ($limit != null) { + if (common_config('db','type') == 'pgsql') { + $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; + } else { + $qry .= ' LIMIT ' . $offset . ', ' . $limit; + } + } + + $blocked = new Profile(); + + $blocked->query(sprintf($qry, $this->id)); + return $blocked; + } + function setOriginal($filename) { $imagefile = new ImageFile($this->id, Avatar::path($filename)); diff --git a/lib/groupnav.php b/lib/groupnav.php index 90bdc1014..194247982 100644 --- a/lib/groupnav.php +++ b/lib/groupnav.php @@ -95,6 +95,12 @@ class GroupNav extends Widget $cur = common_current_user(); if ($cur && $cur->isAdmin($this->group)) { + $this->out->menuItem(common_local_url('blockedfromgroup', array('nickname' => + $nickname)), + _('Blocked'), + sprintf(_('%s blocked users'), $nickname), + $action_name == 'blockedfromgroup', + 'nav_group_blocked'); $this->out->menuItem(common_local_url('editgroup', array('nickname' => $nickname)), _('Admin'), diff --git a/lib/router.php b/lib/router.php index 3d870e565..e10871bc0 100644 --- a/lib/router.php +++ b/lib/router.php @@ -101,7 +101,8 @@ class Router $main = array('login', 'logout', 'register', 'subscribe', 'unsubscribe', 'confirmaddress', 'recoverpassword', 'invite', 'favor', 'disfavor', 'sup', - 'block', 'unblock', 'subedit', 'groupblock'); + 'block', 'unblock', 'subedit', + 'groupblock', 'groupunblock'); foreach ($main as $a) { $m->connect('main/'.$a, array('action' => $a)); @@ -228,6 +229,10 @@ class Router array('nickname' => '[a-zA-Z0-9]+')); } + $m->connect('group/:nickname/blocked', + array('action' => 'blockedfromgroup'), + array('nickname' => '[a-zA-Z0-9]+')); + $m->connect('group/:id/id', array('action' => 'groupbyid'), array('id' => '[0-9]+')); -- cgit v1.2.3-54-g00ecf From 0bc9b2e730bb6368d36ba5bb3f2df1bf1432adad Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 15 Jun 2009 03:21:15 +0000 Subject: Cross-browser notice_attach --- lib/noticeform.php | 4 ++-- theme/base/css/display.css | 20 +++++++++++--------- theme/base/css/ie.css | 9 +++++++++ theme/default/css/ie.css | 7 ++++++- theme/identica/css/ie.css | 7 ++++++- 5 files changed, 34 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/noticeform.php b/lib/noticeform.php index 3212f382a..0ad365856 100644 --- a/lib/noticeform.php +++ b/lib/noticeform.php @@ -148,12 +148,12 @@ class NoticeForm extends Form $this->out->element('dd', array('id' => 'notice_text-count'), '140'); $this->out->elementEnd('dl'); - $this->out->hidden('MAX_FILE_SIZE', common_config('attachments', 'file_quota')); - $this->out->element('label', array('for' => 'notice_data-attach'), _('Attach')); + $this->out->element('label', array('for' => 'notice_data-attach'),_('Attach')); $this->out->element('input', array('id' => 'notice_data-attach', 'type' => 'file', 'name' => 'attach', 'title' => _('Attach a file'))); + $this->out->hidden('MAX_FILE_SIZE', common_config('attachments', 'file_quota')); if ($this->action) { $this->out->hidden('notice_return-to', $this->action, 'returnto'); } diff --git a/theme/base/css/display.css b/theme/base/css/display.css index dc275e19f..060fdfd0d 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -445,6 +445,8 @@ width:80.789%; height:67px; line-height:1.5; padding:7px 7px 16px 7px; +position:relative; +z-index:2; } #form_notice label { display:block; @@ -452,23 +454,23 @@ float:left; font-size:1.3em; margin-bottom:7px; } -#form_notice label[for=notice_data-attach] { -text-indent:-9999px; -} #form_notice label[for=notice_data-attach], #form_notice #notice_data-attach { position:absolute; top:25px; -right:49px; +cursor:pointer; +} +#form_notice label[for=notice_data-attach] { +text-indent:-9999px; +left:394px; width:16px; height:16px; -cursor:pointer; } #form_notice #notice_data-attach { -text-indent:-279px; -} -#form_notice #notice_submit label { -display:none; +left:183px; +padding:0; + +height:16px; } #form_notice .form_note { position:absolute; diff --git a/theme/base/css/ie.css b/theme/base/css/ie.css index 8183fee67..d1b0558ec 100644 --- a/theme/base/css/ie.css +++ b/theme/base/css/ie.css @@ -8,6 +8,15 @@ top:0; #form_notice textarea { width:78%; } +#form_notice .form_note + label { +position:absolute; +top:25px; +left:380px; +text-indent:-9999px; +height:16px; +width:16px; +display:block; +} #form_notice #notice_action-submit { width:17%; max-width:17%; diff --git a/theme/default/css/ie.css b/theme/default/css/ie.css index 2b06768ea..6501f4e48 100644 --- a/theme/default/css/ie.css +++ b/theme/default/css/ie.css @@ -3,7 +3,12 @@ .notice-options input.submit { color:#fff; } - #site_nav_local_views a { background-color:#ACCCDA; } +#form_notice .form_note + label { +background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no-repeat 0 45%; +} +#form_notice #notice_data-attach { +filter: alpha(opacity=0); +} \ No newline at end of file diff --git a/theme/identica/css/ie.css b/theme/identica/css/ie.css index 2f463bb44..69db16aad 100644 --- a/theme/identica/css/ie.css +++ b/theme/identica/css/ie.css @@ -3,7 +3,12 @@ .notice-options input.submit { color:#fff; } - #site_nav_local_views a { background-color:#D0DFE7; } +#form_notice .form_note + label { +background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no-repeat 0 45%; +} +#form_notice #notice_data-attach { +filter: alpha(opacity=0); +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf From ee8dd62038993c184b704df08a3ab1fbcf0c04ac Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 22:07:27 -0700 Subject: try to get the right class for profileminilist --- lib/profilelist.php | 17 +++++++++++++++-- lib/profileminilist.php | 5 +++++ 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/profilelist.php b/lib/profilelist.php index e2faf10af..bd866bed7 100644 --- a/lib/profilelist.php +++ b/lib/profilelist.php @@ -61,9 +61,24 @@ class ProfileList extends Widget } function show() + { + $this->startList(); + $this->showProfiles(); + $this->endList(); + } + + function startList() { $this->out->elementStart('ul', 'profiles'); + } + function endList() + { + $this->out->elementEnd('ul'); + } + + function showProfiles() + { $cnt = 0; while ($this->profile->fetch()) { @@ -75,8 +90,6 @@ class ProfileList extends Widget $pli->show(); } - $this->out->elementEnd('ul'); - return $cnt; } diff --git a/lib/profileminilist.php b/lib/profileminilist.php index f11cae8a5..0c02e2735 100644 --- a/lib/profileminilist.php +++ b/lib/profileminilist.php @@ -47,6 +47,11 @@ define('PROFILES_PER_MINILIST', 27); class ProfileMiniList extends ProfileList { + function startList() + { + $this->out->elementStart('ul', 'entity users xoxo'); + } + function newListItem($profile) { return new ProfileMiniListItem($profile, $this->action); -- cgit v1.2.3-54-g00ecf From bef643352d573235aedbdd93125e93c42edb306b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 22:09:04 -0700 Subject: return count from show --- lib/profilelist.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/profilelist.php b/lib/profilelist.php index bd866bed7..a604230f8 100644 --- a/lib/profilelist.php +++ b/lib/profilelist.php @@ -63,8 +63,9 @@ class ProfileList extends Widget function show() { $this->startList(); - $this->showProfiles(); + $cnt = $this->showProfiles(); $this->endList(); + return $cnt; } function startList() -- cgit v1.2.3-54-g00ecf From 7097804eeb0c648391544f55e32bd66bc35bcdb1 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 22:09:17 -0700 Subject: typo in profileminilist class --- lib/profileminilist.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/profileminilist.php b/lib/profileminilist.php index 0c02e2735..09bef6f7c 100644 --- a/lib/profileminilist.php +++ b/lib/profileminilist.php @@ -49,7 +49,7 @@ class ProfileMiniList extends ProfileList { function startList() { - $this->out->elementStart('ul', 'entity users xoxo'); + $this->out->elementStart('ul', 'entities users xoxo'); } function newListItem($profile) -- cgit v1.2.3-54-g00ecf From ecbd7718d57fc427d2aeac885d8be0321b3cf1fe Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 23:37:24 -0700 Subject: Code for adding and saving group aliases Added code to add and save group aliases. Like tags, aliases are free-texted in to the group admin page. configurable max number of aliases, default is three. --- README | 8 ++++++- actions/editgroup.php | 59 ++++++++++++++++++++++++++++++++++++++++++++++--- actions/newgroup.php | 51 +++++++++++++++++++++++++++++++++++++++++- classes/User_group.php | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/common.php | 2 ++ lib/groupeditform.php | 11 ++++++++- 6 files changed, 185 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/README b/README index 2099f94d6..8fb4a941c 100644 --- a/README +++ b/README @@ -1196,7 +1196,6 @@ reporturl: URL to post statistics to. Defaults to Laconica developers' set 'run' to 'never' than to set this value to something nonsensical. - attachments ----------- @@ -1226,6 +1225,13 @@ user_quota: total size in bytes a user can store on this server. Each user monthly_quota: total size permitted in the current month. This is the total size in bytes that a user can upload each month. +group +----- + +Options for group functionality. + +maxaliases: maximum number of aliases a group can have. Default 3. Set + to 0 or less to prevent aliases in a group. Troubleshooting =============== diff --git a/actions/editgroup.php b/actions/editgroup.php index 39dad0465..29a7bce43 100644 --- a/actions/editgroup.php +++ b/actions/editgroup.php @@ -171,6 +171,7 @@ class EditgroupAction extends Action $homepage = $this->trimmed('homepage'); $description = $this->trimmed('description'); $location = $this->trimmed('location'); + $aliasstring = $this->trimmed('aliases'); if (!Validate::string($nickname, array('min_length' => 1, 'max_length' => 64, @@ -201,6 +202,39 @@ class EditgroupAction extends Action return; } + if (!empty($aliasstring)) { + $aliases = array_map('common_canonical_nickname', array_unique(preg_split('/[\s,]+/', $aliasstring))); + } else { + $aliases = array(); + } + + if (count($aliases) > common_config('group', 'maxaliases')) { + $this->showForm(sprintf(_('Too many aliases! Maximum %d.'), + common_config('group', 'maxaliases'))); + return; + } + + foreach ($aliases as $alias) { + if (!Validate::string($alias, array('min_length' => 1, + 'max_length' => 64, + 'format' => NICKNAME_FMT))) { + $this->showForm(sprintf(_('Invalid alias: "%s"'), $alias)); + return; + } + if ($this->nicknameExists($alias)) { + $this->showForm(sprintf(_('Alias "%s" already in use. Try another one.'), + $alias)); + return; + } + // XXX assumes alphanum nicknames + if (strcmp($alias, $nickname) == 0) { + $this->showForm(_('Alias can\'t be the same as nickname.')); + return; + } + } + + $this->group->query('BEGIN'); + $orig = clone($this->group); $this->group->nickname = $nickname; @@ -217,6 +251,14 @@ class EditgroupAction extends Action $this->serverError(_('Could not update group.')); } + $result = $this->group->setAliases($aliases); + + if (!$result) { + $this->serverError(_('Could not create aliases.')); + } + + $this->group->query('COMMIT'); + if ($this->group->nickname != $orig->nickname) { common_redirect(common_local_url('editgroup', array('nickname' => $nickname)), @@ -229,9 +271,20 @@ class EditgroupAction extends Action function nicknameExists($nickname) { $group = User_group::staticGet('nickname', $nickname); - return (!is_null($group) && - $group != false && - $group->id != $this->group->id); + + if (!empty($group) && + $group->id != $this->group->id) { + return true; + } + + $alias = Group_alias::staticGet('alias', $nickname); + + if (!empty($alias) && + $alias->group_id != $this->group->id) { + return true; + } + + return false; } } diff --git a/actions/newgroup.php b/actions/newgroup.php index 67cd6b2f1..0289e77c2 100644 --- a/actions/newgroup.php +++ b/actions/newgroup.php @@ -123,6 +123,7 @@ class NewgroupAction extends Action $homepage = $this->trimmed('homepage'); $description = $this->trimmed('description'); $location = $this->trimmed('location'); + $aliasstring = $this->trimmed('aliases'); if (!Validate::string($nickname, array('min_length' => 1, 'max_length' => 64, @@ -153,6 +154,37 @@ class NewgroupAction extends Action return; } + if (!empty($aliasstring)) { + $aliases = array_map('common_canonical_nickname', array_unique(preg_split('/[\s,]+/', $aliasstring))); + } else { + $aliases = array(); + } + + if (count($aliases) > common_config('group', 'maxaliases')) { + $this->showForm(sprintf(_('Too many aliases! Maximum %d.'), + common_config('group', 'maxaliases'))); + return; + } + + foreach ($aliases as $alias) { + if (!Validate::string($alias, array('min_length' => 1, + 'max_length' => 64, + 'format' => NICKNAME_FMT))) { + $this->showForm(sprintf(_('Invalid alias: "%s"'), $alias)); + return; + } + if ($this->nicknameExists($alias)) { + $this->showForm(sprintf(_('Alias "%s" already in use. Try another one.'), + $alias)); + return; + } + // XXX assumes alphanum nicknames + if (strcmp($alias, $nickname) == 0) { + $this->showForm(_('Alias can\'t be the same as nickname.')); + return; + } + } + $cur = common_current_user(); // Checked in prepare() above @@ -177,6 +209,12 @@ class NewgroupAction extends Action $this->serverError(_('Could not create group.')); } + $result = $group->setAliases($aliases); + + if (!$result) { + $this->serverError(_('Could not create aliases.')); + } + $member = new Group_member(); $member->group_id = $group->id; @@ -199,7 +237,18 @@ class NewgroupAction extends Action function nicknameExists($nickname) { $group = User_group::staticGet('nickname', $nickname); - return (!is_null($group) && $group != false); + + if (!empty($group)) { + return true; + } + + $alias = Group_alias::staticGet('alias', $nickname); + + if (!empty($alias)) { + return true; + } + + return false; } } diff --git a/classes/User_group.php b/classes/User_group.php index 9f9977755..0fcfee8c6 100644 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -165,4 +165,64 @@ class User_group extends Memcached_DataObject { return ($this->fullname) ? $this->fullname : $this->nickname; } + + function getAliases() + { + $aliases = array(); + + // XXX: cache this + + $alias = new Group_alias(); + + $alias->group_id = $this->id; + + if ($alias->find()) { + while ($alias->fetch()) { + $aliases[] = $alias->alias; + } + } + + $alias->free(); + + return $aliases; + } + + function setAliases($newaliases) { + + $newaliases = array_unique($newaliases); + + $oldaliases = $this->getAliases(); + + # Delete stuff that's old that not in new + + $to_delete = array_diff($oldaliases, $newaliases); + + # Insert stuff that's in new and not in old + + $to_insert = array_diff($newaliases, $oldaliases); + + $alias = new Group_alias(); + + $alias->group_id = $this->id; + + foreach ($to_delete as $delalias) { + $alias->alias = $delalias; + $result = $alias->delete(); + if (!$result) { + common_log_db_error($alias, 'DELETE', __FILE__); + return false; + } + } + + foreach ($to_insert as $insalias) { + $alias->alias = $insalias; + $result = $alias->insert(); + if (!$result) { + common_log_db_error($alias, 'INSERT', __FILE__); + return false; + } + } + + return true; + } } diff --git a/lib/common.php b/lib/common.php index 6bf4ad21f..b4e87445e 100644 --- a/lib/common.php +++ b/lib/common.php @@ -198,6 +198,8 @@ $config = 'user_quota' => 50000000, 'monthly_quota' => 15000000, ), + 'group' => + array('maxaliases' => 3), ); $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); diff --git a/lib/groupeditform.php b/lib/groupeditform.php index ca674f3c8..7e8d6eea3 100644 --- a/lib/groupeditform.php +++ b/lib/groupeditform.php @@ -111,7 +111,6 @@ class GroupEditForm extends Form } } - /** * Name of the form * @@ -157,6 +156,16 @@ class GroupEditForm extends Form ($this->out->arg('location')) ? $this->out->arg('location') : $this->group->location, _('Location for the group, if any, like "City, State (or Region), Country"')); $this->out->elementEnd('li'); + if (common_config('group', 'maxaliases') > 0) { + $aliases = (empty($this->group)) ? array() : $this->group->getAliases(); + $this->out->elementStart('li'); + $this->out->input('aliases', _('Aliases'), + ($this->out->arg('aliases')) ? $this->out->arg('aliases') : + (!empty($aliases)) ? implode(' ', $aliases) : '', + sprintf(_('Extra nicknames for the group, comma- or space- separated, max %d'), + common_config('group', 'maxaliases')));; + $this->out->elementEnd('li'); + } $this->out->elementEnd('ul'); } -- cgit v1.2.3-54-g00ecf From 1b6b00a6d05ad646a9137a872af8d8fdeeaf260f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 14 Jun 2009 23:43:47 -0700 Subject: Link and distribute notices tagged for a group alias Correctly link and distribute notices tagged for a group alias. Added a helper function, getForNickname(), to User_group, to make it easier to get a group by its nickname or aliases. --- classes/Notice.php | 6 +++--- classes/User_group.php | 14 ++++++++++++++ lib/util.php | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/classes/Notice.php b/classes/Notice.php index 78786b27d..68602b1f7 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -752,16 +752,16 @@ class Notice extends Memcached_DataObject foreach (array_unique($match[1]) as $nickname) { /* XXX: remote groups. */ - $group = User_group::staticGet('nickname', $nickname); + $group = User_group::getForNickname($nickname); - if (!$group) { + if (empty($group)) { continue; } // we automatically add a tag for every group name, too $tag = Notice_tag::pkeyGet(array('tag' => common_canonical_tag($nickname), - 'notice_id' => $this->id)); + 'notice_id' => $this->id)); if (is_null($tag)) { $this->saveTag($nickname); diff --git a/classes/User_group.php b/classes/User_group.php index 0fcfee8c6..1a24124bb 100644 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -225,4 +225,18 @@ class User_group extends Memcached_DataObject return true; } + + static function getForNickname($nickname) + { + $nickname = common_canonical_nickname($nickname); + $group = User_group::staticGet('nickname', $nickname); + if (!empty($group)) { + return $group; + } + $alias = Group_alias::staticGet('alias', $nickname); + if (!empty($alias)) { + return User_group::staticGet('id', $alias->group_id); + } + return null; + } } diff --git a/lib/util.php b/lib/util.php index b3a94a5a0..49c6ae108 100644 --- a/lib/util.php +++ b/lib/util.php @@ -591,7 +591,7 @@ function common_at_link($sender_id, $nickname) function common_group_link($sender_id, $nickname) { $sender = Profile::staticGet($sender_id); - $group = User_group::staticGet('nickname', common_canonical_nickname($nickname)); + $group = User_group::getForNickname($nickname); if ($group && $sender->isMember($group)) { $attrs = array('href' => $group->permalink(), 'class' => 'url'); -- cgit v1.2.3-54-g00ecf From 2b8a767770119165ab9c9ce62ea3512c2fb3b049 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 00:59:15 -0700 Subject: make admins of groups --- actions/groupmembers.php | 143 +++++++++++++++++++++++++++++++++++++++++++++++ lib/router.php | 4 ++ 2 files changed, 147 insertions(+) (limited to 'lib') diff --git a/actions/groupmembers.php b/actions/groupmembers.php index 65790b7ca..abfad3f0d 100644 --- a/actions/groupmembers.php +++ b/actions/groupmembers.php @@ -171,10 +171,26 @@ class GroupMemberListItem extends ProfileListItem { $this->startActions(); $this->showSubscribeButton(); + $this->showMakeAdminForm(); $this->showGroupBlockForm(); $this->endActions(); } + function showMakeAdminForm() + { + $user = common_current_user(); + + if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group) && + !$this->profile->isAdmin($this->group)) { + $this->out->elementStart('li', 'entity_make_admin'); + $maf = new MakeAdminForm($this->out, $this->profile, $this->group, + array('action' => 'groupmembers', + 'nickname' => $this->group->nickname)); + $maf->show(); + $this->out->elementEnd('li'); + } + + } function showGroupBlockForm() { $user = common_current_user(); @@ -318,3 +334,130 @@ class GroupBlockForm extends Form $this->out->submit('submit', _('Block'), 'submit', null, _('Block this user')); } } + +/** + * Form for making a user an admin for a group + * + * @category Form + * @package Laconica + * @author Evan Prodromou + * @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/ + */ + +class MakeAdminForm extends Form +{ + /** + * Profile of user to block + */ + + var $profile = null; + + /** + * Group to block the user from + */ + + var $group = null; + + /** + * Return-to args + */ + + var $args = null; + + /** + * Constructor + * + * @param HTMLOutputter $out output channel + * @param Profile $profile profile of user to block + * @param User_group $group group to block user from + * @param array $args return-to args + */ + + function __construct($out=null, $profile=null, $group=null, $args=null) + { + parent::__construct($out); + + $this->profile = $profile; + $this->group = $group; + $this->args = $args; + } + + /** + * ID of the form + * + * @return int ID of the form + */ + + function id() + { + // This should be unique for the page. + return 'makeadmin-' . $this->profile->id; + } + + /** + * class of the form + * + * @return string class of the form + */ + + function formClass() + { + return 'form_make_admin'; + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return common_local_url('makeadmin', array('nickname' => $this->group->nickname)); + } + + /** + * Legend of the Form + * + * @return void + */ + + function formLegend() + { + $this->out->element('legend', null, _('Make user an admin of the group')); + } + + /** + * Data elements of the form + * + * @return void + */ + + function formData() + { + $this->out->hidden('profileid-' . $this->profile->id, + $this->profile->id, + 'profileid'); + $this->out->hidden('groupid-' . $this->group->id, + $this->group->id, + 'groupid'); + if ($this->args) { + foreach ($this->args as $k => $v) { + $this->out->hidden('returnto-' . $k, $v); + } + } + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->submit('submit', _('Make Admin'), 'submit', null, _('Make this user an admin')); + } +} diff --git a/lib/router.php b/lib/router.php index e10871bc0..0fbaba9ed 100644 --- a/lib/router.php +++ b/lib/router.php @@ -233,6 +233,10 @@ class Router array('action' => 'blockedfromgroup'), array('nickname' => '[a-zA-Z0-9]+')); + $m->connect('group/:nickname/makeadmin', + array('action' => 'makeadmin'), + array('nickname' => '[a-zA-Z0-9]+')); + $m->connect('group/:id/id', array('action' => 'groupbyid'), array('id' => '[0-9]+')); -- cgit v1.2.3-54-g00ecf From c077ad0775218e6aa8660ba97129ad74b5d54773 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 10:45:50 -0700 Subject: Configurable avatar directory Avatar directory and path are configurable. --- README | 6 ++++++ classes/Avatar.php | 30 +++++++++++++++++++++++++++--- lib/common.php | 4 +++- 3 files changed, 36 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/README b/README index 8fb4a941c..5b6b847c8 100644 --- a/README +++ b/README @@ -1008,6 +1008,12 @@ avatar For configuring avatar access. +dir: Directory to look for avatar files and to put them into. + Defaults to avatar subdirectory of install directory; if + you change it, make sure to change path, too. +path: Path to avatars. Defaults to path for avatar subdirectory, + but you can change it if you wish. Note that this will + be included with the avatar server, too. server: If set, defines another server where avatars are stored in the root directory. Note that the 'avatar' subdir still has to be writeable. You'd typically use this to split HTTP requests on diff --git a/classes/Avatar.php b/classes/Avatar.php index db9d78e47..5e8b315fe 100644 --- a/classes/Avatar.php +++ b/classes/Avatar.php @@ -55,19 +55,43 @@ class Avatar extends Memcached_DataObject static function path($filename) { - return INSTALLDIR . '/avatar/' . $filename; + $dir = common_config('avatar', 'dir'); + + if ($dir[strlen($dir)-1] != '/') { + $dir .= '/'; + } + + return $dir . $filename; } static function url($filename) { - return common_path('avatar/'.$filename); + $path = common_config('avatar', 'path'); + + if ($path[strlen($path)-1] != '/') { + $path .= '/'; + } + + if ($path[0] != '/') { + $path = '/'.$path; + } + + $server = common_config('avatar', 'server'); + + if (empty($server)) { + $server = common_config('site', 'server'); + } + + // XXX: protocol + + return 'http://'.$server.$path.$filename; } function displayUrl() { $server = common_config('avatar', 'server'); if ($server) { - return 'http://'.$server.'/'.$this->filename; + return Avatar::url($this->filename); } else { return $this->url; } diff --git a/lib/common.php b/lib/common.php index b4e87445e..ab61c812f 100644 --- a/lib/common.php +++ b/lib/common.php @@ -108,7 +108,9 @@ $config = 'profile' => array('banned' => array()), 'avatar' => - array('server' => null), + array('server' => null, + 'dir' => INSTALLDIR . '/avatar/', + 'path' => $_path . '/avatar/'), 'public' => array('localonly' => true, 'blacklist' => array(), -- cgit v1.2.3-54-g00ecf From fd290fc3f9a40a0d3be4e4ffc7d11846bf5295b8 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 15 Jun 2009 16:09:40 -0700 Subject: allow a configured base for cache keys --- README | 7 +++++++ lib/common.php | 1 + lib/util.php | 8 +++++++- 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/README b/README index 5b6b847c8..57ff72f66 100644 --- a/README +++ b/README @@ -1106,6 +1106,13 @@ database data in memcached . enabled: Set to true to enable. Default false. server: a string with the hostname of the memcached server. Can also be an array of hostnames, if you've got more than one server. +base: memcached uses key-value pairs to store data. We build long, + funny-looking keys to make sure we don't have any conflicts. The + base of the key is usually a simplified version of the site name + (like "Identi.ca" => "identica"), but you can overwrite this if + you need to. You can safely ignore it if you only have one + Laconica site using your memcached server. +port: Port to connect to; defaults to 11211. sphinx ------ diff --git a/lib/common.php b/lib/common.php index ab61c812f..51204cede 100644 --- a/lib/common.php +++ b/lib/common.php @@ -152,6 +152,7 @@ $config = 'memcached' => array('enabled' => false, 'server' => 'localhost', + 'base' => null, 'port' => 11211), 'ping' => array('notify' => array()), diff --git a/lib/util.php b/lib/util.php index 49c6ae108..1d5708bd6 100644 --- a/lib/util.php +++ b/lib/util.php @@ -1322,7 +1322,13 @@ function common_session_token() function common_cache_key($extra) { - return 'laconica:' . common_keyize(common_config('site', 'name')) . ':' . $extra; + $base_key = common_config('memcached', 'base'); + + if (empty($base_key)) { + $base_key = common_keyize(common_config('site', 'name')); + } + + return 'laconica:' . $base_key . ':' . $extra; } function common_keyize($str) -- cgit v1.2.3-54-g00ecf From 20d93508776398627f5aff64b83bd20a362cb45d Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Jun 2009 20:21:33 -0700 Subject: User design setting save now --- actions/designsettings.php | 256 ++++++++++++++++++++++++++++++++------------- lib/webcolor.php | 191 +++++++++++++++++++++++++++++++++ 2 files changed, 373 insertions(+), 74 deletions(-) create mode 100644 lib/webcolor.php (limited to 'lib') diff --git a/actions/designsettings.php b/actions/designsettings.php index dba983fdf..0f7c27194 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -32,7 +32,8 @@ if (!defined('LACONICA')) { exit(1); } -require_once INSTALLDIR.'/lib/accountsettingsaction.php'; +require_once INSTALLDIR . '/lib/accountsettingsaction.php'; +require_once INSTALLDIR . '/lib/WebColor.php'; class DesignsettingsAction extends AccountSettingsAction { @@ -81,7 +82,7 @@ class DesignsettingsAction extends AccountSettingsAction $this->element('legend', null, _('Change background image')); $this->elementStart('ul', 'form_data'); $this->elementStart('li'); - $this->element('label', array('for' => 'design_background-image_file'), + $this->element('label', array('for' => 'design_background-image_file'), _('Upload file')); $this->element('input', array('name' => 'design_background-image_file', 'type' => 'file', @@ -105,61 +106,79 @@ class DesignsettingsAction extends AccountSettingsAction $design = $this->defaultDesign(); } - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-0'), _('Background')); - $this->element('input', array('name' => 'design_background', - 'type' => 'text', - 'id' => 'swatch-0', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => $design->backgroundcolor)); - $this->elementEnd('li'); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-1'), _('Content')); - $this->element('input', array('name' => 'design_content', - 'type' => 'text', - 'id' => 'swatch-1', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => $design->contentcolor)); - $this->elementEnd('li'); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-2'), _('Sidebar')); - $this->element('input', array('name' => 'design_sidebar', - 'type' => 'text', - 'id' => 'swatch-2', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => $design->sidebarcolor)); - $this->elementEnd('li'); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-3'), _('Text')); - $this->element('input', array('name' => 'design_text', - 'type' => 'text', - 'id' => 'swatch-3', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => $design->textcolor)); - $this->elementEnd('li'); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-4'), _('Links')); - $this->element('input', array('name' => 'design_links', - 'type' => 'text', - 'id' => 'swatch-4', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => $design->linkcolor)); - - $this->elementEnd('li'); + try { + + $bgcolor = new WebColor($design->backgroundcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-0'), _('Background')); + $this->element('input', array('name' => 'design_background', + 'type' => 'text', + 'id' => 'swatch-0', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $bgcolor->hexValue())); + $this->elementEnd('li'); + + + $ccolor = new WebColor($design->contentcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-1'), _('Content')); + $this->element('input', array('name' => 'design_content', + 'type' => 'text', + 'id' => 'swatch-1', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $ccolor->hexValue())); + $this->elementEnd('li'); + + $sbcolor = new WebColor($design->sidebarcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-2'), _('Sidebar')); + $this->element('input', array('name' => 'design_sidebar', + 'type' => 'text', + 'id' => 'swatch-2', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $sbcolor->hexValue())); + $this->elementEnd('li'); + + $tcolor = new WebColor($design->textcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-3'), _('Text')); + $this->element('input', array('name' => 'design_text', + 'type' => 'text', + 'id' => 'swatch-3', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $tcolor->hexValue())); + $this->elementEnd('li'); + + $lcolor = new WebColor($design->linkcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-4'), _('Links')); + $this->element('input', array('name' => 'design_links', + 'type' => 'text', + 'id' => 'swatch-4', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $lcolor->hexValue())); + + $this->elementEnd('li'); + + } catch (WebColorException $e) { + common_log(LOG_ERR, 'Bad color values in design ID: ' . + $design->id); + } $this->elementEnd('ul'); $this->elementEnd('fieldset'); @@ -169,7 +188,7 @@ class DesignsettingsAction extends AccountSettingsAction 'value' => 'Reset', 'class' => 'submit form_action-primary', 'title' => _('Reset back to default'))); - + $this->submit('save', _('Save'), 'submit form_action-secondary', 'save', _('Save design')); @@ -241,40 +260,129 @@ class DesignsettingsAction extends AccountSettingsAction $this->element('script', array('type' => 'text/javascript', 'src' => $farbtasticGo)); } - + /** * Get a default user design * - * @return Design design + * @return Design design */ - + function defaultDesign() { $defaults = common_config('site', 'design'); $design = new Design(); - $design->backgroundcolor = $defaults['backgroundcolor']; - $design->contentcolor = $defaults['contentcolor']; - $design->sidebarcolor = $defaults['sidebarcolor']; - $design->textcolor = $defaults['textcolor']; - $design->linkcolor = $defaults['linkcolor']; - $design->backgroundimage = $defaults['backgroundimage']; + + try { + + $color = new WebColor(); + + $color->parseColor($defaults['backgroundcolor']); + $design->backgroundcolor = $color->intValue(); + + $color->parseColor($defaults['contentcolor']); + $design->contentcolor = $color->intValue(); + + $color->parseColor($defaults['sidebarcolor']); + $design->sidebarcolor = $color->intValue(); + + $color->parseColor($defaults['textcolor']); + $design->sidebarcolor = $color->intValue(); + + $color->parseColor($defaults['linkcolor']); + $design->linkcolor = $color->intValue(); + + $design->backgroundimage = $defaults['backgroundimage']; + + } catch (WebColorException $e) { + common_log(LOG_ERR, _('Bad default color settings: ' . + $e->getMessage())); + } return $design; } /** - * Save the user's design settings + * Save or update the user's design settings * * @return void */ - + function saveDesign() { $user = common_current_user(); - - - + + try { + + $bgcolor = new WebColor($this->trimmed('design_background')); + $ccolor = new WebColor($this->trimmed('design_content')); + $sbcolor = new WebColor($this->trimmed('design_sidebar')); + $tcolor = new WebColor($this->trimmed('design_text')); + $lcolor = new WebColor($this->trimmed('design_links')); + + } catch (WebColorException $e) { + $this->showForm($e->getMessage()); + return; + } + + $design = User::getDesign(); + + if (!isset($design)) { + + $original = clone($design); + + $original->backgroundcolor = $bgcolor->intValue(); + $original->contentcolor = $ccolor->intValue(); + $original->sidebarcolor = $sbcolor->intValue(); + $original->textcolor = $tcolor->intValue(); + $original->linkcolor = $lcolor->intValue(); + + $result = $design->update($original); + + if ($result === false) { + common_log_db_error($design, 'UPDATE', __FILE__); + $this->showForm(_('Couldn\'t update your design.')); + return; + } + + // update design + } else { + + $user->query('BEGIN'); + + // save new design + $design = new Design(); + + $design->backgroundcolor = $bgcolor->intValue(); + $design->contentcolor = $ccolor->intValue(); + $design->sidebarcolor = $sbcolor->intValue(); + $design->textcolor = $tcolor->intValue(); + $design->linkcolor = $lcolor->intValue(); + $design->backgroundimage = $defaults['backgroundimage']; + + $id = $design->insert(); + + if (empty($id)) { + common_log_db_error($id, 'INSERT', __FILE__); + $this->showForm(_('Unable to save your design settings!')); + return; + } + + $original = clone($user); + $user->design_id = $id; + $result = $user->update($original); + + if (empty($result)) { + common_log_db_error($original, 'UPDATE', __FILE__); + $this->showForm(_('Unable to save your design settings!')); + $user->query('ROLLBACK'); + return; + } + + $user->query('COMMIT'); + + } + $this->showForm(_('Design preferences saved.'), true); } @@ -282,9 +390,9 @@ class DesignsettingsAction extends AccountSettingsAction * Reset design settings to previous saved value if any, or * the defaults * - * @return void + * @return void */ - + function resetDesign() { $this->showForm(_('Design preferences reset.'), true); diff --git a/lib/webcolor.php b/lib/webcolor.php new file mode 100644 index 000000000..65713d26e --- /dev/null +++ b/lib/webcolor.php @@ -0,0 +1,191 @@ +. + * + * @category Personal + * @package Laconica + * @author Zach Copley + * @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); +} + +class WebColor { + + // XXX: Maybe make getters and setters for r,g,b values and tuples, + // e.g.: to support this kinda CSS representation: rgb(255,0,0) + // http://www.w3.org/TR/CSS21/syndata.html#color-units + + var $red = 0; + var $green = 0; + var $blue = 0; + + /** + * Constructor + * + * @return nothing + */ + + function __construct($color = null) + { + if (isset($color)) { + $this->parseColor($color); + } + } + + /** + * Parses input to and tries to determine whether the color + * is being specified via an integer or hex tuple and sets + * the RGB instance variables accordingly. + * + * XXX: Maybe support (r,g,b) style, and array? + * + * @param mixed $color + * + * @return nothing + */ + + function parseColor($color) { + + if (is_numeric($color)) { + $this->setIntColor($color); + } else { + + // XXX named colors + + // XXX: probably should do even more validation + + if (preg_match('/(#([0-9A-Fa-f]{3,6})\b)/u', $color) > 0) { + $this->setHexColor($color); + } else { + $errmsg = _('%s is not a valid color!'); + throw new WebColorException(sprintf($errmsg, $color)); + } + } + } + + /** + * @param string $name + * + * @return nothing + */ + + function setNamedColor($name) + { + // XXX Implement this + } + + + /** + * Sets the RGB color values from a a hex tuple + * + * @param string $hexcolor + * + * @return nothing + */ + + function setHexColor($hexcolor) { + + if ($hexcolor[0] == '#') { + $hexcolor = substr($hexcolor, 1); + } + + if (strlen($hexcolor) == 6) { + list($r, $g, $b) = array($hexcolor[0].$hexcolor[1], + $hexcolor[2].$hexcolor[3], + $hexcolor[4].$hexcolor[5]); + } elseif (strlen($hexcolor) == 3) { + list($r, $g, $b) = array($hexcolor[0].$hexcolor[0], + $hexcolor[1].$hexcolor[1], + $hexcolor[2].$hexcolor[2]); + } else { + return false; + } + + $this->red = hexdec($r); + $this->green = hexdec($g); + $this->blue = hexdec($b); + + } + + /** + * Sets the RGB color values from a 24-bit integer + * + * @param int $intcolor + * + * @return nothing + */ + + function setIntColor($intcolor) + { + // We could do 32 bit and have an alpha channel because + // Sarven wants one real bad, but nah. + + $this->red = $intcolor >> 16; + $this->green = $intcolor >> 8 & 0xFF; + $this->blue = $intcolor & 0xFF; + + } + + /** + * Returns a hex tuple of the RGB color useful for output in HTML + * + * @return string + */ + + function hexValue() { + + $hexcolor = (strlen(dechex($this->red)) < 2 ? '0' : '' ) . + dechex($this->red); + $hexcolor .= (strlen(dechex($this->green)) < 2 ? '0' : '') . + dechex($this->green); + $hexcolor .= (strlen(dechex($this->blue)) < 2 ? '0' : '') . + dechex($this->blue); + + return $hexcolor; + + } + + /** + * Returns a 24-bit packed integer representation of the RGB color + * for convenient storage in the DB + * + * XXX: probably could just use hexdec() instead + * + * @return int + */ + + function intValue() + { + $intcolor = 256 * 256 * $this->red + 256 * $this->green + $this->blue; + return $intcolor; + } + +} + +class WebColorException extends Exception +{ +} + +?> \ No newline at end of file -- cgit v1.2.3-54-g00ecf From e7e3709ae0294b8400b85d87f2ebeade5b31858d Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Jun 2009 21:21:33 -0700 Subject: Throw an WebColorException if wrong # of hex chars --- lib/webcolor.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/webcolor.php b/lib/webcolor.php index 65713d26e..aaf31d990 100644 --- a/lib/webcolor.php +++ b/lib/webcolor.php @@ -120,7 +120,8 @@ class WebColor { $hexcolor[1].$hexcolor[1], $hexcolor[2].$hexcolor[2]); } else { - return false; + $errmsg = _('%s is not a valid color! Use 3 or 6 hex chars.'); + throw new WebColorException(sprintf($errmsg, $hexcolor)); } $this->red = hexdec($r); -- cgit v1.2.3-54-g00ecf From ef99f83963ba598b1e52224ce80a7d8a8e84a96f Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Jun 2009 22:13:35 -0700 Subject: Output custom stylesheets on design sub-Actions --- classes/Design.php | 2 +- lib/currentuserdesignaction.php | 16 ++++++++++++++++ lib/ownerdesignaction.php | 13 +++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/classes/Design.php b/classes/Design.php index bb1e917e3..4f6b2a844 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -47,7 +47,7 @@ class Design extends Memcached_DataObject function showCSS($out) { - $out->element('stylesheet', array('type' => 'text/css'), + $out->element('style', array('type' => 'text/css'), 'body { background-color: #' . dechex($this->backgroundcolor) . '} '."\n". '#content { background-color #' . dechex($this->contentcolor) . '} '."\n". '#aside_primary { background-color #'. dechex($this->sidebarcolor) .'} '."\n". diff --git a/lib/currentuserdesignaction.php b/lib/currentuserdesignaction.php index 297525655..40502bc77 100644 --- a/lib/currentuserdesignaction.php +++ b/lib/currentuserdesignaction.php @@ -47,6 +47,20 @@ if (!defined('LACONICA')) { class CurrentUserDesignAction extends Action { + + /** + * Show the user's design stylesheet + * + * @return nothing + */ + function showStylesheets() + { + parent::showStylesheets(); + + $design = $this->getDesign(); + $design->showCSS($this); + } + /** * A design for this action * @@ -66,4 +80,6 @@ class CurrentUserDesignAction extends Action return $cur->getDesign(); } + + } diff --git a/lib/ownerdesignaction.php b/lib/ownerdesignaction.php index c47633bdb..b6b30a606 100644 --- a/lib/ownerdesignaction.php +++ b/lib/ownerdesignaction.php @@ -52,6 +52,19 @@ class OwnerDesignAction extends Action { var $user = null; + /** + * Show the owner's design stylesheet + * + * @return nothing + */ + function showStylesheets() + { + parent::showStylesheets(); + + $design = $this->getDesign(); + $design->showCSS($this); + } + /** * A design for this action * -- cgit v1.2.3-54-g00ecf From c3c30aa0eafd42cf6544cb32614ffe164bfd9ca2 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 15 Jun 2009 23:18:54 -0700 Subject: Check to make sure a design exists before trying to display it --- lib/currentuserdesignaction.php | 5 ++++- lib/ownerdesignaction.php | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/currentuserdesignaction.php b/lib/currentuserdesignaction.php index 40502bc77..7c2520cf6 100644 --- a/lib/currentuserdesignaction.php +++ b/lib/currentuserdesignaction.php @@ -58,7 +58,10 @@ class CurrentUserDesignAction extends Action parent::showStylesheets(); $design = $this->getDesign(); - $design->showCSS($this); + + if (!empty($design)) { + $design->showCSS($this); + } } /** diff --git a/lib/ownerdesignaction.php b/lib/ownerdesignaction.php index b6b30a606..424474f42 100644 --- a/lib/ownerdesignaction.php +++ b/lib/ownerdesignaction.php @@ -62,7 +62,10 @@ class OwnerDesignAction extends Action { parent::showStylesheets(); $design = $this->getDesign(); - $design->showCSS($this); + + if (!empty($design)) { + $design->showCSS($this); + } } /** -- cgit v1.2.3-54-g00ecf From bc1f877f6e84929b7f2722f57858cfad8508fea5 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 16 Jun 2009 19:17:37 -0700 Subject: Design settings now save and displays backgrounds --- actions/designsettings.php | 69 +++++++++++++++++++++++++++++++++++++++++----- classes/Design.php | 63 +++++++++++++++++++++++++++++++++++++----- lib/common.php | 4 +++ 3 files changed, 122 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/actions/designsettings.php b/actions/designsettings.php index c5aa8c1d3..aa6915b98 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -56,7 +56,8 @@ class DesignsettingsAction extends AccountSettingsAction function getInstructions() { - return _('Customize the way your profile looks with a background image and a colour palette of your choice.'); + return _('Customize the way your profile looks ' . + 'with a background image and a colour palette of your choice.'); } /** @@ -71,14 +72,16 @@ class DesignsettingsAction extends AccountSettingsAction { $user = common_current_user(); $this->elementStart('form', array('method' => 'post', + 'enctype' => 'multipart/form-data', 'id' => 'form_settings_design', 'class' => 'form_settings', 'action' => - common_local_url('designsettings'))); + common_local_url('designsettings'))); $this->elementStart('fieldset'); $this->hidden('token', common_session_token()); - $this->elementStart('fieldset', array('id' => 'settings_design_background-image')); + $this->elementStart('fieldset', array('id' => + 'settings_design_background-image')); $this->element('legend', null, _('Change background image')); $this->elementStart('ul', 'form_data'); $this->elementStart('li'); @@ -87,7 +90,8 @@ class DesignsettingsAction extends AccountSettingsAction $this->element('input', array('name' => 'design_background-image_file', 'type' => 'file', 'id' => 'design_background-image_file')); - $this->element('p', 'form_guide', _('You can upload your personal background image. The maximum file size is 2Mb.')); + $this->element('p', 'form_guide', _('You can upload your personal ' . + 'background image. The maximum file size is 2Mb.')); $this->element('input', array('name' => 'MAX_FILE_SIZE', 'type' => 'hidden', 'id' => 'MAX_FILE_SIZE', @@ -207,6 +211,20 @@ class DesignsettingsAction extends AccountSettingsAction function handlePost() { + // XXX: Robin's workaround for a bug in PHP where $_POST + // and $_FILE are empty in the case that the uploaded + // file is bigger than PHP is configured to handle. + + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + if (empty($_POST) && $_SERVER['CONTENT_LENGTH']) { + + $msg = _('The server was unable to handle that much POST ' . + 'data (%s bytes) due to its current configuration.'); + + $this->showForm(sprintf($msg, $_SERVER['CONTENT_LENGTH'])); + } + } + // CSRF protection $token = $this->trimmed('token'); if (!$token || $token != common_session_token()) { @@ -310,8 +328,6 @@ class DesignsettingsAction extends AccountSettingsAction function saveDesign() { - $user = common_current_user(); - try { $bgcolor = new WebColor($this->trimmed('design_background')); @@ -325,6 +341,7 @@ class DesignsettingsAction extends AccountSettingsAction return; } + $user = common_current_user(); $design = $user->getDesign(); if (!empty($design)) { @@ -336,6 +353,7 @@ class DesignsettingsAction extends AccountSettingsAction $design->sidebarcolor = $sbcolor->intValue(); $design->textcolor = $tcolor->intValue(); $design->linkcolor = $lcolor->intValue(); + $design->backgroundimage = $filepath; $result = $design->update($original); @@ -358,7 +376,7 @@ class DesignsettingsAction extends AccountSettingsAction $design->sidebarcolor = $sbcolor->intValue(); $design->textcolor = $tcolor->intValue(); $design->linkcolor = $lcolor->intValue(); - $design->backgroundimage = $defaults['backgroundimage']; + $design->backgroundimage = $filepath; $id = $design->insert(); @@ -383,6 +401,43 @@ class DesignsettingsAction extends AccountSettingsAction } + // Now that we have a Design ID we can add a file to the design. + // XXX: This is an additional DB hit, but figured having the image + // associated with the Design rather than the User was worth + // it. -- Zach + + if ($_FILES['design_background-image_file']['error'] == + UPLOAD_ERR_OK) { + + $filepath = null; + + try { + $imagefile = + ImageFile::fromUpload('design_background-image_file'); + } catch (Exception $e) { + $this->showForm($e->getMessage()); + return; + } + + $filename = Design::filename($design->id, + image_type_to_extension($imagefile->type), + common_timestamp()); + + $filepath = Design::path($filename); + + move_uploaded_file($imagefile->filepath, $filepath); + + $original = clone($design); + $design->backgroundimage = $filename; + $result = $design->update($original); + + if ($result === false) { + common_log_db_error($design, 'UPDATE', __FILE__); + $this->showForm(_('Couldn\'t update your design.')); + return; + } + } + $this->showForm(_('Design preferences saved.'), true); } diff --git a/classes/Design.php b/classes/Design.php index 8bb527761..f5c87b489 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -64,12 +64,61 @@ class Design extends Memcached_DataObject __FILE__); } - $out->element('style', array('type' => 'text/css'), - 'html, body { background-color: #' . $bgcolor->hexValue() . '} '."\n". - '#content, #site_nav_local_views .current a { background-color: #' . - $ccolor->hexValue() . '} '."\n". - '#aside_primary { background-color: #'. $sbcolor->hexValue() .'} '."\n". - 'html body { color: #'. $tcolor->hexValue() .'} '."\n". - 'a { color: #' . $lcolor->hexValue() . '} '."\n"); + $css = 'html, body { background-color: #' . $bgcolor->hexValue() . '} ' . "\n"; + $css .= '#content, #site_nav_local_views .current a { background-color: #'; + $css .= $ccolor->hexValue() . '} '."\n"; + $css .= '#aside_primary { background-color: #'. $sbcolor->hexValue() . '} ' . "\n"; + $css .= 'html body { color: #'. $tcolor->hexValue() . '} '. "\n"; + $css .= 'a { color: #' . $lcolor->hexValue() . '} ' . "\n"; + + if (!empty($this->backgroundimage)) { + + $css .= 'body { background-image:url(' . + Design::url($this->backgroundimage) . + '); background-repeat:no-repeat; }' . "\n"; + } + + $out->element('style', array('type' => 'text/css'), $css); + + } + + static function filename($id, $extension, $extra=null) + { + return $id . (($extra) ? ('-' . $extra) : '') . $extension; + } + + static function path($filename) + { + $dir = common_config('background', 'dir'); + + if ($dir[strlen($dir)-1] != '/') { + $dir .= '/'; + } + + return $dir . $filename; } + + static function url($filename) + { + $path = common_config('background', 'path'); + + if ($path[strlen($path)-1] != '/') { + $path .= '/'; + } + + if ($path[0] != '/') { + $path = '/'.$path; + } + + $server = common_config('background', 'server'); + + if (empty($server)) { + $server = common_config('site', 'server'); + } + + // XXX: protocol + + return 'http://'.$server.$path.$filename; + } + } diff --git a/lib/common.php b/lib/common.php index 1381d8047..0e710625c 100644 --- a/lib/common.php +++ b/lib/common.php @@ -119,6 +119,10 @@ $config = array('server' => null, 'dir' => INSTALLDIR . '/avatar/', 'path' => $_path . '/avatar/'), + 'background' => + array('server' => null, + 'dir' => INSTALLDIR . '/background/', + 'path' => $_path . '/background/'), 'public' => array('localonly' => true, 'blacklist' => array(), -- cgit v1.2.3-54-g00ecf From d1ae3176b638a8342f0d3cfb4ac071623c639575 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 16 Jun 2009 22:18:25 -0700 Subject: Enable tiling of background imgs for Designs --- actions/designsettings.php | 20 +++++++++++++------- classes/Design.php | 25 ++++++++++++++----------- lib/common.php | 3 ++- 3 files changed, 29 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/actions/designsettings.php b/actions/designsettings.php index e97d01ceb..866d8aaeb 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -71,6 +71,12 @@ class DesignsettingsAction extends AccountSettingsAction function showContent() { $user = common_current_user(); + $design = $user->getDesign(); + + if (empty($design)) { + $design = $this->defaultDesign(); + } + $this->elementStart('form', array('method' => 'post', 'enctype' => 'multipart/form-data', 'id' => 'form_settings_design', @@ -122,7 +128,7 @@ class DesignsettingsAction extends AccountSettingsAction $this->elementStart('li'); $this->checkbox('design_background-image_repeat', _('Tile background image'), - false, null, true, false); + $design->tile); $this->elementEnd('li'); $this->elementEnd('ul'); @@ -132,12 +138,6 @@ class DesignsettingsAction extends AccountSettingsAction $this->element('legend', null, _('Change colours')); $this->elementStart('ul', 'form_data'); - $design = $user->getDesign(); - - if (empty($design)) { - $design = $this->defaultDesign(); - } - try { $bgcolor = new WebColor($design->backgroundcolor); @@ -340,6 +340,8 @@ class DesignsettingsAction extends AccountSettingsAction $design->backgroundimage = $defaults['backgroundimage']; + $deisng->tile = $defaults['tile']; + } catch (WebColorException $e) { common_log(LOG_ERR, _('Bad default color settings: ' . $e->getMessage())); @@ -369,6 +371,8 @@ class DesignsettingsAction extends AccountSettingsAction return; } + $tile = $this->boolean('design_background-image_repeat'); + $user = common_current_user(); $design = $user->getDesign(); @@ -382,6 +386,7 @@ class DesignsettingsAction extends AccountSettingsAction $design->textcolor = $tcolor->intValue(); $design->linkcolor = $lcolor->intValue(); $design->backgroundimage = $filepath; + $design->tile = $tile; $result = $design->update($original); @@ -405,6 +410,7 @@ class DesignsettingsAction extends AccountSettingsAction $design->textcolor = $tcolor->intValue(); $design->linkcolor = $lcolor->intValue(); $design->backgroundimage = $filepath; + $design->tile = $tile; $id = $design->insert(); diff --git a/classes/Design.php b/classes/Design.php index acc94d196..4ea176677 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -41,7 +41,7 @@ class Design extends Memcached_DataObject public $textcolor; // int(4) public $linkcolor; // int(4) public $backgroundimage; // varchar(255) - public $tile; // tinyint(1) + public $tile; // tinyint(1) /* Static get */ function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Design',$k,$v); } @@ -64,23 +64,26 @@ class Design extends Memcached_DataObject common_log(LOG_ERR, "Unable to create color for design $id.", __FILE__); } - + $css = 'html, body { background-color: #' . $bgcolor->hexValue() . '} ' . "\n"; $css .= '#content, #site_nav_local_views .current a { background-color: #'; $css .= $ccolor->hexValue() . '} '."\n"; $css .= '#aside_primary { background-color: #'. $sbcolor->hexValue() . '} ' . "\n"; $css .= 'html body { color: #'. $tcolor->hexValue() . '} '. "\n"; $css .= 'a { color: #' . $lcolor->hexValue() . '} ' . "\n"; - + if (!empty($this->backgroundimage)) { - - $css .= 'body { background-image:url(' . - Design::url($this->backgroundimage) . - '); background-repeat:no-repeat; }' . "\n"; + + $repeat = ($this->tile) ? 'background-repeat:repeat;' : + 'background-repeat:no-repeat;'; + + $css .= 'body { background-image:url(' . + Design::url($this->backgroundimage) . + '); ' . $repeat . ' }' . "\n"; } - + $out->element('style', array('type' => 'text/css'), $css); - + } static function filename($id, $extension, $extra=null) @@ -98,7 +101,7 @@ class Design extends Memcached_DataObject return $dir . $filename; } - + static function url($filename) { $path = common_config('background', 'path'); @@ -121,5 +124,5 @@ class Design extends Memcached_DataObject return 'http://'.$server.$path.$filename; } - + } diff --git a/lib/common.php b/lib/common.php index 0e710625c..629fee25b 100644 --- a/lib/common.php +++ b/lib/common.php @@ -78,7 +78,8 @@ $config = 'sidebarcolor' => '#CEE1E9', 'textcolor' => '#000000', 'linkcolor' => '#002E6E', - 'backgroundimage' => null), + 'backgroundimage' => null, + 'tile' => true), 'path' => $_path, 'logfile' => null, 'logo' => null, -- cgit v1.2.3-54-g00ecf From 76cbeff33c9659cacbb57943056aabcb1517ca5c Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Jun 2009 02:35:51 -0700 Subject: Update background image settings to use bitflags --- actions/designsettings.php | 100 +++++++++++++++++++++++++++------------------ classes/Design.php | 33 +++++++++++++-- classes/laconica.ini | 2 +- db/laconica.sql | 2 +- lib/common.php | 2 +- 5 files changed, 93 insertions(+), 46 deletions(-) (limited to 'lib') diff --git a/actions/designsettings.php b/actions/designsettings.php index fbec3fc67..3dfaddd7b 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -104,37 +104,52 @@ class DesignsettingsAction extends AccountSettingsAction 'value' => ImageFile::maxFileSizeInt())); $this->elementEnd('li'); - $this->elementStart('li', array('id' => 'design_background-image_onoff')); - if (!empty($design->backgroundimage)) { + + $this->elementStart('li', array('id' => 'design_background-image_onoff')); + $this->element('img', array('src' => Design::url($design->backgroundimage))); - } - $this->element('input', array('name' => 'design_background-image_onoff', - 'type' => 'radio', - 'id' => 'design_background-image_on', - 'class' => 'radio', - 'value' => 'true', - 'checked'=> 'checked')); - $this->element('label', array('for' => 'design_background-image_on', - 'class' => 'radio'), - _('On')); - $this->element('input', array('name' => 'design_background-image_onoff', - 'type' => 'radio', - 'id' => 'design_background-image_off', - 'class' => 'radio', - 'value' => 'false')); - $this->element('label', array('for' => 'design_background-image_off', - 'class' => 'radio'), - _('Off')); - $this->element('p', 'form_guide', _('Turn background image on or off.')); - $this->elementEnd('li'); + $attrs = array('name' => 'design_background-image_onoff', + 'type' => 'radio', + 'id' => 'design_background-image_on', + 'class' => 'radio', + 'value' => 'on'); + + if ($design->disposition & BACKGROUND_ON) { + $attrs['checked'] = 'checked'; + } + + $this->element('input', $attrs); + + $this->element('label', array('for' => 'design_background-image_on', + 'class' => 'radio'), + _('On')); + + $attrs = array('name' => 'design_background-image_onoff', + 'type' => 'radio', + 'id' => 'design_background-image_off', + 'class' => 'radio', + 'value' => 'off'); + + if ($design->disposition & BACKGROUND_OFF) { + $attrs['checked'] = 'checked'; + } + + $this->element('input', $attrs); + + $this->element('label', array('for' => 'design_background-image_off', + 'class' => 'radio'), + _('Off')); + $this->element('p', 'form_guide', _('Turn background image on or off.')); + $this->elementEnd('li'); + } $this->elementStart('li'); $this->checkbox('design_background-image_repeat', _('Tile background image'), - $design->tile); + ($design->disposition & BACKGROUND_TILE) ? true : false ); $this->elementEnd('li'); $this->elementEnd('ul'); @@ -159,7 +174,6 @@ class DesignsettingsAction extends AccountSettingsAction 'value' => '#' . $bgcolor->hexValue())); $this->elementEnd('li'); - $ccolor = new WebColor($design->contentcolor); $this->elementStart('li'); @@ -346,7 +360,7 @@ class DesignsettingsAction extends AccountSettingsAction $design->backgroundimage = $defaults['backgroundimage']; - $deisng->tile = $defaults['tile']; + $deisng->disposition = $defaults['disposition']; } catch (WebColorException $e) { common_log(LOG_ERR, _('Bad default color settings: ' . @@ -377,7 +391,23 @@ class DesignsettingsAction extends AccountSettingsAction return; } - $tile = $this->boolean('design_background-image_repeat'); + $onoff = $this->arg('design_background-image_onoff'); + + $on = false; + $off = false; + $tile = false; + + if ($onoff == 'on') { + $on = true; + } else { + $off = true; + } + + $repeat = $this->boolean('design_background-image_repeat'); + + if ($repeat) { + $tile = true; + } $user = common_current_user(); $design = $user->getDesign(); @@ -392,7 +422,8 @@ class DesignsettingsAction extends AccountSettingsAction $design->textcolor = $tcolor->intValue(); $design->linkcolor = $lcolor->intValue(); $design->backgroundimage = $filepath; - $design->tile = $tile; + + $design->setDisposition($on, $off, $tile); $result = $design->update($original); @@ -416,7 +447,8 @@ class DesignsettingsAction extends AccountSettingsAction $design->textcolor = $tcolor->intValue(); $design->linkcolor = $lcolor->intValue(); $design->backgroundimage = $filepath; - $design->tile = $tile; + + $design->setDisposition($on, $off, $tile); $id = $design->insert(); @@ -481,16 +513,4 @@ class DesignsettingsAction extends AccountSettingsAction $this->showForm(_('Design preferences saved.'), true); } - /** - * Reset design settings to previous saved value if any, or - * the defaults - * - * @return void - */ - - function resetDesign() - { - $this->showForm(_('Design preferences reset.'), true); - } - } diff --git a/classes/Design.php b/classes/Design.php index 4ea176677..5b28bf014 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -21,6 +21,10 @@ if (!defined('LACONICA')) { exit(1); } +define('BACKGROUND_ON', 1); +define('BACKGROUND_OFF', 2); +define('BACKGROUND_TILE', 4); + /** * Table Definition for design */ @@ -41,7 +45,7 @@ class Design extends Memcached_DataObject public $textcolor; // int(4) public $linkcolor; // int(4) public $backgroundimage; // varchar(255) - public $tile; // tinyint(1) + public $disposition; // tinyint(1) default_1 /* Static get */ function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Design',$k,$v); } @@ -72,9 +76,11 @@ class Design extends Memcached_DataObject $css .= 'html body { color: #'. $tcolor->hexValue() . '} '. "\n"; $css .= 'a { color: #' . $lcolor->hexValue() . '} ' . "\n"; - if (!empty($this->backgroundimage)) { + if (!empty($this->backgroundimage) && + $this->disposition & BACKGROUND_ON) { - $repeat = ($this->tile) ? 'background-repeat:repeat;' : + $repeat = ($this->disposition & BACKGROUND_TILE) ? + 'background-repeat:repeat;' : 'background-repeat:no-repeat;'; $css .= 'body { background-image:url(' . @@ -125,4 +131,25 @@ class Design extends Memcached_DataObject return 'http://'.$server.$path.$filename; } + function setDisposition($on, $off, $tile) + { + if ($on) { + $this->disposition |= BACKGROUND_ON; + } else { + $this->disposition &= ~BACKGROUND_ON; + } + + if ($off) { + $this->disposition |= BACKGROUND_OFF; + } else { + $this->disposition &= ~BACKGROUND_OFF; + } + + if ($tile) { + $this->disposition |= BACKGROUND_TILE; + } else { + $this->disposition &= ~BACKGROUND_TILE; + } + } + } diff --git a/classes/laconica.ini b/classes/laconica.ini index 569681984..1a650aba5 100755 --- a/classes/laconica.ini +++ b/classes/laconica.ini @@ -46,7 +46,7 @@ sidebarcolor = 1 textcolor = 1 linkcolor = 1 backgroundimage = 2 -tile = 17 +disposition = 17 [design__keys] id = N diff --git a/db/laconica.sql b/db/laconica.sql index 1f302de16..b018afec8 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -496,7 +496,7 @@ create table design ( textcolor integer comment 'text color', linkcolor integer comment 'link color', backgroundimage varchar(255) comment 'background image, if any', - tile tinyint default 0 comment 'tile background image' + disposition tinyint default 1 comment 'bit 1 = hide background image, bit 2 = display background image, bit 4 = tile background image' ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table group_block ( diff --git a/lib/common.php b/lib/common.php index 629fee25b..bcf2e5d0c 100644 --- a/lib/common.php +++ b/lib/common.php @@ -79,7 +79,7 @@ $config = 'textcolor' => '#000000', 'linkcolor' => '#002E6E', 'backgroundimage' => null, - 'tile' => true), + 'disposition' => 1), 'path' => $_path, 'logfile' => null, 'logo' => null, -- cgit v1.2.3-54-g00ecf From af4b18b1e2ef8aded26fc4788c571012da04d1cf Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Jun 2009 03:05:48 -0700 Subject: Uppercase hex color values --- lib/webcolor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/webcolor.php b/lib/webcolor.php index aaf31d990..f3ca6e94a 100644 --- a/lib/webcolor.php +++ b/lib/webcolor.php @@ -164,7 +164,7 @@ class WebColor { $hexcolor .= (strlen(dechex($this->blue)) < 2 ? '0' : '') . dechex($this->blue); - return $hexcolor; + return strtoupper($hexcolor); } -- cgit v1.2.3-54-g00ecf From 28d02ec8cdd0278c802c8fee30acddecca9ca01f Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Wed, 17 Jun 2009 16:44:33 -0400 Subject: Make oohembed endpoint configurable. --- README | 8 ++++++++ classes/File_oembed.php | 2 +- config.php.sample | 1 + lib/common.php | 1 + 4 files changed, 11 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/README b/README index 3279f7bba..7b22e3c5e 100644 --- a/README +++ b/README @@ -1246,6 +1246,14 @@ Options for group functionality. maxaliases: maximum number of aliases a group can have. Default 3. Set to 0 or less to prevent aliases in a group. + +oohembed +-------- + +oEmbed endpoint for multimedia attachments (links in posts). + +endpoint: oohembed endpoint using http://oohembed.com/ software. + Troubleshooting =============== diff --git a/classes/File_oembed.php b/classes/File_oembed.php index f1b2cb13c..6bf972f8f 100644 --- a/classes/File_oembed.php +++ b/classes/File_oembed.php @@ -53,7 +53,7 @@ class File_oembed extends Memcached_DataObject function _getOembed($url, $maxwidth = 500, $maxheight = 400, $format = 'json') { - $cmd = 'http://oohembed.com/oohembed/?url=' . urlencode($url); + $cmd = common_config('oohembed', 'endpoint') . '?url=' . urlencode($url); if (is_int($maxwidth)) $cmd .= "&maxwidth=$maxwidth"; if (is_int($maxheight)) $cmd .= "&maxheight=$maxheight"; if (is_string($format)) $cmd .= "&format=$format"; diff --git a/config.php.sample b/config.php.sample index 636f4cf8e..ed70f85fb 100644 --- a/config.php.sample +++ b/config.php.sample @@ -223,3 +223,4 @@ $config['sphinx']['port'] = 3312; // $config['attachments']['user_quota'] = 50000000; // $config['attachments']['monthly_quota'] = 15000000; +// $config['oohembed']['endpoint'] = 'http://oohembed.com/oohembed/'; diff --git a/lib/common.php b/lib/common.php index 51204cede..9c015a15d 100644 --- a/lib/common.php +++ b/lib/common.php @@ -203,6 +203,7 @@ $config = ), 'group' => array('maxaliases' => 3), + 'oohembed' => array('endpoint' => 'http://oohembed.com/oohembed/') ); $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); -- cgit v1.2.3-54-g00ecf From b58dc5e96117bdb4de899d37c6eb94ebf1c3dfe6 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Wed, 17 Jun 2009 16:55:01 -0400 Subject: Added config option to enable or disable file uploads with notices. --- README | 1 + config.php.sample | 1 + lib/common.php | 1 + lib/noticeform.php | 18 +++++++++++------- 4 files changed, 14 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/README b/README index 7b22e3c5e..5aa7270ee 100644 --- a/README +++ b/README @@ -1223,6 +1223,7 @@ supported: an array of mime types you accept to store and distribute, like 'image/gif', 'video/mpeg', 'audio/mpeg', etc. Make sure you setup your server to properly reckognize the types you want to support. +uploads: false to disable uploading files with notices (true by default). For quotas, be sure you've set the upload_max_filesize and post_max_size in php.ini to be large enough to handle your upload. In httpd.conf diff --git a/config.php.sample b/config.php.sample index ed70f85fb..7649c5262 100644 --- a/config.php.sample +++ b/config.php.sample @@ -222,5 +222,6 @@ $config['sphinx']['port'] = 3312; // $config['attachments']['file_quota'] = 5000000; // $config['attachments']['user_quota'] = 50000000; // $config['attachments']['monthly_quota'] = 15000000; +// $config['attachments']['uploads'] = true; // $config['oohembed']['endpoint'] = 'http://oohembed.com/oohembed/'; diff --git a/lib/common.php b/lib/common.php index 9c015a15d..bbd9f78c3 100644 --- a/lib/common.php +++ b/lib/common.php @@ -200,6 +200,7 @@ $config = 'file_quota' => 5000000, 'user_quota' => 50000000, 'monthly_quota' => 15000000, + 'uploads' => true, ), 'group' => array('maxaliases' => 3), diff --git a/lib/noticeform.php b/lib/noticeform.php index 0ad365856..a36b7f31f 100644 --- a/lib/noticeform.php +++ b/lib/noticeform.php @@ -90,7 +90,9 @@ class NoticeForm extends Form $this->user = common_current_user(); } - $this->enctype = 'multipart/form-data'; + if (common_config('attachments', 'uploads')) { + $this->enctype = 'multipart/form-data'; + } } /** @@ -148,12 +150,14 @@ class NoticeForm extends Form $this->out->element('dd', array('id' => 'notice_text-count'), '140'); $this->out->elementEnd('dl'); - $this->out->element('label', array('for' => 'notice_data-attach'),_('Attach')); - $this->out->element('input', array('id' => 'notice_data-attach', - 'type' => 'file', - 'name' => 'attach', - 'title' => _('Attach a file'))); - $this->out->hidden('MAX_FILE_SIZE', common_config('attachments', 'file_quota')); + if (common_config('attachments', 'uploads')) { + $this->out->hidden('MAX_FILE_SIZE', common_config('attachments', 'file_quota')); + $this->out->element('label', array('for' => 'notice_data-attach'),_('Attach')); + $this->out->element('input', array('id' => 'notice_data-attach', + 'type' => 'file', + 'name' => 'attach', + 'title' => _('Attach a file'))); + } if ($this->action) { $this->out->hidden('notice_return-to', $this->action, 'returnto'); } -- cgit v1.2.3-54-g00ecf From 7e25a7f3aa2a308ddfc141e2e88fd52c042cb931 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Jun 2009 14:32:36 -0700 Subject: Output XML and JSON error msgs for API calls --- lib/twitterapi.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/twitterapi.php b/lib/twitterapi.php index 569bc6d7a..269b60efc 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -545,7 +545,7 @@ class TwitterapiAction extends Action $this->init_twitter_atom(); break; default: - $this->client_error(_('Not a supported data format.')); + $this->clientError(_('Not a supported data format.')); break; } @@ -573,13 +573,13 @@ class TwitterapiAction extends Action $this->end_twitter_rss(); break; default: - $this->client_error(_('Not a supported data format.')); + $this->clientError(_('Not a supported data format.')); break; } return; } - function client_error($msg, $code = 400, $content_type = 'json') + function clientError($msg, $code = 400, $content_type = 'json') { static $status = array(400 => 'Bad Request', @@ -666,7 +666,7 @@ class TwitterapiAction extends Action $this->show_json_objects($profile_array); break; default: - $this->client_error(_('Not a supported data format.')); + $this->clientError(_('Not a supported data format.')); return; } return; -- cgit v1.2.3-54-g00ecf From 8992e8fa7a3c694cc9d424b3e50cf4d87519fa28 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Jun 2009 14:34:04 -0700 Subject: Ticket 1612 - make destory (and create) favorites work via API --- actions/twitapifavorites.php | 65 +++++++++++++++++++++++++++++++++++++++----- lib/router.php | 3 +- 2 files changed, 60 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/actions/twitapifavorites.php b/actions/twitapifavorites.php index 8656adbe8..2266ba11c 100644 --- a/actions/twitapifavorites.php +++ b/actions/twitapifavorites.php @@ -34,6 +34,11 @@ class TwitapifavoritesAction extends TwitterapiAction $user = $this->get_user($apidata['api_arg'], $apidata); if (empty($user)) { + if ($apidata['content-type'] == 'xml') { + $this->show_single_xml_status($notice); + } elseif ($apidata['content-type'] == 'json') { + $this->show_single_json_status($notice); + } $this->clientError('Not Found', 404, $apidata['content-type']); return; } @@ -91,7 +96,6 @@ class TwitapifavoritesAction extends TwitterapiAction // Check for RESTfulness if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) { - // XXX: Twitter just prints the err msg, no XML / JSON. $this->clientError(_('This method requires a POST or DELETE.'), 400, $apidata['content-type']); return; @@ -102,10 +106,9 @@ class TwitapifavoritesAction extends TwitterapiAction return; } - $user = $apidata['user']; // Always the auth user - + $user = $apidata['user']; // Always the auth user $notice_id = $apidata['api_arg']; - $notice = Notice::staticGet($notice_id); + $notice = Notice::staticGet($notice_id); if (empty($notice)) { $this->clientError(_('No status found with that ID.'), @@ -115,7 +118,7 @@ class TwitapifavoritesAction extends TwitterapiAction // XXX: Twitter lets you fave things repeatedly via api. if ($user->hasFave($notice)) { - $this->clientError(_('This notice is already a favorite!'), + $this->clientError(_('This status is already a favorite!'), 403, $apidata['content-type']); return; } @@ -123,7 +126,7 @@ class TwitapifavoritesAction extends TwitterapiAction $fave = Fave::addNew($user, $notice); if (empty($fave)) { - $this->serverError(_('Could not create favorite.')); + $this->clientError(_('Could not create favorite.')); return; } @@ -141,7 +144,55 @@ class TwitapifavoritesAction extends TwitterapiAction function destroy($args, $apidata) { parent::handle($args); - $this->serverError(_('API method under construction.'), $code=501); + + // Check for RESTfulness + if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) { + $this->clientError(_('This method requires a POST or DELETE.'), + 400, $apidata['content-type']); + return; + } + + if (!in_array($apidata['content-type'], array('xml', 'json'))) { + $this->clientError(_('API method not found!'), $code = 404); + return; + } + + $user = $apidata['user']; // Always the auth user + $notice_id = $apidata['api_arg']; + $notice = Notice::staticGet($notice_id); + + if (empty($notice)) { + $this->clientError(_('No status found with that ID.'), + 404, $apidata['content-type']); + return; + } + + $fave = new Fave(); + $fave->user_id = $this->id; + $fave->notice_id = $notice->id; + + if (!$fave->find(true)) { + $this->clientError(_('That status is not a favorite!'), + 403, $apidata['content-type']); + return; + } + + $result = $fave->delete(); + + if (!$result) { + common_log_db_error($fave, 'DELETE', __FILE__); + $this->clientError(_('Could not delete favorite.'), 404); + return; + } + + $user->blowFavesCache(); + + if ($apidata['content-type'] == 'xml') { + $this->show_single_xml_status($notice); + } elseif ($apidata['content-type'] == 'json') { + $this->show_single_json_status($notice); + } + } // XXX: these two funcs swiped from faves. diff --git a/lib/router.php b/lib/router.php index 0fbaba9ed..8b6f63618 100644 --- a/lib/router.php +++ b/lib/router.php @@ -351,7 +351,8 @@ class Router $m->connect('api/favorites/:method/:argument', array('action' => 'api', - 'apiaction' => 'favorites')); + 'apiaction' => 'favorites', + array('method' => '(create|destroy)'))); $m->connect('api/favorites/:argument', array('action' => 'api', -- cgit v1.2.3-54-g00ecf From 2187ec7056a23e76c756f354bf41e3835ba8d103 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 17 Jun 2009 15:20:44 -0700 Subject: hide group name and aliases in group tag cloud section --- lib/grouptagcloudsection.php | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/grouptagcloudsection.php b/lib/grouptagcloudsection.php index 5d68af28b..9b7a10f6b 100644 --- a/lib/grouptagcloudsection.php +++ b/lib/grouptagcloudsection.php @@ -32,7 +32,7 @@ if (!defined('LACONICA')) { } /** - * Personal tag cloud section + * Group tag cloud section * * @category Widget * @package Laconica @@ -64,12 +64,27 @@ class GroupTagCloudSection extends TagCloudSection $weightexpr='sum(exp(-(now() - notice_tag.created) / %s))'; } + $names = $this->group->getAliases(); + + $names = array_merge(array($this->group->nickname), $names); + + // XXX This is dumb. + + $quoted = array(); + + foreach ($names as $name) { + $quoted[] = "\"$name\""; + } + + $namestring = implode(',', $quoted); + $qry = 'SELECT notice_tag.tag, '. $weightexpr . ' as weight ' . 'FROM notice_tag JOIN notice ' . 'ON notice_tag.notice_id = notice.id ' . 'JOIN group_inbox on group_inbox.notice_id = notice.id ' . 'WHERE group_inbox.group_id = %d ' . + 'AND notice_tag.tag not in (%s) '. 'GROUP BY notice_tag.tag ' . 'ORDER BY weight DESC '; @@ -85,9 +100,9 @@ class GroupTagCloudSection extends TagCloudSection $tag = Memcached_DataObject::cachedQuery('Notice_tag', sprintf($qry, common_config('tag', 'dropoff'), - $this->group->id), + $this->group->id, + $namestring), 3600); return $tag; } - } -- cgit v1.2.3-54-g00ecf From 4fc4c0a74bd08f568a55d65660ca2e5170165905 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Jun 2009 17:13:59 -0700 Subject: Remove stale reference to deprecated personal.php --- lib/mailbox.php | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib') diff --git a/lib/mailbox.php b/lib/mailbox.php index 766510a47..b282ce368 100644 --- a/lib/mailbox.php +++ b/lib/mailbox.php @@ -31,8 +31,6 @@ if (!defined('LACONICA')) { exit(1); } -require_once INSTALLDIR.'/lib/personal.php'; - define('MESSAGES_PER_PAGE', 20); /** -- cgit v1.2.3-54-g00ecf From b0591cd98219cf523d35884015ee9f82c2aa9e09 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 17 Jun 2009 17:29:57 -0700 Subject: Make MailboxAction read only --- lib/mailbox.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'lib') diff --git a/lib/mailbox.php b/lib/mailbox.php index b282ce368..f1f6e98c1 100644 --- a/lib/mailbox.php +++ b/lib/mailbox.php @@ -295,4 +295,17 @@ class MailboxAction extends CurrentUserDesignAction return; } + /** + * Mailbox actions are read only + * + * @param array $args other arguments + * + * @return boolean + */ + + function isReadOnly($args) + { + return true; + } + } -- cgit v1.2.3-54-g00ecf From 57274d21ba554e43c6fcd90555388a60d3de014d Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 18 Jun 2009 02:01:06 -0700 Subject: Group theming. --- actions/blockedfromgroup.php | 2 +- actions/designsettings.php | 517 ------------------------------------------ actions/editgroup.php | 6 +- actions/groupblock.php | 17 +- actions/grouplogo.php | 2 +- actions/groupmembers.php | 2 +- actions/showgroup.php | 5 +- lib/accountsettingsaction.php | 2 +- lib/designsettings.php | 402 ++++++++++++++++++++++++++++++++ lib/groupnav.php | 6 + lib/router.php | 4 +- 11 files changed, 427 insertions(+), 538 deletions(-) delete mode 100644 actions/designsettings.php create mode 100644 lib/designsettings.php (limited to 'lib') diff --git a/actions/blockedfromgroup.php b/actions/blockedfromgroup.php index 541ebcfd9..5c1eab354 100644 --- a/actions/blockedfromgroup.php +++ b/actions/blockedfromgroup.php @@ -41,7 +41,7 @@ if (!defined('LACONICA')) { * @link http://laconi.ca/ */ -class BlockedfromgroupAction extends Action +class BlockedfromgroupAction extends GroupDesignAction { var $page = null; diff --git a/actions/designsettings.php b/actions/designsettings.php deleted file mode 100644 index 047059e04..000000000 --- a/actions/designsettings.php +++ /dev/null @@ -1,517 +0,0 @@ -. - * - * @category Settings - * @package Laconica - * @author Sarven Capadisli - * @author Zach Copley - * @copyright 2008-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); -} - -require_once INSTALLDIR . '/lib/accountsettingsaction.php'; -require_once INSTALLDIR . '/lib/webcolor.php'; - -class DesignsettingsAction extends AccountSettingsAction -{ - /** - * Title of the page - * - * @return string Title of the page - */ - - function title() - { - return _('Profile design'); - } - - /** - * Instructions for use - * - * @return instructions for use - */ - - function getInstructions() - { - return _('Customize the way your profile looks ' . - 'with a background image and a colour palette of your choice.'); - } - - /** - * Content area of the page - * - * Shows a form for changing the password - * - * @return void - */ - - function showContent() - { - $user = common_current_user(); - $design = $user->getDesign(); - - if (empty($design)) { - $design = $this->defaultDesign(); - } - - $this->elementStart('form', array('method' => 'post', - 'enctype' => 'multipart/form-data', - 'id' => 'form_settings_design', - 'class' => 'form_settings', - 'action' => - common_local_url('designsettings'))); - $this->elementStart('fieldset'); - $this->hidden('token', common_session_token()); - - $this->elementStart('fieldset', array('id' => - 'settings_design_background-image')); - $this->element('legend', null, _('Change background image')); - $this->elementStart('ul', 'form_data'); - $this->elementStart('li'); - $this->element('label', array('for' => 'design_background-image_file'), - _('Upload file')); - $this->element('input', array('name' => 'design_background-image_file', - 'type' => 'file', - 'id' => 'design_background-image_file')); - $this->element('p', 'form_guide', _('You can upload your personal ' . - 'background image. The maximum file size is 2Mb.')); - $this->element('input', array('name' => 'MAX_FILE_SIZE', - 'type' => 'hidden', - 'id' => 'MAX_FILE_SIZE', - 'value' => ImageFile::maxFileSizeInt())); - $this->elementEnd('li'); - - if (!empty($design->backgroundimage)) { - - $this->elementStart('li', array('id' => 'design_background-image_onoff')); - - $this->element('img', array('src' => - Design::url($design->backgroundimage))); - - $attrs = array('name' => 'design_background-image_onoff', - 'type' => 'radio', - 'id' => 'design_background-image_on', - 'class' => 'radio', - 'value' => 'on'); - - if ($design->disposition & BACKGROUND_ON) { - $attrs['checked'] = 'checked'; - } - - $this->element('input', $attrs); - - $this->element('label', array('for' => 'design_background-image_on', - 'class' => 'radio'), - _('On')); - - $attrs = array('name' => 'design_background-image_onoff', - 'type' => 'radio', - 'id' => 'design_background-image_off', - 'class' => 'radio', - 'value' => 'off'); - - if ($design->disposition & BACKGROUND_OFF) { - $attrs['checked'] = 'checked'; - } - - $this->element('input', $attrs); - - $this->element('label', array('for' => 'design_background-image_off', - 'class' => 'radio'), - _('Off')); - $this->element('p', 'form_guide', _('Turn background image on or off.')); - $this->elementEnd('li'); - } - - $this->elementStart('li'); - $this->checkbox('design_background-image_repeat', - _('Tile background image'), - ($design->disposition & BACKGROUND_TILE) ? true : false ); - $this->elementEnd('li'); - - $this->elementEnd('ul'); - $this->elementEnd('fieldset'); - - $this->elementStart('fieldset', array('id' => 'settings_design_color')); - $this->element('legend', null, _('Change colours')); - $this->elementStart('ul', 'form_data'); - - try { - - $bgcolor = new WebColor($design->backgroundcolor); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-1'), _('Background')); - $this->element('input', array('name' => 'design_background', - 'type' => 'text', - 'id' => 'swatch-1', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => '#' . $bgcolor->hexValue())); - $this->elementEnd('li'); - - $ccolor = new WebColor($design->contentcolor); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-2'), _('Content')); - $this->element('input', array('name' => 'design_content', - 'type' => 'text', - 'id' => 'swatch-2', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => '#' . $ccolor->hexValue())); - $this->elementEnd('li'); - - $sbcolor = new WebColor($design->sidebarcolor); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-3'), _('Sidebar')); - $this->element('input', array('name' => 'design_sidebar', - 'type' => 'text', - 'id' => 'swatch-3', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => '#' . $sbcolor->hexValue())); - $this->elementEnd('li'); - - $tcolor = new WebColor($design->textcolor); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-4'), _('Text')); - $this->element('input', array('name' => 'design_text', - 'type' => 'text', - 'id' => 'swatch-4', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => '#' . $tcolor->hexValue())); - $this->elementEnd('li'); - - $lcolor = new WebColor($design->linkcolor); - - $this->elementStart('li'); - $this->element('label', array('for' => 'swatch-5'), _('Links')); - $this->element('input', array('name' => 'design_links', - 'type' => 'text', - 'id' => 'swatch-5', - 'class' => 'swatch', - 'maxlength' => '7', - 'size' => '7', - 'value' => '#' . $lcolor->hexValue())); - - $this->elementEnd('li'); - - } catch (WebColorException $e) { - common_log(LOG_ERR, 'Bad color values in design ID: ' . - $design->id); - } - - $this->elementEnd('ul'); - $this->elementEnd('fieldset'); - - $this->element('input', array('id' => 'settings_design_reset', - 'type' => 'reset', - 'value' => 'Reset', - 'class' => 'submit form_action-primary', - 'title' => _('Reset back to default'))); - - $this->submit('save', _('Save'), 'submit form_action-secondary', - 'save', _('Save design')); - - $this->elementEnd('fieldset'); - $this->elementEnd('form'); - } - - /** - * Handle a post - * - * Validate input and save changes. Reload the form with a success - * or error message. - * - * @return void - */ - - function handlePost() - { - // XXX: Robin's workaround for a bug in PHP where $_POST - // and $_FILE are empty in the case that the uploaded - // file is bigger than PHP is configured to handle. - - if ($_SERVER['REQUEST_METHOD'] == 'POST') { - if (empty($_POST) && $_SERVER['CONTENT_LENGTH']) { - - $msg = _('The server was unable to handle that much POST ' . - 'data (%s bytes) due to its current configuration.'); - - $this->showForm(sprintf($msg, $_SERVER['CONTENT_LENGTH'])); - } - } - - // CSRF protection - $token = $this->trimmed('token'); - if (!$token || $token != common_session_token()) { - $this->showForm(_('There was a problem with your session token. '. - 'Try again, please.')); - return; - } - - if ($this->arg('save')) { - $this->saveDesign(); - } else if ($this->arg('reset')) { - $this->resetDesign(); - } else { - $this->showForm(_('Unexpected form submission.')); - } - } - - /** - * Add the Farbtastic stylesheet - * - * @return void - */ - - function showStylesheets() - { - parent::showStylesheets(); - $farbtasticStyle = - common_path('theme/base/css/farbtastic.css?version='.LACONICA_VERSION); - - $this->element('link', array('rel' => 'stylesheet', - 'type' => 'text/css', - 'href' => $farbtasticStyle, - 'media' => 'screen, projection, tv')); - } - - /** - * Add the Farbtastic scripts - * - * @return void - */ - - function showScripts() - { - parent::showScripts(); - - $farbtasticPack = common_path('js/farbtastic/farbtastic.js'); - $userDesignGo = common_path('js/userdesign.go.js'); - - $this->element('script', array('type' => 'text/javascript', - 'src' => $farbtasticPack)); - $this->element('script', array('type' => 'text/javascript', - 'src' => $userDesignGo)); - } - - /** - * Get a default user design - * - * @return Design design - */ - - function defaultDesign() - { - $defaults = common_config('site', 'design'); - - $design = new Design(); - - try { - - $color = new WebColor(); - - $color->parseColor($defaults['backgroundcolor']); - $design->backgroundcolor = $color->intValue(); - - $color->parseColor($defaults['contentcolor']); - $design->contentcolor = $color->intValue(); - - $color->parseColor($defaults['sidebarcolor']); - $design->sidebarcolor = $color->intValue(); - - $color->parseColor($defaults['textcolor']); - $design->textcolor = $color->intValue(); - - $color->parseColor($defaults['linkcolor']); - $design->linkcolor = $color->intValue(); - - $design->backgroundimage = $defaults['backgroundimage']; - - $design->disposition = $defaults['disposition']; - - } catch (WebColorException $e) { - common_log(LOG_ERR, _('Bad default color settings: ' . - $e->getMessage())); - } - - return $design; - } - - /** - * Save or update the user's design settings - * - * @return void - */ - - function saveDesign() - { - try { - - $bgcolor = new WebColor($this->trimmed('design_background')); - $ccolor = new WebColor($this->trimmed('design_content')); - $sbcolor = new WebColor($this->trimmed('design_sidebar')); - $tcolor = new WebColor($this->trimmed('design_text')); - $lcolor = new WebColor($this->trimmed('design_links')); - - } catch (WebColorException $e) { - $this->showForm($e->getMessage()); - return; - } - - $onoff = $this->arg('design_background-image_onoff'); - - $on = false; - $off = false; - $tile = false; - - if ($onoff == 'on') { - $on = true; - } else { - $off = true; - } - - $repeat = $this->boolean('design_background-image_repeat'); - - if ($repeat) { - $tile = true; - } - - $user = common_current_user(); - $design = $user->getDesign(); - - if (!empty($design)) { - - $original = clone($design); - - $design->backgroundcolor = $bgcolor->intValue(); - $design->contentcolor = $ccolor->intValue(); - $design->sidebarcolor = $sbcolor->intValue(); - $design->textcolor = $tcolor->intValue(); - $design->linkcolor = $lcolor->intValue(); - $design->backgroundimage = $filepath; - - $design->setDisposition($on, $off, $tile); - - $result = $design->update($original); - - if ($result === false) { - common_log_db_error($design, 'UPDATE', __FILE__); - $this->showForm(_('Couldn\'t update your design.')); - return; - } - - // update design - } else { - - $user->query('BEGIN'); - - // save new design - $design = new Design(); - - $design->backgroundcolor = $bgcolor->intValue(); - $design->contentcolor = $ccolor->intValue(); - $design->sidebarcolor = $sbcolor->intValue(); - $design->textcolor = $tcolor->intValue(); - $design->linkcolor = $lcolor->intValue(); - $design->backgroundimage = $filepath; - - $design->setDisposition($on, $off, $tile); - - $id = $design->insert(); - - if (empty($id)) { - common_log_db_error($id, 'INSERT', __FILE__); - $this->showForm(_('Unable to save your design settings!')); - return; - } - - $original = clone($user); - $user->design_id = $id; - $result = $user->update($original); - - if (empty($result)) { - common_log_db_error($original, 'UPDATE', __FILE__); - $this->showForm(_('Unable to save your design settings!')); - $user->query('ROLLBACK'); - return; - } - - $user->query('COMMIT'); - - } - - // Now that we have a Design ID we can add a file to the design. - // XXX: This is an additional DB hit, but figured having the image - // associated with the Design rather than the User was worth - // it. -- Zach - - if ($_FILES['design_background-image_file']['error'] == - UPLOAD_ERR_OK) { - - $filepath = null; - - try { - $imagefile = - ImageFile::fromUpload('design_background-image_file'); - } catch (Exception $e) { - $this->showForm($e->getMessage()); - return; - } - - $filename = Design::filename($design->id, - image_type_to_extension($imagefile->type), - common_timestamp()); - - $filepath = Design::path($filename); - - move_uploaded_file($imagefile->filepath, $filepath); - - $original = clone($design); - $design->backgroundimage = $filename; - $design->setDisposition(true, false, false); - $result = $design->update($original); - - if ($result === false) { - common_log_db_error($design, 'UPDATE', __FILE__); - $this->showForm(_('Couldn\'t update your design.')); - return; - } - } - - $this->showForm(_('Design preferences saved.'), true); - } - -} diff --git a/actions/editgroup.php b/actions/editgroup.php index 29a7bce43..6aa6f8b11 100644 --- a/actions/editgroup.php +++ b/actions/editgroup.php @@ -23,6 +23,7 @@ * @package Laconica * @author Evan Prodromou * @author Sarven Capadisli + * @author Zach Copley * @copyright 2008-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/ @@ -40,14 +41,15 @@ if (!defined('LACONICA')) { * @category Group * @package Laconica * @author Evan Prodromou + * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://laconi.ca/ */ -class EditgroupAction extends Action +class EditgroupAction extends GroupDesignAction { + var $msg; - var $group = null; function title() { diff --git a/actions/groupblock.php b/actions/groupblock.php index 28685b1d5..93662da79 100644 --- a/actions/groupblock.php +++ b/actions/groupblock.php @@ -151,19 +151,17 @@ class GroupblockAction extends Action function areYouSureForm() { $id = $this->profile->id; - $this->elementStart('form', array('id' => 'block-' . $id, - 'method' => 'post', - 'class' => 'form_settings form_entity_block', - 'action' => common_local_url('groupblock'))); - $this->elementStart('fieldset'); - $this->hidden('token', common_session_token()); - $this->element('legend', null, _('Block user')); $this->element('p', null, sprintf(_('Are you sure you want to block user "%s" from the group "%s"? '. 'They will be removed from the group, unable to post, and '. 'unable to subscribe to the group in the future.'), $this->profile->getBestName(), $this->group->getBestName())); + $this->elementStart('form', array('id' => 'block-' . $id, + 'method' => 'post', + 'class' => 'block', + 'action' => common_local_url('groupblock'))); + $this->hidden('token', common_session_token()); $this->hidden('blockto-' . $this->profile->id, $this->profile->id, 'blockto'); @@ -175,9 +173,8 @@ class GroupblockAction extends Action $this->hidden($k, $v); } } - $this->submit('form_action-no', _('No'), 'submit form_action-primary', 'no', _("Do not block this user from this group")); - $this->submit('form_action-yes', _('Yes'), 'submit form_action-secondary', 'yes', _('Block this user from this group')); - $this->elementEnd('fieldset'); + $this->submit('no', _('No')); + $this->submit('yes', _('Yes')); $this->elementEnd('form'); } diff --git a/actions/grouplogo.php b/actions/grouplogo.php index fe6127da2..8f6158dac 100644 --- a/actions/grouplogo.php +++ b/actions/grouplogo.php @@ -50,7 +50,7 @@ define('MAX_ORIGINAL', 480); * @link http://laconi.ca/ */ -class GrouplogoAction extends Action +class GrouplogoAction extends GroupDesignAction { var $mode = null; var $imagefile = null; diff --git a/actions/groupmembers.php b/actions/groupmembers.php index abfad3f0d..d132cdf96 100644 --- a/actions/groupmembers.php +++ b/actions/groupmembers.php @@ -44,7 +44,7 @@ require_once INSTALLDIR.'/lib/publicgroupnav.php'; * @link http://laconi.ca/ */ -class GroupmembersAction extends Action +class GroupmembersAction extends GroupDesignAction { var $page = null; diff --git a/actions/showgroup.php b/actions/showgroup.php index 357f579d8..b6a0f4844 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -47,10 +47,9 @@ define('MEMBERS_PER_SECTION', 27); * @link http://laconi.ca/ */ -class ShowgroupAction extends Action +class ShowgroupAction extends GroupDesignAction { - /** group we're viewing. */ - var $group = null; + /** page we're viewing. */ var $page = null; diff --git a/lib/accountsettingsaction.php b/lib/accountsettingsaction.php index 86800d2a3..4ab50abce 100644 --- a/lib/accountsettingsaction.php +++ b/lib/accountsettingsaction.php @@ -115,7 +115,7 @@ class AccountSettingsNav extends Widget 'openidsettings' => array(_('OpenID'), _('Add or remove OpenIDs')), - 'designsettings' => + 'userdesignsettings' => array(_('Design'), _('Design your profile')), 'othersettings' => diff --git a/lib/designsettings.php b/lib/designsettings.php new file mode 100644 index 000000000..6aa6bb2f1 --- /dev/null +++ b/lib/designsettings.php @@ -0,0 +1,402 @@ +. + * + * @category Settings + * @package Laconica + * @author Sarven Capadisli + * @author Zach Copley + * @copyright 2008-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); +} + +require_once INSTALLDIR . '/lib/accountsettingsaction.php'; +require_once INSTALLDIR . '/lib/webcolor.php'; + +class DesignSettingsAction extends AccountSettingsAction +{ + + var $submitaction = null; + + /** + * Title of the page + * + * @return string Title of the page + */ + + function title() + { + return _('Profile design'); + } + + /** + * Instructions for use + * + * @return instructions for use + */ + + function getInstructions() + { + return _('Customize the way your profile looks ' . + 'with a background image and a colour palette of your choice.'); + } + + function showDesignForm($design) + { + + $this->elementStart('form', array('method' => 'post', + 'enctype' => 'multipart/form-data', + 'id' => 'form_settings_design', + 'class' => 'form_settings', + 'action' => $this->submitaction)); + $this->elementStart('fieldset'); + $this->hidden('token', common_session_token()); + + $this->elementStart('fieldset', array('id' => + 'settings_design_background-image')); + $this->element('legend', null, _('Change background image')); + $this->elementStart('ul', 'form_data'); + $this->elementStart('li'); + $this->element('label', array('for' => 'design_background-image_file'), + _('Upload file')); + $this->element('input', array('name' => 'design_background-image_file', + 'type' => 'file', + 'id' => 'design_background-image_file')); + $this->element('p', 'form_guide', _('You can upload your personal ' . + 'background image. The maximum file size is 2Mb.')); + $this->element('input', array('name' => 'MAX_FILE_SIZE', + 'type' => 'hidden', + 'id' => 'MAX_FILE_SIZE', + 'value' => ImageFile::maxFileSizeInt())); + $this->elementEnd('li'); + + if (!empty($design->backgroundimage)) { + + $this->elementStart('li', array('id' => 'design_background-image_onoff')); + + $this->element('img', array('src' => + Design::url($design->backgroundimage))); + + $attrs = array('name' => 'design_background-image_onoff', + 'type' => 'radio', + 'id' => 'design_background-image_on', + 'class' => 'radio', + 'value' => 'on'); + + if ($design->disposition & BACKGROUND_ON) { + $attrs['checked'] = 'checked'; + } + + $this->element('input', $attrs); + + $this->element('label', array('for' => 'design_background-image_on', + 'class' => 'radio'), + _('On')); + + $attrs = array('name' => 'design_background-image_onoff', + 'type' => 'radio', + 'id' => 'design_background-image_off', + 'class' => 'radio', + 'value' => 'off'); + + if ($design->disposition & BACKGROUND_OFF) { + $attrs['checked'] = 'checked'; + } + + $this->element('input', $attrs); + + $this->element('label', array('for' => 'design_background-image_off', + 'class' => 'radio'), + _('Off')); + $this->element('p', 'form_guide', _('Turn background image on or off.')); + $this->elementEnd('li'); + } + + $this->elementStart('li'); + $this->checkbox('design_background-image_repeat', + _('Tile background image'), + ($design->disposition & BACKGROUND_TILE) ? true : false ); + $this->elementEnd('li'); + + $this->elementEnd('ul'); + $this->elementEnd('fieldset'); + + $this->elementStart('fieldset', array('id' => 'settings_design_color')); + $this->element('legend', null, _('Change colours')); + $this->elementStart('ul', 'form_data'); + + try { + + $bgcolor = new WebColor($design->backgroundcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-1'), _('Background')); + $this->element('input', array('name' => 'design_background', + 'type' => 'text', + 'id' => 'swatch-1', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $bgcolor->hexValue())); + $this->elementEnd('li'); + + $ccolor = new WebColor($design->contentcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-2'), _('Content')); + $this->element('input', array('name' => 'design_content', + 'type' => 'text', + 'id' => 'swatch-2', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $ccolor->hexValue())); + $this->elementEnd('li'); + + $sbcolor = new WebColor($design->sidebarcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-3'), _('Sidebar')); + $this->element('input', array('name' => 'design_sidebar', + 'type' => 'text', + 'id' => 'swatch-3', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $sbcolor->hexValue())); + $this->elementEnd('li'); + + $tcolor = new WebColor($design->textcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-4'), _('Text')); + $this->element('input', array('name' => 'design_text', + 'type' => 'text', + 'id' => 'swatch-4', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $tcolor->hexValue())); + $this->elementEnd('li'); + + $lcolor = new WebColor($design->linkcolor); + + $this->elementStart('li'); + $this->element('label', array('for' => 'swatch-5'), _('Links')); + $this->element('input', array('name' => 'design_links', + 'type' => 'text', + 'id' => 'swatch-5', + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => '#' . $lcolor->hexValue())); + + $this->elementEnd('li'); + + } catch (WebColorException $e) { + common_log(LOG_ERR, 'Bad color values in design ID: ' . + $design->id); + } + + $this->elementEnd('ul'); + $this->elementEnd('fieldset'); + + $this->element('input', array('id' => 'settings_design_reset', + 'type' => 'reset', + 'value' => 'Reset', + 'class' => 'submit form_action-primary', + 'title' => _('Reset back to default'))); + + $this->submit('save', _('Save'), 'submit form_action-secondary', + 'save', _('Save design')); + + $this->elementEnd('fieldset'); + $this->elementEnd('form'); + } + + /** + * Handle a post + * + * Validate input and save changes. Reload the form with a success + * or error message. + * + * @return void + */ + + function handlePost() + { + // XXX: Robin's workaround for a bug in PHP where $_POST + // and $_FILE are empty in the case that the uploaded + // file is bigger than PHP is configured to handle. + + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + if (empty($_POST) && $_SERVER['CONTENT_LENGTH']) { + + $msg = _('The server was unable to handle that much POST ' . + 'data (%s bytes) due to its current configuration.'); + + $this->showForm(sprintf($msg, $_SERVER['CONTENT_LENGTH'])); + } + } + + // CSRF protection + $token = $this->trimmed('token'); + if (!$token || $token != common_session_token()) { + $this->showForm(_('There was a problem with your session token. '. + 'Try again, please.')); + return; + } + + if ($this->arg('save')) { + $this->saveDesign(); + } else if ($this->arg('reset')) { + $this->resetDesign(); + } else { + $this->showForm(_('Unexpected form submission.')); + } + } + + /** + * Add the Farbtastic stylesheet + * + * @return void + */ + + function showStylesheets() + { + parent::showStylesheets(); + $farbtasticStyle = + common_path('theme/base/css/farbtastic.css?version='.LACONICA_VERSION); + + $this->element('link', array('rel' => 'stylesheet', + 'type' => 'text/css', + 'href' => $farbtasticStyle, + 'media' => 'screen, projection, tv')); + } + + /** + * Add the Farbtastic scripts + * + * @return void + */ + + function showScripts() + { + parent::showScripts(); + + $farbtasticPack = common_path('js/farbtastic/farbtastic.js'); + $userDesignGo = common_path('js/userdesign.go.js'); + + $this->element('script', array('type' => 'text/javascript', + 'src' => $farbtasticPack)); + $this->element('script', array('type' => 'text/javascript', + 'src' => $userDesignGo)); + } + + /** + * Get a default user design + * + * @return Design design + */ + + function defaultDesign() + { + $defaults = common_config('site', 'design'); + + $design = new Design(); + + try { + + $color = new WebColor(); + + $color->parseColor($defaults['backgroundcolor']); + $design->backgroundcolor = $color->intValue(); + + $color->parseColor($defaults['contentcolor']); + $design->contentcolor = $color->intValue(); + + $color->parseColor($defaults['sidebarcolor']); + $design->sidebarcolor = $color->intValue(); + + $color->parseColor($defaults['textcolor']); + $design->textcolor = $color->intValue(); + + $color->parseColor($defaults['linkcolor']); + $design->linkcolor = $color->intValue(); + + $design->backgroundimage = $defaults['backgroundimage']; + + $design->disposition = $defaults['disposition']; + + } catch (WebColorException $e) { + common_log(LOG_ERR, _('Bad default color settings: ' . + $e->getMessage())); + } + + return $design; + } + + function saveBackgroundImage($design) { + + // Now that we have a Design ID we can add a file to the design. + // XXX: This is an additional DB hit, but figured having the image + // associated with the Design rather than the User was worth + // it. -- Zach + + if ($_FILES['design_background-image_file']['error'] == + UPLOAD_ERR_OK) { + + $filepath = null; + + try { + $imagefile = + ImageFile::fromUpload('design_background-image_file'); + } catch (Exception $e) { + $this->showForm($e->getMessage()); + return; + } + + $filename = Design::filename($design->id, + image_type_to_extension($imagefile->type), + common_timestamp()); + + $filepath = Design::path($filename); + + move_uploaded_file($imagefile->filepath, $filepath); + + $original = clone($design); + $design->backgroundimage = $filename; + $design->setDisposition(true, false, false); + $result = $design->update($original); + + if ($result === false) { + common_log_db_error($design, 'UPDATE', __FILE__); + $this->showForm(_('Couldn\'t update your design.')); + return; + } + } + } + +} diff --git a/lib/groupnav.php b/lib/groupnav.php index 194247982..9e530c447 100644 --- a/lib/groupnav.php +++ b/lib/groupnav.php @@ -113,6 +113,12 @@ class GroupNav extends Widget sprintf(_('Add or edit %s logo'), $nickname), $action_name == 'grouplogo', 'nav_group_logo'); + $this->out->menuItem(common_local_url('groupdesignsettings', array('nickname' => + $nickname)), + _('Design'), + sprintf(_('Add or edit %s design'), $nickname), + $action_name == 'groupdesignsettings', + 'nav_group_design'); } $this->out->elementEnd('ul'); } diff --git a/lib/router.php b/lib/router.php index 8b6f63618..1f39c60dc 100644 --- a/lib/router.php +++ b/lib/router.php @@ -132,7 +132,7 @@ class Router // settings foreach (array('profile', 'avatar', 'password', 'openid', 'im', - 'email', 'sms', 'twitter', 'design', 'other') as $s) { + 'email', 'sms', 'twitter', 'userdesign', 'other') as $s) { $m->connect('settings/'.$s, array('action' => $s.'settings')); } @@ -223,7 +223,7 @@ class Router array('nickname' => '[a-zA-Z0-9]+')); } - foreach (array('members', 'logo', 'rss') as $n) { + foreach (array('members', 'logo', 'rss', 'designsettings') as $n) { $m->connect('group/:nickname/'.$n, array('action' => 'group'.$n), array('nickname' => '[a-zA-Z0-9]+')); -- cgit v1.2.3-54-g00ecf From 3f032bc36e2c624a895c584479c8f423e62bba73 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 18 Jun 2009 02:16:39 -0700 Subject: Left out some new user and group theming file in the previous commit --- actions/groupdesignsettings.php | 330 ++++++++++++++++++++++++++++++++++++++++ actions/userdesignsettings.php | 208 +++++++++++++++++++++++++ lib/groupdesignaction.php | 87 +++++++++++ 3 files changed, 625 insertions(+) create mode 100644 actions/groupdesignsettings.php create mode 100644 actions/userdesignsettings.php create mode 100644 lib/groupdesignaction.php (limited to 'lib') diff --git a/actions/groupdesignsettings.php b/actions/groupdesignsettings.php new file mode 100644 index 000000000..7270bc8f7 --- /dev/null +++ b/actions/groupdesignsettings.php @@ -0,0 +1,330 @@ +. + * + * @category Settings + * @package Laconica + * @author Sarven Capadisli + * @author Zach Copley + * @copyright 2008-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); +} + +require_once INSTALLDIR . '/lib/designsettings.php'; + +class GroupDesignSettingsAction extends DesignSettingsAction +{ + var $group = null; + + /** + * Prepare to run + */ + + function prepare($args) + { + parent::prepare($args); + + if (!common_config('inboxes','enabled')) { + $this->serverError(_('Inboxes must be enabled for groups to work')); + return false; + } + + if (!common_logged_in()) { + $this->clientError(_('You must be logged in to edit a group.')); + return false; + } + + $nickname_arg = $this->trimmed('nickname'); + $nickname = common_canonical_nickname($nickname_arg); + + // Permanent redirect on non-canonical nickname + + if ($nickname_arg != $nickname) { + $args = array('nickname' => $nickname); + common_redirect(common_local_url('groupdesignsettings', $args), 301); + return false; + } + + if (!$nickname) { + $this->clientError(_('No nickname'), 404); + return false; + } + + $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); + return false; + } + + $cur = common_current_user(); + + if (!$cur->isAdmin($this->group)) { + $this->clientError(_('You must be an admin to edit the group'), 403); + return false; + } + + $this->submitaction = common_local_url('groupdesignsettings', + array('nickname' => $this->group->nickname)); + + return true; + } + + /** + * A design for this action + * + * if the group attribute has been set, returns that group's + * design. + * + * @return Design a design object to use + */ + + function getDesign() + { + + if (empty($this->group)) { + return null; + } + + return $this->group->getDesign(); + } + + /** + * Title of the page + * + * @return string Title of the page + */ + + function title() + { + return _('Group design'); + } + + /** + * Instructions for use + * + * @return instructions for use + */ + + function getInstructions() + { + return _('Customize the way your group looks ' . + 'with a background image and a colour palette of your choice.'); + } + + /** + * Override to show group nav stuff + * + * @return nothing + */ + + function showLocalNav() + { + $nav = new GroupNav($this, $this->group); + $nav->show(); + } + + /** + * Get the design we want to edit + * + * @return Design + */ + + function getWorkingDesign() { + + $design = null; + + if (isset($this->group)) { + $design = $this->group->getDesign(); + } + + if (empty($design)) { + $design = $this->defaultDesign(); + } + + return $design; + } + + /** + * Content area of the page + * + * Shows a form for changing the design + * + * @return void + */ + + function showContent() + { + $this->showDesignForm($this->getWorkingDesign()); + } + + /** + * Save or update the group's design settings + * + * @return void + */ + + function saveDesign() + { + try { + + $bgcolor = new WebColor($this->trimmed('design_background')); + $ccolor = new WebColor($this->trimmed('design_content')); + $sbcolor = new WebColor($this->trimmed('design_sidebar')); + $tcolor = new WebColor($this->trimmed('design_text')); + $lcolor = new WebColor($this->trimmed('design_links')); + + } catch (WebColorException $e) { + $this->showForm($e->getMessage()); + return; + } + + $onoff = $this->arg('design_background-image_onoff'); + + $on = false; + $off = false; + $tile = false; + + if ($onoff == 'on') { + $on = true; + } else { + $off = true; + } + + $repeat = $this->boolean('design_background-image_repeat'); + + if ($repeat) { + $tile = true; + } + + $design = $this->group->getDesign(); + + if (!empty($design)) { + + // update design + + $original = clone($design); + + $design->backgroundcolor = $bgcolor->intValue(); + $design->contentcolor = $ccolor->intValue(); + $design->sidebarcolor = $sbcolor->intValue(); + $design->textcolor = $tcolor->intValue(); + $design->linkcolor = $lcolor->intValue(); + $design->backgroundimage = $filepath; + + $design->setDisposition($on, $off, $tile); + + $result = $design->update($original); + + if ($result === false) { + common_log_db_error($design, 'UPDATE', __FILE__); + $this->showForm(_('Couldn\'t update your design.')); + return; + } + + } else { + + $this->group->query('BEGIN'); + + // save new design + + $design = new Design(); + + $design->backgroundcolor = $bgcolor->intValue(); + $design->contentcolor = $ccolor->intValue(); + $design->sidebarcolor = $sbcolor->intValue(); + $design->textcolor = $tcolor->intValue(); + $design->linkcolor = $lcolor->intValue(); + $design->backgroundimage = $filepath; + + $design->setDisposition($on, $off, $tile); + + $id = $design->insert(); + + if (empty($id)) { + common_log_db_error($id, 'INSERT', __FILE__); + $this->showForm(_('Unable to save your design settings!')); + return; + } + + $original = clone($this->group); + $this->group->design_id = $id; + $result = $this->group->update($original); + + if (empty($result)) { + common_log_db_error($original, 'UPDATE', __FILE__); + $this->showForm(_('Unable to save your design settings!')); + $this->group->query('ROLLBACK'); + return; + } + + $this->group->query('COMMIT'); + + } + + $this->saveBackgroundImage($design); + + $this->showForm(_('Design preferences saved.'), true); + } + + /** + * Handle input and output a page (overrided) + * + * @param array $args $_REQUEST arguments + * + * @return void + */ + + function handle($args) + { + parent::handle($args); + if (!common_logged_in()) { + $this->clientError(_('Not logged in.')); + return; + } else if (!common_is_real_login()) { + // Cookie theft means that automatic logins can't + // change important settings or see private info, and + // _all_ our settings are important + common_set_returnto($this->selfUrl()); + $user = common_current_user(); + if ($user->hasOpenID()) { + common_redirect(common_local_url('openidlogin'), 303); + } else { + common_redirect(common_local_url('login'), 303); + } + } else if ($_SERVER['REQUEST_METHOD'] == 'POST') { + $this->handlePost(); + } else { + $this->showForm(); + } + } + +} diff --git a/actions/userdesignsettings.php b/actions/userdesignsettings.php new file mode 100644 index 000000000..d6088aa9d --- /dev/null +++ b/actions/userdesignsettings.php @@ -0,0 +1,208 @@ +. + * + * @category Settings + * @package Laconica + * @author Sarven Capadisli + * @author Zach Copley + * @copyright 2008-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); +} + +require_once INSTALLDIR . '/lib/designsettings.php'; + +class UserDesignSettingsAction extends DesignSettingsAction +{ + + function prepare($args) + { + parent::prepare($args); + $this->submitaction = common_local_url('userdesignsettings'); + return true; + } + + /** + * Title of the page + * + * @return string Title of the page + */ + + function title() + { + return _('Profile design'); + } + + /** + * Instructions for use + * + * @return instructions for use + */ + + function getInstructions() + { + return _('Customize the way your profile looks ' . + 'with a background image and a colour palette of your choice.'); + } + + /** + * Get the design we want to edit + * + * @return Design + */ + + function getWorkingDesign() { + + $user = common_current_user(); + $design = $user->getDesign(); + + if (empty($design)) { + $design = $this->defaultDesign(); + } + + return $design; + } + + /** + * Content area of the page + * + * Shows a form for changing the design + * + * @return void + */ + + function showContent() + { + $this->showDesignForm($this->getWorkingDesign()); + } + + /** + * Save or update the user's design settings + * + * @return void + */ + + function saveDesign() + { + try { + + $bgcolor = new WebColor($this->trimmed('design_background')); + $ccolor = new WebColor($this->trimmed('design_content')); + $sbcolor = new WebColor($this->trimmed('design_sidebar')); + $tcolor = new WebColor($this->trimmed('design_text')); + $lcolor = new WebColor($this->trimmed('design_links')); + + } catch (WebColorException $e) { + $this->showForm($e->getMessage()); + return; + } + + $onoff = $this->arg('design_background-image_onoff'); + + $on = false; + $off = false; + $tile = false; + + if ($onoff == 'on') { + $on = true; + } else { + $off = true; + } + + $repeat = $this->boolean('design_background-image_repeat'); + + if ($repeat) { + $tile = true; + } + + $user = common_current_user(); + $design = $user->getDesign(); + + if (!empty($design)) { + + $original = clone($design); + + $design->backgroundcolor = $bgcolor->intValue(); + $design->contentcolor = $ccolor->intValue(); + $design->sidebarcolor = $sbcolor->intValue(); + $design->textcolor = $tcolor->intValue(); + $design->linkcolor = $lcolor->intValue(); + $design->backgroundimage = $filepath; + + $design->setDisposition($on, $off, $tile); + + $result = $design->update($original); + + if ($result === false) { + common_log_db_error($design, 'UPDATE', __FILE__); + $this->showForm(_('Couldn\'t update your design.')); + return; + } + + // update design + } else { + + $user->query('BEGIN'); + + // save new design + $design = new Design(); + + $design->backgroundcolor = $bgcolor->intValue(); + $design->contentcolor = $ccolor->intValue(); + $design->sidebarcolor = $sbcolor->intValue(); + $design->textcolor = $tcolor->intValue(); + $design->linkcolor = $lcolor->intValue(); + $design->backgroundimage = $filepath; + + $design->setDisposition($on, $off, $tile); + + $id = $design->insert(); + + if (empty($id)) { + common_log_db_error($id, 'INSERT', __FILE__); + $this->showForm(_('Unable to save your design settings!')); + return; + } + + $original = clone($user); + $user->design_id = $id; + $result = $user->update($original); + + if (empty($result)) { + common_log_db_error($original, 'UPDATE', __FILE__); + $this->showForm(_('Unable to save your design settings!')); + $user->query('ROLLBACK'); + return; + } + + $user->query('COMMIT'); + + } + + $this->saveBackgroundImage($design); + + $this->showForm(_('Design preferences saved.'), true); + } +} diff --git a/lib/groupdesignaction.php b/lib/groupdesignaction.php new file mode 100644 index 000000000..bc95921f1 --- /dev/null +++ b/lib/groupdesignaction.php @@ -0,0 +1,87 @@ +. + * + * @category Action + * @package Laconica + * @author Zach Copley + * @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); +} + +/** + * Base class for actions that use a group's design + * + * Pages related to groups can be themed with a design. + * This superclass returns that design. + * + * @category Action + * @package Laconica + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + * + */ +class GroupDesignAction extends Action { + + /** The group in question */ + var $group = null; + + /** + * Show the groups's design stylesheet + * + * @return nothing + */ + function showStylesheets() + { + parent::showStylesheets(); + + $design = $this->getDesign(); + + if (!empty($design)) { + $design->showCSS($this); + } + } + + /** + * A design for this action + * + * if the group attribute has been set, returns that group's + * design. + * + * @return Design a design object to use + */ + + function getDesign() + { + + if (empty($this->group)) { + return null; + } + + return $this->group->getDesign(); + } + +} -- cgit v1.2.3-54-g00ecf From 65b4cfbb54f5b44820dd02bb9c3c2ca98dbbd321 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Thu, 18 Jun 2009 06:02:12 -0400 Subject: Display more oembed info in attachment popup. --- lib/attachmentlist.php | 36 ++++++++++++++++++++++++++++++++++++ theme/base/css/display.css | 6 ++++++ 2 files changed, 42 insertions(+) (limited to 'lib') diff --git a/lib/attachmentlist.php b/lib/attachmentlist.php index 45e4fa319..a781c3092 100644 --- a/lib/attachmentlist.php +++ b/lib/attachmentlist.php @@ -244,6 +244,42 @@ class AttachmentListItem extends Widget class Attachment extends AttachmentListItem { + function showLink() { + $this->out->elementStart('a', $this->linkAttr()); + $this->out->element('span', null, $this->linkTitle()); + $this->showRepresentation(); + $this->out->elementEnd('a'); + + if (empty($this->oembed->author_name) && empty($this->oembed->provider)) { + return; + } + + $this->out->elementStart('dl', 'oembed_info'); + + if (!empty($this->oembed->author_name)) { + $this->out->element('dt', null, _('Author:')); + + $this->out->elementStart('dd'); + if (empty($this->oembed->author_url)) { + $this->out->text($this->oembed->author_name); + } else { + $this->out->element('a', array('href' => $this->oembed->author_url), $this->oembed->author_name); + } + $this->out->elementEnd('dd'); + } + if (!empty($this->oembed->provider)) { + $this->out->element('dt', null, _('Provider:')); + $this->out->elementStart('dd'); + if (empty($this->oembed->provider_url)) { + $this->out->text($this->oembed->provider); + } else { + $this->out->element('a', array('href' => $this->oembed->provider_url), $this->oembed->provider); + } + $this->out->elementEnd('dd'); + } + $this->out->elementEnd('dl'); + } + function show() { $this->showNoticeAttachment(); } diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 9e35d015d..dd787f5e2 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -1276,3 +1276,9 @@ display:none; .guide { clear:both; } + +dl.oembed_info dt, +dl.oembed_info dd { +display: inline; +} + -- cgit v1.2.3-54-g00ecf From 730c173238841cdc4d52bb074e53d4a74f7871bf Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 18 Jun 2009 18:48:19 +0000 Subject: Updated markup and CSS for attachment_view --- lib/attachmentlist.php | 62 ++++++++++++++++++++++++++-------------------- theme/base/css/display.css | 22 +++++++++++----- 2 files changed, 51 insertions(+), 33 deletions(-) (limited to 'lib') diff --git a/lib/attachmentlist.php b/lib/attachmentlist.php index c80c0c418..7bd441bf4 100644 --- a/lib/attachmentlist.php +++ b/lib/attachmentlist.php @@ -210,7 +210,7 @@ class AttachmentListItem extends Widget function showRepresentation() { $thumbnail = File_thumbnail::staticGet('file_id', $this->attachment->id); if (!empty($thumbnail)) { - $this->out->element('img', array('alt' => 'nothing to say', 'src' => $thumbnail->url, 'width' => $thumbnail->width, 'height' => $thumbnail->height)); + $this->out->element('img', array('alt' => '', 'src' => $thumbnail->url, 'width' => $thumbnail->width, 'height' => $thumbnail->height)); } } @@ -244,39 +244,47 @@ class AttachmentListItem extends Widget class Attachment extends AttachmentListItem { function showLink() { + $this->out->elementStart('div', array('id' => 'attachment_view', + 'class' => 'hentry')); + $this->out->elementStart('div', 'entry-title'); $this->out->elementStart('a', $this->linkAttr()); $this->out->element('span', null, $this->linkTitle()); $this->showRepresentation(); $this->out->elementEnd('a'); - - if (empty($this->oembed->author_name) && empty($this->oembed->provider)) { - return; - } - - $this->out->elementStart('dl', 'oembed_info'); - - if (!empty($this->oembed->author_name)) { - $this->out->element('dt', null, _('Author:')); - - $this->out->elementStart('dd'); - if (empty($this->oembed->author_url)) { - $this->out->text($this->oembed->author_name); - } else { - $this->out->element('a', array('href' => $this->oembed->author_url), $this->oembed->author_name); + $this->out->elementEnd('div'); + + if ($this->oembed->author_name || $this->oembed->provider) { + $this->out->elementStart('div', array('id' => 'oembed_info', + 'class' => 'entry-content')); + if (!empty($this->oembed->author_name)) { + $this->out->elementStart('dl', 'vcard author'); + $this->out->element('dt', null, _('Author')); + $this->out->elementStart('dd', 'fn'); + if (empty($this->oembed->author_url)) { + $this->out->text($this->oembed->author_name); + } else { + $this->out->element('a', array('href' => $this->oembed->author_url, + 'class' => 'url'), $this->oembed->author_name); + } + $this->out->elementEnd('dd'); + $this->out->elementEnd('dl'); } - $this->out->elementEnd('dd'); - } - if (!empty($this->oembed->provider)) { - $this->out->element('dt', null, _('Provider:')); - $this->out->elementStart('dd'); - if (empty($this->oembed->provider_url)) { - $this->out->text($this->oembed->provider); - } else { - $this->out->element('a', array('href' => $this->oembed->provider_url), $this->oembed->provider); + if (!empty($this->oembed->provider)) { + $this->out->elementStart('dl', 'vcard'); + $this->out->element('dt', null, _('Provider')); + $this->out->elementStart('dd', 'fn'); + if (empty($this->oembed->provider_url)) { + $this->out->text($this->oembed->provider); + } else { + $this->out->element('a', array('href' => $this->oembed->provider_url, + 'class' => 'url'), $this->oembed->provider); + } + $this->out->elementEnd('dd'); + $this->out->elementEnd('dl'); } - $this->out->elementEnd('dd'); + $this->out->elementEnd('div'); } - $this->out->elementEnd('dl'); + $this->out->elementEnd('div'); } function show() { diff --git a/theme/base/css/display.css b/theme/base/css/display.css index daf5ada1c..8957a5b40 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -1018,6 +1018,22 @@ border-radius:7px; -webkit-border-radius:7px; } +#attachment_view #oembed_info { +margin-top:11px; +} +#attachment_view #oembed_info dt, +#attachment_view #oembed_info dd { +float:left; +} +#attachment_view #oembed_info dt { +clear:left; +margin-right:11px; +font-weight:bold; +} +#attachment_view #oembed_info dt:after { +content: ":"; +} + #usergroups #new_group { float: left; margin-right: 2em; @@ -1284,9 +1300,3 @@ display:none; .guide { clear:both; } - -dl.oembed_info dt, -dl.oembed_info dd { -display: inline; -} - -- cgit v1.2.3-54-g00ecf From 23d6d19e75f273bf6e72fbcbbf8e6789f77d07ff Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 18 Jun 2009 19:03:44 +0000 Subject: Better attachment view check --- lib/attachmentlist.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/attachmentlist.php b/lib/attachmentlist.php index 7bd441bf4..a2446a886 100644 --- a/lib/attachmentlist.php +++ b/lib/attachmentlist.php @@ -253,7 +253,7 @@ class Attachment extends AttachmentListItem $this->out->elementEnd('a'); $this->out->elementEnd('div'); - if ($this->oembed->author_name || $this->oembed->provider) { + if (!empty($this->oembed->author_name) || !empty($this->oembed->provider)) { $this->out->elementStart('div', array('id' => 'oembed_info', 'class' => 'entry-content')); if (!empty($this->oembed->author_name)) { -- cgit v1.2.3-54-g00ecf From 597df6a2345ad61e7e0f21277d97866bdb2116a4 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 18 Jun 2009 16:19:26 -0700 Subject: better calculation of path --- lib/common.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/common.php b/lib/common.php index eb8a2b873..702da8235 100644 --- a/lib/common.php +++ b/lib/common.php @@ -55,13 +55,25 @@ require_once(INSTALLDIR.'/lib/language.php'); require_once(INSTALLDIR.'/lib/event.php'); require_once(INSTALLDIR.'/lib/plugin.php'); +function _sn_to_path($sn) +{ + $past_root = substr($sn, 1); + $last_slash = strrpos($past_root, '/'); + if ($last_slash > 0) { + $p = substr($past_root, 0, $last_slash); + } else { + $p = ''; + } + return $p; +} + // try to figure out where we are $_server = array_key_exists('SERVER_NAME', $_SERVER) ? strtolower($_SERVER['SERVER_NAME']) : null; $_path = array_key_exists('SCRIPT_NAME', $_SERVER) ? - substr($_SERVER['SCRIPT_NAME'], 1, strrpos($_SERVER['SCRIPT_NAME'], '/') - 1) : + _sn_to_path($_SERVER['SCRIPT_NAME']) : null; // default configuration, overwritten in config.php -- cgit v1.2.3-54-g00ecf From 1c2cf108118b3d5cfebd0e266099505810e6d850 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 19 Jun 2009 15:54:24 +0000 Subject: Includes a sioc:reply_to link between notices. It helps with things like http://danbri.org/words/2009/06/16/415 Thanks to Toby Inkster for the patch: http://buzzword.org.uk/2009/laconica-0.7.3-sioc-reply_to.patch --- lib/rssaction.php | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib') diff --git a/lib/rssaction.php b/lib/rssaction.php index eafdbf131..08b333d97 100644 --- a/lib/rssaction.php +++ b/lib/rssaction.php @@ -212,6 +212,11 @@ class Rss10Action extends Action $this->element('sioc:has_creator', array('rdf:resource' => $creator_uri.'#acct')); $this->element('laconica:postIcon', array('rdf:resource' => $profile->avatarUrl())); $this->element('cc:licence', array('rdf:resource' => common_config('license', 'url'))); + if ($notice->reply_to) { + $replyurl = common_local_url('shownotice', + array('notice' => $notice->reply_to)); + $this->element('sioc:reply_to', array('rdf:resource' => $replyurl)); + } $this->elementEnd('item'); $this->creators[$creator_uri] = $profile; } -- cgit v1.2.3-54-g00ecf From 9be54a3dcf6520781c1c64897a28cfaca6fd66fb Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 19 Jun 2009 16:04:14 +0000 Subject: Minor indenting --- lib/rssaction.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/rssaction.php b/lib/rssaction.php index 08b333d97..6f6c9a8cb 100644 --- a/lib/rssaction.php +++ b/lib/rssaction.php @@ -213,8 +213,7 @@ class Rss10Action extends Action $this->element('laconica:postIcon', array('rdf:resource' => $profile->avatarUrl())); $this->element('cc:licence', array('rdf:resource' => common_config('license', 'url'))); if ($notice->reply_to) { - $replyurl = common_local_url('shownotice', - array('notice' => $notice->reply_to)); + $replyurl = common_local_url('shownotice', array('notice' => $notice->reply_to)); $this->element('sioc:reply_to', array('rdf:resource' => $replyurl)); } $this->elementEnd('item'); -- cgit v1.2.3-54-g00ecf From b8f3f32f3f12339c3838fcfc883815d63a36dca7 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 19 Jun 2009 20:21:57 -0700 Subject: Keep Twitter gateway notices from leaking thru MySQL notice search --- lib/search_engines.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/search_engines.php b/lib/search_engines.php index 7b9dbb618..0f405afbd 100644 --- a/lib/search_engines.php +++ b/lib/search_engines.php @@ -118,12 +118,20 @@ class MySQLSearch extends SearchEngine } return true; } else if ('identica_notices' === $this->table) { - $this->target->whereAdd('MATCH(content) ' . - 'AGAINST (\''.addslashes($q).'\' IN BOOLEAN MODE)'); + + // Don't show imported notices + $this->target->whereAdd('notice.is_local != ' . NOTICE_GATEWAY); + if (strtolower($q) != $q) { + $this->target->whereAdd("( MATCH(content) AGAINST ('" . addslashes($q) . + "' IN BOOLEAN MODE)) OR ( MATCH(content) " . + "AGAINST ('" . addslashes(strtolower($q)) . + "' IN BOOLEAN MODE))"); + } else { $this->target->whereAdd('MATCH(content) ' . - 'AGAINST (\''.addslashes(strtolower($q)).'\' IN BOOLEAN MODE)', 'OR'); + 'AGAINST (\''.addslashes($q).'\' IN BOOLEAN MODE)'); } + return true; } else { throw new ServerException('Unknown table: ' . $this->table); @@ -138,6 +146,9 @@ class PGSearch extends SearchEngine if ('identica_people' === $this->table) { return $this->target->whereAdd('textsearch @@ plainto_tsquery(\''.addslashes($q).'\')'); } else if ('identica_notices' === $this->table) { + + // XXX: We need to filter out gateway notices (notice.is_local = -2) --Zach + return $this->target->whereAdd('to_tsvector(\'english\', content) @@ plainto_tsquery(\''.addslashes($q).'\')'); } else { throw new ServerException('Unknown table: ' . $this->table); -- cgit v1.2.3-54-g00ecf From 054e4459b2b2701158cd183dc1eb04c454e04bff Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Sat, 20 Jun 2009 18:22:05 +0000 Subject: Position of max_file_size position helps IE --- lib/noticeform.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/noticeform.php b/lib/noticeform.php index a36b7f31f..4e2a2edd6 100644 --- a/lib/noticeform.php +++ b/lib/noticeform.php @@ -151,12 +151,12 @@ class NoticeForm extends Form '140'); $this->out->elementEnd('dl'); if (common_config('attachments', 'uploads')) { - $this->out->hidden('MAX_FILE_SIZE', common_config('attachments', 'file_quota')); $this->out->element('label', array('for' => 'notice_data-attach'),_('Attach')); $this->out->element('input', array('id' => 'notice_data-attach', 'type' => 'file', 'name' => 'attach', 'title' => _('Attach a file'))); + $this->out->hidden('MAX_FILE_SIZE', common_config('attachments', 'file_quota')); } if ($this->action) { $this->out->hidden('notice_return-to', $this->action, 'returnto'); -- cgit v1.2.3-54-g00ecf From 198afa0a1d61c4db2cf6b66e5801af506462ab9b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 20 Jun 2009 14:58:47 -0700 Subject: change scripts to take server and path from commandline --- lib/common.php | 27 +++++++++++++++++++-------- scripts/enjitqueuehandler.php | 14 ++++++++------ scripts/facebookqueuehandler.php | 11 ++++++++--- scripts/jabberqueuehandler.php | 5 +++++ scripts/maildaemon.php | 6 +++++- scripts/ombqueuehandler.php | 11 ++++++++--- scripts/pingqueuehandler.php | 5 +++++ scripts/publicqueuehandler.php | 9 +++++++-- scripts/smsqueuehandler.php | 9 +++++++-- scripts/synctwitterfriends.php | 5 +++++ scripts/triminboxes.php | 9 +++++++-- scripts/twitterqueuehandler.php | 11 ++++++++--- scripts/twitterstatusfetcher.php | 7 ++++++- scripts/xmppconfirmhandler.php | 9 +++++++-- scripts/xmppdaemon.php | 6 +++++- 15 files changed, 110 insertions(+), 34 deletions(-) (limited to 'lib') diff --git a/lib/common.php b/lib/common.php index 702da8235..17eed71cd 100644 --- a/lib/common.php +++ b/lib/common.php @@ -67,14 +67,25 @@ function _sn_to_path($sn) return $p; } -// try to figure out where we are - -$_server = array_key_exists('SERVER_NAME', $_SERVER) ? - strtolower($_SERVER['SERVER_NAME']) : - null; -$_path = array_key_exists('SCRIPT_NAME', $_SERVER) ? - _sn_to_path($_SERVER['SCRIPT_NAME']) : - null; +// try to figure out where we are. $server and $path +// can be set by including module, else we guess based +// on HTTP info. + +if (isset($server)) { + $_server = $server; +} else { + $_server = array_key_exists('SERVER_NAME', $_SERVER) ? + strtolower($_SERVER['SERVER_NAME']) : + null; +} + +if (isset($path)) { + $_path = $path; +} else { + $_path = array_key_exists('SCRIPT_NAME', $_SERVER) ? + _sn_to_path($_SERVER['SCRIPT_NAME']) : + null; +} // default configuration, overwritten in config.php diff --git a/scripts/enjitqueuehandler.php b/scripts/enjitqueuehandler.php index 40f60da5d..37fef0b04 100755 --- a/scripts/enjitqueuehandler.php +++ b/scripts/enjitqueuehandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/mail.php'); require_once(INSTALLDIR . '/lib/queuehandler.php'); @@ -35,7 +40,6 @@ set_error_handler('common_error_handler'); class EnjitQueueHandler extends QueueHandler { - function transport() { return 'enjit'; @@ -60,7 +64,6 @@ class EnjitQueueHandler extends QueueHandler return "skipped"; } - # # Build an Atom message from the notice # @@ -93,8 +96,8 @@ class EnjitQueueHandler extends QueueHandler $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); - - curl_setopt($ch, CURLOPT_HEADER, 1); + + curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1) ; curl_setopt($ch, CURLOPT_POSTFIELDS, $data); @@ -103,7 +106,7 @@ class EnjitQueueHandler extends QueueHandler # # curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); # curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); - # curl_setopt($ch, CURLOPT_VERBOSE, 1); + # curl_setopt($ch, CURLOPT_VERBOSE, 1); $result = curl_exec($ch); @@ -115,7 +118,6 @@ class EnjitQueueHandler extends QueueHandler return $code; } - } diff --git a/scripts/facebookqueuehandler.php b/scripts/facebookqueuehandler.php index c6859cb21..c24a22596 100755 --- a/scripts/facebookqueuehandler.php +++ b/scripts/facebookqueuehandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/facebookutil.php'); require_once(INSTALLDIR . '/lib/queuehandler.php'); @@ -35,12 +40,12 @@ set_error_handler('common_error_handler'); class FacebookQueueHandler extends QueueHandler { - + function transport() { return 'facebook'; } - + function start() { $this->log(LOG_INFO, "INITIALIZE"); @@ -51,7 +56,7 @@ class FacebookQueueHandler extends QueueHandler { return facebookBroadcastNotice($notice); } - + function finish() { } diff --git a/scripts/jabberqueuehandler.php b/scripts/jabberqueuehandler.php index 8b6e974c0..454c67f7b 100755 --- a/scripts/jabberqueuehandler.php +++ b/scripts/jabberqueuehandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/jabber.php'); require_once(INSTALLDIR . '/lib/xmppqueuehandler.php'); diff --git a/scripts/maildaemon.php b/scripts/maildaemon.php index 9dd647bf4..0b9ab0deb 100755 --- a/scripts/maildaemon.php +++ b/scripts/maildaemon.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 1) ? $argv[1] : null; +$path = ($argc > 2) ? $argv[2] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/mail.php'); require_once('Mail/mimeDecode.php'); @@ -36,7 +41,6 @@ require_once('Mail/mimeDecode.php'); class MailerDaemon { - function __construct() { } diff --git a/scripts/ombqueuehandler.php b/scripts/ombqueuehandler.php index cdcea51dc..6abc6d7f1 100755 --- a/scripts/ombqueuehandler.php +++ b/scripts/ombqueuehandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/omb.php'); require_once(INSTALLDIR . '/lib/queuehandler.php'); @@ -35,12 +40,12 @@ set_error_handler('common_error_handler'); class OmbQueueHandler extends QueueHandler { - + function transport() { return 'omb'; } - + function start() { $this->log(LOG_INFO, "INITIALIZE"); @@ -56,7 +61,7 @@ class OmbQueueHandler extends QueueHandler return omb_broadcast_remote_subscribers($notice); } } - + function finish() { } diff --git a/scripts/pingqueuehandler.php b/scripts/pingqueuehandler.php index ada6ecdba..372c550f5 100644 --- a/scripts/pingqueuehandler.php +++ b/scripts/pingqueuehandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/ping.php'); require_once(INSTALLDIR . '/lib/queuehandler.php'); diff --git a/scripts/publicqueuehandler.php b/scripts/publicqueuehandler.php index b0fa22d43..7e09454d1 100755 --- a/scripts/publicqueuehandler.php +++ b/scripts/publicqueuehandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/jabber.php'); require_once(INSTALLDIR . '/lib/xmppqueuehandler.php'); @@ -35,12 +40,12 @@ set_error_handler('common_error_handler'); class PublicQueueHandler extends XmppQueueHandler { - + function transport() { return 'public'; } - + function handle_notice($notice) { try { diff --git a/scripts/smsqueuehandler.php b/scripts/smsqueuehandler.php index 38f2f11fe..ed6dbd2ad 100755 --- a/scripts/smsqueuehandler.php +++ b/scripts/smsqueuehandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/mail.php'); require_once(INSTALLDIR . '/lib/queuehandler.php'); @@ -35,7 +40,7 @@ set_error_handler('common_error_handler'); class SmsQueueHandler extends QueueHandler { - + function transport() { return 'sms'; @@ -51,7 +56,7 @@ class SmsQueueHandler extends QueueHandler { return mail_broadcast_notice_sms($notice); } - + function finish() { } diff --git a/scripts/synctwitterfriends.php b/scripts/synctwitterfriends.php index bd08ba58d..dea3f9700 100755 --- a/scripts/synctwitterfriends.php +++ b/scripts/synctwitterfriends.php @@ -30,6 +30,11 @@ define('LACONICA', true); // Uncomment this to get useful console output //define('SCRIPT_DEBUG', true); +// Preset the server at the command line + +$server = ($argc > 1) ? $argv[1] : null; +$path = ($argc > 2) ? $argv[2] : null; + require_once(INSTALLDIR . '/lib/common.php'); // Make a lockfile diff --git a/scripts/triminboxes.php b/scripts/triminboxes.php index 0d2eaeaf0..0d545b326 100644 --- a/scripts/triminboxes.php +++ b/scripts/triminboxes.php @@ -32,6 +32,11 @@ mb_internal_encoding('UTF-8'); define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); $user = new User(); @@ -74,10 +79,10 @@ while ($user->fetch()) { $delay = 3.0 * ($finish - $start); print "Delaying $delay seconds..."; - + // Wait to let slaves catch up usleep($delay * 1000000); - + print "DONE.\n"; } diff --git a/scripts/twitterqueuehandler.php b/scripts/twitterqueuehandler.php index 7da4f1e20..8c8a59d6a 100755 --- a/scripts/twitterqueuehandler.php +++ b/scripts/twitterqueuehandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/twitter.php'); require_once(INSTALLDIR . '/lib/queuehandler.php'); @@ -35,12 +40,12 @@ set_error_handler('common_error_handler'); class TwitterQueueHandler extends QueueHandler { - + function transport() { return 'twitter'; } - + function start() { $this->log(LOG_INFO, "INITIALIZE"); @@ -51,7 +56,7 @@ class TwitterQueueHandler extends QueueHandler { return broadcast_twitter($notice); } - + function finish() { } diff --git a/scripts/twitterstatusfetcher.php b/scripts/twitterstatusfetcher.php index 20f42cef8..2863207b0 100755 --- a/scripts/twitterstatusfetcher.php +++ b/scripts/twitterstatusfetcher.php @@ -33,7 +33,12 @@ define('MAXCHILDREN', 2); define('POLL_INTERVAL', 60); // in seconds // Uncomment this to get useful logging -define('SCRIPT_DEBUG', true); +// define('SCRIPT_DEBUG', true); + +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; require_once INSTALLDIR . '/lib/common.php'; require_once INSTALLDIR . '/lib/daemon.php'; diff --git a/scripts/xmppconfirmhandler.php b/scripts/xmppconfirmhandler.php index 7f39235fe..fee902320 100755 --- a/scripts/xmppconfirmhandler.php +++ b/scripts/xmppconfirmhandler.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/jabber.php'); require_once(INSTALLDIR . '/lib/xmppqueuehandler.php'); @@ -39,12 +44,12 @@ class XmppConfirmHandler extends XmppQueueHandler { var $_id = 'confirm'; - + function class_name() { return 'XmppConfirmHandler'; } - + function run() { if (!$this->start()) { diff --git a/scripts/xmppdaemon.php b/scripts/xmppdaemon.php index b79fa1b3b..468a163d2 100755 --- a/scripts/xmppdaemon.php +++ b/scripts/xmppdaemon.php @@ -27,6 +27,11 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Preset the server at the command line + +$server = ($argc > 2) ? $argv[2] : null; +$path = ($argc > 3) ? $argv[3] : null; + require_once(INSTALLDIR . '/lib/common.php'); require_once(INSTALLDIR . '/lib/jabber.php'); require_once(INSTALLDIR . '/lib/daemon.php'); @@ -39,7 +44,6 @@ set_error_handler('common_error_handler'); class XMPPDaemon extends Daemon { - function XMPPDaemon($resource=null) { static $attrs = array('server', 'port', 'user', 'password', 'host'); -- cgit v1.2.3-54-g00ecf From 793a6a1155996a7bcdc068fc891e7063934bdb19 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 20 Jun 2009 16:00:04 -0700 Subject: change Controlez-Vous to Control Yourself --- actions/accesstoken.php | 2 +- actions/all.php | 2 +- actions/allrss.php | 2 +- actions/api.php | 2 +- actions/avatarbynickname.php | 2 +- actions/block.php | 2 +- actions/disfavor.php | 2 +- actions/doc.php | 2 +- actions/facebookhome.php | 2 +- actions/facebookinvite.php | 2 +- actions/facebooklogin.php | 2 +- actions/facebookremove.php | 2 +- actions/facebooksettings.php | 2 +- actions/favor.php | 2 +- actions/favoritesrss.php | 2 +- actions/file.php | 2 +- actions/finishopenidlogin.php | 2 +- actions/finishremotesubscribe.php | 2 +- actions/foaf.php | 2 +- actions/groupblock.php | 2 +- actions/groupsearch.php | 2 +- actions/groupunblock.php | 2 +- actions/invite.php | 2 +- actions/logout.php | 2 +- actions/makeadmin.php | 2 +- actions/microsummary.php | 2 +- actions/noticesearch.php | 2 +- actions/noticesearchrss.php | 2 +- actions/nudge.php | 2 +- actions/openidlogin.php | 2 +- actions/opensearch.php | 2 +- actions/peoplesearch.php | 2 +- actions/postnotice.php | 2 +- actions/publicrss.php | 2 +- actions/publicxrds.php | 2 +- actions/recoverpassword.php | 2 +- actions/remotesubscribe.php | 2 +- actions/repliesrss.php | 2 +- actions/requesttoken.php | 2 +- actions/subedit.php | 2 +- actions/subscribe.php | 2 +- actions/sup.php | 2 +- actions/tag.php | 2 +- actions/tagother.php | 2 +- actions/tagrss.php | 2 +- actions/twitapiaccount.php | 2 +- actions/twitapiblocks.php | 2 +- actions/twitapidirect_messages.php | 2 +- actions/twitapifavorites.php | 2 +- actions/twitapifriendships.php | 2 +- actions/twitapihelp.php | 2 +- actions/twitapinotifications.php | 2 +- actions/twitapistatuses.php | 2 +- actions/twitapiusers.php | 2 +- actions/unblock.php | 2 +- actions/unsubscribe.php | 2 +- actions/updateprofile.php | 2 +- actions/userauthorization.php | 2 +- actions/userbyid.php | 2 +- actions/userrss.php | 2 +- actions/xrds.php | 2 +- classes/File.php | 2 +- classes/File_oembed.php | 2 +- classes/File_redirection.php | 2 +- classes/File_thumbnail.php | 2 +- classes/File_to_post.php | 2 +- classes/Group_block.php | 2 +- classes/Memcached_DataObject.php | 2 +- classes/Notice.php | 2 +- classes/Notice_tag.php | 2 +- classes/Profile.php | 2 +- classes/Profile_block.php | 2 +- classes/Remote_profile.php | 2 +- classes/Subscription.php | 2 +- index.php | 2 +- install.php | 2 +- lib/Shorturl_api.php | 2 +- lib/arraywrapper.php | 2 +- lib/channel.php | 2 +- lib/clienterroraction.php | 2 +- lib/command.php | 2 +- lib/commandinterpreter.php | 2 +- lib/common.php | 2 +- lib/daemon.php | 2 +- lib/dberroraction.php | 2 +- lib/error.php | 2 +- lib/facebookutil.php | 2 +- lib/galleryaction.php | 2 +- lib/oauthstore.php | 2 +- lib/omb.php | 2 +- lib/openid.php | 2 +- lib/peoplesearchresults.php | 2 +- lib/queuehandler.php | 2 +- lib/search_engines.php | 2 +- lib/searchaction.php | 2 +- lib/servererroraction.php | 2 +- lib/subs.php | 2 +- lib/twitter.php | 2 +- lib/twitterapi.php | 2 +- lib/util.php | 2 +- lib/xmppqueuehandler.php | 2 +- scripts/enjitqueuehandler.php | 2 +- scripts/facebookqueuehandler.php | 2 +- scripts/fixup_hashtags.php | 2 +- scripts/fixup_inboxes.php | 2 +- scripts/fixup_notices_rendered.php | 2 +- scripts/fixup_replies.php | 2 +- scripts/getpiddir.php | 2 +- scripts/getvaliddaemons.php | 2 +- scripts/inbox_users.php | 2 +- scripts/jabberqueuehandler.php | 2 +- scripts/maildaemon.php | 2 +- scripts/ombqueuehandler.php | 2 +- scripts/pingqueuehandler.php | 2 +- scripts/publicqueuehandler.php | 2 +- scripts/setpassword.php | 2 +- scripts/smsqueuehandler.php | 2 +- scripts/sphinx-cron.sh | 2 +- scripts/sphinx-indexer.sh | 2 +- scripts/startdaemons.sh | 2 +- scripts/stopdaemons.sh | 2 +- scripts/synctwitterfriends.php | 2 +- scripts/twitterqueuehandler.php | 2 +- scripts/twitterstatusfetcher.php | 2 +- scripts/uncache_users.php | 2 +- scripts/xmppconfirmhandler.php | 2 +- scripts/xmppdaemon.php | 2 +- 127 files changed, 127 insertions(+), 127 deletions(-) (limited to 'lib') diff --git a/actions/accesstoken.php b/actions/accesstoken.php index 46b43c702..01aa77574 100644 --- a/actions/accesstoken.php +++ b/actions/accesstoken.php @@ -12,7 +12,7 @@ * @link http://laconi.ca/ * * Laconica - a distributed open-source microblogging tool - * Copyright (C) 2008, Controlez-Vous, Inc. + * Copyright (C) 2008, Control Yourself, 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 diff --git a/actions/all.php b/actions/all.php index 80fc9d54b..f436fabd1 100644 --- a/actions/all.php +++ b/actions/all.php @@ -1,7 +1,7 @@ Date: Sat, 20 Jun 2009 16:12:55 -0700 Subject: Update copyright dates in files modified in 2009 --- actions/accesstoken.php | 2 +- actions/all.php | 2 +- actions/allrss.php | 2 +- actions/api.php | 2 +- actions/avatarbynickname.php | 2 +- actions/block.php | 2 +- actions/disfavor.php | 2 +- actions/doc.php | 2 +- actions/facebookhome.php | 2 +- actions/facebookinvite.php | 2 +- actions/facebooklogin.php | 2 +- actions/facebookremove.php | 2 +- actions/facebooksettings.php | 2 +- actions/favor.php | 2 +- actions/favoritesrss.php | 2 +- actions/file.php | 2 +- actions/finishopenidlogin.php | 2 +- actions/finishremotesubscribe.php | 2 +- actions/foaf.php | 2 +- actions/groupblock.php | 2 +- actions/groupsearch.php | 2 +- actions/groupunblock.php | 2 +- actions/invite.php | 2 +- actions/logout.php | 2 +- actions/makeadmin.php | 2 +- actions/microsummary.php | 2 +- actions/noticesearch.php | 2 +- actions/noticesearchrss.php | 2 +- actions/nudge.php | 2 +- actions/openidlogin.php | 2 +- actions/opensearch.php | 2 +- actions/peoplesearch.php | 2 +- actions/postnotice.php | 2 +- actions/publicrss.php | 2 +- actions/publicxrds.php | 2 +- actions/recoverpassword.php | 2 +- actions/remotesubscribe.php | 2 +- actions/repliesrss.php | 2 +- actions/requesttoken.php | 2 +- actions/subedit.php | 2 +- actions/subscribe.php | 2 +- actions/sup.php | 2 +- actions/tag.php | 2 +- actions/tagother.php | 2 +- actions/tagrss.php | 2 +- actions/twitapiaccount.php | 2 +- actions/twitapiblocks.php | 2 +- actions/twitapidirect_messages.php | 2 +- actions/twitapifavorites.php | 2 +- actions/twitapifriendships.php | 2 +- actions/twitapihelp.php | 2 +- actions/twitapinotifications.php | 2 +- actions/twitapistatuses.php | 2 +- actions/twitapiusers.php | 2 +- actions/unblock.php | 2 +- actions/unsubscribe.php | 2 +- actions/updateprofile.php | 2 +- actions/userauthorization.php | 2 +- actions/userbyid.php | 2 +- actions/userrss.php | 2 +- actions/xrds.php | 2 +- classes/File.php | 2 +- classes/File_oembed.php | 2 +- classes/File_redirection.php | 2 +- classes/File_thumbnail.php | 2 +- classes/File_to_post.php | 2 +- classes/Group_block.php | 2 +- classes/Memcached_DataObject.php | 2 +- classes/Notice.php | 2 +- classes/Notice_tag.php | 2 +- classes/Profile.php | 2 +- classes/Profile_block.php | 2 +- classes/Remote_profile.php | 2 +- classes/Subscription.php | 2 +- index.php | 2 +- lib/Shorturl_api.php | 2 +- lib/arraywrapper.php | 2 +- lib/channel.php | 2 +- lib/clienterroraction.php | 2 +- lib/command.php | 2 +- lib/commandinterpreter.php | 2 +- lib/common.php | 2 +- lib/daemon.php | 2 +- lib/dberroraction.php | 2 +- lib/error.php | 2 +- lib/facebookutil.php | 2 +- lib/galleryaction.php | 2 +- lib/oauthstore.php | 2 +- lib/omb.php | 2 +- lib/openid.php | 2 +- lib/peoplesearchresults.php | 2 +- lib/queuehandler.php | 2 +- lib/search_engines.php | 2 +- lib/searchaction.php | 2 +- lib/servererroraction.php | 2 +- lib/subs.php | 2 +- lib/twitter.php | 2 +- lib/twitterapi.php | 2 +- lib/util.php | 2 +- lib/xmppqueuehandler.php | 2 +- scripts/enjitqueuehandler.php | 2 +- scripts/facebookqueuehandler.php | 2 +- scripts/fixup_hashtags.php | 2 +- scripts/fixup_inboxes.php | 2 +- scripts/fixup_notices_rendered.php | 2 +- scripts/fixup_replies.php | 2 +- scripts/getpiddir.php | 2 +- scripts/getvaliddaemons.php | 2 +- scripts/inbox_users.php | 2 +- scripts/jabberqueuehandler.php | 2 +- scripts/maildaemon.php | 2 +- scripts/ombqueuehandler.php | 2 +- scripts/pingqueuehandler.php | 2 +- scripts/publicqueuehandler.php | 2 +- scripts/setpassword.php | 2 +- scripts/smsqueuehandler.php | 2 +- scripts/sphinx-cron.sh | 2 +- scripts/sphinx-indexer.sh | 2 +- scripts/startdaemons.sh | 2 +- scripts/stopdaemons.sh | 2 +- scripts/synctwitterfriends.php | 2 +- scripts/twitterqueuehandler.php | 2 +- scripts/twitterstatusfetcher.php | 2 +- scripts/uncache_users.php | 2 +- scripts/xmppconfirmhandler.php | 2 +- scripts/xmppdaemon.php | 2 +- 126 files changed, 126 insertions(+), 126 deletions(-) (limited to 'lib') diff --git a/actions/accesstoken.php b/actions/accesstoken.php index 01aa77574..2a8cd1713 100644 --- a/actions/accesstoken.php +++ b/actions/accesstoken.php @@ -12,7 +12,7 @@ * @link http://laconi.ca/ * * Laconica - a distributed open-source microblogging tool - * Copyright (C) 2008, Control Yourself, Inc. + * Copyright (C) 2008, 2009, Control Yourself, 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 diff --git a/actions/all.php b/actions/all.php index f436fabd1..f06ead2a8 100644 --- a/actions/all.php +++ b/actions/all.php @@ -1,7 +1,7 @@ Date: Sun, 21 Jun 2009 11:11:12 -0700 Subject: add collecta.com link --- lib/searchaction.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/searchaction.php b/lib/searchaction.php index bb2d50572..34fe9373f 100644 --- a/lib/searchaction.php +++ b/lib/searchaction.php @@ -148,10 +148,10 @@ You can also try your search on other engines: * [Tweet scan](http://www.tweetscan.com/indexi.php?s=%s) * [Google](http://www.google.com/search?q=site%%3A%%%%site.server%%%%+%s) * [Yahoo](http://search.yahoo.com/search?p=site%%3A%%%%site.server%%%%+%s) - +* [Collecta](http://collecta.com/#q=%s) E_O_T -), $qe, $qe, $qe, $qe); +), $qe, $qe, $qe, $qe, $qe); $this->elementStart('dl', array('id' => 'help_search', 'class' => 'help')); $this->element('dt', null, _('Search help')); $this->elementStart('dd', 'instructions'); -- cgit v1.2.3-54-g00ecf From 02a4ca9e2ea46cb82829dc65e76efc36b0ec470b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 21 Jun 2009 21:38:16 -0700 Subject: got rid of 'skin' concept a while ago --- lib/common.php | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/common.php b/lib/common.php index a4da25157..361759d0a 100644 --- a/lib/common.php +++ b/lib/common.php @@ -83,7 +83,6 @@ $config = array('name' => 'Just another Laconica microblog', 'server' => $_server, 'theme' => 'default', - 'skin' => 'default', 'design' => array('backgroundcolor' => '#F0F2F5', 'contentcolor' => '#FFFFFF', -- cgit v1.2.3-54-g00ecf From 876ab059273a5f223170d6b2c0b9b4342b06c50f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 21 Jun 2009 21:50:35 -0700 Subject: Add like for search --- README | 13 ++++++++++++- classes/Memcached_DataObject.php | 9 ++++++++- lib/common.php | 4 +++- lib/search_engines.php | 22 ++++++++++++++++++++++ 4 files changed, 45 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/README b/README index 5aa7270ee..0c500acb8 100644 --- a/README +++ b/README @@ -1247,7 +1247,6 @@ Options for group functionality. maxaliases: maximum number of aliases a group can have. Default 3. Set to 0 or less to prevent aliases in a group. - oohembed -------- @@ -1255,6 +1254,18 @@ oEmbed endpoint for multimedia attachments (links in posts). endpoint: oohembed endpoint using http://oohembed.com/ software. +search +------ + +Some stuff for search. + +type: type of search. Ignored if PostgreSQL or Sphinx are enabled. Can either + be 'fulltext' (default) or 'like'. The former is faster and more efficient + but requires the lame old MyISAM engine for MySQL. The latter + will work with InnoDB but could be miserably slow on large + systems. We'll probably add another type sometime in the future, + with our own indexing system (maybe like MediaWiki's). + Troubleshooting =============== diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 2d5a73554..f7cbb9d5b 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -193,7 +193,14 @@ class Memcached_DataObject extends DB_DataObject // unable to connect to sphinx' search daemon if (!$connected) { if ('mysql' === common_config('db', 'type')) { - $search_engine = new MySQLSearch($this, $table); + $type = common_config('search', 'type'); + if ($type == 'like') { + $search_engine = new MySQLLikeSearch($this, $table); + } else if ($type == 'fulltext') { + $search_engine = new MySQLSearch($this, $table); + } else { + throw new ServerException('Unknown search type: ' . $type); + } } else { $search_engine = new PGSearch($this, $table); } diff --git a/lib/common.php b/lib/common.php index 361759d0a..14f5c7a7f 100644 --- a/lib/common.php +++ b/lib/common.php @@ -228,7 +228,9 @@ $config = ), 'group' => array('maxaliases' => 3), - 'oohembed' => array('endpoint' => 'http://oohembed.com/oohembed/') + 'oohembed' => array('endpoint' => 'http://oohembed.com/oohembed/'), + 'search' => + array('type' => 'fulltext'), ); $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); diff --git a/lib/search_engines.php b/lib/search_engines.php index c98e8ed87..5c84d7c6b 100644 --- a/lib/search_engines.php +++ b/lib/search_engines.php @@ -131,6 +131,28 @@ class MySQLSearch extends SearchEngine } } +class MySQLLikeSearch extends SearchEngine +{ + function query($q) + { + if ('identica_people' === $this->table) { + $qry = sprintf('(nickname LIKE "%%%1$s%%" OR '. + ' fullname LIKE "%%%1$s%%" OR '. + ' location LIKE "%%%1$s%%" OR '. + ' bio LIKE "%%%1$s%%" OR '. + ' homepage LIKE "%%%1$s%%")', addslashes($q)); + } else if ('identica_notices' === $this->table) { + $qry = sprintf('content LIKE "%%%1$s%%"', addslashes($q)); + } else { + throw new ServerException('Unknown table: ' . $this->table); + } + + $this->target->whereAdd($qry); + + return true; + } +} + class PGSearch extends SearchEngine { function query($q) -- cgit v1.2.3-54-g00ecf From 7cf0a4c6472ab05a0963c003d8c3ecb59237ee67 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 09:31:55 -0700 Subject: theme dir, path configurable --- README | 13 ++++++++++--- lib/common.php | 4 +++- lib/theme.php | 36 +++++++++++++++++++++++++++++------- 3 files changed, 42 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/README b/README index 0c500acb8..cd663d931 100644 --- a/README +++ b/README @@ -1039,9 +1039,16 @@ theme ----- server: Like avatars, you can speed up page loading by pointing the - theme file lookup to another server (virtual or real). The - theme server's root path should map to the Laconica "theme" - subdirectory. Defaults to NULL. + theme file lookup to another server (virtual or real). + Defaults to NULL, meaning to use the site server. +dir: Directory where theme files are stored. Used to determine + whether to show parts of a theme file. Defaults to the theme + subdirectory of the install directory. +path: Path part of theme URLs, before the theme name. Relative to the + theme server. It may make sense to change this path when upgrading, + (using version numbers as the path) to make sure that all files are + reloaded by caching clients or proxies. Defaults to null, + which means to use the site path + '/theme'. xmpp ---- diff --git a/lib/common.php b/lib/common.php index 14f5c7a7f..0333030e1 100644 --- a/lib/common.php +++ b/lib/common.php @@ -140,7 +140,9 @@ $config = 'blacklist' => array(), 'autosource' => array()), 'theme' => - array('server' => null), + array('server' => null, + 'dir' => null, + 'path'=> null), 'throttle' => array('enabled' => false, // whether to throttle edits; false by default 'count' => 20, // number of allowed messages in timespan diff --git a/lib/theme.php b/lib/theme.php index 0d8824822..2fe6ab69b 100644 --- a/lib/theme.php +++ b/lib/theme.php @@ -43,10 +43,14 @@ if (!defined('LACONICA')) { function theme_file($relative, $theme=null) { - if (!$theme) { + if (empty($theme)) { $theme = common_config('site', 'theme'); } - return INSTALLDIR.'/theme/'.$theme.'/'.$relative; + $dir = common_config('theme', 'dir'); + if (empty($dir)) { + $dir = INSTALLDIR.'/theme'; + } + return $dir.'/'.$theme.'/'.$relative; } /** @@ -60,13 +64,31 @@ function theme_file($relative, $theme=null) function theme_path($relative, $theme=null) { - if (!$theme) { + if (empty($theme)) { $theme = common_config('site', 'theme'); } + + $path = common_config('theme', 'path'); + + if (empty($path)) { + $path = common_config('site', 'path') . '/theme/'; + } + + if ($path[strlen($path)-1] != '/') { + $path .= '/'; + } + + if ($path[0] != '/') { + $path = '/'.$path; + } + $server = common_config('theme', 'server'); - if ($server) { - return 'http://'.$server.'/'.$theme.'/'.$relative; - } else { - return common_path('theme/'.$theme.'/'.$relative); + + if (empty($server)) { + $server = common_config('site', 'server'); } + + // XXX: protocol + + return 'http://'.$server.$path.$theme.'/'.$relative; } -- cgit v1.2.3-54-g00ecf From 09e24af6832d6a4ce5605be23e3469c5b33a3efe Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 22 Jun 2009 21:36:04 +0000 Subject: Add upload location to attachments config section --- lib/common.php | 67 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 32 deletions(-) (limited to 'lib') diff --git a/lib/common.php b/lib/common.php index 0333030e1..b773f5f89 100644 --- a/lib/common.php +++ b/lib/common.php @@ -191,38 +191,41 @@ $config = array('run' => 'web', 'frequency' => 10000, 'reporturl' => 'http://laconi.ca/stats/report'), - 'attachments' => - array('supported' => array('image/png', - 'image/jpeg', - 'image/gif', - 'image/svg+xml', - 'audio/mpeg', - 'audio/x-speex', - 'application/ogg', - 'application/pdf', - 'application/vnd.oasis.opendocument.text', - 'application/vnd.oasis.opendocument.text-template', - 'application/vnd.oasis.opendocument.graphics', - 'application/vnd.oasis.opendocument.graphics-template', - 'application/vnd.oasis.opendocument.presentation', - 'application/vnd.oasis.opendocument.presentation-template', - 'application/vnd.oasis.opendocument.spreadsheet', - 'application/vnd.oasis.opendocument.spreadsheet-template', - 'application/vnd.oasis.opendocument.chart', - 'application/vnd.oasis.opendocument.chart-template', - 'application/vnd.oasis.opendocument.image', - 'application/vnd.oasis.opendocument.image-template', - 'application/vnd.oasis.opendocument.formula', - 'application/vnd.oasis.opendocument.formula-template', - 'application/vnd.oasis.opendocument.text-master', - 'application/vnd.oasis.opendocument.text-web', - 'application/x-zip', - 'application/zip', - 'text/plain', - 'video/mpeg', - 'video/mp4', - 'video/quicktime', - 'video/mpeg'), + 'attachments' => + array('server' => null, + 'dir' => INSTALLDIR . '/file/', + 'path' => $_path . '/file/', + 'supported' => array('image/png', + 'image/jpeg', + 'image/gif', + 'image/svg+xml', + 'audio/mpeg', + 'audio/x-speex', + 'application/ogg', + 'application/pdf', + 'application/vnd.oasis.opendocument.text', + 'application/vnd.oasis.opendocument.text-template', + 'application/vnd.oasis.opendocument.graphics', + 'application/vnd.oasis.opendocument.graphics-template', + 'application/vnd.oasis.opendocument.presentation', + 'application/vnd.oasis.opendocument.presentation-template', + 'application/vnd.oasis.opendocument.spreadsheet', + 'application/vnd.oasis.opendocument.spreadsheet-template', + 'application/vnd.oasis.opendocument.chart', + 'application/vnd.oasis.opendocument.chart-template', + 'application/vnd.oasis.opendocument.image', + 'application/vnd.oasis.opendocument.image-template', + 'application/vnd.oasis.opendocument.formula', + 'application/vnd.oasis.opendocument.formula-template', + 'application/vnd.oasis.opendocument.text-master', + 'application/vnd.oasis.opendocument.text-web', + 'application/x-zip', + 'application/zip', + 'text/plain', + 'video/mpeg', + 'video/mp4', + 'video/quicktime', + 'video/mpeg'), 'file_quota' => 5000000, 'user_quota' => 50000000, 'monthly_quota' => 15000000, -- cgit v1.2.3-54-g00ecf From 9171f16b730176717b0b9abf84ace10b7a6dddc7 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 22 Jun 2009 15:29:24 -0700 Subject: add commandline.inc for parsing --- lib/common.php | 16 +++++--- scripts/commandline.inc | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 scripts/commandline.inc (limited to 'lib') diff --git a/lib/common.php b/lib/common.php index a8c7634f6..2327dcb0e 100644 --- a/lib/common.php +++ b/lib/common.php @@ -269,14 +269,18 @@ if (function_exists('date_default_timezone_set')) { // server-wide, then vhost-wide, then for a path, // finally for a dir (usually only need one of the last two). -$_config_files = array('/etc/laconica/laconica.php', - '/etc/laconica/'.$_server.'.php'); +if (isset($conffile)) { + $_config_files = array($conffile); +} else { + $_config_files = array('/etc/laconica/laconica.php', + '/etc/laconica/'.$_server.'.php'); -if (strlen($_path) > 0) { - $_config_files[] = '/etc/laconica/'.$_server.'_'.$_path.'.php'; -} + if (strlen($_path) > 0) { + $_config_files[] = '/etc/laconica/'.$_server.'_'.$_path.'.php'; + } -$_config_files[] = INSTALLDIR.'/config.php'; + $_config_files[] = INSTALLDIR.'/config.php'; +} $_have_a_config = false; diff --git a/scripts/commandline.inc b/scripts/commandline.inc new file mode 100644 index 000000000..292005dca --- /dev/null +++ b/scripts/commandline.inc @@ -0,0 +1,107 @@ +. + */ + +// -*- mode: php -*- + +# Abort if called from a web server + +if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { + print "This script must be run from the command line\n"; + exit(); +} + +define('LACONICA', true); + +// Set various flags so we don't time out on long-running processes + +ini_set("max_execution_time", "0"); +ini_set("max_input_time", "0"); +set_time_limit(0); +mb_internal_encoding('UTF-8'); + +// Add extlib to our path so we can get Console_Getopt + +$_extra_path = array(INSTALLDIR.'/extlib/'); + +set_include_path(implode(PATH_SEPARATOR, $_extra_path) . PATH_SEPARATOR . get_include_path()); + +require_once 'Console/Getopt.php'; + +// Note: $shortoptions and $longoptions should be pre-defined! + +$_default_shortoptions = 'qvhc:s:p:'; + +$_default_longoptions = array('quiet', 'verbose', 'help', 'conf=', 'server=', 'path='); + +if (isset($shortoptions)) { + $shortoptions .= $_default_shortoptions; +} else { + $shortoptions = $_default_shortoptions; +} + +if (isset($longoptions)) { + $longoptions = array_merge($longoptions, $_default_longoptions); +} else { + $longoptions = $_default_longoptions; +} + +$parser = new Console_Getopt(); + +list($options, $args) = $parser->getopt($argv, $shortoptions, $longoptions); + +foreach ($options as $option) { + + switch ($option[0]) { + case '--server': + case '-s': + $server = $option[1]; + break; + + case '--path': + case '-p': + $path = $option[1]; + break; + + case '--conf': + case '-c': + $conffile = $option[1]; + break; + + case '--help': + case '-h': + $_default_help_text = << Use as config file + -s --server= Use as server name + -p --path= Use as path name + -h --help Show this message and quit. + +END_OF_DEFAULT; + if (isset($helptext)) { + print $helptext; + } + print $_default_help_text; + exit(0); + } +} + +require_once INSTALLDIR . '/lib/common.php'; -- cgit v1.2.3-54-g00ecf From 7bcaa858af31c5c496bc5adc0c73ec333d4c1e63 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 05:35:20 -0700 Subject: make file command configurable --- README | 4 ++++ actions/newnotice.php | 3 +++ lib/common.php | 3 ++- 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/README b/README index de1099600..1a57d6a80 100644 --- a/README +++ b/README @@ -1232,6 +1232,10 @@ supported: an array of mime types you accept to store and distribute, setup your server to properly reckognize the types you want to support. uploads: false to disable uploading files with notices (true by default). +filecommand: The required MIME_Type library may need to use the 'file' + command. It tries the one in the Web server's path, but if + you're having problems with uploads, try setting this to the + correct value. Note: 'file' must accept '-b' and '-i' options. For quotas, be sure you've set the upload_max_filesize and post_max_size in php.ini to be large enough to handle your upload. In httpd.conf diff --git a/actions/newnotice.php b/actions/newnotice.php index 09652d2b3..b7d9ec1dd 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -116,6 +116,9 @@ class NewnoticeAction extends Action function getUploadedFileType() { require_once 'MIME/Type.php'; + $cmd = &PEAR::getStaticProperty('MIME_Type', 'fileCmd'); + $cmd = common_config('attachments', 'filecommand'); + $filetype = MIME_Type::autoDetect($_FILES['attach']['tmp_name']); if (in_array($filetype, common_config('attachments', 'supported'))) { return $filetype; diff --git a/lib/common.php b/lib/common.php index 20f1ab35e..76eb4a978 100644 --- a/lib/common.php +++ b/lib/common.php @@ -202,7 +202,7 @@ $config = array('run' => 'web', 'frequency' => 10000, 'reporturl' => 'http://laconi.ca/stats/report'), - 'attachments' => + 'attachments' => array('server' => null, 'dir' => INSTALLDIR . '/file/', 'path' => $_path . '/file/', @@ -241,6 +241,7 @@ $config = 'user_quota' => 50000000, 'monthly_quota' => 15000000, 'uploads' => true, + 'filecommand' => '/usr/bin/file', ), 'group' => array('maxaliases' => 3), -- cgit v1.2.3-54-g00ecf From e2becdb25138350170b58ae8f0d1ecd715533cf5 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 07:25:18 -0700 Subject: use a subclass for single notice items to show attachments --- actions/shownotice.php | 28 +++++++++++++++++++++++++++- lib/noticelist.php | 13 ------------- 2 files changed, 27 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/actions/shownotice.php b/actions/shownotice.php index b0d973a99..0d89af5ac 100644 --- a/actions/shownotice.php +++ b/actions/shownotice.php @@ -209,7 +209,7 @@ class ShownoticeAction extends Action function showContent() { $this->elementStart('ol', array('class' => 'notices xoxo')); - $nli = new NoticeListItem($this->notice, $this); + $nli = new SingleNoticeItem($this->notice, $this); $nli->show(); $this->elementEnd('ol'); } @@ -264,3 +264,29 @@ class ShownoticeAction extends Action } } } + +class SingleNoticeItem extends NoticeListItem +{ + /** + * recipe function for displaying a single notice. + * + * We overload to show attachments. + * + * @return void + */ + + function show() + { + $this->showStart(); + $this->showNotice(); + $this->showNoticeAttachments(); + $this->showNoticeInfo(); + $this->showNoticeOptions(); + $this->showEnd(); + } + + function showNoticeAttachments() { + $al = new AttachmentList($this->notice, $this->out); + $al->show(); + } +} diff --git a/lib/noticelist.php b/lib/noticelist.php index ad792441a..bd4815cd6 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -179,7 +179,6 @@ class NoticeListItem extends Widget { $this->showStart(); $this->showNotice(); - $this->showNoticeAttachments(); $this->showNoticeInfo(); $this->showNoticeOptions(); $this->showEnd(); @@ -193,18 +192,6 @@ class NoticeListItem extends Widget $this->out->elementEnd('div'); } - function showNoticeAttachments() { - if ($this->isUsedInList()) { - return; - } - $al = new AttachmentList($this->notice, $this->out); - $al->show(); - } - - function isUsedInList() { - return 'shownotice' !== $this->out->args['action']; - } - function showNoticeInfo() { $this->out->elementStart('div', 'entry-content'); -- cgit v1.2.3-54-g00ecf From a21a9f26c5f0eb034ea389659dd63ffad400de5b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 23 Jun 2009 07:29:43 -0700 Subject: append uploads to content rather than showing them double --- actions/newnotice.php | 104 +++++++++++++++++++++++++++++++++---------- classes/File.php | 67 +++++++++++++++------------- classes/File_redirection.php | 70 +++-------------------------- lib/noticelist.php | 4 -- lib/util.php | 65 +++++++++++++++++++++++++++ 5 files changed, 186 insertions(+), 124 deletions(-) (limited to 'lib') diff --git a/actions/newnotice.php b/actions/newnotice.php index b7d9ec1dd..a5f87d1be 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -224,16 +224,40 @@ class NewnoticeAction extends Action } } + if (isset($mimetype)) { + $filename = $this->saveFile($mimetype); + if (empty($filename)) { + $this->clientError(_('Couldn\'t save file.')); + } + $fileurl = File::url($filename); + $short_fileurl = common_shorten_url($fileurl); + $content_shortened .= ' ' . $short_fileurl; + if (mb_strlen($content_shortened) > 140) { + $this->deleteFile($filename); + $this->clientError(_('Max notice size is 140 chars, including attachment URL.')); + } + } + + common_debug("newnotice.php - before Notice::saveNew()"); + $notice = Notice::saveNew($user->id, $content_shortened, 'web', 1, ($replyto == 'false') ? null : $replyto); + common_debug("newnotice.php - after Notice::saveNew()"); + if (is_string($notice)) { + if (isset($filename)) { + $this->deleteFile($filename); + } $this->clientError($notice); } + common_debug("newnotice.php - after Notice::saveNew()"); + if (isset($mimetype)) { - $this->storeFile($notice, $mimetype); + $this->attachFile($notice, $filename, $mimetype, $short_fileurl); } + common_broadcast_notice($notice); if ($this->boolean('ajax')) { @@ -259,7 +283,13 @@ class NewnoticeAction extends Action } } - function storeFile($notice, $mimetype) { + function saveFile($mimetype) { + + $cur = common_current_user(); + + if (empty($cur)) { + $this->serverError(_('Somehow lost the login in saveFile')); + } common_debug("NewnoticeAction::storeFile()"); @@ -267,7 +297,7 @@ class NewnoticeAction extends Action common_debug("Basename: $basename"); - $filename = File::filename($notice->id, $basename); + $filename = File::filename($cur->getProfile(), $basename, $mimetype); common_debug("filename: $filename"); @@ -276,33 +306,59 @@ class NewnoticeAction extends Action common_debug("filepath: $filepath"); if (move_uploaded_file($_FILES['attach']['tmp_name'], $filepath)) { + return $filename; + } else { + $this->clientError(_('File could not be moved to destination directory.')); + } + } - $file = new File; - $file->filename = $filename; + function deleteFile($filename) + { + $filepath = File::path($filename); + @unlink($filepath); + } - $file->url = common_local_url('file', array('notice' => $notice->id)); + function attachFile($notice, $filename, $mimetype, $short) + { + $file = new File; + $file->filename = $filename; - common_debug("file->url =". $file->url); + $file->url = common_local_url('file', array('notice' => $notice->id)); - $file->size = filesize($filepath); - $file->date = time(); - $file->mimetype = $mimetype; + common_debug("file->url =". $file->url); - if ($file_id = $file->insert()) { - $file_redir = new File_redirection; - $file_redir->url = File::url($filename); - $file_redir->file_id = $file_id; - $file_redir->insert(); + $filepath = File::path($filename); - $f2p = new File_to_post; - $f2p->file_id = $file_id; - $f2p->post_id = $notice->id; - $f2p->insert(); - } else { - $this->clientError(_('There was a database error while saving your file. Please try again.')); - } - } else { - $this->clientError(_('File could not be moved to destination directory.')); + $file->size = filesize($filepath); + $file->date = time(); + $file->mimetype = $mimetype; + + $file_id = $file->insert(); + + if (!$file_id) { + common_log_db_error($file, "INSERT", __FILE__); + $this->clientError(_('There was a database error while saving your file. Please try again.')); + } + + $file_redir = new File_redirection; + $file_redir->url = File::url($filename); + $file_redir->file_id = $file_id; + + $result = $file_redir->insert(); + + if (!$result) { + common_log_db_error($file_redir, "INSERT", __FILE__); + $this->clientError(_('There was a database error while saving your file. Please try again.')); + } + + $f2p = new File_to_post; + $f2p->file_id = $file_id; + $f2p->post_id = $notice->id; + $f2p->insert(); + + if (!$result) { + common_log_db_error($f2p, "INSERT", __FILE__); + $this->clientError(_('There was a database error while saving your file. Please try again.')); } } diff --git a/classes/File.php b/classes/File.php index 1de136240..b98c9e665 100644 --- a/classes/File.php +++ b/classes/File.php @@ -124,8 +124,8 @@ class File extends Memcached_DataObject function isRespectsQuota($user) { if ($_FILES['attach']['size'] > common_config('attachments', 'file_quota')) { return sprintf(_('No file may be larger than %d bytes ' . - 'and the file you sent was %d bytes. Try to upload a smaller version.'), - common_config('attachments', 'file_quota'), $_FILES['attach']['size']); + 'and the file you sent was %d bytes. Try to upload a smaller version.'), + common_config('attachments', 'file_quota'), $_FILES['attach']['size']); } $query = "select sum(size) as total from file join file_to_post on file_to_post.file_id = file.id join notice on file_to_post.post_id = notice.id where profile_id = {$user->id} and file.url like '%/notice/%/file'"; @@ -148,44 +148,49 @@ class File extends Memcached_DataObject // where should the file go? - static function filename($notice_id, $basename) - { - return $notice_id . '-' . $basename; - } - - static function path($filename) - { - $dir = common_config('attachments', 'dir'); + static function filename($profile, $basename, $mimetype) + { + require_once 'MIME/Type/Extension.php'; + $mte = new MIME_Type_Extension(); + $ext = $mte->getExtension($mimetype); + $nickname = $profile->nickname; + $datestamp = strftime('%Y%m%dT%H%M%S', time()); + $random = strtolower(common_confirmation_code(32)); + return "$nickname-$datestamp-$random.$ext"; + } - if ($dir[strlen($dir)-1] != '/') { - $dir .= '/'; - } + static function path($filename) + { + $dir = common_config('attachments', 'dir'); - return $dir . $filename; - } + if ($dir[strlen($dir)-1] != '/') { + $dir .= '/'; + } - static function url($filename) - { - $path = common_config('attachments', 'path'); + return $dir . $filename; + } - if ($path[strlen($path)-1] != '/') { - $path .= '/'; - } + static function url($filename) + { + $path = common_config('attachments', 'path'); - if ($path[0] != '/') { - $path = '/'.$path; - } + if ($path[strlen($path)-1] != '/') { + $path .= '/'; + } - $server = common_config('attachments', 'server'); + if ($path[0] != '/') { + $path = '/'.$path; + } - if (empty($server)) { - $server = common_config('site', 'server'); - } + $server = common_config('attachments', 'server'); - // XXX: protocol + if (empty($server)) { + $server = common_config('site', 'server'); + } - return 'http://'.$server.$path.$filename; - } + // XXX: protocol + return 'http://'.$server.$path.$filename; + } } diff --git a/classes/File_redirection.php b/classes/File_redirection.php index edd915c1e..c173017e2 100644 --- a/classes/File_redirection.php +++ b/classes/File_redirection.php @@ -25,21 +25,20 @@ require_once INSTALLDIR.'/classes/File_oembed.php'; define('USER_AGENT', 'Laconica user agent / file probe'); - /** * Table Definition for file_redirection */ -class File_redirection extends Memcached_DataObject +class File_redirection extends Memcached_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ public $__table = 'file_redirection'; // table name public $url; // varchar(255) primary_key not_null - public $file_id; // int(4) - public $redirections; // int(4) - public $httpcode; // int(4) + public $file_id; // int(4) + public $redirections; // int(4) + public $httpcode; // int(4) public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP /* Static get */ @@ -48,8 +47,6 @@ class File_redirection extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE - - function _commonCurl($url, $redirs) { $curlh = curl_init(); curl_setopt($curlh, CURLOPT_URL, $url); @@ -86,8 +83,6 @@ class File_redirection extends Memcached_DataObject return $url; } - - $curlh = File_redirection::_commonCurl($short_url, $redirs); // Don't include body in output curl_setopt($curlh, CURLOPT_NOBODY, true); @@ -143,62 +138,7 @@ class File_redirection extends Memcached_DataObject } function _userMakeShort($long_url, $user) { - if (empty($user)) { - // common current user does not find a user when called from the XMPP daemon - // therefore we'll set one here fix, so that XMPP given URLs may be shortened - $user->urlshorteningservice = 'ur1.ca'; - } - $curlh = curl_init(); - curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait - curl_setopt($curlh, CURLOPT_USERAGENT, 'Laconica'); - curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true); - - switch($user->urlshorteningservice) { - case 'ur1.ca': - require_once INSTALLDIR.'/lib/Shorturl_api.php'; - $short_url_service = new LilUrl; - $short_url = $short_url_service->shorten($long_url); - break; - - case '2tu.us': - $short_url_service = new TightUrl; - require_once INSTALLDIR.'/lib/Shorturl_api.php'; - $short_url = $short_url_service->shorten($long_url); - break; - - case 'ptiturl.com': - require_once INSTALLDIR.'/lib/Shorturl_api.php'; - $short_url_service = new PtitUrl; - $short_url = $short_url_service->shorten($long_url); - break; - - case 'bit.ly': - curl_setopt($curlh, CURLOPT_URL, 'http://bit.ly/api?method=shorten&long_url='.urlencode($long_url)); - $short_url = current(json_decode(curl_exec($curlh))->results)->hashUrl; - break; - - case 'is.gd': - curl_setopt($curlh, CURLOPT_URL, 'http://is.gd/api.php?longurl='.urlencode($long_url)); - $short_url = curl_exec($curlh); - break; - case 'snipr.com': - curl_setopt($curlh, CURLOPT_URL, 'http://snipr.com/site/snip?r=simple&link='.urlencode($long_url)); - $short_url = curl_exec($curlh); - break; - case 'metamark.net': - curl_setopt($curlh, CURLOPT_URL, 'http://metamark.net/api/rest/simple?long_url='.urlencode($long_url)); - $short_url = curl_exec($curlh); - break; - case 'tinyurl.com': - curl_setopt($curlh, CURLOPT_URL, 'http://tinyurl.com/api-create.php?url='.urlencode($long_url)); - $short_url = curl_exec($curlh); - break; - default: - $short_url = false; - } - - curl_close($curlh); - + $short_url = common_shorten_url($long_url); if ($short_url) { $short_url = (string)$short_url; // store it diff --git a/lib/noticelist.php b/lib/noticelist.php index bd4815cd6..6f05c63d6 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -336,10 +336,6 @@ class NoticeListItem extends Widget // versions (>> 0.4.x) $this->out->raw(common_render_content($this->notice->content, $this->notice)); } - $uploaded = $this->notice->getUploadedAttachment(); - if ($uploaded) { - $this->out->element('a', array('href' => $uploaded[0], 'class' => 'attachment', 'id' => 'attachment-' . $uploaded[1]), $uploaded[0]); - } $this->out->elementEnd('p'); } diff --git a/lib/util.php b/lib/util.php index 0aff893fd..1af462516 100644 --- a/lib/util.php +++ b/lib/util.php @@ -1377,3 +1377,68 @@ function common_database_tablename($tablename) //table prefixes could be added here later return $tablename; } + +function common_shorten_url($long_url) +{ + $user = common_current_user(); + if (empty($user)) { + // common current user does not find a user when called from the XMPP daemon + // therefore we'll set one here fix, so that XMPP given URLs may be shortened + $svc = 'ur1.ca'; + } else { + $svc = $user->urlshorteningservice; + } + + $curlh = curl_init(); + curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait + curl_setopt($curlh, CURLOPT_USERAGENT, 'Laconica'); + curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true); + + switch($svc) { + case 'ur1.ca': + require_once INSTALLDIR.'/lib/Shorturl_api.php'; + $short_url_service = new LilUrl; + $short_url = $short_url_service->shorten($long_url); + break; + + case '2tu.us': + $short_url_service = new TightUrl; + require_once INSTALLDIR.'/lib/Shorturl_api.php'; + $short_url = $short_url_service->shorten($long_url); + break; + + case 'ptiturl.com': + require_once INSTALLDIR.'/lib/Shorturl_api.php'; + $short_url_service = new PtitUrl; + $short_url = $short_url_service->shorten($long_url); + break; + + case 'bit.ly': + curl_setopt($curlh, CURLOPT_URL, 'http://bit.ly/api?method=shorten&long_url='.urlencode($long_url)); + $short_url = current(json_decode(curl_exec($curlh))->results)->hashUrl; + break; + + case 'is.gd': + curl_setopt($curlh, CURLOPT_URL, 'http://is.gd/api.php?longurl='.urlencode($long_url)); + $short_url = curl_exec($curlh); + break; + case 'snipr.com': + curl_setopt($curlh, CURLOPT_URL, 'http://snipr.com/site/snip?r=simple&link='.urlencode($long_url)); + $short_url = curl_exec($curlh); + break; + case 'metamark.net': + curl_setopt($curlh, CURLOPT_URL, 'http://metamark.net/api/rest/simple?long_url='.urlencode($long_url)); + $short_url = curl_exec($curlh); + break; + case 'tinyurl.com': + curl_setopt($curlh, CURLOPT_URL, 'http://tinyurl.com/api-create.php?url='.urlencode($long_url)); + $short_url = curl_exec($curlh); + break; + default: + $short_url = false; + } + + curl_close($curlh); + + return $short_url; +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf