RevDelList::setVisibility()   F
last analyzed

Complexity

Conditions 23
Paths 2486

Size

Total Lines 184
Code Lines 113

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 23
eloc 113
nc 2486
nop 1
dl 0
loc 184
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * This program is free software; you can redistribute it and/or modify
4
 * it under the terms of the GNU General Public License as published by
5
 * the Free Software Foundation; either version 2 of the License, or
6
 * (at your option) any later version.
7
 *
8
 * This program is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
 * GNU General Public License for more details.
12
 *
13
 * You should have received a copy of the GNU General Public License along
14
 * with this program; if not, write to the Free Software Foundation, Inc.,
15
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16
 * http://www.gnu.org/copyleft/gpl.html
17
 *
18
 * @file
19
 * @ingroup RevisionDelete
20
 */
21
22
/**
23
 * Abstract base class for a list of deletable items. The list class
24
 * needs to be able to make a query from a set of identifiers to pull
25
 * relevant rows, to return RevDelItem subclasses wrapping them, and
26
 * to wrap bulk update operations.
27
 */
28
abstract class RevDelList extends RevisionListBase {
29
	function __construct( IContextSource $context, Title $title, array $ids ) {
30
		parent::__construct( $context, $title );
31
		$this->ids = $ids;
32
	}
33
34
	/**
35
	 * Get the DB field name associated with the ID list.
36
	 * This used to populate the log_search table for finding log entries.
37
	 * Override this function.
38
	 * @return string|null
39
	 */
40
	public static function getRelationType() {
41
		return null;
42
	}
43
44
	/**
45
	 * Get the user right required for this list type
46
	 * Override this function.
47
	 * @since 1.22
48
	 * @return string|null
49
	 */
50
	public static function getRestriction() {
51
		return null;
52
	}
53
54
	/**
55
	 * Get the revision deletion constant for this list type
56
	 * Override this function.
57
	 * @since 1.22
58
	 * @return int|null
59
	 */
60
	public static function getRevdelConstant() {
61
		return null;
62
	}
63
64
	/**
65
	 * Suggest a target for the revision deletion
66
	 * Optionally override this function.
67
	 * @since 1.22
68
	 * @param Title|null $target User-supplied target
69
	 * @param array $ids
70
	 * @return Title|null
71
	 */
72
	public static function suggestTarget( $target, array $ids ) {
73
		return $target;
74
	}
75
76
	/**
77
	 * Indicate whether any item in this list is suppressed
78
	 * @since 1.25
79
	 * @return bool
80
	 */
81
	public function areAnySuppressed() {
82
		$bit = $this->getSuppressBit();
83
84
		/** @var $item RevDelItem */
85
		foreach ( $this as $item ) {
86
			if ( $item->getBits() & $bit ) {
0 ignored issues
show
Bug introduced by
The method getBits() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
87
				return true;
88
			}
89
		}
90
91
		return false;
92
	}
93
94
	/**
95
	 * Set the visibility for the revisions in this list. Logging and
96
	 * transactions are done here.
97
	 *
98
	 * @param array $params Associative array of parameters. Members are:
99
	 *     value:         ExtractBitParams() bitfield array
100
	 *     comment:       The log comment.
101
	 *     perItemStatus: Set if you want per-item status reports
102
	 * @return Status
103
	 * @since 1.23 Added 'perItemStatus' param
104
	 */
105
	public function setVisibility( array $params ) {
106
		$status = Status::newGood();
107
108
		$bitPars = $params['value'];
109
		$comment = $params['comment'];
110
		$perItemStatus = isset( $params['perItemStatus'] ) ? $params['perItemStatus'] : false;
111
112
		// CAS-style checks are done on the _deleted fields so the select
113
		// does not need to use FOR UPDATE nor be in the atomic section
114
		$dbw = wfGetDB( DB_MASTER );
115
		$this->res = $this->doQuery( $dbw );
0 ignored issues
show
Bug introduced by
It seems like $dbw defined by wfGetDB(DB_MASTER) on line 114 can be null; however, RevisionListBase::doQuery() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
116
117
		$status->merge( $this->acquireItemLocks() );
118
		if ( !$status->isGood() ) {
119
			return $status;
120
		}
121
122
		$dbw->startAtomic( __METHOD__ );
123
		$dbw->onTransactionResolution(
124
			function () {
125
				// Release locks on commit or error
126
				$this->releaseItemLocks();
127
			},
128
			__METHOD__
129
		);
130
131
		$missing = array_flip( $this->ids );
132
		$this->clearFileOps();
133
		$idsForLog = [];
134
		$authorIds = $authorIPs = [];
135
136
		if ( $perItemStatus ) {
137
			$status->itemStatuses = [];
0 ignored issues
show
Documentation introduced by
The property itemStatuses does not exist on object<Status>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
138
		}
139
140
		// For multi-item deletions, set the old/new bitfields in log_params such that "hid X"
141
		// shows in logs if field X was hidden from ANY item and likewise for "unhid Y". Note the
142
		// form does not let the same field get hidden and unhidden in different items at once.
143
		$virtualOldBits = 0;
144
		$virtualNewBits = 0;
145
		$logType = 'delete';
146
147
		// Will be filled with id => [old, new bits] information and
148
		// passed to doPostCommitUpdates().
149
		$visibilityChangeMap = [];
150
151
		/** @var $item RevDelItem */
152
		foreach ( $this as $item ) {
153
			unset( $missing[$item->getId()] );
154
155
			if ( $perItemStatus ) {
156
				$itemStatus = Status::newGood();
157
				$status->itemStatuses[$item->getId()] = $itemStatus;
0 ignored issues
show
Documentation introduced by
The property itemStatuses does not exist on object<Status>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
158
			} else {
159
				$itemStatus = $status;
160
			}
161
162
			$oldBits = $item->getBits();
0 ignored issues
show
Bug introduced by
The method getBits() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
163
			// Build the actual new rev_deleted bitfield
164
			$newBits = RevisionDeleter::extractBitfield( $bitPars, $oldBits );
165
166
			if ( $oldBits == $newBits ) {
167
				$itemStatus->warning(
168
					'revdelete-no-change', $item->formatDate(), $item->formatTime() );
0 ignored issues
show
Bug introduced by
The method formatDate() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method formatTime() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
169
				$status->failCount++;
170
				continue;
171
			} elseif ( $oldBits == 0 && $newBits != 0 ) {
172
				$opType = 'hide';
173
			} elseif ( $oldBits != 0 && $newBits == 0 ) {
174
				$opType = 'show';
175
			} else {
176
				$opType = 'modify';
177
			}
178
179
			if ( $item->isHideCurrentOp( $newBits ) ) {
0 ignored issues
show
Bug introduced by
The method isHideCurrentOp() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
180
				// Cannot hide current version text
181
				$itemStatus->error(
182
					'revdelete-hide-current', $item->formatDate(), $item->formatTime() );
0 ignored issues
show
Bug introduced by
The method formatDate() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method formatTime() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
183
				$status->failCount++;
184
				continue;
185
			} elseif ( !$item->canView() ) {
0 ignored issues
show
Bug introduced by
The method canView() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
186
				// Cannot access this revision
187
				$msg = ( $opType == 'show' ) ?
188
					'revdelete-show-no-access' : 'revdelete-modify-no-access';
189
				$itemStatus->error( $msg, $item->formatDate(), $item->formatTime() );
0 ignored issues
show
Bug introduced by
The method formatDate() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method formatTime() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
190
				$status->failCount++;
191
				continue;
192
			// Cannot just "hide from Sysops" without hiding any fields
193
			} elseif ( $newBits == Revision::DELETED_RESTRICTED ) {
194
				$itemStatus->warning(
195
					'revdelete-only-restricted', $item->formatDate(), $item->formatTime() );
0 ignored issues
show
Bug introduced by
The method formatDate() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method formatTime() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
196
				$status->failCount++;
197
				continue;
198
			}
199
200
			// Update the revision
201
			$ok = $item->setBits( $newBits );
0 ignored issues
show
Bug introduced by
The method setBits() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
202
203
			if ( $ok ) {
204
				$idsForLog[] = $item->getId();
205
				// If any item field was suppressed or unsupressed
206
				if ( ( $oldBits | $newBits ) & $this->getSuppressBit() ) {
207
					$logType = 'suppress';
208
				}
209
				// Track which fields where (un)hidden for each item
210
				$addedBits = ( $oldBits ^ $newBits ) & $newBits;
211
				$removedBits = ( $oldBits ^ $newBits ) & $oldBits;
212
				$virtualNewBits |= $addedBits;
213
				$virtualOldBits |= $removedBits;
214
215
				$status->successCount++;
216
				if ( $item->getAuthorId() > 0 ) {
0 ignored issues
show
Bug introduced by
The method getAuthorId() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
217
					$authorIds[] = $item->getAuthorId();
0 ignored issues
show
Bug introduced by
The method getAuthorId() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
218
				} elseif ( IP::isIPAddress( $item->getAuthorName() ) ) {
0 ignored issues
show
Bug introduced by
The method getAuthorName() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
219
					$authorIPs[] = $item->getAuthorName();
0 ignored issues
show
Bug introduced by
The method getAuthorName() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
220
				}
221
222
				// Save the old and new bits in $visibilityChangeMap for
223
				// later use.
224
				$visibilityChangeMap[$item->getId()] = [
225
					'oldBits' => $oldBits,
226
					'newBits' => $newBits,
227
				];
228
			} else {
229
				$itemStatus->error(
230
					'revdelete-concurrent-change', $item->formatDate(), $item->formatTime() );
0 ignored issues
show
Bug introduced by
The method formatDate() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method formatTime() does not seem to exist on object<Revision>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
231
				$status->failCount++;
232
			}
233
		}
234
235
		// Handle missing revisions
236
		foreach ( $missing as $id => $unused ) {
237
			if ( $perItemStatus ) {
238
				$status->itemStatuses[$id] = Status::newFatal( 'revdelete-modify-missing', $id );
0 ignored issues
show
Documentation introduced by
The property itemStatuses does not exist on object<Status>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
239
			} else {
240
				$status->error( 'revdelete-modify-missing', $id );
241
			}
242
			$status->failCount++;
243
		}
244
245
		if ( $status->successCount == 0 ) {
246
			$dbw->endAtomic( __METHOD__ );
247
			return $status;
248
		}
249
250
		// Save success count
251
		$successCount = $status->successCount;
252
253
		// Move files, if there are any
254
		$status->merge( $this->doPreCommitUpdates() );
255
		if ( !$status->isOK() ) {
256
			// Fatal error, such as no configured archive directory or I/O failures
257
			wfGetLBFactory()->rollbackMasterChanges( __METHOD__ );
0 ignored issues
show
Deprecated Code introduced by
The function wfGetLBFactory() has been deprecated with message: since 1.27, use MediaWikiServices::getDBLoadBalancerFactory() instead.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
258
			return $status;
259
		}
260
261
		// Log it
262
		$this->updateLog(
263
			$logType,
264
			[
265
				'title' => $this->title,
266
				'count' => $successCount,
267
				'newBits' => $virtualNewBits,
268
				'oldBits' => $virtualOldBits,
269
				'comment' => $comment,
270
				'ids' => $idsForLog,
271
				'authorIds' => $authorIds,
272
				'authorIPs' => $authorIPs
273
			]
274
		);
275
276
		// Clear caches after commit
277
		DeferredUpdates::addCallableUpdate(
278
			function () use ( $visibilityChangeMap ) {
279
				$this->doPostCommitUpdates( $visibilityChangeMap );
280
			},
281
			DeferredUpdates::PRESEND,
282
			$dbw
283
		);
284
285
		$dbw->endAtomic( __METHOD__ );
286
287
		return $status;
288
	}
289
290
	final protected function acquireItemLocks() {
291
		$status = Status::newGood();
292
		/** @var $item RevDelItem */
293
		foreach ( $this as $item ) {
294
			$status->merge( $item->lock() );
295
		}
296
297
		return $status;
298
	}
299
300
	final protected function releaseItemLocks() {
301
		$status = Status::newGood();
302
		/** @var $item RevDelItem */
303
		foreach ( $this as $item ) {
304
			$status->merge( $item->unlock() );
305
		}
306
307
		return $status;
308
	}
309
310
	/**
311
	 * Reload the list data from the master DB. This can be done after setVisibility()
312
	 * to allow $item->getHTML() to show the new data.
313
	 */
314
	function reloadFromMaster() {
315
		$dbw = wfGetDB( DB_MASTER );
316
		$this->res = $this->doQuery( $dbw );
0 ignored issues
show
Bug introduced by
It seems like $dbw defined by wfGetDB(DB_MASTER) on line 315 can be null; however, RevisionListBase::doQuery() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
317
	}
318
319
	/**
320
	 * Record a log entry on the action
321
	 * @param string $logType One of (delete,suppress)
322
	 * @param array $params Associative array of parameters:
323
	 *     newBits:         The new value of the *_deleted bitfield
324
	 *     oldBits:         The old value of the *_deleted bitfield.
325
	 *     title:           The target title
326
	 *     ids:             The ID list
327
	 *     comment:         The log comment
328
	 *     authorsIds:      The array of the user IDs of the offenders
329
	 *     authorsIPs:      The array of the IP/anon user offenders
330
	 * @throws MWException
331
	 */
332
	private function updateLog( $logType, $params ) {
333
		// Get the URL param's corresponding DB field
334
		$field = RevisionDeleter::getRelationType( $this->getType() );
335
		if ( !$field ) {
336
			throw new MWException( "Bad log URL param type!" );
337
		}
338
		// Add params for affected page and ids
339
		$logParams = $this->getLogParams( $params );
340
		// Actually add the deletion log entry
341
		$logEntry = new ManualLogEntry( $logType, $this->getLogAction() );
342
		$logEntry->setTarget( $params['title'] );
343
		$logEntry->setComment( $params['comment'] );
344
		$logEntry->setParameters( $logParams );
345
		$logEntry->setPerformer( $this->getUser() );
346
		// Allow for easy searching of deletion log items for revision/log items
347
		$logEntry->setRelations( [
348
			$field => $params['ids'],
349
			'target_author_id' => $params['authorIds'],
350
			'target_author_ip' => $params['authorIPs'],
351
		] );
352
		$logId = $logEntry->insert();
353
		$logEntry->publish( $logId );
354
	}
355
356
	/**
357
	 * Get the log action for this list type
358
	 * @return string
359
	 */
360
	public function getLogAction() {
361
		return 'revision';
362
	}
363
364
	/**
365
	 * Get log parameter array.
366
	 * @param array $params Associative array of log parameters, same as updateLog()
367
	 * @return array
368
	 */
369
	public function getLogParams( $params ) {
370
		return [
371
			'4::type' => $this->getType(),
372
			'5::ids' => $params['ids'],
373
			'6::ofield' => $params['oldBits'],
374
			'7::nfield' => $params['newBits'],
375
		];
376
	}
377
378
	/**
379
	 * Clear any data structures needed for doPreCommitUpdates() and doPostCommitUpdates()
380
	 * STUB
381
	 */
382
	public function clearFileOps() {
383
	}
384
385
	/**
386
	 * A hook for setVisibility(): do batch updates pre-commit.
387
	 * STUB
388
	 * @return Status
389
	 */
390
	public function doPreCommitUpdates() {
391
		return Status::newGood();
392
	}
393
394
	/**
395
	 * A hook for setVisibility(): do any necessary updates post-commit.
396
	 * STUB
397
	 * @param array [id => ['oldBits' => $oldBits, 'newBits' => $newBits], ... ]
398
	 * @return Status
399
	 */
400
	public function doPostCommitUpdates( array $visibilityChangeMap ) {
401
		return Status::newGood();
402
	}
403
404
	/**
405
	 * Get the integer value of the flag used for suppression
406
	 */
407
	abstract public function getSuppressBit();
408
}
409