From 92c12898e780ed3685c93bd85cae5772f1547c5e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 27 Jul 2009 15:07:39 -0400 Subject: [PATCH 1/8] change front page to link to max member groups --- actions/public.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/public.php b/actions/public.php index ef9ef0d1ab..d0317ac706 100644 --- a/actions/public.php +++ b/actions/public.php @@ -229,7 +229,7 @@ class PublicAction extends Action // $top->show(); $pop = new PopularNoticeSection($this); $pop->show(); - $gbp = new GroupsByPostsSection($this); + $gbp = new GroupsByMembersSection($this); $gbp->show(); $feat = new FeaturedUsersSection($this); $feat->show(); From 2cbee8213ae9973c929d8d130cdc54d031e0ccd6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 27 Jul 2009 13:51:40 -0400 Subject: [PATCH 2/8] better check for existing DB connection runs SET NAMES UTF8 less --- classes/Memcached_DataObject.php | 69 ++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index f7cbb9d5b6..ea070ec849 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -241,10 +241,19 @@ class Memcached_DataObject extends DB_DataObject function _connect() { global $_DB_DATAOBJECT; - $exists = !empty($this->_database_dsn_md5) && - isset($_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]); + + $sum = $this->_getDbDsnMD5(); + + if (!empty($_DB_DATAOBJECT['CONNECTIONS'][$sum]) && + !PEAR::isError($_DB_DATAOBJECT['CONNECTIONS'][$sum])) { + $exists = true; + } else { + $exists = false; + } + $result = parent::_connect(); - if (!$exists) { + + if ($result && !$exists) { $DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]; if (common_config('db', 'type') == 'mysql' && common_config('db', 'utf8')) { @@ -258,7 +267,61 @@ class Memcached_DataObject extends DB_DataObject } } } + return $result; } + // XXX: largely cadged from DB_DataObject + + function _getDbDsnMD5() + { + if ($this->_database_dsn_md5) { + return $this->_database_dsn_md5; + } + + $dsn = $this->_getDbDsn(); + + if (is_string($dsn)) { + $sum = md5($dsn); + } else { + /// support array based dsn's + $sum = md5(serialize($dsn)); + } + + return $sum; + } + + function _getDbDsn() + { + global $_DB_DATAOBJECT; + + if (empty($_DB_DATAOBJECT['CONFIG'])) { + DB_DataObject::_loadConfig(); + } + + $options = &$_DB_DATAOBJECT['CONFIG']; + + // if the databse dsn dis defined in the object.. + + $dsn = isset($this->_database_dsn) ? $this->_database_dsn : null; + + if (!$dsn) { + + if (!$this->_database) { + $this->_database = isset($options["table_{$this->__table}"]) ? $options["table_{$this->__table}"] : null; + } + + if ($this->_database && !empty($options["database_{$this->_database}"])) { + $dsn = $options["database_{$this->_database}"]; + } else if (!empty($options['database'])) { + $dsn = $options['database']; + } + } + + if (!$dsn) { + throw new Exception("No database name / dsn found anywhere"); + } + + return $dsn; + } } From 421ee4297ef5055bdd190fe2bd62cdc22b41c82b Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Fri, 17 Jul 2009 22:59:58 -0400 Subject: [PATCH 3/8] Fix RDFS namespace declaration. Thanks tobyink --- lib/rssaction.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/rssaction.php b/lib/rssaction.php index ffa1f9e99f..7686d06460 100644 --- a/lib/rssaction.php +++ b/lib/rssaction.php @@ -320,6 +320,8 @@ class Rss10Action extends Action 'http://rdfs.org/sioc/ns#', 'xmlns:sioct' => 'http://rdfs.org/sioc/types#', + 'xmlns:rdfs' => + 'http://www.w3.org/2000/01/rdf-schema#', 'xmlns:laconica' => 'http://laconi.ca/ont/', 'xmlns' => 'http://purl.org/rss/1.0/')); From 854d24b05a052bffe21f112b705d58c9abf126a9 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 30 Jul 2009 17:05:35 -0400 Subject: [PATCH 4/8] Site-wide design configuration I added some code so that the site-wide design can be set, using the configuration interface. I also moved the configuration option from $config['site']['design']['background'] to just $config['design']['background'], but the old syntax will still work. Conflicts: config.php.sample --- README | 17 ++++-- classes/Design.php | 92 +++++++++++++++++++++++++++------ config.php.sample | 8 +++ lib/action.php | 28 ++++++++++ lib/common.php | 20 ++++--- lib/currentuserdesignaction.php | 37 ++++--------- lib/groupdesignaction.php | 30 +++-------- lib/ownerdesignaction.php | 31 +++-------- 8 files changed, 160 insertions(+), 103 deletions(-) diff --git a/README b/README index 0214e49315..41c015d29b 100644 --- a/README +++ b/README @@ -961,9 +961,6 @@ sslserver: use an alternate server name for SSL URLs, like shorturllength: Length of URL at which URLs in a message exceeding 140 characters will be sent to the user's chosen shortening service. -design: a default design (colors and background) for the site. - Sub-items are: backgroundcolor, contentcolor, sidebarcolor, - textcolor, linkcolor, backgroundimage, disposition. dupelimit: minimum time allowed for one person to say the same thing twice. Default 60s. Anything lower is considered a user or UI error. @@ -1429,6 +1426,20 @@ notify third-party servers of updates. notify: an array of URLs for ping endpoints. Default is the empty array (no notification). +design +------ + +Default design (colors and background) for the site. Actual appearance +depends on the theme. Null values mean to use the theme defaults. + +backgroundcolor: Hex color of the site background. +contentcolor: Hex color of the content area background. +sidebarcolor: Hex color of the sidebar background. +textcolor: Hex color of all non-link text. +linkcolor: Hex color of all links. +backgroundimage: Image to use for the background. +disposition: Flags for whether or not to tile the background image. + Plugins ======= diff --git a/classes/Design.php b/classes/Design.php index 0927fcda70..43544f1c9d 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -55,26 +55,38 @@ class Design extends Memcached_DataObject function showCSS($out) { - try { + $css = ''; - $bgcolor = new WebColor($this->backgroundcolor); - $ccolor = new WebColor($this->contentcolor); - $sbcolor = new WebColor($this->sidebarcolor); - $tcolor = new WebColor($this->textcolor); - $lcolor = new WebColor($this->linkcolor); + $bgcolor = Design::toWebColor($this->backgroundcolor); - } catch (WebColorException $e) { - // This shouldn't happen - common_log(LOG_ERR, "Unable to create color for design $id.", - __FILE__); + if (!empty($bgcolor)) { + $css .= 'body { background-color: #' . $bgcolor->hexValue() . ' }' . "\n"; } - $css = '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"; + $ccolor = Design::toWebColor($this->contentcolor); + + if (!empty($ccolor)) { + $css .= '#content, #site_nav_local_views .current a { background-color: #'; + $css .= $ccolor->hexValue() . '} '."\n"; + } + + $sbcolor = Design::toWebColor($this->sidebarcolor); + + if (!empty($sbcolor)) { + $css .= '#aside_primary { background-color: #'. $sbcolor->hexValue() . ' }' . "\n"; + } + + $tcolor = Design::toWebColor($this->textcolor); + + if (!empty($tcolor)) { + $css .= 'html body { color: #'. $tcolor->hexValue() . ' }'. "\n"; + } + + $lcolor = Design::toWebColor($this->linkcolor); + + if (!empty($lcolor)) { + $css .= 'a { color: #' . $lcolor->hexValue() . ' }' . "\n"; + } if (!empty($this->backgroundimage) && $this->disposition & BACKGROUND_ON) { @@ -88,8 +100,25 @@ class Design extends Memcached_DataObject '); ' . $repeat . ' background-attachment:fixed; }' . "\n"; } - $out->element('style', array('type' => 'text/css'), $css); + if (0 != mb_strlen($css)) { + $out->element('style', array('type' => 'text/css'), $css); + } + } + static function toWebColor($color) + { + if (is_null($color)) { + return null; + } + + try { + return new WebColor($color); + } catch (WebColorException $e) { + // This shouldn't happen + common_log(LOG_ERR, "Unable to create color for design $id.", + __FILE__); + return null; + } } static function filename($id, $extension, $extra=null) @@ -152,4 +181,33 @@ class Design extends Memcached_DataObject } } + /** + * Return a design object based on the configured site design. + * + * @return Design a singleton design object for the site. + */ + + static function siteDesign() + { + static $siteDesign = null; + + if (empty($siteDesign)) { + + $siteDesign = new Design(); + + $attrs = array('backgroundcolor', + 'contentcolor', + 'sidebarcolor', + 'textcolor', + 'linkcolor', + 'backgroundimage', + 'disposition'); + + foreach ($attrs as $attr) { + $siteDesign->$attr = common_config('design', $attr); + } + } + + return $siteDesign; + } } diff --git a/config.php.sample b/config.php.sample index 57aa6a6c8c..c27645ff87 100644 --- a/config.php.sample +++ b/config.php.sample @@ -18,6 +18,14 @@ $config['site']['server'] = 'localhost'; $config['site']['path'] = 'laconica'; // $config['site']['fancy'] = false; // $config['site']['theme'] = 'default'; +// Sets the site's default design values +// $config['design']['backgroundcolor'] = '#F0F2F5'; +// $config['design']['contentcolor'] = '#FFFFFF'; +// $config['design']['sidebarcolor'] = '#CEE1E9'; +// $config['design']['textcolor'] = '#000000'; +// $config['design']['linkcolor'] = '#002E6E'; +// $config['design']['backgroundimage'] = null; +// $config['design']['disposition'] = 1; // To enable the built-in mobile style sheet, defaults to false. // $config['site']['mobile'] = true; // For contact email, defaults to $_SERVER["SERVER_ADMIN"] diff --git a/lib/action.php b/lib/action.php index 95ee10c642..a5244371a5 100644 --- a/lib/action.php +++ b/lib/action.php @@ -191,6 +191,7 @@ class Action extends HTMLOutputter // lawsuit function showStylesheets() { if (Event::handle('StartShowStyles', array($this))) { + if (Event::handle('StartShowLaconicaStyles', array($this))) { $this->element('link', array('rel' => 'stylesheet', 'type' => 'text/css', @@ -209,6 +210,7 @@ class Action extends HTMLOutputter // lawsuit 'media' => 'print')); Event::handle('EndShowLaconicaStyles', array($this)); } + if (Event::handle('StartShowUAStyles', array($this))) { $this->comment('[if IE]>viewdesigns) { + $design = $this->getDesign(); + + if (!empty($design)) { + $design->showCSS($this); + } + } + + Event::handle('EndShowDesign', array($this)); + } Event::handle('EndShowStyles', array($this)); } } @@ -1074,4 +1091,15 @@ class Action extends HTMLOutputter // lawsuit { return null; } + + /** + * A design for this action + * + * @return Design a design object to use + */ + + function getDesign() + { + return Design::siteDesign(); + } } diff --git a/lib/common.php b/lib/common.php index c47702779d..507a2a281f 100644 --- a/lib/common.php +++ b/lib/common.php @@ -94,14 +94,6 @@ $config = array('name' => 'Just another Laconica microblog', 'server' => $_server, 'theme' => 'default', - 'design' => - array('backgroundcolor' => '#CEE1E9', - 'contentcolor' => '#FFFFFF', - 'sidebarcolor' => '#C8D1D5', - 'textcolor' => '#000000', - 'linkcolor' => '#002E6E', - 'backgroundimage' => null, - 'disposition' => 1), 'path' => $_path, 'logfile' => null, 'logo' => null, @@ -261,6 +253,14 @@ $config = 'sessions' => array('handle' => false, // whether to handle sessions ourselves 'debug' => false), // debugging output for sessions + 'design' => + array('backgroundcolor' => null, // null -> 'use theme default' + 'contentcolor' => null, + 'sidebarcolor' => null, + 'textcolor' => null, + 'linkcolor' => null, + 'backgroundimage' => null, + 'disposition' => null), ); $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); @@ -277,6 +277,10 @@ $config['db'] = 'quote_identifiers' => false, 'type' => 'mysql' ); +// Backward compatibility + +$config['site']['design'] =& $config['design']; + if (function_exists('date_default_timezone_set')) { /* Work internally in UTC */ date_default_timezone_set('UTC'); diff --git a/lib/currentuserdesignaction.php b/lib/currentuserdesignaction.php index 4c7e15a8b7..52516b624a 100644 --- a/lib/currentuserdesignaction.php +++ b/lib/currentuserdesignaction.php @@ -47,33 +47,10 @@ if (!defined('LACONICA')) { class CurrentUserDesignAction extends Action { - - /** - * Show the user's design stylesheet - * - * @return nothing - */ - - function showStylesheets() - { - parent::showStylesheets(); - - $user = common_current_user(); - - if (empty($user) || $user->viewdesigns) { - $design = $this->getDesign(); - - if (!empty($design)) { - $design->showCSS($this); - } - } - } - /** * A design for this action * - * if the user attribute has been set, returns that user's - * design. + * Returns the design preferences for the current user. * * @return Design a design object to use */ @@ -82,11 +59,15 @@ class CurrentUserDesignAction extends Action { $cur = common_current_user(); - if (empty($cur)) { - return null; + if (!empty($cur)) { + + $design = $cur->getDesign(); + + if (!empty($design)) { + return $design; + } } - return $cur->getDesign(); + return parent::getDesign(); } - } diff --git a/lib/groupdesignaction.php b/lib/groupdesignaction.php index 58777c283a..c7cdff1fe9 100644 --- a/lib/groupdesignaction.php +++ b/lib/groupdesignaction.php @@ -49,26 +49,6 @@ class GroupDesignAction extends Action { /** The group in question */ var $group = null; - /** - * Show the groups's design stylesheet - * - * @return nothing - */ - function showStylesheets() - { - parent::showStylesheets(); - - $user = common_current_user(); - - if (empty($user) || $user->viewdesigns) { - $design = $this->getDesign(); - - if (!empty($design)) { - $design->showCSS($this); - } - } - } - /** * A design for this action * @@ -80,10 +60,12 @@ class GroupDesignAction extends Action { function getDesign() { - if (empty($this->group)) { - return null; + if (!empty($this->group)) { + $design = $this->group->getDesign(); + if (!empty($design)) { + return $design; + } } - - return $this->group->getDesign(); + return parent::getDesign(); } } diff --git a/lib/ownerdesignaction.php b/lib/ownerdesignaction.php index 785b8a93d3..b42df926d0 100644 --- a/lib/ownerdesignaction.php +++ b/lib/ownerdesignaction.php @@ -52,26 +52,6 @@ class OwnerDesignAction extends Action { var $user = null; - /** - * Show the owner's design stylesheet - * - * @return nothing - */ - function showStylesheets() - { - parent::showStylesheets(); - - $user = common_current_user(); - - if (empty($user) || $user->viewdesigns) { - $design = $this->getDesign(); - - if (!empty($design)) { - $design->showCSS($this); - } - } - } - /** * A design for this action * @@ -83,10 +63,15 @@ class OwnerDesignAction extends Action { function getDesign() { - if (empty($this->user)) { - return null; + if (!empty($this->user)) { + + $design = $this->user->getDesign(); + + if (!empty($design)) { + return $design; + } } - return $this->user->getDesign(); + return parent::getDesign(); } } From 77c5f9481c5cf1cc548c73c71bd4723001d912f5 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 30 Jul 2009 20:44:51 +0000 Subject: [PATCH 5/8] Removed default values from s. JavaScript will now get the colours from the theme. This approach removes data that was previously available in HTML. It was only necessary if the user wanted to know the site's default values. --- js/userdesign.go.js | 31 ++++++++++++++++++++++++++++++- lib/designsettings.php | 10 +++++----- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/js/userdesign.go.js b/js/userdesign.go.js index dda86294ed..70dd9c7de7 100644 --- a/js/userdesign.go.js +++ b/js/userdesign.go.js @@ -7,6 +7,35 @@ * @link http://laconi.ca/ */ $(document).ready(function() { + function InitColors(i, E) { + switch (parseInt(E.id.slice(-1))) { + case 1: default: + $(E).val(rgb2hex($('body').css('background-color'))); + break; + case 2: + $(E).val(rgb2hex($('#content').css('background-color'))); + break; + case 3: + $(E).val(rgb2hex($('#aside_primary').css('background-color'))); + break; + case 4: + $(E).val(rgb2hex($('html body').css('color'))); + break; + case 5: + $(E).val(rgb2hex($('a').css('color'))); + break; + } + } + + function rgb2hex(rgb) { + rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); + function hex(x) { + hexDigits = new Array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"); + return isNaN(x) ? "00" : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16]; + } + return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]); + } + function UpdateColors(S) { C = $(S).val(); switch (parseInt(S.id.slice(-1))) { @@ -55,7 +84,7 @@ $(document).ready(function() { f = $.farbtastic('#color-picker', SynchColors); swatches = $('#settings_design_color .swatch'); - + swatches.each(InitColors); swatches .each(SynchColors) .blur(function() { diff --git a/lib/designsettings.php b/lib/designsettings.php index fbffdb208f..1b0e621669 100644 --- a/lib/designsettings.php +++ b/lib/designsettings.php @@ -182,7 +182,7 @@ class DesignSettingsAction extends AccountSettingsAction 'class' => 'swatch', 'maxlength' => '7', 'size' => '7', - 'value' => '#' . $bgcolor->hexValue())); + 'value' => '')); $this->elementEnd('li'); $ccolor = new WebColor($design->contentcolor); @@ -195,7 +195,7 @@ class DesignSettingsAction extends AccountSettingsAction 'class' => 'swatch', 'maxlength' => '7', 'size' => '7', - 'value' => '#' . $ccolor->hexValue())); + 'value' => '')); $this->elementEnd('li'); $sbcolor = new WebColor($design->sidebarcolor); @@ -208,7 +208,7 @@ class DesignSettingsAction extends AccountSettingsAction 'class' => 'swatch', 'maxlength' => '7', 'size' => '7', - 'value' => '#' . $sbcolor->hexValue())); + 'value' => '')); $this->elementEnd('li'); $tcolor = new WebColor($design->textcolor); @@ -221,7 +221,7 @@ class DesignSettingsAction extends AccountSettingsAction 'class' => 'swatch', 'maxlength' => '7', 'size' => '7', - 'value' => '#' . $tcolor->hexValue())); + 'value' => '')); $this->elementEnd('li'); $lcolor = new WebColor($design->linkcolor); @@ -234,7 +234,7 @@ class DesignSettingsAction extends AccountSettingsAction 'class' => 'swatch', 'maxlength' => '7', 'size' => '7', - 'value' => '#' . $lcolor->hexValue())); + 'value' => '')); $this->elementEnd('li'); } catch (WebColorException $e) { From 60c39e470524ff53995887e8d13aa076b9744e68 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 2 Aug 2009 10:34:23 -0400 Subject: [PATCH 6/8] GC sessions one by one to make sure memcached gets cleared --- classes/Session.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/classes/Session.php b/classes/Session.php index ac80279c5e..a92ce405b5 100644 --- a/classes/Session.php +++ b/classes/Session.php @@ -110,9 +110,18 @@ class Session extends Memcached_DataObject $session = new Session(); $session->whereAdd('modified < "'.$epoch.'"'); - $result = $session->delete(DB_DATAOBJECT_WHEREADD_ONLY); - self::logdeb("garbage collection result = $result"); + $session->find(); + + while ($session->fetch()) { + $other = new Session(); + $other->id = $session->id; + self::logdeb("Collecting session $other->id"); + $result = $other->delete(); + self::logdeb("garbage collection result = $result"); + } + + $session->free(); } static function setSaveHandler() From f342db586d2d95035c53581bebba66eb7e7f7eec Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 2 Aug 2009 10:34:40 -0400 Subject: [PATCH 7/8] A script to GC sessions correctly --- scripts/sessiongc.php | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 scripts/sessiongc.php diff --git a/scripts/sessiongc.php b/scripts/sessiongc.php new file mode 100644 index 0000000000..314b641eb9 --- /dev/null +++ b/scripts/sessiongc.php @@ -0,0 +1,36 @@ +#!/usr/bin/env php +. + */ + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); + +$helptext = << Date: Sun, 2 Aug 2009 11:18:41 -0400 Subject: [PATCH 8/8] don't delete during select --- classes/Session.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/classes/Session.php b/classes/Session.php index a92ce405b5..5ec509f5f9 100644 --- a/classes/Session.php +++ b/classes/Session.php @@ -108,20 +108,24 @@ class Session extends Memcached_DataObject $epoch = common_sql_date(time() - $maxlifetime); + $ids = array(); + $session = new Session(); $session->whereAdd('modified < "'.$epoch.'"'); + $session->selectAdd(); + $session->selectAdd('id'); $session->find(); while ($session->fetch()) { - $other = new Session(); - $other->id = $session->id; - self::logdeb("Collecting session $other->id"); - $result = $other->delete(); - self::logdeb("garbage collection result = $result"); + $ids[] = $session->id; } $session->free(); + + foreach ($ids as $id) { + self::destroy($id); + } } static function setSaveHandler()