Index: trunk/extensions/ExtensionManagement/ExtensionManagement.php |
— | — | @@ -0,0 +1,77 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Initialization file for the ExtensionManagement extension. |
| 6 | + * Extension documentation: http://www.mediawiki.org/wiki/Extension:ExtensionManagement |
| 7 | + * |
| 8 | + * @file extensionManagement.php |
| 9 | + * @ingroup ExtensionManagement |
| 10 | + */ |
| 11 | + |
| 12 | +// Alert the user that this is not a valid entry point to MediaWiki if they try to access the special pages file directly. |
| 13 | +if (!defined('MEDIAWIKI')) { |
| 14 | + echo <<<EOT |
| 15 | +To install this extension, put the following line in LocalSettings.php: |
| 16 | +require_once( "\$IP/extensions/ExtensionManagement/ExtensionManagement.php" ); |
| 17 | +EOT; |
| 18 | + exit( 1 ); |
| 19 | +} |
| 20 | + |
| 21 | +$wgExtensionCredits['specialpage'][] = array( |
| 22 | + 'path' => __FILE__, |
| 23 | + 'name' => 'ExtensionManagement', |
| 24 | + 'author' => array('aigerim'), |
| 25 | + 'url' => 'http://www.mediawiki.org/wiki/Extension:ExtensionManagement', |
| 26 | + 'description' => 'Extension for displaying installed extension information.', |
| 27 | + 'descriptionmsg' => 'extensionmanagement-desc', |
| 28 | +); |
| 29 | + |
| 30 | +$dir = dirname(__FILE__) . '/'; |
| 31 | + |
| 32 | +// Register the internalization and aliasing files |
| 33 | +$wgExtensionMessagesFiles['ExtensionManagement'] = $dir . 'ExtensionManagement.i18n.php'; |
| 34 | +$wgExtensionAliasesFiles['ExtensionManagement'] = $dir . 'ExtensionManagement.alias.php'; |
| 35 | + |
| 36 | +// Load classes |
| 37 | +$wgAutoloadClasses['ExtensionManagement'] = $dir . 'ExtensionManagement.php'; |
| 38 | +$wgAutoloadClasses['ExtensionManagementPage'] = $dir . 'ExtensionManagement_body.php'; |
| 39 | +$wgAutoloadClasses['EMSubversion'] = $dir . 'includes/EMSubversion.php'; |
| 40 | + |
| 41 | +// Special pages |
| 42 | +$wgSpecialPages['ExtensionManagement'] = 'SpecialExtensionManagement'; |
| 43 | +$wgAutoloadClasses['SpecialExtensionManagement'] = $dir . 'specials/SpecialExtensionManagement.php'; |
| 44 | +//$wgSpecialPageGroups['ExtensionManagement'] = 'other'; |
| 45 | + |
| 46 | +// API modules |
| 47 | + |
| 48 | +// Hook registration |
| 49 | +$wgHooks['LoadExtensionSchemaUpdates'][] = 'efExtensionMgmtSchemaUpdate'; |
| 50 | + |
| 51 | +/** |
| 52 | + * LoadExtensionSchemaUpdates hook |
| 53 | + * |
| 54 | + */ |
| 55 | +function efExtensionMgmtSchemaUpdate( $updater = null ) { |
| 56 | + if ( $updater === null ) { |
| 57 | + global $wgExtNewTables; |
| 58 | + $wgExtNewTables[] = array( |
| 59 | + 'extensionmanagement', dirname( __FILE__ ) . '/extensionmanagement.sql' |
| 60 | + ); |
| 61 | + $wgExtNewTables[] = array( |
| 62 | + 'extensionmanagement_versions', dirname( __FILE__ ) . '/extensionmanagement.sql' |
| 63 | + ); |
| 64 | + $wgExtNewTables[] = array( |
| 65 | + 'extensionmanagement_mwreleases', dirname( __FILE__ ) . '/extensionmanagement.sql' |
| 66 | + ); |
| 67 | + } else { |
| 68 | + $updater->addExtensionUpdate( array( 'addTable', 'extensionmanagement', |
| 69 | + dirname( __FILE__ ) . '/extensionmanagement.sql', true ) ); |
| 70 | + $updater->addExtensionUpdate( array( 'addTable', 'extensionmanagement_versions', |
| 71 | + dirname( __FILE__ ) . '/extensionmanagement.sql', true ) ); |
| 72 | + $updater->addExtensionUpdate( array( 'addTable', 'extensionmanagement_mwreleases', |
| 73 | + dirname( __FILE__ ) . '/extensionmanagement.sql', true ) ); |
| 74 | + } |
| 75 | + return true; |
| 76 | +} |
| 77 | + |
| 78 | +?> |
Index: trunk/extensions/ExtensionManagement/specials/SpecialExtensionManagement.php |
— | — | @@ -0,0 +1,213 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * A special page that displays installed extensions. |
| 6 | + * Based on Special:Version. |
| 7 | + * |
| 8 | + * @ingroup ExtensionManagement |
| 9 | + * @ingroup SpecialPage |
| 10 | + */ |
| 11 | + |
| 12 | +class SpecialExtensionManagement extends SpecialPage { |
| 13 | + |
| 14 | + private $firstExtOpened = true; |
| 15 | + |
| 16 | + static $viewvcUrls = array( |
| 17 | + 'svn+ssh://svn.wikimedia.org/svnroot/mediawiki' => 'http://svn.wikimedia.org/viewvc/mediawiki', |
| 18 | + 'http://svn.wikimedia.org/svnroot/mediawiki' => 'http://svn.wikimedia.org/viewvc/mediawiki', |
| 19 | + # Doesn't work at the time of writing but maybe some day: |
| 20 | + 'https://svn.wikimedia.org/viewvc/mediawiki' => 'http://svn.wikimedia.org/viewvc/mediawiki', |
| 21 | + ); |
| 22 | + |
| 23 | + function __construct() { |
| 24 | + parent::__construct( 'ExtensionManagement' ); |
| 25 | + } |
| 26 | + |
| 27 | + |
| 28 | + function execute( $par ) { |
| 29 | + global $wgOut, $wgMessageCache, $wgContLang; |
| 30 | + $wgMessageCache->loadAllMessages(); |
| 31 | + |
| 32 | + $this->setHeaders(); |
| 33 | + $this->outputHeader(); |
| 34 | + |
| 35 | + $wgOut->addHTML( Xml::openElement( 'div', |
| 36 | + array( 'dir' => $wgContLang->getDir() ) ) ); |
| 37 | + $wgOut->addWikiMsgArray( 'extensionmanagement-page-explanation', '' ); |
| 38 | + |
| 39 | + $text = |
| 40 | + $this->displayExtensions(); |
| 41 | + |
| 42 | + $wgOut->addWikiText( $text ); |
| 43 | + $wgOut->addHTML( '</div>' ); |
| 44 | + } |
| 45 | + |
| 46 | + |
| 47 | + function displayExtensions() { |
| 48 | + global $wgOut, $wgExtensionCredits; |
| 49 | + |
| 50 | + $extensionAmount = 0; |
| 51 | + |
| 52 | + $extensionTypes = array( |
| 53 | + 'specialpage' => wfMsg( 'version-specialpages' ), |
| 54 | + 'parserhook' => wfMsg( 'version-parserhooks' ), |
| 55 | + 'variable' => wfMsg( 'version-variables' ), |
| 56 | + 'media' => wfMsg( 'version-mediahandlers' ), |
| 57 | + 'other' => wfMsg( 'version-other' ), |
| 58 | + ); |
| 59 | + |
| 60 | + $out = Xml::element( 'h2', array( 'id' => 'mw-version-ext' ), wfMsg( 'version-extensions' ) ) . |
| 61 | + Xml::openElement( 'table', array( 'class' => 'wikitable', 'id' => 'sv-ext' ) ); |
| 62 | + |
| 63 | + foreach ( $extensionTypes as $type => $text ) { |
| 64 | + if ( isset ( $wgExtensionCredits[$type] ) && count ( $wgExtensionCredits[$type] ) ) { |
| 65 | + $out .= $this->openExtType( $text, 'credits-' . $type ); |
| 66 | + |
| 67 | + usort( $wgExtensionCredits[$type], array( $this, 'compare' ) ); |
| 68 | + |
| 69 | + foreach ( $wgExtensionCredits[$type] as $extension ) { |
| 70 | + $out .= $this->formatCredits( $extension ); |
| 71 | + } |
| 72 | + } |
| 73 | + } |
| 74 | + //$wgOut->addWikiText( $out ); |
| 75 | + $out .= Xml::closeElement( 'table' ); |
| 76 | + return $out; |
| 77 | + } |
| 78 | + |
| 79 | + private function openExtType( $text, $name = null ) { |
| 80 | + $out = ''; |
| 81 | + $opt = array( 'colspan' => 2 ); |
| 82 | + |
| 83 | + if( !$this->firstExtOpened ) { |
| 84 | + // Insert a spacing line |
| 85 | + $out .= '<tr class="sv-space">' . Xml::element( 'td', $opt ) . "</tr>\n"; |
| 86 | + } |
| 87 | + $this->firstExtOpened = false; |
| 88 | + |
| 89 | + if( $name ) |
| 90 | + $opt['id'] = "sv-$name"; |
| 91 | + |
| 92 | + $out .= "<tr>" . Xml::element( 'th', $opt, $text ) . "</tr>\n"; |
| 93 | + return $out; |
| 94 | + } |
| 95 | + |
| 96 | + /** Callback to sort extensions by type */ |
| 97 | + function compare( $a, $b ) { |
| 98 | + global $wgLang; |
| 99 | + if( $a['name'] === $b['name'] ) { |
| 100 | + return 0; |
| 101 | + } else { |
| 102 | + return $wgLang->lc( $a['name'] ) > $wgLang->lc( $b['name'] ) |
| 103 | + ? 1 |
| 104 | + : -1; |
| 105 | + } |
| 106 | + } |
| 107 | + function formatCredits( $extension ) { |
| 108 | + $out = ''; |
| 109 | + $name = isset( $extension['name'] ) ? $extension['name'] : '[no name]'; |
| 110 | + |
| 111 | + if ( isset( $extension['path'] ) ) { |
| 112 | + $svnInfo = SpecialVersion::getSvnInfo( dirname($extension['path']) ); |
| 113 | + $directoryRev = isset( $svnInfo['directory-rev'] ) ? $svnInfo['directory-rev'] : null; |
| 114 | + $checkoutRev = isset( $svnInfo['checkout-rev'] ) ? $svnInfo['checkout-rev'] : null; |
| 115 | + $viewvcUrl = isset( $svnInfo['viewvc-url'] ) ? $svnInfo['viewvc-url'] : null; |
| 116 | + } else { |
| 117 | + $directoryRev = null; |
| 118 | + $checkoutRev = null; |
| 119 | + $viewvcUrl = null; |
| 120 | + } |
| 121 | + |
| 122 | + # Make main link (or just the name if there is no URL) |
| 123 | + if ( isset( $extension['url'] ) ) { |
| 124 | + $mainLink = "[{$extension['url']} $name]"; |
| 125 | + } else { |
| 126 | + $mainLink = $name; |
| 127 | + } |
| 128 | + # Version |
| 129 | + if ( isset( $extension['version'] ) ) { |
| 130 | + $versionText = '<span class="mw-version-ext-version"><em>' . |
| 131 | + wfMsg( 'version-version', $extension['version'] ) . |
| 132 | + '</em></span> | '; |
| 133 | + } else { |
| 134 | + $versionText = ''; |
| 135 | + } |
| 136 | + /* |
| 137 | + if ( $checkoutRev ) { |
| 138 | + $svnText = wfMsg( 'version-svn-revision', $directoryRev, $checkoutRev ); |
| 139 | + $svnText = isset( $viewvcUrl ) ? "[$viewvcUrl $svnText]" : $svnText; |
| 140 | + } else { |
| 141 | + $svnText = false; |
| 142 | + }*/ |
| 143 | + |
| 144 | + # Make description text |
| 145 | + $description = isset ( $extension['description'] ) ? $extension['description'] : ''; |
| 146 | + if( isset ( $extension['descriptionmsg'] ) ) { |
| 147 | + # Look for a localized description |
| 148 | + $descriptionMsg = $extension['descriptionmsg']; |
| 149 | + if( is_array( $descriptionMsg ) ) { |
| 150 | + $descriptionMsgKey = $descriptionMsg[0]; // Get the message key |
| 151 | + array_shift( $descriptionMsg ); // Shift out the message key to get the parameters only |
| 152 | + array_map( "htmlspecialchars", $descriptionMsg ); // For sanity |
| 153 | + $msg = wfMsg( $descriptionMsgKey, $descriptionMsg ); |
| 154 | + } else { |
| 155 | + $msg = wfMsg( $descriptionMsg ); |
| 156 | + } |
| 157 | + if ( !wfEmptyMsg( $descriptionMsg, $msg ) && $msg != '' ) { |
| 158 | + $description = $msg; |
| 159 | + } |
| 160 | + } |
| 161 | + $author = isset ( $extension['author'] ) ? $extension['author'] : array(); |
| 162 | + $extDescAuthor = "<td>$description <br />". $versionText . $this->listToText( (array)$author, false ) . "</td> |
| 163 | + </tr>\n"; |
| 164 | + |
| 165 | + $extNameVer = "<tr> |
| 166 | + <td><em>$mainLink</em></td>"; |
| 167 | + |
| 168 | + return $extNameVer.$extDescAuthor; |
| 169 | + } |
| 170 | + /** |
| 171 | + * @param array $list |
| 172 | + * @param bool $sort |
| 173 | + * @return string |
| 174 | + */ |
| 175 | + function listToText( $list, $sort = true ) { |
| 176 | + $cnt = count( $list ); |
| 177 | + |
| 178 | + if ( $cnt == 1 ) { |
| 179 | + // Enforce always returning a string |
| 180 | + return (string)self::arrayToString( $list[0] ); |
| 181 | + } elseif ( $cnt == 0 ) { |
| 182 | + return ''; |
| 183 | + } else { |
| 184 | + global $wgLang; |
| 185 | + if ( $sort ) { |
| 186 | + sort( $list ); |
| 187 | + } |
| 188 | + return $wgLang->listToText( array_map( array( __CLASS__, 'arrayToString' ), $list ) ); |
| 189 | + } |
| 190 | + } |
| 191 | + |
| 192 | + /** |
| 193 | + * @param mixed $list Will convert an array to string if given and return |
| 194 | + * the paramater unaltered otherwise |
| 195 | + * @return mixed |
| 196 | + */ |
| 197 | + static function arrayToString( $list ) { |
| 198 | + if( is_array( $list ) && count( $list ) == 1 ) |
| 199 | + $list = $list[0]; |
| 200 | + if( is_object( $list ) ) { |
| 201 | + $class = get_class( $list ); |
| 202 | + return "($class)"; |
| 203 | + } elseif ( !is_array( $list ) ) { |
| 204 | + return $list; |
| 205 | + } else { |
| 206 | + if( is_object( $list[0] ) ) |
| 207 | + $class = get_class( $list[0] ); |
| 208 | + else |
| 209 | + $class = $list[0]; |
| 210 | + return "($class, {$list[1]})"; |
| 211 | + } |
| 212 | + } |
| 213 | +} |
| 214 | +?> |
Index: trunk/extensions/ExtensionManagement/includes/EMSubversion.php |
Index: trunk/extensions/ExtensionManagement/ExtensionManagement.alias.php |
— | — | @@ -0,0 +1,12 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Special page aliases for the ExtensionManagement extension. |
| 5 | + * |
| 6 | + * @file ExtensionManagement.i18n.php |
| 7 | + */ |
| 8 | + |
| 9 | +$specialPageAliases = array(); |
| 10 | + |
| 11 | +$specialPageAliases['en'] = array( |
| 12 | + 'ExtensionManagement' => array( 'ExtensionManagement' ), |
| 13 | +); |
Index: trunk/extensions/ExtensionManagement/extensionmanagement.sql |
— | — | @@ -0,0 +1,41 @@ |
| 2 | +-- MySQL database schema for the Extension Management extension. |
| 3 | + |
| 4 | +CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/extensionmanagement ( |
| 5 | + ext_id INT(8) unsigned NOT NULL auto_increment PRIMARY KEY, |
| 6 | + ext_name VARCHAR(255) NOT NULL, |
| 7 | + ext_url VARCHAR(255) NULL, |
| 8 | + -- Latest stable release |
| 9 | + ext_current INT(8) unsigned NOT NULL, |
| 10 | + -- Info of the latest stable release |
| 11 | + current_desc BLOB NOT NULL, |
| 12 | + current_authors BLOB NOT NULL |
| 13 | +) /*$wgDBTableOptions*/; |
| 14 | + |
| 15 | +CREATE UNIQUE INDEX unit_name ON /*$wgDBprefix*/extensionmanagement (ext_name); |
| 16 | + |
| 17 | +-- Specific versions of extensions |
| 18 | +CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/extensionmanagement_versions ( |
| 19 | + version_id INT(8) unsigned NOT NULL auto_increment PRIMARY KEY, |
| 20 | + |
| 21 | + version_ext_id INT(8) unsigned NOT NULL, |
| 22 | + FOREIGN KEY (version_ext_id) REFERENCES /*$wgDBprefix*/extensionmanagement (ext_id), |
| 23 | + |
| 24 | + version_status TINYINT unsigned NOT NULL, |
| 25 | + version_release_date CHAR(14) binary NOT NULL default '', |
| 26 | + version_directory VARCHAR(255) NOT NULL, |
| 27 | + version_entrypoint VARCHAR(255) NOT NULL, |
| 28 | + version_desc BLOB NOT NULL, |
| 29 | + version_authors BLOB NOT NULL |
| 30 | +) /*$wgDBTableOptions*/; |
| 31 | + |
| 32 | +CREATE TABLE IF NOT EXISTS /*_*/extensionmanagement_mwreleases ( |
| 33 | + mwr_id int(10) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, |
| 34 | + mwr_name varchar(255) NOT NULL, |
| 35 | + mwr_number varchar(32) NOT NULL, |
| 36 | + mwr_reldate varbinary(32) DEFAULT NULL, |
| 37 | + mwr_eoldate varbinary(32) DEFAULT NULL, |
| 38 | + mwr_branch varchar(32) NOT NULL, |
| 39 | + mwr_tag varchar(32) NOT NULL, |
| 40 | + mwr_announcement varchar(255) DEFAULT NULL, |
| 41 | + mwr_supported int(1) NOT NULL |
| 42 | +) /*$wgDBTableOptions*/; |
Index: trunk/extensions/ExtensionManagement/ExtensionManagement_body.php |
Index: trunk/extensions/ExtensionManagement/ExtensionManagement.i18n.php |
— | — | @@ -0,0 +1,17 @@ |
| 2 | +<?php |
| 3 | +$aliases = array(); |
| 4 | +$messages = array(); |
| 5 | + |
| 6 | +$aliases['en'] = array( |
| 7 | + 'ExtensionManagement' => array( 'ExtensionManagement' ), |
| 8 | +); |
| 9 | + |
| 10 | +$messages['en'] = array( |
| 11 | + 'extensionmanagement' => 'Extension Management', |
| 12 | + 'extensionmanagement-desc' => 'TBA', |
| 13 | + |
| 14 | + //Special:ExtensionManagement |
| 15 | + 'extensionmanagement-page-explanation' => 'This page shows all extensions installed on this wiki. |
| 16 | +For more info about this wiki installation, see [[Special:Version|{{int:version}}]].', |
| 17 | +); |
| 18 | +?> |