X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=lib%2Faction.php;h=ddc058d4185979e8042b1b1dd25f7601f28da37a;hb=b7d07466943a73e1c009467c8daa6e499810080f;hp=491d7d4810e17ee0db73a36ef0bc8702cfb15161;hpb=f72eb17304af9c2d7dac8a34b07bd2433b79c8c4;p=quix0rs-gnu-social.git diff --git a/lib/action.php b/lib/action.php index 491d7d4810..3ef9ffa3c8 100644 --- a/lib/action.php +++ b/lib/action.php @@ -111,6 +111,19 @@ class Action extends HTMLOutputter // lawsuit } } + function endHTML() + { + global $_startTime; + + if (isset($_startTime)) { + $endTime = microtime(true); + $diff = round(($endTime - $_startTime) * 1000); + $this->raw(""); + } + + return parent::endHTML(); + } + /** * Show head, a template method. * @@ -121,7 +134,10 @@ class Action extends HTMLOutputter // lawsuit // XXX: attributes (profile?) $this->elementStart('head'); if (Event::handle('StartShowHeadElements', array($this))) { - $this->showTitle(); + if (Event::handle('StartShowHeadTitle', array($this))) { + $this->showTitle(); + Event::handle('EndShowHeadTitle', array($this)); + } $this->showShortcutIcon(); $this->showStylesheets(); $this->showOpenSearch(); @@ -141,6 +157,7 @@ class Action extends HTMLOutputter // lawsuit function showTitle() { $this->element('title', null, + // TRANS: Page title. %1$s is the title, %2$s is the site name. sprintf(_("%1\$s - %2\$s"), $this->title(), common_config('site', 'name'))); @@ -156,6 +173,7 @@ class Action extends HTMLOutputter // lawsuit function title() { + // TRANS: Page title for a page without a title set. return _("Untitled page"); } @@ -170,8 +188,9 @@ class Action extends HTMLOutputter // lawsuit $this->element('link', array('rel' => 'shortcut icon', 'href' => Theme::path('favicon.ico'))); } else { + // favicon.ico should be HTTPS if the rest of the page is $this->element('link', array('rel' => 'shortcut icon', - 'href' => common_path('favicon.ico'))); + 'href' => common_path('favicon.ico', StatusNet::isHTTPS()))); } if (common_config('site', 'mobile')) { @@ -198,8 +217,7 @@ class Action extends HTMLOutputter // lawsuit if (Event::handle('StartShowStatusNetStyles', array($this)) && Event::handle('StartShowLaconicaStyles', array($this))) { - $this->cssLink('css/display.css',null,'screen, projection, tv'); - $this->cssLink('css/print.css','base','print'); + $this->primaryCssLink(null, 'screen, projection, tv, print'); Event::handle('EndShowStatusNetStyles', array($this)); Event::handle('EndShowLaconicaStyles', array($this)); } @@ -234,7 +252,29 @@ class Action extends HTMLOutputter // lawsuit Event::handle('EndShowDesign', array($this)); } Event::handle('EndShowStyles', array($this)); + + if (common_config('custom_css', 'enabled')) { + $css = common_config('custom_css', 'css'); + if (Event::handle('StartShowCustomCss', array($this, &$css))) { + if (trim($css) != '') { + $this->style($css); + } + Event::handle('EndShowCustomCss', array($this)); + } + } + } + } + + function primaryCssLink($mainTheme=null, $media=null) + { + // If the currently-selected theme has dependencies on other themes, + // we'll need to load their display.css files as well in order. + $theme = new Theme($mainTheme); + $baseThemes = $theme->getDeps(); + foreach ($baseThemes as $baseTheme) { + $this->cssLink('css/display.css', $baseTheme, $media); } + $this->cssLink('css/display.css', $mainTheme, $media); } /** @@ -247,17 +287,16 @@ class Action extends HTMLOutputter // lawsuit if (Event::handle('StartShowScripts', array($this))) { if (Event::handle('StartShowJQueryScripts', array($this))) { $this->script('jquery.min.js'); - $this->script('jquery.form.js'); - $this->script('jquery.cookie.js'); - $this->inlineScript('if (typeof window.JSON !== "object") { $.getScript("'.common_path('js/json2.js').'"); }'); + $this->script('jquery.form.min.js'); + $this->script('jquery.cookie.min.js'); + $this->inlineScript('if (typeof window.JSON !== "object") { $.getScript("'.common_path('js/json2.min.js').'"); }'); $this->script('jquery.joverlay.min.js'); Event::handle('EndShowJQueryScripts', array($this)); } if (Event::handle('StartShowStatusNetScripts', array($this)) && Event::handle('StartShowLaconicaScripts', array($this))) { - $this->script('xbImportNode.js'); - $this->script('util.js'); - $this->script('geometa.js'); + $this->script('util.min.js'); + $this->showScriptMessages(); // Frame-busting code to avoid clickjacking attacks. $this->inlineScript('if (window.top !== window.self) { window.top.location.href = window.self.location.href; }'); Event::handle('EndShowStatusNetScripts', array($this)); @@ -267,6 +306,59 @@ class Action extends HTMLOutputter // lawsuit } } + /** + * Exports a map of localized text strings to JavaScript code. + * + * Plugins can add to what's exported by hooking the StartScriptMessages or EndScriptMessages + * events and appending to the array. Try to avoid adding strings that won't be used, as + * they'll be added to HTML output. + */ + + function showScriptMessages() + { + $messages = array(); + + if (Event::handle('StartScriptMessages', array($this, &$messages))) { + // Common messages needed for timeline views etc... + + // TRANS: Localized tooltip for '...' expansion button on overlong remote messages. + $messages['showmore_tooltip'] = _m('TOOLTIP', 'Show more'); + + $messages = array_merge($messages, $this->getScriptMessages()); + + Event::handle('EndScriptMessages', array($this, &$messages)); + } + + if (!empty($messages)) { + $this->inlineScript('SN.messages=' . json_encode($messages)); + } + + return $messages; + } + + /** + * If the action will need localizable text strings, export them here like so: + * + * return array('pool_deepend' => _('Deep end'), + * 'pool_shallow' => _('Shallow end')); + * + * The exported map will be available via SN.msg() to JS code: + * + * $('#pool').html('
'); + * $('#pool .deepend').text(SN.msg('pool_deepend')); + * $('#pool .shallow').text(SN.msg('pool_shallow')); + * + * Exports a map of localized text strings to JavaScript code. + * + * Plugins can add to what's exported on any action by hooking the StartScriptMessages or + * EndScriptMessages events and appending to the array. Try to avoid adding strings that won't + * be used, as they'll be added to HTML output. + */ + function getScriptMessages() + { + return array(); + } + /** * Show OpenSearch headers * @@ -290,7 +382,6 @@ class Action extends HTMLOutputter // lawsuit * * @return nothing */ - function showFeeds() { $feeds = $this->getFeeds(); @@ -338,9 +429,9 @@ class Action extends HTMLOutputter // lawsuit */ function showBody() { - $this->elementStart('body', (common_current_user()) ? array('id' => $this->trimmed('action'), + $this->elementStart('body', (common_current_user()) ? array('id' => strtolower($this->trimmed('action')), 'class' => 'user_in') - : array('id' => $this->trimmed('action'))); + : array('id' => strtolower($this->trimmed('action')))); $this->elementStart('div', array('id' => 'wrap')); if (Event::handle('StartShowHeader', array($this))) { $this->showHeader(); @@ -374,7 +465,10 @@ class Action extends HTMLOutputter // lawsuit Event::handle('EndShowSiteNotice', array($this)); } if (common_logged_in()) { - $this->showNoticeForm(); + if (Event::handle('StartShowNoticeForm', array($this))) { + $this->showNoticeForm(); + Event::handle('EndShowNoticeForm', array($this)); + } } else { $this->showAnonymousMessage(); } @@ -392,21 +486,51 @@ class Action extends HTMLOutputter // lawsuit 'class' => 'vcard')); if (Event::handle('StartAddressData', array($this))) { if (common_config('singleuser', 'enabled')) { + $user = User::singleUser(); $url = common_local_url('showstream', - array('nickname' => common_config('singleuser', 'nickname'))); + array('nickname' => $user->nickname)); + } else if (common_logged_in()) { + $cur = common_current_user(); + $url = common_local_url('all', array('nickname' => $cur->nickname)); } else { $url = common_local_url('public'); } + $this->elementStart('a', array('class' => 'url home bookmark', 'href' => $url)); - if (common_config('site', 'logo') || file_exists(Theme::file('logo.png'))) { + + if (StatusNet::isHTTPS()) { + $logoUrl = common_config('site', 'ssllogo'); + if (empty($logoUrl)) { + // if logo is an uploaded file, try to fall back to HTTPS file URL + $httpUrl = common_config('site', 'logo'); + if (!empty($httpUrl)) { + $f = File::staticGet('url', $httpUrl); + if (!empty($f) && !empty($f->filename)) { + // this will handle the HTTPS case + $logoUrl = File::url($f->filename); + } + } + } + } else { + $logoUrl = common_config('site', 'logo'); + } + + if (empty($logoUrl) && file_exists(Theme::file('logo.png'))) { + // This should handle the HTTPS case internally + $logoUrl = Theme::path('logo.png'); + } + + if (!empty($logoUrl)) { $this->element('img', array('class' => 'logo photo', - 'src' => (common_config('site', 'logo')) ? common_config('site', 'logo') : Theme::path('logo.png'), + 'src' => $logoUrl, 'alt' => common_config('site', 'name'))); } + $this->text(' '); $this->element('span', array('class' => 'fn org'), common_config('site', 'name')); $this->elementEnd('a'); + Event::handle('EndAddressData', array($this)); } $this->elementEnd('address'); @@ -420,81 +544,68 @@ class Action extends HTMLOutputter // lawsuit function showPrimaryNav() { $user = common_current_user(); - $this->elementStart('dl', array('id' => 'site_nav_global_primary')); - $this->element('dt', null, _('Primary site navigation')); - $this->elementStart('dd'); - $this->elementStart('ul', array('class' => 'nav')); + $this->elementStart('ul', array('class' => 'nav', + 'id' => 'site_nav_global_primary')); if (Event::handle('StartPrimaryNav', array($this))) { - if ($user) { - // TRANS: Tooltip for main menu option "Personal" - $tooltip = _m('TOOLTIP', 'Personal profile and friends timeline'); - // TRANS: Main menu option when logged in for access to personal profile and friends timeline - $this->menuItem(common_local_url('all', array('nickname' => $user->nickname)), - _m('MENU', 'Personal'), $tooltip, false, 'nav_home'); - // TRANS: Tooltip for main menu option "Account" - $tooltip = _m('TOOLTIP', 'Change your email, avatar, password, profile'); - // TRANS: Main menu option when logged in for access to user settings + if (!empty($user)) { + $this->menuItem(common_local_url('all', + array('nickname' => $user->nickname)), + _m('Home'), + _m('Friends timeline'), + false, + 'nav_home'); + $this->menuItem(common_local_url('showstream', + array('nickname' => $user->nickname)), + _m('Profile'), + _m('Your profile'), + false, + 'nav_profile'); + $this->menuItem(common_local_url('public'), + _m('Public'), + _m('Everyone on this site'), + false, + 'nav_public'); $this->menuItem(common_local_url('profilesettings'), - _('Account'), $tooltip, false, 'nav_account'); - // TRANS: Tooltip for main menu option "Services" - $tooltip = _m('TOOLTIP', 'Connect to services'); - // TRANS: Main menu option when logged in and connection are possible for access to options to connect to other services - $this->menuItem(common_local_url('oauthconnectionssettings'), - _('Connect'), $tooltip, false, 'nav_connect'); + _m('Settings'), + _m('Change your personal settings'), + false, + 'nav_account'); if ($user->hasRight(Right::CONFIGURESITE)) { - // TRANS: Tooltip for menu option "Admin" - $tooltip = _m('TOOLTIP', 'Change site configuration'); - // TRANS: Main menu option when logged in and site admin for access to site configuration $this->menuItem(common_local_url('siteadminpanel'), - _m('MENU', 'Admin'), $tooltip, false, 'nav_admin'); + _m('Admin'), + _m('Site configuration'), + false, + 'nav_admin'); } - if (common_config('invite', 'enabled')) { - // TRANS: Tooltip for main menu option "Invite" - $tooltip = _m('TOOLTIP', 'Invite friends and colleagues to join you on %s'); - // TRANS: Main menu option when logged in and invitations are allowed for inviting new users - $this->menuItem(common_local_url('invite'), - _m('MENU', 'Invite'), - sprintf($tooltip, - common_config('site', 'name')), - false, 'nav_invitecontact'); - } - // TRANS: Tooltip for main menu option "Logout" - $tooltip = _m('TOOLTIP', 'Logout from the site'); - // TRANS: Main menu option when logged in to log out the current user $this->menuItem(common_local_url('logout'), - _m('MENU', 'Logout'), $tooltip, false, 'nav_logout'); - } - else { - if (!common_config('site', 'closed')) { - // TRANS: Tooltip for main menu option "Register" - $tooltip = _m('TOOLTIP', 'Create an account'); - // TRANS: Main menu option when not logged in to register a new account - $this->menuItem(common_local_url('register'), - _m('MENU', 'Register'), $tooltip, false, 'nav_register'); - } - // TRANS: Tooltip for main menu option "Login" - $tooltip = _m('TOOLTIP', 'Login to the site'); - // TRANS: Main menu option when not logged in to log in + _m('Logout'), + _m('Logout from the site'), + false, + 'nav_logout'); + } else { + $this->menuItem(common_local_url('public'), + _m('Public'), + _m('Everyone on this site'), + false, + 'nav_public'); $this->menuItem(common_local_url('login'), - _m('MENU', 'Login'), $tooltip, false, 'nav_login'); + _m('Login'), + _m('Login to the site'), + false, + 'nav_login'); } - // TRANS: Tooltip for main menu option "Help" - $tooltip = _m('TOOLTIP', 'Help me!'); - // TRANS: Main menu option for help on the StatusNet site - $this->menuItem(common_local_url('doc', array('title' => 'help')), - _m('MENU', 'Help'), $tooltip, false, 'nav_help'); - if ($user || !common_config('site', 'private')) { - // TRANS: Tooltip for main menu option "Search" - $tooltip = _m('TOOLTIP', 'Search for people or text'); - // TRANS: Main menu option when logged in or when the StatusNet instance is not private - $this->menuItem(common_local_url('peoplesearch'), - _m('MENU', 'Search'), $tooltip, false, 'nav_search'); + + if (!empty($user) || !common_config('site', 'private')) { + $this->menuItem(common_local_url('noticesearch'), + _m('Search'), + _m('Search the site'), + false, + 'nav_search'); } + Event::handle('EndPrimaryNav', array($this)); } $this->elementEnd('ul'); - $this->elementEnd('dd'); - $this->elementEnd('dl'); } /** @@ -507,14 +618,10 @@ class Action extends HTMLOutputter // lawsuit // Revist. Should probably do an hAtom pattern here $text = common_config('site', 'notice'); if ($text) { - $this->elementStart('dl', array('id' => 'site_notice', + $this->elementStart('div', array('id' => 'site_notice', 'class' => 'system_notice')); - // TRANS: DT element for site notice. String is hidden in default CSS. - $this->element('dt', null, _('Site notice')); - $this->elementStart('dd', null); $this->raw($text); - $this->elementEnd('dd'); - $this->elementEnd('dl'); + $this->elementEnd('div'); } } @@ -575,12 +682,11 @@ class Action extends HTMLOutputter // lawsuit */ function showLocalNavBlock() { - $this->elementStart('dl', array('id' => 'site_nav_local_views')); - $this->element('dt', null, _('Local views')); - $this->elementStart('dd'); + // Need to have this ID for CSS; I'm too lazy to add it to + // all menus + $this->elementStart('div', array('id' => 'site_nav_local_views')); $this->showLocalNav(); - $this->elementEnd('dd'); - $this->elementEnd('dl'); + $this->elementEnd('div'); } /** @@ -603,7 +709,10 @@ class Action extends HTMLOutputter // lawsuit function showContentBlock() { $this->elementStart('div', array('id' => 'content')); - $this->showPageTitle(); + if (Event::handle('StartShowPageTitle', array($this))) { + $this->showPageTitle(); + Event::handle('EndShowPageTitle', array($this)); + } $this->showPageNoticeBlock(); $this->elementStart('div', array('id' => 'content_inner')); // show the actual content (forms, lists, whatever) @@ -640,16 +749,13 @@ class Action extends HTMLOutputter // lawsuit if ($dclass != 'Action' || Event::hasHandler('StartShowPageNotice')) { - $this->elementStart('dl', array('id' => 'page_notice', + $this->elementStart('div', array('id' => 'page_notice', 'class' => 'system_notice')); - $this->element('dt', null, _('Page notice')); - $this->elementStart('dd'); if (Event::handle('StartShowPageNotice', array($this))) { $this->showPageNotice(); Event::handle('EndShowPageNotice', array($this)); } - $this->elementEnd('dd'); - $this->elementEnd('dl'); + $this->elementEnd('div'); } } @@ -680,19 +786,18 @@ class Action extends HTMLOutputter // lawsuit * * @return nothing */ - function showAside() { $this->elementStart('div', array('id' => 'aside_primary', 'class' => 'aside')); - if (Event::handle('StartShowExportData', array($this))) { - $this->showExportData(); - Event::handle('EndShowExportData', array($this)); - } if (Event::handle('StartShowSections', array($this))) { $this->showSections(); Event::handle('EndShowSections', array($this)); } + if (Event::handle('StartShowExportData', array($this))) { + $this->showExportData(); + Event::handle('EndShowExportData', array($this)); + } $this->elementEnd('div'); } @@ -701,7 +806,6 @@ class Action extends HTMLOutputter // lawsuit * * @return void */ - function showExportData() { $feeds = $this->getFeeds(); @@ -731,8 +835,11 @@ class Action extends HTMLOutputter // lawsuit function showFooter() { $this->elementStart('div', array('id' => 'footer')); - $this->showSecondaryNav(); - $this->showLicenses(); + if (Event::handle('StartShowInsideFooter', array($this))) { + $this->showSecondaryNav(); + $this->showLicenses(); + Event::handle('EndShowInsideFooter', array($this)); + } $this->elementEnd('div'); } @@ -743,37 +850,43 @@ class Action extends HTMLOutputter // lawsuit */ function showSecondaryNav() { - $this->elementStart('dl', array('id' => 'site_nav_global_secondary')); - $this->element('dt', null, _('Secondary site navigation')); - $this->elementStart('dd', null); - $this->elementStart('ul', array('class' => 'nav')); + $this->elementStart('ul', array('class' => 'nav', + 'id' => 'site_nav_global_secondary')); if (Event::handle('StartSecondaryNav', array($this))) { $this->menuItem(common_local_url('doc', array('title' => 'help')), + // TRANS: Secondary navigation menu option leading to help on StatusNet. _('Help')); $this->menuItem(common_local_url('doc', array('title' => 'about')), + // TRANS: Secondary navigation menu option leading to text about StatusNet site. _('About')); $this->menuItem(common_local_url('doc', array('title' => 'faq')), + // TRANS: Secondary navigation menu option leading to Frequently Asked Questions. _('FAQ')); $bb = common_config('site', 'broughtby'); if (!empty($bb)) { $this->menuItem(common_local_url('doc', array('title' => 'tos')), + // TRANS: Secondary navigation menu option leading to Terms of Service. _('TOS')); } $this->menuItem(common_local_url('doc', array('title' => 'privacy')), + // TRANS: Secondary navigation menu option leading to privacy policy. _('Privacy')); $this->menuItem(common_local_url('doc', array('title' => 'source')), + // TRANS: Secondary navigation menu option. Leads to information about StatusNet and its license. _('Source')); $this->menuItem(common_local_url('version'), + // TRANS: Secondary navigation menu option leading to version information on the StatusNet site. _('Version')); $this->menuItem(common_local_url('doc', array('title' => 'contact')), + // TRANS: Secondary navigation menu option leading to e-mail contact information on the + // TRANS: StatusNet site, where to report bugs, ... _('Contact')); $this->menuItem(common_local_url('doc', array('title' => 'badge')), + // TRANS: Secondary navigation menu option. Leads to information about embedding a timeline widget. _('Badge')); Event::handle('EndSecondaryNav', array($this)); } $this->elementEnd('ul'); - $this->elementEnd('dd'); - $this->elementEnd('dl'); } /** @@ -783,10 +896,8 @@ class Action extends HTMLOutputter // lawsuit */ function showLicenses() { - $this->elementStart('dl', array('id' => 'licenses')); $this->showStatusNetLicense(); $this->showContentLicense(); - $this->elementEnd('dl'); } /** @@ -796,20 +907,24 @@ class Action extends HTMLOutputter // lawsuit */ function showStatusNetLicense() { - $this->element('dt', array('id' => 'site_statusnet_license'), _('StatusNet software license')); - $this->elementStart('dd', null); - // @fixme drop the final spaces in the messages when at good spot - // to let translations get updated. if (common_config('site', 'broughtby')) { - $instr = _('**%%site.name%%** is a microblogging service brought to you by [%%site.broughtby%%](%%site.broughtbyurl%%). '); + // TRANS: First sentence of the StatusNet site license. Used if 'broughtby' is set. + // TRANS: Text between [] is a link description, text between () is the link itself. + // TRANS: Make sure there is no whitespace between "]" and "(". + // TRANS: "%%site.broughtby%%" is the value of the variable site.broughtby + $instr = _('**%%site.name%%** is a microblogging service brought to you by [%%site.broughtby%%](%%site.broughtbyurl%%).'); } else { - $instr = _('**%%site.name%%** is a microblogging service. '); + // TRANS: First sentence of the StatusNet site license. Used if 'broughtby' is not set. + $instr = _('**%%site.name%%** is a microblogging service.'); } $instr .= ' '; + // TRANS: Second sentence of the StatusNet site license. Mentions the StatusNet source code license. + // TRANS: Make sure there is no whitespace between "]" and "(". + // TRANS: Text between [] is a link description, text between () is the link itself. + // TRANS: %s is the version of StatusNet that is being used. $instr .= sprintf(_('It runs the [StatusNet](http://status.net/) microblogging software, version %s, available under the [GNU Affero General Public License](http://www.fsf.org/licensing/licenses/agpl-3.0.html).'), STATUSNET_VERSION); $output = common_markup_to_html($instr); $this->raw($output); - $this->elementEnd('dd'); // do it } @@ -821,44 +936,66 @@ class Action extends HTMLOutputter // lawsuit function showContentLicense() { if (Event::handle('StartShowContentLicense', array($this))) { - $this->element('dt', array('id' => 'site_content_license'), _('Site content license')); - $this->elementStart('dd', array('id' => 'site_content_license_cc')); - switch (common_config('license', 'type')) { case 'private': + // TRANS: Content license displayed when license is set to 'private'. + // TRANS: %1$s is the site name. $this->element('p', null, sprintf(_('Content and data of %1$s are private and confidential.'), common_config('site', 'name'))); // fall through case 'allrightsreserved': if (common_config('license', 'owner')) { + // TRANS: Content license displayed when license is set to 'allrightsreserved'. + // TRANS: %1$s is the copyright owner. $this->element('p', null, sprintf(_('Content and data copyright by %1$s. All rights reserved.'), common_config('license', 'owner'))); } else { + // TRANS: Content license displayed when license is set to 'allrightsreserved' and no owner is set. $this->element('p', null, _('Content and data copyright by contributors. All rights reserved.')); } break; case 'cc': // fall through default: $this->elementStart('p'); + + $image = common_config('license', 'image'); + $sslimage = common_config('license', 'sslimage'); + + if (StatusNet::isHTTPS()) { + if (!empty($sslimage)) { + $url = $sslimage; + } else if (preg_match('#^http://i.creativecommons.org/#', $image)) { + // CC support HTTPS on their images + $url = preg_replace('/^http/', 'https', $image); + } else { + // Better to show mixed content than no content + $url = $image; + } + } else { + $url = $image; + } + $this->element('img', array('id' => 'license_cc', - 'src' => common_config('license', 'image'), + 'src' => $url, 'alt' => common_config('license', 'title'), 'width' => '80', 'height' => '15')); $this->text(' '); - //TODO: This is dirty: i18n - $this->text(_('All '.common_config('site', 'name').' content and data are available under the ')); - $this->element('a', array('class' => 'license', - 'rel' => 'external license', - 'href' => common_config('license', 'url')), - common_config('license', 'title')); - $this->text(' '); - $this->text(_('license.')); + // TRANS: license message in footer. + // TRANS: %1$s is the site name, %2$s is a link to the license URL, with a licence name set in configuration. + $notice = _('All %1$s content and data are available under the %2$s license.'); + $link = "" . + htmlspecialchars(common_config('license', 'title')) . + ""; + $this->raw(sprintf(htmlspecialchars($notice), + htmlspecialchars(common_config('site', 'name')), + $link)); $this->elementEnd('p'); break; } - $this->elementEnd('dd'); Event::handle('EndShowContentLicense', array($this)); } } @@ -898,7 +1035,6 @@ class Action extends HTMLOutputter // lawsuit * * @return boolean is read only action? */ - function isReadOnly($args) { return false; @@ -945,29 +1081,61 @@ class Action extends HTMLOutputter // lawsuit function handle($argarray=null) { header('Vary: Accept-Encoding,Cookie'); + $lm = $this->lastModified(); $etag = $this->etag(); + if ($etag) { header('ETag: ' . $etag); } + if ($lm) { header('Last-Modified: ' . date(DATE_RFC1123, $lm)); - if (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) { - $if_modified_since = $_SERVER['HTTP_IF_MODIFIED_SINCE']; - $ims = strtotime($if_modified_since); - if ($lm <= $ims) { - $if_none_match = (array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER)) ? - $_SERVER['HTTP_IF_NONE_MATCH'] : null; - if (!$if_none_match || - !$etag || - $this->_hasEtag($etag, $if_none_match)) { - header('HTTP/1.1 304 Not Modified'); - // Better way to do this? - exit(0); - } + if ($this->isCacheable()) { + header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' ); + header( "Cache-Control: private, must-revalidate, max-age=0" ); + header( "Pragma:"); + } + } + + $checked = false; + if ($etag) { + $if_none_match = (array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER)) ? + $_SERVER['HTTP_IF_NONE_MATCH'] : null; + if ($if_none_match) { + // If this check fails, ignore the if-modified-since below. + $checked = true; + if ($this->_hasEtag($etag, $if_none_match)) { + header('HTTP/1.1 304 Not Modified'); + // Better way to do this? + exit(0); } } } + + if (!$checked && $lm && array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) { + $if_modified_since = $_SERVER['HTTP_IF_MODIFIED_SINCE']; + $ims = strtotime($if_modified_since); + if ($lm <= $ims) { + header('HTTP/1.1 304 Not Modified'); + // Better way to do this? + exit(0); + } + } + } + + /** + * Is this action cacheable? + * + * If the action returns a last-modified + * + * @param array $argarray is ignored since it's now passed in in prepare() + * + * @return boolean is read only action? + */ + function isCacheable() + { + return true; } /** @@ -978,7 +1146,6 @@ class Action extends HTMLOutputter // lawsuit * * @return boolean */ - function _hasEtag($etag, $if_none_match) { $etags = explode(',', $if_none_match); @@ -1018,7 +1185,6 @@ class Action extends HTMLOutputter // lawsuit * * @return integer integer value */ - function int($key, $defValue=null, $maxValue=null, $minValue=null) { $arg = strtolower($this->trimmed($key)); @@ -1046,7 +1212,6 @@ class Action extends HTMLOutputter // lawsuit * * @return nothing */ - function serverError($msg, $code=500) { $action = $this->trimmed('action'); @@ -1062,7 +1227,6 @@ class Action extends HTMLOutputter // lawsuit * * @return nothing */ - function clientError($msg, $code=400) { $action = $this->trimmed('action'); @@ -1075,7 +1239,6 @@ class Action extends HTMLOutputter // lawsuit * * @return string current URL */ - function selfUrl() { list($action, $args) = $this->returnToArgs(); @@ -1087,7 +1250,6 @@ class Action extends HTMLOutputter // lawsuit * * @return array two elements: action, other args */ - function returnToArgs() { $action = $this->trimmed('action'); @@ -1147,20 +1309,23 @@ class Action extends HTMLOutputter // lawsuit * * @return nothing */ + // XXX: The messages in this pagination method only tailor to navigating + // notices. In other lists, "Previous"/"Next" type navigation is + // desirable, but not available. function pagination($have_before, $have_after, $page, $action, $args=null) { // Does a little before-after block for next/prev page if ($have_before || $have_after) { - $this->elementStart('dl', 'pagination'); - $this->element('dt', null, _('Pagination')); - $this->elementStart('dd', null); - $this->elementStart('ul', array('class' => 'nav')); + $this->elementStart('ul', array('class' => 'nav', + 'id' => 'pagination')); } if ($have_before) { $pargs = array('page' => $page-1); $this->elementStart('li', array('class' => 'nav_prev')); $this->element('a', array('href' => common_local_url($action, $args, $pargs), 'rel' => 'prev'), + // TRANS: Pagination message to go to a page displaying information more in the + // TRANS: present than the currently displayed information. _('After')); $this->elementEnd('li'); } @@ -1169,13 +1334,13 @@ class Action extends HTMLOutputter // lawsuit $this->elementStart('li', array('class' => 'nav_next')); $this->element('a', array('href' => common_local_url($action, $args, $pargs), 'rel' => 'next'), + // TRANS: Pagination message to go to a page displaying information more in the + // TRANS: past than the currently displayed information. _('Before')); $this->elementEnd('li'); } if ($have_before || $have_after) { $this->elementEnd('ul'); - $this->elementEnd('dd'); - $this->elementEnd('dl'); } } @@ -1186,7 +1351,6 @@ class Action extends HTMLOutputter // lawsuit * * @return array Feed object to show in head and links */ - function getFeeds() { return null; @@ -1197,7 +1361,6 @@ class Action extends HTMLOutputter // lawsuit * * @return Design a design object to use */ - function getDesign() { return Design::siteDesign(); @@ -1211,13 +1374,26 @@ class Action extends HTMLOutputter // lawsuit * * @return void */ - + // XXX: Finding this type of check with the same message about 50 times. + // Possible to refactor? function checkSessionToken() { // CSRF protection $token = $this->trimmed('token'); if (empty($token) || $token != common_session_token()) { + // TRANS: Client error text when there is a problem with the session token. $this->clientError(_('There was a problem with your session token.')); } } + + /** + * Check if the current request is a POST + * + * @return boolean true if POST; otherwise false. + */ + + function isPost() + { + return ($_SERVER['REQUEST_METHOD'] == 'POST'); + } }