Extension:AdvancedSkinSystem/Download
From MediaWiki.org
Contents |
[edit] AdvancedSkinSystem.php
<?php if (!defined('MEDIAWIKI')) die(); /** * A Special Page extension to dynamically generate skins from Wikipages and cache them * for better performance, runnable by users with updateskins righs * * @ingroup Extensions * * @author Jan M. Simons <jamasi at piratenpartei.de> * @copyright Copyright © 2007, Jan M. Simons * @license http://www.gnu.org/licenses/agpl.html GNU Affero General Public License 3.0 or later * loosely based on RenameUser Extension: * Copyright © 2005, Ævar Arnfjörð Bjarmason * license http://www.gnu.org/licenses/gpl.html GNU General Public License 2.0 or later */ # Configurationfile file require_once( 'ASS_Settings.php' ); # Internationalisation file require_once( 'ASS.i18n.php' ); # Fixes to better display raw HTML, PHP, ... in the ASS namespaces require_once( 'ASS_DisplayFixes.php' ); # setup restrictions and namespaces // restrict edits in the ASS namespaces, as one can use ASS to get malicious code run by the server $wgAvailableRights[] = 'updateskins'; $wgGroupPermissions['*']['updateskins'] = false; $wgGroupPermissions['bureaucrat']['updateskins'] = true; $wgGroupPermissions['sysop']['updateskins'] = true; $wgGroupPermissions['updateskins']['updateskins'] = true; // you can enforce a four eye principle with this splitting of rights $wgAvailableRights[] = 'editskins'; $wgGroupPermissions['*']['editskins'] = false; $wgGroupPermissions['bureaucrat']['editskins'] = true; $wgGroupPermissions['sysop']['editskins'] = true; $wgGroupPermissions['editskins']['editskins'] = true; # register namespaces $wgExtraNamespaces[$wgASSTemplateNameSpaceNumber] = $wgASSTemplateNameSpaceName; $wgExtraNamespaces[$wgASSTemplateNameSpaceNumber + 1] = $wgASSTemplateNameSpaceName. "_talk"; $wgNamespaceProtection[$wgASSTemplateNameSpaceNumber] = array( 'editskins' ); $wgExtraNamespaces[$wgASSFillerNameSpaceNumber] = $wgASSFillerNameSpaceName; $wgExtraNamespaces[$wgASSFillerNameSpaceNumber + 1] = $wgASSFillerNameSpaceName ."_talk"; $wgNamespaceProtection[$wgASSFillerNameSpaceNumber] = array( 'editskins' ); # register specialpage $wgExtensionFunctions[] = 'wfSpecialUpdateSkins'; $wgExtensionCredits['specialpage'][] = array( 'name' => 'UpdateSkins', 'author' => 'Jan M. Simons', 'version' => '0.9.0', 'url' => 'http://www.mediawiki.org/wiki/Extension:AdvancedSkinSystem', 'description' => 'UpdateSkins page (from the Advanced Skin System)', ); # Add a new log type global $wgLogTypes, $wgLogNames, $wgLogHeaders, $wgLogActions; $wgLogTypes[] = 'updateskins'; $wgLogNames['updateskins'] = 'updateskinslogpage'; $wgLogHeaders['updateskins'] = 'updateskinslogpagetext'; $wgLogActions['updateskins/updateskins'] = 'updateskinslogentry'; # Register the special page $wgAutoloadClasses['UpdateSkins'] = dirname(__FILE__) . '/SpecialUpdateSkins_body.php'; $wgSpecialPages['UpdateSkins'] = 'UpdateSkins'; function wfSpecialUpdateSkins() { # Add messages global $wgMessageCache, $wgASSMessages; foreach( $wgASSMessages as $key => $value ) { $wgMessageCache->addMessages( $wgASSMessages[$key], $key ); } }
[edit] SpecialUpdateSkins_body.php
<?php if (!defined('MEDIAWIKI')) die(); class UpdateSkins extends SpecialPage { function UpdateSkins() { SpecialPage::SpecialPage('UpdateSkins', 'updateskins'); } function execute() { global $wgOut, $wgUser, $wgTitle, $wgRequest, $wgContLang, $wgLang; global $wgVersion, $wgMaxNameChars, $wgCapitalLinks; global $wgASSTemplateNameSpaceNumber; $fname = 'UpdateSkins::execute'; $this->setHeaders(); if ( !$wgUser->isAllowed( 'updateskins' ) ) { $wgOut->permissionRequired( 'updateskins' ); return; } if ( wfReadOnly() ) { $wgOut->readOnlyPage(); return; } if ( version_compare( $wgVersion, '1.10.0', '<' ) ) { $wgOut->versionRequired( '1.10.0' ); return; } $showBlockLog = $wgRequest->getBool( 'submit-showBlockLog' ); $token = $wgUser->editToken(); $dbr = wfGetDB( DB_SLAVE ); $res = $dbr->select( 'page', array('page_title','page_id'), array('page_namespace' => $wgASSTemplateNameSpaceNumber), $fname); $wgOut->addHTML( Xml::openElement( 'form', array( 'method' => 'post', 'action' => $action, 'id' => 'updateskins' ) ) . Xml::openElement( 'table' ) . "<tr> <td align='left'>" . Xml::label( wfMsg( 'updateskinstemplates' ).":", 'skintempltename' ) . "</td> </tr>" ); while ( $row = $dbr->fetchObject( $res ) ) { $is_checked[$row->page_id] = true; if ( $wgRequest->wasPosted() && ! $wgRequest->getCheck( 'dopage-'. $row->page_id ) ) { $is_checked[$row->page_id] = false; } $wgOut->addHTML( "<tr> <td align='left'>" . Xml::checkLabel( $row->page_title, 'dopage-'. $row->page_id, 'dopage-'. $row->page_id, $is_checked[$row->page_id] ) . "</td> </tr>" ); if ( $wgRequest->wasPosted() && $is_checked[$row->page_id] ) { # generate skin $wgOut->addHTML( "<tr><td align='left'>" . $this->generateSkinFromTemplate( $row->page_id ) . "</td></tr>" ); } } $dbr->freeResult( $res ); $wgOut->addHTML( Xml::closeElement( 'table' ) . "<br />" . Xml::submitButton( wfMsg( 'updateskinssubmit' ), array( 'name' => 'submit', 'id' => 'submit' ) ) . Xml::hidden( 'token', $token ) . Xml::closeElement( 'form' ) . "\n" ); } function generateSkinFromTemplate( $skin_id ) { global $wgUser, $wgASSOutputDir, $wgASSdefaultSkin, $wgASSTemplateNameSpaceNumber, $wgASSParsedFiles, $wgParser; $ASSTemplate = new Article(Title::newFromID($skin_id)); // Check if the article to parse belongs to the correct namespace. // This might seem redundant, but it's important for security as // one would be able to circomvent namespace protections otherwise. if ($ASSTemplate->getTitle()->getNamespace() != $wgASSTemplateNameSpaceNumber) die($skin_id." is not a valid skin template ID."); // pre-parse article $ASScontent = $ASSTemplate->fetchContent(0,false,false); $ASSparsedcontent = $this->parseTemplate( $ASScontent ); $ASSfilename = $wgASSOutputDir."/".$ASSTemplate->getTitle()->getDBkey().".php"; // echo $ASSfilename; file_put_contents ( $ASSfilename, $ASSparsedcontent ); $flags = explode("\n", $this->getTaggedText( "<skinflags>", "</skinflags>", $ASScontent)); foreach ($flags as $flag) { switch (strtolower(trim($flag, " "))) { case "present_to_user": //creatre a skin-file based on the template. $this->PlaceSkinTemplate($ASSTemplate->getTitle()->getDBkey()); break; //case "": // break; } } $this->PlaceSkinTemplate("standard"); $wgASSParsedFiles = ""; } function parseTemplate( $TemplateContent ) { global $wgUser, $wgASSOutputPath, $wgASSOutputDir, $wgTitle, $wgParser, $wgASSParsedFiles, $wgASSDebugFile; //file_put_contents ( $wgASSDebugFile, "################################################\n", FILE_APPEND); //file_put_contents ( $wgASSDebugFile, "################################################\n", FILE_APPEND); //file_put_contents ( $wgASSDebugFile, "debug: parsetemplate ".$TemplateContent."\n-----------------------\n".$wgASSParsedFiles."\n\n", FILE_APPEND); //file_put_contents ( $wgASSDebugFile, "------------------------------------------------\n", FILE_APPEND); // create helper-files $externals = explode( "\n", $this->getTaggedText( "<external>", "</external>", $TemplateContent ) ); foreach ($externals as $link) { $repl= explode( "==", $link ); if ( trim( $repl[0], " " ) ) { $token[] = trim($repl[0], " "); $repl[1] = trim(trim(trim($repl[1]," "),"]]"),"[["); if ( stripos($repl[1], "media:") === false && stripos($repl[1], "image:") === false ) { // copy external file from article to folder $ASSLinkedArticle = new Article(Title::newFromText($repl[1])); $ASSFcontent = $ASSLinkedArticle->fetchContent(0,false,false); $ASSFilename = $wgASSOutputDir."/".$ASSLinkedArticle->getTitle()->getDBkey(); // Check if it has already been parsed, skip if it has been parsed if (strpos( $wgASSParsedFiles, "|*".$repl[1]."*" ) === false ) { $ASSFcontent = $this->parseTemplate( $ASSFcontent ); file_put_contents ( $ASSFilename, $ASSFcontent ); // add parsed file to to list to skip parsing it again. $wgASSParsedFiles.= "|*".$repl[1]."*"; } //echo $ASSFilename."<br>"; $replacewith[] = str_replace($wgASSOutputDir, $wgASSOutputPath, $ASSFilename); } else { $imageTitle = Title::makeTitleSafe("Image", $repl[1]); if($imageTitle == NULL) { echo "<!-- WarnImageNotFound: $repl[1] -->"; } $img = Image::newFromTitle($imageTitle); if($img->exists() != true) { echo "<!-- WarnImageNotFound: $repl[1] -->"; } $replacewith[] = $img->getViewURL(false); } } } // get include-files $internals = explode("\n", $this->getTaggedText( "<internal>", "</internal>", $TemplateContent)); foreach ($internals as $link) { $repl= explode( "==", $link ); if (trim($repl[0], " ")) { $token[] = trim($repl[0], " "); // copy external content to include into array $ASSLinkedArticle = new Article(Title::newFromText(trim(trim($repl[1],"]]"),"[["))); $ASSFcontent = $ASSLinkedArticle->fetchContent(0,false,false); $replacewith[] = $this->parseTemplate( $ASSFcontent ); } } // get dynamic content to be included $dynamic = explode("\n", $this->getTaggedText( "<dynamic>", "</dynamic>", $TemplateContent)); foreach ($dynamic as $link) { $repl= explode( "==", $link ); if (trim($repl[0], " ")) { $token[] = trim($repl[0], " "); // copy external content to include into array $DynBit = file_get_contents (dirname(__FILE__)."/template/dynamic.php" ); $DynBit = str_replace ("___TO_REPLACE___", trim(trim($repl[1],"]]"),"[["), $DynBit); $replacewith[] = $DynBit; } } // get wikibits (=(rendered) wikitext to be included) $wikibits = explode("\n", $this->getTaggedText( "<wikibits>", "</wikibits>", $TemplateContent)); foreach ($wikibits as $link) { $repl= explode( "==", $link ); if (trim($repl[0], " ")) { $token[] = trim($repl[0], " "); // fetch article content $boxarticle = new Article(Title::newFromText(trim(trim($repl[1],"]]"),"[["))); $WikiBit = $boxarticle->fetchContent(0,false,false); if (strpos($WikiBit, '__RAW__') === false) { $parseoptions = ParserOptions::newFromUser($wgUser); $parsedoutput = $wgParser->parse(preg_replace('/^\\s+/m','',$WikiBit),$wgTitle,$parseoptions,true,true); $WikiBit = $parsedoutput->getText(); } else { $WikiBit = str_replace('__RAW__','',$WikiBit); } $replacewith[] = $WikiBit; } } $stripedcontent = $this->getTaggedText( "<skintemplate>", "</skintemplate>", $TemplateContent); if (trim($stripedcontent, " ") == "") $stripedcontent = $this->getTaggedText( "<skinfiller>", "</skinfiller>", $TemplateContent); if (trim($stripedcontent, " ") == "") $stripedcontent = $TemplateContent; $parsedcontent = str_replace ($token, $replacewith, $stripedcontent); //file_put_contents ( $wgASSDebugFile, "return: ".$parsedcontent."\n", FILE_APPEND); return $parsedcontent; } function PlaceSkinTemplate( $TemplateName ) { global $wgStyleDirectory; if (!copy(dirname(__FILE__)."/template/advancedskin.deps.php", $wgStyleDirectory."/".$TemplateName.".deps.php")) { return ("failed to copy file...<br>\n"); } $skintemplate = file_get_contents (dirname(__FILE__)."/template/advancedskin.php" ); $skinfile = str_replace ("___TO_REPLACE___", $TemplateName, $skintemplate); return file_put_contents ( $wgStyleDirectory."/".$TemplateName.".php", $skinfile ); } function getTaggedText ( $StartTag, $EndTag, $Text ) { // get start position of the content of the tag $start = strpos( $Text, $StartTag ); if ($start === false) $start = -1; else $start += strlen($StartTag); // get end position of the content of the tag $end = strpos( $Text, $EndTag ); if ($end === false) $end = -1; // if tag is found, return text between if (($start >= 0) && ($end > 0) && ($end > $start)) { return substr( $Text, $start, $end-$start ); } else { return ""; } } function showLogExtract( $username, $type, &$out ) { global $wgOut; # Show relevant lines from the logs: $wgOut->addHtml( "<h2>" . htmlspecialchars( LogPage::logName( $type ) ) . "</h2>\n" ); $logViewer = new LogViewer( new LogReader( new FauxRequest( array( 'page' => $username->getPrefixedText(), 'type' => $type ) ) ) ); $logViewer->showList( $out ); } }
[edit] ASS.i18n.php
<?php /** * Internationalisation file for UpdateSkins extension. * * @ingroup Extensions */ $wgASSMessages = array(); $wgASSMessages['en'] = array( 'updateskins' => 'Update dynamic skins', 'updateskinstemplates' => 'skin templates', 'updateskinssubmit' => 'Submit', 'updateskinslogpage' => 'Skin Update log', 'updateskinslogpagetext' => 'This is a log of (re)generation events for dynamic skins', 'updateskinslogentry' => '', # Don't translate this 'updateskinslog' => 'Generated SkinClass "$1" from Pages: "$2"', ); $wgASSMessages['de'] = array( 'updateskins' => 'Dynamische Skins aktualisieren', 'updateskinstemplates' => 'Skin-Vorlagen', 'updateskinssubmit' => 'Erneuern', 'updateskinslogpage' => 'Aktualisierungs-Logbug für Skin-ÃÂnderungen', 'updateskinslogpagetext' => 'In diesem Logbuch werden die Neuerstellungen von dynamischen Skins protokolliert.', 'updateskinslog' => 'Skin-Klasse "$1" wurde erzeugt aus den Seiten: "$2"', );
[edit] ASS_Settings.php
<?php $wgASSDebug = false; // Debug log on if set to true $wgASSTemplateNameSpaceNumber = 110; // Number of the namespace for dynamic skin templates $wgASSTemplateNameSpaceName = "Skin"; // Name of the namespace for dynamic skin templates $wgASSFillerNameSpaceNumber = 112; // Number of the namespace for dynamic skin fillers $wgASSFillerNameSpaceName = "Filler"; // Name of the namespace for dynamic skin fillers $wgASSCategoryPrefix = "Skin:"; // Name of the category-prefix for dynamic skin selection $wgASSOutputName = "advancedskin"; // Name of the directory for dynamic skin files into $wgASSOutputPath = $wgStylePath."/".$wgASSOutputName; // Path to place dynamic skin files into $wgASSOutputDir = $IP."/skins/".$wgASSOutputName; // Directory to place dynamic skin files into $wgASSDebugFile = $IP."/extensions/AdvancedSkinSystem/debug.txt"; // Path to the debug log
[edit] ASS_DisplayFixes.php
<?php if (!defined('MEDIAWIKI')) die(); /** * A Special Page extension to dynamically generate skins from Wikipages and cache them * for better performance, runnable by users with updateskins righs * * @ingroup Extensions * * @author Jan M. Simons <jamasi at piratenpartei.de> * @copyright Copyright © 2007, Jan M. Simons * @license http://www.gnu.org/licenses/agpl.html GNU Affero General Public License 3.0 or later * loosely based on RenameUser extesnsion: * Copyright © 2005, Ævar Arnfjörð Bjarmason * license http://www.gnu.org/licenses/gpl.html GNU General Public License 2.0 or later * and Poem extension: * Copyright © 2005 Nikola Smolenski <smolensk@eunet.yu>, Brion Vibber, Steve Sanbeg */ # configurationfile file require_once( 'ASS_Settings.php' ); # Internationalisation file require_once( 'ASS.i18n.php' ); $wgExtensionFunctions[] = 'wfAdvancedSkinSystem'; $wgExtensionCredits['parserhook'][] = array( 'name' => 'DisplayFixes', 'author' => 'Jan M. Simons', 'version' => '0.9.0', 'url' => 'http://www.mediawiki.org/wiki/Extension:AdvancedSkinSystem', 'description' => 'Displays pages of the template systems namespaces as sourcecode (part of the Advanced Skin System)', ); function wfAdvancedSkinSystem() { # Add messages global $wgMessageCache, $wgASSMessages; foreach( $wgASSMessages as $key => $value ) { $wgMessageCache->addMessages( $wgASSMessages[$key], $key ); } $GLOBALS['wgParser']->setHook("skintemplate","ASS_EscapeCode"); $GLOBALS['wgParser']->setHook("skinfiller","ASS_EscapeCode"); //$GLOBALS['wgParser']->setHook("internal","ATS_EscapeCode"); //$GLOBALS['wgParser']->setHook("external","ATS_EscapeCode"); } function ASS_EscapeCode( $in, $param=array(), $parser=null ) { global $wgASSTemplateNameSpaceNumber, $wgASSFillerNameSpaceNumber; global $wgTitle; //echo "blobbb".$wgTitle->getNamespace()."<br /> "; if (($wgTitle->getNamespace() == $wgASSTemplateNameSpaceNumber) || ($wgTitle->getNamespace() == $wgASSFillerNameSpaceNumber)) { if (method_exists($parser, 'recursiveTagParse')) { //new methods in 1.8 allow nesting <nowiki> in <poem>. $tag = $parser->insertStripItem("<br />", $parser->mStripState); $text = "<nowiki>".preg_replace( array("/</","/>/","/^\n/","/\n$/D","/\n/"), array("<",">","", "", "$tag\n"), $in )."</nowiki>"; $text = $parser->recursiveTagParse($text); } else { $text = preg_replace( array("/</","/>/","/^\n/","/\n$/D","/\n/", "/^( +)/me"), array("<",">","", "", "$tag\n","str_replace(' ',' ','\\1')"), $in ); $ret = $parser->parse( $text, $parser->getTitle(), $parser->getOptions(), // We begin at line start true, // Important, otherwise $this->clearState() // would get run every time <ref> or // <references> is called, fucking the whole // thing up. false ); $text = $ret->getText(); } } else { $text = $in; } global $wgVersion; if( version_compare( $wgVersion, "1.7alpha" ) >= 0 ) { // Pass HTML attributes through to the output. $attribs = Sanitizer::validateTagAttributes( $param, 'div' ); } else { // Can't guarantee safety on 1.6 or older. $attribs = array(); } // Wrap output in a <div> with "code" class. if( isset( $attribs['class'] ) ) { $attribs['class'] = 'code ' . $attribs['class']; } else { $attribs['class'] = 'code'; } return wfOpenElement( 'div', $attribs ) . "\n" . trim( $text ) . "\n</div>"; }
[edit] template/advancedskin.deps.php
<?php // This file exists to ensure that base classes are preloaded before // MonoBook.php is compiled, working around a bug in the APC opcode // cache on PHP 5, where cached code can break if the include order // changed on a subsequent page view. // see http://mail.wikipedia.org/pipermail/wikitech-l/2006-January/033660.html require_once('includes/SkinTemplate.php');
[edit] template/advancedskin.php
<?php /** * Advanced Skin selection skin * * @todo document * @package MediaWiki * @subpackage Skins */ if( !defined( 'MEDIAWIKI' ) ) die( 1 ); /** */ require_once('includes/SkinTemplate.php'); /** * Inherit main code from SkinTemplate, set the CSS and template filter. * @todo document * @package MediaWiki * @subpackage Skins */ class Skin___TO_REPLACE___ extends SkinTemplate { function initPage( &$out ) { SkinTemplate::initPage( $out ); $this->skinname = '___TO_REPLACE___'; $this->stylename = '___TO_REPLACE___'; $this->template = '___TO_REPLACE___Template'; } } /** * @todo document * @package MediaWiki * @subpackage Skins */ class ___TO_REPLACE___Template extends QuickTemplate { function execute() { global $wgASSCategoryPrefix, $wgASSOutputDir, $wgDefaultSkin; global $wgUser, $wgTitle, $wgValidSkinNames, $wgStyleDirectory; $skin = $wgUser->getSkin(); // Suppress warnings to prevent notices about missing indexes in $this->data wfSuppressWarnings(); // categories override skinselection from namespace $WebsiteCategory = $this->data['catlinks']; $match = strrpos($WebsiteCategory, $wgASSCategoryPrefix); if ($match === false) { // it's a normal page, use normal skin if it exists $MySkinfileClass = $this->data['stylename']; // check for namespace mappings $Mappings = wfMsg('ASSNamespace2Skin'); if ($Mappings) { $Mappings = explode("\n", $Mappings); $MyNS = $wgTitle->getNsText(); foreach ($Mappings as $Map) { // remove spaces prefix Marker $Map = "*".trim($Map); #echo "<!-- ".$Map." / ".$MyNS." -->\n"; // check for occurance of the namespace of the page in mappings $match = strpos($Map, "*".$MyNS."="); if (is_numeric($match)) { $match = strrpos($Map, "="); $MySkinfileClass = substr($Map, $match + 1); break; } } } } else { // get skin from category $end = strpos($WebsiteCategory, "</a>", $match); $match += strlen($wgASSCategoryPrefix); $SkinToUse = substr($WebsiteCategory, $match, $end-$match); $MySkinfileClass = $SkinToUse; } $MySkinfileClass = $wgASSOutputDir. "/" .$MySkinfileClass. ".php"; #echo "<!-- ".$MySkinfileClass." -->\n"; // if skin does not exist, use the default skin. if (file_exists($MySkinfileClass) == false) { $NormalSkinfile=$wgStyleDirectory."/".$wgValidSkinNames[basename($MySkinfileClass,'.php')].".php"; #echo "<!-- check: ".$NormalSkinfile." -->\n"; if (file_exists($NormalSkinfile) == false) { #echo "<!-- ".$MySkinfileClass." not found falling back to default -->\n"; $MySkinfileClass = $wgStyleDirectory. "/" .$wgValidSkinNames[$wgDefaultSkin]. ".php"; #echo "<!-- default: ".$MySkinfileClass." -->\n"; } else { #echo "<!-- found: ".$NormalSkinfile." -->\n"; $MySkinfileClass = $NormalSkinfile; #echo "<!-- will call: ".$MySkinfileClass." -->\n"; } } { include($MySkinfileClass); } #echo "<!-- using ".$MySkinfileClass." -->\n"; wfRestoreWarnings(); } }
[edit] template/dynamic.php
<?php global $wgUser,$wgTitle,$wgParser; $boxarticle = new Article(Title::newFromText('___TO_REPLACE___')); $content = $boxarticle->fetchContent(0,false,false); $parseoptions = ParserOptions::newFromUser($wgUser); $parsedoutput = $wgParser->parse(preg_replace('/^\\s+/m','',$content),$wgTitle,$parseoptions,true,true); $content = $parsedoutput->getText(); echo $content; ?>
