/**
  * @return string HTML
  */
 protected function buildCheckBoxes()
 {
     $html = '<table>';
     // If there is just one item, use checkboxes
     $list = $this->getList();
     if ($list->length() == 1) {
         $list->reset();
         $bitfield = $list->current()->getBits();
         // existing field
         if ($this->submitClicked) {
             $bitfield = RevisionDeleter::extractBitfield($this->extractBitParams(), $bitfield);
         }
         foreach ($this->checks as $item) {
             // Messages: revdelete-hide-text, revdelete-hide-image, revdelete-hide-name,
             // revdelete-hide-comment, revdelete-hide-user, revdelete-hide-restricted
             list($message, $name, $field) = $item;
             $innerHTML = Xml::checkLabel($this->msg($message)->text(), $name, $name, $bitfield & $field);
             if ($field == Revision::DELETED_RESTRICTED) {
                 $innerHTML = "<b>{$innerHTML}</b>";
             }
             $line = Xml::tags('td', array('class' => 'mw-input'), $innerHTML);
             $html .= "<tr>{$line}</tr>\n";
         }
     } else {
         // Otherwise, use tri-state radios
         $html .= '<tr>';
         $html .= '<th class="mw-revdel-checkbox">' . $this->msg('revdelete-radio-same')->escaped() . '</th>';
         $html .= '<th class="mw-revdel-checkbox">' . $this->msg('revdelete-radio-unset')->escaped() . '</th>';
         $html .= '<th class="mw-revdel-checkbox">' . $this->msg('revdelete-radio-set')->escaped() . '</th>';
         $html .= "<th></th></tr>\n";
         foreach ($this->checks as $item) {
             // Messages: revdelete-hide-text, revdelete-hide-image, revdelete-hide-name,
             // revdelete-hide-comment, revdelete-hide-user, revdelete-hide-restricted
             list($message, $name, $field) = $item;
             // If there are several items, use third state by default...
             if ($this->submitClicked) {
                 $selected = $this->getRequest()->getInt($name, 0);
             } else {
                 $selected = -1;
                 // use existing field
             }
             $line = '<td class="mw-revdel-checkbox">' . Xml::radio($name, -1, $selected == -1) . '</td>';
             $line .= '<td class="mw-revdel-checkbox">' . Xml::radio($name, 0, $selected == 0) . '</td>';
             $line .= '<td class="mw-revdel-checkbox">' . Xml::radio($name, 1, $selected == 1) . '</td>';
             $label = $this->msg($message)->escaped();
             if ($field == Revision::DELETED_RESTRICTED) {
                 $label = "<b>{$label}</b>";
             }
             $line .= "<td>{$label}</td>";
             $html .= "<tr>{$line}</tr>\n";
         }
     }
     $html .= '</table>';
     return $html;
 }
