}
}
+ function endHTML()
+ {
+ global $_startTime;
+
+ if (isset($_startTime)) {
+ $endTime = microtime(true);
+ $diff = round(($endTime - $_startTime) * 1000);
+ $this->raw("<!-- ${diff}ms -->");
+ }
+
+ return parent::endHTML();
+ }
+
/**
* Show head, a template method.
*
// 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();
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')));
function title()
{
+ // TRANS: Page title for a page without a title set.
return _("Untitled page");
}
$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')) {
if (Event::handle('StartShowStatusNetStyles', array($this)) &&
Event::handle('StartShowLaconicaStyles', array($this))) {
- $this->cssLink('css/display.css',null, 'screen, projection, tv, print');
+ $this->primaryCssLink(null, 'screen, projection, tv, print');
Event::handle('EndShowStatusNetStyles', array($this));
Event::handle('EndShowLaconicaStyles', array($this));
}
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);
}
/**
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));
}
}
+ /**
+ * 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('<div class="deepend"></div><div class="shallow"></div>');
+ * $('#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
*
*
* @return nothing
*/
-
function showFeeds()
{
$feeds = $this->getFeeds();
*/
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();
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();
}
'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');
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');
}
/**
// 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');
}
}
*/
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');
}
/**
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)
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');
}
}
*
* @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');
}
*
* @return void
*/
-
function showExportData()
{
$feeds = $this->getFeeds();
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');
}
*/
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');
}
/**
*/
function showLicenses()
{
- $this->elementStart('dl', array('id' => 'licenses'));
$this->showStatusNetLicense();
$this->showContentLicense();
- $this->elementEnd('dl');
}
/**
*/
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
}
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 = "<a class=\"license\" rel=\"external license\" href=\"" .
+ htmlspecialchars(common_config('license', 'url')) .
+ "\">" .
+ htmlspecialchars(common_config('license', 'title')) .
+ "</a>";
+ $this->raw(sprintf(htmlspecialchars($notice),
+ htmlspecialchars(common_config('site', 'name')),
+ $link));
$this->elementEnd('p');
break;
}
- $this->elementEnd('dd');
Event::handle('EndShowContentLicense', array($this));
}
}
*
* @return boolean is read only action?
*/
-
function isReadOnly($args)
{
return false;
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;
}
/**
*
* @return boolean
*/
-
function _hasEtag($etag, $if_none_match)
{
$etags = explode(',', $if_none_match);
*
* @return integer integer value
*/
-
function int($key, $defValue=null, $maxValue=null, $minValue=null)
{
$arg = strtolower($this->trimmed($key));
*
* @return nothing
*/
-
function serverError($msg, $code=500)
{
$action = $this->trimmed('action');
*
* @return nothing
*/
-
function clientError($msg, $code=400)
{
$action = $this->trimmed('action');
*
* @return string current URL
*/
-
function selfUrl()
{
list($action, $args) = $this->returnToArgs();
*
* @return array two elements: action, other args
*/
-
function returnToArgs()
{
$action = $this->trimmed('action');
*
* @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');
}
$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');
}
}
*
* @return array Feed object to show in head and links
*/
-
function getFeeds()
{
return null;
*
* @return Design a design object to use
*/
-
function getDesign()
{
return Design::siteDesign();
*
* @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');
+ }
}