/**
  * Prepare change attributes for the given EntityChange. This can be used to avoid
  * re-calculating these attributes for each target page, when processing a change
  * with respect to a batch of affected target pages.
  *
  * @param EntityChange $change
  *
  * @return array Associative array of prepared change attributes, for use with the
  *      $preparedAttribs of newRecentChange().
  */
 public function prepareChangeAttributes(EntityChange $change)
 {
     $rcinfo = $change->getMetadata();
     $fields = $change->getFields();
     $fields['entity_type'] = $change->getEntityId()->getEntityType();
     if (isset($fields['info']['changes'])) {
         $changesForComment = $fields['info']['changes'];
     } else {
         $changesForComment = array($change);
     }
     $comment = $this->getEditCommentMulti($changesForComment);
     unset($fields['info']);
     $metadata = array_merge($fields, $rcinfo);
     $isBot = false;
     if (array_key_exists('bot', $metadata)) {
         $isBot = $metadata['bot'];
     }
     // compatibility
     if (array_key_exists('user_text', $metadata)) {
         $userText = $metadata['user_text'];
     } elseif (array_key_exists('rc_user_text', $metadata)) {
         $userText = $metadata['rc_user_text'];
     } else {
         $userText = '';
     }
     $time = isset($metadata['time']) ? $metadata['time'] : wfTimestamp(TS_MW);
     $params = array('wikibase-repo-change' => $metadata);
     return array('rc_user' => 0, 'rc_user_text' => $userText, 'rc_comment' => $comment, 'rc_type' => RC_EXTERNAL, 'rc_minor' => true, 'rc_bot' => $isBot, 'rc_patrolled' => true, 'rc_params' => serialize($params), 'rc_timestamp' => $time, 'rc_log_type' => null, 'rc_log_action' => '', 'rc_source' => self::SRC_WIKIBASE, 'rc_deleted' => false);
 }
 /**
  * Returns the page updates implied by the given the change.
  *
  * @param EntityChange $change
  *
  * @return Traversable of PageEntityUsages
  */
 private function getAffectedPages(EntityChange $change)
 {
     $entityId = $change->getEntityId();
     $changedAspects = $this->getChangedAspects($change);
     $usages = $this->usageLookup->getPagesUsing(array($entityId), array_merge($changedAspects, array(EntityUsage::ALL_USAGE)));
     // @todo: use iterators throughout!
     $usages = iterator_to_array($usages, true);
     $usages = $this->transformAllPageEntityUsages($usages, $entityId, $changedAspects);
     if ($change instanceof ItemChange && in_array(EntityUsage::TITLE_USAGE, $changedAspects)) {
         $siteLinkDiff = $change->getSiteLinkDiff();
         $namesFromDiff = $this->getPagesReferencedInDiff($siteLinkDiff);
         $titlesFromDiff = $this->getTitlesFromTexts($namesFromDiff);
         $usagesFromDiff = $this->makeVirtualUsages($titlesFromDiff, $entityId, array(EntityUsage::SITELINK_USAGE));
         //FIXME: we can't really merge if $usages is an iterator, not an array.
         //TODO: Inject $usagesFromDiff "on the fly" while streaming other usages.
         //NOTE: $usages must pass through mergeUsagesInto for re-indexing
         $mergedUsages = array();
         $this->mergeUsagesInto($usages, $mergedUsages);
         $this->mergeUsagesInto($usagesFromDiff, $mergedUsages);
         $usages = $mergedUsages;
     }
     return new ArrayIterator($usages);
 }
 /**
  * @dataProvider changeProvider
  * @since 0.4
  */
 public function testToString(EntityChange $entityChange)
 {
     $string = $entityChange->__toString();
     $id = strtolower($entityChange->getEntityId()->getSerialization());
     $type = $entityChange->getType();
     $this->assertContains("'object_id' => '{$id}'", $string, "missing entity ID {$id}");
     $this->assertContains("'type' => '{$type}'", $string, "missing type {$type}");
 }