Exemplo n.º 2
0
 /**
  * Set the visibility for the revisions in this list. Logging and
  * transactions are done here.
  *
  * @param array $params Associative array of parameters. Members are:
  *     value:         ExtractBitParams() bitfield array
  *     comment:       The log comment.
  *     perItemStatus: Set if you want per-item status reports
  * @return Status
  * @since 1.23 Added 'perItemStatus' param
  */
 public function setVisibility($params)
 {
     $bitPars = $params['value'];
     $comment = $params['comment'];
     $perItemStatus = isset($params['perItemStatus']) ? $params['perItemStatus'] : false;
     // CAS-style checks are done on the _deleted fields so the select
     // does not need to use FOR UPDATE nor be in the atomic section
     $dbw = wfGetDB(DB_MASTER);
     $this->res = $this->doQuery($dbw);
     $dbw->startAtomic(__METHOD__);
     $status = Status::newGood();
     $missing = array_flip($this->ids);
     $this->clearFileOps();
     $idsForLog = array();
     $authorIds = $authorIPs = array();
     if ($perItemStatus) {
         $status->itemStatuses = array();
     }
     // @codingStandardsIgnoreStart Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed
     for ($this->reset(); $this->current(); $this->next()) {
         // @codingStandardsIgnoreEnd
         /** @var $item RevDelItem */
         $item = $this->current();
         unset($missing[$item->getId()]);
         if ($perItemStatus) {
             $itemStatus = Status::newGood();
             $status->itemStatuses[$item->getId()] = $itemStatus;
         } else {
             $itemStatus = $status;
         }
         $oldBits = $item->getBits();
         // Build the actual new rev_deleted bitfield
         $newBits = RevisionDeleter::extractBitfield($bitPars, $oldBits);
         if ($oldBits == $newBits) {
             $itemStatus->warning('revdelete-no-change', $item->formatDate(), $item->formatTime());
             $status->failCount++;
             continue;
         } elseif ($oldBits == 0 && $newBits != 0) {
             $opType = 'hide';
         } elseif ($oldBits != 0 && $newBits == 0) {
             $opType = 'show';
         } else {
             $opType = 'modify';
         }
         if ($item->isHideCurrentOp($newBits)) {
             // Cannot hide current version text
             $itemStatus->error('revdelete-hide-current', $item->formatDate(), $item->formatTime());
             $status->failCount++;
             continue;
         }
         if (!$item->canView()) {
             // Cannot access this revision
             $msg = $opType == 'show' ? 'revdelete-show-no-access' : 'revdelete-modify-no-access';
             $itemStatus->error($msg, $item->formatDate(), $item->formatTime());
             $status->failCount++;
             continue;
         }
         // Cannot just "hide from Sysops" without hiding any fields
         if ($newBits == Revision::DELETED_RESTRICTED) {
             $itemStatus->warning('revdelete-only-restricted', $item->formatDate(), $item->formatTime());
             $status->failCount++;
             continue;
         }
         // Update the revision
         $ok = $item->setBits($newBits);
         if ($ok) {
             $idsForLog[] = $item->getId();
             $status->successCount++;
             if ($item->getAuthorId() > 0) {
                 $authorIds[] = $item->getAuthorId();
             } elseif (IP::isIPAddress($item->getAuthorName())) {
                 $authorIPs[] = $item->getAuthorName();
             }
         } else {
             $itemStatus->error('revdelete-concurrent-change', $item->formatDate(), $item->formatTime());
             $status->failCount++;
         }
     }
     // Handle missing revisions
     foreach ($missing as $id => $unused) {
         if ($perItemStatus) {
             $status->itemStatuses[$id] = Status::newFatal('revdelete-modify-missing', $id);
         } else {
             $status->error('revdelete-modify-missing', $id);
         }
         $status->failCount++;
     }
     if ($status->successCount == 0) {
         $dbw->rollback(__METHOD__);
         return $status;
     }
     // Save success count
     $successCount = $status->successCount;
     // Move files, if there are any
     $status->merge($this->doPreCommitUpdates());
     if (!$status->isOK()) {
         // Fatal error, such as no configured archive directory
         $dbw->rollback(__METHOD__);
         return $status;
     }
     // Log it
     // @FIXME: $newBits/$oldBits set in for loop, makes IDE warnings too
     $this->updateLog(array('title' => $this->title, 'count' => $successCount, 'newBits' => $newBits, 'oldBits' => $oldBits, 'comment' => $comment, 'ids' => $idsForLog, 'authorIds' => $authorIds, 'authorIPs' => $authorIPs));
     // Clear caches
     $that = $this;
     $dbw->onTransactionIdle(function () use($that) {
         $that->doPostCommitUpdates();
     });
     $dbw->endAtomic(__METHOD__);
     return $status;
 }
 /**
  * Set the visibility for the revisions in this list. Logging and
  * transactions are done here.
  *
  * @param array $params Associative array of parameters. Members are:
  *     value:         The integer value to set the visibility to
  *     comment:       The log comment.
  *     perItemStatus: Set if you want per-item status reports
  * @return Status
  * @since 1.23 Added 'perItemStatus' param
  */
 public function setVisibility($params)
 {
     $bitPars = $params['value'];
     $comment = $params['comment'];
     $perItemStatus = isset($params['perItemStatus']) ? $params['perItemStatus'] : false;
     $this->res = false;
     $dbw = wfGetDB(DB_MASTER);
     $this->doQuery($dbw);
     $dbw->begin(__METHOD__);
     $status = Status::newGood();
     $missing = array_flip($this->ids);
     $this->clearFileOps();
     $idsForLog = array();
     $authorIds = $authorIPs = array();
     if ($perItemStatus) {
         $status->itemStatuses = array();
     }
     for ($this->reset(); $this->current(); $this->next()) {
         $item = $this->current();
         unset($missing[$item->getId()]);
         if ($perItemStatus) {
             $itemStatus = Status::newGood();
             $status->itemStatuses[$item->getId()] = $itemStatus;
         } else {
             $itemStatus = $status;
         }
         $oldBits = $item->getBits();
         // Build the actual new rev_deleted bitfield
         $newBits = RevisionDeleter::extractBitfield($bitPars, $oldBits);
         if ($oldBits == $newBits) {
             $itemStatus->warning('revdelete-no-change', $item->formatDate(), $item->formatTime());
             $status->failCount++;
             continue;
         } elseif ($oldBits == 0 && $newBits != 0) {
             $opType = 'hide';
         } elseif ($oldBits != 0 && $newBits == 0) {
             $opType = 'show';
         } else {
             $opType = 'modify';
         }
         if ($item->isHideCurrentOp($newBits)) {
             // Cannot hide current version text
             $itemStatus->error('revdelete-hide-current', $item->formatDate(), $item->formatTime());
             $status->failCount++;
             continue;
         }
         if (!$item->canView()) {
             // Cannot access this revision
             $msg = $opType == 'show' ? 'revdelete-show-no-access' : 'revdelete-modify-no-access';
             $itemStatus->error($msg, $item->formatDate(), $item->formatTime());
             $status->failCount++;
             continue;
         }
         // Cannot just "hide from Sysops" without hiding any fields
         if ($newBits == Revision::DELETED_RESTRICTED) {
             $itemStatus->warning('revdelete-only-restricted', $item->formatDate(), $item->formatTime());
             $status->failCount++;
             continue;
         }
         // Update the revision
         $ok = $item->setBits($newBits);
         if ($ok) {
             $idsForLog[] = $item->getId();
             $status->successCount++;
             if ($item->getAuthorId() > 0) {
                 $authorIds[] = $item->getAuthorId();
             } elseif (IP::isIPAddress($item->getAuthorName())) {
                 $authorIPs[] = $item->getAuthorName();
             }
         } else {
             $itemStatus->error('revdelete-concurrent-change', $item->formatDate(), $item->formatTime());
             $status->failCount++;
         }
     }
     // Handle missing revisions
     foreach ($missing as $id => $unused) {
         if ($perItemStatus) {
             $status->itemStatuses[$id] = Status::newFatal('revdelete-modify-missing', $id);
         } else {
             $status->error('revdelete-modify-missing', $id);
         }
         $status->failCount++;
     }
     if ($status->successCount == 0) {
         $dbw->rollback(__METHOD__);
         return $status;
     }
     // Save success count
     $successCount = $status->successCount;
     // Move files, if there are any
     $status->merge($this->doPreCommitUpdates());
     if (!$status->isOK()) {
         // Fatal error, such as no configured archive directory
         $dbw->rollback(__METHOD__);
         return $status;
     }
     // Log it
     $this->updateLog(array('title' => $this->title, 'count' => $successCount, 'newBits' => $newBits, 'oldBits' => $oldBits, 'comment' => $comment, 'ids' => $idsForLog, 'authorIds' => $authorIds, 'authorIPs' => $authorIPs));
     $dbw->commit(__METHOD__);
     // Clear caches
     $status->merge($this->doPostCommitUpdates());
     return $status;
 }
