diff options
author | Luke Shumaker <LukeShu@sbcglobal.net> | 2014-01-28 09:50:25 -0500 |
---|---|---|
committer | Luke Shumaker <LukeShu@sbcglobal.net> | 2014-01-28 09:50:25 -0500 |
commit | 5744df39e15f85c6cc8a9faf8924d77e76d2b216 (patch) | |
tree | a8c8dd40a94d1fa0d5377566aa5548ae55a163da /includes/logging | |
parent | 4bb2aeca1d198391ca856aa16c40b8559c68daec (diff) | |
parent | 224b22a051051f6c2e494c3a2fb4adb42898e2d1 (diff) |
Merge branch 'archwiki'
Conflicts:
extensions/FluxBBAuthPlugin.php
extensions/SyntaxHighlight_GeSHi/README
extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.class.php
extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.i18n.php
extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.php
extensions/SyntaxHighlight_GeSHi/geshi/docs/CHANGES
extensions/SyntaxHighlight_GeSHi/geshi/docs/THANKS
extensions/SyntaxHighlight_GeSHi/geshi/docs/TODO
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractClass.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractClass_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractMethod.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractPrivateClass.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractPrivateClass_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractPrivateMethod.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Class.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Class_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Constant.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Constructor.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Destructor.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Function.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Global.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/I.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Index.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Interface.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Interface_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/L.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Lminus.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Lplus.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Method.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Page.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Page_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/PrivateClass.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/PrivateClass_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/PrivateMethod.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/PrivateVariable.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/StaticMethod.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/StaticVariable.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/T.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Tminus.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Tplus.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Variable.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/blank.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/class_folder.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/file.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/folder.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/function_folder.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/next_button.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/next_button_disabled.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/package.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/package_folder.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/previous_button.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/previous_button_disabled.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/private_class_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/tutorial.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/tutorial_folder.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/up_button.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/geshi-doc.html
extensions/SyntaxHighlight_GeSHi/geshi/docs/geshi-doc.txt
extensions/SyntaxHighlight_GeSHi/geshi/geshi.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/4cs.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/6502acme.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/6502kickass.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/6502tasm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/68000devpac.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/abap.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/actionscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/actionscript3.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ada.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/algol68.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/apache.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/applescript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/apt_sources.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/asm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/asp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/autoconf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/autohotkey.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/autoit.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/avisynth.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/awk.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/bascomavr.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/bash.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/basic4gl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/bf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/bibtex.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/blitzbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/bnf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/boo.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/c.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/c_loadrunner.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/c_mac.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/caddcl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cadlisp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cfdg.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cfm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/chaiscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cil.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/clojure.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cmake.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cobol.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/coffeescript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cpp-qt.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cpp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/csharp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/css.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cuesheet.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/d.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/dcs.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/delphi.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/diff.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/div.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/dos.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/dot.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/e.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ecmascript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/eiffel.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/email.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/epc.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/erlang.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/euphoria.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/f1.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/falcon.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/fo.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/fortran.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/freebasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/fsharp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gambas.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gdb.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/genero.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/genie.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gettext.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/glsl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gml.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gnuplot.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/go.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/groovy.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gwbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/haskell.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/hicest.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/hq9plus.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/html4strict.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/html5.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/icon.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/idl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ini.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/inno.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/intercal.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/io.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/j.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/java.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/java5.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/javascript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/jquery.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/kixtart.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/klonec.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/klonecpp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/latex.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lb.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lisp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/llvm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/locobasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/logtalk.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lolcode.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lotusformulas.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lotusscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lsl2.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lua.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/m68k.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/magiksf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/make.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mapbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/matlab.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mirc.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mmix.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/modula2.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/modula3.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mpasm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mxml.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mysql.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/newlisp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/nsis.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oberon2.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/objc.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/objeck.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ocaml-brief.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ocaml.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oobas.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oracle11.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oracle8.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oxygene.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oz.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pascal.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pcre.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/per.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/perl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/perl6.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/php-brief.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/php.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pic16.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pike.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pixelbender.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pli.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/plsql.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/postgresql.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/povray.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/powerbuilder.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/powershell.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/proftpd.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/progress.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/prolog.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/properties.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/providex.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/purebasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pycon.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/python.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/q.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/qbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/rails.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/rebol.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/reg.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/robots.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/rpmspec.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/rsplus.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ruby.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/sas.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/scala.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/scheme.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/scilab.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/sdlbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/smalltalk.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/smarty.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/sql.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/systemverilog.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/tcl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/teraterm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/text.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/thinbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/tsql.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/typoscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/unicon.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/uscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/vala.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/vb.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/vbnet.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/verilog.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/vhdl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/vim.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/visualfoxpro.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/visualprolog.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/whitespace.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/whois.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/winbatch.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/xbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/xml.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/xorg_conf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/xpp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/yaml.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/z80.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/zxbasic.php
Diffstat (limited to 'includes/logging')
-rw-r--r-- | includes/logging/DeleteLogFormatter.php | 196 | ||||
-rw-r--r-- | includes/logging/LogEntry.php | 125 | ||||
-rw-r--r-- | includes/logging/LogEventsList.php | 146 | ||||
-rw-r--r-- | includes/logging/LogFormatter.php | 446 | ||||
-rw-r--r-- | includes/logging/LogPage.php | 137 | ||||
-rw-r--r-- | includes/logging/LogPager.php | 105 | ||||
-rw-r--r-- | includes/logging/MoveLogFormatter.php | 82 | ||||
-rw-r--r-- | includes/logging/NewUsersLogFormatter.php | 65 | ||||
-rw-r--r-- | includes/logging/PatrolLog.php | 7 | ||||
-rw-r--r-- | includes/logging/PatrolLogFormatter.php | 63 | ||||
-rw-r--r-- | includes/logging/RightsLogFormatter.php | 112 |
11 files changed, 917 insertions, 567 deletions
diff --git a/includes/logging/DeleteLogFormatter.php b/includes/logging/DeleteLogFormatter.php new file mode 100644 index 00000000..01528b7e --- /dev/null +++ b/includes/logging/DeleteLogFormatter.php @@ -0,0 +1,196 @@ +<?php +/** + * Formatter for delete log entries. + * + * 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 + * @author Niklas Laxström + * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later + * @since 1.22 + */ + +/** + * This class formats delete log entries. + * + * @since 1.19 + */ +class DeleteLogFormatter extends LogFormatter { + protected function getMessageKey() { + $key = parent::getMessageKey(); + if ( in_array( $this->entry->getSubtype(), array( 'event', 'revision' ) ) ) { + if ( count( $this->getMessageParameters() ) < 5 ) { + return "$key-legacy"; + } + } + return $key; + } + + protected function getMessageParameters() { + if ( isset( $this->parsedParametersDeleteLog ) ) { + return $this->parsedParametersDeleteLog; + } + + $params = parent::getMessageParameters(); + $subtype = $this->entry->getSubtype(); + if ( in_array( $subtype, array( 'event', 'revision' ) ) ) { + // $params[3] here is 'revision' for page revisions, 'oldimage' for file versions, or a comma-separated list of log_ids for log entries. + // $subtype here is 'revision' for page revisions and file versions, or 'event' for log entries. + if ( + ( $subtype === 'event' && count( $params ) === 6 ) || + ( $subtype === 'revision' && isset( $params[3] ) && ( $params[3] === 'revision' || $params[3] === 'oldimage' ) ) + ) { + $paramStart = $subtype === 'revision' ? 4 : 3; + + $old = $this->parseBitField( $params[$paramStart + 1] ); + $new = $this->parseBitField( $params[$paramStart + 2] ); + list( $hid, $unhid, $extra ) = RevisionDeleter::getChanges( $new, $old ); + $changes = array(); + foreach ( $hid as $v ) { + $changes[] = $this->msg( "$v-hid" )->plain(); + } + foreach ( $unhid as $v ) { + $changes[] = $this->msg( "$v-unhid" )->plain(); + } + foreach ( $extra as $v ) { + $changes[] = $this->msg( $v )->plain(); + } + $changeText = $this->context->getLanguage()->listToText( $changes ); + + $newParams = array_slice( $params, 0, 3 ); + $newParams[3] = $changeText; + $count = count( explode( ',', $params[$paramStart] ) ); + $newParams[4] = $this->context->getLanguage()->formatNum( $count ); + return $this->parsedParametersDeleteLog = $newParams; + } else { + return $this->parsedParametersDeleteLog = array_slice( $params, 0, 3 ); + } + } + + return $this->parsedParametersDeleteLog = $params; + } + + protected function parseBitField( $string ) { + // Input is like ofield=2134 or just the number + if ( strpos( $string, 'field=' ) === 1 ) { + list( , $field ) = explode( '=', $string ); + return (int)$field; + } else { + return (int)$string; + } + } + + public function getActionLinks() { + $user = $this->context->getUser(); + if ( !$user->isAllowed( 'deletedhistory' ) || $this->entry->isDeleted( LogPage::DELETED_ACTION ) ) { + return ''; + } + + switch ( $this->entry->getSubtype() ) { + case 'delete': // Show undelete link + if ( $user->isAllowed( 'undelete' ) ) { + $message = 'undeletelink'; + } else { + $message = 'undeleteviewlink'; + } + $revert = Linker::linkKnown( + SpecialPage::getTitleFor( 'Undelete' ), + $this->msg( $message )->escaped(), + array(), + array( 'target' => $this->entry->getTarget()->getPrefixedDBkey() ) + ); + return $this->msg( 'parentheses' )->rawParams( $revert )->escaped(); + + case 'revision': // If an edit was hidden from a page give a review link to the history + $params = $this->extractParameters(); + if ( !isset( $params[3] ) || !isset( $params[4] ) ) { + return ''; + } + + // Different revision types use different URL params... + $key = $params[3]; + // This is a CSV of the IDs + $ids = explode( ',', $params[4] ); + + $links = array(); + + // If there's only one item, we can show a diff link + if ( count( $ids ) == 1 ) { + // Live revision diffs... + if ( $key == 'oldid' || $key == 'revision' ) { + $links[] = Linker::linkKnown( + $this->entry->getTarget(), + $this->msg( 'diff' )->escaped(), + array(), + array( + 'diff' => intval( $ids[0] ), + 'unhide' => 1 + ) + ); + // Deleted revision diffs... + } elseif ( $key == 'artimestamp' || $key == 'archive' ) { + $links[] = Linker::linkKnown( + SpecialPage::getTitleFor( 'Undelete' ), + $this->msg( 'diff' )->escaped(), + array(), + array( + 'target' => $this->entry->getTarget()->getPrefixedDBkey(), + 'diff' => 'prev', + 'timestamp' => $ids[0] + ) + ); + } + } + + // View/modify link... + $links[] = Linker::linkKnown( + SpecialPage::getTitleFor( 'Revisiondelete' ), + $this->msg( 'revdel-restore' )->escaped(), + array(), + array( + 'target' => $this->entry->getTarget()->getPrefixedText(), + 'type' => $key, + 'ids' => implode( ',', $ids ), + ) + ); + + return $this->msg( 'parentheses' )->rawParams( + $this->context->getLanguage()->pipeList( $links ) )->escaped(); + + case 'event': // Hidden log items, give review link + $params = $this->extractParameters(); + if ( !isset( $params[3] ) ) { + return ''; + } + // This is a CSV of the IDs + $query = $params[3]; + // Link to each hidden object ID, $params[1] is the url param + $revert = Linker::linkKnown( + SpecialPage::getTitleFor( 'Revisiondelete' ), + $this->msg( 'revdel-restore' )->escaped(), + array(), + array( + 'target' => $this->entry->getTarget()->getPrefixedText(), + 'type' => 'logging', + 'ids' => $query + ) + ); + return $this->msg( 'parentheses' )->rawParams( $revert )->escaped(); + default: + return ''; + } + } +} diff --git a/includes/logging/LogEntry.php b/includes/logging/LogEntry.php index 37560d80..b2a8e50d 100644 --- a/includes/logging/LogEntry.php +++ b/includes/logging/LogEntry.php @@ -151,7 +151,7 @@ class DatabaseLogEntry extends LogEntryBase { return array( 'tables' => $tables, 'fields' => $fields, - 'conds' => array(), + 'conds' => array(), 'options' => array(), 'join_conds' => $joins, ); @@ -165,7 +165,7 @@ class DatabaseLogEntry extends LogEntryBase { */ public static function newFromRow( $row ) { if ( is_array( $row ) && isset( $row['rc_logid'] ) ) { - return new RCDatabaseLogEntry( (object) $row ); + return new RCDatabaseLogEntry( (object)$row ); } else { return new self( $row ); } @@ -175,6 +175,7 @@ class DatabaseLogEntry extends LogEntryBase { /// Database result row. protected $row; + protected $performer; protected function __construct( $row ) { $this->row = $row; @@ -232,17 +233,20 @@ class DatabaseLogEntry extends LogEntryBase { } public function getPerformer() { - $userId = (int) $this->row->log_user; - if ( $userId !== 0 ) { // logged-in users - if ( isset( $this->row->user_name ) ) { - return User::newFromRow( $this->row ); - } else { - return User::newFromId( $userId ); + if ( !$this->performer ) { + $userId = (int)$this->row->log_user; + if ( $userId !== 0 ) { // logged-in users + if ( isset( $this->row->user_name ) ) { + $this->performer = User::newFromRow( $this->row ); + } else { + $this->performer = User::newFromId( $userId ); + } + } else { // IP users + $userText = $this->row->log_user_text; + $this->performer = User::newFromName( $userText, false ); } - } else { // IP users - $userText = $this->row->log_user_text; - return User::newFromName( $userText, false ); } + return $this->performer; } public function getTarget() { @@ -287,14 +291,17 @@ class RCDatabaseLogEntry extends DatabaseLogEntry { } public function getPerformer() { - $userId = (int) $this->row->rc_user; - if ( $userId !== 0 ) { - return User::newFromId( $userId ); - } else { - $userText = $this->row->rc_user_text; - // Might be an IP, don't validate the username - return User::newFromName( $userText, false ); + if ( !$this->performer ) { + $userId = (int)$this->row->rc_user; + if ( $userId !== 0 ) { + $this->performer = User::newFromId( $userId ); + } else { + $userText = $this->row->rc_user_text; + // Might be an IP, don't validate the username + $this->performer = User::newFromName( $userText, false ); + } } + return $this->performer; } public function getTarget() { @@ -327,6 +334,7 @@ class ManualLogEntry extends LogEntryBase { protected $type; ///!< @var string protected $subtype; ///!< @var string protected $parameters = array(); ///!< @var array + protected $relations = array(); ///!< @var array protected $performer; ///!< @var User protected $target; ///!< @var Title protected $timestamp; ///!< @var string @@ -335,9 +343,9 @@ class ManualLogEntry extends LogEntryBase { /** * Constructor. - * + * * @since 1.19 - * + * * @param string $type * @param string $subtype */ @@ -357,20 +365,31 @@ class ManualLogEntry extends LogEntryBase { * '4:color' => 'blue', * 'animal' => 'dog' * ); - * + * * @since 1.19 - * - * @param $parameters array Associative array + * + * @param array $parameters Associative array */ public function setParameters( $parameters ) { $this->parameters = $parameters; } /** + * Declare arbitrary tag/value relations to this log entry. + * These can be used to filter log entries later on. + * + * @param array Map of (tag => (list of values)) + * @since 1.22 + */ + public function setRelations( array $relations ) { + $this->relations = $relations; + } + + /** * Set the user that performed the action being logged. - * + * * @since 1.19 - * + * * @param User $performer */ public function setPerformer( User $performer ) { @@ -379,9 +398,9 @@ class ManualLogEntry extends LogEntryBase { /** * Set the title of the object changed. - * + * * @since 1.19 - * + * * @param Title $target */ public function setTarget( Title $target ) { @@ -390,9 +409,9 @@ class ManualLogEntry extends LogEntryBase { /** * Set the timestamp of when the logged action took place. - * + * * @since 1.19 - * + * * @param string $timestamp */ public function setTimestamp( $timestamp ) { @@ -401,9 +420,9 @@ class ManualLogEntry extends LogEntryBase { /** * Set a comment associated with the action being logged. - * + * * @since 1.19 - * + * * @param string $comment */ public function setComment( $comment ) { @@ -412,9 +431,9 @@ class ManualLogEntry extends LogEntryBase { /** * TODO: document - * + * * @since 1.19 - * + * * @param integer $deleted */ public function setDeleted( $deleted ) { @@ -423,20 +442,24 @@ class ManualLogEntry extends LogEntryBase { /** * Inserts the entry into the logging table. + * @param IDatabase $dbw * @return int If of the log entry */ - public function insert() { + public function insert( IDatabase $dbw = null ) { global $wgContLang; - $dbw = wfGetDB( DB_MASTER ); + $dbw = $dbw ?: wfGetDB( DB_MASTER ); $id = $dbw->nextSequenceValue( 'logging_log_id_seq' ); if ( $this->timestamp === null ) { $this->timestamp = wfTimestampNow(); } + # Trim spaces on user supplied text + $comment = trim( $this->getComment() ); + # Truncate for whole multibyte characters. - $comment = $wgContLang->truncate( $this->getComment(), 255 ); + $comment = $wgContLang->truncate( $comment, 255 ); $data = array( 'log_id' => $id, @@ -449,17 +472,35 @@ class ManualLogEntry extends LogEntryBase { 'log_title' => $this->getTarget()->getDBkey(), 'log_page' => $this->getTarget()->getArticleID(), 'log_comment' => $comment, - 'log_params' => serialize( (array) $this->getParameters() ), + 'log_params' => serialize( (array)$this->getParameters() ), ); $dbw->insert( 'logging', $data, __METHOD__ ); $this->id = !is_null( $id ) ? $id : $dbw->insertId(); + + $rows = array(); + foreach ( $this->relations as $tag => $values ) { + if ( !strlen( $tag ) ) { + throw new MWException( "Got empty log search tag." ); + } + foreach ( $values as $value ) { + $rows[] = array( + 'ls_field' => $tag, + 'ls_value' => $value, + 'ls_log_id' => $this->id + ); + } + } + if ( count( $rows ) ) { + $dbw->insert( 'log_search', $rows, __METHOD__, 'IGNORE' ); + } + return $this->id; } /** * Publishes the log entry. - * @param $newId int id of the log entry. - * @param $to string: rcandudp (default), rc, udp + * @param int $newId id of the log entry. + * @param string $to rcandudp (default), rc, udp */ public function publish( $newId, $to = 'rcandudp' ) { $log = new LogPage( $this->getType() ); @@ -493,7 +534,7 @@ class ManualLogEntry extends LogEntryBase { $this->getSubtype(), $this->getTarget(), $this->getComment(), - serialize( (array) $this->getParameters() ), + serialize( (array)$this->getParameters() ), $newId, $formatter->getIRCActionComment() // Used for IRC feeds ); @@ -503,7 +544,7 @@ class ManualLogEntry extends LogEntryBase { } if ( $to === 'udp' || $to === 'rcandudp' ) { - $rc->notifyRC2UDP(); + $rc->notifyRCFeeds(); } } @@ -545,7 +586,7 @@ class ManualLogEntry extends LogEntryBase { } public function getDeleted() { - return (int) $this->deleted; + return (int)$this->deleted; } } diff --git a/includes/logging/LogEventsList.php b/includes/logging/LogEventsList.php index 4de1a974..c27b57af 100644 --- a/includes/logging/LogEventsList.php +++ b/includes/logging/LogEventsList.php @@ -42,7 +42,7 @@ class LogEventsList extends ContextSource { * * @param $context IContextSource Context to use; formerly it was Skin object. * @param $unused void Unused; used to be an OutputPage object. - * @param $flags int flags; can be a combinaison of self::NO_ACTION_LINK, + * @param int $flags flags; can be a combinaison of self::NO_ACTION_LINK, * self::NO_EXTRA_USER_LINKS or self::USE_REVDEL_CHECKBOXES. */ public function __construct( $context, $unused = null, $flags = 0 ) { @@ -74,9 +74,9 @@ class LogEventsList extends ContextSource { public function showHeader( $type ) { wfDeprecated( __METHOD__, '1.19' ); // If only one log type is used, then show a special message... - $headerType = (count($type) == 1) ? $type[0] : ''; + $headerType = count( $type ) == 1 ? $type[0] : ''; $out = $this->getOutput(); - if( LogPage::isLogType( $headerType ) ) { + if ( LogPage::isLogType( $headerType ) ) { $page = new LogPage( $headerType ); $out->setPageTitle( $page->getName()->text() ); $out->addHTML( $page->getDescription()->parseAsBlock() ); @@ -88,7 +88,7 @@ class LogEventsList extends ContextSource { /** * Show options for the log list * - * @param $types string or Array + * @param string $types or Array * @param $user String * @param $page String * @param $pattern String @@ -97,14 +97,14 @@ class LogEventsList extends ContextSource { * @param $filter: array * @param $tagFilter: array? */ - public function showOptions( $types=array(), $user='', $page='', $pattern='', $year='', - $month = '', $filter = null, $tagFilter='' ) { + public function showOptions( $types = array(), $user = '', $page = '', $pattern = '', $year = '', + $month = '', $filter = null, $tagFilter = '' ) { global $wgScript, $wgMiserMode; $title = SpecialPage::getTitleFor( 'Log' ); // For B/C, we take strings, but make sure they are converted... - $types = ($types === '') ? array() : (array)$types; + $types = ( $types === '' ) ? array() : (array)$types; $tagSelector = ChangeTags::buildTagFilterSelector( $tagFilter ); @@ -117,7 +117,7 @@ class LogEventsList extends ContextSource { $html .= $this->getExtraInputs( $types ) . "\n"; // Title pattern, if allowed - if (!$wgMiserMode) { + if ( !$wgMiserMode ) { $html .= $this->getTitlePattern( $pattern ) . "\n"; } @@ -125,12 +125,12 @@ class LogEventsList extends ContextSource { $html .= Xml::tags( 'p', null, Xml::dateMenu( $year, $month ) ); // Tag filter - if ($tagSelector) { + if ( $tagSelector ) { $html .= Xml::tags( 'p', null, implode( ' ', $tagSelector ) ); } // Filter links - if ($filter) { + if ( $filter ) { $html .= Xml::tags( 'p', null, $this->getFilterLinks( $filter ) ); } @@ -156,13 +156,13 @@ class LogEventsList extends ContextSource { // Option value -> message mapping $links = array(); $hiddens = ''; // keep track for "go" button - foreach( $filter as $type => $val ) { + foreach ( $filter as $type => $val ) { // Should the below assignment be outside the foreach? // Then it would have to be copied. Not certain what is more expensive. $query = $this->getDefaultQuery(); $queryKey = "hide_{$type}_log"; - $hideVal = 1 - intval($val); + $hideVal = 1 - intval( $val ); $query[$queryKey] = $hideVal; $link = Linker::linkKnown( @@ -172,11 +172,12 @@ class LogEventsList extends ContextSource { $query ); + // Message: log-show-hide-patrol $links[$type] = $this->msg( "log-show-hide-{$type}" )->rawParams( $link )->escaped(); $hiddens .= Html::hidden( "hide_{$type}_log", $val ) . "\n"; } // Build links - return '<small>'.$this->getLanguage()->pipeList( $links ) . '</small>' . $hiddens; + return '<small>' . $this->getLanguage()->pipeList( $links ) . '</small>' . $hiddens; } private function getDefaultQuery() { @@ -198,7 +199,7 @@ class LogEventsList extends ContextSource { * @return String: Formatted HTML */ private function getTypeMenu( $queryTypes ) { - $queryType = count($queryTypes) == 1 ? $queryTypes[0] : ''; + $queryType = count( $queryTypes ) == 1 ? $queryTypes[0] : ''; $selector = $this->getTypeSelector(); $selector->setDefault( $queryType ); return $selector->getHtml(); @@ -212,7 +213,7 @@ class LogEventsList extends ContextSource { public function getTypeSelector() { $typesByName = array(); // Temporary array // First pass to load the log names - foreach( LogPage::validTypes() as $type ) { + foreach ( LogPage::validTypes() as $type ) { $page = new LogPage( $type ); $restriction = $page->getRestriction(); if ( $this->getUser()->isAllowed( $restriction ) ) { @@ -221,7 +222,7 @@ class LogEventsList extends ContextSource { } // Second pass to sort by name - asort($typesByName); + asort( $typesByName ); // Always put "All public logs" on top $public = $typesByName['']; @@ -229,7 +230,7 @@ class LogEventsList extends ContextSource { $typesByName = array( '' => $public ) + $typesByName; $select = new XmlSelect( 'type' ); - foreach( $typesByName as $type => $name ) { + foreach ( $typesByName as $type => $name ) { $select->addOption( $name, $type ); } @@ -273,10 +274,10 @@ class LogEventsList extends ContextSource { private function getExtraInputs( $types ) { $offender = $this->getRequest()->getVal( 'offender' ); $user = User::newFromName( $offender, false ); - if( !$user || ($user->getId() == 0 && !IP::isIPAddress($offender) ) ) { + if ( !$user || ( $user->getId() == 0 && !IP::isIPAddress( $offender ) ) ) { $offender = ''; // Blank field if invalid } - if( count($types) == 1 && $types[0] == 'suppress' ) { + if ( count( $types ) == 1 && $types[0] == 'suppress' ) { return Xml::inputLabel( $this->msg( 'revdelete-offender' )->text(), 'offender', 'mw-log-offender', 20, $offender ); } @@ -307,7 +308,6 @@ class LogEventsList extends ContextSource { $formatter->setContext( $this->getContext() ); $formatter->setShowUserToolLinks( !( $this->flags & self::NO_EXTRA_USER_LINKS ) ); - $title = $entry->getTarget(); $time = htmlspecialchars( $this->getLanguage()->userTimeAndDate( $entry->getTimestamp(), $this->getUser() ) ); @@ -343,17 +343,17 @@ class LogEventsList extends ContextSource { * @return string */ private function getShowHideLinks( $row ) { - if( ( $this->flags == self::NO_ACTION_LINK ) // we don't want to see the links + if ( ( $this->flags == self::NO_ACTION_LINK ) // we don't want to see the links || $row->log_type == 'suppress' ) { // no one can hide items from the suppress log return ''; } $del = ''; $user = $this->getUser(); // Don't show useless checkbox to people who cannot hide log entries - if( $user->isAllowed( 'deletedhistory' ) ) { - if( $row->log_deleted || $user->isAllowed( 'deletelogentry' ) ) { - $canHide = $user->isAllowed( 'deletelogentry' ); - if ( $this->flags & self::USE_REVDEL_CHECKBOXES ) { // Show checkboxes instead of links. + if ( $user->isAllowed( 'deletedhistory' ) ) { + $canHide = $user->isAllowed( 'deletelogentry' ); + if ( $row->log_deleted || $canHide ) { + if ( $canHide && $this->flags & self::USE_REVDEL_CHECKBOXES ) { // Show checkboxes instead of links. if ( !self::userCan( $row, LogPage::DELETED_RESTRICTED, $user ) ) { // If event was hidden from sysops $del = Xml::check( 'deleterevisions', false, array( 'disabled' => 'disabled' ) ); } else { @@ -365,8 +365,8 @@ class LogEventsList extends ContextSource { } else { $query = array( 'target' => SpecialPage::getTitleFor( 'Log', $row->log_type )->getPrefixedDBkey(), - 'type' => 'logging', - 'ids' => $row->log_id, + 'type' => 'logging', + 'ids' => $row->log_id, ); $del = Linker::revDeleteLink( $query, self::isDeleted( $row, LogPage::DELETED_RESTRICTED ), $canHide ); } @@ -383,13 +383,13 @@ class LogEventsList extends ContextSource { * @param $right string * @return Boolean */ - public static function typeAction( $row, $type, $action, $right='' ) { - $match = is_array($type) ? + public static function typeAction( $row, $type, $action, $right = '' ) { + $match = is_array( $type ) ? in_array( $row->log_type, $type ) : $row->log_type == $type; - if( $match ) { + if ( $match ) { $match = is_array( $action ) ? in_array( $row->log_action, $action ) : $row->log_action == $action; - if( $match && $right ) { + if ( $match && $right ) { global $wgUser; $match = $wgUser->isAllowed( $right ); } @@ -420,7 +420,7 @@ class LogEventsList extends ContextSource { * @return Boolean */ public static function userCanBitfield( $bitfield, $field, User $user = null ) { - if( $bitfield & $field ) { + if ( $bitfield & $field ) { if ( $bitfield & LogPage::DELETED_RESTRICTED ) { $permission = 'suppressrevision'; } else { @@ -450,10 +450,10 @@ class LogEventsList extends ContextSource { * Show log extract. Either with text and a box (set $msgKey) or without (don't set $msgKey) * * @param $out OutputPage|String-by-reference - * @param $types String|Array Log types to show - * @param $page String|Title The page title to show log entries for - * @param $user String The user who made the log entries - * @param $param array Associative Array with the following additional options: + * @param string|array $types Log types to show + * @param string|Title $page The page title to show log entries for + * @param string $user The user who made the log entries + * @param array $param Associative Array with the following additional options: * - lim Integer Limit of items to show, default is 50 * - conds Array Extra conditions for the query (e.g. "log_action != 'revision'") * - showIfEmpty boolean Set to false if you don't want any output in case the loglist is empty @@ -465,18 +465,20 @@ class LogEventsList extends ContextSource { * set to '' to unset offset * - wrap String Wrap the message in html (usually something like "<div ...>$1</div>"). * - flags Integer display flags (NO_ACTION_LINK,NO_EXTRA_USER_LINKS) + * - useRequestParams boolean Set true to use Pager-related parameters in the WebRequest * @return Integer Number of total log items (not limited by $lim) */ public static function showLogExtract( - &$out, $types=array(), $page='', $user='', $param = array() + &$out, $types = array(), $page = '', $user = '', $param = array() ) { $defaultParameters = array( 'lim' => 25, 'conds' => array(), 'showIfEmpty' => true, - 'msgKey' => array(''), + 'msgKey' => array( '' ), 'wrap' => "$1", - 'flags' => 0 + 'flags' => 0, + 'useRequestParams' => false, ); # The + operator appends elements of remaining keys from the right # handed array to the left handed, whereas duplicated keys are NOT overwritten. @@ -488,6 +490,7 @@ class LogEventsList extends ContextSource { $msgKey = $param['msgKey']; $wrap = $param['wrap']; $flags = $param['flags']; + $useRequestParams = $param['useRequestParams']; if ( !is_array( $msgKey ) ) { $msgKey = array( $msgKey ); } @@ -501,13 +504,22 @@ class LogEventsList extends ContextSource { # Insert list of top 50 (or top $lim) items $loglist = new LogEventsList( $context, null, $flags ); $pager = new LogPager( $loglist, $types, $user, $page, '', $conds ); + if ( !$useRequestParams ) { + # Reset vars that may have been taken from the request + $pager->mLimit = 50; + $pager->mDefaultLimit = 50; + $pager->mOffset = ""; + $pager->mIsBackwards = false; + } if ( isset( $param['offset'] ) ) { # Tell pager to ignore WebRequest offset $pager->setOffset( $param['offset'] ); } - if( $lim > 0 ) $pager->mLimit = $lim; + if ( $lim > 0 ) { + $pager->mLimit = $lim; + } $logBody = $pager->getBody(); $s = ''; - if( $logBody ) { + if ( $logBody ) { if ( $msgKey[0] ) { $s = '<div class="mw-warning-with-logexcerpt">'; @@ -520,28 +532,29 @@ class LogEventsList extends ContextSource { } } $s .= $loglist->beginLogEventsList() . - $logBody . - $loglist->endLogEventsList(); - } else { - if ( $showIfEmpty ) { - $s = Html::rawElement( 'div', array( 'class' => 'mw-warning-logempty' ), - $context->msg( 'logempty' )->parse() ); - } + $logBody . + $loglist->endLogEventsList(); + } elseif ( $showIfEmpty ) { + $s = Html::rawElement( 'div', array( 'class' => 'mw-warning-logempty' ), + $context->msg( 'logempty' )->parse() ); } - if( $pager->getNumRows() > $pager->mLimit ) { # Show "Full log" link + if ( $pager->getNumRows() > $pager->mLimit ) { # Show "Full log" link $urlParam = array(); if ( $page instanceof Title ) { $urlParam['page'] = $page->getPrefixedDBkey(); } elseif ( $page != '' ) { $urlParam['page'] = $page; } - if ( $user != '') + if ( $user != '' ) { $urlParam['user'] = $user; - if ( !is_array( $types ) ) # Make it an array, if it isn't + } + if ( !is_array( $types ) ) { # Make it an array, if it isn't $types = array( $types ); + } # If there is exactly one log type, we can link to Special:Log?type=foo - if ( count( $types ) == 1 ) + if ( count( $types ) == 1 ) { $urlParam['type'] = $types[0]; + } $s .= Linker::link( SpecialPage::getTitleFor( 'Log' ), $context->msg( 'log-fulllog' )->escaped(), @@ -560,7 +573,7 @@ class LogEventsList extends ContextSource { /* hook can return false, if we don't want the message to be emitted (Wikia BugId:7093) */ if ( wfRunHooks( 'LogEventsListShowLogExtract', array( &$s, $types, $page, $user, $param ) ) ) { // $out can be either an OutputPage object or a String-by-reference - if ( $out instanceof OutputPage ){ + if ( $out instanceof OutputPage ) { $out->addHTML( $s ); } else { $out = $s; @@ -575,24 +588,31 @@ class LogEventsList extends ContextSource { * * @param $db DatabaseBase * @param $audience string, public/user + * @param $user User object to check, or null to use $wgUser * @return Mixed: string or false */ - public static function getExcludeClause( $db, $audience = 'public' ) { - global $wgLogRestrictions, $wgUser; + public static function getExcludeClause( $db, $audience = 'public', User $user = null ) { + global $wgLogRestrictions; + + if ( $audience != 'public' && $user === null ) { + global $wgUser; + $user = $wgUser; + } + // Reset the array, clears extra "where" clauses when $par is used $hiddenLogs = array(); + // Don't show private logs to unprivileged users - foreach( $wgLogRestrictions as $logType => $right ) { - if( $audience == 'public' || !$wgUser->isAllowed($right) ) { - $safeType = $db->strencode( $logType ); - $hiddenLogs[] = $safeType; + foreach ( $wgLogRestrictions as $logType => $right ) { + if ( $audience == 'public' || !$user->isAllowed( $right ) ) { + $hiddenLogs[] = $logType; } } - if( count($hiddenLogs) == 1 ) { + if ( count( $hiddenLogs ) == 1 ) { return 'log_type != ' . $db->addQuotes( $hiddenLogs[0] ); - } elseif( $hiddenLogs ) { - return 'log_type NOT IN (' . $db->makeList($hiddenLogs) . ')'; + } elseif ( $hiddenLogs ) { + return 'log_type NOT IN (' . $db->makeList( $hiddenLogs ) . ')'; } return false; } - } +} diff --git a/includes/logging/LogFormatter.php b/includes/logging/LogFormatter.php index 7586bb65..8f60aee1 100644 --- a/includes/logging/LogFormatter.php +++ b/includes/logging/LogFormatter.php @@ -192,18 +192,18 @@ class LogFormatter { $parameters = $entry->getParameters(); // @see LogPage::actionText() // Text of title the action is aimed at. - $target = $entry->getTarget()->getPrefixedText() ; + $target = $entry->getTarget()->getPrefixedText(); $text = null; - switch( $entry->getType() ) { + switch ( $entry->getType() ) { case 'move': - switch( $entry->getSubtype() ) { + switch ( $entry->getSubtype() ) { case 'move': - $movesource = $parameters['4::target']; + $movesource = $parameters['4::target']; $text = wfMessage( '1movedto2' ) ->rawParams( $target, $movesource )->inContentLanguage()->escaped(); break; case 'move_redir': - $movesource = $parameters['4::target']; + $movesource = $parameters['4::target']; $text = wfMessage( '1movedto2_redir' ) ->rawParams( $target, $movesource )->inContentLanguage()->escaped(); break; @@ -215,7 +215,7 @@ class LogFormatter { break; case 'delete': - switch( $entry->getSubtype() ) { + switch ( $entry->getSubtype() ) { case 'delete': $text = wfMessage( 'deletedarticle' ) ->rawParams( $target )->inContentLanguage()->escaped(); @@ -246,7 +246,7 @@ class LogFormatter { break; case 'protect': - switch( $entry->getSubtype() ) { + switch ( $entry->getSubtype() ) { case 'protect': $text = wfMessage( 'protectedarticle' ) ->rawParams( $target . ' ' . $parameters[0] )->inContentLanguage()->escaped(); @@ -263,13 +263,14 @@ class LogFormatter { break; case 'newusers': - switch( $entry->getSubtype() ) { + switch ( $entry->getSubtype() ) { case 'newusers': case 'create': $text = wfMessage( 'newuserlog-create-entry' ) ->inContentLanguage()->escaped(); break; case 'create2': + case 'byemail': $text = wfMessage( 'newuserlog-create2-entry' ) ->rawParams( $target )->inContentLanguage()->escaped(); break; @@ -281,7 +282,7 @@ class LogFormatter { break; case 'upload': - switch( $entry->getSubtype() ) { + switch ( $entry->getSubtype() ) { case 'upload': $text = wfMessage( 'uploadedimage' ) ->rawParams( $target )->inContentLanguage()->escaped(); @@ -293,11 +294,33 @@ class LogFormatter { } break; + case 'rights': + if ( count( $parameters['4::oldgroups'] ) ) { + $oldgroups = implode( ', ', $parameters['4::oldgroups'] ); + } else { + $oldgroups = wfMessage( 'rightsnone' )->inContentLanguage()->escaped(); + } + if ( count( $parameters['5::newgroups'] ) ) { + $newgroups = implode( ', ', $parameters['5::newgroups'] ); + } else { + $newgroups = wfMessage( 'rightsnone' )->inContentLanguage()->escaped(); + } + switch ( $entry->getSubtype() ) { + case 'rights': + $text = wfMessage( 'rightslogentry' ) + ->rawParams( $target, $oldgroups, $newgroups )->inContentLanguage()->escaped(); + break; + case 'autopromote': + $text = wfMessage( 'rightslogentry-autopromote' ) + ->rawParams( $target, $oldgroups, $newgroups )->inContentLanguage()->escaped(); + break; + } + break; // case 'suppress' --private log -- aaron (sign your messages so we know who to blame in a few years :-D) // default: } - if( is_null( $text ) ) { + if ( is_null( $text ) ) { $text = $this->getPlainActionText(); } @@ -379,9 +402,11 @@ class LogFormatter { // Filter out parameters which are not in format #:foo foreach ( $entry->getParameters() as $key => $value ) { - if ( strpos( $key, ':' ) === false ) continue; - list( $index, $type, $name ) = explode( ':', $key, 3 ); - $params[$index - 1] = $value; + if ( strpos( $key, ':' ) === false ) { + continue; + } + list( $index, $type, ) = explode( ':', $key, 3 ); + $params[$index - 1] = $this->formatParameterValue( $type, $value ); } /* Message class doesn't like non consecutive numbering. @@ -416,7 +441,7 @@ class LogFormatter { $entry = $this->entry; $params = $this->extractParameters(); $params[0] = Message::rawParam( $this->getPerformerElement() ); - $params[1] = $entry->getPerformer()->getName(); + $params[1] = $this->canView( LogPage::DELETED_USER ) ? $entry->getPerformer()->getName() : ''; $params[2] = Message::rawParam( $this->makePageLink( $entry->getTarget() ) ); // Bad things happens if the numbers are not in correct order @@ -425,10 +450,83 @@ class LogFormatter { } /** + * Formats parameters values dependent to their type + * @param string $type The type of the value. + * Valid are currently: + * * - (empty) or plain: The value is returned as-is + * * raw: The value will be added to the log message + * as raw parameter (e.g. no escaping) + * Use this only if there is no other working + * type like user-link or title-link + * * msg: The value is a message-key, the output is + * the message in user language + * * msg-content: The value is a message-key, the output + * is the message in content language + * * user: The value is a user name, e.g. for GENDER + * * user-link: The value is a user name, returns a + * link for the user + * * title: The value is a page title, + * returns name of page + * * title-link: The value is a page title, + * returns link to this page + * * number: Format value as number + * @param string $value The parameter value that should + * be formated + * @return string or Message::numParam or Message::rawParam + * Formated value + * @since 1.21 + */ + protected function formatParameterValue( $type, $value ) { + $saveLinkFlood = $this->linkFlood; + + switch ( strtolower( trim( $type ) ) ) { + case 'raw': + $value = Message::rawParam( $value ); + break; + case 'msg': + $value = $this->msg( $value )->text(); + break; + case 'msg-content': + $value = $this->msg( $value )->inContentLanguage()->text(); + break; + case 'number': + $value = Message::numParam( $value ); + break; + case 'user': + $user = User::newFromName( $value ); + $value = $user->getName(); + break; + case 'user-link': + $this->setShowUserToolLinks( false ); + + $user = User::newFromName( $value ); + $value = Message::rawParam( $this->makeUserLink( $user ) ); + + $this->setShowUserToolLinks( $saveLinkFlood ); + break; + case 'title': + $title = Title::newFromText( $value ); + $value = $title->getPrefixedText(); + break; + case 'title-link': + $title = Title::newFromText( $value ); + $value = Message::rawParam( $this->makePageLink( $title ) ); + break; + case 'plain': + // Plain text, nothing to do + default: + // Catch other types and use the old behavior (return as-is) + } + + return $value; + } + + /** * Helper to make a link to the page, taking the plaintext * value in consideration. * @param $title Title the page - * @param $parameters array query parameters + * @param array $parameters query parameters + * @throws MWException * @return String */ protected function makePageLink( Title $title = null, $parameters = array() ) { @@ -492,7 +590,7 @@ class LogFormatter { return $this->msg( $message )->text(); } - $content = $this->msg( $message )->escaped(); + $content = $this->msg( $message )->escaped(); $attribs = array( 'class' => 'history-deleted' ); return Html::rawElement( 'span', $attribs, $content ); } @@ -547,6 +645,16 @@ class LogFormatter { return array(); } + /** + * @return Output of getMessageParameters() for testing + */ + public function getMessageParametersForTesting() { + // This function was added because getMessageParameters() is + // protected and a change from protected to public caused + // problems with extensions + return $this->getMessageParameters(); + } + } /** @@ -607,7 +715,7 @@ class LegacyLogFormatter extends LogFormatter { $performer = $this->getPerformerElement(); if ( !$this->irctext ) { - $action = $performer . $this->msg( 'word-separator' )->text() . $action; + $action = $performer . $this->msg( 'word-separator' )->text() . $action; } return $action; @@ -667,7 +775,7 @@ class LegacyLogFormatter extends LogFormatter { return $this->msg( 'parentheses' )->rawParams( $this->context->getLanguage()->pipeList( $links ) )->escaped(); // Show unmerge link - } elseif( $type == 'merge' && $subtype == 'merge' ) { + } elseif ( $type == 'merge' && $subtype == 'merge' ) { if ( !$this->context->getUser()->isAllowed( 'mergehistory' ) ) { return ''; } @@ -706,305 +814,3 @@ class LegacyLogFormatter extends LogFormatter { } } -/** - * This class formats move log entries. - * @since 1.19 - */ -class MoveLogFormatter extends LogFormatter { - public function getPreloadTitles() { - $params = $this->extractParameters(); - return array( Title::newFromText( $params[3] ) ); - } - - protected function getMessageKey() { - $key = parent::getMessageKey(); - $params = $this->getMessageParameters(); - if ( isset( $params[4] ) && $params[4] === '1' ) { - $key .= '-noredirect'; - } - return $key; - } - - protected function getMessageParameters() { - $params = parent::getMessageParameters(); - $oldname = $this->makePageLink( $this->entry->getTarget(), array( 'redirect' => 'no' ) ); - $newname = $this->makePageLink( Title::newFromText( $params[3] ) ); - $params[2] = Message::rawParam( $oldname ); - $params[3] = Message::rawParam( $newname ); - return $params; - } - - public function getActionLinks() { - if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) // Action is hidden - || $this->entry->getSubtype() !== 'move' - || !$this->context->getUser()->isAllowed( 'move' ) ) - { - return ''; - } - - $params = $this->extractParameters(); - $destTitle = Title::newFromText( $params[3] ); - if ( !$destTitle ) { - return ''; - } - - $revert = Linker::linkKnown( - SpecialPage::getTitleFor( 'Movepage' ), - $this->msg( 'revertmove' )->escaped(), - array(), - array( - 'wpOldTitle' => $destTitle->getPrefixedDBkey(), - 'wpNewTitle' => $this->entry->getTarget()->getPrefixedDBkey(), - 'wpReason' => $this->msg( 'revertmove' )->inContentLanguage()->text(), - 'wpMovetalk' => 0 - ) - ); - return $this->msg( 'parentheses' )->rawParams( $revert )->escaped(); - } -} - -/** - * This class formats delete log entries. - * @since 1.19 - */ -class DeleteLogFormatter extends LogFormatter { - protected function getMessageKey() { - $key = parent::getMessageKey(); - if ( in_array( $this->entry->getSubtype(), array( 'event', 'revision' ) ) ) { - if ( count( $this->getMessageParameters() ) < 5 ) { - return "$key-legacy"; - } - } - return $key; - } - - protected function getMessageParameters() { - if ( isset( $this->parsedParametersDeleteLog ) ) { - return $this->parsedParametersDeleteLog; - } - - $params = parent::getMessageParameters(); - $subtype = $this->entry->getSubtype(); - if ( in_array( $subtype, array( 'event', 'revision' ) ) ) { - if ( - ($subtype === 'event' && count( $params ) === 6 ) || - ($subtype === 'revision' && isset( $params[3] ) && $params[3] === 'revision' ) - ) { - $paramStart = $subtype === 'revision' ? 4 : 3; - - $old = $this->parseBitField( $params[$paramStart+1] ); - $new = $this->parseBitField( $params[$paramStart+2] ); - list( $hid, $unhid, $extra ) = RevisionDeleter::getChanges( $new, $old ); - $changes = array(); - foreach ( $hid as $v ) { - $changes[] = $this->msg( "$v-hid" )->plain(); - } - foreach ( $unhid as $v ) { - $changes[] = $this->msg( "$v-unhid" )->plain(); - } - foreach ( $extra as $v ) { - $changes[] = $this->msg( $v )->plain(); - } - $changeText = $this->context->getLanguage()->listToText( $changes ); - - - $newParams = array_slice( $params, 0, 3 ); - $newParams[3] = $changeText; - $count = count( explode( ',', $params[$paramStart] ) ); - $newParams[4] = $this->context->getLanguage()->formatNum( $count ); - return $this->parsedParametersDeleteLog = $newParams; - } else { - return $this->parsedParametersDeleteLog = array_slice( $params, 0, 3 ); - } - } - - return $this->parsedParametersDeleteLog = $params; - } - - protected function parseBitField( $string ) { - // Input is like ofield=2134 or just the number - if ( strpos( $string, 'field=' ) === 1 ) { - list( , $field ) = explode( '=', $string ); - return (int) $field; - } else { - return (int) $string; - } - } - - public function getActionLinks() { - $user = $this->context->getUser(); - if ( !$user->isAllowed( 'deletedhistory' ) || $this->entry->isDeleted( LogPage::DELETED_ACTION ) ) { - return ''; - } - - switch ( $this->entry->getSubtype() ) { - case 'delete': // Show undelete link - if( $user->isAllowed( 'undelete' ) ) { - $message = 'undeletelink'; - } else { - $message = 'undeleteviewlink'; - } - $revert = Linker::linkKnown( - SpecialPage::getTitleFor( 'Undelete' ), - $this->msg( $message )->escaped(), - array(), - array( 'target' => $this->entry->getTarget()->getPrefixedDBkey() ) - ); - return $this->msg( 'parentheses' )->rawParams( $revert )->escaped(); - - case 'revision': // If an edit was hidden from a page give a review link to the history - $params = $this->extractParameters(); - if ( !isset( $params[3] ) || !isset( $params[4] ) ) { - return ''; - } - - // Different revision types use different URL params... - $key = $params[3]; - // This is a CSV of the IDs - $ids = explode( ',', $params[4] ); - - $links = array(); - - // If there's only one item, we can show a diff link - if ( count( $ids ) == 1 ) { - // Live revision diffs... - if ( $key == 'oldid' || $key == 'revision' ) { - $links[] = Linker::linkKnown( - $this->entry->getTarget(), - $this->msg( 'diff' )->escaped(), - array(), - array( - 'diff' => intval( $ids[0] ), - 'unhide' => 1 - ) - ); - // Deleted revision diffs... - } elseif ( $key == 'artimestamp' || $key == 'archive' ) { - $links[] = Linker::linkKnown( - SpecialPage::getTitleFor( 'Undelete' ), - $this->msg( 'diff' )->escaped(), - array(), - array( - 'target' => $this->entry->getTarget()->getPrefixedDBKey(), - 'diff' => 'prev', - 'timestamp' => $ids[0] - ) - ); - } - } - - // View/modify link... - $links[] = Linker::linkKnown( - SpecialPage::getTitleFor( 'Revisiondelete' ), - $this->msg( 'revdel-restore' )->escaped(), - array(), - array( - 'target' => $this->entry->getTarget()->getPrefixedText(), - 'type' => $key, - 'ids' => implode( ',', $ids ), - ) - ); - - return $this->msg( 'parentheses' )->rawParams( - $this->context->getLanguage()->pipeList( $links ) )->escaped(); - - case 'event': // Hidden log items, give review link - $params = $this->extractParameters(); - if ( !isset( $params[3] ) ) { - return ''; - } - // This is a CSV of the IDs - $query = $params[3]; - // Link to each hidden object ID, $params[1] is the url param - $revert = Linker::linkKnown( - SpecialPage::getTitleFor( 'Revisiondelete' ), - $this->msg( 'revdel-restore' )->escaped(), - array(), - array( - 'target' => $this->entry->getTarget()->getPrefixedText(), - 'type' => 'logging', - 'ids' => $query - ) - ); - return $this->msg( 'parentheses' )->rawParams( $revert )->escaped(); - default: - return ''; - } - } -} - -/** - * This class formats patrol log entries. - * @since 1.19 - */ -class PatrolLogFormatter extends LogFormatter { - protected function getMessageKey() { - $key = parent::getMessageKey(); - $params = $this->getMessageParameters(); - if ( isset( $params[5] ) && $params[5] ) { - $key .= '-auto'; - } - return $key; - } - - protected function getMessageParameters() { - $params = parent::getMessageParameters(); - - $target = $this->entry->getTarget(); - $oldid = $params[3]; - $revision = $this->context->getLanguage()->formatNum( $oldid, true ); - - if ( $this->plaintext ) { - $revlink = $revision; - } elseif ( $target->exists() ) { - $query = array( - 'oldid' => $oldid, - 'diff' => 'prev' - ); - $revlink = Linker::link( $target, htmlspecialchars( $revision ), array(), $query ); - } else { - $revlink = htmlspecialchars( $revision ); - } - - $params[3] = Message::rawParam( $revlink ); - return $params; - } -} - -/** - * This class formats new user log entries. - * @since 1.19 - */ -class NewUsersLogFormatter extends LogFormatter { - protected function getMessageParameters() { - $params = parent::getMessageParameters(); - if ( $this->entry->getSubtype() === 'create2' ) { - if ( isset( $params[3] ) ) { - $target = User::newFromId( $params[3] ); - } else { - $target = User::newFromName( $this->entry->getTarget()->getText(), false ); - } - $params[2] = Message::rawParam( $this->makeUserLink( $target ) ); - $params[3] = $target->getName(); - } - return $params; - } - - public function getComment() { - $timestamp = wfTimestamp( TS_MW, $this->entry->getTimestamp() ); - if ( $timestamp < '20080129000000' ) { - # Suppress $comment from old entries (before 2008-01-29), - # not needed and can contain incorrect links - return ''; - } - return parent::getComment(); - } - - public function getPreloadTitles() { - if ( $this->entry->getSubtype() === 'create2' ) { - //add the user talk to LinkBatch for the userLink - return array( Title::makeTitle( NS_USER_TALK, $this->entry->getTarget()->getText() ) ); - } - return array(); - } -} diff --git a/includes/logging/LogPage.php b/includes/logging/LogPage.php index d96a5ea5..cc473c18 100644 --- a/includes/logging/LogPage.php +++ b/includes/logging/LogPage.php @@ -50,16 +50,16 @@ class LogPage { */ var $target; - /* @acess public */ + /* @access public */ var $updateRecentChanges, $sendToUDP; /** * Constructor * - * @param $type String: one of '', 'block', 'protect', 'rights', 'delete', + * @param string $type one of '', 'block', 'protect', 'rights', 'delete', * 'upload', 'move' * @param $rc Boolean: whether to update recent changes as well as the logging table - * @param $udp String: pass 'UDP' to send to the UDP feed if NOT sent to RC + * @param string $udp pass 'UDP' to send to the UDP feed if NOT sent to RC */ public function __construct( $type, $rc = true, $udp = 'skipUDP' ) { $this->type = $type; @@ -94,7 +94,7 @@ class LogPage { $newId = !is_null( $log_id ) ? $log_id : $dbw->insertId(); # And update recentchanges - if( $this->updateRecentChanges ) { + if ( $this->updateRecentChanges ) { $titleObj = SpecialPage::getTitleFor( 'Log', $this->type ); RecentChange::notifyLog( @@ -102,9 +102,9 @@ class LogPage { $this->type, $this->action, $this->target, $this->comment, $this->params, $newId, $this->getRcCommentIRC() ); - } elseif( $this->sendToUDP ) { + } elseif ( $this->sendToUDP ) { # Don't send private logs to UDP - if( isset( $wgLogRestrictions[$this->type] ) && $wgLogRestrictions[$this->type] != '*' ) { + if ( isset( $wgLogRestrictions[$this->type] ) && $wgLogRestrictions[$this->type] != '*' ) { return $newId; } @@ -129,7 +129,7 @@ class LogPage { public function getRcComment() { $rcComment = $this->actionText; - if( $this->comment != '' ) { + if ( $this->comment != '' ) { if ( $rcComment == '' ) { $rcComment = $this->comment; } else { @@ -149,7 +149,7 @@ class LogPage { public function getRcCommentIRC() { $rcComment = $this->ircActionText; - if( $this->comment != '' ) { + if ( $this->comment != '' ) { if ( $rcComment == '' ) { $rcComment = $this->comment; } else { @@ -181,7 +181,7 @@ class LogPage { /** * Is $type a valid log type * - * @param $type String: log type to check + * @param string $type log type to check * @return Boolean */ public static function isLogType( $type ) { @@ -191,14 +191,14 @@ class LogPage { /** * Get the name for the given log type * - * @param $type String: logtype + * @param string $type logtype * @return String: log name * @deprecated in 1.19, warnings in 1.21. Use getName() */ public static function logName( $type ) { global $wgLogNames; - if( isset( $wgLogNames[$type] ) ) { + if ( isset( $wgLogNames[$type] ) ) { return str_replace( '_', ' ', wfMessage( $wgLogNames[$type] )->text() ); } else { // Bogus log types? Perhaps an extension was removed. @@ -210,7 +210,7 @@ class LogPage { * Get the log header for the given log type * * @todo handle missing log types - * @param $type String: logtype + * @param string $type logtype * @return String: headertext of this logtype * @deprecated in 1.19, warnings in 1.21. Use getDescription() */ @@ -220,15 +220,15 @@ class LogPage { } /** - * Generate text for a log entry. + * Generate text for a log entry. * Only LogFormatter should call this function. * - * @param $type String: log type - * @param $action String: log action + * @param string $type log type + * @param string $action log action * @param $title Mixed: Title object or null * @param $skin Mixed: Skin object or null. If null, we want to use the wiki * content language, since that will go to the IRC feed. - * @param $params Array: parameters + * @param array $params parameters * @param $filterWikilinks Boolean: whether to filter wiki links * @return HTML string */ @@ -247,36 +247,13 @@ class LogPage { $key = "$type/$action"; - if( isset( $wgLogActions[$key] ) ) { - if( is_null( $title ) ) { + if ( isset( $wgLogActions[$key] ) ) { + if ( is_null( $title ) ) { $rv = wfMessage( $wgLogActions[$key] )->inLanguage( $langObj )->escaped(); } else { $titleLink = self::getTitleLink( $type, $langObjOrNull, $title, $params ); - if( preg_match( '/^rights\/(rights|autopromote)/', $key ) ) { - $rightsnone = wfMessage( 'rightsnone' )->inLanguage( $langObj )->text(); - - if( $skin ) { - $username = $title->getText(); - foreach ( $params as &$param ) { - $groupArray = array_map( 'trim', explode( ',', $param ) ); - foreach( $groupArray as &$group ) { - $group = User::getGroupMember( $group, $username ); - } - $param = $wgLang->listToText( $groupArray ); - } - } - - if( !isset( $params[0] ) || trim( $params[0] ) == '' ) { - $params[0] = $rightsnone; - } - - if( !isset( $params[1] ) || trim( $params[1] ) == '' ) { - $params[1] = $rightsnone; - } - } - - if( count( $params ) == 0 ) { + if ( count( $params ) == 0 ) { $rv = wfMessage( $wgLogActions[$key] )->rawParams( $titleLink )->inLanguage( $langObj )->escaped(); } else { $details = ''; @@ -285,7 +262,7 @@ class LogPage { // User suppression if ( preg_match( '/^(block|suppress)\/(block|reblock)$/', $key ) ) { if ( $skin ) { - $params[1] = '<span class="blockExpiry" dir="ltr" title="' . htmlspecialchars( $params[1] ). '">' . + $params[1] = '<span class="blockExpiry" title="‎' . htmlspecialchars( $params[1] ) . '">' . $wgLang->translateBlockExpiry( $params[1] ) . '</span>'; } else { $params[1] = $wgContLang->translateBlockExpiry( $params[1] ); @@ -294,16 +271,16 @@ class LogPage { $params[2] = isset( $params[2] ) ? self::formatBlockFlags( $params[2], $langObj ) : ''; // Page protections - } elseif ( $type == 'protect' && count($params) == 3 ) { + } elseif ( $type == 'protect' && count( $params ) == 3 ) { // Restrictions and expiries - if( $skin ) { + if ( $skin ) { $details .= $wgLang->getDirMark() . htmlspecialchars( " {$params[1]}" ); } else { $details .= " {$params[1]}"; } // Cascading flag... - if( $params[2] ) { + if ( $params[2] ) { $details .= ' [' . wfMessage( 'protect-summary-cascade' )->inLanguage( $langObj )->text() . ']'; } } @@ -314,7 +291,7 @@ class LogPage { } else { global $wgLogActionsHandlers; - if( isset( $wgLogActionsHandlers[$key] ) ) { + if ( isset( $wgLogActionsHandlers[$key] ) ) { $args = func_get_args(); $rv = call_user_func_array( $wgLogActionsHandlers[$key], $args ); } else { @@ -333,7 +310,7 @@ class LogPage { // you want to link to something OTHER than the title of the log entry. // The real problem, which Erik was trying to fix (and it sort-of works now) is // that the same messages are being treated as both wikitext *and* HTML. - if( $filterWikilinks ) { + if ( $filterWikilinks ) { $rv = str_replace( '[[', '', $rv ); $rv = str_replace( ']]', '', $rv ); } @@ -350,13 +327,11 @@ class LogPage { * @return String */ protected static function getTitleLink( $type, $lang, $title, &$params ) { - global $wgContLang, $wgUserrightsInterwikiDelimiter; - - if( !$lang ) { + if ( !$lang ) { return $title->getPrefixedText(); } - switch( $type ) { + switch ( $type ) { case 'move': $titleLink = Linker::link( $title, @@ -378,7 +353,7 @@ class LogPage { } break; case 'block': - if( substr( $title->getText(), 0, 1 ) == '#' ) { + if ( substr( $title->getText(), 0, 1 ) == '#' ) { $titleLink = $title->getText(); } else { // @todo Store the user identifier in the parameters @@ -388,20 +363,6 @@ class LogPage { . Linker::userToolLinks( $id, $title->getText(), false, Linker::TOOL_LINKS_NOBLOCK ); } break; - case 'rights': - $text = $wgContLang->ucfirst( $title->getText() ); - $parts = explode( $wgUserrightsInterwikiDelimiter, $text, 2 ); - - if ( count( $parts ) == 2 ) { - $titleLink = WikiMap::foreignUserLink( $parts[1], $parts[0], - htmlspecialchars( $title->getPrefixedText() ) ); - - if ( $titleLink !== false ) { - break; - } - } - $titleLink = Linker::link( Title::makeTitle( NS_USER, $text ) ); - break; case 'merge': $titleLink = Linker::link( $title, @@ -416,11 +377,11 @@ class LogPage { $params[1] = $lang->timeanddate( $params[1] ); break; default: - if( $title->isSpecialPage() ) { + if ( $title->isSpecialPage() ) { list( $name, $par ) = SpecialPageFactory::resolveAlias( $title->getDBkey() ); # Use the language name for log titles, rather than Log/X - if( $name == 'Log' ) { + if ( $name == 'Log' ) { $logPage = new LogPage( $par ); $titleLink = Linker::link( $title, $logPage->getName()->escaped() ); $titleLink = wfMessage( 'parentheses' ) @@ -441,10 +402,10 @@ class LogPage { /** * Add a log entry * - * @param $action String: one of '', 'block', 'protect', 'rights', 'delete', 'upload', 'move', 'move_redir' + * @param string $action one of '', 'block', 'protect', 'rights', 'delete', 'upload', 'move', 'move_redir' * @param $target Title object - * @param $comment String: description associated - * @param $params Array: parameters passed later to wfMessage function + * @param string $comment description associated + * @param array $params parameters passed later to wfMessage function * @param $doer User object: the user doing the action * * @return int log_id of the inserted log entry @@ -460,6 +421,9 @@ class LogPage { $comment = ''; } + # Trim spaces on user supplied text + $comment = trim( $comment ); + # Truncate for whole multibyte characters. $comment = $wgContLang->truncate( $comment, 255 ); @@ -501,13 +465,13 @@ class LogPage { * @return Boolean */ public function addRelations( $field, $values, $logid ) { - if( !strlen( $field ) || empty( $values ) ) { + if ( !strlen( $field ) || empty( $values ) ) { return false; // nothing } $data = array(); - foreach( $values as $value ) { + foreach ( $values as $value ) { $data[] = array( 'ls_field' => $field, 'ls_value' => $value, @@ -549,35 +513,35 @@ class LogPage { * Convert a comma-delimited list of block log flags * into a more readable (and translated) form * - * @param $flags string Flags to format + * @param string $flags Flags to format * @param $lang Language object to use * @return String */ public static function formatBlockFlags( $flags, $lang ) { - $flags = explode( ',', trim( $flags ) ); + $flags = trim( $flags ); + if ( $flags === '' ) { + return ''; //nothing to do + } + $flags = explode( ',', $flags ); - if( count( $flags ) > 0 ) { - for( $i = 0; $i < count( $flags ); $i++ ) { - $flags[$i] = self::formatBlockFlag( $flags[$i], $lang ); - } - return wfMessage( 'parentheses' )->inLanguage( $lang ) - ->rawParams( $lang->commaList( $flags ) )->escaped(); - } else { - return ''; + for ( $i = 0; $i < count( $flags ); $i++ ) { + $flags[$i] = self::formatBlockFlag( $flags[$i], $lang ); } + return wfMessage( 'parentheses' )->inLanguage( $lang ) + ->rawParams( $lang->commaList( $flags ) )->escaped(); } /** * Translate a block log flag if possible * - * @param $flag int Flag to translate + * @param int $flag Flag to translate * @param $lang Language object to use * @return String */ public static function formatBlockFlag( $flag, $lang ) { static $messages = array(); - if( !isset( $messages[$flag] ) ) { + if ( !isset( $messages[$flag] ) ) { $messages[$flag] = htmlspecialchars( $flag ); // Fallback // For grepping. The following core messages can be used here: @@ -598,7 +562,6 @@ class LogPage { return $messages[$flag]; } - /** * Name of the log. * @return Message diff --git a/includes/logging/LogPager.php b/includes/logging/LogPager.php index ea1be8e0..09ae3b8c 100644 --- a/includes/logging/LogPager.php +++ b/includes/logging/LogPager.php @@ -34,15 +34,15 @@ class LogPager extends ReverseChronologicalPager { /** * Constructor * - * @param $list LogEventsList - * @param $types String or Array: log types to show - * @param $performer String: the user who made the log entries - * @param $title String|Title: the page title the log entries are for - * @param $pattern String: do a prefix search rather than an exact title match - * @param $conds Array: extra conditions for the query - * @param $year Integer: the year to start from - * @param $month Integer: the month to start from - * @param $tagFilter String: tag + * @param LogEventsList $list + * @param string $types or Array: log types to show + * @param string $performer the user who made the log entries + * @param string|Title $title the page title the log entries are for + * @param string $pattern do a prefix search rather than an exact title match + * @param array $conds extra conditions for the query + * @param int $year The year to start from + * @param int $month The month to start from + * @param string $tagFilter tag */ public function __construct( $list, $types = array(), $performer = '', $title = '', $pattern = '', $conds = array(), $year = false, $month = false, $tagFilter = '' ) { @@ -71,16 +71,17 @@ class LogPager extends ReverseChronologicalPager { public function getFilterParams() { global $wgFilterLogTypes; $filters = array(); - if( count($this->types) ) { + if ( count( $this->types ) ) { return $filters; } - foreach( $wgFilterLogTypes as $type => $default ) { + foreach ( $wgFilterLogTypes as $type => $default ) { // Avoid silly filtering - if( $type !== 'patrol' || $this->getUser()->useNPPatrol() ) { + if ( $type !== 'patrol' || $this->getUser()->useNPPatrol() ) { $hide = $this->getRequest()->getInt( "hide_{$type}_log", $default ); $filters[$type] = $hide; - if( $hide ) + if ( $hide ) { $this->mConds[] = 'log_type != ' . $this->mDb->addQuotes( $type ); + } } } return $filters; @@ -90,18 +91,20 @@ class LogPager extends ReverseChronologicalPager { * Set the log reader to return only entries of the given type. * Type restrictions enforced here * - * @param $types String or array: Log types ('upload', 'delete', etc); + * @param string $types or array: Log types ('upload', 'delete', etc); * empty string means no restriction */ private function limitType( $types ) { global $wgLogRestrictions; + + $user = $this->getUser(); // If $types is not an array, make it an array - $types = ($types === '') ? array() : (array)$types; + $types = ( $types === '' ) ? array() : (array)$types; // Don't even show header for private logs; don't recognize it... $needReindex = false; foreach ( $types as $type ) { - if( isset( $wgLogRestrictions[$type] ) - && !$this->getUser()->isAllowed($wgLogRestrictions[$type]) + if ( isset( $wgLogRestrictions[$type] ) + && !$user->isAllowed( $wgLogRestrictions[$type] ) ) { $needReindex = true; $types = array_diff( $types, array( $type ) ); @@ -116,34 +119,36 @@ class LogPager extends ReverseChronologicalPager { // Don't show private logs to unprivileged users. // Also, only show them upon specific request to avoid suprises. $audience = $types ? 'user' : 'public'; - $hideLogs = LogEventsList::getExcludeClause( $this->mDb, $audience ); - if( $hideLogs !== false ) { + $hideLogs = LogEventsList::getExcludeClause( $this->mDb, $audience, $user ); + if ( $hideLogs !== false ) { $this->mConds[] = $hideLogs; } - if( count($types) ) { + if ( count( $types ) ) { $this->mConds['log_type'] = $types; // Set typeCGI; used in url param for paging - if( count($types) == 1 ) $this->typeCGI = $types[0]; + if ( count( $types ) == 1 ) { + $this->typeCGI = $types[0]; + } } } /** * Set the log reader to return only entries by the given user. * - * @param $name String: (In)valid user name + * @param string $name (In)valid user name * @return bool */ private function limitPerformer( $name ) { - if( $name == '' ) { + if ( $name == '' ) { return false; } $usertitle = Title::makeTitleSafe( NS_USER, $name ); - if( is_null($usertitle) ) { + if ( is_null( $usertitle ) ) { return false; } /* Fetch userid at first, if known, provides awesome query plan afterwards */ $userid = User::idFromName( $name ); - if( !$userid ) { + if ( !$userid ) { /* It should be nicer to abort query at all, but for now it won't pass anywhere behind the optimizer */ $this->mConds[] = "NULL"; @@ -151,10 +156,10 @@ class LogPager extends ReverseChronologicalPager { $this->mConds['log_user'] = $userid; // Paranoia: avoid brute force searches (bug 17342) $user = $this->getUser(); - if( !$user->isAllowed( 'deletedhistory' ) ) { - $this->mConds[] = $this->mDb->bitAnd('log_deleted', LogPage::DELETED_USER) . ' = 0'; - } elseif( !$user->isAllowed( 'suppressrevision' ) ) { - $this->mConds[] = $this->mDb->bitAnd('log_deleted', LogPage::SUPPRESSED_USER) . + if ( !$user->isAllowed( 'deletedhistory' ) ) { + $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::DELETED_USER ) . ' = 0'; + } elseif ( !$user->isAllowed( 'suppressrevision' ) ) { + $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::SUPPRESSED_USER ) . ' != ' . LogPage::SUPPRESSED_USER; } $this->performer = $usertitle->getText(); @@ -165,7 +170,7 @@ class LogPager extends ReverseChronologicalPager { * Set the log reader to return only entries affecting the given page. * (For the block and rights logs, this is a user page.) * - * @param $page String or Title object: Title name + * @param string $page or Title object: Title name * @param $pattern String * @return bool */ @@ -176,7 +181,7 @@ class LogPager extends ReverseChronologicalPager { $title = $page; } else { $title = Title::newFromText( $page ); - if( strlen( $page ) == 0 || !$title instanceof Title ) { + if ( strlen( $page ) == 0 || !$title instanceof Title ) { return false; } } @@ -196,7 +201,7 @@ class LogPager extends ReverseChronologicalPager { # use the page_time index. That should have no more than a few hundred # log entries for even the busiest pages, so it can be safely scanned # in full to satisfy an impossible condition on user or similar. - if( $pattern && !$wgMiserMode ) { + if ( $pattern && !$wgMiserMode ) { $this->mConds['log_namespace'] = $ns; $this->mConds[] = 'log_title ' . $db->buildLike( $title->getDBkey(), $db->anyString() ); $this->pattern = $pattern; @@ -206,10 +211,10 @@ class LogPager extends ReverseChronologicalPager { } // Paranoia: avoid brute force searches (bug 17342) $user = $this->getUser(); - if( !$user->isAllowed( 'deletedhistory' ) ) { - $this->mConds[] = $db->bitAnd('log_deleted', LogPage::DELETED_ACTION) . ' = 0'; - } elseif( !$user->isAllowed( 'suppressrevision' ) ) { - $this->mConds[] = $db->bitAnd('log_deleted', LogPage::SUPPRESSED_ACTION) . + if ( !$user->isAllowed( 'deletedhistory' ) ) { + $this->mConds[] = $db->bitAnd( 'log_deleted', LogPage::DELETED_ACTION ) . ' = 0'; + } elseif ( !$user->isAllowed( 'suppressrevision' ) ) { + $this->mConds[] = $db->bitAnd( 'log_deleted', LogPage::SUPPRESSED_ACTION ) . ' != ' . LogPage::SUPPRESSED_ACTION; } } @@ -232,7 +237,7 @@ class LogPager extends ReverseChronologicalPager { # Add log_search table if there are conditions on it. # This filters the results to only include log rows that have # log_search records with the specified ls_field and ls_value values. - if( array_key_exists( 'ls_field', $this->mConds ) ) { + if ( array_key_exists( 'ls_field', $this->mConds ) ) { $tables[] = 'log_search'; $index['log_search'] = 'ls_field_val'; $index['logging'] = 'PRIMARY'; @@ -244,28 +249,18 @@ class LogPager extends ReverseChronologicalPager { # no duplicate log rows. Otherwise, we need to remove the duplicates. $options[] = 'DISTINCT'; } - # Avoid usage of the wrong index by limiting - # the choices of available indexes. This mainly - # avoids site-breaking filesorts. - } elseif( $this->title || $this->pattern || $this->performer ) { - $index['logging'] = array( 'page_time', 'user_time' ); - if( count($this->types) == 1 ) { - $index['logging'][] = 'log_user_type_time'; - } - } elseif( count($this->types) == 1 ) { - $index['logging'] = 'type_time'; - } else { - $index['logging'] = 'times'; } - $options['USE INDEX'] = $index; + if ( count( $index ) ) { + $options['USE INDEX'] = $index; + } # Don't show duplicate rows when using log_search $joins['log_search'] = array( 'INNER JOIN', 'ls_log_id=log_id' ); $info = array( - 'tables' => $tables, - 'fields' => $fields, - 'conds' => array_merge( $conds, $this->mConds ), - 'options' => $options, + 'tables' => $tables, + 'fields' => $fields, + 'conds' => array_merge( $conds, $this->mConds ), + 'options' => $options, 'join_conds' => $joins, ); # Add ChangeTags filter query @@ -293,7 +288,7 @@ class LogPager extends ReverseChronologicalPager { public function getStartBody() { wfProfileIn( __METHOD__ ); # Do a link batch query - if( $this->getNumRows() > 0 ) { + if ( $this->getNumRows() > 0 ) { $lb = new LinkBatch; foreach ( $this->mResult as $row ) { $lb->add( $row->log_namespace, $row->log_title ); diff --git a/includes/logging/MoveLogFormatter.php b/includes/logging/MoveLogFormatter.php new file mode 100644 index 00000000..0978f976 --- /dev/null +++ b/includes/logging/MoveLogFormatter.php @@ -0,0 +1,82 @@ +<?php +/** + * Formatter for move log entries. + * + * 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 + * @author Niklas Laxström + * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later + * @since 1.22 + */ + +/** + * This class formats move log entries. + * + * @since 1.19 + */ +class MoveLogFormatter extends LogFormatter { + public function getPreloadTitles() { + $params = $this->extractParameters(); + return array( Title::newFromText( $params[3] ) ); + } + + protected function getMessageKey() { + $key = parent::getMessageKey(); + $params = $this->getMessageParameters(); + if ( isset( $params[4] ) && $params[4] === '1' ) { + $key .= '-noredirect'; + } + return $key; + } + + protected function getMessageParameters() { + $params = parent::getMessageParameters(); + $oldname = $this->makePageLink( $this->entry->getTarget(), array( 'redirect' => 'no' ) ); + $newname = $this->makePageLink( Title::newFromText( $params[3] ) ); + $params[2] = Message::rawParam( $oldname ); + $params[3] = Message::rawParam( $newname ); + return $params; + } + + public function getActionLinks() { + if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) // Action is hidden + || $this->entry->getSubtype() !== 'move' + || !$this->context->getUser()->isAllowed( 'move' ) ) + { + return ''; + } + + $params = $this->extractParameters(); + $destTitle = Title::newFromText( $params[3] ); + if ( !$destTitle ) { + return ''; + } + + $revert = Linker::linkKnown( + SpecialPage::getTitleFor( 'Movepage' ), + $this->msg( 'revertmove' )->escaped(), + array(), + array( + 'wpOldTitle' => $destTitle->getPrefixedDBkey(), + 'wpNewTitle' => $this->entry->getTarget()->getPrefixedDBkey(), + 'wpReason' => $this->msg( 'revertmove' )->inContentLanguage()->text(), + 'wpMovetalk' => 0 + ) + ); + return $this->msg( 'parentheses' )->rawParams( $revert )->escaped(); + } +} diff --git a/includes/logging/NewUsersLogFormatter.php b/includes/logging/NewUsersLogFormatter.php new file mode 100644 index 00000000..602728b4 --- /dev/null +++ b/includes/logging/NewUsersLogFormatter.php @@ -0,0 +1,65 @@ +<?php +/** + * Formatter for new user log entries. + * + * 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 + * @author Niklas Laxström + * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later + * @since 1.22 + */ + +/** + * This class formats new user log entries. + * + * @since 1.19 + */ +class NewUsersLogFormatter extends LogFormatter { + protected function getMessageParameters() { + $params = parent::getMessageParameters(); + $subtype = $this->entry->getSubtype(); + if ( $subtype === 'create2' || $subtype === 'byemail' ) { + if ( isset( $params[3] ) ) { + $target = User::newFromId( $params[3] ); + } else { + $target = User::newFromName( $this->entry->getTarget()->getText(), false ); + } + $params[2] = Message::rawParam( $this->makeUserLink( $target ) ); + $params[3] = $target->getName(); + } + return $params; + } + + public function getComment() { + $timestamp = wfTimestamp( TS_MW, $this->entry->getTimestamp() ); + if ( $timestamp < '20080129000000' ) { + # Suppress $comment from old entries (before 2008-01-29), + # not needed and can contain incorrect links + return ''; + } + return parent::getComment(); + } + + public function getPreloadTitles() { + $subtype = $this->entry->getSubtype(); + if ( $subtype === 'create2' || $subtype === 'byemail' ) { + //add the user talk to LinkBatch for the userLink + return array( Title::makeTitle( NS_USER_TALK, $this->entry->getTarget()->getText() ) ); + } + return array(); + } +} diff --git a/includes/logging/PatrolLog.php b/includes/logging/PatrolLog.php index 911fffc0..bb76d5a9 100644 --- a/includes/logging/PatrolLog.php +++ b/includes/logging/PatrolLog.php @@ -38,6 +38,13 @@ class PatrolLog { * @return bool */ public static function record( $rc, $auto = false, User $user = null ) { + global $wgLogAutopatrol; + + // do not log autopatrolled edits if setting disables it + if ( $auto && !$wgLogAutopatrol ) { + return false; + } + if ( !$rc instanceof RecentChange ) { $rc = RecentChange::newFromId( $rc ); if ( !is_object( $rc ) ) { diff --git a/includes/logging/PatrolLogFormatter.php b/includes/logging/PatrolLogFormatter.php new file mode 100644 index 00000000..507039ba --- /dev/null +++ b/includes/logging/PatrolLogFormatter.php @@ -0,0 +1,63 @@ +<?php +/** + * Formatter for new user log entries. + * + * 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 + * @author Niklas Laxström + * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later + * @since 1.22 + */ + +/** + * This class formats patrol log entries. + * + * @since 1.19 + */ +class PatrolLogFormatter extends LogFormatter { + protected function getMessageKey() { + $key = parent::getMessageKey(); + $params = $this->getMessageParameters(); + if ( isset( $params[5] ) && $params[5] ) { + $key .= '-auto'; + } + return $key; + } + + protected function getMessageParameters() { + $params = parent::getMessageParameters(); + + $target = $this->entry->getTarget(); + $oldid = $params[3]; + $revision = $this->context->getLanguage()->formatNum( $oldid, true ); + + if ( $this->plaintext ) { + $revlink = $revision; + } elseif ( $target->exists() ) { + $query = array( + 'oldid' => $oldid, + 'diff' => 'prev' + ); + $revlink = Linker::link( $target, htmlspecialchars( $revision ), array(), $query ); + } else { + $revlink = htmlspecialchars( $revision ); + } + + $params[3] = Message::rawParam( $revlink ); + return $params; + } +} diff --git a/includes/logging/RightsLogFormatter.php b/includes/logging/RightsLogFormatter.php new file mode 100644 index 00000000..d3daf6ee --- /dev/null +++ b/includes/logging/RightsLogFormatter.php @@ -0,0 +1,112 @@ +<?php +/** + * Formatter for user rights log entries. + * + * 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 + * @author Alexandre Emsenhuber + * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later + * @since 1.22 + */ + +/** + * This class formats rights log entries. + * + * @since 1.21 + */ +class RightsLogFormatter extends LogFormatter { + protected function makePageLink( Title $title = null, $parameters = array() ) { + global $wgContLang, $wgUserrightsInterwikiDelimiter; + + if ( !$this->plaintext ) { + $text = $wgContLang->ucfirst( $title->getText() ); + $parts = explode( $wgUserrightsInterwikiDelimiter, $text, 2 ); + + if ( count( $parts ) === 2 ) { + $titleLink = WikiMap::foreignUserLink( $parts[1], $parts[0], + htmlspecialchars( $title->getPrefixedText() ) ); + + if ( $titleLink !== false ) { + return $titleLink; + } + } + } + + return parent::makePageLink( $title, $parameters ); + } + + protected function getMessageKey() { + $key = parent::getMessageKey(); + $params = $this->getMessageParameters(); + if ( !isset( $params[3] ) && !isset( $params[4] ) ) { + $key .= '-legacy'; + } + return $key; + } + + protected function getMessageParameters() { + $params = parent::getMessageParameters(); + + // Really old entries + if ( !isset( $params[3] ) && !isset( $params[4] ) ) { + return $params; + } + + $oldGroups = $params[3]; + $newGroups = $params[4]; + + // Less old entries + if ( $oldGroups === '' ) { + $oldGroups = array(); + } elseif ( is_string( $oldGroups ) ) { + $oldGroups = array_map( 'trim', explode( ',', $oldGroups ) ); + } + if ( $newGroups === '' ) { + $newGroups = array(); + } elseif ( is_string( $newGroups ) ) { + $newGroups = array_map( 'trim', explode( ',', $newGroups ) ); + } + + $userName = $this->entry->getTarget()->getText(); + if ( !$this->plaintext && count( $oldGroups ) ) { + foreach ( $oldGroups as &$group ) { + $group = User::getGroupMember( $group, $userName ); + } + } + if ( !$this->plaintext && count( $newGroups ) ) { + foreach ( $newGroups as &$group ) { + $group = User::getGroupMember( $group, $userName ); + } + } + + $lang = $this->context->getLanguage(); + if ( count( $oldGroups ) ) { + $params[3] = $lang->listToText( $oldGroups ); + } else { + $params[3] = $this->msg( 'rightsnone' )->text(); + } + if ( count( $newGroups ) ) { + // Array_values is used here because of bug 42211 + // see use of array_unique in UserrightsPage::doSaveUserGroups on $newGroups. + $params[4] = $lang->listToText( array_values( $newGroups ) ); + } else { + $params[4] = $this->msg( 'rightsnone' )->text(); + } + + return $params; + } +} |