Index: trunk/extensions/ServerAdminLog/ServerAdminLog.alias.php |
— | — | @@ -0,0 +1,13 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Aliases for special pages for extension ServerAdminLo |
| 5 | + * |
| 6 | + * @ignore |
| 7 | + */ |
| 8 | + |
| 9 | +$specialPageAliases = array(); |
| 10 | + |
| 11 | +/** English (English) */ |
| 12 | +$specialPageAliases['en'] = array( |
| 13 | + 'AdminLog' => array( 'AdminLog', 'ServerAdminLog' ), |
| 14 | +); |
Property changes on: trunk/extensions/ServerAdminLog/ServerAdminLog.alias.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 15 | + native |
Index: trunk/extensions/ServerAdminLog/ServerAdminLogChannel.php |
— | — | @@ -0,0 +1,90 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Channel object |
| 6 | + */ |
| 7 | +class ServerAdminLogChannel { |
| 8 | + |
| 9 | + /** |
| 10 | + * Channel ID |
| 11 | + * |
| 12 | + * @var int |
| 13 | + */ |
| 14 | + protected $id = 0; |
| 15 | + |
| 16 | + /** |
| 17 | + * Chanel code |
| 18 | + * |
| 19 | + * @var string |
| 20 | + */ |
| 21 | + protected $code = ''; |
| 22 | + |
| 23 | + /** |
| 24 | + * Channel human readable name |
| 25 | + * |
| 26 | + * @var string |
| 27 | + */ |
| 28 | + protected $name = ''; |
| 29 | + |
| 30 | + /** |
| 31 | + * Returns a channel instance by a code |
| 32 | + * |
| 33 | + * @param $code |
| 34 | + * @return null|ServerAdminLogChannel |
| 35 | + */ |
| 36 | + public static function getChannelByCode( $code ) { |
| 37 | + $db = wfGetDB( DB_SLAVE ); |
| 38 | + $row = $db->selectRow( |
| 39 | + 'sal_channel', |
| 40 | + '*', |
| 41 | + array( 'salc_code' => $code ), |
| 42 | + __METHOD__ |
| 43 | + ); |
| 44 | + |
| 45 | + if ( $row === false ) { |
| 46 | + return null; |
| 47 | + } |
| 48 | + |
| 49 | + $channel = new self( $row ); |
| 50 | + return $channel; |
| 51 | + } |
| 52 | + |
| 53 | + /** |
| 54 | + * Constructor |
| 55 | + * |
| 56 | + * @param stdClass $row |
| 57 | + */ |
| 58 | + protected function __construct( $row ) { |
| 59 | + $this->id = $row->salc_id; |
| 60 | + |
| 61 | + if ( isset( $row->salc_code ) ) { |
| 62 | + $this->code = $row->salc_code; |
| 63 | + } |
| 64 | + |
| 65 | + if ( isset( $row->salc_name ) ) { |
| 66 | + $this->name = $row->salc_name; |
| 67 | + } |
| 68 | + } |
| 69 | + |
| 70 | + /** |
| 71 | + * @return string |
| 72 | + */ |
| 73 | + public function getCode() { |
| 74 | + return $this->code; |
| 75 | + } |
| 76 | + |
| 77 | + /** |
| 78 | + * @return int |
| 79 | + */ |
| 80 | + public function getId() { |
| 81 | + return $this->id; |
| 82 | + } |
| 83 | + |
| 84 | + /** |
| 85 | + * @return string |
| 86 | + */ |
| 87 | + public function getName() { |
| 88 | + return $this->name; |
| 89 | + } |
| 90 | + |
| 91 | +} |
Property changes on: trunk/extensions/ServerAdminLog/ServerAdminLogChannel.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 92 | + native |
Index: trunk/extensions/ServerAdminLog/specials/SpecialAdminLog.php |
— | — | @@ -0,0 +1,67 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Special page to display log entries |
| 6 | + */ |
| 7 | +class SpecialAdminLog extends IncludableSpecialPage { |
| 8 | + |
| 9 | + /** |
| 10 | + * @var ServerAdminLogEntryPager |
| 11 | + */ |
| 12 | + protected $pager; |
| 13 | + |
| 14 | + /** |
| 15 | + * Constructor |
| 16 | + */ |
| 17 | + public function __construct() { |
| 18 | + parent::__construct( 'AdminLog' ); |
| 19 | + } |
| 20 | + |
| 21 | + /** |
| 22 | + * Execute. You know what this does! |
| 23 | + * |
| 24 | + * @param $par string Parameter |
| 25 | + */ |
| 26 | + public function execute( $par ) { |
| 27 | + $this->setHeaders(); |
| 28 | + |
| 29 | + $this->pager = new ServerAdminLogEntryPager( $this->getContext() ); |
| 30 | + |
| 31 | + if ( $par === null ) { |
| 32 | + // No channel, do a full overview |
| 33 | + $this->showOverview(); |
| 34 | + } else { |
| 35 | + $this->showChannel( $par ); |
| 36 | + } |
| 37 | + } |
| 38 | + |
| 39 | + /** |
| 40 | + * Display the overview for all channels |
| 41 | + */ |
| 42 | + private function showOverview() { |
| 43 | + $out = $this->getOutput(); |
| 44 | + $out->addHTML( $this->pager->getBody() ); |
| 45 | + } |
| 46 | + |
| 47 | + /** |
| 48 | + * Display information for one channel |
| 49 | + * |
| 50 | + * @param $par |
| 51 | + * @throws ErrorPageError |
| 52 | + */ |
| 53 | + private function showChannel( $par ) { |
| 54 | + $channel = ServerAdminLogChannel::getChannelByCode( $par ); |
| 55 | + if ( $channel === null ) { |
| 56 | + throw new ErrorPageError( 'serveradminlog-invalidchannel', 'serveradminlog-invalidchannel-msg', $par ); |
| 57 | + } |
| 58 | + |
| 59 | + $out = $this->getOutput(); |
| 60 | + $out->setPageTitle( $channel->getName() ); |
| 61 | + |
| 62 | + $this->pager->setChannel( $channel->getId() ); |
| 63 | + |
| 64 | + $out->addHTML( $this->pager->getBody() ); |
| 65 | + |
| 66 | + |
| 67 | + } |
| 68 | +} |
Property changes on: trunk/extensions/ServerAdminLog/specials/SpecialAdminLog.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 69 | + native |
Index: trunk/extensions/ServerAdminLog/ServerAdminLog.i18n.php |
— | — | @@ -0,0 +1,32 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Internationalization file for ServerAdminLog |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ignore |
| 8 | + */ |
| 9 | + |
| 10 | +$messages = array(); |
| 11 | + |
| 12 | +/** English |
| 13 | + * @author John Du Hart |
| 14 | + */ |
| 15 | +$messages['en'] = array( |
| 16 | + 'serveradminlog-desc' => '[[Special:AdminLog|Log]] for admin actions', |
| 17 | + |
| 18 | + // Special:AdminLog |
| 19 | + 'adminlog' => 'Server Admin Log', |
| 20 | + 'serveradminlog-invalidchannel' => 'Invalid channel', |
| 21 | + 'serveradminlog-invalidchannel-msg' => "Channel '''$1''' does not exist!", |
| 22 | +); |
| 23 | + |
| 24 | +/** Message documentation (Message documentation) |
| 25 | + * @author John Du Hart |
| 26 | + */ |
| 27 | +$messages['qqq'] = array( |
| 28 | + 'serveradminlog-desc' => '{{desc}}', |
| 29 | + |
| 30 | + // Special:AdminLog |
| 31 | + 'adminlog' => 'Title at the top of [[Special:AdminLog]]', |
| 32 | + 'serveradminlog-invalidchannel' => 'Title of the page in the ' |
| 33 | +); |
\ No newline at end of file |
Property changes on: trunk/extensions/ServerAdminLog/ServerAdminLog.i18n.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 34 | + native |
Index: trunk/extensions/ServerAdminLog/ServerAdminLog.php |
— | — | @@ -0,0 +1,43 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Server Admin Log: Let everyone know you 'rm -rf /' enwiki |
| 5 | + * |
| 6 | + * @ingroup Extensions |
| 7 | + * @file |
| 8 | + */ |
| 9 | + |
| 10 | +// TODO: Database setup |
| 11 | + |
| 12 | + |
| 13 | +/* |
| 14 | + * Exit if called outside of MediaWiki |
| 15 | + */ |
| 16 | +if( !defined( 'MEDIAWIKI' ) ) { |
| 17 | + echo( "This file is an extension to the MediaWiki software and cannot be used standalone.\n" ); |
| 18 | + die( 1 ); |
| 19 | +} |
| 20 | + |
| 21 | +/* |
| 22 | + * Greets to all mah homies |
| 23 | + */ |
| 24 | +$wgExtensionCredits['special'][] = array( |
| 25 | + 'path' => __FILE__, |
| 26 | + 'name' => 'Server Admin Log', |
| 27 | + 'version' => 1.0, |
| 28 | + 'author' => array( 'John Du Hart' ), |
| 29 | + 'url' => '//www.mediawiki.org/wiki/Extension:ServerAdminLog', |
| 30 | + 'descriptionmsg' => 'serveradminlog-desc', |
| 31 | +); |
| 32 | + |
| 33 | +/* |
| 34 | + * Introduce our files to the autoloader |
| 35 | + */ |
| 36 | +$dir = dirname( __FILE__ ) . '/'; |
| 37 | + |
| 38 | +$wgAutoloadClasses['ServerAdminLogEntryPager'] = $dir . '/ServerAdminLogEntryPager.php'; |
| 39 | +$wgAutoloadClasses['ServerAdminLogChannel'] = $dir . '/ServerAdminLogChannel.php'; |
| 40 | +$wgAutoloadClasses['SpecialAdminLog'] = $dir . '/specials/SpecialAdminLog.php'; |
| 41 | + |
| 42 | +$wgSpecialPages['AdminLog'] = 'SpecialAdminLog'; |
| 43 | + |
| 44 | +$wgExtensionMessagesFiles['ServerAdminLog'] = $dir . 'ServerAdminLog.i18n.php'; |
\ No newline at end of file |
Property changes on: trunk/extensions/ServerAdminLog/ServerAdminLog.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 45 | + native |
Index: trunk/extensions/ServerAdminLog/ServerAdminLogEntryPager.php |
— | — | @@ -0,0 +1,158 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Pager for log entries |
| 6 | + */ |
| 7 | +class ServerAdminLogEntryPager extends ReverseChronologicalPager { |
| 8 | + |
| 9 | + /** |
| 10 | + * Channel to filter entries to |
| 11 | + * |
| 12 | + * @var null|int |
| 13 | + */ |
| 14 | + protected $channel = null; |
| 15 | + |
| 16 | + /** |
| 17 | + * Last date for an entry |
| 18 | + * |
| 19 | + * @var string |
| 20 | + */ |
| 21 | + protected $lastDate = ''; |
| 22 | + |
| 23 | + /** |
| 24 | + * Abstract formatting function. This should return an HTML string |
| 25 | + * representing the result row $row. Rows will be concatenated and |
| 26 | + * returned by getBody() |
| 27 | + * |
| 28 | + * @param $row Object: database row |
| 29 | + * @return String |
| 30 | + */ |
| 31 | + function formatRow( $row ) { |
| 32 | + |
| 33 | + $time = $this->getLanguage()->time( wfTimestamp( TS_MW, $row->sale_timestamp ) ); |
| 34 | + $message = htmlspecialchars( $row->sale_comment ); |
| 35 | + |
| 36 | + // Link to the user if they're not anon |
| 37 | + if ( $row->sale_user == 0 ) { |
| 38 | + $user = $row->sale_user_text; |
| 39 | + } else { |
| 40 | + $userPage = Title::makeTitle( NS_USER, $row->user_name ); |
| 41 | + $user = Linker::link( $userPage, htmlspecialchars( $userPage->getText() ) ); |
| 42 | + } |
| 43 | + |
| 44 | + // Link to the chanel name if the column is there |
| 45 | + if ( isset( $row->salc_name ) ) { |
| 46 | + $chanTitle = SpecialPage::getTitleFor( 'AdminLog', $row->salc_code ); |
| 47 | + $channel = Linker::link( $chanTitle, htmlspecialchars( $row->salc_name ) ); |
| 48 | + $channel = ' ' . $this->msg( 'parentheses' )->rawParams( $channel )->escaped(); |
| 49 | + } else { |
| 50 | + $channel = ''; |
| 51 | + } |
| 52 | + |
| 53 | + $html = "<li>{$time}{$channel} {$user}: ${message}</li>"; |
| 54 | + |
| 55 | + $date = $this->getLanguage()->date( wfTimestamp( TS_MW, $row->sale_timestamp ) ); |
| 56 | + if ( $date != $this->lastDate ) { |
| 57 | + $html = "<h2>$date</h2>\n<ul>\n$html"; |
| 58 | + |
| 59 | + // Close the last list if there is one |
| 60 | + if ( $this->lastDate != '' ) { |
| 61 | + $html = "</ul>\n$html"; |
| 62 | + } |
| 63 | + |
| 64 | + $this->lastDate = $date; |
| 65 | + } |
| 66 | + |
| 67 | + return $html; |
| 68 | + } |
| 69 | + |
| 70 | + protected function getStartBody() { |
| 71 | + return $this->getNavigationBar(); |
| 72 | + } |
| 73 | + |
| 74 | + protected function getEndBody() { |
| 75 | + return '</ul>' . $this->getNavigationBar(); |
| 76 | + } |
| 77 | + |
| 78 | + |
| 79 | + /** |
| 80 | + * This function should be overridden to provide all parameters |
| 81 | + * needed for the main paged query. It returns an associative |
| 82 | + * array with the following elements: |
| 83 | + * tables => Table(s) for passing to Database::select() |
| 84 | + * fields => Field(s) for passing to Database::select(), may be * |
| 85 | + * conds => WHERE conditions |
| 86 | + * options => option array |
| 87 | + * join_conds => JOIN conditions |
| 88 | + * |
| 89 | + * @return Array |
| 90 | + */ |
| 91 | + function getQueryInfo() { |
| 92 | + $info = array( |
| 93 | + 'tables' => array( 'sal_entry', 'sal_channel', 'user' ), |
| 94 | + 'fields' => array( |
| 95 | + 'sale_id', 'sale_user', 'sale_user_text', |
| 96 | + 'sale_timestamp', 'sale_comment', 'user_name', |
| 97 | + ), |
| 98 | + 'join_conds' => array( |
| 99 | + 'sal_channel' => array( 'LEFT JOIN', 'sale_channel = salc_id' ), |
| 100 | + 'user' => array( 'LEFT JOIN', 'sale_user != 0 AND sale_user = user_id' ), |
| 101 | + ), |
| 102 | + 'options' => array(), |
| 103 | + 'conds' => array(), |
| 104 | + ); |
| 105 | + |
| 106 | + if ( $this->channel === null ) { |
| 107 | + // No channel! |
| 108 | + $info['fields'][] = 'salc_name'; |
| 109 | + $info['fields'][] = 'salc_code'; |
| 110 | + } else { |
| 111 | + // Has a channel, filter by it |
| 112 | + $info['conds'][] = 'sale_channel = ' . intval( $this->channel ); |
| 113 | + } |
| 114 | + |
| 115 | + return $info; |
| 116 | + } |
| 117 | + |
| 118 | + /** |
| 119 | + * Precache the user links |
| 120 | + */ |
| 121 | + protected function doBatchLookups() { |
| 122 | + parent::doBatchLookups(); |
| 123 | + |
| 124 | + $this->mResult->rewind(); |
| 125 | + $batch = new LinkBatch(); |
| 126 | + foreach ( $this->mResult as $row ) { |
| 127 | + if ( $row->sale_user != 0 ) { |
| 128 | + $batch->addObj( Title::makeTitleSafe( NS_USER, $row->user_name ) ); |
| 129 | + } |
| 130 | + } |
| 131 | + $batch->execute(); |
| 132 | + $this->mResult->rewind(); |
| 133 | + } |
| 134 | + |
| 135 | + /** |
| 136 | + * This function should be overridden to return the name of the index fi- |
| 137 | + * eld. If the pager supports multiple orders, it may return an array of |
| 138 | + * 'querykey' => 'indexfield' pairs, so that a request with &count=querykey |
| 139 | + * will use indexfield to sort. In this case, the first returned key is |
| 140 | + * the default. |
| 141 | + * |
| 142 | + * Needless to say, it's really not a good idea to use a non-unique index |
| 143 | + * for this! That won't page right. |
| 144 | + * |
| 145 | + * @return string|Array |
| 146 | + */ |
| 147 | + function getIndexField() { |
| 148 | + return 'sale_id'; |
| 149 | + } |
| 150 | + |
| 151 | + /** |
| 152 | + * Sets the channel to filter |
| 153 | + * |
| 154 | + * @param int $channel |
| 155 | + */ |
| 156 | + public function setChannel( $channel ) { |
| 157 | + $this->channel = $channel; |
| 158 | + } |
| 159 | +} |
Property changes on: trunk/extensions/ServerAdminLog/ServerAdminLogEntryPager.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 160 | + native |
Index: trunk/extensions/ServerAdminLog/tables.sql |
— | — | @@ -0,0 +1,29 @@ |
| 2 | +-- Channel definition table |
| 3 | +CREATE TABLE /*_*/sal_channel ( |
| 4 | + salc_id int(10) unsigned NOT NULL AUTO_INCREMENT, |
| 5 | + -- Code to access the chanel by |
| 6 | + salc_code varbinary(255) NOT NULL, |
| 7 | + -- Human readable name |
| 8 | + salc_name varbinary(255) NOT NULL, |
| 9 | + |
| 10 | + PRIMARY KEY (salc_id) |
| 11 | +) |
| 12 | + |
| 13 | +CREATE UNIQUE INDEX /*i*/salc_code ON /*_*/sal_channel (salc_code) |
| 14 | + |
| 15 | +-- Actual log entries |
| 16 | +CREATE TABLE /*_*/sal_entry ( |
| 17 | + sale_id int(10) unsigned NOT NULL AUTO_INCREMENT, |
| 18 | + -- FK to sal_channel.salc_id |
| 19 | + sale_channel int(10) unsigned NOT NULL, |
| 20 | + -- FK to user.user_id |
| 21 | + sale_user int(10) unsigned NOT NULL DEFAULT '0', |
| 22 | + -- If sale_user is 0, this will be used as the user text |
| 23 | + sale_user_text varbinary(250) NOT NULL, |
| 24 | + -- Timestamp for the sal_entry |
| 25 | + sale_timestamp binary(14) NOT NULL, |
| 26 | + -- Entry text |
| 27 | + sale_comment blob NOT NULL, |
| 28 | + |
| 29 | + PRIMARY KEY (sale_id) |
| 30 | +) |
\ No newline at end of file |
Property changes on: trunk/extensions/ServerAdminLog/tables.sql |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 31 | + native |