Exemplo n.º 4
0
	/**
	 * Put together a rev_deleted bitfield
	 * @deprecated since 1.22, use RevisionDeleter::extractBitfield instead
	 * @param array $bitPars extractBitParams() params
	 * @param int $oldfield current bitfield
	 * @return array
	 */
	public static function extractBitfield( $bitPars, $oldfield ) {
		return RevisionDeleter::extractBitfield( $bitPars, $oldfield );
	}
Exemplo n.º 5
0
 /**
  * Set the visibility for the revisions in this list. Logging and
  * transactions are done here.
  *
  * @param array $params Associative array of parameters. Members are:
  *     value:         ExtractBitParams() bitfield array
  *     comment:       The log comment.
  *     perItemStatus: Set if you want per-item status reports
  * @return Status
  * @since 1.23 Added 'perItemStatus' param
  */
 public function setVisibility(array $params)
 {
     $status = Status::newGood();
     $bitPars = $params['value'];
     $comment = $params['comment'];
     $perItemStatus = isset($params['perItemStatus']) ? $params['perItemStatus'] : false;
     // CAS-style checks are done on the _deleted fields so the select
     // does not need to use FOR UPDATE nor be in the atomic section
     $dbw = wfGetDB(DB_MASTER);
     $this->res = $this->doQuery($dbw);
     $status->merge($this->acquireItemLocks());
     if (!$status->isGood()) {
         return $status;
     }
     $dbw->startAtomic(__METHOD__);
     $dbw->onTransactionResolution(function () {
         // Release locks on commit or error
         $this->releaseItemLocks();
     }, __METHOD__);
     $missing = array_flip($this->ids);
     $this->clearFileOps();
     $idsForLog = [];
     $authorIds = $authorIPs = [];
     if ($perItemStatus) {
         $status->itemStatuses = [];
     }
     // For multi-item deletions, set the old/new bitfields in log_params such that "hid X"
     // shows in logs if field X was hidden from ANY item and likewise for "unhid Y". Note the
     // form does not let the same field get hidden and unhidden in different items at once.
     $virtualOldBits = 0;
     $virtualNewBits = 0;
     $logType = 'delete';
     // Will be filled with id => [old, new bits] information and
     // passed to doPostCommitUpdates().
     $visibilityChangeMap = [];
     /** @var $item RevDelItem */
     foreach ($this as $item) {
         unset($missing[$item->getId()]);
         if ($perItemStatus) {
             $itemStatus = Status::newGood();
             $status->itemStatuses[$item->getId()] = $itemStatus;
         } else {
             $itemStatus = $status;
         }
         $oldBits = $item->getBits();
         // Build the actual new rev_deleted bitfield
         $newBits = RevisionDeleter::extractBitfield($bitPars, $oldBits);
         if ($oldBits == $newBits) {
             $itemStatus->warning('revdelete-no-change', $item->formatDate(), $item->formatTime());
             $status->failCount++;
             continue;
         } elseif ($oldBits == 0 && $newBits != 0) {
             $opType = 'hide';
         } elseif ($oldBits != 0 && $newBits == 0) {
             $opType = 'show';
         } else {
             $opType = 'modify';
         }
         if ($item->isHideCurrentOp($newBits)) {
             // Cannot hide current version text
             $itemStatus->error('revdelete-hide-current', $item->formatDate(), $item->formatTime());
             $status->failCount++;
             continue;
         } elseif (!$item->canView()) {
             // Cannot access this revision
             $msg = $opType == 'show' ? 'revdelete-show-no-access' : 'revdelete-modify-no-access';
             $itemStatus->error($msg, $item->formatDate(), $item->formatTime());
             $status->failCount++;
             continue;
             // Cannot just "hide from Sysops" without hiding any fields
         } elseif ($newBits == Revision::DELETED_RESTRICTED) {
             $itemStatus->warning('revdelete-only-restricted', $item->formatDate(), $item->formatTime());
             $status->failCount++;
             continue;
         }
         // Update the revision
         $ok = $item->setBits($newBits);
         if ($ok) {
             $idsForLog[] = $item->getId();
             // If any item field was suppressed or unsupressed
             if (($oldBits | $newBits) & $this->getSuppressBit()) {
                 $logType = 'suppress';
             }
             // Track which fields where (un)hidden for each item
             $addedBits = ($oldBits ^ $newBits) & $newBits;
             $removedBits = ($oldBits ^ $newBits) & $oldBits;
             $virtualNewBits |= $addedBits;
             $virtualOldBits |= $removedBits;
             $status->successCount++;
             if ($item->getAuthorId() > 0) {
                 $authorIds[] = $item->getAuthorId();
             } elseif (IP::isIPAddress($item->getAuthorName())) {
                 $authorIPs[] = $item->getAuthorName();
             }
             // Save the old and new bits in $visibilityChangeMap for
             // later use.
             $visibilityChangeMap[$item->getId()] = ['oldBits' => $oldBits, 'newBits' => $newBits];
         } else {
             $itemStatus->error('revdelete-concurrent-change', $item->formatDate(), $item->formatTime());
             $status->failCount++;
         }
     }
     // Handle missing revisions
     foreach ($missing as $id => $unused) {
         if ($perItemStatus) {
             $status->itemStatuses[$id] = Status::newFatal('revdelete-modify-missing', $id);
         } else {
             $status->error('revdelete-modify-missing', $id);
         }
         $status->failCount++;
     }
     if ($status->successCount == 0) {
         $dbw->endAtomic(__METHOD__);
         return $status;
     }
     // Save success count
     $successCount = $status->successCount;
     // Move files, if there are any
     $status->merge($this->doPreCommitUpdates());
     if (!$status->isOK()) {
         // Fatal error, such as no configured archive directory or I/O failures
         wfGetLBFactory()->rollbackMasterChanges(__METHOD__);
         return $status;
     }
     // Log it
     $this->updateLog($logType, ['title' => $this->title, 'count' => $successCount, 'newBits' => $virtualNewBits, 'oldBits' => $virtualOldBits, 'comment' => $comment, 'ids' => $idsForLog, 'authorIds' => $authorIds, 'authorIPs' => $authorIPs]);
     // Clear caches after commit
     DeferredUpdates::addCallableUpdate(function () use($visibilityChangeMap) {
         $this->doPostCommitUpdates($visibilityChangeMap);
     }, DeferredUpdates::PRESEND, $dbw);
     $dbw->endAtomic(__METHOD__);
     return $status;
 }