Index: trunk/phase3/includes/debug/Debug.php |
— | — | @@ -43,6 +43,14 @@ |
44 | 44 | protected static $enabled = true; |
45 | 45 | |
46 | 46 | /** |
| 47 | + * Array of functions that have already been warned, formatted |
| 48 | + * function-caller to prevent a buttload of warnings |
| 49 | + * |
| 50 | + * @var array |
| 51 | + */ |
| 52 | + protected static $deprecationWarnings = array(); |
| 53 | + |
| 54 | + /** |
47 | 55 | * Called in Setup.php, initializes the debugger if it is enabled with |
48 | 56 | * $wgDebugToolbar |
49 | 57 | */ |
— | — | @@ -60,9 +68,6 @@ |
61 | 69 | /** |
62 | 70 | * Adds a line to the log |
63 | 71 | * |
64 | | - * This does nothing atm, there's not frontend for it |
65 | | - * |
66 | | - * @todo Add error and warning log type |
67 | 72 | * @todo Add support for passing objects |
68 | 73 | * |
69 | 74 | * @param $str string |
— | — | @@ -72,10 +77,78 @@ |
73 | 78 | return; |
74 | 79 | } |
75 | 80 | |
76 | | - self::$log[] = $str; |
| 81 | + self::$log[] = array( |
| 82 | + 'msg' => htmlspecialchars( $str ), |
| 83 | + 'type' => 'log', |
| 84 | + 'caller' => wfGetCaller(), |
| 85 | + ); |
77 | 86 | } |
78 | 87 | |
79 | 88 | /** |
| 89 | + * Adds a warning entry to the log |
| 90 | + * |
| 91 | + * @param $msg |
| 92 | + * @param int $callerOffset |
| 93 | + * @return mixed |
| 94 | + */ |
| 95 | + public static function warning( $msg, $callerOffset = 1 ) { |
| 96 | + if ( !self::$enabled ) { |
| 97 | + return; |
| 98 | + } |
| 99 | + |
| 100 | + // Check to see if there was already a deprecation notice, so not to |
| 101 | + // get a duplicate warning |
| 102 | + $lastLog = self::$log[ count( self::$log ) - 1 ]; |
| 103 | + if ( $lastLog['type'] == 'deprecated' && $lastLog['caller'] == wfGetCaller( $callerOffset + 1 ) ) { |
| 104 | + return; |
| 105 | + } |
| 106 | + |
| 107 | + self::$log[] = array( |
| 108 | + 'msg' => htmlspecialchars( $msg ), |
| 109 | + 'type' => 'warn', |
| 110 | + 'caller' => wfGetCaller( $callerOffset ), |
| 111 | + ); |
| 112 | + } |
| 113 | + |
| 114 | + /** |
| 115 | + * Adds a depreciation entry to the log, along with a backtrace |
| 116 | + * |
| 117 | + * @param $function |
| 118 | + * @param $version |
| 119 | + * @param $component |
| 120 | + * @return mixed |
| 121 | + */ |
| 122 | + public static function deprecated( $function, $version, $component ) { |
| 123 | + if ( !self::$enabled ) { |
| 124 | + return; |
| 125 | + } |
| 126 | + |
| 127 | + // Chain: This function -> wfDeprecated -> deprecatedFunction -> caller |
| 128 | + $caller = wfGetCaller( 4 ); |
| 129 | + |
| 130 | + // Check to see if there already was a warning about this function |
| 131 | + $functionString = "$function-$caller"; |
| 132 | + if ( in_array( $functionString, self::$deprecationWarnings ) ) { |
| 133 | + return; |
| 134 | + } |
| 135 | + |
| 136 | + $version = $version === false ? '(unknown version)' : $version; |
| 137 | + $component = $component === false ? 'MediaWiki' : $component; |
| 138 | + $msg = htmlspecialchars( "Use of function $function was deprecated in $component $version" ); |
| 139 | + $msg .= Html::rawElement( 'div', array( 'class' => 'mw-debug-backtrace' ), |
| 140 | + Html::element( 'span', array(), 'Backtrace:' ) |
| 141 | + . wfBacktrace() |
| 142 | + ); |
| 143 | + |
| 144 | + self::$deprecationWarnings[] = $functionString; |
| 145 | + self::$log[] = array( |
| 146 | + 'msg' => $msg, |
| 147 | + 'type' => 'deprecated', |
| 148 | + 'caller' => $caller, |
| 149 | + ); |
| 150 | + } |
| 151 | + |
| 152 | + /** |
80 | 153 | * This is a method to pass messages from wfDebug to the pretty debugger. |
81 | 154 | * Do NOT use this method, use MWDebug::log or wfDebug() |
82 | 155 | * |
— | — | @@ -178,6 +251,7 @@ |
179 | 252 | } |
180 | 253 | |
181 | 254 | global $wgVersion, $wgRequestTime; |
| 255 | + MWDebug::log( 'MWDebug output complete' ); |
182 | 256 | $debugInfo = array( |
183 | 257 | 'mwVersion' => $wgVersion, |
184 | 258 | 'phpVersion' => PHP_VERSION, |
Index: trunk/phase3/includes/GlobalFunctions.php |
— | — | @@ -3460,7 +3460,9 @@ |
3461 | 3461 | */ |
3462 | 3462 | function wfDeprecated( $function, $version = false, $component = false ) { |
3463 | 3463 | static $functionsWarned = array(); |
3464 | | - |
| 3464 | + |
| 3465 | + MWDebug::deprecated( $function, $version, $component ); |
| 3466 | + |
3465 | 3467 | if ( !in_array( $function, $GLOBALS['wgDeprecationWhitelist'] ) && !isset( $functionsWarned[$function] ) ) { |
3466 | 3468 | $functionsWarned[$function] = true; |
3467 | 3469 | |
— | — | @@ -3501,6 +3503,8 @@ |
3502 | 3504 | function wfWarn( $msg, $callerOffset = 1, $level = E_USER_NOTICE ) { |
3503 | 3505 | global $wgDevelopmentWarnings; |
3504 | 3506 | |
| 3507 | + MWDebug::warning( $msg, $callerOffset + 2 ); |
| 3508 | + |
3505 | 3509 | $callers = wfDebugBacktrace(); |
3506 | 3510 | if ( isset( $callers[$callerOffset + 1] ) ) { |
3507 | 3511 | $callerfunc = $callers[$callerOffset + 1]; |
Index: trunk/phase3/resources/mediawiki/mediawiki.debug.css |
— | — | @@ -88,7 +88,7 @@ |
89 | 89 | } |
90 | 90 | |
91 | 91 | .mw-debug-pane { |
92 | | - max-height: 300px; |
| 92 | + height: 300px; |
93 | 93 | overflow: scroll; |
94 | 94 | display: none; |
95 | 95 | font-size: 11px; |
— | — | @@ -129,3 +129,49 @@ |
130 | 130 | #mw-debug-pane-request td { |
131 | 131 | background-color: white; |
132 | 132 | } |
| 133 | + |
| 134 | +#mw-debug-console tr td:first-child { |
| 135 | + font-weight: bold; |
| 136 | + vertical-align: top; |
| 137 | +} |
| 138 | + |
| 139 | +.mw-debug-console-log { |
| 140 | + background-color: #add8e6; |
| 141 | +} |
| 142 | + |
| 143 | +.mw-debug-console-warn { |
| 144 | + background-color: #ffa07a; |
| 145 | +} |
| 146 | + |
| 147 | +.mw-debug-console-deprecated { |
| 148 | + background-color: #ffb6c1; |
| 149 | +} |
| 150 | + |
| 151 | +.mw-debug-backtrace { |
| 152 | + padding: 5px 10px; |
| 153 | + margin: 5px; |
| 154 | + background-color: #dedede; |
| 155 | +} |
| 156 | + |
| 157 | +.mw-debug-backtrace span { |
| 158 | + font-weight: bold; |
| 159 | + color: #111; |
| 160 | +} |
| 161 | + |
| 162 | +.mw-debug-backtrace ul { |
| 163 | + padding-left: 10px; |
| 164 | +} |
| 165 | + |
| 166 | +.mw-debug-backtrace li { |
| 167 | + width: auto; |
| 168 | + padding: 0; |
| 169 | + color: #333; |
| 170 | + font-size: 10px; |
| 171 | + margin-bottom: 0; |
| 172 | + line-height: 1em; |
| 173 | +} |
| 174 | + |
| 175 | +/* Cheapo hack to hide the first 3 lines of the backtrace */ |
| 176 | +.mw-debug-backtrace li:nth-child(-n+3) { |
| 177 | + display: none; |
| 178 | +} |
\ No newline at end of file |
Index: trunk/phase3/resources/mediawiki/mediawiki.debug.js |
— | — | @@ -127,6 +127,8 @@ |
128 | 128 | .appendTo( $bits ); |
129 | 129 | } |
130 | 130 | |
| 131 | + paneTriggerBitDiv( 'console', 'Console (' + this.data.log.length + ')' ); |
| 132 | + |
131 | 133 | paneTriggerBitDiv( 'querylist', 'Queries: ' + this.data.queries.length ); |
132 | 134 | |
133 | 135 | paneTriggerBitDiv( 'debuglog', 'Debug Log (' + this.data.debugLog.length + ' lines)' ); |
— | — | @@ -154,6 +156,7 @@ |
155 | 157 | $bits.appendTo( $container ); |
156 | 158 | |
157 | 159 | panes = { |
| 160 | + console: this.buildConsoleTable(), |
158 | 161 | querylist: this.buildQueryTable(), |
159 | 162 | debuglog: this.buildDebugLogTable(), |
160 | 163 | request: this.buildRequestPane(), |
— | — | @@ -178,6 +181,49 @@ |
179 | 182 | }, |
180 | 183 | |
181 | 184 | /** |
| 185 | + * Builds the console panel |
| 186 | + */ |
| 187 | + buildConsoleTable: function () { |
| 188 | + var $table, entryTypeText, i, length, entry; |
| 189 | + |
| 190 | + $table = $( '<table id="mw-debug-console">' ); |
| 191 | + |
| 192 | + $('<colgroup>').css( 'width', /*padding=*/20 + ( 10*/*fontSize*/11 ) ).appendTo( $table ); |
| 193 | + $('<colgroup>').appendTo( $table ); |
| 194 | + $('<colgroup>').css( 'width', 350 ).appendTo( $table ); |
| 195 | + |
| 196 | + |
| 197 | + entryTypeText = function( entryType ) { |
| 198 | + switch ( entryType ) { |
| 199 | + case 'log': |
| 200 | + return 'Log'; |
| 201 | + case 'warn': |
| 202 | + return 'Warning'; |
| 203 | + case 'deprecated': |
| 204 | + return 'Deprecated'; |
| 205 | + default: |
| 206 | + return 'Unknown'; |
| 207 | + } |
| 208 | + }; |
| 209 | + |
| 210 | + for ( i = 0, length = this.data.log.length; i < length; i += 1 ) { |
| 211 | + entry = this.data.log[i]; |
| 212 | + entry.typeText = entryTypeText( entry.type ); |
| 213 | + |
| 214 | + $( '<tr>' ) |
| 215 | + .append( $( '<td>' ) |
| 216 | + .text( entry.typeText ) |
| 217 | + .attr( 'class', 'mw-debug-console-' + entry.type ) |
| 218 | + ) |
| 219 | + .append( $( '<td>' ).html( entry.msg ) ) |
| 220 | + .append( $( '<td>' ).text( entry.caller ) ) |
| 221 | + .appendTo( $table ); |
| 222 | + } |
| 223 | + |
| 224 | + return $table; |
| 225 | + }, |
| 226 | + |
| 227 | + /** |
182 | 228 | * Query list pane |
183 | 229 | */ |
184 | 230 | buildQueryTable: function () { |