2004-02-18 02:15:00 +00:00
|
|
|
<?php
|
2012-05-11 08:34:29 +00:00
|
|
|
/**
|
|
|
|
|
* Preparation for the final page rendering.
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
|
|
|
*
|
|
|
|
|
* @file
|
|
|
|
|
*/
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2011-01-13 21:08:59 +00:00
|
|
|
* This class should be covered by a general architecture document which does
|
2011-03-26 15:18:16 +00:00
|
|
|
* not exist as of January 2011. This is one of the Core classes and should
|
2011-01-13 21:08:59 +00:00
|
|
|
* be read at least once by any new developers.
|
|
|
|
|
*
|
|
|
|
|
* This class is used to prepare the final rendering. A skin is then
|
|
|
|
|
* applied to the output parameters (links, javascript, html, categories ...).
|
2011-04-23 19:28:35 +00:00
|
|
|
*
|
2011-05-17 22:03:20 +00:00
|
|
|
* @todo FIXME: Another class handles sending the whole page to the client.
|
2011-04-23 19:28:35 +00:00
|
|
|
*
|
2011-10-24 09:08:13 +00:00
|
|
|
* Some comments comes from a pairing session between Zak Greant and Antoine Musso
|
2011-03-26 15:18:16 +00:00
|
|
|
* in November 2010.
|
2011-01-13 21:08:59 +00:00
|
|
|
*
|
2004-09-02 23:28:24 +00:00
|
|
|
* @todo document
|
|
|
|
|
*/
|
2011-07-30 19:37:19 +00:00
|
|
|
class OutputPage extends ContextSource {
|
2012-07-10 12:48:06 +00:00
|
|
|
/// Should be private. Used with addMeta() which adds "<meta>"
|
2011-01-13 21:08:59 +00:00
|
|
|
var $mMetatags = array();
|
|
|
|
|
|
2012-07-10 12:48:06 +00:00
|
|
|
/// "<meta keywords='stuff'>" most of the time the first 10 links to an article
|
2011-01-13 21:08:59 +00:00
|
|
|
var $mKeywords = array();
|
|
|
|
|
|
2011-01-13 22:08:13 +00:00
|
|
|
var $mLinktags = array();
|
2012-12-31 01:11:43 +00:00
|
|
|
var $mCanonicalUrl = false;
|
2011-01-13 21:08:59 +00:00
|
|
|
|
2011-01-14 07:54:28 +00:00
|
|
|
/// Additional stylesheets. Looks like this is for extensions. Might be replaced by resource loader.
|
2008-08-10 07:14:08 +00:00
|
|
|
var $mExtStyles = array();
|
2011-01-13 22:08:13 +00:00
|
|
|
|
2011-01-14 07:54:28 +00:00
|
|
|
/// Should be private - has getter and setter. Contains the HTML title
|
2011-01-13 21:08:59 +00:00
|
|
|
var $mPagetitle = '';
|
|
|
|
|
|
2012-07-10 12:48:06 +00:00
|
|
|
/// Contains all of the "<body>" content. Should be private we got set/get accessors and the append() method.
|
2011-01-13 21:08:59 +00:00
|
|
|
var $mBodytext = '';
|
2010-07-08 08:12:19 +00:00
|
|
|
|
|
|
|
|
/**
|
2011-03-30 06:35:32 +00:00
|
|
|
* Holds the debug lines that will be output as comments in page source if
|
2010-07-08 08:12:19 +00:00
|
|
|
* $wgDebugComments is enabled. See also $wgShowDebug.
|
2012-08-27 20:57:15 +00:00
|
|
|
* @deprecated since 1.20; use MWDebug class instead.
|
2010-07-08 08:12:19 +00:00
|
|
|
*/
|
2012-08-27 20:57:15 +00:00
|
|
|
public $mDebugtext = '';
|
2011-01-13 21:08:59 +00:00
|
|
|
|
2012-07-10 12:48:06 +00:00
|
|
|
/// Should be private. Stores contents of "<title>" tag
|
2011-01-13 21:08:59 +00:00
|
|
|
var $mHTMLtitle = '';
|
|
|
|
|
|
2011-01-14 07:54:28 +00:00
|
|
|
/// Should be private. Is the displayed content related to the source of the corresponding wiki article.
|
2011-07-27 13:14:28 +00:00
|
|
|
var $mIsarticle = false;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Should be private. Has get/set methods properly documented.
|
|
|
|
|
* Stores "article flag" toggle.
|
|
|
|
|
*/
|
|
|
|
|
var $mIsArticleRelated = true;
|
2011-01-13 21:08:59 +00:00
|
|
|
|
2011-01-14 07:54:28 +00:00
|
|
|
/**
|
|
|
|
|
* Should be private. We have to set isPrintable(). Some pages should
|
|
|
|
|
* never be printed (ex: redirections).
|
2011-01-13 21:08:59 +00:00
|
|
|
*/
|
|
|
|
|
var $mPrintable = false;
|
|
|
|
|
|
2011-01-14 07:54:28 +00:00
|
|
|
/**
|
2011-01-13 21:08:59 +00:00
|
|
|
* Should be private. We have set/get/append methods.
|
|
|
|
|
*
|
2011-01-14 07:54:28 +00:00
|
|
|
* Contains the page subtitle. Special pages usually have some links here.
|
|
|
|
|
* Don't confuse with site subtitle added by skins.
|
2011-01-13 22:20:04 +00:00
|
|
|
*/
|
2011-11-08 18:02:26 +00:00
|
|
|
private $mSubtitle = array();
|
2011-01-13 21:08:59 +00:00
|
|
|
|
|
|
|
|
var $mRedirect = '';
|
|
|
|
|
var $mStatusCode;
|
|
|
|
|
|
2011-01-14 07:54:28 +00:00
|
|
|
/**
|
|
|
|
|
* mLastModified and mEtag are used for sending cache control.
|
2011-03-26 15:18:16 +00:00
|
|
|
* The whole caching system should probably be moved into its own class.
|
2011-01-14 07:54:28 +00:00
|
|
|
*/
|
2011-01-13 21:08:59 +00:00
|
|
|
var $mLastModified = '';
|
2011-01-13 22:08:13 +00:00
|
|
|
|
2011-01-14 07:54:28 +00:00
|
|
|
/**
|
2011-01-13 21:08:59 +00:00
|
|
|
* Should be private. No getter but used in sendCacheControl();
|
|
|
|
|
* Contains an HTTP Entity Tags (see RFC 2616 section 3.13) which is used
|
|
|
|
|
* as a unique identifier for the content. It is later used by the client
|
2011-03-26 15:18:16 +00:00
|
|
|
* to compare its cached version with the server version. Client sends
|
|
|
|
|
* headers If-Match and If-None-Match containing its locally cached ETAG value.
|
2011-01-13 21:08:59 +00:00
|
|
|
*
|
2011-06-19 19:39:54 +00:00
|
|
|
* To get more information, you will have to look at HTTP/1.1 protocol which
|
2011-01-13 21:08:59 +00:00
|
|
|
* is properly described in RFC 2616 : http://tools.ietf.org/html/rfc2616
|
|
|
|
|
*/
|
|
|
|
|
var $mETag = false;
|
|
|
|
|
|
|
|
|
|
var $mCategoryLinks = array();
|
|
|
|
|
var $mCategories = array();
|
|
|
|
|
|
2011-02-16 10:28:24 +00:00
|
|
|
/// Should be private. Array of Interwiki Prefixed (non DB key) Titles (e.g. 'fr:Test page')
|
2011-01-13 21:08:59 +00:00
|
|
|
var $mLanguageLinks = array();
|
|
|
|
|
|
2011-01-14 07:54:28 +00:00
|
|
|
/**
|
|
|
|
|
* Should be private. Used for JavaScript (pre resource loader)
|
2011-01-13 21:08:59 +00:00
|
|
|
* We should split js / css.
|
2012-07-10 12:48:06 +00:00
|
|
|
* mScripts content is inserted as is in "<head>" by Skin. This might
|
|
|
|
|
* contains either a link to a stylesheet or inline css.
|
2011-01-13 21:08:59 +00:00
|
|
|
*/
|
|
|
|
|
var $mScripts = '';
|
2011-01-14 07:54:28 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Inline CSS styles. Use addInlineStyle() sparsingly
|
|
|
|
|
*/
|
|
|
|
|
var $mInlineStyles = '';
|
2011-01-13 21:08:59 +00:00
|
|
|
|
|
|
|
|
//
|
|
|
|
|
var $mLinkColours;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Used by skin template.
|
|
|
|
|
* Example: $tpl->set( 'displaytitle', $out->mPageLinkTitle );
|
|
|
|
|
*/
|
|
|
|
|
var $mPageLinkTitle = '';
|
2010-07-08 08:12:19 +00:00
|
|
|
|
2012-07-10 12:48:06 +00:00
|
|
|
/// Array of elements in "<head>". Parser might add its own headers!
|
2011-01-13 21:08:59 +00:00
|
|
|
var $mHeadItems = array();
|
here it is ... the upload-api, script-server, js2 (javascript phase2) branch merge 1st attempt.
Here is a short overview of changes and associated default configuration variables (most everything is off by default) also see ~soon to be updated~: http://www.mediawiki.org/wiki/Media_Projects_Overview
= Upload Improvements =
==Upload API ==
* Based on the early work of Bryan Tong and others it adds the upload option to the api.
* We rewrite Special:Upload page to include use the new refactoring
* Added in token checks in both the SpecialUpload.php page so avoids DOS / xss copy-by-url JavaScript based cross site POST file submissions
== Copy by URL==
$wgAllowCopyUploads = false;
* http class rewrite includes a new http background download see: includes/HttpFunctions.php
* spins off a php process that calls: maintenance/http_session_download.php
* pushes updates to the session and gives the user a progress bar on http copy uploads from other server progress (using js2 upload interface) (if not using the js2 upload interface it does the request in-place but the download is limited to the php ini timeout time)
== Firefogg ==
* Firefogg enables resumable upload by chunks
* progress indicators and conditional invokation (js2 system)
* and of-course client side transcoding.
= Script Server =
$wgEnableScriptLoader = false;
* off by default if $wgEnableScriptLoader is turned on script files are grouped, gziped, cached etc.
for more info see: http://www.mediawiki.org/wiki/Extension:ScriptLoader
* Includes some early skin js include fixes (skin/script system still lots of love)
* Includes a "javascript class autoloader" this is packaged into mwEmbed so that the mwEmbed library can work in stand alone mode (while retaining localization and script serving) (one such application is the make page for firefogg.org : http://www.firefogg.org/make/index.html )
* The file that contains the autojavascript loading classes is: js2/php/jsAutoloadLocalClasses.php
* One can use this auto class loading dependency system with extensions and add-ons but I need to better document that.
= js2 system / mwEmbed=
$wgEnableJS2system = false
* includes initial rewrite towards more jquery based javascript code
* especially for the Special:Upload page.
* Also the edit page include support for the "add-media-wizard"
* includes dependency loader for javascript that optionally takes advantage of the script-loader
* remote embedding of javascript interfaces (like embedding video, or commons media searching)
* $wgDebugJavaScript = false; .. .this variable lets you always get "always fresh javascript". When used with the script-loader it does not minify the script-loader output.
= mwEmbed =
* Will commit a separate patch to oggHandler that conditionally outputs <video tag> to use the new javascript video player.
** mv_embed player includes: play-head, volume control, remote embedding, oggz-chop support across plugins.
* add-media-wizard adds easy inserts of media to pages (with import)
== jQuery==
* we include a base install of jQuery, jQuery ui and some plugins.
* all the javascript classes are in the scriptloader so its easy to load any set of jquery ui components that you may need using the script-server. You get a callback so you can then execute js with dependencies loaded.
== other stuff ==
there is a bit more code in js2 that pertains to sequence editing, timed text display and basic image editing. We include a base import of pixastic-lib & pixastic-editor... will work with the pixastic developer to try and ensure upstream compatibility on our usage of the library for in-browser photo and sequence manipulation.
2009-07-14 23:52:14 +00:00
|
|
|
|
2011-05-17 22:03:20 +00:00
|
|
|
// @todo FIXME: Next variables probably comes from the resource loader
|
2010-09-04 04:00:09 +00:00
|
|
|
var $mModules = array(), $mModuleScripts = array(), $mModuleStyles = array(), $mModuleMessages = array();
|
2010-09-29 19:04:04 +00:00
|
|
|
var $mResourceLoader;
|
2011-09-28 22:08:08 +00:00
|
|
|
var $mJsConfigVars = array();
|
2011-01-13 22:08:13 +00:00
|
|
|
|
2011-05-17 22:03:20 +00:00
|
|
|
/** @todo FIXME: Is this still used ?*/
|
2009-09-17 01:19:02 +00:00
|
|
|
var $mInlineMsg = array();
|
|
|
|
|
|
2008-07-25 01:27:51 +00:00
|
|
|
var $mTemplateIds = array();
|
2011-03-23 17:35:40 +00:00
|
|
|
var $mImageTimeKeys = array();
|
2006-05-11 22:40:38 +00:00
|
|
|
|
2011-07-25 22:03:08 +00:00
|
|
|
var $mRedirectCode = '';
|
2011-07-06 17:55:44 +00:00
|
|
|
|
2011-07-25 22:03:08 +00:00
|
|
|
var $mFeedLinksAppendQuery = null;
|
2011-07-06 17:55:44 +00:00
|
|
|
|
2011-02-04 16:39:17 +00:00
|
|
|
# What level of 'untrustworthiness' is allowed in CSS/JS modules loaded on this page?
|
|
|
|
|
# @see ResourceLoaderModule::$origin
|
|
|
|
|
# ResourceLoaderModule::ORIGIN_ALL is assumed unless overridden;
|
|
|
|
|
protected $mAllowedModules = array(
|
|
|
|
|
ResourceLoaderModule::TYPE_COMBINED => ResourceLoaderModule::ORIGIN_ALL,
|
|
|
|
|
);
|
2011-01-13 21:08:59 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @EasterEgg I just love the name for this self documenting variable.
|
|
|
|
|
* @todo document
|
|
|
|
|
*/
|
2008-07-25 01:27:51 +00:00
|
|
|
var $mDoNothing = false;
|
2011-01-13 21:08:59 +00:00
|
|
|
|
|
|
|
|
// Parser related.
|
2008-07-25 01:27:51 +00:00
|
|
|
var $mContainsOldMagic = 0, $mContainsNewMagic = 0;
|
2011-01-13 21:08:59 +00:00
|
|
|
|
2011-10-26 03:44:47 +00:00
|
|
|
/**
|
|
|
|
|
* lazy initialised, use parserOptions()
|
|
|
|
|
* @var ParserOptions
|
|
|
|
|
*/
|
2011-01-13 21:08:59 +00:00
|
|
|
protected $mParserOptions = null;
|
|
|
|
|
|
2011-01-14 07:54:28 +00:00
|
|
|
/**
|
2011-01-13 21:08:59 +00:00
|
|
|
* Handles the atom / rss links.
|
|
|
|
|
* We probably only support atom in 2011.
|
|
|
|
|
* Looks like a private variable.
|
2011-01-14 07:54:28 +00:00
|
|
|
* @see $wgAdvertisedFeedTypes
|
2011-01-13 21:08:59 +00:00
|
|
|
*/
|
2009-09-30 17:35:41 +00:00
|
|
|
var $mFeedLinks = array();
|
2009-11-07 09:26:02 +00:00
|
|
|
|
2011-01-13 21:08:59 +00:00
|
|
|
// Gwicke work on squid caching? Roughly from 2003.
|
2006-05-11 22:40:38 +00:00
|
|
|
var $mEnableClientCache = true;
|
2011-01-13 21:08:59 +00:00
|
|
|
|
2011-01-14 07:54:28 +00:00
|
|
|
/**
|
2011-01-13 21:08:59 +00:00
|
|
|
* Flag if output should only contain the body of the article.
|
|
|
|
|
* Should be private.
|
|
|
|
|
*/
|
2006-05-11 22:40:38 +00:00
|
|
|
var $mArticleBodyOnly = false;
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2006-05-11 22:40:38 +00:00
|
|
|
var $mNewSectionLink = false;
|
2009-02-19 22:14:59 +00:00
|
|
|
var $mHideNewSectionLink = false;
|
2011-01-13 21:08:59 +00:00
|
|
|
|
2011-01-14 07:54:28 +00:00
|
|
|
/**
|
|
|
|
|
* Comes from the parser. This was probably made to load CSS/JS only
|
2012-07-10 12:48:06 +00:00
|
|
|
* if we had "<gallery>". Used directly in CategoryPage.php
|
2011-01-13 21:08:59 +00:00
|
|
|
* Looks like resource loader can replace this.
|
|
|
|
|
*/
|
2006-06-13 18:35:11 +00:00
|
|
|
var $mNoGallery = false;
|
2011-01-13 21:08:59 +00:00
|
|
|
|
|
|
|
|
// should be private.
|
2007-07-22 14:45:12 +00:00
|
|
|
var $mPageTitleActionText = '';
|
2007-12-10 06:02:29 +00:00
|
|
|
var $mParseWarnings = array();
|
2011-01-13 21:08:59 +00:00
|
|
|
|
|
|
|
|
// Cache stuff. Looks like mEnableClientCache
|
2008-07-25 01:27:51 +00:00
|
|
|
var $mSquidMaxage = 0;
|
2011-01-13 21:08:59 +00:00
|
|
|
|
|
|
|
|
// @todo document
|
2011-01-04 06:12:33 +00:00
|
|
|
var $mPreventClickjacking = true;
|
2011-01-13 21:08:59 +00:00
|
|
|
|
2011-01-14 07:54:28 +00:00
|
|
|
/// should be private. To include the variable {{REVISIONID}}
|
2008-07-25 01:27:51 +00:00
|
|
|
var $mRevisionId = null;
|
2011-12-10 16:30:40 +00:00
|
|
|
private $mRevisionTimestamp = null;
|
2011-01-13 21:08:59 +00:00
|
|
|
|
2011-07-05 05:23:26 +00:00
|
|
|
var $mFileVersion = null;
|
|
|
|
|
|
2008-08-21 14:09:57 +00:00
|
|
|
/**
|
|
|
|
|
* An array of stylesheet filenames (relative from skins path), with options
|
|
|
|
|
* for CSS media, IE conditions, and RTL/LTR direction.
|
|
|
|
|
* For internal use; add settings in the skin via $this->addStyle()
|
2011-01-13 21:08:59 +00:00
|
|
|
*
|
|
|
|
|
* Style again! This seems like a code duplication since we already have
|
|
|
|
|
* mStyles. This is what makes OpenSource amazing.
|
2008-08-21 14:09:57 +00:00
|
|
|
*/
|
|
|
|
|
var $styles = array();
|
|
|
|
|
|
2010-01-23 20:11:42 +00:00
|
|
|
/**
|
2011-01-14 07:54:28 +00:00
|
|
|
* Whether jQuery is already handled.
|
2010-01-23 20:11:42 +00:00
|
|
|
*/
|
2010-01-27 04:17:49 +00:00
|
|
|
protected $mJQueryDone = false;
|
2010-01-23 20:11:42 +00:00
|
|
|
|
2008-07-23 19:05:43 +00:00
|
|
|
private $mIndexPolicy = 'index';
|
|
|
|
|
private $mFollowPolicy = 'follow';
|
2010-05-22 12:18:22 +00:00
|
|
|
private $mVaryHeader = array(
|
|
|
|
|
'Accept-Encoding' => array( 'list-contains=gzip' ),
|
|
|
|
|
);
|
2010-01-28 21:58:50 +00:00
|
|
|
|
2011-11-30 12:43:10 +00:00
|
|
|
/**
|
|
|
|
|
* If the current page was reached through a redirect, $mRedirectedFrom contains the Title
|
|
|
|
|
* of the redirect.
|
|
|
|
|
*
|
|
|
|
|
* @var Title
|
|
|
|
|
*/
|
|
|
|
|
private $mRedirectedFrom = null;
|
|
|
|
|
|
2013-02-08 22:58:38 +00:00
|
|
|
/**
|
|
|
|
|
* Additional key => value data
|
|
|
|
|
*/
|
|
|
|
|
private $mProperties = array();
|
|
|
|
|
|
2011-04-04 00:37:42 +00:00
|
|
|
/**
|
|
|
|
|
* Constructor for OutputPage. This should not be called directly.
|
|
|
|
|
* Instead a new RequestContext should be created and it will implicitly create
|
|
|
|
|
* a OutputPage tied to that context.
|
|
|
|
|
*/
|
2011-09-15 15:19:49 +00:00
|
|
|
function __construct( IContextSource $context = null ) {
|
2011-07-30 19:37:19 +00:00
|
|
|
if ( $context === null ) {
|
2011-04-04 00:37:42 +00:00
|
|
|
# Extensions should use `new RequestContext` instead of `new OutputPage` now.
|
2012-10-05 18:26:00 +00:00
|
|
|
wfDeprecated( __METHOD__, '1.18' );
|
2011-07-30 19:37:19 +00:00
|
|
|
} else {
|
|
|
|
|
$this->setContext( $context );
|
2011-04-04 00:37:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
|
|
|
|
* Redirect to $url rather than displaying the normal page
|
|
|
|
|
*
|
|
|
|
|
* @param $url String: URL
|
|
|
|
|
* @param $responsecode String: HTTP status code
|
|
|
|
|
*/
|
2006-11-07 05:37:31 +00:00
|
|
|
public function redirect( $url, $responsecode = '302' ) {
|
2006-06-23 03:56:03 +00:00
|
|
|
# Strip newlines as a paranoia check for header injection in PHP<5.1.2
|
|
|
|
|
$this->mRedirect = str_replace( "\n", '', $url );
|
|
|
|
|
$this->mRedirectCode = $responsecode;
|
|
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
|
|
|
|
* Get the URL to redirect to, or an empty string if not redirect URL set
|
|
|
|
|
*
|
|
|
|
|
* @return String
|
|
|
|
|
*/
|
2007-11-06 01:16:25 +00:00
|
|
|
public function getRedirect() {
|
|
|
|
|
return $this->mRedirect;
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2006-11-07 05:37:31 +00:00
|
|
|
/**
|
|
|
|
|
* Set the HTTP status code to send with the output.
|
|
|
|
|
*
|
2010-01-28 21:58:50 +00:00
|
|
|
* @param $statusCode Integer
|
2006-11-07 05:37:31 +00:00
|
|
|
*/
|
2010-01-28 21:58:50 +00:00
|
|
|
public function setStatusCode( $statusCode ) {
|
|
|
|
|
$this->mStatusCode = $statusCode;
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-21 14:09:57 +00:00
|
|
|
/**
|
2012-07-10 12:48:06 +00:00
|
|
|
* Add a new "<meta>" tag
|
2008-08-21 14:09:57 +00:00
|
|
|
* To add an http-equiv meta tag, precede the name with "http:"
|
|
|
|
|
*
|
2011-01-14 07:54:28 +00:00
|
|
|
* @param $name String tag name
|
|
|
|
|
* @param $val String tag value
|
2008-08-21 14:09:57 +00:00
|
|
|
*/
|
|
|
|
|
function addMeta( $name, $val ) {
|
|
|
|
|
array_push( $this->mMetatags, array( $name, $val ) );
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
|
|
|
|
* Add a keyword or a list of keywords in the page header
|
|
|
|
|
*
|
|
|
|
|
* @param $text String or array of strings
|
|
|
|
|
*/
|
2009-05-30 05:07:46 +00:00
|
|
|
function addKeyword( $text ) {
|
2010-01-28 21:58:50 +00:00
|
|
|
if( is_array( $text ) ) {
|
2009-05-30 05:07:46 +00:00
|
|
|
$this->mKeywords = array_merge( $this->mKeywords, $text );
|
2009-07-15 00:55:58 +00:00
|
|
|
} else {
|
2009-05-30 05:07:46 +00:00
|
|
|
array_push( $this->mKeywords, $text );
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-01-28 21:58:50 +00:00
|
|
|
|
|
|
|
|
/**
|
2012-12-31 01:11:43 +00:00
|
|
|
* Add a new \<link\> tag to the page header.
|
|
|
|
|
*
|
|
|
|
|
* Note: use setCanonicalUrl() for rel=canonical.
|
2010-01-28 21:58:50 +00:00
|
|
|
*
|
|
|
|
|
* @param $linkarr Array: associative array of attributes.
|
|
|
|
|
*/
|
|
|
|
|
function addLink( $linkarr ) {
|
|
|
|
|
array_push( $this->mLinktags, $linkarr );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add a new \<link\> with "rel" attribute set to "meta"
|
|
|
|
|
*
|
|
|
|
|
* @param $linkarr Array: associative array mapping attribute names to their
|
|
|
|
|
* values, both keys and values will be escaped, and the
|
|
|
|
|
* "rel" attribute will be automatically added
|
|
|
|
|
*/
|
|
|
|
|
function addMetadataLink( $linkarr ) {
|
2011-04-02 18:38:42 +00:00
|
|
|
$linkarr['rel'] = $this->getMetadataAttribute();
|
|
|
|
|
$this->addLink( $linkarr );
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-31 01:11:43 +00:00
|
|
|
/**
|
|
|
|
|
* Set the URL to be used for the <link rel=canonical>. This should be used
|
|
|
|
|
* in preference to addLink(), to avoid duplicate link tags.
|
|
|
|
|
*/
|
|
|
|
|
function setCanonicalUrl( $url ) {
|
|
|
|
|
$this->mCanonicalUrl = $url;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-02 18:38:42 +00:00
|
|
|
/**
|
|
|
|
|
* Get the value of the "rel" attribute for metadata links
|
|
|
|
|
*
|
|
|
|
|
* @return String
|
|
|
|
|
*/
|
2011-05-26 00:57:54 +00:00
|
|
|
public function getMetadataAttribute() {
|
2010-01-28 21:58:50 +00:00
|
|
|
# note: buggy CC software only reads first "meta" link
|
|
|
|
|
static $haveMeta = false;
|
2011-04-02 18:38:42 +00:00
|
|
|
if ( $haveMeta ) {
|
|
|
|
|
return 'alternate meta';
|
|
|
|
|
} else {
|
|
|
|
|
$haveMeta = true;
|
|
|
|
|
return 'meta';
|
|
|
|
|
}
|
2010-01-28 21:58:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add raw HTML to the list of scripts (including \<script\> tag, etc.)
|
|
|
|
|
*
|
|
|
|
|
* @param $script String: raw HTML
|
|
|
|
|
*/
|
2009-08-07 00:16:54 +00:00
|
|
|
function addScript( $script ) {
|
2009-08-22 20:15:22 +00:00
|
|
|
$this->mScripts .= $script . "\n";
|
2009-08-07 00:16:54 +00:00
|
|
|
}
|
here it is ... the upload-api, script-server, js2 (javascript phase2) branch merge 1st attempt.
Here is a short overview of changes and associated default configuration variables (most everything is off by default) also see ~soon to be updated~: http://www.mediawiki.org/wiki/Media_Projects_Overview
= Upload Improvements =
==Upload API ==
* Based on the early work of Bryan Tong and others it adds the upload option to the api.
* We rewrite Special:Upload page to include use the new refactoring
* Added in token checks in both the SpecialUpload.php page so avoids DOS / xss copy-by-url JavaScript based cross site POST file submissions
== Copy by URL==
$wgAllowCopyUploads = false;
* http class rewrite includes a new http background download see: includes/HttpFunctions.php
* spins off a php process that calls: maintenance/http_session_download.php
* pushes updates to the session and gives the user a progress bar on http copy uploads from other server progress (using js2 upload interface) (if not using the js2 upload interface it does the request in-place but the download is limited to the php ini timeout time)
== Firefogg ==
* Firefogg enables resumable upload by chunks
* progress indicators and conditional invokation (js2 system)
* and of-course client side transcoding.
= Script Server =
$wgEnableScriptLoader = false;
* off by default if $wgEnableScriptLoader is turned on script files are grouped, gziped, cached etc.
for more info see: http://www.mediawiki.org/wiki/Extension:ScriptLoader
* Includes some early skin js include fixes (skin/script system still lots of love)
* Includes a "javascript class autoloader" this is packaged into mwEmbed so that the mwEmbed library can work in stand alone mode (while retaining localization and script serving) (one such application is the make page for firefogg.org : http://www.firefogg.org/make/index.html )
* The file that contains the autojavascript loading classes is: js2/php/jsAutoloadLocalClasses.php
* One can use this auto class loading dependency system with extensions and add-ons but I need to better document that.
= js2 system / mwEmbed=
$wgEnableJS2system = false
* includes initial rewrite towards more jquery based javascript code
* especially for the Special:Upload page.
* Also the edit page include support for the "add-media-wizard"
* includes dependency loader for javascript that optionally takes advantage of the script-loader
* remote embedding of javascript interfaces (like embedding video, or commons media searching)
* $wgDebugJavaScript = false; .. .this variable lets you always get "always fresh javascript". When used with the script-loader it does not minify the script-loader output.
= mwEmbed =
* Will commit a separate patch to oggHandler that conditionally outputs <video tag> to use the new javascript video player.
** mv_embed player includes: play-head, volume control, remote embedding, oggz-chop support across plugins.
* add-media-wizard adds easy inserts of media to pages (with import)
== jQuery==
* we include a base install of jQuery, jQuery ui and some plugins.
* all the javascript classes are in the scriptloader so its easy to load any set of jquery ui components that you may need using the script-server. You get a callback so you can then execute js with dependencies loaded.
== other stuff ==
there is a bit more code in js2 that pertains to sequence editing, timed text display and basic image editing. We include a base import of pixastic-lib & pixastic-editor... will work with the pixastic developer to try and ensure upstream compatibility on our usage of the library for in-browser photo and sequence manipulation.
2009-07-14 23:52:14 +00:00
|
|
|
|
2009-07-26 16:57:45 +00:00
|
|
|
/**
|
2009-08-07 00:16:54 +00:00
|
|
|
* Register and add a stylesheet from an extension directory.
|
2010-01-28 21:58:50 +00:00
|
|
|
*
|
2009-07-26 16:57:45 +00:00
|
|
|
* @param $url String path to sheet. Provide either a full url (beginning
|
|
|
|
|
* with 'http', etc) or a relative path from the document root
|
|
|
|
|
* (beginning with '/'). Otherwise it behaves identically to
|
|
|
|
|
* addStyle() and draws from the /skins folder.
|
|
|
|
|
*/
|
|
|
|
|
public function addExtensionStyle( $url ) {
|
2009-08-11 00:09:24 +00:00
|
|
|
array_push( $this->mExtStyles, $url );
|
2008-08-10 07:14:08 +00:00
|
|
|
}
|
2006-12-08 06:09:15 +00:00
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
2011-01-14 07:54:28 +00:00
|
|
|
* Get all styles added by extensions
|
2010-01-28 21:58:50 +00:00
|
|
|
*
|
|
|
|
|
* @return Array
|
|
|
|
|
*/
|
|
|
|
|
function getExtStyle() {
|
|
|
|
|
return $this->mExtStyles;
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-09 20:18:35 +00:00
|
|
|
/**
|
|
|
|
|
* Add a JavaScript file out of skins/common, or a given relative path.
|
2010-01-28 21:58:50 +00:00
|
|
|
*
|
|
|
|
|
* @param $file String: filename in skins/common or complete on-server path
|
|
|
|
|
* (/foo/bar.js)
|
2010-06-04 19:13:16 +00:00
|
|
|
* @param $version String: style version of the file. Defaults to $wgStyleVersion
|
2008-05-09 20:18:35 +00:00
|
|
|
*/
|
2010-06-04 19:13:16 +00:00
|
|
|
public function addScriptFile( $file, $version = null ) {
|
2010-01-24 19:43:02 +00:00
|
|
|
global $wgStylePath, $wgStyleVersion;
|
2010-08-20 01:47:52 +00:00
|
|
|
// See if $file parameter is an absolute URL or begins with a slash
|
2010-02-26 02:41:49 +00:00
|
|
|
if( substr( $file, 0, 1 ) == '/' || preg_match( '#^[a-z]*://#i', $file ) ) {
|
2008-05-09 20:18:35 +00:00
|
|
|
$path = $file;
|
|
|
|
|
} else {
|
2010-05-22 12:18:22 +00:00
|
|
|
$path = "{$wgStylePath}/common/{$file}";
|
here it is ... the upload-api, script-server, js2 (javascript phase2) branch merge 1st attempt.
Here is a short overview of changes and associated default configuration variables (most everything is off by default) also see ~soon to be updated~: http://www.mediawiki.org/wiki/Media_Projects_Overview
= Upload Improvements =
==Upload API ==
* Based on the early work of Bryan Tong and others it adds the upload option to the api.
* We rewrite Special:Upload page to include use the new refactoring
* Added in token checks in both the SpecialUpload.php page so avoids DOS / xss copy-by-url JavaScript based cross site POST file submissions
== Copy by URL==
$wgAllowCopyUploads = false;
* http class rewrite includes a new http background download see: includes/HttpFunctions.php
* spins off a php process that calls: maintenance/http_session_download.php
* pushes updates to the session and gives the user a progress bar on http copy uploads from other server progress (using js2 upload interface) (if not using the js2 upload interface it does the request in-place but the download is limited to the php ini timeout time)
== Firefogg ==
* Firefogg enables resumable upload by chunks
* progress indicators and conditional invokation (js2 system)
* and of-course client side transcoding.
= Script Server =
$wgEnableScriptLoader = false;
* off by default if $wgEnableScriptLoader is turned on script files are grouped, gziped, cached etc.
for more info see: http://www.mediawiki.org/wiki/Extension:ScriptLoader
* Includes some early skin js include fixes (skin/script system still lots of love)
* Includes a "javascript class autoloader" this is packaged into mwEmbed so that the mwEmbed library can work in stand alone mode (while retaining localization and script serving) (one such application is the make page for firefogg.org : http://www.firefogg.org/make/index.html )
* The file that contains the autojavascript loading classes is: js2/php/jsAutoloadLocalClasses.php
* One can use this auto class loading dependency system with extensions and add-ons but I need to better document that.
= js2 system / mwEmbed=
$wgEnableJS2system = false
* includes initial rewrite towards more jquery based javascript code
* especially for the Special:Upload page.
* Also the edit page include support for the "add-media-wizard"
* includes dependency loader for javascript that optionally takes advantage of the script-loader
* remote embedding of javascript interfaces (like embedding video, or commons media searching)
* $wgDebugJavaScript = false; .. .this variable lets you always get "always fresh javascript". When used with the script-loader it does not minify the script-loader output.
= mwEmbed =
* Will commit a separate patch to oggHandler that conditionally outputs <video tag> to use the new javascript video player.
** mv_embed player includes: play-head, volume control, remote embedding, oggz-chop support across plugins.
* add-media-wizard adds easy inserts of media to pages (with import)
== jQuery==
* we include a base install of jQuery, jQuery ui and some plugins.
* all the javascript classes are in the scriptloader so its easy to load any set of jquery ui components that you may need using the script-server. You get a callback so you can then execute js with dependencies loaded.
== other stuff ==
there is a bit more code in js2 that pertains to sequence editing, timed text display and basic image editing. We include a base import of pixastic-lib & pixastic-editor... will work with the pixastic developer to try and ensure upstream compatibility on our usage of the library for in-browser photo and sequence manipulation.
2009-07-14 23:52:14 +00:00
|
|
|
}
|
2010-06-04 19:13:16 +00:00
|
|
|
if ( is_null( $version ) )
|
|
|
|
|
$version = $wgStyleVersion;
|
|
|
|
|
$this->addScript( Html::linkedScript( wfAppendQuery( $path, $version ) ) );
|
2008-05-09 20:18:35 +00:00
|
|
|
}
|
2009-07-15 00:55:58 +00:00
|
|
|
|
2006-12-08 06:09:15 +00:00
|
|
|
/**
|
|
|
|
|
* Add a self-contained script tag with the given contents
|
2010-01-28 21:58:50 +00:00
|
|
|
*
|
2012-07-10 12:48:06 +00:00
|
|
|
* @param $script String: JavaScript text, no "<script>" tags
|
2006-12-08 06:09:15 +00:00
|
|
|
*/
|
2010-01-28 21:58:50 +00:00
|
|
|
public function addInlineScript( $script ) {
|
2009-08-22 20:15:22 +00:00
|
|
|
$this->mScripts .= Html::inlineScript( "\n$script\n" ) . "\n";
|
2006-12-08 06:09:15 +00:00
|
|
|
}
|
|
|
|
|
|
2009-09-10 06:43:01 +00:00
|
|
|
/**
|
|
|
|
|
* Get all registered JS and CSS tags for the header.
|
2010-01-28 21:58:50 +00:00
|
|
|
*
|
|
|
|
|
* @return String
|
2009-09-10 06:43:01 +00:00
|
|
|
*/
|
2008-04-14 07:45:50 +00:00
|
|
|
function getScript() {
|
2009-11-26 12:00:36 +00:00
|
|
|
return $this->mScripts . $this->getHeadItems();
|
2007-04-03 21:58:18 +00:00
|
|
|
}
|
|
|
|
|
|
2011-02-04 16:39:17 +00:00
|
|
|
/**
|
2011-03-19 21:19:50 +00:00
|
|
|
* Filter an array of modules to remove insufficiently trustworthy members, and modules
|
|
|
|
|
* which are no longer registered (eg a page is cached before an extension is disabled)
|
2011-02-04 16:39:17 +00:00
|
|
|
* @param $modules Array
|
2011-04-07 12:07:25 +00:00
|
|
|
* @param $position String if not null, only return modules with this position
|
2011-05-21 19:07:24 +00:00
|
|
|
* @param $type string
|
2011-02-04 16:39:17 +00:00
|
|
|
* @return Array
|
|
|
|
|
*/
|
2012-12-20 15:09:25 +00:00
|
|
|
protected function filterModules( $modules, $position = null, $type = ResourceLoaderModule::TYPE_COMBINED ) {
|
2011-02-04 16:39:17 +00:00
|
|
|
$resourceLoader = $this->getResourceLoader();
|
|
|
|
|
$filteredModules = array();
|
2013-01-26 18:32:03 +00:00
|
|
|
foreach( $modules as $val ) {
|
2011-02-04 16:39:17 +00:00
|
|
|
$module = $resourceLoader->getModule( $val );
|
2011-03-19 21:19:50 +00:00
|
|
|
if( $module instanceof ResourceLoaderModule
|
2011-04-07 12:07:25 +00:00
|
|
|
&& $module->getOrigin() <= $this->getAllowedModules( $type )
|
|
|
|
|
&& ( is_null( $position ) || $module->getPosition() == $position ) )
|
2011-03-19 21:19:50 +00:00
|
|
|
{
|
2011-02-04 16:39:17 +00:00
|
|
|
$filteredModules[] = $val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return $filteredModules;
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-04 04:00:09 +00:00
|
|
|
/**
|
|
|
|
|
* Get the list of modules to include on this page
|
2010-09-07 21:05:09 +00:00
|
|
|
*
|
2011-02-04 16:39:17 +00:00
|
|
|
* @param $filter Bool whether to filter out insufficiently trustworthy modules
|
2011-04-07 12:07:25 +00:00
|
|
|
* @param $position String if not null, only return modules with this position
|
2011-05-21 19:07:24 +00:00
|
|
|
* @param $param string
|
2010-09-07 21:05:09 +00:00
|
|
|
* @return Array of module names
|
2010-09-04 04:00:09 +00:00
|
|
|
*/
|
2011-04-07 12:07:25 +00:00
|
|
|
public function getModules( $filter = false, $position = null, $param = 'mModules' ) {
|
2011-02-04 16:39:17 +00:00
|
|
|
$modules = array_values( array_unique( $this->$param ) );
|
|
|
|
|
return $filter
|
2011-04-07 12:07:25 +00:00
|
|
|
? $this->filterModules( $modules, $position )
|
2011-02-04 16:39:17 +00:00
|
|
|
: $modules;
|
2010-09-04 04:00:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add one or more modules recognized by the resource loader. Modules added
|
|
|
|
|
* through this function will be loaded by the resource loader when the
|
|
|
|
|
* page loads.
|
2010-09-07 21:05:09 +00:00
|
|
|
*
|
|
|
|
|
* @param $modules Mixed: module name (string) or array of module names
|
2010-09-04 04:00:09 +00:00
|
|
|
*/
|
|
|
|
|
public function addModules( $modules ) {
|
|
|
|
|
$this->mModules = array_merge( $this->mModules, (array)$modules );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the list of module JS to include on this page
|
2011-05-21 19:07:24 +00:00
|
|
|
*
|
|
|
|
|
* @param $filter
|
|
|
|
|
* @param $position
|
|
|
|
|
*
|
2010-09-04 04:00:09 +00:00
|
|
|
* @return array of module names
|
|
|
|
|
*/
|
2011-04-07 12:07:25 +00:00
|
|
|
public function getModuleScripts( $filter = false, $position = null ) {
|
|
|
|
|
return $this->getModules( $filter, $position, 'mModuleScripts' );
|
2010-09-04 04:00:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add only JS of one or more modules recognized by the resource loader. Module
|
|
|
|
|
* scripts added through this function will be loaded by the resource loader when
|
|
|
|
|
* the page loads.
|
2010-09-07 21:05:09 +00:00
|
|
|
*
|
|
|
|
|
* @param $modules Mixed: module name (string) or array of module names
|
2010-09-04 04:00:09 +00:00
|
|
|
*/
|
|
|
|
|
public function addModuleScripts( $modules ) {
|
|
|
|
|
$this->mModuleScripts = array_merge( $this->mModuleScripts, (array)$modules );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the list of module CSS to include on this page
|
2010-09-07 21:05:09 +00:00
|
|
|
*
|
2011-05-21 19:07:24 +00:00
|
|
|
* @param $filter
|
|
|
|
|
* @param $position
|
2011-07-18 23:01:08 +00:00
|
|
|
*
|
2010-09-07 21:05:09 +00:00
|
|
|
* @return Array of module names
|
2010-09-04 04:00:09 +00:00
|
|
|
*/
|
2011-04-07 12:07:25 +00:00
|
|
|
public function getModuleStyles( $filter = false, $position = null ) {
|
2013-01-26 18:32:03 +00:00
|
|
|
return $this->getModules( $filter, $position, 'mModuleStyles' );
|
2010-09-04 04:00:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add only CSS of one or more modules recognized by the resource loader. Module
|
|
|
|
|
* styles added through this function will be loaded by the resource loader when
|
|
|
|
|
* the page loads.
|
2010-09-07 21:05:09 +00:00
|
|
|
*
|
|
|
|
|
* @param $modules Mixed: module name (string) or array of module names
|
2010-09-04 04:00:09 +00:00
|
|
|
*/
|
|
|
|
|
public function addModuleStyles( $modules ) {
|
|
|
|
|
$this->mModuleStyles = array_merge( $this->mModuleStyles, (array)$modules );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the list of module messages to include on this page
|
2010-09-07 21:05:09 +00:00
|
|
|
*
|
2011-05-21 19:07:24 +00:00
|
|
|
* @param $filter
|
|
|
|
|
* @param $position
|
|
|
|
|
*
|
2010-09-07 21:05:09 +00:00
|
|
|
* @return Array of module names
|
2010-09-04 04:00:09 +00:00
|
|
|
*/
|
2011-04-07 12:07:25 +00:00
|
|
|
public function getModuleMessages( $filter = false, $position = null ) {
|
|
|
|
|
return $this->getModules( $filter, $position, 'mModuleMessages' );
|
2010-09-04 04:00:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add only messages of one or more modules recognized by the resource loader.
|
|
|
|
|
* Module messages added through this function will be loaded by the resource
|
|
|
|
|
* loader when the page loads.
|
2010-09-07 21:05:09 +00:00
|
|
|
*
|
|
|
|
|
* @param $modules Mixed: module name (string) or array of module names
|
2010-09-04 04:00:09 +00:00
|
|
|
*/
|
|
|
|
|
public function addModuleMessages( $modules ) {
|
|
|
|
|
$this->mModuleMessages = array_merge( $this->mModuleMessages, (array)$modules );
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-02 15:40:03 +00:00
|
|
|
/**
|
|
|
|
|
* Get an array of head items
|
|
|
|
|
*
|
|
|
|
|
* @return Array
|
|
|
|
|
*/
|
|
|
|
|
function getHeadItemsArray() {
|
|
|
|
|
return $this->mHeadItems;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
|
|
|
|
* Get all header items in a string
|
|
|
|
|
*
|
|
|
|
|
* @return String
|
|
|
|
|
*/
|
2007-04-03 21:58:18 +00:00
|
|
|
function getHeadItems() {
|
|
|
|
|
$s = '';
|
|
|
|
|
foreach ( $this->mHeadItems as $item ) {
|
|
|
|
|
$s .= $item;
|
|
|
|
|
}
|
|
|
|
|
return $s;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
|
|
|
|
* Add or replace an header item to the output
|
|
|
|
|
*
|
|
|
|
|
* @param $name String: item name
|
|
|
|
|
* @param $value String: raw HTML
|
|
|
|
|
*/
|
|
|
|
|
public function addHeadItem( $name, $value ) {
|
2007-04-29 10:15:05 +00:00
|
|
|
$this->mHeadItems[$name] = $value;
|
|
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
|
|
|
|
* Check if the header item $name is already set
|
|
|
|
|
*
|
|
|
|
|
* @param $name String: item name
|
|
|
|
|
* @return Boolean
|
|
|
|
|
*/
|
|
|
|
|
public function hasHeadItem( $name ) {
|
Basic integrated audio/video support, with Ogg implementation.
* JavaScript video player based loosely on Greg Maxwell's player
* Image page text snippet customisation
* Abstraction of transform parameters in the parser. Introduced Linker::makeImageLink2().
* Made canRender(), mustRender() depend on file, not just on handler. Moved width=0, height=0 checking to ImageHandler::canRender(), since audio streams have width=height=0 but should be rendered.
Also:
* Automatic upgrade for oldimage rows on image page view, allows media handler selection based on oi_*_mime
* oi_*_mime unconditionally referenced, REQUIRES SCHEMA UPGRADE
* Don't destroy file info for missing files on upgrade
* Simple, centralised extension message file handling
* Made MessageCache::loadAllMessages non-static, optimised for repeated-call case due to abuse in User.php
* Support for lightweight parser output hooks, with callback whitelist for security
* Moved Linker::formatSize() to Language, to join the new formatTimePeriod() and formatBitrate()
* Introduced MagicWordArray, regex capture trick requires that magic word IDs DO NOT CONTAIN HYPHENS.
2007-08-15 10:50:09 +00:00
|
|
|
return isset( $this->mHeadItems[$name] );
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
|
|
|
|
* Set the value of the ETag HTTP header, only used if $wgUseETag is true
|
|
|
|
|
*
|
|
|
|
|
* @param $tag String: value of "ETag" header
|
|
|
|
|
*/
|
|
|
|
|
function setETag( $tag ) {
|
|
|
|
|
$this->mETag = $tag;
|
2004-04-10 11:19:33 +00:00
|
|
|
}
|
here it is ... the upload-api, script-server, js2 (javascript phase2) branch merge 1st attempt.
Here is a short overview of changes and associated default configuration variables (most everything is off by default) also see ~soon to be updated~: http://www.mediawiki.org/wiki/Media_Projects_Overview
= Upload Improvements =
==Upload API ==
* Based on the early work of Bryan Tong and others it adds the upload option to the api.
* We rewrite Special:Upload page to include use the new refactoring
* Added in token checks in both the SpecialUpload.php page so avoids DOS / xss copy-by-url JavaScript based cross site POST file submissions
== Copy by URL==
$wgAllowCopyUploads = false;
* http class rewrite includes a new http background download see: includes/HttpFunctions.php
* spins off a php process that calls: maintenance/http_session_download.php
* pushes updates to the session and gives the user a progress bar on http copy uploads from other server progress (using js2 upload interface) (if not using the js2 upload interface it does the request in-place but the download is limited to the php ini timeout time)
== Firefogg ==
* Firefogg enables resumable upload by chunks
* progress indicators and conditional invokation (js2 system)
* and of-course client side transcoding.
= Script Server =
$wgEnableScriptLoader = false;
* off by default if $wgEnableScriptLoader is turned on script files are grouped, gziped, cached etc.
for more info see: http://www.mediawiki.org/wiki/Extension:ScriptLoader
* Includes some early skin js include fixes (skin/script system still lots of love)
* Includes a "javascript class autoloader" this is packaged into mwEmbed so that the mwEmbed library can work in stand alone mode (while retaining localization and script serving) (one such application is the make page for firefogg.org : http://www.firefogg.org/make/index.html )
* The file that contains the autojavascript loading classes is: js2/php/jsAutoloadLocalClasses.php
* One can use this auto class loading dependency system with extensions and add-ons but I need to better document that.
= js2 system / mwEmbed=
$wgEnableJS2system = false
* includes initial rewrite towards more jquery based javascript code
* especially for the Special:Upload page.
* Also the edit page include support for the "add-media-wizard"
* includes dependency loader for javascript that optionally takes advantage of the script-loader
* remote embedding of javascript interfaces (like embedding video, or commons media searching)
* $wgDebugJavaScript = false; .. .this variable lets you always get "always fresh javascript". When used with the script-loader it does not minify the script-loader output.
= mwEmbed =
* Will commit a separate patch to oggHandler that conditionally outputs <video tag> to use the new javascript video player.
** mv_embed player includes: play-head, volume control, remote embedding, oggz-chop support across plugins.
* add-media-wizard adds easy inserts of media to pages (with import)
== jQuery==
* we include a base install of jQuery, jQuery ui and some plugins.
* all the javascript classes are in the scriptloader so its easy to load any set of jquery ui components that you may need using the script-server. You get a callback so you can then execute js with dependencies loaded.
== other stuff ==
there is a bit more code in js2 that pertains to sequence editing, timed text display and basic image editing. We include a base import of pixastic-lib & pixastic-editor... will work with the pixastic developer to try and ensure upstream compatibility on our usage of the library for in-browser photo and sequence manipulation.
2009-07-14 23:52:14 +00:00
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
|
|
|
|
* Set whether the output should only contain the body of the article,
|
|
|
|
|
* without any skin, sidebar, etc.
|
2010-02-01 18:04:17 +00:00
|
|
|
* Used e.g. when calling with "action=render".
|
2010-01-28 21:58:50 +00:00
|
|
|
*
|
|
|
|
|
* @param $only Boolean: whether to output only the body of the article
|
|
|
|
|
*/
|
|
|
|
|
public function setArticleBodyOnly( $only ) {
|
|
|
|
|
$this->mArticleBodyOnly = $only;
|
2008-08-10 07:14:08 +00:00
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
|
|
|
|
* Return whether the output will contain only the body of the article
|
|
|
|
|
*
|
|
|
|
|
* @return Boolean
|
|
|
|
|
*/
|
|
|
|
|
public function getArticleBodyOnly() {
|
|
|
|
|
return $this->mArticleBodyOnly;
|
2004-04-04 22:33:11 +00:00
|
|
|
}
|
2004-04-04 21:58:05 +00:00
|
|
|
|
2013-02-08 22:58:38 +00:00
|
|
|
/**
|
|
|
|
|
* Set an additional output property
|
|
|
|
|
* @since 1.21
|
|
|
|
|
*
|
|
|
|
|
* @param string $name
|
|
|
|
|
* @param mixed $value
|
|
|
|
|
*/
|
|
|
|
|
public function setProperty( $name, $value ) {
|
|
|
|
|
$this->mProperties[$name] = $value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get an additional output property
|
|
|
|
|
* @since 1.21
|
|
|
|
|
*
|
|
|
|
|
* @param $name
|
|
|
|
|
* @return mixed: Property value or null if not found
|
|
|
|
|
*/
|
|
|
|
|
public function getProperty( $name ) {
|
|
|
|
|
if ( isset( $this->mProperties[$name] ) ) {
|
|
|
|
|
return $this->mProperties[$name];
|
|
|
|
|
} else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* checkLastModified tells the client to use the client-cached page if
|
2012-12-01 16:02:15 +00:00
|
|
|
* possible. If successful, the OutputPage is disabled so that
|
2006-11-07 05:37:31 +00:00
|
|
|
* any future call to OutputPage->output() have no effect.
|
|
|
|
|
*
|
2008-08-29 08:40:13 +00:00
|
|
|
* Side effect: sets mLastModified for Last-Modified header
|
|
|
|
|
*
|
2011-05-21 19:07:24 +00:00
|
|
|
* @param $timestamp string
|
|
|
|
|
*
|
2010-01-28 21:58:50 +00:00
|
|
|
* @return Boolean: true iff cache-ok headers was sent.
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2010-01-28 21:58:50 +00:00
|
|
|
public function checkLastModified( $timestamp ) {
|
2011-04-03 12:46:36 +00:00
|
|
|
global $wgCachePages, $wgCacheEpoch;
|
here it is ... the upload-api, script-server, js2 (javascript phase2) branch merge 1st attempt.
Here is a short overview of changes and associated default configuration variables (most everything is off by default) also see ~soon to be updated~: http://www.mediawiki.org/wiki/Media_Projects_Overview
= Upload Improvements =
==Upload API ==
* Based on the early work of Bryan Tong and others it adds the upload option to the api.
* We rewrite Special:Upload page to include use the new refactoring
* Added in token checks in both the SpecialUpload.php page so avoids DOS / xss copy-by-url JavaScript based cross site POST file submissions
== Copy by URL==
$wgAllowCopyUploads = false;
* http class rewrite includes a new http background download see: includes/HttpFunctions.php
* spins off a php process that calls: maintenance/http_session_download.php
* pushes updates to the session and gives the user a progress bar on http copy uploads from other server progress (using js2 upload interface) (if not using the js2 upload interface it does the request in-place but the download is limited to the php ini timeout time)
== Firefogg ==
* Firefogg enables resumable upload by chunks
* progress indicators and conditional invokation (js2 system)
* and of-course client side transcoding.
= Script Server =
$wgEnableScriptLoader = false;
* off by default if $wgEnableScriptLoader is turned on script files are grouped, gziped, cached etc.
for more info see: http://www.mediawiki.org/wiki/Extension:ScriptLoader
* Includes some early skin js include fixes (skin/script system still lots of love)
* Includes a "javascript class autoloader" this is packaged into mwEmbed so that the mwEmbed library can work in stand alone mode (while retaining localization and script serving) (one such application is the make page for firefogg.org : http://www.firefogg.org/make/index.html )
* The file that contains the autojavascript loading classes is: js2/php/jsAutoloadLocalClasses.php
* One can use this auto class loading dependency system with extensions and add-ons but I need to better document that.
= js2 system / mwEmbed=
$wgEnableJS2system = false
* includes initial rewrite towards more jquery based javascript code
* especially for the Special:Upload page.
* Also the edit page include support for the "add-media-wizard"
* includes dependency loader for javascript that optionally takes advantage of the script-loader
* remote embedding of javascript interfaces (like embedding video, or commons media searching)
* $wgDebugJavaScript = false; .. .this variable lets you always get "always fresh javascript". When used with the script-loader it does not minify the script-loader output.
= mwEmbed =
* Will commit a separate patch to oggHandler that conditionally outputs <video tag> to use the new javascript video player.
** mv_embed player includes: play-head, volume control, remote embedding, oggz-chop support across plugins.
* add-media-wizard adds easy inserts of media to pages (with import)
== jQuery==
* we include a base install of jQuery, jQuery ui and some plugins.
* all the javascript classes are in the scriptloader so its easy to load any set of jquery ui components that you may need using the script-server. You get a callback so you can then execute js with dependencies loaded.
== other stuff ==
there is a bit more code in js2 that pertains to sequence editing, timed text display and basic image editing. We include a base import of pixastic-lib & pixastic-editor... will work with the pixastic developer to try and ensure upstream compatibility on our usage of the library for in-browser photo and sequence manipulation.
2009-07-14 23:52:14 +00:00
|
|
|
|
2005-03-20 03:59:06 +00:00
|
|
|
if ( !$timestamp || $timestamp == '19700101000000' ) {
|
2008-04-16 13:46:16 +00:00
|
|
|
wfDebug( __METHOD__ . ": CACHE DISABLED, NO TIMESTAMP\n" );
|
2008-08-29 08:40:13 +00:00
|
|
|
return false;
|
2005-03-20 03:59:06 +00:00
|
|
|
}
|
2003-07-10 04:55:41 +00:00
|
|
|
if( !$wgCachePages ) {
|
2008-04-16 13:46:16 +00:00
|
|
|
wfDebug( __METHOD__ . ": CACHE DISABLED\n", false );
|
2008-08-29 08:40:13 +00:00
|
|
|
return false;
|
2003-07-10 04:55:41 +00:00
|
|
|
}
|
2011-04-03 03:59:47 +00:00
|
|
|
if( $this->getUser()->getOption( 'nocache' ) ) {
|
2008-04-16 13:46:16 +00:00
|
|
|
wfDebug( __METHOD__ . ": USER DISABLED CACHE\n", false );
|
2008-08-29 08:40:13 +00:00
|
|
|
return false;
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2004-03-20 15:03:26 +00:00
|
|
|
|
2008-08-29 08:40:13 +00:00
|
|
|
$timestamp = wfTimestamp( TS_MW, $timestamp );
|
|
|
|
|
$modifiedTimes = array(
|
|
|
|
|
'page' => $timestamp,
|
2011-04-03 03:59:47 +00:00
|
|
|
'user' => $this->getUser()->getTouched(),
|
2008-08-29 08:40:13 +00:00
|
|
|
'epoch' => $wgCacheEpoch
|
|
|
|
|
);
|
|
|
|
|
wfRunHooks( 'OutputPageCheckLastModified', array( &$modifiedTimes ) );
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2008-08-29 08:40:13 +00:00
|
|
|
$maxModified = max( $modifiedTimes );
|
|
|
|
|
$this->mLastModified = wfTimestamp( TS_RFC2822, $maxModified );
|
|
|
|
|
|
2012-07-19 16:35:25 +00:00
|
|
|
$clientHeader = $this->getRequest()->getHeader( 'If-Modified-Since' );
|
|
|
|
|
if ( $clientHeader === false ) {
|
2008-04-16 13:46:16 +00:00
|
|
|
wfDebug( __METHOD__ . ": client did not send If-Modified-Since header\n", false );
|
2008-08-29 08:40:13 +00:00
|
|
|
return false;
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2008-08-29 08:40:13 +00:00
|
|
|
|
|
|
|
|
# IE sends sizes after the date like this:
|
|
|
|
|
# Wed, 20 Aug 2003 06:51:19 GMT; length=5202
|
|
|
|
|
# this breaks strtotime().
|
2012-07-19 16:35:25 +00:00
|
|
|
$clientHeader = preg_replace( '/;.*$/', '', $clientHeader );
|
2008-08-29 08:40:13 +00:00
|
|
|
|
2008-12-23 19:39:00 +00:00
|
|
|
wfSuppressWarnings(); // E_STRICT system time bitching
|
|
|
|
|
$clientHeaderTime = strtotime( $clientHeader );
|
|
|
|
|
wfRestoreWarnings();
|
|
|
|
|
if ( !$clientHeaderTime ) {
|
2008-08-29 08:40:13 +00:00
|
|
|
wfDebug( __METHOD__ . ": unable to parse the client's If-Modified-Since header: $clientHeader\n" );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
$clientHeaderTime = wfTimestamp( TS_MW, $clientHeaderTime );
|
|
|
|
|
|
2012-07-19 16:35:25 +00:00
|
|
|
# Make debug info
|
|
|
|
|
$info = '';
|
|
|
|
|
foreach ( $modifiedTimes as $name => $value ) {
|
|
|
|
|
if ( $info !== '' ) {
|
|
|
|
|
$info .= ', ';
|
|
|
|
|
}
|
|
|
|
|
$info .= "$name=" . wfTimestamp( TS_ISO_8601, $value );
|
|
|
|
|
}
|
|
|
|
|
|
here it is ... the upload-api, script-server, js2 (javascript phase2) branch merge 1st attempt.
Here is a short overview of changes and associated default configuration variables (most everything is off by default) also see ~soon to be updated~: http://www.mediawiki.org/wiki/Media_Projects_Overview
= Upload Improvements =
==Upload API ==
* Based on the early work of Bryan Tong and others it adds the upload option to the api.
* We rewrite Special:Upload page to include use the new refactoring
* Added in token checks in both the SpecialUpload.php page so avoids DOS / xss copy-by-url JavaScript based cross site POST file submissions
== Copy by URL==
$wgAllowCopyUploads = false;
* http class rewrite includes a new http background download see: includes/HttpFunctions.php
* spins off a php process that calls: maintenance/http_session_download.php
* pushes updates to the session and gives the user a progress bar on http copy uploads from other server progress (using js2 upload interface) (if not using the js2 upload interface it does the request in-place but the download is limited to the php ini timeout time)
== Firefogg ==
* Firefogg enables resumable upload by chunks
* progress indicators and conditional invokation (js2 system)
* and of-course client side transcoding.
= Script Server =
$wgEnableScriptLoader = false;
* off by default if $wgEnableScriptLoader is turned on script files are grouped, gziped, cached etc.
for more info see: http://www.mediawiki.org/wiki/Extension:ScriptLoader
* Includes some early skin js include fixes (skin/script system still lots of love)
* Includes a "javascript class autoloader" this is packaged into mwEmbed so that the mwEmbed library can work in stand alone mode (while retaining localization and script serving) (one such application is the make page for firefogg.org : http://www.firefogg.org/make/index.html )
* The file that contains the autojavascript loading classes is: js2/php/jsAutoloadLocalClasses.php
* One can use this auto class loading dependency system with extensions and add-ons but I need to better document that.
= js2 system / mwEmbed=
$wgEnableJS2system = false
* includes initial rewrite towards more jquery based javascript code
* especially for the Special:Upload page.
* Also the edit page include support for the "add-media-wizard"
* includes dependency loader for javascript that optionally takes advantage of the script-loader
* remote embedding of javascript interfaces (like embedding video, or commons media searching)
* $wgDebugJavaScript = false; .. .this variable lets you always get "always fresh javascript". When used with the script-loader it does not minify the script-loader output.
= mwEmbed =
* Will commit a separate patch to oggHandler that conditionally outputs <video tag> to use the new javascript video player.
** mv_embed player includes: play-head, volume control, remote embedding, oggz-chop support across plugins.
* add-media-wizard adds easy inserts of media to pages (with import)
== jQuery==
* we include a base install of jQuery, jQuery ui and some plugins.
* all the javascript classes are in the scriptloader so its easy to load any set of jquery ui components that you may need using the script-server. You get a callback so you can then execute js with dependencies loaded.
== other stuff ==
there is a bit more code in js2 that pertains to sequence editing, timed text display and basic image editing. We include a base import of pixastic-lib & pixastic-editor... will work with the pixastic developer to try and ensure upstream compatibility on our usage of the library for in-browser photo and sequence manipulation.
2009-07-14 23:52:14 +00:00
|
|
|
wfDebug( __METHOD__ . ": client sent If-Modified-Since: " .
|
2008-08-29 08:40:13 +00:00
|
|
|
wfTimestamp( TS_ISO_8601, $clientHeaderTime ) . "\n", false );
|
here it is ... the upload-api, script-server, js2 (javascript phase2) branch merge 1st attempt.
Here is a short overview of changes and associated default configuration variables (most everything is off by default) also see ~soon to be updated~: http://www.mediawiki.org/wiki/Media_Projects_Overview
= Upload Improvements =
==Upload API ==
* Based on the early work of Bryan Tong and others it adds the upload option to the api.
* We rewrite Special:Upload page to include use the new refactoring
* Added in token checks in both the SpecialUpload.php page so avoids DOS / xss copy-by-url JavaScript based cross site POST file submissions
== Copy by URL==
$wgAllowCopyUploads = false;
* http class rewrite includes a new http background download see: includes/HttpFunctions.php
* spins off a php process that calls: maintenance/http_session_download.php
* pushes updates to the session and gives the user a progress bar on http copy uploads from other server progress (using js2 upload interface) (if not using the js2 upload interface it does the request in-place but the download is limited to the php ini timeout time)
== Firefogg ==
* Firefogg enables resumable upload by chunks
* progress indicators and conditional invokation (js2 system)
* and of-course client side transcoding.
= Script Server =
$wgEnableScriptLoader = false;
* off by default if $wgEnableScriptLoader is turned on script files are grouped, gziped, cached etc.
for more info see: http://www.mediawiki.org/wiki/Extension:ScriptLoader
* Includes some early skin js include fixes (skin/script system still lots of love)
* Includes a "javascript class autoloader" this is packaged into mwEmbed so that the mwEmbed library can work in stand alone mode (while retaining localization and script serving) (one such application is the make page for firefogg.org : http://www.firefogg.org/make/index.html )
* The file that contains the autojavascript loading classes is: js2/php/jsAutoloadLocalClasses.php
* One can use this auto class loading dependency system with extensions and add-ons but I need to better document that.
= js2 system / mwEmbed=
$wgEnableJS2system = false
* includes initial rewrite towards more jquery based javascript code
* especially for the Special:Upload page.
* Also the edit page include support for the "add-media-wizard"
* includes dependency loader for javascript that optionally takes advantage of the script-loader
* remote embedding of javascript interfaces (like embedding video, or commons media searching)
* $wgDebugJavaScript = false; .. .this variable lets you always get "always fresh javascript". When used with the script-loader it does not minify the script-loader output.
= mwEmbed =
* Will commit a separate patch to oggHandler that conditionally outputs <video tag> to use the new javascript video player.
** mv_embed player includes: play-head, volume control, remote embedding, oggz-chop support across plugins.
* add-media-wizard adds easy inserts of media to pages (with import)
== jQuery==
* we include a base install of jQuery, jQuery ui and some plugins.
* all the javascript classes are in the scriptloader so its easy to load any set of jquery ui components that you may need using the script-server. You get a callback so you can then execute js with dependencies loaded.
== other stuff ==
there is a bit more code in js2 that pertains to sequence editing, timed text display and basic image editing. We include a base import of pixastic-lib & pixastic-editor... will work with the pixastic developer to try and ensure upstream compatibility on our usage of the library for in-browser photo and sequence manipulation.
2009-07-14 23:52:14 +00:00
|
|
|
wfDebug( __METHOD__ . ": effective Last-Modified: " .
|
2008-08-29 08:40:13 +00:00
|
|
|
wfTimestamp( TS_ISO_8601, $maxModified ) . "\n", false );
|
|
|
|
|
if( $clientHeaderTime < $maxModified ) {
|
|
|
|
|
wfDebug( __METHOD__ . ": STALE, $info\n", false );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-23 19:39:00 +00:00
|
|
|
# Not modified
|
here it is ... the upload-api, script-server, js2 (javascript phase2) branch merge 1st attempt.
Here is a short overview of changes and associated default configuration variables (most everything is off by default) also see ~soon to be updated~: http://www.mediawiki.org/wiki/Media_Projects_Overview
= Upload Improvements =
==Upload API ==
* Based on the early work of Bryan Tong and others it adds the upload option to the api.
* We rewrite Special:Upload page to include use the new refactoring
* Added in token checks in both the SpecialUpload.php page so avoids DOS / xss copy-by-url JavaScript based cross site POST file submissions
== Copy by URL==
$wgAllowCopyUploads = false;
* http class rewrite includes a new http background download see: includes/HttpFunctions.php
* spins off a php process that calls: maintenance/http_session_download.php
* pushes updates to the session and gives the user a progress bar on http copy uploads from other server progress (using js2 upload interface) (if not using the js2 upload interface it does the request in-place but the download is limited to the php ini timeout time)
== Firefogg ==
* Firefogg enables resumable upload by chunks
* progress indicators and conditional invokation (js2 system)
* and of-course client side transcoding.
= Script Server =
$wgEnableScriptLoader = false;
* off by default if $wgEnableScriptLoader is turned on script files are grouped, gziped, cached etc.
for more info see: http://www.mediawiki.org/wiki/Extension:ScriptLoader
* Includes some early skin js include fixes (skin/script system still lots of love)
* Includes a "javascript class autoloader" this is packaged into mwEmbed so that the mwEmbed library can work in stand alone mode (while retaining localization and script serving) (one such application is the make page for firefogg.org : http://www.firefogg.org/make/index.html )
* The file that contains the autojavascript loading classes is: js2/php/jsAutoloadLocalClasses.php
* One can use this auto class loading dependency system with extensions and add-ons but I need to better document that.
= js2 system / mwEmbed=
$wgEnableJS2system = false
* includes initial rewrite towards more jquery based javascript code
* especially for the Special:Upload page.
* Also the edit page include support for the "add-media-wizard"
* includes dependency loader for javascript that optionally takes advantage of the script-loader
* remote embedding of javascript interfaces (like embedding video, or commons media searching)
* $wgDebugJavaScript = false; .. .this variable lets you always get "always fresh javascript". When used with the script-loader it does not minify the script-loader output.
= mwEmbed =
* Will commit a separate patch to oggHandler that conditionally outputs <video tag> to use the new javascript video player.
** mv_embed player includes: play-head, volume control, remote embedding, oggz-chop support across plugins.
* add-media-wizard adds easy inserts of media to pages (with import)
== jQuery==
* we include a base install of jQuery, jQuery ui and some plugins.
* all the javascript classes are in the scriptloader so its easy to load any set of jquery ui components that you may need using the script-server. You get a callback so you can then execute js with dependencies loaded.
== other stuff ==
there is a bit more code in js2 that pertains to sequence editing, timed text display and basic image editing. We include a base import of pixastic-lib & pixastic-editor... will work with the pixastic developer to try and ensure upstream compatibility on our usage of the library for in-browser photo and sequence manipulation.
2009-07-14 23:52:14 +00:00
|
|
|
# Give a 304 response code and disable body output
|
2008-12-23 19:39:00 +00:00
|
|
|
wfDebug( __METHOD__ . ": NOT MODIFIED, $info\n", false );
|
2010-05-22 12:18:22 +00:00
|
|
|
ini_set( 'zlib.output_compression', 0 );
|
2011-04-03 12:46:36 +00:00
|
|
|
$this->getRequest()->response()->header( "HTTP/1.1 304 Not Modified" );
|
2008-08-29 08:40:13 +00:00
|
|
|
$this->sendCacheControl();
|
|
|
|
|
$this->disable();
|
|
|
|
|
|
|
|
|
|
// Don't output a compressed blob when using ob_gzhandler;
|
|
|
|
|
// it's technically against HTTP spec and seems to confuse
|
|
|
|
|
// Firefox when the response gets split over two packets.
|
|
|
|
|
wfClearOutputBuffers();
|
|
|
|
|
|
|
|
|
|
return true;
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2010-04-05 16:14:58 +00:00
|
|
|
/**
|
|
|
|
|
* Override the last modified timestamp
|
|
|
|
|
*
|
|
|
|
|
* @param $timestamp String: new timestamp, in a format readable by
|
|
|
|
|
* wfTimestamp()
|
|
|
|
|
*/
|
|
|
|
|
public function setLastModified( $timestamp ) {
|
|
|
|
|
$this->mLastModified = wfTimestamp( TS_RFC2822, $timestamp );
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-23 19:05:43 +00:00
|
|
|
/**
|
|
|
|
|
* Set the robot policy for the page: <http://www.robotstxt.org/meta.html>
|
|
|
|
|
*
|
2010-01-28 21:58:50 +00:00
|
|
|
* @param $policy String: the literal string to output as the contents of
|
2008-07-23 19:05:43 +00:00
|
|
|
* the meta tag. Will be parsed according to the spec and output in
|
|
|
|
|
* standardized form.
|
|
|
|
|
* @return null
|
|
|
|
|
*/
|
|
|
|
|
public function setRobotPolicy( $policy ) {
|
2009-08-31 19:19:12 +00:00
|
|
|
$policy = Article::formatRobotPolicy( $policy );
|
2008-07-23 19:05:43 +00:00
|
|
|
|
2010-05-22 12:18:22 +00:00
|
|
|
if( isset( $policy['index'] ) ) {
|
2009-08-31 19:19:12 +00:00
|
|
|
$this->setIndexPolicy( $policy['index'] );
|
2010-01-28 21:58:50 +00:00
|
|
|
}
|
2010-05-22 12:18:22 +00:00
|
|
|
if( isset( $policy['follow'] ) ) {
|
2009-08-31 19:19:12 +00:00
|
|
|
$this->setFollowPolicy( $policy['follow'] );
|
2010-01-28 21:58:50 +00:00
|
|
|
}
|
2008-07-23 19:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the index policy for the page, but leave the follow policy un-
|
|
|
|
|
* touched.
|
|
|
|
|
*
|
|
|
|
|
* @param $policy string Either 'index' or 'noindex'.
|
|
|
|
|
* @return null
|
|
|
|
|
*/
|
|
|
|
|
public function setIndexPolicy( $policy ) {
|
|
|
|
|
$policy = trim( $policy );
|
|
|
|
|
if( in_array( $policy, array( 'index', 'noindex' ) ) ) {
|
|
|
|
|
$this->mIndexPolicy = $policy;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the follow policy for the page, but leave the index policy un-
|
|
|
|
|
* touched.
|
|
|
|
|
*
|
2010-01-28 21:58:50 +00:00
|
|
|
* @param $policy String: either 'follow' or 'nofollow'.
|
2008-07-23 19:05:43 +00:00
|
|
|
* @return null
|
|
|
|
|
*/
|
|
|
|
|
public function setFollowPolicy( $policy ) {
|
|
|
|
|
$policy = trim( $policy );
|
|
|
|
|
if( in_array( $policy, array( 'follow', 'nofollow' ) ) ) {
|
|
|
|
|
$this->mFollowPolicy = $policy;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
|
|
|
|
* Set the new value of the "action text", this will be added to the
|
|
|
|
|
* "HTML title", separated from it with " - ".
|
|
|
|
|
*
|
|
|
|
|
* @param $text String: new value of the "action text"
|
|
|
|
|
*/
|
|
|
|
|
public function setPageTitleActionText( $text ) {
|
|
|
|
|
$this->mPageTitleActionText = $text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the value of the "action text"
|
|
|
|
|
*
|
|
|
|
|
* @return String
|
|
|
|
|
*/
|
|
|
|
|
public function getPageTitleActionText() {
|
|
|
|
|
if ( isset( $this->mPageTitleActionText ) ) {
|
|
|
|
|
return $this->mPageTitleActionText;
|
|
|
|
|
}
|
2012-12-09 02:59:04 +00:00
|
|
|
return '';
|
2010-01-28 21:58:50 +00:00
|
|
|
}
|
|
|
|
|
|
2009-04-09 05:15:43 +00:00
|
|
|
/**
|
2012-07-10 12:48:06 +00:00
|
|
|
* "HTML title" means the contents of "<title>".
|
2010-04-10 05:46:01 +00:00
|
|
|
* It is stored as plain, unescaped text and will be run through htmlspecialchars in the skin file.
|
2011-05-21 19:07:24 +00:00
|
|
|
*
|
|
|
|
|
* @param $name string
|
2009-04-09 05:15:43 +00:00
|
|
|
*/
|
2010-04-10 13:38:50 +00:00
|
|
|
public function setHTMLTitle( $name ) {
|
2011-10-27 20:23:16 +00:00
|
|
|
if ( $name instanceof Message ) {
|
|
|
|
|
$this->mHTMLtitle = $name->setContext( $this->getContext() )->text();
|
|
|
|
|
} else {
|
|
|
|
|
$this->mHTMLtitle = $name;
|
|
|
|
|
}
|
2011-10-24 17:24:38 +00:00
|
|
|
}
|
|
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
2012-07-10 12:48:06 +00:00
|
|
|
* Return the "HTML title", i.e. the content of the "<title>" tag.
|
2010-01-28 21:58:50 +00:00
|
|
|
*
|
|
|
|
|
* @return String
|
|
|
|
|
*/
|
|
|
|
|
public function getHTMLTitle() {
|
|
|
|
|
return $this->mHTMLtitle;
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-30 12:43:10 +00:00
|
|
|
/**
|
|
|
|
|
* Set $mRedirectedFrom, the Title of the page which redirected us to the current page.
|
|
|
|
|
*
|
2012-07-10 14:58:52 +00:00
|
|
|
* @param $t Title
|
2011-11-30 12:43:10 +00:00
|
|
|
*/
|
|
|
|
|
public function setRedirectedFrom( $t ) {
|
|
|
|
|
$this->mRedirectedFrom = $t;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-09 05:15:43 +00:00
|
|
|
/**
|
2010-02-01 18:04:17 +00:00
|
|
|
* "Page title" means the contents of \<h1\>. It is stored as a valid HTML fragment.
|
|
|
|
|
* This function allows good tags like \<sup\> in the \<h1\> tag, but not bad tags like \<script\>.
|
|
|
|
|
* This function automatically sets \<title\> to the same content as \<h1\> but with all tags removed.
|
|
|
|
|
* Bad tags that were escaped in \<h1\> will still be escaped in \<title\>, and good tags like \<i\> will be dropped entirely.
|
2011-05-21 19:07:24 +00:00
|
|
|
*
|
2011-10-27 20:23:16 +00:00
|
|
|
* @param $name string|Message
|
2009-11-14 21:27:13 +00:00
|
|
|
*/
|
2006-11-07 05:37:31 +00:00
|
|
|
public function setPageTitle( $name ) {
|
2011-10-27 20:23:16 +00:00
|
|
|
if ( $name instanceof Message ) {
|
|
|
|
|
$name = $name->setContext( $this->getContext() )->text();
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-09 05:15:43 +00:00
|
|
|
# change "<script>foo&bar</script>" to "<script>foo&bar</script>"
|
|
|
|
|
# but leave "<i>foobar</i>" alone
|
|
|
|
|
$nameWithTags = Sanitizer::normalizeCharReferences( Sanitizer::removeHTMLtags( $name ) );
|
|
|
|
|
$this->mPagetitle = $nameWithTags;
|
2009-02-04 19:43:30 +00:00
|
|
|
|
2009-04-09 05:15:43 +00:00
|
|
|
# change "<i>foo&bar</i>" to "foo&bar"
|
2012-01-13 13:30:58 +00:00
|
|
|
$this->setHTMLTitle( $this->msg( 'pagetitle' )->rawParams( Sanitizer::stripAllTags( $nameWithTags ) ) );
|
2004-04-25 00:32:24 +00:00
|
|
|
}
|
here it is ... the upload-api, script-server, js2 (javascript phase2) branch merge 1st attempt.
Here is a short overview of changes and associated default configuration variables (most everything is off by default) also see ~soon to be updated~: http://www.mediawiki.org/wiki/Media_Projects_Overview
= Upload Improvements =
==Upload API ==
* Based on the early work of Bryan Tong and others it adds the upload option to the api.
* We rewrite Special:Upload page to include use the new refactoring
* Added in token checks in both the SpecialUpload.php page so avoids DOS / xss copy-by-url JavaScript based cross site POST file submissions
== Copy by URL==
$wgAllowCopyUploads = false;
* http class rewrite includes a new http background download see: includes/HttpFunctions.php
* spins off a php process that calls: maintenance/http_session_download.php
* pushes updates to the session and gives the user a progress bar on http copy uploads from other server progress (using js2 upload interface) (if not using the js2 upload interface it does the request in-place but the download is limited to the php ini timeout time)
== Firefogg ==
* Firefogg enables resumable upload by chunks
* progress indicators and conditional invokation (js2 system)
* and of-course client side transcoding.
= Script Server =
$wgEnableScriptLoader = false;
* off by default if $wgEnableScriptLoader is turned on script files are grouped, gziped, cached etc.
for more info see: http://www.mediawiki.org/wiki/Extension:ScriptLoader
* Includes some early skin js include fixes (skin/script system still lots of love)
* Includes a "javascript class autoloader" this is packaged into mwEmbed so that the mwEmbed library can work in stand alone mode (while retaining localization and script serving) (one such application is the make page for firefogg.org : http://www.firefogg.org/make/index.html )
* The file that contains the autojavascript loading classes is: js2/php/jsAutoloadLocalClasses.php
* One can use this auto class loading dependency system with extensions and add-ons but I need to better document that.
= js2 system / mwEmbed=
$wgEnableJS2system = false
* includes initial rewrite towards more jquery based javascript code
* especially for the Special:Upload page.
* Also the edit page include support for the "add-media-wizard"
* includes dependency loader for javascript that optionally takes advantage of the script-loader
* remote embedding of javascript interfaces (like embedding video, or commons media searching)
* $wgDebugJavaScript = false; .. .this variable lets you always get "always fresh javascript". When used with the script-loader it does not minify the script-loader output.
= mwEmbed =
* Will commit a separate patch to oggHandler that conditionally outputs <video tag> to use the new javascript video player.
** mv_embed player includes: play-head, volume control, remote embedding, oggz-chop support across plugins.
* add-media-wizard adds easy inserts of media to pages (with import)
== jQuery==
* we include a base install of jQuery, jQuery ui and some plugins.
* all the javascript classes are in the scriptloader so its easy to load any set of jquery ui components that you may need using the script-server. You get a callback so you can then execute js with dependencies loaded.
== other stuff ==
there is a bit more code in js2 that pertains to sequence editing, timed text display and basic image editing. We include a base import of pixastic-lib & pixastic-editor... will work with the pixastic developer to try and ensure upstream compatibility on our usage of the library for in-browser photo and sequence manipulation.
2009-07-14 23:52:14 +00:00
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
2010-02-02 16:26:52 +00:00
|
|
|
* Return the "page title", i.e. the content of the \<h1\> tag.
|
2010-01-28 21:58:50 +00:00
|
|
|
*
|
|
|
|
|
* @return String
|
|
|
|
|
*/
|
|
|
|
|
public function getPageTitle() {
|
|
|
|
|
return $this->mPagetitle;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-03 03:59:47 +00:00
|
|
|
/**
|
2011-04-03 10:41:14 +00:00
|
|
|
* Set the Title object to use
|
2011-04-03 03:59:47 +00:00
|
|
|
*
|
2011-04-03 10:41:14 +00:00
|
|
|
* @param $t Title object
|
2011-04-03 03:59:47 +00:00
|
|
|
*/
|
2011-07-28 17:48:35 +00:00
|
|
|
public function setTitle( Title $t ) {
|
2011-04-18 12:43:53 +00:00
|
|
|
$this->getContext()->setTitle( $t );
|
2011-04-03 10:41:14 +00:00
|
|
|
}
|
|
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
|
|
|
|
* Replace the subtile with $str
|
|
|
|
|
*
|
2012-09-21 22:30:28 +00:00
|
|
|
* @param $str String|Message: new value of the subtitle. String should be safe HTML.
|
2010-01-28 21:58:50 +00:00
|
|
|
*/
|
|
|
|
|
public function setSubtitle( $str ) {
|
2011-11-08 18:02:26 +00:00
|
|
|
$this->clearSubtitle();
|
|
|
|
|
$this->addSubtitle( $str );
|
2010-01-28 21:58:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add $str to the subtitle
|
|
|
|
|
*
|
2011-11-08 18:02:26 +00:00
|
|
|
* @deprecated in 1.19; use addSubtitle() instead
|
|
|
|
|
* @param $str String|Message to add to the subtitle
|
2010-01-28 21:58:50 +00:00
|
|
|
*/
|
|
|
|
|
public function appendSubtitle( $str ) {
|
2011-11-08 18:02:26 +00:00
|
|
|
$this->addSubtitle( $str );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add $str to the subtitle
|
|
|
|
|
*
|
2012-09-21 22:30:28 +00:00
|
|
|
* @param $str String|Message to add to the subtitle. String should be safe HTML.
|
2011-11-08 18:02:26 +00:00
|
|
|
*/
|
|
|
|
|
public function addSubtitle( $str ) {
|
|
|
|
|
if ( $str instanceof Message ) {
|
|
|
|
|
$this->mSubtitle[] = $str->setContext( $this->getContext() )->parse();
|
|
|
|
|
} else {
|
|
|
|
|
$this->mSubtitle[] = $str;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add a subtitle containing a backlink to a page
|
|
|
|
|
*
|
|
|
|
|
* @param $title Title to link to
|
|
|
|
|
*/
|
|
|
|
|
public function addBacklinkSubtitle( Title $title ) {
|
|
|
|
|
$query = array();
|
|
|
|
|
if ( $title->isRedirect() ) {
|
|
|
|
|
$query['redirect'] = 'no';
|
|
|
|
|
}
|
|
|
|
|
$this->addSubtitle( $this->msg( 'backlinksubtitle' )->rawParams( Linker::link( $title, null, array(), $query ) ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Clear the subtitles
|
|
|
|
|
*/
|
|
|
|
|
public function clearSubtitle() {
|
|
|
|
|
$this->mSubtitle = array();
|
2010-01-28 21:58:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the subtitle
|
|
|
|
|
*
|
|
|
|
|
* @return String
|
|
|
|
|
*/
|
|
|
|
|
public function getSubtitle() {
|
2011-11-08 18:02:26 +00:00
|
|
|
return implode( "<br />\n\t\t\t\t", $this->mSubtitle );
|
2010-01-28 21:58:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the page as printable, i.e. it'll be displayed with with all
|
|
|
|
|
* print styles included
|
|
|
|
|
*/
|
|
|
|
|
public function setPrintable() {
|
|
|
|
|
$this->mPrintable = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return whether the page is "printable"
|
|
|
|
|
*
|
|
|
|
|
* @return Boolean
|
|
|
|
|
*/
|
|
|
|
|
public function isPrintable() {
|
|
|
|
|
return $this->mPrintable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Disable output completely, i.e. calling output() will have no effect
|
|
|
|
|
*/
|
|
|
|
|
public function disable() {
|
|
|
|
|
$this->mDoNothing = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return whether the output will be completely disabled
|
|
|
|
|
*
|
|
|
|
|
* @return Boolean
|
|
|
|
|
*/
|
|
|
|
|
public function isDisabled() {
|
|
|
|
|
return $this->mDoNothing;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
|
|
|
|
* Show an "add new section" link?
|
|
|
|
|
*
|
|
|
|
|
* @return Boolean
|
|
|
|
|
*/
|
|
|
|
|
public function showNewSectionLink() {
|
|
|
|
|
return $this->mNewSectionLink;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Forcibly hide the new section link?
|
|
|
|
|
*
|
|
|
|
|
* @return Boolean
|
|
|
|
|
*/
|
|
|
|
|
public function forceHideNewSectionLink() {
|
|
|
|
|
return $this->mHideNewSectionLink;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-26 20:47:34 +00:00
|
|
|
/**
|
|
|
|
|
* Add or remove feed links in the page header
|
|
|
|
|
* This is mainly kept for backward compatibility, see OutputPage::addFeedLink()
|
|
|
|
|
* for the new version
|
|
|
|
|
* @see addFeedLink()
|
|
|
|
|
*
|
|
|
|
|
* @param $show Boolean: true: add default feeds, false: remove all feeds
|
|
|
|
|
*/
|
2010-01-13 20:23:14 +00:00
|
|
|
public function setSyndicated( $show = true ) {
|
|
|
|
|
if ( $show ) {
|
|
|
|
|
$this->setFeedAppendQuery( false );
|
|
|
|
|
} else {
|
|
|
|
|
$this->mFeedLinks = array();
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-10-24 21:32:53 +00:00
|
|
|
|
2010-01-26 20:47:34 +00:00
|
|
|
/**
|
|
|
|
|
* Add default feeds to the page header
|
|
|
|
|
* This is mainly kept for backward compatibility, see OutputPage::addFeedLink()
|
|
|
|
|
* for the new version
|
|
|
|
|
* @see addFeedLink()
|
|
|
|
|
*
|
|
|
|
|
* @param $val String: query to append to feed links or false to output
|
|
|
|
|
* default links
|
|
|
|
|
*/
|
2009-09-30 17:35:41 +00:00
|
|
|
public function setFeedAppendQuery( $val ) {
|
2010-01-26 20:52:55 +00:00
|
|
|
global $wgAdvertisedFeedTypes;
|
2009-10-24 21:32:53 +00:00
|
|
|
|
2009-09-30 17:35:41 +00:00
|
|
|
$this->mFeedLinks = array();
|
2009-10-24 21:32:53 +00:00
|
|
|
|
2010-01-13 21:29:47 +00:00
|
|
|
foreach ( $wgAdvertisedFeedTypes as $type ) {
|
2010-01-13 20:23:14 +00:00
|
|
|
$query = "feed=$type";
|
2010-01-13 21:29:47 +00:00
|
|
|
if ( is_string( $val ) ) {
|
2010-01-13 20:23:14 +00:00
|
|
|
$query .= '&' . $val;
|
2010-01-13 21:29:47 +00:00
|
|
|
}
|
2009-09-30 17:35:41 +00:00
|
|
|
$this->mFeedLinks[$type] = $this->getTitle()->getLocalURL( $query );
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-10-24 21:32:53 +00:00
|
|
|
|
2010-01-26 20:47:34 +00:00
|
|
|
/**
|
|
|
|
|
* Add a feed link to the page header
|
|
|
|
|
*
|
|
|
|
|
* @param $format String: feed type, should be a key of $wgFeedClasses
|
|
|
|
|
* @param $href String: URL
|
|
|
|
|
*/
|
2009-09-30 17:35:41 +00:00
|
|
|
public function addFeedLink( $format, $href ) {
|
2010-05-11 19:36:47 +00:00
|
|
|
global $wgAdvertisedFeedTypes;
|
|
|
|
|
|
|
|
|
|
if ( in_array( $format, $wgAdvertisedFeedTypes ) ) {
|
|
|
|
|
$this->mFeedLinks[$format] = $href;
|
|
|
|
|
}
|
2009-09-30 17:35:41 +00:00
|
|
|
}
|
2009-10-24 21:32:53 +00:00
|
|
|
|
2010-01-26 20:47:34 +00:00
|
|
|
/**
|
2010-01-27 00:11:13 +00:00
|
|
|
* Should we output feed links for this page?
|
2010-01-26 20:47:34 +00:00
|
|
|
* @return Boolean
|
|
|
|
|
*/
|
2010-01-28 21:58:50 +00:00
|
|
|
public function isSyndicated() {
|
|
|
|
|
return count( $this->mFeedLinks ) > 0;
|
|
|
|
|
}
|
2006-11-07 05:37:31 +00:00
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
|
|
|
|
* Return URLs for each supported syndication format for this page.
|
|
|
|
|
* @return array associating format keys with URLs
|
|
|
|
|
*/
|
|
|
|
|
public function getSyndicationLinks() {
|
|
|
|
|
return $this->mFeedLinks;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
|
|
|
|
* Will currently always return null
|
|
|
|
|
*
|
|
|
|
|
* @return null
|
|
|
|
|
*/
|
|
|
|
|
public function getFeedAppendQuery() {
|
|
|
|
|
return $this->mFeedLinksAppendQuery;
|
|
|
|
|
}
|
2010-01-26 20:47:34 +00:00
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
|
|
|
|
* Set whether the displayed content is related to the source of the
|
|
|
|
|
* corresponding article on the wiki
|
|
|
|
|
* Setting true will cause the change "article related" toggle to true
|
|
|
|
|
*
|
|
|
|
|
* @param $v Boolean
|
|
|
|
|
*/
|
|
|
|
|
public function setArticleFlag( $v ) {
|
|
|
|
|
$this->mIsarticle = $v;
|
|
|
|
|
if ( $v ) {
|
|
|
|
|
$this->mIsArticleRelated = $v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return whether the content displayed page is related to the source of
|
|
|
|
|
* the corresponding article on the wiki
|
|
|
|
|
*
|
|
|
|
|
* @return Boolean
|
|
|
|
|
*/
|
|
|
|
|
public function isArticle() {
|
|
|
|
|
return $this->mIsarticle;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set whether this page is related an article on the wiki
|
|
|
|
|
* Setting false will cause the change of "article flag" toggle to false
|
|
|
|
|
*
|
|
|
|
|
* @param $v Boolean
|
|
|
|
|
*/
|
2006-11-07 05:37:31 +00:00
|
|
|
public function setArticleRelated( $v ) {
|
2004-01-17 09:49:43 +00:00
|
|
|
$this->mIsArticleRelated = $v;
|
|
|
|
|
if ( !$v ) {
|
|
|
|
|
$this->mIsarticle = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-01-28 21:58:50 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return whether this page is related an article on the wiki
|
|
|
|
|
*
|
|
|
|
|
* @return Boolean
|
|
|
|
|
*/
|
|
|
|
|
public function isArticleRelated() {
|
|
|
|
|
return $this->mIsArticleRelated;
|
2004-01-17 09:49:43 +00:00
|
|
|
}
|
|
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
|
|
|
|
* Add new language links
|
|
|
|
|
*
|
2012-02-09 18:01:10 +00:00
|
|
|
* @param $newLinkArray array Associative array mapping language code to the page
|
2010-01-28 21:58:50 +00:00
|
|
|
* name
|
|
|
|
|
*/
|
|
|
|
|
public function addLanguageLinks( $newLinkArray ) {
|
2004-06-01 18:29:31 +00:00
|
|
|
$this->mLanguageLinks += $newLinkArray;
|
|
|
|
|
}
|
2010-01-28 21:58:50 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reset the language links and add new language links
|
|
|
|
|
*
|
2012-02-09 18:01:10 +00:00
|
|
|
* @param $newLinkArray array Associative array mapping language code to the page
|
2010-01-28 21:58:50 +00:00
|
|
|
* name
|
|
|
|
|
*/
|
|
|
|
|
public function setLanguageLinks( $newLinkArray ) {
|
2004-06-01 18:29:31 +00:00
|
|
|
$this->mLanguageLinks = $newLinkArray;
|
|
|
|
|
}
|
2004-09-17 15:24:43 +00:00
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
|
|
|
|
* Get the list of language links
|
|
|
|
|
*
|
2011-02-16 10:28:24 +00:00
|
|
|
* @return Array of Interwiki Prefixed (non DB key) Titles (e.g. 'fr:Test page')
|
2010-01-28 21:58:50 +00:00
|
|
|
*/
|
|
|
|
|
public function getLanguageLinks() {
|
|
|
|
|
return $this->mLanguageLinks;
|
2004-07-08 14:53:54 +00:00
|
|
|
}
|
2005-12-30 09:33:11 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add an array of categories, with names in the keys
|
2010-01-28 21:58:50 +00:00
|
|
|
*
|
2011-02-02 11:00:09 +00:00
|
|
|
* @param $categories Array mapping category name => sort key
|
2005-12-30 09:33:11 +00:00
|
|
|
*/
|
2008-02-20 08:53:12 +00:00
|
|
|
public function addCategoryLinks( $categories ) {
|
2011-04-03 03:59:47 +00:00
|
|
|
global $wgContLang;
|
2005-12-30 09:33:11 +00:00
|
|
|
|
2008-02-25 16:38:25 +00:00
|
|
|
if ( !is_array( $categories ) || count( $categories ) == 0 ) {
|
2008-02-20 08:53:12 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2008-02-25 16:38:25 +00:00
|
|
|
|
2008-02-20 08:53:12 +00:00
|
|
|
# Add the links to a LinkBatch
|
2005-12-30 09:33:11 +00:00
|
|
|
$arr = array( NS_CATEGORY => $categories );
|
|
|
|
|
$lb = new LinkBatch;
|
|
|
|
|
$lb->setArray( $arr );
|
|
|
|
|
|
2008-02-20 08:53:12 +00:00
|
|
|
# Fetch existence plus the hiddencat property
|
|
|
|
|
$dbr = wfGetDB( DB_SLAVE );
|
2011-01-24 23:15:10 +00:00
|
|
|
$res = $dbr->select( array( 'page', 'page_props' ),
|
|
|
|
|
array( 'page_id', 'page_namespace', 'page_title', 'page_len', 'page_is_redirect', 'page_latest', 'pp_value' ),
|
|
|
|
|
$lb->constructSet( 'page', $dbr ),
|
|
|
|
|
__METHOD__,
|
2011-01-26 23:13:20 +00:00
|
|
|
array(),
|
2011-01-28 23:31:01 +00:00
|
|
|
array( 'page_props' => array( 'LEFT JOIN', array( 'pp_propname' => 'hiddencat', 'pp_page = page_id' ) ) )
|
2011-01-24 23:15:10 +00:00
|
|
|
);
|
2008-02-20 08:53:12 +00:00
|
|
|
|
|
|
|
|
# Add the results to the link cache
|
|
|
|
|
$lb->addResultToCache( LinkCache::singleton(), $res );
|
|
|
|
|
|
2008-02-25 16:38:25 +00:00
|
|
|
# Set all the values to 'normal'. This can be done with array_fill_keys in PHP 5.2.0+
|
2010-05-22 12:18:22 +00:00
|
|
|
$categories = array_combine(
|
|
|
|
|
array_keys( $categories ),
|
|
|
|
|
array_fill( 0, count( $categories ), 'normal' )
|
|
|
|
|
);
|
2008-02-25 16:38:25 +00:00
|
|
|
|
|
|
|
|
# Mark hidden categories
|
2008-02-20 08:53:12 +00:00
|
|
|
foreach ( $res as $row ) {
|
2008-02-25 16:38:25 +00:00
|
|
|
if ( isset( $row->pp_value ) ) {
|
|
|
|
|
$categories[$row->page_title] = 'hidden';
|
2008-02-20 08:53:12 +00:00
|
|
|
}
|
|
|
|
|
}
|
2008-02-25 16:38:25 +00:00
|
|
|
|
2008-02-20 08:53:12 +00:00
|
|
|
# Add the remaining categories to the skin
|
2008-07-02 20:02:51 +00:00
|
|
|
if ( wfRunHooks( 'OutputPageMakeCategoryLinks', array( &$this, $categories, &$this->mCategoryLinks ) ) ) {
|
|
|
|
|
foreach ( $categories as $category => $type ) {
|
2009-02-02 07:54:43 +00:00
|
|
|
$origcategory = $category;
|
2008-07-02 20:02:51 +00:00
|
|
|
$title = Title::makeTitleSafe( NS_CATEGORY, $category );
|
2009-02-02 07:54:43 +00:00
|
|
|
$wgContLang->findVariantLink( $category, $title, true );
|
2010-05-22 12:18:22 +00:00
|
|
|
if ( $category != $origcategory ) {
|
|
|
|
|
if ( array_key_exists( $category, $categories ) ) {
|
2009-02-02 07:54:43 +00:00
|
|
|
continue;
|
2010-05-22 12:18:22 +00:00
|
|
|
}
|
|
|
|
|
}
|
2008-07-02 20:02:51 +00:00
|
|
|
$text = $wgContLang->convertHtml( $title->getText() );
|
2009-11-19 00:37:00 +00:00
|
|
|
$this->mCategories[] = $title->getText();
|
2011-06-22 18:24:58 +00:00
|
|
|
$this->mCategoryLinks[$type][] = Linker::link( $title, $text );
|
2008-07-02 20:02:51 +00:00
|
|
|
}
|
2005-12-30 09:33:11 +00:00
|
|
|
}
|
2004-06-19 06:46:54 +00:00
|
|
|
}
|
2005-12-30 09:33:11 +00:00
|
|
|
|
2010-01-28 21:58:50 +00:00
|
|
|
/**
|
|
|
|
|
* Reset the category links (but not the category list) and add $categories
|
|
|
|
|
*
|
2011-02-02 11:00:09 +00:00
|
|
|
* @param $categories Array mapping category name => sort key
|
2010-01-28 21:58:50 +00:00
|
|
|
*/
|
|
|
|
|
public function setCategoryLinks( $categories ) {
|
2005-12-30 09:33:11 +00:00
|
|
|
$this->mCategoryLinks = array();
|
2010-01-28 21:58:50 +00:00
|
|
|
$this->addCategoryLinks( $categories );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the list of category links, in a 2-D array with the following format:
|
|
|
|
|
* $arr[$type][] = $link, where $type is either "normal" or "hidden" (for
|
|
|
|
|
* hidden categories) and $link a HTML fragment with a link to the category
|
|
|
|
|
* page
|
|
|
|
|
*
|
|
|
|
|
* @return Array
|
|
|
|
|
*/
|
|
|
|
|
public function getCategoryLinks() {
|
|
|
|
|
return $this->mCategoryLinks;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the list of category names this page belongs to
|
|
|
|
|
*
|
|
|
|
|
* @return Array of strings
|
|
|
|
|
*/
|
|
|
|
|
public function getCategories() {
|
|
|
|
|
return $this->mCategories;
|
2004-06-19 06:46:54 +00:00
|
|
|
}
|
|
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
2011-02-04 16:39:17 +00:00
|
|
|
* Do not allow scripts which can be modified by wiki users to load on this page;
|
|
|
|
|
* only allow scripts bundled with, or generated by, the software.
|
2010-01-29 21:32:45 +00:00
|
|
|
*/
|
|
|
|
|
public function disallowUserJs() {
|
2011-02-04 16:39:17 +00:00
|
|
|
$this->reduceAllowedModules(
|
|
|
|
|
ResourceLoaderModule::TYPE_SCRIPTS,
|
|
|
|
|
ResourceLoaderModule::ORIGIN_CORE_INDIVIDUAL
|
|
|
|
|
);
|
2010-01-29 21:32:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return whether user JavaScript is allowed for this page
|
2011-03-12 18:14:33 +00:00
|
|
|
* @deprecated since 1.18 Load modules with ResourceLoader, and origin and
|
2011-04-23 19:28:35 +00:00
|
|
|
* trustworthiness is identified and enforced automagically.
|
2012-01-02 12:19:24 +00:00
|
|
|
* Will be removed in 1.20.
|
2010-01-29 21:32:45 +00:00
|
|
|
* @return Boolean
|
|
|
|
|
*/
|
|
|
|
|
public function isUserJsAllowed() {
|
2012-01-02 12:19:24 +00:00
|
|
|
wfDeprecated( __METHOD__, '1.18' );
|
2011-02-04 16:39:17 +00:00
|
|
|
return $this->getAllowedModules( ResourceLoaderModule::TYPE_SCRIPTS ) >= ResourceLoaderModule::ORIGIN_USER_INDIVIDUAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Show what level of JavaScript / CSS untrustworthiness is allowed on this page
|
|
|
|
|
* @see ResourceLoaderModule::$origin
|
|
|
|
|
* @param $type String ResourceLoaderModule TYPE_ constant
|
|
|
|
|
* @return Int ResourceLoaderModule ORIGIN_ class constant
|
|
|
|
|
*/
|
2012-12-20 15:09:25 +00:00
|
|
|
public function getAllowedModules( $type ) {
|
2013-01-26 18:32:03 +00:00
|
|
|
if( $type == ResourceLoaderModule::TYPE_COMBINED ) {
|
2011-02-04 16:39:17 +00:00
|
|
|
return min( array_values( $this->mAllowedModules ) );
|
|
|
|
|
} else {
|
|
|
|
|
return isset( $this->mAllowedModules[$type] )
|
|
|
|
|
? $this->mAllowedModules[$type]
|
|
|
|
|
: ResourceLoaderModule::ORIGIN_ALL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the highest level of CSS/JS untrustworthiness allowed
|
|
|
|
|
* @param $type String ResourceLoaderModule TYPE_ constant
|
|
|
|
|
* @param $level Int ResourceLoaderModule class constant
|
|
|
|
|
*/
|
2012-12-20 15:09:25 +00:00
|
|
|
public function setAllowedModules( $type, $level ) {
|
2011-02-04 16:39:17 +00:00
|
|
|
$this->mAllowedModules[$type] = $level;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* As for setAllowedModules(), but don't inadvertantly make the page more accessible
|
|
|
|
|
* @param $type String
|
|
|
|
|
* @param $level Int ResourceLoaderModule class constant
|
|
|
|
|
*/
|
2012-12-20 15:09:25 +00:00
|
|
|
public function reduceAllowedModules( $type, $level ) {
|
2013-02-03 20:05:24 +00:00
|
|
|
$this->mAllowedModules[$type] = min( $this->getAllowedModules( $type ), $level );
|
2010-01-29 21:32:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Prepend $text to the body HTML
|
|
|
|
|
*
|
|
|
|
|
* @param $text String: HTML
|
|
|
|
|
*/
|
|
|
|
|
public function prependHTML( $text ) {
|
|
|
|
|
$this->mBodytext = $text . $this->mBodytext;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Append $text to the body HTML
|
|
|
|
|
*
|
|
|
|
|
* @param $text String: HTML
|
|
|
|
|
*/
|
|
|
|
|
public function addHTML( $text ) {
|
|
|
|
|
$this->mBodytext .= $text;
|
|
|
|
|
}
|
2011-10-16 03:27:12 +00:00
|
|
|
|
2011-10-10 21:05:02 +00:00
|
|
|
/**
|
|
|
|
|
* Shortcut for adding an Html::element via addHTML.
|
2011-10-16 03:27:12 +00:00
|
|
|
*
|
2011-10-10 21:05:02 +00:00
|
|
|
* @since 1.19
|
2011-10-16 03:27:12 +00:00
|
|
|
*
|
2011-10-10 21:05:02 +00:00
|
|
|
* @param $element string
|
|
|
|
|
* @param $attribs array
|
|
|
|
|
* @param $contents string
|
|
|
|
|
*/
|
|
|
|
|
public function addElement( $element, $attribs = array(), $contents = '' ) {
|
|
|
|
|
$this->addHTML( Html::element( $element, $attribs, $contents ) );
|
|
|
|
|
}
|
2010-01-29 21:32:45 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Clear the body HTML
|
|
|
|
|
*/
|
|
|
|
|
public function clearHTML() {
|
|
|
|
|
$this->mBodytext = '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the body HTML
|
|
|
|
|
*
|
|
|
|
|
* @return String: HTML
|
|
|
|
|
*/
|
|
|
|
|
public function getHTML() {
|
|
|
|
|
return $this->mBodytext;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get/set the ParserOptions object to use for wikitext parsing
|
|
|
|
|
*
|
2012-02-09 19:29:36 +00:00
|
|
|
* @param $options ParserOptions|null either the ParserOption to use or null to only get the
|
2010-01-29 21:32:45 +00:00
|
|
|
* current ParserOption object
|
2011-02-21 17:12:33 +00:00
|
|
|
* @return ParserOptions object
|
2010-01-29 21:32:45 +00:00
|
|
|
*/
|
2006-11-07 05:37:31 +00:00
|
|
|
public function parserOptions( $options = null ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
if ( !$this->mParserOptions ) {
|
2011-10-19 14:16:01 +00:00
|
|
|
$this->mParserOptions = ParserOptions::newFromContext( $this->getContext() );
|
2011-07-20 22:32:30 +00:00
|
|
|
$this->mParserOptions->setEditSection( false );
|
2006-07-26 07:15:39 +00:00
|
|
|
}
|
2004-02-29 08:43:29 +00:00
|
|
|
return wfSetVar( $this->mParserOptions, $options );
|
|
|
|
|
}
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2005-11-27 06:04:41 +00:00
|
|
|
/**
|
|
|
|
|
* Set the revision ID which will be seen by the wiki text parser
|
|
|
|
|
* for things such as embedded {{REVISIONID}} variable use.
|
2010-01-29 21:32:45 +00:00
|
|
|
*
|
|
|
|
|
* @param $revid Mixed: an positive integer, or null
|
|
|
|
|
* @return Mixed: previous value
|
2005-11-27 06:04:41 +00:00
|
|
|
*/
|
2006-11-07 05:37:31 +00:00
|
|
|
public function setRevisionId( $revid ) {
|
2005-11-27 06:04:41 +00:00
|
|
|
$val = is_null( $revid ) ? null : intval( $revid );
|
|
|
|
|
return wfSetVar( $this->mRevisionId, $val );
|
|
|
|
|
}
|
here it is ... the upload-api, script-server, js2 (javascript phase2) branch merge 1st attempt.
Here is a short overview of changes and associated default configuration variables (most everything is off by default) also see ~soon to be updated~: http://www.mediawiki.org/wiki/Media_Projects_Overview
= Upload Improvements =
==Upload API ==
* Based on the early work of Bryan Tong and others it adds the upload option to the api.
* We rewrite Special:Upload page to include use the new refactoring
* Added in token checks in both the SpecialUpload.php page so avoids DOS / xss copy-by-url JavaScript based cross site POST file submissions
== Copy by URL==
$wgAllowCopyUploads = false;
* http class rewrite includes a new http background download see: includes/HttpFunctions.php
* spins off a php process that calls: maintenance/http_session_download.php
* pushes updates to the session and gives the user a progress bar on http copy uploads from other server progress (using js2 upload interface) (if not using the js2 upload interface it does the request in-place but the download is limited to the php ini timeout time)
== Firefogg ==
* Firefogg enables resumable upload by chunks
* progress indicators and conditional invokation (js2 system)
* and of-course client side transcoding.
= Script Server =
$wgEnableScriptLoader = false;
* off by default if $wgEnableScriptLoader is turned on script files are grouped, gziped, cached etc.
for more info see: http://www.mediawiki.org/wiki/Extension:ScriptLoader
* Includes some early skin js include fixes (skin/script system still lots of love)
* Includes a "javascript class autoloader" this is packaged into mwEmbed so that the mwEmbed library can work in stand alone mode (while retaining localization and script serving) (one such application is the make page for firefogg.org : http://www.firefogg.org/make/index.html )
* The file that contains the autojavascript loading classes is: js2/php/jsAutoloadLocalClasses.php
* One can use this auto class loading dependency system with extensions and add-ons but I need to better document that.
= js2 system / mwEmbed=
$wgEnableJS2system = false
* includes initial rewrite towards more jquery based javascript code
* especially for the Special:Upload page.
* Also the edit page include support for the "add-media-wizard"
* includes dependency loader for javascript that optionally takes advantage of the script-loader
* remote embedding of javascript interfaces (like embedding video, or commons media searching)
* $wgDebugJavaScript = false; .. .this variable lets you always get "always fresh javascript". When used with the script-loader it does not minify the script-loader output.
= mwEmbed =
* Will commit a separate patch to oggHandler that conditionally outputs <video tag> to use the new javascript video player.
** mv_embed player includes: play-head, volume control, remote embedding, oggz-chop support across plugins.
* add-media-wizard adds easy inserts of media to pages (with import)
== jQuery==
* we include a base install of jQuery, jQuery ui and some plugins.
* all the javascript classes are in the scriptloader so its easy to load any set of jquery ui components that you may need using the script-server. You get a callback so you can then execute js with dependencies loaded.
== other stuff ==
there is a bit more code in js2 that pertains to sequence editing, timed text display and basic image editing. We include a base import of pixastic-lib & pixastic-editor... will work with the pixastic developer to try and ensure upstream compatibility on our usage of the library for in-browser photo and sequence manipulation.
2009-07-14 23:52:14 +00:00
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
2011-07-05 05:23:26 +00:00
|
|
|
* Get the displayed revision ID
|
2010-01-29 21:32:45 +00:00
|
|
|
*
|
|
|
|
|
* @return Integer
|
|
|
|
|
*/
|
2008-08-11 13:23:45 +00:00
|
|
|
public function getRevisionId() {
|
|
|
|
|
return $this->mRevisionId;
|
|
|
|
|
}
|
2004-02-29 08:43:29 +00:00
|
|
|
|
2011-12-10 16:30:40 +00:00
|
|
|
/**
|
|
|
|
|
* Set the timestamp of the revision which will be displayed. This is used
|
|
|
|
|
* to avoid a extra DB call in Skin::lastModified().
|
|
|
|
|
*
|
2012-07-10 15:19:07 +00:00
|
|
|
* @param $timestamp Mixed: string, or null
|
2011-12-10 16:30:40 +00:00
|
|
|
* @return Mixed: previous value
|
|
|
|
|
*/
|
2012-07-10 15:19:07 +00:00
|
|
|
public function setRevisionTimestamp( $timestamp) {
|
|
|
|
|
return wfSetVar( $this->mRevisionTimestamp, $timestamp );
|
2011-12-10 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the timestamp of displayed revision.
|
|
|
|
|
* This will be null if not filled by setRevisionTimestamp().
|
|
|
|
|
*
|
|
|
|
|
* @return String or null
|
|
|
|
|
*/
|
|
|
|
|
public function getRevisionTimestamp() {
|
|
|
|
|
return $this->mRevisionTimestamp;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-05 05:23:26 +00:00
|
|
|
/**
|
|
|
|
|
* Set the displayed file version
|
|
|
|
|
*
|
2012-02-09 18:01:10 +00:00
|
|
|
* @param $file File|bool
|
2011-07-05 05:23:26 +00:00
|
|
|
* @return Mixed: previous value
|
|
|
|
|
*/
|
|
|
|
|
public function setFileVersion( $file ) {
|
2011-07-06 17:27:33 +00:00
|
|
|
$val = null;
|
2011-07-05 05:23:26 +00:00
|
|
|
if ( $file instanceof File && $file->exists() ) {
|
|
|
|
|
$val = array( 'time' => $file->getTimestamp(), 'sha1' => $file->getSha1() );
|
|
|
|
|
}
|
2011-07-06 17:27:33 +00:00
|
|
|
return wfSetVar( $this->mFileVersion, $val, true );
|
2011-07-05 05:23:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the displayed file version
|
|
|
|
|
*
|
|
|
|
|
* @return Array|null ('time' => MW timestamp, 'sha1' => sha1)
|
|
|
|
|
*/
|
|
|
|
|
public function getFileVersion() {
|
|
|
|
|
return $this->mFileVersion;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-03 05:53:07 +00:00
|
|
|
/**
|
|
|
|
|
* Get the templates used on this page
|
|
|
|
|
*
|
|
|
|
|
* @return Array (namespace => dbKey => revId)
|
2011-04-04 01:22:08 +00:00
|
|
|
* @since 1.18
|
2011-04-03 05:53:07 +00:00
|
|
|
*/
|
|
|
|
|
public function getTemplateIds() {
|
|
|
|
|
return $this->mTemplateIds;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the files used on this page
|
|
|
|
|
*
|
|
|
|
|
* @return Array (dbKey => array('time' => MW timestamp or null, 'sha1' => sha1 or ''))
|
2011-04-04 01:22:08 +00:00
|
|
|
* @since 1.18
|
2011-04-03 05:53:07 +00:00
|
|
|
*/
|
2011-09-14 19:05:43 +00:00
|
|
|
public function getFileSearchOptions() {
|
2011-04-03 05:53:07 +00:00
|
|
|
return $this->mImageTimeKeys;
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* Convert wikitext to HTML and add it to the buffer
|
2010-01-29 21:32:45 +00:00
|
|
|
* Default assumes that the current page title will be used.
|
2006-11-07 05:37:31 +00:00
|
|
|
*
|
2010-01-29 21:32:45 +00:00
|
|
|
* @param $text String
|
|
|
|
|
* @param $linestart Boolean: is this the start of a line?
|
2011-09-11 21:07:17 +00:00
|
|
|
* @param $interface Boolean: is this text in the user interface language?
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2011-09-11 21:07:17 +00:00
|
|
|
public function addWikiText( $text, $linestart = true, $interface = true ) {
|
2009-04-09 08:53:15 +00:00
|
|
|
$title = $this->getTitle(); // Work arround E_STRICT
|
2013-01-18 18:50:38 +00:00
|
|
|
if ( !$title ) {
|
|
|
|
|
throw new MWException( 'Title is null' );
|
|
|
|
|
}
|
2011-09-10 20:05:13 +00:00
|
|
|
$this->addWikiTextTitle( $text, $title, $linestart, /*tidy*/false, $interface );
|
2005-05-21 17:26:42 +00:00
|
|
|
}
|
|
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
|
|
|
|
* Add wikitext with a custom Title object
|
|
|
|
|
*
|
|
|
|
|
* @param $text String: wikitext
|
|
|
|
|
* @param $title Title object
|
|
|
|
|
* @param $linestart Boolean: is this the start of a line?
|
|
|
|
|
*/
|
|
|
|
|
public function addWikiTextWithTitle( $text, &$title, $linestart = true ) {
|
|
|
|
|
$this->addWikiTextTitle( $text, $title, $linestart );
|
2005-05-21 17:26:42 +00:00
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
2011-09-28 22:08:08 +00:00
|
|
|
* Add wikitext with a custom Title object and tidy enabled.
|
2010-01-29 21:32:45 +00:00
|
|
|
*
|
|
|
|
|
* @param $text String: wikitext
|
|
|
|
|
* @param $title Title object
|
|
|
|
|
* @param $linestart Boolean: is this the start of a line?
|
|
|
|
|
*/
|
|
|
|
|
function addWikiTextTitleTidy( $text, &$title, $linestart = true ) {
|
2007-01-14 17:37:29 +00:00
|
|
|
$this->addWikiTextTitle( $text, $title, $linestart, true );
|
2007-01-10 23:32:38 +00:00
|
|
|
}
|
|
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
|
|
|
|
* Add wikitext with tidy enabled
|
|
|
|
|
*
|
|
|
|
|
* @param $text String: wikitext
|
|
|
|
|
* @param $linestart Boolean: is this the start of a line?
|
|
|
|
|
*/
|
|
|
|
|
public function addWikiTextTidy( $text, $linestart = true ) {
|
|
|
|
|
$title = $this->getTitle();
|
2010-05-22 12:18:22 +00:00
|
|
|
$this->addWikiTextTitleTidy( $text, $title, $linestart );
|
2010-01-29 21:32:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add wikitext with a custom Title object
|
|
|
|
|
*
|
|
|
|
|
* @param $text String: wikitext
|
|
|
|
|
* @param $title Title object
|
|
|
|
|
* @param $linestart Boolean: is this the start of a line?
|
|
|
|
|
* @param $tidy Boolean: whether to use tidy
|
2011-09-10 20:05:13 +00:00
|
|
|
* @param $interface Boolean: whether it is an interface message
|
|
|
|
|
* (for example disables conversion)
|
2010-01-29 21:32:45 +00:00
|
|
|
*/
|
2012-11-15 15:25:09 +00:00
|
|
|
public function addWikiTextTitle( $text, Title $title, $linestart, $tidy = false, $interface = false ) {
|
2005-12-04 18:27:59 +00:00
|
|
|
global $wgParser;
|
2007-01-10 23:32:38 +00:00
|
|
|
|
2008-04-16 13:46:16 +00:00
|
|
|
wfProfileIn( __METHOD__ );
|
2007-01-10 23:32:38 +00:00
|
|
|
|
|
|
|
|
$popts = $this->parserOptions();
|
2008-04-16 13:46:16 +00:00
|
|
|
$oldTidy = $popts->setTidy( $tidy );
|
2011-09-10 20:05:13 +00:00
|
|
|
$popts->setInterfaceMessage( (bool) $interface );
|
2007-01-10 23:32:38 +00:00
|
|
|
|
2010-05-22 12:18:22 +00:00
|
|
|
$parserOutput = $wgParser->parse(
|
|
|
|
|
$text, $title, $popts,
|
|
|
|
|
$linestart, true, $this->mRevisionId
|
|
|
|
|
);
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2007-09-11 18:22:37 +00:00
|
|
|
$popts->setTidy( $oldTidy );
|
2007-01-10 23:32:38 +00:00
|
|
|
|
2006-01-01 20:08:08 +00:00
|
|
|
$this->addParserOutput( $parserOutput );
|
2007-01-10 23:32:38 +00:00
|
|
|
|
2008-04-16 13:46:16 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2006-01-01 20:08:08 +00:00
|
|
|
}
|
|
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
|
|
|
|
* Add a ParserOutput object, but without Html
|
|
|
|
|
*
|
|
|
|
|
* @param $parserOutput ParserOutput object
|
2006-11-07 05:37:31 +00:00
|
|
|
*/
|
|
|
|
|
public function addParserOutputNoText( &$parserOutput ) {
|
2004-08-21 14:56:07 +00:00
|
|
|
$this->mLanguageLinks += $parserOutput->getLanguageLinks();
|
2005-12-30 09:33:11 +00:00
|
|
|
$this->addCategoryLinks( $parserOutput->getCategories() );
|
2006-05-01 20:35:08 +00:00
|
|
|
$this->mNewSectionLink = $parserOutput->getNewSection();
|
2009-02-19 22:14:59 +00:00
|
|
|
$this->mHideNewSectionLink = $parserOutput->getHideNewSection();
|
2008-07-24 18:02:20 +00:00
|
|
|
|
2007-12-10 06:02:29 +00:00
|
|
|
$this->mParseWarnings = $parserOutput->getWarnings();
|
2010-06-01 14:28:51 +00:00
|
|
|
if ( !$parserOutput->isCacheable() ) {
|
2005-05-28 11:09:22 +00:00
|
|
|
$this->enableClientCache( false );
|
|
|
|
|
}
|
2006-08-24 17:05:52 +00:00
|
|
|
$this->mNoGallery = $parserOutput->getNoGallery();
|
2010-01-16 13:07:58 +00:00
|
|
|
$this->mHeadItems = array_merge( $this->mHeadItems, $parserOutput->getHeadItems() );
|
2010-09-04 04:00:09 +00:00
|
|
|
$this->addModules( $parserOutput->getModules() );
|
2011-08-02 15:40:03 +00:00
|
|
|
$this->addModuleScripts( $parserOutput->getModuleScripts() );
|
|
|
|
|
$this->addModuleStyles( $parserOutput->getModuleStyles() );
|
|
|
|
|
$this->addModuleMessages( $parserOutput->getModuleMessages() );
|
2011-03-23 17:35:40 +00:00
|
|
|
|
|
|
|
|
// Template versioning...
|
|
|
|
|
foreach ( (array)$parserOutput->getTemplateIds() as $ns => $dbks ) {
|
2008-11-01 23:20:25 +00:00
|
|
|
if ( isset( $this->mTemplateIds[$ns] ) ) {
|
|
|
|
|
$this->mTemplateIds[$ns] = $dbks + $this->mTemplateIds[$ns];
|
|
|
|
|
} else {
|
|
|
|
|
$this->mTemplateIds[$ns] = $dbks;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-03-23 17:35:40 +00:00
|
|
|
// File versioning...
|
2011-09-14 19:05:43 +00:00
|
|
|
foreach ( (array)$parserOutput->getFileSearchOptions() as $dbk => $data ) {
|
2011-03-23 17:35:40 +00:00
|
|
|
$this->mImageTimeKeys[$dbk] = $data;
|
|
|
|
|
}
|
Basic integrated audio/video support, with Ogg implementation.
* JavaScript video player based loosely on Greg Maxwell's player
* Image page text snippet customisation
* Abstraction of transform parameters in the parser. Introduced Linker::makeImageLink2().
* Made canRender(), mustRender() depend on file, not just on handler. Moved width=0, height=0 checking to ImageHandler::canRender(), since audio streams have width=height=0 but should be rendered.
Also:
* Automatic upgrade for oldimage rows on image page view, allows media handler selection based on oi_*_mime
* oi_*_mime unconditionally referenced, REQUIRES SCHEMA UPGRADE
* Don't destroy file info for missing files on upgrade
* Simple, centralised extension message file handling
* Made MessageCache::loadAllMessages non-static, optimised for repeated-call case due to abuse in User.php
* Support for lightweight parser output hooks, with callback whitelist for security
* Moved Linker::formatSize() to Language, to join the new formatTimePeriod() and formatBitrate()
* Introduced MagicWordArray, regex capture trick requires that magic word IDs DO NOT CONTAIN HYPHENS.
2007-08-15 10:50:09 +00:00
|
|
|
|
2008-02-20 08:53:12 +00:00
|
|
|
// Hooks registered in the object
|
Basic integrated audio/video support, with Ogg implementation.
* JavaScript video player based loosely on Greg Maxwell's player
* Image page text snippet customisation
* Abstraction of transform parameters in the parser. Introduced Linker::makeImageLink2().
* Made canRender(), mustRender() depend on file, not just on handler. Moved width=0, height=0 checking to ImageHandler::canRender(), since audio streams have width=height=0 but should be rendered.
Also:
* Automatic upgrade for oldimage rows on image page view, allows media handler selection based on oi_*_mime
* oi_*_mime unconditionally referenced, REQUIRES SCHEMA UPGRADE
* Don't destroy file info for missing files on upgrade
* Simple, centralised extension message file handling
* Made MessageCache::loadAllMessages non-static, optimised for repeated-call case due to abuse in User.php
* Support for lightweight parser output hooks, with callback whitelist for security
* Moved Linker::formatSize() to Language, to join the new formatTimePeriod() and formatBitrate()
* Introduced MagicWordArray, regex capture trick requires that magic word IDs DO NOT CONTAIN HYPHENS.
2007-08-15 10:50:09 +00:00
|
|
|
global $wgParserOutputHooks;
|
|
|
|
|
foreach ( $parserOutput->getOutputHooks() as $hookInfo ) {
|
|
|
|
|
list( $hookName, $data ) = $hookInfo;
|
|
|
|
|
if ( isset( $wgParserOutputHooks[$hookName] ) ) {
|
|
|
|
|
call_user_func( $wgParserOutputHooks[$hookName], $this, $parserOutput, $data );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-24 17:05:52 +00:00
|
|
|
wfRunHooks( 'OutputPageParserOutput', array( &$this, $parserOutput ) );
|
2006-01-01 20:08:08 +00:00
|
|
|
}
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2006-11-07 05:37:31 +00:00
|
|
|
/**
|
2010-01-29 21:32:45 +00:00
|
|
|
* Add a ParserOutput object
|
|
|
|
|
*
|
|
|
|
|
* @param $parserOutput ParserOutput
|
2006-11-07 05:37:31 +00:00
|
|
|
*/
|
2006-01-01 20:08:08 +00:00
|
|
|
function addParserOutput( &$parserOutput ) {
|
|
|
|
|
$this->addParserOutputNoText( $parserOutput );
|
2009-09-18 20:10:25 +00:00
|
|
|
$text = $parserOutput->getText();
|
2010-05-22 12:18:22 +00:00
|
|
|
wfRunHooks( 'OutputPageBeforeHTML', array( &$this, &$text ) );
|
2006-08-24 17:05:52 +00:00
|
|
|
$this->addHTML( $text );
|
2005-07-01 00:03:31 +00:00
|
|
|
}
|
|
|
|
|
|
2006-01-23 18:37:46 +00:00
|
|
|
|
2004-11-25 06:04:16 +00:00
|
|
|
/**
|
|
|
|
|
* Add the output of a QuickTemplate to the output buffer
|
2006-11-07 05:37:31 +00:00
|
|
|
*
|
2010-01-29 21:32:45 +00:00
|
|
|
* @param $template QuickTemplate
|
2004-11-25 06:04:16 +00:00
|
|
|
*/
|
2006-11-07 05:37:31 +00:00
|
|
|
public function addTemplate( &$template ) {
|
2004-11-25 06:04:16 +00:00
|
|
|
ob_start();
|
|
|
|
|
$template->execute();
|
2005-12-30 09:33:11 +00:00
|
|
|
$this->addHTML( ob_get_contents() );
|
2004-11-25 06:04:16 +00:00
|
|
|
ob_end_clean();
|
|
|
|
|
}
|
2004-11-29 11:26:24 +00:00
|
|
|
|
|
|
|
|
/**
|
2006-04-29 13:15:19 +00:00
|
|
|
* Parse wikitext and return the HTML.
|
2006-11-07 05:37:31 +00:00
|
|
|
*
|
2010-01-29 21:32:45 +00:00
|
|
|
* @param $text String
|
|
|
|
|
* @param $linestart Boolean: is this the start of a line?
|
2010-01-30 17:40:17 +00:00
|
|
|
* @param $interface Boolean: use interface language ($wgLang instead of
|
|
|
|
|
* $wgContLang) while parsing language sensitive magic
|
2011-09-04 21:19:18 +00:00
|
|
|
* words like GRAMMAR and PLURAL. This also disables
|
2012-10-07 23:35:26 +00:00
|
|
|
* LanguageConverter.
|
2011-01-05 12:24:39 +00:00
|
|
|
* @param $language Language object: target language object, will override
|
|
|
|
|
* $interface
|
2012-10-07 23:35:26 +00:00
|
|
|
* @throws MWException
|
2010-01-29 21:32:45 +00:00
|
|
|
* @return String: HTML
|
2004-11-29 11:26:24 +00:00
|
|
|
*/
|
2011-01-05 12:24:39 +00:00
|
|
|
public function parse( $text, $linestart = true, $interface = false, $language = null ) {
|
2009-04-09 02:22:36 +00:00
|
|
|
global $wgParser;
|
2011-01-05 12:24:39 +00:00
|
|
|
|
2009-04-09 02:22:36 +00:00
|
|
|
if( is_null( $this->getTitle() ) ) {
|
|
|
|
|
throw new MWException( 'Empty $mTitle in ' . __METHOD__ );
|
2008-11-24 01:58:15 +00:00
|
|
|
}
|
2011-01-05 12:24:39 +00:00
|
|
|
|
2006-07-26 07:15:39 +00:00
|
|
|
$popts = $this->parserOptions();
|
2010-05-22 12:18:22 +00:00
|
|
|
if ( $interface ) {
|
|
|
|
|
$popts->setInterfaceMessage( true );
|
|
|
|
|
}
|
2011-01-05 12:24:39 +00:00
|
|
|
if ( $language !== null ) {
|
|
|
|
|
$oldLang = $popts->setTargetLanguage( $language );
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-22 12:18:22 +00:00
|
|
|
$parserOutput = $wgParser->parse(
|
|
|
|
|
$text, $this->getTitle(), $popts,
|
|
|
|
|
$linestart, true, $this->mRevisionId
|
|
|
|
|
);
|
2011-01-05 12:24:39 +00:00
|
|
|
|
2010-05-22 12:18:22 +00:00
|
|
|
if ( $interface ) {
|
|
|
|
|
$popts->setInterfaceMessage( false );
|
|
|
|
|
}
|
2011-01-05 12:24:39 +00:00
|
|
|
if ( $language !== null ) {
|
|
|
|
|
$popts->setTargetLanguage( $oldLang );
|
|
|
|
|
}
|
|
|
|
|
|
2004-11-29 11:26:24 +00:00
|
|
|
return $parserOutput->getText();
|
|
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
|
|
|
|
* Parse wikitext, strip paragraphs, and return the HTML.
|
|
|
|
|
*
|
|
|
|
|
* @param $text String
|
|
|
|
|
* @param $linestart Boolean: is this the start of a line?
|
2010-01-30 17:40:17 +00:00
|
|
|
* @param $interface Boolean: use interface language ($wgLang instead of
|
|
|
|
|
* $wgContLang) while parsing language sensitive magic
|
|
|
|
|
* words like GRAMMAR and PLURAL
|
2010-01-29 21:32:45 +00:00
|
|
|
* @return String: HTML
|
|
|
|
|
*/
|
2009-01-31 01:59:13 +00:00
|
|
|
public function parseInline( $text, $linestart = true, $interface = false ) {
|
|
|
|
|
$parsed = $this->parse( $text, $linestart, $interface );
|
|
|
|
|
|
|
|
|
|
$m = array();
|
|
|
|
|
if ( preg_match( '/^<p>(.*)\n?<\/p>\n?/sU', $parsed, $m ) ) {
|
|
|
|
|
$parsed = $m[1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $parsed;
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2010-01-29 21:32:45 +00:00
|
|
|
* Set the value of the "s-maxage" part of the "Cache-control" HTTP header
|
|
|
|
|
*
|
|
|
|
|
* @param $maxage Integer: maximum cache time on the Squid, in seconds.
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2006-11-07 05:37:31 +00:00
|
|
|
public function setSquidMaxage( $maxage ) {
|
2004-03-13 13:42:17 +00:00
|
|
|
$this->mSquidMaxage = $maxage;
|
2004-02-08 21:12:07 +00:00
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* Use enableClientCache(false) to force it to send nocache headers
|
2010-01-29 21:32:45 +00:00
|
|
|
*
|
2011-05-21 19:07:24 +00:00
|
|
|
* @param $state bool
|
|
|
|
|
*
|
|
|
|
|
* @return bool
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2006-11-07 05:37:31 +00:00
|
|
|
public function enableClientCache( $state ) {
|
2004-03-23 10:19:31 +00:00
|
|
|
return wfSetVar( $this->mEnableClientCache, $state );
|
|
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
|
|
|
|
* Get the list of cookies that will influence on the cache
|
|
|
|
|
*
|
|
|
|
|
* @return Array
|
|
|
|
|
*/
|
2008-02-20 04:13:24 +00:00
|
|
|
function getCacheVaryCookies() {
|
2008-04-10 08:42:36 +00:00
|
|
|
global $wgCookiePrefix, $wgCacheVaryCookies;
|
|
|
|
|
static $cookies;
|
|
|
|
|
if ( $cookies === null ) {
|
2008-04-14 07:45:50 +00:00
|
|
|
$cookies = array_merge(
|
2008-04-10 08:42:36 +00:00
|
|
|
array(
|
|
|
|
|
"{$wgCookiePrefix}Token",
|
|
|
|
|
"{$wgCookiePrefix}LoggedOut",
|
|
|
|
|
session_name()
|
|
|
|
|
),
|
|
|
|
|
$wgCacheVaryCookies
|
|
|
|
|
);
|
2010-05-22 12:18:22 +00:00
|
|
|
wfRunHooks( 'GetCacheVaryCookies', array( $this, &$cookies ) );
|
2008-04-10 08:42:36 +00:00
|
|
|
}
|
|
|
|
|
return $cookies;
|
2008-02-20 04:13:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Check if the request has a cache-varying cookie header
|
|
|
|
|
* If it does, it's very important that we don't allow public caching
|
2010-01-29 21:32:45 +00:00
|
|
|
*
|
|
|
|
|
* @return Boolean
|
2008-02-20 04:13:24 +00:00
|
|
|
*/
|
|
|
|
|
function haveCacheVaryCookies() {
|
2011-04-03 12:46:36 +00:00
|
|
|
$cookieHeader = $this->getRequest()->getHeader( 'cookie' );
|
2008-02-20 04:13:24 +00:00
|
|
|
if ( $cookieHeader === false ) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
$cvCookies = $this->getCacheVaryCookies();
|
|
|
|
|
foreach ( $cvCookies as $cookieName ) {
|
|
|
|
|
# Check for a simple string match, like the way squid does it
|
2010-07-23 05:11:18 +00:00
|
|
|
if ( strpos( $cookieHeader, $cookieName ) !== false ) {
|
2010-05-22 12:18:22 +00:00
|
|
|
wfDebug( __METHOD__ . ": found $cookieName\n" );
|
2008-02-20 04:13:24 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-05-22 12:18:22 +00:00
|
|
|
wfDebug( __METHOD__ . ": no cache-varying cookies found\n" );
|
2008-02-20 04:13:24 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
|
|
|
|
* Add an HTTP header that will influence on the cache
|
|
|
|
|
*
|
|
|
|
|
* @param $header String: header name
|
2011-02-02 11:00:09 +00:00
|
|
|
* @param $option Array|null
|
2011-05-17 22:03:20 +00:00
|
|
|
* @todo FIXME: Document the $option parameter; it appears to be for
|
2011-01-22 16:59:01 +00:00
|
|
|
* X-Vary-Options but what format is acceptable?
|
2010-01-29 21:32:45 +00:00
|
|
|
*/
|
2009-11-29 06:47:51 +00:00
|
|
|
public function addVaryHeader( $header, $option = null ) {
|
|
|
|
|
if ( !array_key_exists( $header, $this->mVaryHeader ) ) {
|
2011-01-22 16:59:01 +00:00
|
|
|
$this->mVaryHeader[$header] = (array)$option;
|
2010-05-22 12:18:22 +00:00
|
|
|
} elseif( is_array( $option ) ) {
|
2009-11-29 06:47:51 +00:00
|
|
|
if( is_array( $this->mVaryHeader[$header] ) ) {
|
|
|
|
|
$this->mVaryHeader[$header] = array_merge( $this->mVaryHeader[$header], $option );
|
2010-05-22 12:18:22 +00:00
|
|
|
} else {
|
2009-11-29 06:47:51 +00:00
|
|
|
$this->mVaryHeader[$header] = $option;
|
2009-11-28 19:13:23 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-10-31 18:27:35 +00:00
|
|
|
$this->mVaryHeader[$header] = array_unique( (array)$this->mVaryHeader[$header] );
|
2009-11-28 19:13:23 +00:00
|
|
|
}
|
|
|
|
|
|
2012-06-01 10:23:53 +00:00
|
|
|
/**
|
|
|
|
|
* Return a Vary: header on which to vary caches. Based on the keys of $mVaryHeader,
|
|
|
|
|
* such as Accept-Encoding or Cookie
|
2012-08-08 08:42:17 +00:00
|
|
|
*
|
2012-06-01 10:23:53 +00:00
|
|
|
* @return String
|
|
|
|
|
*/
|
|
|
|
|
public function getVaryHeader() {
|
|
|
|
|
return 'Vary: ' . join( ', ', array_keys( $this->mVaryHeader ) );
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
|
|
|
|
* Get a complete X-Vary-Options header
|
|
|
|
|
*
|
|
|
|
|
* @return String
|
|
|
|
|
*/
|
2008-02-08 07:12:38 +00:00
|
|
|
public function getXVO() {
|
2008-02-20 04:13:24 +00:00
|
|
|
$cvCookies = $this->getCacheVaryCookies();
|
2010-05-22 11:47:56 +00:00
|
|
|
|
2009-11-28 19:13:23 +00:00
|
|
|
$cookiesOption = array();
|
2008-02-20 04:13:24 +00:00
|
|
|
foreach ( $cvCookies as $cookieName ) {
|
2009-11-28 19:13:23 +00:00
|
|
|
$cookiesOption[] = 'string-contains=' . $cookieName;
|
|
|
|
|
}
|
2009-11-29 06:47:51 +00:00
|
|
|
$this->addVaryHeader( 'Cookie', $cookiesOption );
|
2010-05-22 11:47:56 +00:00
|
|
|
|
2009-11-28 19:13:23 +00:00
|
|
|
$headers = array();
|
2009-11-29 06:47:51 +00:00
|
|
|
foreach( $this->mVaryHeader as $header => $option ) {
|
2009-11-28 19:13:23 +00:00
|
|
|
$newheader = $header;
|
2012-06-05 22:58:54 +00:00
|
|
|
if ( is_array( $option ) && count( $option ) > 0 ) {
|
2009-11-28 19:13:23 +00:00
|
|
|
$newheader .= ';' . implode( ';', $option );
|
2010-05-22 12:18:22 +00:00
|
|
|
}
|
2009-11-28 19:13:23 +00:00
|
|
|
$headers[] = $newheader;
|
|
|
|
|
}
|
|
|
|
|
$xvo = 'X-Vary-Options: ' . implode( ',', $headers );
|
2010-05-22 11:47:56 +00:00
|
|
|
|
2008-02-20 04:13:24 +00:00
|
|
|
return $xvo;
|
2008-02-08 07:12:38 +00:00
|
|
|
}
|
|
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
|
|
|
|
* bug 21672: Add Accept-Language to Vary and XVO headers
|
2010-01-30 17:40:17 +00:00
|
|
|
* if there's no 'variant' parameter existed in GET.
|
2010-01-29 21:32:45 +00:00
|
|
|
*
|
|
|
|
|
* For example:
|
|
|
|
|
* /w/index.php?title=Main_page should always be served; but
|
|
|
|
|
* /w/index.php?title=Main_page&variant=zh-cn should never be served.
|
|
|
|
|
*/
|
2009-12-21 18:55:42 +00:00
|
|
|
function addAcceptLanguage() {
|
2011-09-22 20:31:23 +00:00
|
|
|
$lang = $this->getTitle()->getPageLanguage();
|
|
|
|
|
if( !$this->getRequest()->getCheck( 'variant' ) && $lang->hasVariants() ) {
|
|
|
|
|
$variants = $lang->getVariants();
|
2009-12-21 18:55:42 +00:00
|
|
|
$aloption = array();
|
|
|
|
|
foreach ( $variants as $variant ) {
|
2011-09-22 20:31:23 +00:00
|
|
|
if( $variant === $lang->getCode() ) {
|
2009-12-21 18:55:42 +00:00
|
|
|
continue;
|
2010-05-22 12:18:22 +00:00
|
|
|
} else {
|
2010-10-28 16:58:39 +00:00
|
|
|
$aloption[] = 'string-contains=' . $variant;
|
2011-01-13 22:08:13 +00:00
|
|
|
|
2012-11-17 20:00:12 +00:00
|
|
|
// IE and some other browsers use BCP 47 standards in
|
|
|
|
|
// their Accept-Language header, like "zh-CN" or "zh-Hant".
|
2010-10-28 16:58:39 +00:00
|
|
|
// We should handle these too.
|
2012-11-17 20:00:12 +00:00
|
|
|
$variantBCP47 = wfBCP47( $variant );
|
|
|
|
|
if ( $variantBCP47 !== $variant ) {
|
|
|
|
|
$aloption[] = 'string-contains=' . $variantBCP47;
|
2010-10-28 16:58:39 +00:00
|
|
|
}
|
2010-05-22 12:18:22 +00:00
|
|
|
}
|
2009-12-21 18:55:42 +00:00
|
|
|
}
|
|
|
|
|
$this->addVaryHeader( 'Accept-Language', $aloption );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-04 06:12:33 +00:00
|
|
|
/**
|
2011-04-23 19:28:35 +00:00
|
|
|
* Set a flag which will cause an X-Frame-Options header appropriate for
|
|
|
|
|
* edit pages to be sent. The header value is controlled by
|
2011-01-04 06:12:33 +00:00
|
|
|
* $wgEditPageFrameOptions.
|
|
|
|
|
*
|
2011-04-23 19:28:35 +00:00
|
|
|
* This is the default for special pages. If you display a CSRF-protected
|
2011-01-04 06:12:33 +00:00
|
|
|
* form on an ordinary view page, then you need to call this function.
|
2011-05-21 19:07:24 +00:00
|
|
|
*
|
|
|
|
|
* @param $enable bool
|
2011-01-04 06:12:33 +00:00
|
|
|
*/
|
|
|
|
|
public function preventClickjacking( $enable = true ) {
|
|
|
|
|
$this->mPreventClickjacking = $enable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Turn off frame-breaking. Alias for $this->preventClickjacking(false).
|
|
|
|
|
* This can be called from pages which do not contain any CSRF-protected
|
|
|
|
|
* HTML form.
|
|
|
|
|
*/
|
|
|
|
|
public function allowClickjacking() {
|
|
|
|
|
$this->mPreventClickjacking = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2011-04-23 19:28:35 +00:00
|
|
|
* Get the X-Frame-Options header value (without the name part), or false
|
|
|
|
|
* if there isn't one. This is used by Skin to determine whether to enable
|
2011-01-04 06:12:33 +00:00
|
|
|
* JavaScript frame-breaking, for clients that don't support X-Frame-Options.
|
2011-05-21 19:07:24 +00:00
|
|
|
*
|
|
|
|
|
* @return string
|
2011-01-04 06:12:33 +00:00
|
|
|
*/
|
|
|
|
|
public function getFrameOptions() {
|
|
|
|
|
global $wgBreakFrames, $wgEditPageFrameOptions;
|
|
|
|
|
if ( $wgBreakFrames ) {
|
|
|
|
|
return 'DENY';
|
|
|
|
|
} elseif ( $this->mPreventClickjacking && $wgEditPageFrameOptions ) {
|
|
|
|
|
return $wgEditPageFrameOptions;
|
|
|
|
|
}
|
2011-10-16 03:27:12 +00:00
|
|
|
return false;
|
2011-01-04 06:12:33 +00:00
|
|
|
}
|
|
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
|
|
|
|
* Send cache control HTTP headers
|
|
|
|
|
*/
|
2006-11-07 05:37:31 +00:00
|
|
|
public function sendCacheControl() {
|
2011-04-03 12:46:36 +00:00
|
|
|
global $wgUseSquid, $wgUseESI, $wgUseETag, $wgSquidMaxage, $wgUseXVO;
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2011-04-03 12:46:36 +00:00
|
|
|
$response = $this->getRequest()->response();
|
2010-05-22 12:18:22 +00:00
|
|
|
if ( $wgUseETag && $this->mETag ) {
|
|
|
|
|
$response->header( "ETag: $this->mETag" );
|
|
|
|
|
}
|
2008-12-23 19:39:00 +00:00
|
|
|
|
2012-06-01 10:23:53 +00:00
|
|
|
$this->addVaryHeader( 'Cookie' );
|
2009-12-21 18:55:42 +00:00
|
|
|
$this->addAcceptLanguage();
|
|
|
|
|
|
2008-12-23 19:39:00 +00:00
|
|
|
# don't serve compressed data to clients who can't handle it
|
2005-03-08 02:58:43 +00:00
|
|
|
# maintain different caches for logged-in users and non-logged in ones
|
2012-06-01 10:23:53 +00:00
|
|
|
$response->header( $this->getVaryHeader() );
|
2008-02-08 07:12:38 +00:00
|
|
|
|
2009-07-24 20:01:23 +00:00
|
|
|
if ( $wgUseXVO ) {
|
|
|
|
|
# Add an X-Vary-Options header for Squid with Wikimedia patches
|
|
|
|
|
$response->header( $this->getXVO() );
|
|
|
|
|
}
|
2008-02-08 07:12:38 +00:00
|
|
|
|
2012-05-22 23:37:53 +00:00
|
|
|
if( $this->mEnableClientCache ) {
|
2010-05-22 12:18:22 +00:00
|
|
|
if(
|
|
|
|
|
$wgUseSquid && session_id() == '' && !$this->isPrintable() &&
|
|
|
|
|
$this->mSquidMaxage != 0 && !$this->haveCacheVaryCookies()
|
|
|
|
|
)
|
2004-02-04 00:45:48 +00:00
|
|
|
{
|
2008-12-23 19:39:00 +00:00
|
|
|
if ( $wgUseESI ) {
|
2004-02-02 01:40:03 +00:00
|
|
|
# We'll purge the proxy cache explicitly, but require end user agents
|
2004-01-31 12:45:09 +00:00
|
|
|
# to revalidate against the proxy on each visit.
|
|
|
|
|
# Surrogate-Control controls our Squid, Cache-Control downstream caches
|
2008-04-16 13:46:16 +00:00
|
|
|
wfDebug( __METHOD__ . ": proxy caching with ESI; {$this->mLastModified} **\n", false );
|
2004-01-31 12:45:09 +00:00
|
|
|
# start with a shorter timeout for initial testing
|
|
|
|
|
# header( 'Surrogate-Control: max-age=2678400+2678400, content="ESI/1.0"');
|
2013-02-09 22:03:53 +00:00
|
|
|
$response->header( 'Surrogate-Control: max-age=' . $wgSquidMaxage . '+' . $this->mSquidMaxage . ', content="ESI/1.0"' );
|
2008-02-08 07:12:38 +00:00
|
|
|
$response->header( 'Cache-Control: s-maxage=0, must-revalidate, max-age=0' );
|
2004-01-31 12:45:09 +00:00
|
|
|
} else {
|
|
|
|
|
# We'll purge the proxy cache for anons explicitly, but require end user agents
|
|
|
|
|
# to revalidate against the proxy on each visit.
|
2004-07-08 14:53:54 +00:00
|
|
|
# IMPORTANT! The Squid needs to replace the Cache-Control header with
|
2004-01-31 12:45:09 +00:00
|
|
|
# Cache-Control: s-maxage=0, must-revalidate, max-age=0
|
2008-04-16 13:46:16 +00:00
|
|
|
wfDebug( __METHOD__ . ": local proxy caching; {$this->mLastModified} **\n", false );
|
2004-01-31 12:45:09 +00:00
|
|
|
# start with a shorter timeout for initial testing
|
|
|
|
|
# header( "Cache-Control: s-maxage=2678400, must-revalidate, max-age=0" );
|
2013-02-03 20:05:24 +00:00
|
|
|
$response->header( 'Cache-Control: s-maxage=' . $this->mSquidMaxage . ', must-revalidate, max-age=0' );
|
2004-01-31 12:45:09 +00:00
|
|
|
}
|
2004-01-31 10:29:31 +00:00
|
|
|
} else {
|
|
|
|
|
# We do want clients to cache if they can, but they *must* check for updates
|
|
|
|
|
# on revisiting the page.
|
2008-04-16 13:46:16 +00:00
|
|
|
wfDebug( __METHOD__ . ": private caching; {$this->mLastModified} **\n", false );
|
2008-02-08 07:12:38 +00:00
|
|
|
$response->header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' );
|
|
|
|
|
$response->header( "Cache-Control: private, must-revalidate, max-age=0" );
|
2004-01-31 10:29:31 +00:00
|
|
|
}
|
2013-02-03 20:05:24 +00:00
|
|
|
if( $this->mLastModified ) {
|
2008-08-29 08:40:13 +00:00
|
|
|
$response->header( "Last-Modified: {$this->mLastModified}" );
|
|
|
|
|
}
|
2003-07-03 10:18:07 +00:00
|
|
|
} else {
|
2008-04-16 13:46:16 +00:00
|
|
|
wfDebug( __METHOD__ . ": no caching **\n", false );
|
2004-03-23 10:19:31 +00:00
|
|
|
|
|
|
|
|
# In general, the absence of a last modified header should be enough to prevent
|
|
|
|
|
# the client from using its cache. We send a few other things just to make sure.
|
2008-02-08 07:12:38 +00:00
|
|
|
$response->header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' );
|
|
|
|
|
$response->header( 'Cache-Control: no-cache, no-store, max-age=0, must-revalidate' );
|
|
|
|
|
$response->header( 'Pragma: no-cache' );
|
2003-07-03 10:18:07 +00:00
|
|
|
}
|
|
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2009-12-01 20:56:43 +00:00
|
|
|
/**
|
|
|
|
|
* Get the message associed with the HTTP response code $code
|
|
|
|
|
*
|
|
|
|
|
* @param $code Integer: status code
|
|
|
|
|
* @return String or null: message or null if $code is not in the list of
|
2011-07-18 23:01:08 +00:00
|
|
|
* messages
|
2011-07-04 21:01:19 +00:00
|
|
|
*
|
2011-07-18 23:01:08 +00:00
|
|
|
* @deprecated since 1.18 Use HttpStatus::getMessage() instead.
|
2009-12-01 20:56:43 +00:00
|
|
|
*/
|
|
|
|
|
public static function getStatusMessage( $code ) {
|
2012-10-05 18:26:00 +00:00
|
|
|
wfDeprecated( __METHOD__, '1.18' );
|
2011-07-04 21:01:19 +00:00
|
|
|
return HttpStatus::getMessage( $code );
|
2009-12-01 20:56:43 +00:00
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* Finally, all the text has been munged and accumulated into
|
|
|
|
|
* the object, let's actually output it:
|
|
|
|
|
*/
|
2006-11-07 05:37:31 +00:00
|
|
|
public function output() {
|
2011-10-03 13:15:28 +00:00
|
|
|
global $wgLanguageCode, $wgDebugRedirects, $wgMimeType, $wgVaryOnXFP;
|
2004-10-08 04:27:07 +00:00
|
|
|
|
2010-05-22 12:18:22 +00:00
|
|
|
if( $this->mDoNothing ) {
|
2008-12-31 17:56:04 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2011-04-02 18:38:42 +00:00
|
|
|
|
2008-04-16 13:46:16 +00:00
|
|
|
wfProfileIn( __METHOD__ );
|
2011-04-02 18:38:42 +00:00
|
|
|
|
2011-04-03 12:46:36 +00:00
|
|
|
$response = $this->getRequest()->response();
|
2011-04-02 18:38:42 +00:00
|
|
|
|
2010-01-06 19:59:42 +00:00
|
|
|
if ( $this->mRedirect != '' ) {
|
2008-02-13 05:59:14 +00:00
|
|
|
# Standards require redirect URLs to be absolute
|
2011-08-19 15:46:08 +00:00
|
|
|
$this->mRedirect = wfExpandUrl( $this->mRedirect, PROTO_CURRENT );
|
2011-12-14 00:38:21 +00:00
|
|
|
|
|
|
|
|
$redirect = $this->mRedirect;
|
|
|
|
|
$code = $this->mRedirectCode;
|
|
|
|
|
|
2011-12-14 00:50:06 +00:00
|
|
|
if( wfRunHooks( "BeforePageRedirect", array( $this, &$redirect, &$code ) ) ) {
|
2011-12-14 00:38:21 +00:00
|
|
|
if( $code == '301' || $code == '303' ) {
|
|
|
|
|
if( !$wgDebugRedirects ) {
|
|
|
|
|
$message = HttpStatus::getMessage( $code );
|
|
|
|
|
$response->header( "HTTP/1.1 $code $message" );
|
|
|
|
|
}
|
|
|
|
|
$this->mLastModified = wfTimestamp( TS_RFC2822 );
|
|
|
|
|
}
|
|
|
|
|
if ( $wgVaryOnXFP ) {
|
|
|
|
|
$this->addVaryHeader( 'X-Forwarded-Proto' );
|
|
|
|
|
}
|
|
|
|
|
$this->sendCacheControl();
|
|
|
|
|
|
|
|
|
|
$response->header( "Content-Type: text/html; charset=utf-8" );
|
|
|
|
|
if( $wgDebugRedirects ) {
|
|
|
|
|
$url = htmlspecialchars( $redirect );
|
|
|
|
|
print "<html>\n<head>\n<title>Redirect</title>\n</head>\n<body>\n";
|
|
|
|
|
print "<p>Location: <a href=\"$url\">$url</a></p>\n";
|
|
|
|
|
print "</body>\n</html>\n";
|
|
|
|
|
} else {
|
|
|
|
|
$response->header( 'Location: ' . $redirect );
|
2004-03-05 03:18:31 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-12-14 00:38:21 +00:00
|
|
|
|
2008-04-16 13:46:16 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2003-04-14 23:10:40 +00:00
|
|
|
return;
|
2009-12-01 20:56:43 +00:00
|
|
|
} elseif ( $this->mStatusCode ) {
|
2011-07-05 14:37:22 +00:00
|
|
|
$message = HttpStatus::getMessage( $this->mStatusCode );
|
2010-05-22 12:18:22 +00:00
|
|
|
if ( $message ) {
|
2011-04-02 18:38:42 +00:00
|
|
|
$response->header( 'HTTP/1.1 ' . $this->mStatusCode . ' ' . $message );
|
2008-10-10 01:15:11 +00:00
|
|
|
}
|
|
|
|
|
}
|
2010-05-22 11:47:56 +00:00
|
|
|
|
2004-11-12 09:34:11 +00:00
|
|
|
# Buffer output; final headers may depend on later processing
|
2008-09-15 01:27:22 +00:00
|
|
|
ob_start();
|
2004-11-12 09:34:11 +00:00
|
|
|
|
2011-05-06 22:09:47 +00:00
|
|
|
$response->header( "Content-type: $wgMimeType; charset=UTF-8" );
|
2011-04-02 18:38:42 +00:00
|
|
|
$response->header( 'Content-language: ' . $wgLanguageCode );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2011-01-04 06:12:33 +00:00
|
|
|
// Prevent framing, if requested
|
|
|
|
|
$frameOptions = $this->getFrameOptions();
|
|
|
|
|
if ( $frameOptions ) {
|
2011-04-02 18:38:42 +00:00
|
|
|
$response->header( "X-Frame-Options: $frameOptions" );
|
2011-01-04 06:12:33 +00:00
|
|
|
}
|
|
|
|
|
|
2010-05-22 12:18:22 +00:00
|
|
|
if ( $this->mArticleBodyOnly ) {
|
|
|
|
|
$this->out( $this->mBodytext );
|
2005-07-03 04:00:33 +00:00
|
|
|
} else {
|
2011-04-02 18:38:42 +00:00
|
|
|
$this->addDefaultModules();
|
|
|
|
|
|
2011-06-22 18:24:58 +00:00
|
|
|
$sk = $this->getSkin();
|
2011-03-11 14:31:12 +00:00
|
|
|
|
2008-04-06 20:25:45 +00:00
|
|
|
// Hook that allows last minute changes to the output page, e.g.
|
|
|
|
|
// adding of CSS or Javascript by extensions.
|
2008-04-07 17:53:31 +00:00
|
|
|
wfRunHooks( 'BeforePageDisplay', array( &$this, &$sk ) );
|
2008-04-06 20:25:45 +00:00
|
|
|
|
2005-07-03 04:00:33 +00:00
|
|
|
wfProfileIn( 'Output-skin' );
|
2011-09-01 10:24:35 +00:00
|
|
|
$sk->outputPage();
|
2005-07-03 04:00:33 +00:00
|
|
|
wfProfileOut( 'Output-skin' );
|
|
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2012-07-05 14:21:21 +00:00
|
|
|
// This hook allows last minute changes to final overall output by modifying output buffer
|
|
|
|
|
wfRunHooks( 'AfterFinalPageOutput', array( $this ) );
|
|
|
|
|
|
2004-11-12 09:34:11 +00:00
|
|
|
$this->sendCacheControl();
|
2012-07-04 21:23:56 +00:00
|
|
|
|
2004-11-12 09:34:11 +00:00
|
|
|
ob_end_flush();
|
2012-07-04 21:23:56 +00:00
|
|
|
|
2008-04-16 13:46:16 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2006-11-07 05:37:31 +00:00
|
|
|
/**
|
2011-05-14 17:02:37 +00:00
|
|
|
* Actually output something with print().
|
2010-01-29 21:32:45 +00:00
|
|
|
*
|
|
|
|
|
* @param $ins String: the string to output
|
2006-11-07 05:37:31 +00:00
|
|
|
*/
|
|
|
|
|
public function out( $ins ) {
|
2011-05-14 17:02:37 +00:00
|
|
|
print $ins;
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2006-01-06 23:09:37 +00:00
|
|
|
/**
|
2006-11-07 05:37:31 +00:00
|
|
|
* Produce a "user is blocked" page.
|
2011-04-13 14:30:55 +00:00
|
|
|
* @deprecated since 1.18
|
2006-01-06 23:09:37 +00:00
|
|
|
*/
|
2011-04-13 14:30:55 +00:00
|
|
|
function blockedPage() {
|
2011-07-27 22:28:59 +00:00
|
|
|
throw new UserBlockedError( $this->getUser()->mBlock );
|
2006-01-06 23:09:37 +00:00
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2011-10-28 15:45:54 +00:00
|
|
|
/**
|
|
|
|
|
* Prepare this object to display an error page; disable caching and
|
|
|
|
|
* indexing, clear the current text and redirect, set the page's title
|
2012-07-10 12:48:06 +00:00
|
|
|
* and optionally an custom HTML title (content of the "<title>" tag).
|
2011-10-28 15:45:54 +00:00
|
|
|
*
|
|
|
|
|
* @param $pageTitle String|Message will be passed directly to setPageTitle()
|
|
|
|
|
* @param $htmlTitle String|Message will be passed directly to setHTMLTitle();
|
2012-07-10 12:48:06 +00:00
|
|
|
* optional, if not passed the "<title>" attribute will be
|
2011-10-28 15:45:54 +00:00
|
|
|
* based on $pageTitle
|
|
|
|
|
*/
|
|
|
|
|
public function prepareErrorPage( $pageTitle, $htmlTitle = false ) {
|
|
|
|
|
$this->setPageTitle( $pageTitle );
|
|
|
|
|
if ( $htmlTitle !== false ) {
|
|
|
|
|
$this->setHTMLTitle( $htmlTitle );
|
|
|
|
|
}
|
|
|
|
|
$this->setRobotPolicy( 'noindex,nofollow' );
|
|
|
|
|
$this->setArticleRelated( false );
|
|
|
|
|
$this->enableClientCache( false );
|
|
|
|
|
$this->mRedirect = '';
|
2011-11-08 18:02:26 +00:00
|
|
|
$this->clearSubtitle();
|
2011-10-28 15:45:54 +00:00
|
|
|
$this->clearHTML();
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2007-05-18 20:46:42 +00:00
|
|
|
* Output a standard error page
|
2006-11-07 05:37:31 +00:00
|
|
|
*
|
2011-08-25 10:13:30 +00:00
|
|
|
* showErrorPage( 'titlemsg', 'pagetextmsg', array( 'param1', 'param2' ) );
|
|
|
|
|
* showErrorPage( 'titlemsg', $messageObject );
|
2012-08-06 21:07:24 +00:00
|
|
|
* showErrorPage( $titleMessageObj, $messageObject );
|
2011-08-31 14:47:08 +00:00
|
|
|
*
|
2012-08-06 21:07:24 +00:00
|
|
|
* @param $title Mixed: message key (string) for page title, or a Message object
|
2011-08-25 10:13:30 +00:00
|
|
|
* @param $msg Mixed: message key (string) for page text, or a Message object
|
|
|
|
|
* @param $params Array: message parameters; ignored if $msg is a Message object
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2007-05-18 20:46:42 +00:00
|
|
|
public function showErrorPage( $title, $msg, $params = array() ) {
|
2012-08-06 21:07:24 +00:00
|
|
|
if( !$title instanceof Message ) {
|
|
|
|
|
$title = $this->msg( $title );
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-18 23:17:57 +00:00
|
|
|
$this->prepareErrorPage( $title );
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2013-01-26 18:32:03 +00:00
|
|
|
if ( $msg instanceof Message ) {
|
2012-10-06 15:28:09 +00:00
|
|
|
$this->addHTML( $msg->parseAsBlock() );
|
2011-08-25 10:13:30 +00:00
|
|
|
} else {
|
2011-08-25 10:56:46 +00:00
|
|
|
$this->addWikiMsgArray( $msg, $params );
|
2011-08-25 10:13:30 +00:00
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2008-04-16 13:46:16 +00:00
|
|
|
$this->returnToMain();
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2007-08-06 11:30:40 +00:00
|
|
|
/**
|
|
|
|
|
* Output a standard permission error page
|
|
|
|
|
*
|
2010-01-29 21:32:45 +00:00
|
|
|
* @param $errors Array: error message keys
|
|
|
|
|
* @param $action String: action that was denied or null if unknown
|
2007-08-06 11:30:40 +00:00
|
|
|
*/
|
2010-01-29 21:32:45 +00:00
|
|
|
public function showPermissionsErrorPage( $errors, $action = null ) {
|
2011-11-05 19:51:05 +00:00
|
|
|
// For some action (read, edit, create and upload), display a "login to do this action"
|
|
|
|
|
// error if all of the following conditions are met:
|
|
|
|
|
// 1. the user is not logged in
|
|
|
|
|
// 2. the only error is insufficient permissions (i.e. no block or something else)
|
|
|
|
|
// 3. the error can be avoided simply by logging in
|
|
|
|
|
if ( in_array( $action, array( 'read', 'edit', 'createpage', 'createtalk', 'upload' ) )
|
|
|
|
|
&& $this->getUser()->isAnon() && count( $errors ) == 1 && isset( $errors[0][0] )
|
|
|
|
|
&& ( $errors[0][0] == 'badaccess-groups' || $errors[0][0] == 'badaccess-group0' )
|
2012-10-04 16:17:46 +00:00
|
|
|
&& ( User::groupHasPermission( 'user', $action )
|
|
|
|
|
|| User::groupHasPermission( 'autoconfirmed', $action ) )
|
2011-11-05 19:51:05 +00:00
|
|
|
) {
|
|
|
|
|
$displayReturnto = null;
|
2011-11-28 23:18:55 +00:00
|
|
|
|
2011-11-29 21:04:20 +00:00
|
|
|
# Due to bug 32276, if a user does not have read permissions,
|
|
|
|
|
# $this->getTitle() will just give Special:Badtitle, which is
|
|
|
|
|
# not especially useful as a returnto parameter. Use the title
|
2011-11-28 23:18:55 +00:00
|
|
|
# from the request instead, if there was one.
|
|
|
|
|
$request = $this->getRequest();
|
|
|
|
|
$returnto = Title::newFromURL( $request->getVal( 'title', '' ) );
|
2011-11-05 19:51:05 +00:00
|
|
|
if ( $action == 'edit' ) {
|
|
|
|
|
$msg = 'whitelistedittext';
|
|
|
|
|
$displayReturnto = $returnto;
|
|
|
|
|
} elseif ( $action == 'createpage' || $action == 'createtalk' ) {
|
|
|
|
|
$msg = 'nocreatetext';
|
|
|
|
|
} elseif ( $action == 'upload' ) {
|
|
|
|
|
$msg = 'uploadnologintext';
|
|
|
|
|
} else { # Read
|
|
|
|
|
$msg = 'loginreqpagetext';
|
|
|
|
|
$displayReturnto = Title::newMainPage();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$query = array();
|
2011-11-28 23:18:55 +00:00
|
|
|
|
2011-11-05 19:51:05 +00:00
|
|
|
if ( $returnto ) {
|
|
|
|
|
$query['returnto'] = $returnto->getPrefixedText();
|
2011-11-28 23:18:55 +00:00
|
|
|
|
2011-11-05 19:51:05 +00:00
|
|
|
if ( !$request->wasPosted() ) {
|
|
|
|
|
$returntoquery = $request->getValues();
|
|
|
|
|
unset( $returntoquery['title'] );
|
|
|
|
|
unset( $returntoquery['returnto'] );
|
|
|
|
|
unset( $returntoquery['returntoquery'] );
|
2013-01-28 18:04:20 +00:00
|
|
|
$query['returntoquery'] = wfArrayToCgi( $returntoquery );
|
2011-11-05 19:51:05 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$loginLink = Linker::linkKnown(
|
|
|
|
|
SpecialPage::getTitleFor( 'Userlogin' ),
|
|
|
|
|
$this->msg( 'loginreqlink' )->escaped(),
|
|
|
|
|
array(),
|
|
|
|
|
$query
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$this->prepareErrorPage( $this->msg( 'loginreqtitle' ) );
|
|
|
|
|
$this->addHTML( $this->msg( $msg )->rawParams( $loginLink )->parse() );
|
2011-10-28 15:45:54 +00:00
|
|
|
|
2011-11-05 19:51:05 +00:00
|
|
|
# Don't return to a page the user can't read otherwise
|
|
|
|
|
# we'll end up in a pointless loop
|
2011-12-19 16:10:06 +00:00
|
|
|
if ( $displayReturnto && $displayReturnto->userCan( 'read', $this->getUser() ) ) {
|
2011-11-05 19:51:05 +00:00
|
|
|
$this->returnToMain( null, $displayReturnto );
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$this->prepareErrorPage( $this->msg( 'permissionserrors' ) );
|
|
|
|
|
$this->addWikiText( $this->formatPermissionsErrorMessage( $errors, $action ) );
|
|
|
|
|
}
|
2007-08-01 10:19:26 +00:00
|
|
|
}
|
|
|
|
|
|
2005-06-26 06:49:56 +00:00
|
|
|
/**
|
|
|
|
|
* Display an error page indicating that a given version of MediaWiki is
|
|
|
|
|
* required to use it
|
|
|
|
|
*
|
2010-01-29 21:32:45 +00:00
|
|
|
* @param $version Mixed: the version of MediaWiki needed to use the page
|
2005-06-26 06:49:56 +00:00
|
|
|
*/
|
2006-11-07 05:37:31 +00:00
|
|
|
public function versionRequired( $version ) {
|
2011-10-28 15:45:54 +00:00
|
|
|
$this->prepareErrorPage( $this->msg( 'versionrequired', $version ) );
|
2005-06-26 06:49:56 +00:00
|
|
|
|
2008-02-18 07:25:35 +00:00
|
|
|
$this->addWikiMsg( 'versionrequiredtext', $version );
|
2005-06-26 06:49:56 +00:00
|
|
|
$this->returnToMain();
|
|
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-06-19 06:25:53 +00:00
|
|
|
/**
|
|
|
|
|
* Display an error page noting that a given permission bit is required.
|
2011-04-12 22:59:17 +00:00
|
|
|
* @deprecated since 1.18, just throw the exception directly
|
2010-01-29 21:32:45 +00:00
|
|
|
* @param $permission String: key required
|
2012-10-07 23:35:26 +00:00
|
|
|
* @throws PermissionsError
|
2005-06-19 06:25:53 +00:00
|
|
|
*/
|
2006-11-07 05:37:31 +00:00
|
|
|
public function permissionRequired( $permission ) {
|
2011-04-12 22:59:17 +00:00
|
|
|
throw new PermissionsError( $permission );
|
2007-08-26 09:49:28 +00:00
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2006-05-02 15:37:06 +00:00
|
|
|
/**
|
|
|
|
|
* Produce the stock "please login to use the wiki" page
|
2011-11-05 19:51:05 +00:00
|
|
|
*
|
|
|
|
|
* @deprecated in 1.19; throw the exception directly
|
2006-05-02 15:37:06 +00:00
|
|
|
*/
|
2006-11-07 05:37:31 +00:00
|
|
|
public function loginToUse() {
|
2011-11-05 19:51:05 +00:00
|
|
|
throw new PermissionsError( 'read' );
|
2004-03-05 13:19:19 +00:00
|
|
|
}
|
|
|
|
|
|
2007-08-03 09:27:28 +00:00
|
|
|
/**
|
2010-01-29 21:32:45 +00:00
|
|
|
* Format a list of error messages
|
|
|
|
|
*
|
2011-02-02 11:00:09 +00:00
|
|
|
* @param $errors Array of arrays returned by Title::getUserPermissionsErrors
|
2010-01-29 21:32:45 +00:00
|
|
|
* @param $action String: action that was denied or null if unknown
|
|
|
|
|
* @return String: the wikitext error-messages, formatted into a list.
|
2007-08-03 09:27:28 +00:00
|
|
|
*/
|
2008-05-23 10:34:11 +00:00
|
|
|
public function formatPermissionsErrorMessage( $errors, $action = null ) {
|
2010-05-22 12:18:22 +00:00
|
|
|
if ( $action == null ) {
|
2011-10-23 08:13:52 +00:00
|
|
|
$text = $this->msg( 'permissionserrorstext', count( $errors ) )->plain() . "\n\n";
|
2008-05-23 10:34:11 +00:00
|
|
|
} else {
|
2011-10-23 08:13:52 +00:00
|
|
|
$action_desc = $this->msg( "action-$action" )->plain();
|
|
|
|
|
$text = $this->msg(
|
2010-05-22 12:18:22 +00:00
|
|
|
'permissionserrorstext-withaction',
|
|
|
|
|
count( $errors ),
|
|
|
|
|
$action_desc
|
2011-10-23 08:13:52 +00:00
|
|
|
)->plain() . "\n\n";
|
2008-05-23 10:34:11 +00:00
|
|
|
}
|
2008-01-02 01:16:44 +00:00
|
|
|
|
2010-05-22 12:18:22 +00:00
|
|
|
if ( count( $errors ) > 1 ) {
|
2007-08-16 07:05:38 +00:00
|
|
|
$text .= '<ul class="permissions-errors">' . "\n";
|
|
|
|
|
|
2010-05-22 12:18:22 +00:00
|
|
|
foreach( $errors as $error ) {
|
2007-08-16 07:05:38 +00:00
|
|
|
$text .= '<li>';
|
2011-10-23 08:13:52 +00:00
|
|
|
$text .= call_user_func_array( array( $this, 'msg' ), $error )->plain();
|
2007-08-16 07:05:38 +00:00
|
|
|
$text .= "</li>\n";
|
|
|
|
|
}
|
|
|
|
|
$text .= '</ul>';
|
|
|
|
|
} else {
|
2010-05-22 12:18:22 +00:00
|
|
|
$text .= "<div class=\"permissions-errors\">\n" .
|
2011-10-23 08:13:52 +00:00
|
|
|
call_user_func_array( array( $this, 'msg' ), reset( $errors ) )->plain() .
|
2010-05-22 12:18:22 +00:00
|
|
|
"\n</div>";
|
2007-08-03 09:27:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $text;
|
|
|
|
|
}
|
|
|
|
|
|
2006-11-07 05:37:31 +00:00
|
|
|
/**
|
2007-12-09 00:16:59 +00:00
|
|
|
* Display a page stating that the Wiki is in read-only mode,
|
|
|
|
|
* and optionally show the source of the page that the user
|
|
|
|
|
* was trying to edit. Should only be called (for this
|
|
|
|
|
* purpose) after wfReadOnly() has returned true.
|
|
|
|
|
*
|
|
|
|
|
* For historical reasons, this function is _also_ used to
|
|
|
|
|
* show the error message when a user tries to edit a page
|
|
|
|
|
* they are not allowed to edit. (Unless it's because they're
|
|
|
|
|
* blocked, then we show blockedPage() instead.) In this
|
|
|
|
|
* case, the second parameter should be set to true and a list
|
|
|
|
|
* of reasons supplied as the third parameter.
|
|
|
|
|
*
|
|
|
|
|
* @todo Needs to be split into multiple functions.
|
|
|
|
|
*
|
2010-01-29 21:32:45 +00:00
|
|
|
* @param $source String: source code to show (or null).
|
|
|
|
|
* @param $protected Boolean: is this a permissions error?
|
|
|
|
|
* @param $reasons Array: list of reasons for this error, as returned by Title::getUserPermissionsErrors().
|
|
|
|
|
* @param $action String: action that was denied or null if unknown
|
2012-10-07 23:35:26 +00:00
|
|
|
* @throws ReadOnlyError
|
2006-11-07 05:37:31 +00:00
|
|
|
*/
|
2008-05-23 10:34:11 +00:00
|
|
|
public function readOnlyPage( $source = null, $protected = false, $reasons = array(), $action = null ) {
|
2008-07-23 19:05:43 +00:00
|
|
|
$this->setRobotPolicy( 'noindex,nofollow' );
|
2004-01-17 09:49:43 +00:00
|
|
|
$this->setArticleRelated( false );
|
2008-01-24 01:59:35 +00:00
|
|
|
|
2007-12-09 00:16:59 +00:00
|
|
|
// If no reason is given, just supply a default "I can't let you do
|
|
|
|
|
// that, Dave" message. Should only occur if called by legacy code.
|
2010-05-22 12:18:22 +00:00
|
|
|
if ( $protected && empty( $reasons ) ) {
|
2007-12-09 00:16:59 +00:00
|
|
|
$reasons[] = array( 'badaccess-group0' );
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-22 12:18:22 +00:00
|
|
|
if ( !empty( $reasons ) ) {
|
2007-12-09 00:16:59 +00:00
|
|
|
// Permissions error
|
2008-01-02 02:49:31 +00:00
|
|
|
if( $source ) {
|
2011-11-08 18:02:26 +00:00
|
|
|
$this->setPageTitle( $this->msg( 'viewsource-title', $this->getTitle()->getPrefixedText() ) );
|
|
|
|
|
$this->addBacklinkSubtitle( $this->getTitle() );
|
2008-01-02 02:49:31 +00:00
|
|
|
} else {
|
2011-10-27 20:23:16 +00:00
|
|
|
$this->setPageTitle( $this->msg( 'badaccess' ) );
|
2008-01-02 02:49:31 +00:00
|
|
|
}
|
2011-09-11 21:07:17 +00:00
|
|
|
$this->addWikiText( $this->formatPermissionsErrorMessage( $reasons, $action ) );
|
2003-11-09 11:45:12 +00:00
|
|
|
} else {
|
2007-12-09 00:16:59 +00:00
|
|
|
// Wiki is read only
|
2011-04-13 14:30:55 +00:00
|
|
|
throw new ReadOnlyError;
|
2003-11-09 11:45:12 +00:00
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2007-12-09 00:16:59 +00:00
|
|
|
// Show source, if supplied
|
2004-04-30 07:18:38 +00:00
|
|
|
if( is_string( $source ) ) {
|
2008-02-18 07:25:35 +00:00
|
|
|
$this->addWikiMsg( 'viewsourcetext' );
|
2009-09-18 20:10:25 +00:00
|
|
|
|
2011-08-27 21:46:39 +00:00
|
|
|
$pageLang = $this->getTitle()->getPageLanguage();
|
2009-09-18 20:10:25 +00:00
|
|
|
$params = array(
|
2013-02-03 20:05:24 +00:00
|
|
|
'id' => 'wpTextbox1',
|
2009-09-18 20:10:25 +00:00
|
|
|
'name' => 'wpTextbox1',
|
2012-01-25 18:26:46 +00:00
|
|
|
'cols' => $this->getUser()->getOption( 'cols' ),
|
2011-04-03 03:59:47 +00:00
|
|
|
'rows' => $this->getUser()->getOption( 'rows' ),
|
2011-08-27 21:46:39 +00:00
|
|
|
'readonly' => 'readonly',
|
2011-12-11 18:46:18 +00:00
|
|
|
'lang' => $pageLang->getHtmlCode(),
|
2011-08-27 21:46:39 +00:00
|
|
|
'dir' => $pageLang->getDir(),
|
2009-09-18 20:10:25 +00:00
|
|
|
);
|
|
|
|
|
$this->addHTML( Html::element( 'textarea', $params, $source ) );
|
2007-12-09 00:16:59 +00:00
|
|
|
|
|
|
|
|
// Show templates used by this article
|
2011-12-29 15:12:00 +00:00
|
|
|
$templates = Linker::formatTemplates( $this->getTitle()->getTemplateLinksFrom() );
|
2008-08-08 12:23:17 +00:00
|
|
|
$this->addHTML( "<div class='templatesUsed'>
|
2011-06-22 18:24:58 +00:00
|
|
|
$templates
|
2008-08-08 12:23:17 +00:00
|
|
|
</div>
|
2011-08-24 13:03:03 +00:00
|
|
|
" );
|
2003-09-09 05:46:22 +00:00
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2008-01-02 02:49:31 +00:00
|
|
|
# If the title doesn't exist, it's fairly pointless to print a return
|
|
|
|
|
# link to it. After all, you just tried editing it and couldn't, so
|
|
|
|
|
# what's there to do there?
|
2009-04-09 02:22:36 +00:00
|
|
|
if( $this->getTitle()->exists() ) {
|
|
|
|
|
$this->returnToMain( null, $this->getTitle() );
|
2008-01-02 02:49:31 +00:00
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2011-04-07 16:04:08 +00:00
|
|
|
/**
|
|
|
|
|
* Turn off regular page output and return an error reponse
|
|
|
|
|
* for when rate limiting has triggered.
|
|
|
|
|
*/
|
|
|
|
|
public function rateLimited() {
|
2011-04-18 22:29:23 +00:00
|
|
|
throw new ThrottledError;
|
2011-04-07 16:04:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Show a warning about slave lag
|
|
|
|
|
*
|
|
|
|
|
* If the lag is higher than $wgSlaveLagCritical seconds,
|
|
|
|
|
* then the warning is a bit more obvious. If the lag is
|
|
|
|
|
* lower than $wgSlaveLagWarning, then no warning is shown.
|
|
|
|
|
*
|
|
|
|
|
* @param $lag Integer: slave lag
|
|
|
|
|
*/
|
|
|
|
|
public function showLagWarning( $lag ) {
|
|
|
|
|
global $wgSlaveLagWarning, $wgSlaveLagCritical;
|
|
|
|
|
if( $lag >= $wgSlaveLagWarning ) {
|
|
|
|
|
$message = $lag < $wgSlaveLagCritical
|
|
|
|
|
? 'lag-warn-normal'
|
|
|
|
|
: 'lag-warn-high';
|
|
|
|
|
$wrap = Html::rawElement( 'div', array( 'class' => "mw-{$message}" ), "\n$1\n" );
|
2011-11-21 16:13:21 +00:00
|
|
|
$this->wrapWikiMsg( "$wrap\n", array( $message, $this->getLanguage()->formatNum( $lag ) ) );
|
2011-04-07 16:04:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-11-07 05:37:31 +00:00
|
|
|
public function showFatalError( $message ) {
|
2011-10-28 15:45:54 +00:00
|
|
|
$this->prepareErrorPage( $this->msg( 'internalerror' ) );
|
|
|
|
|
|
|
|
|
|
$this->addHTML( $message );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2006-11-07 05:37:31 +00:00
|
|
|
public function showUnexpectedValueError( $name, $val ) {
|
2011-10-23 08:13:52 +00:00
|
|
|
$this->showFatalError( $this->msg( 'unexpected', $name, $val )->text() );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2006-11-07 05:37:31 +00:00
|
|
|
public function showFileCopyError( $old, $new ) {
|
2011-10-23 08:13:52 +00:00
|
|
|
$this->showFatalError( $this->msg( 'filecopyerror', $old, $new )->text() );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2006-11-07 05:37:31 +00:00
|
|
|
public function showFileRenameError( $old, $new ) {
|
2011-10-23 08:13:52 +00:00
|
|
|
$this->showFatalError( $this->msg( 'filerenameerror', $old, $new )->text() );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2006-11-07 05:37:31 +00:00
|
|
|
public function showFileDeleteError( $name ) {
|
2011-10-23 08:13:52 +00:00
|
|
|
$this->showFatalError( $this->msg( 'filedeleteerror', $name )->text() );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2006-11-07 05:37:31 +00:00
|
|
|
public function showFileNotFoundError( $name ) {
|
2011-10-23 08:13:52 +00:00
|
|
|
$this->showFatalError( $this->msg( 'filenotfound', $name )->text() );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2007-07-29 23:53:45 +00:00
|
|
|
* Add a "return to" link pointing to a specified title
|
|
|
|
|
*
|
2009-12-20 15:08:26 +00:00
|
|
|
* @param $title Title to link
|
2012-08-08 08:42:17 +00:00
|
|
|
* @param $query Array query string parameters
|
2010-03-13 19:07:25 +00:00
|
|
|
* @param $text String text of the link (input is not escaped)
|
2012-09-27 17:47:42 +00:00
|
|
|
* @param $options Options array to pass to Linker
|
2007-07-29 23:53:45 +00:00
|
|
|
*/
|
2012-09-27 17:47:42 +00:00
|
|
|
public function addReturnTo( $title, $query = array(), $text = null, $options = array() ) {
|
|
|
|
|
if( in_array( 'http', $options ) ) {
|
|
|
|
|
$proto = PROTO_HTTP;
|
|
|
|
|
} elseif( in_array( 'https', $options ) ) {
|
|
|
|
|
$proto = PROTO_HTTPS;
|
|
|
|
|
} else {
|
|
|
|
|
$proto = PROTO_RELATIVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->addLink( array( 'rel' => 'next', 'href' => $title->getFullURL( '', false, $proto ) ) );
|
2011-10-23 08:13:52 +00:00
|
|
|
$link = $this->msg( 'returnto' )->rawParams(
|
2012-09-27 17:47:42 +00:00
|
|
|
Linker::link( $title, $text, array(), $query, $options ) )->escaped();
|
2009-06-15 11:11:17 +00:00
|
|
|
$this->addHTML( "<p id=\"mw-returnto\">{$link}</p>\n" );
|
2007-07-29 23:53:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add a "return to" link pointing to a specified title,
|
|
|
|
|
* or the title indicated in the request, or else the main page
|
|
|
|
|
*
|
2012-02-09 19:29:36 +00:00
|
|
|
* @param $unused
|
2009-12-20 15:08:26 +00:00
|
|
|
* @param $returnto Title or String to return to
|
|
|
|
|
* @param $returntoquery String: query string for the return to link
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2009-07-14 21:25:33 +00:00
|
|
|
public function returnToMain( $unused = null, $returnto = null, $returntoquery = null ) {
|
|
|
|
|
if ( $returnto == null ) {
|
2011-04-03 12:46:36 +00:00
|
|
|
$returnto = $this->getRequest()->getText( 'returnto' );
|
2004-04-01 12:44:54 +00:00
|
|
|
}
|
2009-08-07 00:16:54 +00:00
|
|
|
|
2009-07-14 21:25:33 +00:00
|
|
|
if ( $returntoquery == null ) {
|
2011-04-03 12:46:36 +00:00
|
|
|
$returntoquery = $this->getRequest()->getText( 'returntoquery' );
|
2009-07-14 21:25:33 +00:00
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2010-01-06 19:59:42 +00:00
|
|
|
if ( $returnto === '' ) {
|
2006-12-03 00:22:14 +00:00
|
|
|
$returnto = Title::newMainPage();
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2006-06-21 16:28:04 +00:00
|
|
|
|
|
|
|
|
if ( is_object( $returnto ) ) {
|
|
|
|
|
$titleObj = $returnto;
|
|
|
|
|
} else {
|
|
|
|
|
$titleObj = Title::newFromText( $returnto );
|
|
|
|
|
}
|
2006-06-23 06:53:05 +00:00
|
|
|
if ( !is_object( $titleObj ) ) {
|
|
|
|
|
$titleObj = Title::newMainPage();
|
|
|
|
|
}
|
2006-06-21 16:28:04 +00:00
|
|
|
|
2012-08-08 08:42:17 +00:00
|
|
|
$this->addReturnTo( $titleObj, wfCgiToArray( $returntoquery ) );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2009-09-17 01:19:02 +00:00
|
|
|
* @param $sk Skin The given Skin
|
2010-05-22 12:18:22 +00:00
|
|
|
* @param $includeStyle Boolean: unused
|
2012-07-10 12:48:06 +00:00
|
|
|
* @return String: The doctype, opening "<html>", and head element.
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2009-09-22 16:52:40 +00:00
|
|
|
public function headElement( Skin $sk, $includeStyle = true ) {
|
2012-01-21 06:57:34 +00:00
|
|
|
global $wgContLang;
|
2012-01-08 01:49:06 +00:00
|
|
|
|
2011-11-21 16:13:21 +00:00
|
|
|
$userdir = $this->getLanguage()->getDir();
|
2011-07-19 20:36:09 +00:00
|
|
|
$sitedir = $wgContLang->getDir();
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2009-07-07 21:49:45 +00:00
|
|
|
if ( $sk->commonPrintStylesheet() ) {
|
2010-09-10 00:21:36 +00:00
|
|
|
$this->addModuleStyles( 'mediawiki.legacy.wikiprintable' );
|
2009-07-07 21:49:45 +00:00
|
|
|
}
|
2008-08-21 14:09:57 +00:00
|
|
|
|
2011-12-11 18:46:18 +00:00
|
|
|
$ret = Html::htmlHeader( array( 'lang' => $this->getLanguage()->getHtmlCode(), 'dir' => $userdir, 'class' => 'client-nojs' ) );
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2010-01-06 19:59:42 +00:00
|
|
|
if ( $this->getHTMLTitle() == '' ) {
|
2011-10-27 20:23:16 +00:00
|
|
|
$this->setHTMLTitle( $this->msg( 'pagetitle', $this->getPageTitle() ) );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2005-02-07 14:11:59 +00:00
|
|
|
|
2010-05-12 18:25:50 +00:00
|
|
|
$openHead = Html::openElement( 'head' );
|
|
|
|
|
if ( $openHead ) {
|
|
|
|
|
# Don't bother with the newline if $head == ''
|
|
|
|
|
$ret .= "$openHead\n";
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-08 13:45:14 +00:00
|
|
|
$ret .= Html::element( 'title', null, $this->getHTMLTitle() ) . "\n";
|
2010-03-21 05:12:15 +00:00
|
|
|
|
2009-07-07 21:49:45 +00:00
|
|
|
$ret .= implode( "\n", array(
|
2011-07-22 10:45:07 +00:00
|
|
|
$this->getHeadLinks( null, true ),
|
|
|
|
|
$this->buildCssLinks(),
|
|
|
|
|
$this->getHeadScripts(),
|
2011-01-06 16:58:29 +00:00
|
|
|
$this->getHeadItems()
|
2010-03-21 05:11:55 +00:00
|
|
|
) );
|
2004-04-09 04:53:52 +00:00
|
|
|
|
2010-03-21 05:12:02 +00:00
|
|
|
$closeHead = Html::closeElement( 'head' );
|
|
|
|
|
if ( $closeHead ) {
|
|
|
|
|
$ret .= "$closeHead\n";
|
|
|
|
|
}
|
2010-01-15 01:16:52 +00:00
|
|
|
|
|
|
|
|
$bodyAttrs = array();
|
|
|
|
|
|
2011-07-06 02:26:06 +00:00
|
|
|
# Classes for LTR/RTL directionality support
|
2011-11-22 15:58:28 +00:00
|
|
|
$bodyAttrs['class'] = "mediawiki $userdir sitedir-$sitedir";
|
2010-01-15 01:16:52 +00:00
|
|
|
|
2011-11-21 16:13:21 +00:00
|
|
|
if ( $this->getLanguage()->capitalizeAllNouns() ) {
|
2010-01-15 01:16:52 +00:00
|
|
|
# A <body> class is probably not the best way to do this . . .
|
|
|
|
|
$bodyAttrs['class'] .= ' capitalize-all-nouns';
|
|
|
|
|
}
|
2011-02-06 21:08:48 +00:00
|
|
|
$bodyAttrs['class'] .= ' ' . $sk->getPageClasses( $this->getTitle() );
|
|
|
|
|
$bodyAttrs['class'] .= ' skin-' . Sanitizer::escapeClass( $sk->getSkinName() );
|
2012-01-21 06:57:34 +00:00
|
|
|
$bodyAttrs['class'] .= ' action-' . Sanitizer::escapeClass( Action::getActionName( $this->getContext() ) );
|
2010-01-15 01:16:52 +00:00
|
|
|
|
2010-10-04 05:38:48 +00:00
|
|
|
$sk->addToBodyAttributes( $this, $bodyAttrs ); // Allow skins to add body attributes they need
|
|
|
|
|
wfRunHooks( 'OutputPageBodyAttributes', array( $this, $sk, &$bodyAttrs ) );
|
2010-10-03 14:12:41 +00:00
|
|
|
|
2010-01-15 01:16:52 +00:00
|
|
|
$ret .= Html::openElement( 'body', $bodyAttrs ) . "\n";
|
|
|
|
|
|
2004-04-09 04:53:52 +00:00
|
|
|
return $ret;
|
|
|
|
|
}
|
2010-10-02 13:45:35 +00:00
|
|
|
|
2011-04-02 18:38:42 +00:00
|
|
|
/**
|
|
|
|
|
* Add the default ResourceLoader modules to this object
|
|
|
|
|
*/
|
|
|
|
|
private function addDefaultModules() {
|
2012-01-29 19:40:11 +00:00
|
|
|
global $wgIncludeLegacyJavaScript, $wgPreloadJavaScriptMwUtil, $wgUseAjax,
|
Initial stab at responsive images for screen densities.
* adds $wgResponsiveImages setting, defaulting to true, to enable the feature
* adds 'srcset' attribute with 1.5x and 2x URLs to image links and image thumbs
* adds jquery.hidpi plugin to check pixel density and implement partial 'srcset' polyfill
** $.devicePixelRatio() returns window.devicePixelRatio, with compat fallback for IE 10
** $().hidpi() performs a 'srcset' polyfill for browsers with no native 'srcset' support
* adds mediawiki.hidpi RL script to trigger hidpi loads after main images load
Note that this is a work in progress. There will be places where this doesn't yet work which output their imgs differently. If moving from a low to high-DPI screen on a MacBook Pro Retina display, you won't see images load until you reload.
Confirmed basic images and thumbs in wikitext appear to work in Safari 6, Chrome 21, Firefox 18 nightly on MacBook Pro Retina display, and IE 10 in Windows 8 at 150% zoom, 200% zoom, and 140% and 180%-ratio Metro tablet sizes.
Internally this is still a bit of a hack; Linker::makeImageLink and Linker::makeThumbLink explicitly ask for 1.5x and 2x scaled versions and insert their URLs, if different, into the original thumbnail object which (in default handler) outputs the srcset. This means that a number of places that handle images differently won't see the higher-resolution versions, such as <gallery> and the large thumbnail on the File: description page.
At some point we may wish to redo some of how the MediaHandler stuff works so that requesting a single thumbnail automatically produces the extra sizes in all circumstances. We might also consider outputting a 'srcset' or multiple src sizes in 'imageinfo' API requests, which would make ApiForeignRepo/InstantCommons more efficient. (Currently it has to make three requests for each image to get the three sizes.)
Change-Id: Id80ebd07a1a9f401a2c2bfeb21aae987e5aa863b
2012-09-18 07:18:50 +00:00
|
|
|
$wgAjaxWatch, $wgResponsiveImages;
|
2011-04-02 18:38:42 +00:00
|
|
|
|
|
|
|
|
// Add base resources
|
2011-06-22 21:27:12 +00:00
|
|
|
$this->addModules( array(
|
|
|
|
|
'mediawiki.user',
|
|
|
|
|
'mediawiki.page.startup',
|
|
|
|
|
'mediawiki.page.ready',
|
|
|
|
|
) );
|
2013-01-26 18:32:03 +00:00
|
|
|
if ( $wgIncludeLegacyJavaScript ) {
|
2011-04-02 18:38:42 +00:00
|
|
|
$this->addModules( 'mediawiki.legacy.wikibits' );
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-29 19:40:11 +00:00
|
|
|
if ( $wgPreloadJavaScriptMwUtil ) {
|
|
|
|
|
$this->addModules( 'mediawiki.util' );
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-06 17:34:33 +00:00
|
|
|
MWDebug::addModules( $this );
|
|
|
|
|
|
2011-04-02 18:38:42 +00:00
|
|
|
// Add various resources if required
|
|
|
|
|
if ( $wgUseAjax ) {
|
|
|
|
|
$this->addModules( 'mediawiki.legacy.ajax' );
|
|
|
|
|
|
|
|
|
|
wfRunHooks( 'AjaxAddScript', array( &$this ) );
|
|
|
|
|
|
2011-04-03 03:59:47 +00:00
|
|
|
if( $wgAjaxWatch && $this->getUser()->isLoggedIn() ) {
|
2012-06-19 23:00:57 +00:00
|
|
|
$this->addModules( 'mediawiki.page.watch.ajax' );
|
2011-04-02 18:38:42 +00:00
|
|
|
}
|
|
|
|
|
|
(bug 40448) Replace legacy mwsuggest with mediawiki.searchSuggest
The module has been broken for a while now, but nobody noticed
because in plain core it is disabled by default, and in the
bundle we ship with Extension:Vector (and its SimpleSearch).
This commit removed the mediawiki.legacy.mwsuggest module (and
related components that become obsolete with its deletion) and
replaces it with the new mediawiki.searchSuggest module, which is
based on SimpleSearch from Extension:Vector (where it will be
removed soon).
The following and all references to it in core have been removed,
I also made sure that they weren't used in any of extensions/*.
Only matches in extensions/Settings and some file that dumped the startup module, and in extensions/Vector which are addressed in
I1d5bf81a8a0266c51c99d41eefacc0f4b3ae4b76.
Had to make a few updates to jquery.suggestions to make it work
in other skins. So far it was only used in Vector, but now that
it is used in mediawiki.searchSuggest, I noticed several issues
in other skins. Most importantly the fact that it assumed the
default offset was from the right corner, which isn't the case in
Monobook where the search bar is on the left (in the sidebar).
It now detects the appropiate origin corner automatically, and
also takes directionality of the page into account.
It also uses the correct font-size automatically. Previously it
used font-size: 0.8; but that only works in Vector. Every skin
seems to have its own way of making a sane font-size. In Monobook
the <body> has an extra small font-size which is then fixed in
div#globalWrapper, and in Vector it is extra large, which is then
fixed as well deeper in the document. Either way, the size on
<body> can't be used, and since this suggestions box is appended
to the <body> (it is a generic jQuery plugin without knowledge of
the document, and even if we could give it knowledge inside
the configuration, it'd have to be per-skin). So I removed the
Vector specific font-size and let it handle it automatically.
This was needed because it is now used in all skins.
Removed modules:
* mediawiki.legacy.mwsuggest:
> Replaced with mediawiki.searchSuggest.
Removed messages:
* search-mwsuggest-enabled
* search-mwsuggest-disabled
> No longer used.
Removed mw.config.values:
* wgMWSuggestTemplate
> Obsolete.
* wgSearchNamespaces
> Obsolete.
Removed server-side settings:
* $wgEnableMWSuggest
> Suggestions are now enabled by default and can be disabled
through the user preference `disablesuggest` still.
They can be disabled by default site-wide or hidden from
prefs through the standard mechanisms for that.
* $wgMWSuggestTemplate
> Obsolete.
Removed methods
* SearchEngine::getMWSuggestTemplate()
> Obsolete.
Filters:
$ ack mwsuggest -i -Q --ignore-dir=languages/messages
$ ack wgSearchNamespaces -Q
Message changes:
* vector-simplesearch-preference
> It was wrong, it didn't activate search suggestions, that
was handled by the Vector extension. This preference in
MediaWiki core controls whether the SimpleSearch bar HTML
and CSS will be used (e.g. the rectangle search box with
the magnifying class instead of the browser-default input
field with the plain submit buttons).
* searchsuggest-search
* searchsuggest-containing
These come from Extension:Vector message and should be imported
by translatewiki:
- vector-simplesearch-search
- vector-simplesearch-containing
Change-Id: Icd721011b40bb8d2c20aefa8b359a3e45413a07f
2012-09-23 01:06:53 +00:00
|
|
|
if ( !$this->getUser()->getOption( 'disablesuggest', false ) ) {
|
|
|
|
|
$this->addModules( 'mediawiki.searchSuggest' );
|
2011-04-02 18:38:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-13 22:36:03 +00:00
|
|
|
if ( $this->getUser()->getBoolOption( 'editsectiononrightclick' ) ) {
|
2011-04-02 18:38:42 +00:00
|
|
|
$this->addModules( 'mediawiki.action.view.rightClickEdit' );
|
|
|
|
|
}
|
2011-07-18 23:01:08 +00:00
|
|
|
|
2011-08-01 22:13:32 +00:00
|
|
|
# Crazy edit-on-double-click stuff
|
|
|
|
|
if ( $this->isArticle() && $this->getUser()->getOption( 'editondblclick' ) ) {
|
|
|
|
|
$this->addModules( 'mediawiki.action.view.dblClickEdit' );
|
|
|
|
|
}
|
Initial stab at responsive images for screen densities.
* adds $wgResponsiveImages setting, defaulting to true, to enable the feature
* adds 'srcset' attribute with 1.5x and 2x URLs to image links and image thumbs
* adds jquery.hidpi plugin to check pixel density and implement partial 'srcset' polyfill
** $.devicePixelRatio() returns window.devicePixelRatio, with compat fallback for IE 10
** $().hidpi() performs a 'srcset' polyfill for browsers with no native 'srcset' support
* adds mediawiki.hidpi RL script to trigger hidpi loads after main images load
Note that this is a work in progress. There will be places where this doesn't yet work which output their imgs differently. If moving from a low to high-DPI screen on a MacBook Pro Retina display, you won't see images load until you reload.
Confirmed basic images and thumbs in wikitext appear to work in Safari 6, Chrome 21, Firefox 18 nightly on MacBook Pro Retina display, and IE 10 in Windows 8 at 150% zoom, 200% zoom, and 140% and 180%-ratio Metro tablet sizes.
Internally this is still a bit of a hack; Linker::makeImageLink and Linker::makeThumbLink explicitly ask for 1.5x and 2x scaled versions and insert their URLs, if different, into the original thumbnail object which (in default handler) outputs the srcset. This means that a number of places that handle images differently won't see the higher-resolution versions, such as <gallery> and the large thumbnail on the File: description page.
At some point we may wish to redo some of how the MediaHandler stuff works so that requesting a single thumbnail automatically produces the extra sizes in all circumstances. We might also consider outputting a 'srcset' or multiple src sizes in 'imageinfo' API requests, which would make ApiForeignRepo/InstantCommons more efficient. (Currently it has to make three requests for each image to get the three sizes.)
Change-Id: Id80ebd07a1a9f401a2c2bfeb21aae987e5aa863b
2012-09-18 07:18:50 +00:00
|
|
|
|
|
|
|
|
// Support for high-density display images
|
|
|
|
|
if ( $wgResponsiveImages ) {
|
|
|
|
|
$this->addModules( 'mediawiki.hidpi' );
|
|
|
|
|
}
|
2011-04-02 18:38:42 +00:00
|
|
|
}
|
|
|
|
|
|
* Made Resources.php return a pure-data array instead of an ugly mix of data and code. This allows the class code to be lazy-loaded with the autoloader, for a performance advantage especially on non-APC installs. And using the convention where if the class is omitted, ResourceLoaderFileModule is assumed, the registration code becomes shorter and simpler.
* Modified ResourceLoader to lazy-initialise module objects, for a further performance advantage.
* Deleted ResourceLoader::getModules(), provided getModuleNames() instead. Although the startup module needs this functionality, it's slow to generate, so to avoid misuse, it's better to provide a foolproof fast interface and let the startup module do the slow thing itself.
* Modified ResourceLoader::register() to optionally accept an info array instead of an object.
* Added $wgResourceModules, allowing extensions to efficiently define their own resource loader modules. The trouble with hooks is that they contain code, and code is slow. We've been through all this before with i18n. Hooks are useful as a performance tool only if you call them very rarely.
* Moved ResourceLoader settings to their own section in DefaultSettings.php
* Added options to ResourceLoaderFileModule equivalent to the $localBasePath and $remoteBasePath parameters, to allow it to be instantiated via the new array style. Also added remoteExtPath, which allows modules to be registered before $wgExtensionAssetsPath is known.
* Added OutputPage::getResourceLoader(), mostly for debugging.
* The time saving at the moment is about 5ms per request with no extensions, which is significant already with 6 load.php requests for a cold cache page view. This is a much more scalable interface; the relative saving will grow as more extensions are added which use this interface, especially for non-APC installs.
Although the interface is backwards compatible, extension updates will follow in a subsequent commit.
2010-11-19 10:41:06 +00:00
|
|
|
/**
|
|
|
|
|
* Get a ResourceLoader object associated with this OutputPage
|
2011-02-21 17:12:33 +00:00
|
|
|
*
|
|
|
|
|
* @return ResourceLoader
|
* Made Resources.php return a pure-data array instead of an ugly mix of data and code. This allows the class code to be lazy-loaded with the autoloader, for a performance advantage especially on non-APC installs. And using the convention where if the class is omitted, ResourceLoaderFileModule is assumed, the registration code becomes shorter and simpler.
* Modified ResourceLoader to lazy-initialise module objects, for a further performance advantage.
* Deleted ResourceLoader::getModules(), provided getModuleNames() instead. Although the startup module needs this functionality, it's slow to generate, so to avoid misuse, it's better to provide a foolproof fast interface and let the startup module do the slow thing itself.
* Modified ResourceLoader::register() to optionally accept an info array instead of an object.
* Added $wgResourceModules, allowing extensions to efficiently define their own resource loader modules. The trouble with hooks is that they contain code, and code is slow. We've been through all this before with i18n. Hooks are useful as a performance tool only if you call them very rarely.
* Moved ResourceLoader settings to their own section in DefaultSettings.php
* Added options to ResourceLoaderFileModule equivalent to the $localBasePath and $remoteBasePath parameters, to allow it to be instantiated via the new array style. Also added remoteExtPath, which allows modules to be registered before $wgExtensionAssetsPath is known.
* Added OutputPage::getResourceLoader(), mostly for debugging.
* The time saving at the moment is about 5ms per request with no extensions, which is significant already with 6 load.php requests for a cold cache page view. This is a much more scalable interface; the relative saving will grow as more extensions are added which use this interface, especially for non-APC installs.
Although the interface is backwards compatible, extension updates will follow in a subsequent commit.
2010-11-19 10:41:06 +00:00
|
|
|
*/
|
|
|
|
|
public function getResourceLoader() {
|
|
|
|
|
if ( is_null( $this->mResourceLoader ) ) {
|
|
|
|
|
$this->mResourceLoader = new ResourceLoader();
|
|
|
|
|
}
|
|
|
|
|
return $this->mResourceLoader;
|
2011-04-23 19:28:35 +00:00
|
|
|
}
|
* Made Resources.php return a pure-data array instead of an ugly mix of data and code. This allows the class code to be lazy-loaded with the autoloader, for a performance advantage especially on non-APC installs. And using the convention where if the class is omitted, ResourceLoaderFileModule is assumed, the registration code becomes shorter and simpler.
* Modified ResourceLoader to lazy-initialise module objects, for a further performance advantage.
* Deleted ResourceLoader::getModules(), provided getModuleNames() instead. Although the startup module needs this functionality, it's slow to generate, so to avoid misuse, it's better to provide a foolproof fast interface and let the startup module do the slow thing itself.
* Modified ResourceLoader::register() to optionally accept an info array instead of an object.
* Added $wgResourceModules, allowing extensions to efficiently define their own resource loader modules. The trouble with hooks is that they contain code, and code is slow. We've been through all this before with i18n. Hooks are useful as a performance tool only if you call them very rarely.
* Moved ResourceLoader settings to their own section in DefaultSettings.php
* Added options to ResourceLoaderFileModule equivalent to the $localBasePath and $remoteBasePath parameters, to allow it to be instantiated via the new array style. Also added remoteExtPath, which allows modules to be registered before $wgExtensionAssetsPath is known.
* Added OutputPage::getResourceLoader(), mostly for debugging.
* The time saving at the moment is about 5ms per request with no extensions, which is significant already with 6 load.php requests for a cold cache page view. This is a much more scalable interface; the relative saving will grow as more extensions are added which use this interface, especially for non-APC installs.
Although the interface is backwards compatible, extension updates will follow in a subsequent commit.
2010-11-19 10:41:06 +00:00
|
|
|
|
2010-11-06 18:52:32 +00:00
|
|
|
/**
|
|
|
|
|
* TODO: Document
|
2011-08-13 17:27:35 +00:00
|
|
|
* @param $modules Array/string with the module name(s)
|
2011-02-04 16:39:17 +00:00
|
|
|
* @param $only String ResourceLoaderModule TYPE_ class constant
|
2010-11-06 18:52:32 +00:00
|
|
|
* @param $useESI boolean
|
2011-08-13 17:27:35 +00:00
|
|
|
* @param $extraQuery Array with extra query parameters to add to each request. array( param => value )
|
2012-07-10 12:48:06 +00:00
|
|
|
* @param $loadCall boolean If true, output an (asynchronous) mw.loader.load() call rather than a "<script src='...'>" tag
|
|
|
|
|
* @return string html "<script>" and "<style>" tags
|
2010-11-06 18:52:32 +00:00
|
|
|
*/
|
ResourceLoader: Add an experimental option to move the main module loading queue (the bottom queue) from the bottom of the <body> up into the <head> , while still being loaded asynchronously. This makes them load earlier, which should make the page load faster. This is the product of a long discussion on bug 27488
* Added a "blocking" state to mw.loader . When loading scripts while the document is not ready, the loader will use document.write() if blocking is true, and append to the <body> or the <head> if blocking is false. If the document is ready, the loader will always append to the <body>
* Enable blocking mode while loading the top queue, and disable it after. This ensures that modules in the top queue are still loaded in a blocking way as they were before
* If $wgResourceLoaderExperimentalAsyncLoading is true, the bottom queue is also loaded in the head, but with blocking mode disabled. Otherwise, it's loaded at the bottom of the <body> as before
* scripts-only and messages-only requests need special treatment:
** in the top queue, they can continue to use <script src="..."> tags because they are blocking
** if the bottom queue is at the bottom of the <body> (experimental async loading disabled), they can continue to use <script src="..."> tags as before
** if the bottom queue is in the <head> (experimental async loading enabled), they cannot use <script src="..."> tags, because those would block. Instead, call mw.loader.load() on the load.php URL
2012-01-05 23:32:41 +00:00
|
|
|
protected function makeResourceLoaderLink( $modules, $only, $useESI = false, array $extraQuery = array(), $loadCall = false ) {
|
2012-03-22 19:52:37 +00:00
|
|
|
global $wgResourceLoaderUseESI;
|
2011-01-13 22:08:13 +00:00
|
|
|
|
2012-06-29 00:52:09 +00:00
|
|
|
$modules = (array) $modules;
|
|
|
|
|
|
2010-11-06 18:52:32 +00:00
|
|
|
if ( !count( $modules ) ) {
|
|
|
|
|
return '';
|
|
|
|
|
}
|
2011-01-13 22:08:13 +00:00
|
|
|
|
2010-11-06 18:52:32 +00:00
|
|
|
if ( count( $modules ) > 1 ) {
|
|
|
|
|
// Remove duplicate module requests
|
2012-06-29 00:52:09 +00:00
|
|
|
$modules = array_unique( $modules );
|
2010-11-06 18:52:32 +00:00
|
|
|
// Sort module names so requests are more uniform
|
|
|
|
|
sort( $modules );
|
2011-01-13 22:08:13 +00:00
|
|
|
|
2010-11-06 18:52:32 +00:00
|
|
|
if ( ResourceLoader::inDebugMode() ) {
|
|
|
|
|
// Recursively call us for every item
|
|
|
|
|
$links = '';
|
|
|
|
|
foreach ( $modules as $name ) {
|
2011-07-22 10:45:07 +00:00
|
|
|
$links .= $this->makeResourceLoaderLink( $name, $only, $useESI );
|
2010-11-06 18:52:32 +00:00
|
|
|
}
|
|
|
|
|
return $links;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-01-13 22:08:13 +00:00
|
|
|
|
2010-09-20 21:54:15 +00:00
|
|
|
// Create keyed-by-group list of module objects from modules list
|
|
|
|
|
$groups = array();
|
* Made Resources.php return a pure-data array instead of an ugly mix of data and code. This allows the class code to be lazy-loaded with the autoloader, for a performance advantage especially on non-APC installs. And using the convention where if the class is omitted, ResourceLoaderFileModule is assumed, the registration code becomes shorter and simpler.
* Modified ResourceLoader to lazy-initialise module objects, for a further performance advantage.
* Deleted ResourceLoader::getModules(), provided getModuleNames() instead. Although the startup module needs this functionality, it's slow to generate, so to avoid misuse, it's better to provide a foolproof fast interface and let the startup module do the slow thing itself.
* Modified ResourceLoader::register() to optionally accept an info array instead of an object.
* Added $wgResourceModules, allowing extensions to efficiently define their own resource loader modules. The trouble with hooks is that they contain code, and code is slow. We've been through all this before with i18n. Hooks are useful as a performance tool only if you call them very rarely.
* Moved ResourceLoader settings to their own section in DefaultSettings.php
* Added options to ResourceLoaderFileModule equivalent to the $localBasePath and $remoteBasePath parameters, to allow it to be instantiated via the new array style. Also added remoteExtPath, which allows modules to be registered before $wgExtensionAssetsPath is known.
* Added OutputPage::getResourceLoader(), mostly for debugging.
* The time saving at the moment is about 5ms per request with no extensions, which is significant already with 6 load.php requests for a cold cache page view. This is a much more scalable interface; the relative saving will grow as more extensions are added which use this interface, especially for non-APC installs.
Although the interface is backwards compatible, extension updates will follow in a subsequent commit.
2010-11-19 10:41:06 +00:00
|
|
|
$resourceLoader = $this->getResourceLoader();
|
2012-06-29 00:52:09 +00:00
|
|
|
foreach ( $modules as $name ) {
|
* Made Resources.php return a pure-data array instead of an ugly mix of data and code. This allows the class code to be lazy-loaded with the autoloader, for a performance advantage especially on non-APC installs. And using the convention where if the class is omitted, ResourceLoaderFileModule is assumed, the registration code becomes shorter and simpler.
* Modified ResourceLoader to lazy-initialise module objects, for a further performance advantage.
* Deleted ResourceLoader::getModules(), provided getModuleNames() instead. Although the startup module needs this functionality, it's slow to generate, so to avoid misuse, it's better to provide a foolproof fast interface and let the startup module do the slow thing itself.
* Modified ResourceLoader::register() to optionally accept an info array instead of an object.
* Added $wgResourceModules, allowing extensions to efficiently define their own resource loader modules. The trouble with hooks is that they contain code, and code is slow. We've been through all this before with i18n. Hooks are useful as a performance tool only if you call them very rarely.
* Moved ResourceLoader settings to their own section in DefaultSettings.php
* Added options to ResourceLoaderFileModule equivalent to the $localBasePath and $remoteBasePath parameters, to allow it to be instantiated via the new array style. Also added remoteExtPath, which allows modules to be registered before $wgExtensionAssetsPath is known.
* Added OutputPage::getResourceLoader(), mostly for debugging.
* The time saving at the moment is about 5ms per request with no extensions, which is significant already with 6 load.php requests for a cold cache page view. This is a much more scalable interface; the relative saving will grow as more extensions are added which use this interface, especially for non-APC installs.
Although the interface is backwards compatible, extension updates will follow in a subsequent commit.
2010-11-19 10:41:06 +00:00
|
|
|
$module = $resourceLoader->getModule( $name );
|
2011-02-04 16:39:17 +00:00
|
|
|
# Check that we're allowed to include this module on this page
|
2011-11-23 13:27:50 +00:00
|
|
|
if ( !$module
|
|
|
|
|
|| ( $module->getOrigin() > $this->getAllowedModules( ResourceLoaderModule::TYPE_SCRIPTS )
|
2011-02-04 16:39:17 +00:00
|
|
|
&& $only == ResourceLoaderModule::TYPE_SCRIPTS )
|
|
|
|
|
|| ( $module->getOrigin() > $this->getAllowedModules( ResourceLoaderModule::TYPE_STYLES )
|
|
|
|
|
&& $only == ResourceLoaderModule::TYPE_STYLES )
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-20 21:54:15 +00:00
|
|
|
$group = $module->getGroup();
|
|
|
|
|
if ( !isset( $groups[$group] ) ) {
|
|
|
|
|
$groups[$group] = array();
|
|
|
|
|
}
|
|
|
|
|
$groups[$group][$name] = $module;
|
2010-09-11 03:26:15 +00:00
|
|
|
}
|
2011-02-04 16:39:17 +00:00
|
|
|
|
2010-09-11 03:26:15 +00:00
|
|
|
$links = '';
|
2012-06-29 00:52:09 +00:00
|
|
|
foreach ( $groups as $group => $grpModules ) {
|
2010-09-24 22:10:25 +00:00
|
|
|
// Special handling for user-specific groups
|
2011-09-13 20:36:24 +00:00
|
|
|
$user = null;
|
2011-04-03 03:59:47 +00:00
|
|
|
if ( ( $group === 'user' || $group === 'private' ) && $this->getUser()->isLoggedIn() ) {
|
2011-09-13 20:36:24 +00:00
|
|
|
$user = $this->getUser()->getName();
|
2010-09-20 21:54:15 +00:00
|
|
|
}
|
2011-04-23 19:28:35 +00:00
|
|
|
|
2011-02-19 17:07:05 +00:00
|
|
|
// Create a fake request based on the one we are about to make so modules return
|
|
|
|
|
// correct timestamp and emptiness data
|
2011-09-13 20:36:24 +00:00
|
|
|
$query = ResourceLoader::makeLoaderQuery(
|
|
|
|
|
array(), // modules; not determined yet
|
2011-11-21 16:13:21 +00:00
|
|
|
$this->getLanguage()->getCode(),
|
2011-09-13 20:36:24 +00:00
|
|
|
$this->getSkin()->getSkinName(),
|
|
|
|
|
$user,
|
|
|
|
|
null, // version; not determined yet
|
|
|
|
|
ResourceLoader::inDebugMode(),
|
|
|
|
|
$only === ResourceLoaderModule::TYPE_COMBINED ? null : $only,
|
|
|
|
|
$this->isPrintable(),
|
|
|
|
|
$this->getRequest()->getBool( 'handheld' ),
|
|
|
|
|
$extraQuery
|
|
|
|
|
);
|
2011-02-19 17:07:05 +00:00
|
|
|
$context = new ResourceLoaderContext( $resourceLoader, new FauxRequest( $query ) );
|
2012-04-25 18:24:03 +00:00
|
|
|
// Extract modules that know they're empty
|
|
|
|
|
$emptyModules = array ();
|
2012-06-29 00:52:09 +00:00
|
|
|
foreach ( $grpModules as $key => $module ) {
|
2011-02-19 17:07:05 +00:00
|
|
|
if ( $module->isKnownEmpty( $context ) ) {
|
2012-04-25 18:24:03 +00:00
|
|
|
$emptyModules[$key] = 'ready';
|
2012-06-29 00:52:09 +00:00
|
|
|
unset( $grpModules[$key] );
|
2011-02-19 17:07:05 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-04-25 18:24:03 +00:00
|
|
|
// Inline empty modules: since they're empty, just mark them as 'ready'
|
|
|
|
|
if ( count( $emptyModules ) > 0 && $only !== ResourceLoaderModule::TYPE_STYLES ) {
|
|
|
|
|
// If we're only getting the styles, we don't need to do anything for empty modules.
|
2012-05-11 08:34:29 +00:00
|
|
|
$links .= Html::inlineScript(
|
|
|
|
|
|
|
|
|
|
ResourceLoader::makeLoaderConditionalScript(
|
|
|
|
|
|
|
|
|
|
ResourceLoader::makeLoaderStateScript( $emptyModules )
|
|
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
2012-04-25 18:24:03 +00:00
|
|
|
) . "\n";
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-19 17:07:05 +00:00
|
|
|
// If there are no modules left, skip this group
|
2012-06-29 00:52:09 +00:00
|
|
|
if ( count( $grpModules ) === 0 ) {
|
2011-02-19 17:07:05 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
2011-04-23 19:28:35 +00:00
|
|
|
|
2012-03-22 19:52:37 +00:00
|
|
|
// Inline private modules. These can't be loaded through load.php for security
|
|
|
|
|
// reasons, see bug 34907. Note that these modules should be loaded from
|
|
|
|
|
// getHeadScripts() before the first loader call. Otherwise other modules can't
|
|
|
|
|
// properly use them as dependencies (bug 30914)
|
|
|
|
|
if ( $group === 'private' ) {
|
2011-02-04 16:39:17 +00:00
|
|
|
if ( $only == ResourceLoaderModule::TYPE_STYLES ) {
|
2010-09-24 22:10:25 +00:00
|
|
|
$links .= Html::inlineStyle(
|
2012-06-29 00:52:09 +00:00
|
|
|
$resourceLoader->makeModuleResponse( $context, $grpModules )
|
2010-09-24 22:10:25 +00:00
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
$links .= Html::inlineScript(
|
|
|
|
|
ResourceLoader::makeLoaderConditionalScript(
|
2012-06-29 00:52:09 +00:00
|
|
|
$resourceLoader->makeModuleResponse( $context, $grpModules )
|
2010-09-24 22:10:25 +00:00
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
2011-07-22 10:45:07 +00:00
|
|
|
$links .= "\n";
|
2010-09-24 22:10:25 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
2011-03-14 15:16:43 +00:00
|
|
|
// Special handling for the user group; because users might change their stuff
|
|
|
|
|
// on-wiki like user pages, or user preferences; we need to find the highest
|
2010-12-03 23:59:50 +00:00
|
|
|
// timestamp of these user-changable modules so we can ensure cache misses on change
|
2011-03-14 15:16:43 +00:00
|
|
|
// This should NOT be done for the site group (bug 27564) because anons get that too
|
|
|
|
|
// and we shouldn't be putting timestamps in Squid-cached HTML
|
2011-09-13 20:36:24 +00:00
|
|
|
$version = null;
|
2011-03-14 15:16:43 +00:00
|
|
|
if ( $group === 'user' ) {
|
2010-09-20 21:54:15 +00:00
|
|
|
// Get the maximum timestamp
|
2010-09-30 21:20:09 +00:00
|
|
|
$timestamp = 1;
|
2012-06-29 00:52:09 +00:00
|
|
|
foreach ( $grpModules as $module ) {
|
2010-09-24 22:10:25 +00:00
|
|
|
$timestamp = max( $timestamp, $module->getModifiedTime( $context ) );
|
2010-09-11 03:26:15 +00:00
|
|
|
}
|
2010-09-20 21:54:15 +00:00
|
|
|
// Add a version parameter so cache will break when things change
|
2011-09-13 20:36:24 +00:00
|
|
|
$version = wfTimestamp( TS_ISO_8601_BASIC, $timestamp );
|
2010-09-20 21:54:15 +00:00
|
|
|
}
|
2011-09-29 22:14:44 +00:00
|
|
|
|
2011-09-13 20:36:24 +00:00
|
|
|
$url = ResourceLoader::makeLoaderURL(
|
2012-06-29 00:52:09 +00:00
|
|
|
array_keys( $grpModules ),
|
2011-11-21 16:13:21 +00:00
|
|
|
$this->getLanguage()->getCode(),
|
2011-09-13 20:36:24 +00:00
|
|
|
$this->getSkin()->getSkinName(),
|
|
|
|
|
$user,
|
|
|
|
|
$version,
|
|
|
|
|
ResourceLoader::inDebugMode(),
|
|
|
|
|
$only === ResourceLoaderModule::TYPE_COMBINED ? null : $only,
|
|
|
|
|
$this->isPrintable(),
|
|
|
|
|
$this->getRequest()->getBool( 'handheld' ),
|
|
|
|
|
$extraQuery
|
|
|
|
|
);
|
2010-09-24 20:01:52 +00:00
|
|
|
if ( $useESI && $wgResourceLoaderUseESI ) {
|
|
|
|
|
$esi = Xml::element( 'esi:include', array( 'src' => $url ) );
|
2011-02-04 16:39:17 +00:00
|
|
|
if ( $only == ResourceLoaderModule::TYPE_STYLES ) {
|
2011-03-05 16:01:25 +00:00
|
|
|
$link = Html::inlineStyle( $esi );
|
2010-09-24 20:01:52 +00:00
|
|
|
} else {
|
2011-03-05 16:01:25 +00:00
|
|
|
$link = Html::inlineScript( $esi );
|
2010-09-24 20:01:52 +00:00
|
|
|
}
|
2010-09-20 21:54:15 +00:00
|
|
|
} else {
|
2010-09-24 20:01:52 +00:00
|
|
|
// Automatically select style/script elements
|
2011-02-04 16:39:17 +00:00
|
|
|
if ( $only === ResourceLoaderModule::TYPE_STYLES ) {
|
2011-05-26 09:49:45 +00:00
|
|
|
$link = Html::linkedStyle( $url );
|
2012-04-25 18:24:03 +00:00
|
|
|
} else if ( $loadCall ) {
|
ResourceLoader: Add an experimental option to move the main module loading queue (the bottom queue) from the bottom of the <body> up into the <head> , while still being loaded asynchronously. This makes them load earlier, which should make the page load faster. This is the product of a long discussion on bug 27488
* Added a "blocking" state to mw.loader . When loading scripts while the document is not ready, the loader will use document.write() if blocking is true, and append to the <body> or the <head> if blocking is false. If the document is ready, the loader will always append to the <body>
* Enable blocking mode while loading the top queue, and disable it after. This ensures that modules in the top queue are still loaded in a blocking way as they were before
* If $wgResourceLoaderExperimentalAsyncLoading is true, the bottom queue is also loaded in the head, but with blocking mode disabled. Otherwise, it's loaded at the bottom of the <body> as before
* scripts-only and messages-only requests need special treatment:
** in the top queue, they can continue to use <script src="..."> tags because they are blocking
** if the bottom queue is at the bottom of the <body> (experimental async loading disabled), they can continue to use <script src="..."> tags as before
** if the bottom queue is in the <head> (experimental async loading enabled), they cannot use <script src="..."> tags, because those would block. Instead, call mw.loader.load() on the load.php URL
2012-01-05 23:32:41 +00:00
|
|
|
$link = Html::inlineScript(
|
|
|
|
|
ResourceLoader::makeLoaderConditionalScript(
|
2012-02-15 23:38:40 +00:00
|
|
|
Xml::encodeJsCall( 'mw.loader.load', array( $url, 'text/javascript', true ) )
|
ResourceLoader: Add an experimental option to move the main module loading queue (the bottom queue) from the bottom of the <body> up into the <head> , while still being loaded asynchronously. This makes them load earlier, which should make the page load faster. This is the product of a long discussion on bug 27488
* Added a "blocking" state to mw.loader . When loading scripts while the document is not ready, the loader will use document.write() if blocking is true, and append to the <body> or the <head> if blocking is false. If the document is ready, the loader will always append to the <body>
* Enable blocking mode while loading the top queue, and disable it after. This ensures that modules in the top queue are still loaded in a blocking way as they were before
* If $wgResourceLoaderExperimentalAsyncLoading is true, the bottom queue is also loaded in the head, but with blocking mode disabled. Otherwise, it's loaded at the bottom of the <body> as before
* scripts-only and messages-only requests need special treatment:
** in the top queue, they can continue to use <script src="..."> tags because they are blocking
** if the bottom queue is at the bottom of the <body> (experimental async loading disabled), they can continue to use <script src="..."> tags as before
** if the bottom queue is in the <head> (experimental async loading enabled), they cannot use <script src="..."> tags, because those would block. Instead, call mw.loader.load() on the load.php URL
2012-01-05 23:32:41 +00:00
|
|
|
)
|
|
|
|
|
);
|
2010-09-24 20:01:52 +00:00
|
|
|
} else {
|
2011-05-26 09:49:45 +00:00
|
|
|
$link = Html::linkedScript( $url );
|
2010-09-24 20:01:52 +00:00
|
|
|
}
|
2010-09-11 03:26:15 +00:00
|
|
|
}
|
2011-03-05 16:01:25 +00:00
|
|
|
|
2013-01-26 18:32:03 +00:00
|
|
|
if( $group == 'noscript' ) {
|
2011-03-05 16:01:25 +00:00
|
|
|
$links .= Html::rawElement( 'noscript', array(), $link ) . "\n";
|
|
|
|
|
} else {
|
|
|
|
|
$links .= $link . "\n";
|
|
|
|
|
}
|
2010-09-04 04:00:09 +00:00
|
|
|
}
|
2010-09-11 03:26:15 +00:00
|
|
|
return $links;
|
2010-09-04 04:00:09 +00:00
|
|
|
}
|
2010-10-02 13:45:35 +00:00
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
2012-07-10 12:48:06 +00:00
|
|
|
* JS stuff to put in the "<head>". This is the startup module, config
|
2011-04-07 12:07:25 +00:00
|
|
|
* vars and modules marked with position 'top'
|
2009-09-22 01:00:06 +00:00
|
|
|
*
|
2010-01-29 21:32:45 +00:00
|
|
|
* @return String: HTML fragment
|
|
|
|
|
*/
|
2011-07-22 10:45:07 +00:00
|
|
|
function getHeadScripts() {
|
ResourceLoader: Add an experimental option to move the main module loading queue (the bottom queue) from the bottom of the <body> up into the <head> , while still being loaded asynchronously. This makes them load earlier, which should make the page load faster. This is the product of a long discussion on bug 27488
* Added a "blocking" state to mw.loader . When loading scripts while the document is not ready, the loader will use document.write() if blocking is true, and append to the <body> or the <head> if blocking is false. If the document is ready, the loader will always append to the <body>
* Enable blocking mode while loading the top queue, and disable it after. This ensures that modules in the top queue are still loaded in a blocking way as they were before
* If $wgResourceLoaderExperimentalAsyncLoading is true, the bottom queue is also loaded in the head, but with blocking mode disabled. Otherwise, it's loaded at the bottom of the <body> as before
* scripts-only and messages-only requests need special treatment:
** in the top queue, they can continue to use <script src="..."> tags because they are blocking
** if the bottom queue is at the bottom of the <body> (experimental async loading disabled), they can continue to use <script src="..."> tags as before
** if the bottom queue is in the <head> (experimental async loading enabled), they cannot use <script src="..."> tags, because those would block. Instead, call mw.loader.load() on the load.php URL
2012-01-05 23:32:41 +00:00
|
|
|
global $wgResourceLoaderExperimentalAsyncLoading;
|
2012-04-25 18:24:03 +00:00
|
|
|
|
2010-09-24 20:01:52 +00:00
|
|
|
// Startup - this will immediately load jquery and mediawiki modules
|
2011-07-22 10:45:07 +00:00
|
|
|
$scripts = $this->makeResourceLoaderLink( 'startup', ResourceLoaderModule::TYPE_SCRIPTS, true );
|
2011-04-23 19:28:35 +00:00
|
|
|
|
2011-04-07 12:07:25 +00:00
|
|
|
// Load config before anything else
|
2011-02-16 18:25:44 +00:00
|
|
|
$scripts .= Html::inlineScript(
|
|
|
|
|
ResourceLoader::makeLoaderConditionalScript(
|
2011-04-07 12:07:25 +00:00
|
|
|
ResourceLoader::makeConfigSetScript( $this->getJSVars() )
|
2011-02-16 18:25:44 +00:00
|
|
|
)
|
|
|
|
|
);
|
2011-04-23 19:28:35 +00:00
|
|
|
|
2011-12-28 22:20:29 +00:00
|
|
|
// Load embeddable private modules before any loader links
|
2012-02-09 11:04:24 +00:00
|
|
|
// This needs to be TYPE_COMBINED so these modules are properly wrapped
|
|
|
|
|
// in mw.loader.implement() calls and deferred until mw.user is available
|
2011-12-28 22:20:29 +00:00
|
|
|
$embedScripts = array( 'user.options', 'user.tokens' );
|
2012-02-09 10:59:52 +00:00
|
|
|
$scripts .= $this->makeResourceLoaderLink( $embedScripts, ResourceLoaderModule::TYPE_COMBINED );
|
2011-12-28 22:20:29 +00:00
|
|
|
|
2011-04-07 12:07:25 +00:00
|
|
|
// Script and Messages "only" requests marked for top inclusion
|
|
|
|
|
// Messages should go first
|
2011-07-22 10:45:07 +00:00
|
|
|
$scripts .= $this->makeResourceLoaderLink( $this->getModuleMessages( true, 'top' ), ResourceLoaderModule::TYPE_MESSAGES );
|
|
|
|
|
$scripts .= $this->makeResourceLoaderLink( $this->getModuleScripts( true, 'top' ), ResourceLoaderModule::TYPE_SCRIPTS );
|
2011-04-07 12:07:25 +00:00
|
|
|
|
|
|
|
|
// Modules requests - let the client calculate dependencies and batch requests as it likes
|
|
|
|
|
// Only load modules that have marked themselves for loading at the top
|
|
|
|
|
$modules = $this->getModules( true, 'top' );
|
|
|
|
|
if ( $modules ) {
|
|
|
|
|
$scripts .= Html::inlineScript(
|
|
|
|
|
ResourceLoader::makeLoaderConditionalScript(
|
2012-02-15 23:38:40 +00:00
|
|
|
Xml::encodeJsCall( 'mw.loader.load', array( $modules ) )
|
2011-04-07 12:07:25 +00:00
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
2012-04-25 18:24:03 +00:00
|
|
|
|
ResourceLoader: Add an experimental option to move the main module loading queue (the bottom queue) from the bottom of the <body> up into the <head> , while still being loaded asynchronously. This makes them load earlier, which should make the page load faster. This is the product of a long discussion on bug 27488
* Added a "blocking" state to mw.loader . When loading scripts while the document is not ready, the loader will use document.write() if blocking is true, and append to the <body> or the <head> if blocking is false. If the document is ready, the loader will always append to the <body>
* Enable blocking mode while loading the top queue, and disable it after. This ensures that modules in the top queue are still loaded in a blocking way as they were before
* If $wgResourceLoaderExperimentalAsyncLoading is true, the bottom queue is also loaded in the head, but with blocking mode disabled. Otherwise, it's loaded at the bottom of the <body> as before
* scripts-only and messages-only requests need special treatment:
** in the top queue, they can continue to use <script src="..."> tags because they are blocking
** if the bottom queue is at the bottom of the <body> (experimental async loading disabled), they can continue to use <script src="..."> tags as before
** if the bottom queue is in the <head> (experimental async loading enabled), they cannot use <script src="..."> tags, because those would block. Instead, call mw.loader.load() on the load.php URL
2012-01-05 23:32:41 +00:00
|
|
|
if ( $wgResourceLoaderExperimentalAsyncLoading ) {
|
|
|
|
|
$scripts .= $this->getScriptsForBottomQueue( true );
|
|
|
|
|
}
|
2011-04-07 12:07:25 +00:00
|
|
|
|
|
|
|
|
return $scripts;
|
|
|
|
|
}
|
2011-04-23 19:28:35 +00:00
|
|
|
|
2011-04-07 12:07:25 +00:00
|
|
|
/**
|
2012-07-10 12:48:06 +00:00
|
|
|
* JS stuff to put at the 'bottom', which can either be the bottom of the "<body>"
|
|
|
|
|
* or the bottom of the "<head>" depending on $wgResourceLoaderExperimentalAsyncLoading:
|
ResourceLoader: Add an experimental option to move the main module loading queue (the bottom queue) from the bottom of the <body> up into the <head> , while still being loaded asynchronously. This makes them load earlier, which should make the page load faster. This is the product of a long discussion on bug 27488
* Added a "blocking" state to mw.loader . When loading scripts while the document is not ready, the loader will use document.write() if blocking is true, and append to the <body> or the <head> if blocking is false. If the document is ready, the loader will always append to the <body>
* Enable blocking mode while loading the top queue, and disable it after. This ensures that modules in the top queue are still loaded in a blocking way as they were before
* If $wgResourceLoaderExperimentalAsyncLoading is true, the bottom queue is also loaded in the head, but with blocking mode disabled. Otherwise, it's loaded at the bottom of the <body> as before
* scripts-only and messages-only requests need special treatment:
** in the top queue, they can continue to use <script src="..."> tags because they are blocking
** if the bottom queue is at the bottom of the <body> (experimental async loading disabled), they can continue to use <script src="..."> tags as before
** if the bottom queue is in the <head> (experimental async loading enabled), they cannot use <script src="..."> tags, because those would block. Instead, call mw.loader.load() on the load.php URL
2012-01-05 23:32:41 +00:00
|
|
|
* modules marked with position 'bottom', legacy scripts ($this->mScripts),
|
|
|
|
|
* user preferences, site JS and user JS
|
2011-05-21 19:07:24 +00:00
|
|
|
*
|
2012-07-10 12:48:06 +00:00
|
|
|
* @param $inHead boolean If true, this HTML goes into the "<head>", if false it goes into the "<body>"
|
2011-05-21 19:07:24 +00:00
|
|
|
* @return string
|
2011-04-07 12:07:25 +00:00
|
|
|
*/
|
ResourceLoader: Add an experimental option to move the main module loading queue (the bottom queue) from the bottom of the <body> up into the <head> , while still being loaded asynchronously. This makes them load earlier, which should make the page load faster. This is the product of a long discussion on bug 27488
* Added a "blocking" state to mw.loader . When loading scripts while the document is not ready, the loader will use document.write() if blocking is true, and append to the <body> or the <head> if blocking is false. If the document is ready, the loader will always append to the <body>
* Enable blocking mode while loading the top queue, and disable it after. This ensures that modules in the top queue are still loaded in a blocking way as they were before
* If $wgResourceLoaderExperimentalAsyncLoading is true, the bottom queue is also loaded in the head, but with blocking mode disabled. Otherwise, it's loaded at the bottom of the <body> as before
* scripts-only and messages-only requests need special treatment:
** in the top queue, they can continue to use <script src="..."> tags because they are blocking
** if the bottom queue is at the bottom of the <body> (experimental async loading disabled), they can continue to use <script src="..."> tags as before
** if the bottom queue is in the <head> (experimental async loading enabled), they cannot use <script src="..."> tags, because those would block. Instead, call mw.loader.load() on the load.php URL
2012-01-05 23:32:41 +00:00
|
|
|
function getScriptsForBottomQueue( $inHead ) {
|
2011-04-07 12:07:25 +00:00
|
|
|
global $wgUseSiteJs, $wgAllowUserJs;
|
2011-04-23 19:28:35 +00:00
|
|
|
|
2011-04-07 12:07:25 +00:00
|
|
|
// Script and Messages "only" requests marked for bottom inclusion
|
ResourceLoader: Add an experimental option to move the main module loading queue (the bottom queue) from the bottom of the <body> up into the <head> , while still being loaded asynchronously. This makes them load earlier, which should make the page load faster. This is the product of a long discussion on bug 27488
* Added a "blocking" state to mw.loader . When loading scripts while the document is not ready, the loader will use document.write() if blocking is true, and append to the <body> or the <head> if blocking is false. If the document is ready, the loader will always append to the <body>
* Enable blocking mode while loading the top queue, and disable it after. This ensures that modules in the top queue are still loaded in a blocking way as they were before
* If $wgResourceLoaderExperimentalAsyncLoading is true, the bottom queue is also loaded in the head, but with blocking mode disabled. Otherwise, it's loaded at the bottom of the <body> as before
* scripts-only and messages-only requests need special treatment:
** in the top queue, they can continue to use <script src="..."> tags because they are blocking
** if the bottom queue is at the bottom of the <body> (experimental async loading disabled), they can continue to use <script src="..."> tags as before
** if the bottom queue is in the <head> (experimental async loading enabled), they cannot use <script src="..."> tags, because those would block. Instead, call mw.loader.load() on the load.php URL
2012-01-05 23:32:41 +00:00
|
|
|
// If we're in the <head>, use load() calls rather than <script src="..."> tags
|
2011-04-07 12:07:25 +00:00
|
|
|
// Messages should go first
|
ResourceLoader: Add an experimental option to move the main module loading queue (the bottom queue) from the bottom of the <body> up into the <head> , while still being loaded asynchronously. This makes them load earlier, which should make the page load faster. This is the product of a long discussion on bug 27488
* Added a "blocking" state to mw.loader . When loading scripts while the document is not ready, the loader will use document.write() if blocking is true, and append to the <body> or the <head> if blocking is false. If the document is ready, the loader will always append to the <body>
* Enable blocking mode while loading the top queue, and disable it after. This ensures that modules in the top queue are still loaded in a blocking way as they were before
* If $wgResourceLoaderExperimentalAsyncLoading is true, the bottom queue is also loaded in the head, but with blocking mode disabled. Otherwise, it's loaded at the bottom of the <body> as before
* scripts-only and messages-only requests need special treatment:
** in the top queue, they can continue to use <script src="..."> tags because they are blocking
** if the bottom queue is at the bottom of the <body> (experimental async loading disabled), they can continue to use <script src="..."> tags as before
** if the bottom queue is in the <head> (experimental async loading enabled), they cannot use <script src="..."> tags, because those would block. Instead, call mw.loader.load() on the load.php URL
2012-01-05 23:32:41 +00:00
|
|
|
$scripts = $this->makeResourceLoaderLink( $this->getModuleMessages( true, 'bottom' ),
|
|
|
|
|
ResourceLoaderModule::TYPE_MESSAGES, /* $useESI = */ false, /* $extraQuery = */ array(),
|
|
|
|
|
/* $loadCall = */ $inHead
|
|
|
|
|
);
|
|
|
|
|
$scripts .= $this->makeResourceLoaderLink( $this->getModuleScripts( true, 'bottom' ),
|
|
|
|
|
ResourceLoaderModule::TYPE_SCRIPTS, /* $useESI = */ false, /* $extraQuery = */ array(),
|
|
|
|
|
/* $loadCall = */ $inHead
|
|
|
|
|
);
|
2010-10-02 13:45:35 +00:00
|
|
|
|
2011-04-07 12:07:25 +00:00
|
|
|
// Modules requests - let the client calculate dependencies and batch requests as it likes
|
2011-04-07 13:14:33 +00:00
|
|
|
// Only load modules that have marked themselves for loading at the bottom
|
2011-04-07 12:07:25 +00:00
|
|
|
$modules = $this->getModules( true, 'bottom' );
|
|
|
|
|
if ( $modules ) {
|
|
|
|
|
$scripts .= Html::inlineScript(
|
|
|
|
|
ResourceLoader::makeLoaderConditionalScript(
|
2012-02-15 23:38:40 +00:00
|
|
|
Xml::encodeJsCall( 'mw.loader.load', array( $modules, null, true ) )
|
2011-04-07 12:07:25 +00:00
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
2011-04-23 19:28:35 +00:00
|
|
|
|
2010-12-03 23:59:50 +00:00
|
|
|
// Legacy Scripts
|
|
|
|
|
$scripts .= "\n" . $this->mScripts;
|
|
|
|
|
|
2012-04-25 18:24:03 +00:00
|
|
|
$defaultModules = array();
|
2011-02-16 19:54:02 +00:00
|
|
|
|
2010-12-03 23:59:50 +00:00
|
|
|
// Add site JS if enabled
|
|
|
|
|
if ( $wgUseSiteJs ) {
|
ResourceLoader: Add an experimental option to move the main module loading queue (the bottom queue) from the bottom of the <body> up into the <head> , while still being loaded asynchronously. This makes them load earlier, which should make the page load faster. This is the product of a long discussion on bug 27488
* Added a "blocking" state to mw.loader . When loading scripts while the document is not ready, the loader will use document.write() if blocking is true, and append to the <body> or the <head> if blocking is false. If the document is ready, the loader will always append to the <body>
* Enable blocking mode while loading the top queue, and disable it after. This ensures that modules in the top queue are still loaded in a blocking way as they were before
* If $wgResourceLoaderExperimentalAsyncLoading is true, the bottom queue is also loaded in the head, but with blocking mode disabled. Otherwise, it's loaded at the bottom of the <body> as before
* scripts-only and messages-only requests need special treatment:
** in the top queue, they can continue to use <script src="..."> tags because they are blocking
** if the bottom queue is at the bottom of the <body> (experimental async loading disabled), they can continue to use <script src="..."> tags as before
** if the bottom queue is in the <head> (experimental async loading enabled), they cannot use <script src="..."> tags, because those would block. Instead, call mw.loader.load() on the load.php URL
2012-01-05 23:32:41 +00:00
|
|
|
$scripts .= $this->makeResourceLoaderLink( 'site', ResourceLoaderModule::TYPE_SCRIPTS,
|
|
|
|
|
/* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
|
|
|
|
|
);
|
2012-04-25 18:24:03 +00:00
|
|
|
$defaultModules['site'] = 'loading';
|
|
|
|
|
} else {
|
|
|
|
|
// The wiki is configured to not allow a site module.
|
|
|
|
|
$defaultModules['site'] = 'missing';
|
2010-12-03 23:59:50 +00:00
|
|
|
}
|
|
|
|
|
|
2011-02-16 19:54:02 +00:00
|
|
|
// Add user JS if enabled
|
2012-04-25 18:24:03 +00:00
|
|
|
if ( $wgAllowUserJs ) {
|
|
|
|
|
if ( $this->getUser()->isLoggedIn() ) {
|
|
|
|
|
if( $this->getTitle() && $this->getTitle()->isJsSubpage() && $this->userCanPreview() ) {
|
|
|
|
|
# XXX: additional security check/prompt?
|
|
|
|
|
// We're on a preview of a JS subpage
|
|
|
|
|
// Exclude this page from the user module in case it's in there (bug 26283)
|
|
|
|
|
$scripts .= $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_SCRIPTS, false,
|
|
|
|
|
array( 'excludepage' => $this->getTitle()->getPrefixedDBkey() ), $inHead
|
|
|
|
|
);
|
|
|
|
|
// Load the previewed JS
|
|
|
|
|
$scripts .= Html::inlineScript( "\n" . $this->getRequest()->getText( 'wpTextbox1' ) . "\n" ) . "\n";
|
|
|
|
|
// FIXME: If the user is previewing, say, ./vector.js, his ./common.js will be loaded
|
|
|
|
|
// asynchronously and may arrive *after* the inline script here. So the previewed code
|
|
|
|
|
// may execute before ./common.js runs. Normally, ./common.js runs before ./vector.js...
|
|
|
|
|
} else {
|
|
|
|
|
// Include the user module normally, i.e., raw to avoid it being wrapped in a closure.
|
|
|
|
|
$scripts .= $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_SCRIPTS,
|
|
|
|
|
/* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
$defaultModules['user'] = 'loading';
|
2009-09-22 16:52:40 +00:00
|
|
|
} else {
|
2012-04-25 18:24:03 +00:00
|
|
|
// Non-logged-in users have no user module. Treat it as empty and 'ready' to avoid
|
|
|
|
|
// blocking default gadgets that might depend on it. Although arguably default-enabled
|
|
|
|
|
// gadgets should not depend on the user module, it's harmless and less error-prone to
|
|
|
|
|
// handle this case.
|
|
|
|
|
$defaultModules['user'] = 'ready';
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2012-04-26 20:53:11 +00:00
|
|
|
// User JS disabled
|
2012-04-25 18:24:03 +00:00
|
|
|
$defaultModules['user'] = 'missing';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Group JS is only enabled if site JS is enabled.
|
|
|
|
|
if ( $wgUseSiteJs ) {
|
|
|
|
|
if ( $this->getUser()->isLoggedIn() ) {
|
|
|
|
|
$scripts .= $this->makeResourceLoaderLink( 'user.groups', ResourceLoaderModule::TYPE_COMBINED,
|
ResourceLoader: Add an experimental option to move the main module loading queue (the bottom queue) from the bottom of the <body> up into the <head> , while still being loaded asynchronously. This makes them load earlier, which should make the page load faster. This is the product of a long discussion on bug 27488
* Added a "blocking" state to mw.loader . When loading scripts while the document is not ready, the loader will use document.write() if blocking is true, and append to the <body> or the <head> if blocking is false. If the document is ready, the loader will always append to the <body>
* Enable blocking mode while loading the top queue, and disable it after. This ensures that modules in the top queue are still loaded in a blocking way as they were before
* If $wgResourceLoaderExperimentalAsyncLoading is true, the bottom queue is also loaded in the head, but with blocking mode disabled. Otherwise, it's loaded at the bottom of the <body> as before
* scripts-only and messages-only requests need special treatment:
** in the top queue, they can continue to use <script src="..."> tags because they are blocking
** if the bottom queue is at the bottom of the <body> (experimental async loading disabled), they can continue to use <script src="..."> tags as before
** if the bottom queue is in the <head> (experimental async loading enabled), they cannot use <script src="..."> tags, because those would block. Instead, call mw.loader.load() on the load.php URL
2012-01-05 23:32:41 +00:00
|
|
|
/* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
|
|
|
|
|
);
|
2012-04-25 18:24:03 +00:00
|
|
|
$defaultModules['user.groups'] = 'loading';
|
|
|
|
|
} else {
|
|
|
|
|
// Non-logged-in users have no user.groups module. Treat it as empty and 'ready' to
|
|
|
|
|
// avoid blocking gadgets that might depend upon the module.
|
|
|
|
|
$defaultModules['user.groups'] = 'ready';
|
2009-09-22 16:52:40 +00:00
|
|
|
}
|
2012-04-25 18:24:03 +00:00
|
|
|
} else {
|
|
|
|
|
// Site (and group JS) disabled
|
|
|
|
|
$defaultModules['user.groups'] = 'missing';
|
2009-09-22 01:00:06 +00:00
|
|
|
}
|
2011-04-23 19:28:35 +00:00
|
|
|
|
2012-04-25 18:24:03 +00:00
|
|
|
$loaderInit = '';
|
|
|
|
|
if ( $inHead ) {
|
|
|
|
|
// We generate loader calls anyway, so no need to fix the client-side loader's state to 'loading'.
|
|
|
|
|
foreach ( $defaultModules as $m => $state ) {
|
|
|
|
|
if ( $state == 'loading' ) {
|
|
|
|
|
unset( $defaultModules[$m] );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( count( $defaultModules ) > 0 ) {
|
|
|
|
|
$loaderInit = Html::inlineScript(
|
|
|
|
|
ResourceLoader::makeLoaderConditionalScript(
|
|
|
|
|
ResourceLoader::makeLoaderStateScript( $defaultModules )
|
|
|
|
|
)
|
|
|
|
|
) . "\n";
|
|
|
|
|
}
|
|
|
|
|
return $loaderInit . $scripts;
|
2009-09-22 01:00:06 +00:00
|
|
|
}
|
|
|
|
|
|
ResourceLoader: Add an experimental option to move the main module loading queue (the bottom queue) from the bottom of the <body> up into the <head> , while still being loaded asynchronously. This makes them load earlier, which should make the page load faster. This is the product of a long discussion on bug 27488
* Added a "blocking" state to mw.loader . When loading scripts while the document is not ready, the loader will use document.write() if blocking is true, and append to the <body> or the <head> if blocking is false. If the document is ready, the loader will always append to the <body>
* Enable blocking mode while loading the top queue, and disable it after. This ensures that modules in the top queue are still loaded in a blocking way as they were before
* If $wgResourceLoaderExperimentalAsyncLoading is true, the bottom queue is also loaded in the head, but with blocking mode disabled. Otherwise, it's loaded at the bottom of the <body> as before
* scripts-only and messages-only requests need special treatment:
** in the top queue, they can continue to use <script src="..."> tags because they are blocking
** if the bottom queue is at the bottom of the <body> (experimental async loading disabled), they can continue to use <script src="..."> tags as before
** if the bottom queue is in the <head> (experimental async loading enabled), they cannot use <script src="..."> tags, because those would block. Instead, call mw.loader.load() on the load.php URL
2012-01-05 23:32:41 +00:00
|
|
|
/**
|
2012-07-10 12:48:06 +00:00
|
|
|
* JS stuff to put at the bottom of the "<body>"
|
2012-02-09 21:35:05 +00:00
|
|
|
* @return string
|
ResourceLoader: Add an experimental option to move the main module loading queue (the bottom queue) from the bottom of the <body> up into the <head> , while still being loaded asynchronously. This makes them load earlier, which should make the page load faster. This is the product of a long discussion on bug 27488
* Added a "blocking" state to mw.loader . When loading scripts while the document is not ready, the loader will use document.write() if blocking is true, and append to the <body> or the <head> if blocking is false. If the document is ready, the loader will always append to the <body>
* Enable blocking mode while loading the top queue, and disable it after. This ensures that modules in the top queue are still loaded in a blocking way as they were before
* If $wgResourceLoaderExperimentalAsyncLoading is true, the bottom queue is also loaded in the head, but with blocking mode disabled. Otherwise, it's loaded at the bottom of the <body> as before
* scripts-only and messages-only requests need special treatment:
** in the top queue, they can continue to use <script src="..."> tags because they are blocking
** if the bottom queue is at the bottom of the <body> (experimental async loading disabled), they can continue to use <script src="..."> tags as before
** if the bottom queue is in the <head> (experimental async loading enabled), they cannot use <script src="..."> tags, because those would block. Instead, call mw.loader.load() on the load.php URL
2012-01-05 23:32:41 +00:00
|
|
|
*/
|
|
|
|
|
function getBottomScripts() {
|
|
|
|
|
global $wgResourceLoaderExperimentalAsyncLoading;
|
|
|
|
|
if ( !$wgResourceLoaderExperimentalAsyncLoading ) {
|
|
|
|
|
return $this->getScriptsForBottomQueue( false );
|
|
|
|
|
} else {
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-16 18:25:44 +00:00
|
|
|
/**
|
2011-09-28 22:08:08 +00:00
|
|
|
* Add one or more variables to be set in mw.config in JavaScript.
|
2011-04-23 19:28:35 +00:00
|
|
|
*
|
2012-07-10 14:58:52 +00:00
|
|
|
* @param $keys {String|Array} Key or array of key/value pairs.
|
2011-12-31 21:25:00 +00:00
|
|
|
* @param $value {Mixed} [optional] Value of the configuration variable.
|
2011-09-28 22:08:08 +00:00
|
|
|
*/
|
2011-12-31 21:25:00 +00:00
|
|
|
public function addJsConfigVars( $keys, $value = null ) {
|
2011-09-28 22:08:08 +00:00
|
|
|
if ( is_array( $keys ) ) {
|
|
|
|
|
foreach ( $keys as $key => $value ) {
|
|
|
|
|
$this->mJsConfigVars[$key] = $value;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->mJsConfigVars[$keys] = $value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get an array containing the variables to be set in mw.config in JavaScript.
|
|
|
|
|
*
|
2011-12-29 20:39:29 +00:00
|
|
|
* DO NOT CALL THIS FROM OUTSIDE OF THIS CLASS OR Skin::makeGlobalVariablesScript().
|
|
|
|
|
* This is only public until that function is removed. You have been warned.
|
|
|
|
|
*
|
2011-09-28 22:08:08 +00:00
|
|
|
* Do not add things here which can be evaluated in ResourceLoaderStartupScript
|
2011-10-03 14:59:56 +00:00
|
|
|
* - in other words, page-independent/site-wide variables (without state).
|
2011-09-28 22:08:08 +00:00
|
|
|
* You will only be adding bloat to the html page and causing page caches to
|
2011-02-16 18:25:44 +00:00
|
|
|
* have to be purged on configuration changes.
|
2011-11-29 21:04:20 +00:00
|
|
|
* @return array
|
2011-02-16 18:25:44 +00:00
|
|
|
*/
|
2011-12-29 20:39:29 +00:00
|
|
|
public function getJSVars() {
|
2012-10-09 09:29:48 +00:00
|
|
|
global $wgContLang;
|
2011-02-16 18:25:44 +00:00
|
|
|
|
2012-01-29 20:35:32 +00:00
|
|
|
$latestRevID = 0;
|
|
|
|
|
$pageID = 0;
|
|
|
|
|
$canonicalName = false; # bug 21115
|
|
|
|
|
|
2011-02-16 18:25:44 +00:00
|
|
|
$title = $this->getTitle();
|
|
|
|
|
$ns = $title->getNamespace();
|
|
|
|
|
$nsname = MWNamespace::exists( $ns ) ? MWNamespace::getCanonicalName( $ns ) : $title->getNsText();
|
2012-01-29 20:35:32 +00:00
|
|
|
|
2012-03-13 17:57:54 +00:00
|
|
|
// Get the relevant title so that AJAX features can use the correct page name
|
|
|
|
|
// when making API requests from certain special pages (bug 34972).
|
|
|
|
|
$relevantTitle = $this->getSkin()->getRelevantTitle();
|
|
|
|
|
|
2011-02-25 11:48:14 +00:00
|
|
|
if ( $ns == NS_SPECIAL ) {
|
2011-04-17 11:31:11 +00:00
|
|
|
list( $canonicalName, /*...*/ ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
|
2012-01-29 20:35:32 +00:00
|
|
|
} elseif ( $this->canUseWikiPage() ) {
|
|
|
|
|
$wikiPage = $this->getWikiPage();
|
|
|
|
|
$latestRevID = $wikiPage->getLatest();
|
|
|
|
|
$pageID = $wikiPage->getId();
|
2011-02-25 11:48:14 +00:00
|
|
|
}
|
2011-02-16 18:25:44 +00:00
|
|
|
|
2011-11-28 20:53:26 +00:00
|
|
|
$lang = $title->getPageLanguage();
|
|
|
|
|
|
|
|
|
|
// Pre-process information
|
|
|
|
|
$separatorTransTable = $lang->separatorTransformTable();
|
|
|
|
|
$separatorTransTable = $separatorTransTable ? $separatorTransTable : array();
|
|
|
|
|
$compactSeparatorTransTable = array(
|
|
|
|
|
implode( "\t", array_keys( $separatorTransTable ) ),
|
|
|
|
|
implode( "\t", $separatorTransTable ),
|
|
|
|
|
);
|
|
|
|
|
$digitTransTable = $lang->digitTransformTable();
|
|
|
|
|
$digitTransTable = $digitTransTable ? $digitTransTable : array();
|
|
|
|
|
$compactDigitTransTable = array(
|
|
|
|
|
implode( "\t", array_keys( $digitTransTable ) ),
|
|
|
|
|
implode( "\t", $digitTransTable ),
|
|
|
|
|
);
|
|
|
|
|
|
2011-02-16 18:25:44 +00:00
|
|
|
$vars = array(
|
|
|
|
|
'wgCanonicalNamespace' => $nsname,
|
2011-02-25 11:48:14 +00:00
|
|
|
'wgCanonicalSpecialPageName' => $canonicalName,
|
2011-02-16 18:25:44 +00:00
|
|
|
'wgNamespaceNumber' => $title->getNamespace(),
|
|
|
|
|
'wgPageName' => $title->getPrefixedDBKey(),
|
|
|
|
|
'wgTitle' => $title->getText(),
|
2012-01-29 20:35:32 +00:00
|
|
|
'wgCurRevisionId' => $latestRevID,
|
|
|
|
|
'wgArticleId' => $pageID,
|
2011-02-16 18:25:44 +00:00
|
|
|
'wgIsArticle' => $this->isArticle(),
|
2012-01-21 06:57:34 +00:00
|
|
|
'wgAction' => Action::getActionName( $this->getContext() ),
|
2011-04-03 03:59:47 +00:00
|
|
|
'wgUserName' => $this->getUser()->isAnon() ? null : $this->getUser()->getName(),
|
|
|
|
|
'wgUserGroups' => $this->getUser()->getEffectiveGroups(),
|
2011-02-16 18:25:44 +00:00
|
|
|
'wgCategories' => $this->getCategories(),
|
|
|
|
|
'wgBreakFrames' => $this->getFrameOptions() == 'DENY',
|
2011-11-28 20:53:26 +00:00
|
|
|
'wgPageContentLanguage' => $lang->getCode(),
|
|
|
|
|
'wgSeparatorTransformTable' => $compactSeparatorTransTable,
|
|
|
|
|
'wgDigitTransformTable' => $compactDigitTransTable,
|
2012-07-04 22:00:44 +00:00
|
|
|
'wgDefaultDateFormat' => $lang->getDefaultDateFormat(),
|
|
|
|
|
'wgMonthNames' => $lang->getMonthNamesArray(),
|
|
|
|
|
'wgMonthNamesShort' => $lang->getMonthAbbreviationsArray(),
|
2012-03-13 17:57:54 +00:00
|
|
|
'wgRelevantPageName' => $relevantTitle->getPrefixedDBKey(),
|
2011-02-16 18:25:44 +00:00
|
|
|
);
|
2012-03-06 11:11:01 +00:00
|
|
|
if ( $wgContLang->hasVariants() ) {
|
|
|
|
|
$vars['wgUserVariant'] = $wgContLang->getPreferredVariant();
|
2012-10-26 15:42:13 +00:00
|
|
|
}
|
2011-02-16 18:25:44 +00:00
|
|
|
foreach ( $title->getRestrictionTypes() as $type ) {
|
|
|
|
|
$vars['wgRestriction' . ucfirst( $type )] = $title->getRestrictions( $type );
|
|
|
|
|
}
|
2011-06-14 23:29:45 +00:00
|
|
|
if ( $title->isMainPage() ) {
|
2011-06-15 01:11:16 +00:00
|
|
|
$vars['wgIsMainPage'] = true;
|
2011-11-30 12:43:10 +00:00
|
|
|
}
|
|
|
|
|
if ( $this->mRedirectedFrom ) {
|
|
|
|
|
$vars['wgRedirectedFrom'] = $this->mRedirectedFrom->getPrefixedDBKey();
|
2011-06-14 23:29:45 +00:00
|
|
|
}
|
2011-04-23 19:28:35 +00:00
|
|
|
|
2011-09-28 22:08:08 +00:00
|
|
|
// Allow extensions to add their custom variables to the mw.config map.
|
|
|
|
|
// Use the 'ResourceLoaderGetConfigVars' hook if the variable is not
|
|
|
|
|
// page-dependant but site-wide (without state).
|
|
|
|
|
// Alternatively, you may want to use OutputPage->addJsConfigVars() instead.
|
2011-11-03 22:21:19 +00:00
|
|
|
wfRunHooks( 'MakeGlobalVariablesScript', array( &$vars, $this ) );
|
2011-04-23 19:28:35 +00:00
|
|
|
|
2011-09-28 22:08:08 +00:00
|
|
|
// Merge in variables from addJsConfigVars last
|
|
|
|
|
return array_merge( $vars, $this->mJsConfigVars );
|
2011-02-16 18:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
2011-07-22 10:45:07 +00:00
|
|
|
* To make it harder for someone to slip a user a fake
|
|
|
|
|
* user-JavaScript or user-CSS preview, a random token
|
|
|
|
|
* is associated with the login session. If it's not
|
|
|
|
|
* passed back with the preview request, we won't render
|
|
|
|
|
* the code.
|
|
|
|
|
*
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public function userCanPreview() {
|
|
|
|
|
if ( $this->getRequest()->getVal( 'action' ) != 'submit'
|
|
|
|
|
|| !$this->getRequest()->wasPosted()
|
|
|
|
|
|| !$this->getUser()->matchEditToken(
|
|
|
|
|
$this->getRequest()->getVal( 'wpEditToken' ) )
|
|
|
|
|
) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if ( !$this->getTitle()->isJsSubpage() && !$this->getTitle()->isCssSubpage() ) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return !count( $this->getTitle()->getUserPermissionsErrors( 'edit', $this->getUser() ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2012-07-10 12:48:06 +00:00
|
|
|
* @param $addContentType bool: Whether "<meta>" specifying content type should be returned
|
2011-05-21 19:07:24 +00:00
|
|
|
*
|
2012-04-24 17:25:06 +00:00
|
|
|
* @return array in format "link name or number => 'link html'".
|
2010-01-29 21:32:45 +00:00
|
|
|
*/
|
2012-04-24 17:25:06 +00:00
|
|
|
public function getHeadLinksArray( $addContentType = false ) {
|
2011-04-02 18:38:42 +00:00
|
|
|
global $wgUniversalEditButton, $wgFavicon, $wgAppleTouchIcon, $wgEnableAPI,
|
2011-05-15 13:21:16 +00:00
|
|
|
$wgSitename, $wgVersion, $wgHtml5, $wgMimeType,
|
2011-04-02 18:38:42 +00:00
|
|
|
$wgFeed, $wgOverrideSiteFeed, $wgAdvertisedFeedTypes,
|
2011-09-22 20:31:23 +00:00
|
|
|
$wgDisableLangConversion, $wgCanonicalLanguageLinks,
|
2011-04-02 18:38:42 +00:00
|
|
|
$wgRightsPage, $wgRightsUrl;
|
2009-07-07 21:49:45 +00:00
|
|
|
|
2011-04-02 18:38:42 +00:00
|
|
|
$tags = array();
|
2009-07-07 21:49:45 +00:00
|
|
|
|
2012-12-31 01:11:43 +00:00
|
|
|
$canonicalUrl = $this->mCanonicalUrl;
|
|
|
|
|
|
2011-04-02 18:38:42 +00:00
|
|
|
if ( $addContentType ) {
|
|
|
|
|
if ( $wgHtml5 ) {
|
|
|
|
|
# More succinct than <meta http-equiv=Content-Type>, has the
|
|
|
|
|
# same effect
|
2012-04-24 17:25:06 +00:00
|
|
|
$tags['meta-charset'] = Html::element( 'meta', array( 'charset' => 'UTF-8' ) );
|
2011-04-02 18:38:42 +00:00
|
|
|
} else {
|
2012-04-24 17:25:06 +00:00
|
|
|
$tags['meta-content-type'] = Html::element( 'meta', array(
|
2011-04-02 18:38:42 +00:00
|
|
|
'http-equiv' => 'Content-Type',
|
2011-05-06 22:09:47 +00:00
|
|
|
'content' => "$wgMimeType; charset=UTF-8"
|
2011-04-02 18:38:42 +00:00
|
|
|
) );
|
2013-02-03 20:05:24 +00:00
|
|
|
$tags['meta-content-style-type'] = Html::element( 'meta', array( // bug 15835
|
2011-04-02 18:38:42 +00:00
|
|
|
'http-equiv' => 'Content-Style-Type',
|
|
|
|
|
'content' => 'text/css'
|
|
|
|
|
) );
|
|
|
|
|
}
|
2009-07-10 04:19:51 +00:00
|
|
|
}
|
2011-04-02 18:38:42 +00:00
|
|
|
|
2012-04-24 17:25:06 +00:00
|
|
|
$tags['meta-generator'] = Html::element( 'meta', array(
|
2011-04-02 18:38:42 +00:00
|
|
|
'name' => 'generator',
|
2011-05-15 13:21:16 +00:00
|
|
|
'content' => "MediaWiki $wgVersion",
|
2011-04-02 18:38:42 +00:00
|
|
|
) );
|
here it is ... the upload-api, script-server, js2 (javascript phase2) branch merge 1st attempt.
Here is a short overview of changes and associated default configuration variables (most everything is off by default) also see ~soon to be updated~: http://www.mediawiki.org/wiki/Media_Projects_Overview
= Upload Improvements =
==Upload API ==
* Based on the early work of Bryan Tong and others it adds the upload option to the api.
* We rewrite Special:Upload page to include use the new refactoring
* Added in token checks in both the SpecialUpload.php page so avoids DOS / xss copy-by-url JavaScript based cross site POST file submissions
== Copy by URL==
$wgAllowCopyUploads = false;
* http class rewrite includes a new http background download see: includes/HttpFunctions.php
* spins off a php process that calls: maintenance/http_session_download.php
* pushes updates to the session and gives the user a progress bar on http copy uploads from other server progress (using js2 upload interface) (if not using the js2 upload interface it does the request in-place but the download is limited to the php ini timeout time)
== Firefogg ==
* Firefogg enables resumable upload by chunks
* progress indicators and conditional invokation (js2 system)
* and of-course client side transcoding.
= Script Server =
$wgEnableScriptLoader = false;
* off by default if $wgEnableScriptLoader is turned on script files are grouped, gziped, cached etc.
for more info see: http://www.mediawiki.org/wiki/Extension:ScriptLoader
* Includes some early skin js include fixes (skin/script system still lots of love)
* Includes a "javascript class autoloader" this is packaged into mwEmbed so that the mwEmbed library can work in stand alone mode (while retaining localization and script serving) (one such application is the make page for firefogg.org : http://www.firefogg.org/make/index.html )
* The file that contains the autojavascript loading classes is: js2/php/jsAutoloadLocalClasses.php
* One can use this auto class loading dependency system with extensions and add-ons but I need to better document that.
= js2 system / mwEmbed=
$wgEnableJS2system = false
* includes initial rewrite towards more jquery based javascript code
* especially for the Special:Upload page.
* Also the edit page include support for the "add-media-wizard"
* includes dependency loader for javascript that optionally takes advantage of the script-loader
* remote embedding of javascript interfaces (like embedding video, or commons media searching)
* $wgDebugJavaScript = false; .. .this variable lets you always get "always fresh javascript". When used with the script-loader it does not minify the script-loader output.
= mwEmbed =
* Will commit a separate patch to oggHandler that conditionally outputs <video tag> to use the new javascript video player.
** mv_embed player includes: play-head, volume control, remote embedding, oggz-chop support across plugins.
* add-media-wizard adds easy inserts of media to pages (with import)
== jQuery==
* we include a base install of jQuery, jQuery ui and some plugins.
* all the javascript classes are in the scriptloader so its easy to load any set of jquery ui components that you may need using the script-server. You get a callback so you can then execute js with dependencies loaded.
== other stuff ==
there is a bit more code in js2 that pertains to sequence editing, timed text display and basic image editing. We include a base import of pixastic-lib & pixastic-editor... will work with the pixastic developer to try and ensure upstream compatibility on our usage of the library for in-browser photo and sequence manipulation.
2009-07-14 23:52:14 +00:00
|
|
|
|
2008-07-23 19:05:43 +00:00
|
|
|
$p = "{$this->mIndexPolicy},{$this->mFollowPolicy}";
|
|
|
|
|
if( $p !== 'index,follow' ) {
|
2008-07-02 22:52:22 +00:00
|
|
|
// http://www.robotstxt.org/wc/meta-user.html
|
|
|
|
|
// Only show if it's different from the default robots policy
|
2012-04-24 17:25:06 +00:00
|
|
|
$tags['meta-robots'] = Html::element( 'meta', array(
|
2011-04-02 18:38:42 +00:00
|
|
|
'name' => 'robots',
|
|
|
|
|
'content' => $p,
|
|
|
|
|
) );
|
2008-07-02 22:52:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( count( $this->mKeywords ) > 0 ) {
|
|
|
|
|
$strip = array(
|
2009-03-16 00:36:17 +00:00
|
|
|
"/<.*?" . ">/" => '',
|
2008-07-02 22:52:22 +00:00
|
|
|
"/_/" => ' '
|
|
|
|
|
);
|
2012-04-24 17:25:06 +00:00
|
|
|
$tags['meta-keywords'] = Html::element( 'meta', array(
|
2011-04-02 18:38:42 +00:00
|
|
|
'name' => 'keywords',
|
2013-02-03 20:05:24 +00:00
|
|
|
'content' => preg_replace(
|
2010-05-22 12:18:22 +00:00
|
|
|
array_keys( $strip ),
|
|
|
|
|
array_values( $strip ),
|
|
|
|
|
implode( ',', $this->mKeywords )
|
|
|
|
|
)
|
2011-04-02 18:38:42 +00:00
|
|
|
) );
|
2008-07-02 22:52:22 +00:00
|
|
|
}
|
here it is ... the upload-api, script-server, js2 (javascript phase2) branch merge 1st attempt.
Here is a short overview of changes and associated default configuration variables (most everything is off by default) also see ~soon to be updated~: http://www.mediawiki.org/wiki/Media_Projects_Overview
= Upload Improvements =
==Upload API ==
* Based on the early work of Bryan Tong and others it adds the upload option to the api.
* We rewrite Special:Upload page to include use the new refactoring
* Added in token checks in both the SpecialUpload.php page so avoids DOS / xss copy-by-url JavaScript based cross site POST file submissions
== Copy by URL==
$wgAllowCopyUploads = false;
* http class rewrite includes a new http background download see: includes/HttpFunctions.php
* spins off a php process that calls: maintenance/http_session_download.php
* pushes updates to the session and gives the user a progress bar on http copy uploads from other server progress (using js2 upload interface) (if not using the js2 upload interface it does the request in-place but the download is limited to the php ini timeout time)
== Firefogg ==
* Firefogg enables resumable upload by chunks
* progress indicators and conditional invokation (js2 system)
* and of-course client side transcoding.
= Script Server =
$wgEnableScriptLoader = false;
* off by default if $wgEnableScriptLoader is turned on script files are grouped, gziped, cached etc.
for more info see: http://www.mediawiki.org/wiki/Extension:ScriptLoader
* Includes some early skin js include fixes (skin/script system still lots of love)
* Includes a "javascript class autoloader" this is packaged into mwEmbed so that the mwEmbed library can work in stand alone mode (while retaining localization and script serving) (one such application is the make page for firefogg.org : http://www.firefogg.org/make/index.html )
* The file that contains the autojavascript loading classes is: js2/php/jsAutoloadLocalClasses.php
* One can use this auto class loading dependency system with extensions and add-ons but I need to better document that.
= js2 system / mwEmbed=
$wgEnableJS2system = false
* includes initial rewrite towards more jquery based javascript code
* especially for the Special:Upload page.
* Also the edit page include support for the "add-media-wizard"
* includes dependency loader for javascript that optionally takes advantage of the script-loader
* remote embedding of javascript interfaces (like embedding video, or commons media searching)
* $wgDebugJavaScript = false; .. .this variable lets you always get "always fresh javascript". When used with the script-loader it does not minify the script-loader output.
= mwEmbed =
* Will commit a separate patch to oggHandler that conditionally outputs <video tag> to use the new javascript video player.
** mv_embed player includes: play-head, volume control, remote embedding, oggz-chop support across plugins.
* add-media-wizard adds easy inserts of media to pages (with import)
== jQuery==
* we include a base install of jQuery, jQuery ui and some plugins.
* all the javascript classes are in the scriptloader so its easy to load any set of jquery ui components that you may need using the script-server. You get a callback so you can then execute js with dependencies loaded.
== other stuff ==
there is a bit more code in js2 that pertains to sequence editing, timed text display and basic image editing. We include a base import of pixastic-lib & pixastic-editor... will work with the pixastic developer to try and ensure upstream compatibility on our usage of the library for in-browser photo and sequence manipulation.
2009-07-14 23:52:14 +00:00
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
foreach ( $this->mMetatags as $tag ) {
|
2012-02-20 22:48:43 +00:00
|
|
|
if ( 0 == strcasecmp( 'http:', substr( $tag[0], 0, 5 ) ) ) {
|
|
|
|
|
$a = 'http-equiv';
|
|
|
|
|
$tag[0] = substr( $tag[0], 5 );
|
|
|
|
|
} else {
|
|
|
|
|
$a = 'name';
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2012-04-24 17:25:06 +00:00
|
|
|
$tagName = "meta-{$tag[0]}";
|
|
|
|
|
if ( isset( $tags[$tagName] ) ) {
|
|
|
|
|
$tagName .= $tag[1];
|
|
|
|
|
}
|
|
|
|
|
$tags[$tagName] = Html::element( 'meta',
|
2008-07-02 22:52:22 +00:00
|
|
|
array(
|
|
|
|
|
$a => $tag[0],
|
2010-05-22 12:18:22 +00:00
|
|
|
'content' => $tag[1]
|
|
|
|
|
)
|
|
|
|
|
);
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2011-04-02 18:38:42 +00:00
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
foreach ( $this->mLinktags as $tag ) {
|
2009-09-18 20:10:25 +00:00
|
|
|
$tags[] = Html::element( 'link', $tag );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2011-04-02 18:38:42 +00:00
|
|
|
# Universal edit button
|
2011-11-07 13:51:40 +00:00
|
|
|
if ( $wgUniversalEditButton && $this->isArticleRelated() ) {
|
|
|
|
|
$user = $this->getUser();
|
|
|
|
|
if ( $this->getTitle()->quickUserCan( 'edit', $user )
|
|
|
|
|
&& ( $this->getTitle()->exists() || $this->getTitle()->quickUserCan( 'create', $user ) ) ) {
|
2011-04-02 18:38:42 +00:00
|
|
|
// Original UniversalEditButton
|
2011-10-23 08:13:52 +00:00
|
|
|
$msg = $this->msg( 'edit' )->text();
|
2012-04-24 17:25:06 +00:00
|
|
|
$tags['universal-edit-button'] = Html::element( 'link', array(
|
2011-04-02 18:38:42 +00:00
|
|
|
'rel' => 'alternate',
|
|
|
|
|
'type' => 'application/x-wiki',
|
|
|
|
|
'title' => $msg,
|
|
|
|
|
'href' => $this->getTitle()->getLocalURL( 'action=edit' )
|
|
|
|
|
) );
|
|
|
|
|
// Alternate edit link
|
2012-04-24 17:25:06 +00:00
|
|
|
$tags['alternative-edit'] = Html::element( 'link', array(
|
2011-04-02 18:38:42 +00:00
|
|
|
'rel' => 'edit',
|
|
|
|
|
'title' => $msg,
|
|
|
|
|
'href' => $this->getTitle()->getLocalURL( 'action=edit' )
|
|
|
|
|
) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Generally the order of the favicon and apple-touch-icon links
|
|
|
|
|
# should not matter, but Konqueror (3.5.9 at least) incorrectly
|
|
|
|
|
# uses whichever one appears later in the HTML source. Make sure
|
|
|
|
|
# apple-touch-icon is specified first to avoid this.
|
|
|
|
|
if ( $wgAppleTouchIcon !== false ) {
|
2012-04-24 17:25:06 +00:00
|
|
|
$tags['apple-touch-icon'] = Html::element( 'link', array( 'rel' => 'apple-touch-icon', 'href' => $wgAppleTouchIcon ) );
|
2011-04-02 18:38:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( $wgFavicon !== false ) {
|
2012-04-24 17:25:06 +00:00
|
|
|
$tags['favicon'] = Html::element( 'link', array( 'rel' => 'shortcut icon', 'href' => $wgFavicon ) );
|
2011-04-02 18:38:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# OpenSearch description link
|
2012-04-24 17:25:06 +00:00
|
|
|
$tags['opensearch'] = Html::element( 'link', array(
|
2011-04-02 18:38:42 +00:00
|
|
|
'rel' => 'search',
|
|
|
|
|
'type' => 'application/opensearchdescription+xml',
|
|
|
|
|
'href' => wfScript( 'opensearch_desc' ),
|
2011-10-23 08:13:52 +00:00
|
|
|
'title' => $this->msg( 'opensearch-desc' )->inContentLanguage()->text(),
|
2011-04-02 18:38:42 +00:00
|
|
|
) );
|
|
|
|
|
|
|
|
|
|
if ( $wgEnableAPI ) {
|
|
|
|
|
# Real Simple Discovery link, provides auto-discovery information
|
|
|
|
|
# for the MediaWiki API (and potentially additional custom API
|
|
|
|
|
# support such as WordPress or Twitter-compatible APIs for a
|
|
|
|
|
# blogging extension, etc)
|
2012-04-24 17:25:06 +00:00
|
|
|
$tags['rsd'] = Html::element( 'link', array(
|
2011-04-02 18:38:42 +00:00
|
|
|
'rel' => 'EditURI',
|
|
|
|
|
'type' => 'application/rsd+xml',
|
2011-08-03 12:58:21 +00:00
|
|
|
// Output a protocol-relative URL here if $wgServer is protocol-relative
|
|
|
|
|
// Whether RSD accepts relative or protocol-relative URLs is completely undocumented, though
|
2011-08-03 13:11:42 +00:00
|
|
|
'href' => wfExpandUrl( wfAppendQuery( wfScript( 'api' ), array( 'action' => 'rsd' ) ), PROTO_RELATIVE ),
|
2011-04-02 18:38:42 +00:00
|
|
|
) );
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-22 20:31:23 +00:00
|
|
|
|
2011-04-02 18:38:42 +00:00
|
|
|
# Language variants
|
2011-11-05 20:25:00 +00:00
|
|
|
if ( !$wgDisableLangConversion && $wgCanonicalLanguageLinks ) {
|
|
|
|
|
$lang = $this->getTitle()->getPageLanguage();
|
|
|
|
|
if ( $lang->hasVariants() ) {
|
|
|
|
|
|
|
|
|
|
$urlvar = $lang->getURLVariant();
|
|
|
|
|
|
|
|
|
|
if ( !$urlvar ) {
|
|
|
|
|
$variants = $lang->getVariants();
|
|
|
|
|
foreach ( $variants as $_v ) {
|
2012-04-24 17:25:06 +00:00
|
|
|
$tags["variant-$_v"] = Html::element( 'link', array(
|
2011-11-05 20:25:00 +00:00
|
|
|
'rel' => 'alternate',
|
|
|
|
|
'hreflang' => $_v,
|
2011-12-12 19:19:23 +00:00
|
|
|
'href' => $this->getTitle()->getLocalURL( array( 'variant' => $_v ) ) )
|
2011-11-05 20:25:00 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2012-12-31 01:11:43 +00:00
|
|
|
$canonicalUrl = $this->getTitle()->getLocalURL();
|
2011-04-02 18:38:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Copyright
|
|
|
|
|
$copyright = '';
|
|
|
|
|
if ( $wgRightsPage ) {
|
|
|
|
|
$copy = Title::newFromText( $wgRightsPage );
|
|
|
|
|
|
|
|
|
|
if ( $copy ) {
|
|
|
|
|
$copyright = $copy->getLocalURL();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( !$copyright && $wgRightsUrl ) {
|
|
|
|
|
$copyright = $wgRightsUrl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( $copyright ) {
|
2012-04-24 17:25:06 +00:00
|
|
|
$tags['copyright'] = Html::element( 'link', array(
|
2011-04-02 18:38:42 +00:00
|
|
|
'rel' => 'copyright',
|
|
|
|
|
'href' => $copyright )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Feeds
|
|
|
|
|
if ( $wgFeed ) {
|
2008-02-22 12:33:51 +00:00
|
|
|
foreach( $this->getSyndicationLinks() as $format => $link ) {
|
2011-05-26 16:11:47 +00:00
|
|
|
# Use the page name for the title. In principle, this could
|
|
|
|
|
# lead to issues with having the same name for different feeds
|
|
|
|
|
# corresponding to the same page, but we can't avoid that at
|
|
|
|
|
# this low a level.
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2008-07-02 22:52:22 +00:00
|
|
|
$tags[] = $this->feedLink(
|
2008-02-22 12:33:51 +00:00
|
|
|
$format,
|
|
|
|
|
$link,
|
2010-01-13 21:29:47 +00:00
|
|
|
# Used messages: 'page-rss-feed' and 'page-atom-feed' (for an easier grep)
|
2011-10-23 08:13:52 +00:00
|
|
|
$this->msg( "page-{$format}-feed", $this->getTitle()->getPrefixedText() )->text()
|
2010-05-22 12:18:22 +00:00
|
|
|
);
|
2008-02-22 12:33:51 +00:00
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
here it is ... the upload-api, script-server, js2 (javascript phase2) branch merge 1st attempt.
Here is a short overview of changes and associated default configuration variables (most everything is off by default) also see ~soon to be updated~: http://www.mediawiki.org/wiki/Media_Projects_Overview
= Upload Improvements =
==Upload API ==
* Based on the early work of Bryan Tong and others it adds the upload option to the api.
* We rewrite Special:Upload page to include use the new refactoring
* Added in token checks in both the SpecialUpload.php page so avoids DOS / xss copy-by-url JavaScript based cross site POST file submissions
== Copy by URL==
$wgAllowCopyUploads = false;
* http class rewrite includes a new http background download see: includes/HttpFunctions.php
* spins off a php process that calls: maintenance/http_session_download.php
* pushes updates to the session and gives the user a progress bar on http copy uploads from other server progress (using js2 upload interface) (if not using the js2 upload interface it does the request in-place but the download is limited to the php ini timeout time)
== Firefogg ==
* Firefogg enables resumable upload by chunks
* progress indicators and conditional invokation (js2 system)
* and of-course client side transcoding.
= Script Server =
$wgEnableScriptLoader = false;
* off by default if $wgEnableScriptLoader is turned on script files are grouped, gziped, cached etc.
for more info see: http://www.mediawiki.org/wiki/Extension:ScriptLoader
* Includes some early skin js include fixes (skin/script system still lots of love)
* Includes a "javascript class autoloader" this is packaged into mwEmbed so that the mwEmbed library can work in stand alone mode (while retaining localization and script serving) (one such application is the make page for firefogg.org : http://www.firefogg.org/make/index.html )
* The file that contains the autojavascript loading classes is: js2/php/jsAutoloadLocalClasses.php
* One can use this auto class loading dependency system with extensions and add-ons but I need to better document that.
= js2 system / mwEmbed=
$wgEnableJS2system = false
* includes initial rewrite towards more jquery based javascript code
* especially for the Special:Upload page.
* Also the edit page include support for the "add-media-wizard"
* includes dependency loader for javascript that optionally takes advantage of the script-loader
* remote embedding of javascript interfaces (like embedding video, or commons media searching)
* $wgDebugJavaScript = false; .. .this variable lets you always get "always fresh javascript". When used with the script-loader it does not minify the script-loader output.
= mwEmbed =
* Will commit a separate patch to oggHandler that conditionally outputs <video tag> to use the new javascript video player.
** mv_embed player includes: play-head, volume control, remote embedding, oggz-chop support across plugins.
* add-media-wizard adds easy inserts of media to pages (with import)
== jQuery==
* we include a base install of jQuery, jQuery ui and some plugins.
* all the javascript classes are in the scriptloader so its easy to load any set of jquery ui components that you may need using the script-server. You get a callback so you can then execute js with dependencies loaded.
== other stuff ==
there is a bit more code in js2 that pertains to sequence editing, timed text display and basic image editing. We include a base import of pixastic-lib & pixastic-editor... will work with the pixastic developer to try and ensure upstream compatibility on our usage of the library for in-browser photo and sequence manipulation.
2009-07-14 23:52:14 +00:00
|
|
|
# Recent changes feed should appear on every page (except recentchanges,
|
|
|
|
|
# that would be redundant). Put it after the per-page feed to avoid
|
|
|
|
|
# changing existing behavior. It's still available, probably via a
|
2008-08-08 01:41:14 +00:00
|
|
|
# menu in your browser. Some sites might have a different feed they'd
|
|
|
|
|
# like to promote instead of the RC feed (maybe like a "Recent New Articles"
|
|
|
|
|
# or "Breaking news" one). For this, we see if $wgOverrideSiteFeed is defined.
|
|
|
|
|
# If so, use it instead.
|
2008-08-08 21:02:52 +00:00
|
|
|
if ( $wgOverrideSiteFeed ) {
|
here it is ... the upload-api, script-server, js2 (javascript phase2) branch merge 1st attempt.
Here is a short overview of changes and associated default configuration variables (most everything is off by default) also see ~soon to be updated~: http://www.mediawiki.org/wiki/Media_Projects_Overview
= Upload Improvements =
==Upload API ==
* Based on the early work of Bryan Tong and others it adds the upload option to the api.
* We rewrite Special:Upload page to include use the new refactoring
* Added in token checks in both the SpecialUpload.php page so avoids DOS / xss copy-by-url JavaScript based cross site POST file submissions
== Copy by URL==
$wgAllowCopyUploads = false;
* http class rewrite includes a new http background download see: includes/HttpFunctions.php
* spins off a php process that calls: maintenance/http_session_download.php
* pushes updates to the session and gives the user a progress bar on http copy uploads from other server progress (using js2 upload interface) (if not using the js2 upload interface it does the request in-place but the download is limited to the php ini timeout time)
== Firefogg ==
* Firefogg enables resumable upload by chunks
* progress indicators and conditional invokation (js2 system)
* and of-course client side transcoding.
= Script Server =
$wgEnableScriptLoader = false;
* off by default if $wgEnableScriptLoader is turned on script files are grouped, gziped, cached etc.
for more info see: http://www.mediawiki.org/wiki/Extension:ScriptLoader
* Includes some early skin js include fixes (skin/script system still lots of love)
* Includes a "javascript class autoloader" this is packaged into mwEmbed so that the mwEmbed library can work in stand alone mode (while retaining localization and script serving) (one such application is the make page for firefogg.org : http://www.firefogg.org/make/index.html )
* The file that contains the autojavascript loading classes is: js2/php/jsAutoloadLocalClasses.php
* One can use this auto class loading dependency system with extensions and add-ons but I need to better document that.
= js2 system / mwEmbed=
$wgEnableJS2system = false
* includes initial rewrite towards more jquery based javascript code
* especially for the Special:Upload page.
* Also the edit page include support for the "add-media-wizard"
* includes dependency loader for javascript that optionally takes advantage of the script-loader
* remote embedding of javascript interfaces (like embedding video, or commons media searching)
* $wgDebugJavaScript = false; .. .this variable lets you always get "always fresh javascript". When used with the script-loader it does not minify the script-loader output.
= mwEmbed =
* Will commit a separate patch to oggHandler that conditionally outputs <video tag> to use the new javascript video player.
** mv_embed player includes: play-head, volume control, remote embedding, oggz-chop support across plugins.
* add-media-wizard adds easy inserts of media to pages (with import)
== jQuery==
* we include a base install of jQuery, jQuery ui and some plugins.
* all the javascript classes are in the scriptloader so its easy to load any set of jquery ui components that you may need using the script-server. You get a callback so you can then execute js with dependencies loaded.
== other stuff ==
there is a bit more code in js2 that pertains to sequence editing, timed text display and basic image editing. We include a base import of pixastic-lib & pixastic-editor... will work with the pixastic developer to try and ensure upstream compatibility on our usage of the library for in-browser photo and sequence manipulation.
2009-07-14 23:52:14 +00:00
|
|
|
foreach ( $wgOverrideSiteFeed as $type => $feedUrl ) {
|
2011-09-07 19:14:06 +00:00
|
|
|
// Note, this->feedLink escapes the url.
|
2010-05-22 12:18:22 +00:00
|
|
|
$tags[] = $this->feedLink(
|
2008-08-08 01:41:14 +00:00
|
|
|
$type,
|
2011-09-07 19:14:06 +00:00
|
|
|
$feedUrl,
|
2011-10-23 08:13:52 +00:00
|
|
|
$this->msg( "site-{$type}-feed", $wgSitename )->text()
|
2010-05-22 12:18:22 +00:00
|
|
|
);
|
2008-08-08 01:41:14 +00:00
|
|
|
}
|
2011-11-05 20:25:00 +00:00
|
|
|
} elseif ( !$this->getTitle()->isSpecial( 'Recentchanges' ) ) {
|
2011-12-20 09:12:20 +00:00
|
|
|
$rctitle = SpecialPage::getTitleFor( 'Recentchanges' );
|
2010-01-13 21:29:47 +00:00
|
|
|
foreach ( $wgAdvertisedFeedTypes as $format ) {
|
2008-09-16 03:58:18 +00:00
|
|
|
$tags[] = $this->feedLink(
|
|
|
|
|
$format,
|
2011-12-20 09:12:20 +00:00
|
|
|
$rctitle->getLocalURL( "feed={$format}" ),
|
2011-10-23 08:13:52 +00:00
|
|
|
$this->msg( "site-{$format}-feed", $wgSitename )->text() # For grep: 'site-rss-feed', 'site-atom-feed'.
|
2010-05-22 12:18:22 +00:00
|
|
|
);
|
2008-09-16 03:58:18 +00:00
|
|
|
}
|
2008-06-12 00:51:04 +00:00
|
|
|
}
|
2004-03-19 08:05:36 +00:00
|
|
|
}
|
2012-12-31 01:11:43 +00:00
|
|
|
|
|
|
|
|
# Canonical URL
|
|
|
|
|
global $wgEnableCanonicalServerLink;
|
|
|
|
|
if ( $wgEnableCanonicalServerLink ) {
|
|
|
|
|
if ( $canonicalUrl !== false ) {
|
|
|
|
|
$canonicalUrl = wfExpandUrl( $canonicalUrl, PROTO_CANONICAL );
|
|
|
|
|
} else {
|
|
|
|
|
$reqUrl = $this->getRequest()->getRequestURL();
|
|
|
|
|
$canonicalUrl = wfExpandUrl( $reqUrl, PROTO_CANONICAL );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( $canonicalUrl !== false ) {
|
|
|
|
|
$tags[] = Html::element( 'link', array(
|
|
|
|
|
'rel' => 'canonical',
|
|
|
|
|
'href' => $canonicalUrl
|
|
|
|
|
) );
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-24 17:25:06 +00:00
|
|
|
return $tags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param $unused
|
2012-07-10 12:48:06 +00:00
|
|
|
* @param $addContentType bool: Whether "<meta>" specifying content type should be returned
|
2012-04-24 17:25:06 +00:00
|
|
|
*
|
|
|
|
|
* @return string HTML tag links to be put in the header.
|
|
|
|
|
*/
|
|
|
|
|
public function getHeadLinks( $unused = null, $addContentType = false ) {
|
|
|
|
|
return implode( "\n", $this->getHeadLinksArray( $addContentType ) );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2008-01-12 00:13:53 +00:00
|
|
|
/**
|
2012-07-10 12:48:06 +00:00
|
|
|
* Generate a "<link rel/>" for a feed.
|
2010-01-29 21:32:45 +00:00
|
|
|
*
|
|
|
|
|
* @param $type String: feed type
|
|
|
|
|
* @param $url String: URL to the feed
|
|
|
|
|
* @param $text String: value of the "title" attribute
|
|
|
|
|
* @return String: HTML fragment
|
2007-09-24 18:25:56 +00:00
|
|
|
*/
|
|
|
|
|
private function feedLink( $type, $url, $text ) {
|
2009-09-18 20:10:25 +00:00
|
|
|
return Html::element( 'link', array(
|
2007-09-24 18:25:56 +00:00
|
|
|
'rel' => 'alternate',
|
|
|
|
|
'type' => "application/$type+xml",
|
|
|
|
|
'title' => $text,
|
2010-05-22 12:18:22 +00:00
|
|
|
'href' => $url )
|
|
|
|
|
);
|
2007-09-24 18:25:56 +00:00
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2008-08-21 14:09:57 +00:00
|
|
|
/**
|
|
|
|
|
* Add a local or specified stylesheet, with the given media options.
|
|
|
|
|
* Meant primarily for internal use...
|
|
|
|
|
*
|
2010-01-29 21:32:45 +00:00
|
|
|
* @param $style String: URL to the file
|
|
|
|
|
* @param $media String: to specify a media type, 'screen', 'printable', 'handheld' or any.
|
|
|
|
|
* @param $condition String: for IE conditional comments, specifying an IE version
|
|
|
|
|
* @param $dir String: set to 'rtl' or 'ltr' for direction-specific sheets
|
2008-08-21 14:09:57 +00:00
|
|
|
*/
|
2010-05-22 12:18:22 +00:00
|
|
|
public function addStyle( $style, $media = '', $condition = '', $dir = '' ) {
|
2008-08-21 14:09:57 +00:00
|
|
|
$options = array();
|
2009-08-18 21:22:59 +00:00
|
|
|
// Even though we expect the media type to be lowercase, but here we
|
|
|
|
|
// force it to lowercase to be safe.
|
2010-05-22 12:18:22 +00:00
|
|
|
if( $media ) {
|
2008-08-21 14:09:57 +00:00
|
|
|
$options['media'] = $media;
|
2010-05-22 12:18:22 +00:00
|
|
|
}
|
|
|
|
|
if( $condition ) {
|
2008-08-21 14:09:57 +00:00
|
|
|
$options['condition'] = $condition;
|
2010-05-22 12:18:22 +00:00
|
|
|
}
|
|
|
|
|
if( $dir ) {
|
2008-08-21 14:09:57 +00:00
|
|
|
$options['dir'] = $dir;
|
2010-05-22 12:18:22 +00:00
|
|
|
}
|
2008-08-21 14:09:57 +00:00
|
|
|
$this->styles[$style] = $options;
|
|
|
|
|
}
|
2009-07-15 00:55:58 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds inline CSS styles
|
|
|
|
|
* @param $style_css Mixed: inline CSS
|
2011-09-11 21:07:17 +00:00
|
|
|
* @param $flip String: Set to 'flip' to flip the CSS if needed
|
2009-07-15 00:55:58 +00:00
|
|
|
*/
|
2011-09-11 21:07:17 +00:00
|
|
|
public function addInlineStyle( $style_css, $flip = 'noflip' ) {
|
2011-11-21 16:13:21 +00:00
|
|
|
if( $flip === 'flip' && $this->getLanguage()->isRTL() ) {
|
2011-09-04 21:50:02 +00:00
|
|
|
# If wanted, and the interface is right-to-left, flip the CSS
|
|
|
|
|
$style_css = CSSJanus::transform( $style_css, true, false );
|
|
|
|
|
}
|
2011-01-06 16:58:29 +00:00
|
|
|
$this->mInlineStyles .= Html::inlineStyle( $style_css );
|
here it is ... the upload-api, script-server, js2 (javascript phase2) branch merge 1st attempt.
Here is a short overview of changes and associated default configuration variables (most everything is off by default) also see ~soon to be updated~: http://www.mediawiki.org/wiki/Media_Projects_Overview
= Upload Improvements =
==Upload API ==
* Based on the early work of Bryan Tong and others it adds the upload option to the api.
* We rewrite Special:Upload page to include use the new refactoring
* Added in token checks in both the SpecialUpload.php page so avoids DOS / xss copy-by-url JavaScript based cross site POST file submissions
== Copy by URL==
$wgAllowCopyUploads = false;
* http class rewrite includes a new http background download see: includes/HttpFunctions.php
* spins off a php process that calls: maintenance/http_session_download.php
* pushes updates to the session and gives the user a progress bar on http copy uploads from other server progress (using js2 upload interface) (if not using the js2 upload interface it does the request in-place but the download is limited to the php ini timeout time)
== Firefogg ==
* Firefogg enables resumable upload by chunks
* progress indicators and conditional invokation (js2 system)
* and of-course client side transcoding.
= Script Server =
$wgEnableScriptLoader = false;
* off by default if $wgEnableScriptLoader is turned on script files are grouped, gziped, cached etc.
for more info see: http://www.mediawiki.org/wiki/Extension:ScriptLoader
* Includes some early skin js include fixes (skin/script system still lots of love)
* Includes a "javascript class autoloader" this is packaged into mwEmbed so that the mwEmbed library can work in stand alone mode (while retaining localization and script serving) (one such application is the make page for firefogg.org : http://www.firefogg.org/make/index.html )
* The file that contains the autojavascript loading classes is: js2/php/jsAutoloadLocalClasses.php
* One can use this auto class loading dependency system with extensions and add-ons but I need to better document that.
= js2 system / mwEmbed=
$wgEnableJS2system = false
* includes initial rewrite towards more jquery based javascript code
* especially for the Special:Upload page.
* Also the edit page include support for the "add-media-wizard"
* includes dependency loader for javascript that optionally takes advantage of the script-loader
* remote embedding of javascript interfaces (like embedding video, or commons media searching)
* $wgDebugJavaScript = false; .. .this variable lets you always get "always fresh javascript". When used with the script-loader it does not minify the script-loader output.
= mwEmbed =
* Will commit a separate patch to oggHandler that conditionally outputs <video tag> to use the new javascript video player.
** mv_embed player includes: play-head, volume control, remote embedding, oggz-chop support across plugins.
* add-media-wizard adds easy inserts of media to pages (with import)
== jQuery==
* we include a base install of jQuery, jQuery ui and some plugins.
* all the javascript classes are in the scriptloader so its easy to load any set of jquery ui components that you may need using the script-server. You get a callback so you can then execute js with dependencies loaded.
== other stuff ==
there is a bit more code in js2 that pertains to sequence editing, timed text display and basic image editing. We include a base import of pixastic-lib & pixastic-editor... will work with the pixastic developer to try and ensure upstream compatibility on our usage of the library for in-browser photo and sequence manipulation.
2009-07-14 23:52:14 +00:00
|
|
|
}
|
2009-07-15 00:55:58 +00:00
|
|
|
|
2008-08-21 14:09:57 +00:00
|
|
|
/**
|
2012-07-10 12:48:06 +00:00
|
|
|
* Build a set of "<link>" elements for the stylesheets specified in the $this->styles array.
|
2008-08-21 14:09:57 +00:00
|
|
|
* These will be applied to various media & IE conditionals.
|
2011-05-21 19:07:24 +00:00
|
|
|
*
|
|
|
|
|
* @return string
|
2008-08-21 14:09:57 +00:00
|
|
|
*/
|
2011-07-22 10:45:07 +00:00
|
|
|
public function buildCssLinks() {
|
2012-01-04 20:01:29 +00:00
|
|
|
global $wgUseSiteCss, $wgAllowUserCss, $wgAllowUserCssPrefs,
|
|
|
|
|
$wgLang, $wgContLang;
|
2011-07-22 10:45:07 +00:00
|
|
|
|
|
|
|
|
$this->getSkin()->setupSkinUserCss( $this );
|
|
|
|
|
|
2011-01-06 16:58:29 +00:00
|
|
|
// Add ResourceLoader styles
|
2011-02-20 17:24:42 +00:00
|
|
|
// Split the styles into four groups
|
2011-03-05 16:01:25 +00:00
|
|
|
$styles = array( 'other' => array(), 'user' => array(), 'site' => array(), 'private' => array(), 'noscript' => array() );
|
2011-08-13 17:27:35 +00:00
|
|
|
$otherTags = ''; // Tags to append after the normal <link> tags
|
2011-01-06 16:58:29 +00:00
|
|
|
$resourceLoader = $this->getResourceLoader();
|
2011-07-22 10:45:07 +00:00
|
|
|
|
|
|
|
|
$moduleStyles = $this->getModuleStyles();
|
|
|
|
|
|
|
|
|
|
// Per-site custom styles
|
|
|
|
|
if ( $wgUseSiteCss ) {
|
|
|
|
|
$moduleStyles[] = 'site';
|
|
|
|
|
$moduleStyles[] = 'noscript';
|
2013-01-26 18:32:03 +00:00
|
|
|
if( $this->getUser()->isLoggedIn() ) {
|
2011-07-22 10:45:07 +00:00
|
|
|
$moduleStyles[] = 'user.groups';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Per-user custom styles
|
|
|
|
|
if ( $wgAllowUserCss ) {
|
|
|
|
|
if ( $this->getTitle()->isCssSubpage() && $this->userCanPreview() ) {
|
2011-08-13 17:27:35 +00:00
|
|
|
// We're on a preview of a CSS subpage
|
|
|
|
|
// Exclude this page from the user module in case it's in there (bug 26283)
|
|
|
|
|
$otherTags .= $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_STYLES, false,
|
2011-08-17 14:55:06 +00:00
|
|
|
array( 'excludepage' => $this->getTitle()->getPrefixedDBkey() )
|
2011-08-13 17:27:35 +00:00
|
|
|
);
|
2012-04-25 18:24:03 +00:00
|
|
|
|
2011-08-13 17:27:35 +00:00
|
|
|
// Load the previewed CSS
|
2012-01-04 20:01:29 +00:00
|
|
|
// If needed, Janus it first. This is user-supplied CSS, so it's
|
|
|
|
|
// assumed to be right for the content language directionality.
|
|
|
|
|
$previewedCSS = $this->getRequest()->getText( 'wpTextbox1' );
|
|
|
|
|
if ( $wgLang->getDir() !== $wgContLang->getDir() ) {
|
|
|
|
|
$previewedCSS = CSSJanus::transform( $previewedCSS, true, false );
|
|
|
|
|
}
|
|
|
|
|
$otherTags .= Html::inlineStyle( $previewedCSS );
|
2011-07-22 10:45:07 +00:00
|
|
|
} else {
|
2011-08-13 17:27:35 +00:00
|
|
|
// Load the user styles normally
|
2011-07-22 10:45:07 +00:00
|
|
|
$moduleStyles[] = 'user';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Per-user preference styles
|
|
|
|
|
if ( $wgAllowUserCssPrefs ) {
|
2012-02-09 11:04:24 +00:00
|
|
|
$moduleStyles[] = 'user.cssprefs';
|
2011-07-22 10:45:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ( $moduleStyles as $name ) {
|
2011-11-23 13:27:50 +00:00
|
|
|
$module = $resourceLoader->getModule( $name );
|
|
|
|
|
if ( !$module ) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
$group = $module->getGroup();
|
2011-02-20 17:24:42 +00:00
|
|
|
// Modules in groups named "other" or anything different than "user", "site" or "private"
|
|
|
|
|
// will be placed in the "other" group
|
2011-01-06 16:58:29 +00:00
|
|
|
$styles[isset( $styles[$group] ) ? $group : 'other'][] = $name;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-20 17:24:42 +00:00
|
|
|
// We want site, private and user styles to override dynamically added styles from modules, but we want
|
2011-01-06 16:58:29 +00:00
|
|
|
// dynamically added styles to override statically added styles from other modules. So the order
|
2011-02-20 17:24:42 +00:00
|
|
|
// has to be other, dynamic, site, private, user
|
2011-01-06 16:58:29 +00:00
|
|
|
// Add statically added styles for other modules
|
2011-07-22 10:45:07 +00:00
|
|
|
$ret = $this->makeResourceLoaderLink( $styles['other'], ResourceLoaderModule::TYPE_STYLES );
|
2011-01-06 16:58:29 +00:00
|
|
|
// Add normal styles added through addStyle()/addInlineStyle() here
|
|
|
|
|
$ret .= implode( "\n", $this->buildCssLinksArray() ) . $this->mInlineStyles;
|
|
|
|
|
// Add marker tag to mark the place where the client-side loader should inject dynamic styles
|
|
|
|
|
// We use a <meta> tag with a made-up name for this because that's valid HTML
|
2011-03-05 16:01:25 +00:00
|
|
|
$ret .= Html::element( 'meta', array( 'name' => 'ResourceLoaderDynamicStyles', 'content' => '' ) ) . "\n";
|
2011-04-23 19:28:35 +00:00
|
|
|
|
2011-02-20 17:24:42 +00:00
|
|
|
// Add site, private and user styles
|
|
|
|
|
// 'private' at present only contains user.options, so put that before 'user'
|
|
|
|
|
// Any future private modules will likely have a similar user-specific character
|
2011-03-05 16:01:25 +00:00
|
|
|
foreach ( array( 'site', 'noscript', 'private', 'user' ) as $group ) {
|
2011-07-22 10:45:07 +00:00
|
|
|
$ret .= $this->makeResourceLoaderLink( $styles[$group],
|
2011-02-20 17:24:42 +00:00
|
|
|
ResourceLoaderModule::TYPE_STYLES
|
|
|
|
|
);
|
|
|
|
|
}
|
2011-08-31 14:47:08 +00:00
|
|
|
|
2011-08-13 17:27:35 +00:00
|
|
|
// Add stuff in $otherTags (previewed user CSS if applicable)
|
|
|
|
|
$ret .= $otherTags;
|
2011-01-06 16:58:29 +00:00
|
|
|
return $ret;
|
2010-05-24 16:35:23 +00:00
|
|
|
}
|
|
|
|
|
|
2011-09-11 21:07:17 +00:00
|
|
|
/**
|
|
|
|
|
* @return Array
|
|
|
|
|
*/
|
2010-05-24 16:35:23 +00:00
|
|
|
public function buildCssLinksArray() {
|
2008-08-21 14:09:57 +00:00
|
|
|
$links = array();
|
2011-07-22 10:45:07 +00:00
|
|
|
|
|
|
|
|
// Add any extension CSS
|
|
|
|
|
foreach ( $this->mExtStyles as $url ) {
|
|
|
|
|
$this->addStyle( $url );
|
|
|
|
|
}
|
|
|
|
|
$this->mExtStyles = array();
|
|
|
|
|
|
2008-08-21 14:09:57 +00:00
|
|
|
foreach( $this->styles as $file => $options ) {
|
|
|
|
|
$link = $this->styleLink( $file, $options );
|
2010-05-22 12:18:22 +00:00
|
|
|
if( $link ) {
|
2010-05-24 16:35:23 +00:00
|
|
|
$links[$file] = $link;
|
2010-05-22 12:18:22 +00:00
|
|
|
}
|
2008-08-21 14:09:57 +00:00
|
|
|
}
|
2010-05-24 16:35:23 +00:00
|
|
|
return $links;
|
2008-08-21 14:09:57 +00:00
|
|
|
}
|
|
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
|
|
|
|
* Generate \<link\> tags for stylesheets
|
|
|
|
|
*
|
|
|
|
|
* @param $style String: URL to the file
|
|
|
|
|
* @param $options Array: option, can contain 'condition', 'dir', 'media'
|
|
|
|
|
* keys
|
|
|
|
|
* @return String: HTML fragment
|
|
|
|
|
*/
|
2008-08-21 14:09:57 +00:00
|
|
|
protected function styleLink( $style, $options ) {
|
|
|
|
|
if( isset( $options['dir'] ) ) {
|
2011-11-21 16:13:21 +00:00
|
|
|
if( $this->getLanguage()->getDir() != $options['dir'] ) {
|
2008-08-21 14:09:57 +00:00
|
|
|
return '';
|
2010-05-22 12:18:22 +00:00
|
|
|
}
|
2008-08-21 14:09:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( isset( $options['media'] ) ) {
|
2011-01-07 20:22:50 +00:00
|
|
|
$media = self::transformCssMedia( $options['media'] );
|
2008-08-21 14:09:57 +00:00
|
|
|
if( is_null( $media ) ) {
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2009-09-07 00:21:55 +00:00
|
|
|
$media = 'all';
|
2008-08-21 14:09:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( substr( $style, 0, 1 ) == '/' ||
|
|
|
|
|
substr( $style, 0, 5 ) == 'http:' ||
|
|
|
|
|
substr( $style, 0, 6 ) == 'https:' ) {
|
|
|
|
|
$url = $style;
|
|
|
|
|
} else {
|
|
|
|
|
global $wgStylePath, $wgStyleVersion;
|
|
|
|
|
$url = $wgStylePath . '/' . $style . '?' . $wgStyleVersion;
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-11 00:09:24 +00:00
|
|
|
$link = Html::linkedStyle( $url, $media );
|
2008-08-21 14:09:57 +00:00
|
|
|
|
|
|
|
|
if( isset( $options['condition'] ) ) {
|
|
|
|
|
$condition = htmlspecialchars( $options['condition'] );
|
|
|
|
|
$link = "<!--[if $condition]>$link<![endif]-->";
|
|
|
|
|
}
|
|
|
|
|
return $link;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-29 21:32:45 +00:00
|
|
|
/**
|
|
|
|
|
* Transform "media" attribute based on request parameters
|
|
|
|
|
*
|
|
|
|
|
* @param $media String: current value of the "media" attribute
|
2013-01-14 03:26:15 +00:00
|
|
|
* @return String: modified value of the "media" attribute, or null to skip
|
|
|
|
|
* this stylesheet
|
2010-01-29 21:32:45 +00:00
|
|
|
*/
|
2011-01-07 20:22:50 +00:00
|
|
|
public static function transformCssMedia( $media ) {
|
2011-04-03 12:55:48 +00:00
|
|
|
global $wgRequest, $wgHandheldForIPhone;
|
2008-08-21 14:09:57 +00:00
|
|
|
|
2013-01-14 03:26:15 +00:00
|
|
|
// http://www.w3.org/TR/css3-mediaqueries/#syntax
|
|
|
|
|
$screenMediaQueryRegex = '/^(?:only\s+)?screen\b/i';
|
|
|
|
|
|
2008-08-21 14:09:57 +00:00
|
|
|
// Switch in on-screen display for media testing
|
|
|
|
|
$switches = array(
|
|
|
|
|
'printable' => 'print',
|
|
|
|
|
'handheld' => 'handheld',
|
|
|
|
|
);
|
|
|
|
|
foreach( $switches as $switch => $targetMedia ) {
|
2011-04-03 12:55:48 +00:00
|
|
|
if( $wgRequest->getBool( $switch ) ) {
|
2008-08-21 14:09:57 +00:00
|
|
|
if( $media == $targetMedia ) {
|
|
|
|
|
$media = '';
|
2013-01-14 03:26:15 +00:00
|
|
|
} elseif( preg_match( $screenMediaQueryRegex, $media ) === 1 ) {
|
|
|
|
|
// This regex will not attempt to understand a comma-separated media_query_list
|
|
|
|
|
//
|
|
|
|
|
// Example supported values for $media: 'screen', 'only screen', 'screen and (min-width: 982px)' ),
|
|
|
|
|
// Example NOT supported value for $media: '3d-glasses, screen, print and resolution > 90dpi'
|
|
|
|
|
//
|
|
|
|
|
// If it's a print request, we never want any kind of screen styesheets
|
|
|
|
|
// If it's a handheld request (currently the only other choice with a switch),
|
|
|
|
|
// we don't want simple 'screen' but we might want screen queries that
|
|
|
|
|
// have a max-width or something, so we'll pass all others on and let the
|
|
|
|
|
// client do the query.
|
|
|
|
|
if( $targetMedia == 'print' || $media == 'screen' ) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2008-08-21 14:09:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Expand longer media queries as iPhone doesn't grok 'handheld'
|
|
|
|
|
if( $wgHandheldForIPhone ) {
|
|
|
|
|
$mediaAliases = array(
|
|
|
|
|
'screen' => 'screen and (min-device-width: 481px)',
|
|
|
|
|
'handheld' => 'handheld, only screen and (max-device-width: 480px)',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if( isset( $mediaAliases[$media] ) ) {
|
|
|
|
|
$media = $mediaAliases[$media];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $media;
|
|
|
|
|
}
|
|
|
|
|
|
2008-02-18 07:25:35 +00:00
|
|
|
/**
|
|
|
|
|
* Add a wikitext-formatted message to the output.
|
|
|
|
|
* This is equivalent to:
|
|
|
|
|
*
|
2012-07-24 01:04:15 +00:00
|
|
|
* $wgOut->addWikiText( wfMessage( ... )->plain() )
|
2008-02-18 07:25:35 +00:00
|
|
|
*/
|
|
|
|
|
public function addWikiMsg( /*...*/ ) {
|
|
|
|
|
$args = func_get_args();
|
|
|
|
|
$name = array_shift( $args );
|
|
|
|
|
$this->addWikiMsgArray( $name, $args );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add a wikitext-formatted message to the output.
|
|
|
|
|
* Like addWikiMsg() except the parameters are taken as an array
|
|
|
|
|
* instead of a variable argument list.
|
|
|
|
|
*
|
2011-05-21 19:07:24 +00:00
|
|
|
* @param $name string
|
|
|
|
|
* @param $args array
|
2008-02-18 07:25:35 +00:00
|
|
|
*/
|
2011-10-23 08:13:52 +00:00
|
|
|
public function addWikiMsgArray( $name, $args ) {
|
2012-03-08 20:06:49 +00:00
|
|
|
$this->addHTML( $this->msg( $name, $args )->parseAsBlock() );
|
2008-02-18 07:25:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2008-04-14 07:45:50 +00:00
|
|
|
* This function takes a number of message/argument specifications, wraps them in
|
2008-02-18 07:25:35 +00:00
|
|
|
* some overall structure, and then parses the result and adds it to the output.
|
|
|
|
|
*
|
2008-04-14 07:45:50 +00:00
|
|
|
* In the $wrap, $1 is replaced with the first message, $2 with the second, and so
|
|
|
|
|
* on. The subsequent arguments may either be strings, in which case they are the
|
2009-05-19 23:27:53 +00:00
|
|
|
* message names, or arrays, in which case the first element is the message name,
|
2008-02-18 07:25:35 +00:00
|
|
|
* and subsequent elements are the parameters to that message.
|
|
|
|
|
*
|
2008-04-18 06:31:37 +00:00
|
|
|
* Don't use this for messages that are not in users interface language.
|
|
|
|
|
*
|
2008-02-18 07:25:35 +00:00
|
|
|
* For example:
|
|
|
|
|
*
|
2010-05-28 21:22:45 +00:00
|
|
|
* $wgOut->wrapWikiMsg( "<div class='error'>\n$1\n</div>", 'some-error' );
|
2008-04-14 07:45:50 +00:00
|
|
|
*
|
2008-02-18 07:25:35 +00:00
|
|
|
* Is equivalent to:
|
|
|
|
|
*
|
2012-09-03 08:03:42 +00:00
|
|
|
* $wgOut->addWikiText( "<div class='error'>\n" . wfMessage( 'some-error' )->plain() . "\n</div>" );
|
2010-01-14 17:14:49 +00:00
|
|
|
*
|
|
|
|
|
* The newline after opening div is needed in some wikitext. See bug 19226.
|
2011-05-21 19:07:24 +00:00
|
|
|
*
|
|
|
|
|
* @param $wrap string
|
2008-02-18 07:25:35 +00:00
|
|
|
*/
|
|
|
|
|
public function wrapWikiMsg( $wrap /*, ...*/ ) {
|
|
|
|
|
$msgSpecs = func_get_args();
|
|
|
|
|
array_shift( $msgSpecs );
|
|
|
|
|
$msgSpecs = array_values( $msgSpecs );
|
|
|
|
|
$s = $wrap;
|
|
|
|
|
foreach ( $msgSpecs as $n => $spec ) {
|
|
|
|
|
if ( is_array( $spec ) ) {
|
|
|
|
|
$args = $spec;
|
|
|
|
|
$name = array_shift( $args );
|
|
|
|
|
if ( isset( $args['options'] ) ) {
|
|
|
|
|
unset( $args['options'] );
|
2012-09-03 10:18:23 +00:00
|
|
|
wfDeprecated(
|
|
|
|
|
'Adding "options" to ' . __METHOD__ . ' is no longer supported',
|
|
|
|
|
'1.20'
|
|
|
|
|
);
|
2008-02-18 07:25:35 +00:00
|
|
|
}
|
2013-02-03 20:05:24 +00:00
|
|
|
} else {
|
2008-02-18 07:25:35 +00:00
|
|
|
$args = array();
|
|
|
|
|
$name = $spec;
|
|
|
|
|
}
|
2012-09-03 19:38:59 +00:00
|
|
|
$s = str_replace( '$' . ( $n + 1 ), $this->msg( $name, $args )->plain(), $s );
|
2008-02-18 07:25:35 +00:00
|
|
|
}
|
2011-09-11 21:07:17 +00:00
|
|
|
$this->addWikiText( $s );
|
2008-02-18 07:25:35 +00:00
|
|
|
}
|
2010-01-23 20:11:42 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Include jQuery core. Use this to avoid loading it multiple times
|
2010-05-22 11:47:56 +00:00
|
|
|
* before we get a usable script loader.
|
2010-01-27 04:17:49 +00:00
|
|
|
*
|
2010-01-29 21:32:45 +00:00
|
|
|
* @param $modules Array: list of jQuery modules which should be loaded
|
|
|
|
|
* @return Array: the list of modules which were not loaded.
|
2010-02-24 16:21:52 +00:00
|
|
|
* @since 1.16
|
2011-03-12 18:14:33 +00:00
|
|
|
* @deprecated since 1.17
|
2010-01-23 20:11:42 +00:00
|
|
|
*/
|
2010-01-27 04:17:49 +00:00
|
|
|
public function includeJQuery( $modules = array() ) {
|
2010-09-04 04:00:09 +00:00
|
|
|
return array();
|
2010-01-23 20:11:42 +00:00
|
|
|
}
|
|
|
|
|
|
2007-08-16 07:05:38 +00:00
|
|
|
}
|