private function getMergeScore() { $totalScore = $totalCount = 0; $baseStdData = array(); for ($m = count($this->data) - 1; $m >= 0; $m--) { for ($p = 0; $p < count($this->data[$m]); $p++) { // calculate a total match score if ($this->data[$m][$p]['revid'] || $this->data[$m][$p]['gedcom']) { // if page exists or is gedcom $mergeTargetNs = $this->namespace == 'Family' && $m == 0 ? NS_FAMILY : NS_PERSON; if ($mergeTargetNs == NS_FAMILY) { $stdData = MergeForm::standardizeFamilyData($this->data[$m][$p]); } else { $stdData = MergeForm::standardizePersonData($this->data[$m][$p]); } if ($p == 0) { $baseStdData = $stdData; } else { $score = MergeForm::calcMatchScore($baseStdData, $stdData); wfDebug("MERGESCORE title=" . $this->data[$m][$p]['title'] . " score={$score}\n"); $totalScore += $score; $totalCount++; } } } } if ($totalCount) { return $avgScore = $totalScore / $totalCount; } else { return 0; } }
function writeMerge($userid, &$userMerge) { $foundFamilyTitle = null; $foundPeopleCount = 0; $familyCount = 0; $mergeCount = count($userMerge->merges); $preMergeTimestamp = wfTimestamp(TS_MW, wfTimestamp(TS_UNIX, $userMerge->firstTimestamp) - 2); foreach ($userMerge->merges as $merge) { $mergeNs = $merge->target->title->getNamespace(); if ($mergeNs != NS_PERSON && $mergeNs != NS_FAMILY && $mergeNs != NS_PERSON_TALK && $mergeNs != NS_FAMILY_TALK) { return "invalid target for merge: title={$merge->target->title->getPrefixedText()}"; } if ($foundFamilyTitle && $mergeNs == NS_FAMILY) { return "invalid merge sequence - {$merge->target->title->getPrefixedText()} after family: {$foundFamilyTitle->getPrefixedText()}"; } if ($mergeNs == NS_FAMILY) { $familyCount = count($merge->sources) + 1; $foundFamilyTitle = $merge->target->title; } else { if ($mergeNs == NS_PERSON) { $foundPeopleCount++; } } // get target preRevid $revid = StructuredData::getRevidForTimestamp($merge->target->title, $preMergeTimestamp); // its ok if revid was created during the merge for talk pages if ($revid == 0 || $revid > $userMerge->lastRevid || $revid >= $userMerge->firstRevid && $mergeNs != NS_PERSON_TALK && $mergeNs != NS_FAMILY_TALK) { return "revision not found for target={$merge->target->title->getPrefixedText()} revid={$revid} firstRevid={$userMerge->firstRevid} timestamp={$preMergeTimestamp}"; } $merge->target->preRevid = $revid >= $userMerge->firstRevid ? 0 : $revid; // 0 if created during the merge $revision = Revision::newFromId($revid); $merge->target->revPage = $revision->getPage(); // get target postRevid and comment list($revid, $comment) = $this->getNextRevidComment($merge->target->revPage, $merge->target->preRevid); if ($revid != 0 && $revid <= $userMerge->lastRevid) { // if target was edited in the merge $merge->target->postRevid = $revid; $merge->target->comment = $comment; } // get source preRevid's and titles foreach ($merge->sources as $source) { $revid = $this->getPrevRevid($source->revPage, $source->postRevid); if (!$revid) { return "previous revision not found for source={$source->postRevid}"; } $source->preRevid = $revid; $revision = Revision::newFromId($revid); $title = $revision->getTitle(); if (!$title) { return "title not found for source={$source->postRevid}"; } $source->title = $title; if ($title->getNamespace() != $mergeNs) { return "invalid source={$title->getPrefixedText()} target={$merge->target->title->getPrefixedText()}"; } } } if ($foundPeopleCount > 1 && !$foundFamilyTitle) { return "invalid merge sequence: multiple merges without a family: count={$mergeCount}"; } if (!$foundFamilyTitle && $foundPeopleCount == 0) { return "invalid merge sequence: no people or families count={$mergeCount}"; } // put merge revids into their proper rows and columns, and add roles $mergeRows = array(); for ($m = 0; $m < count($userMerge->merges); $m++) { $mergeRows[$m] = (object) array('role' => '', 'revids' => array()); if ($foundFamilyTitle && $userMerge->merges[$m]->target->title->getNamespace() == NS_PERSON) { for ($p = 0; $p < count($familyCount); $p++) { $mergeRows[$m]->revids[$p] = array(); } } } $mainTitle = null; $totalScore = 0; $totalCount = 0; $seenRevids = array(); for ($m = 0; $m < count($userMerge->merges); $m++) { $merge =& $userMerge->merges[$m]; $ns = $merge->target->title->getNamespace(); // read baseData and data, calc match score if ($ns == NS_PERSON || $ns == NS_FAMILY) { $baseData = $this->readData($merge->target->title, $merge->target->preRevid); if (!$baseData) { return "unable to read data for {$merge->target->title->getPrefixedText()} revid={$merge->target->preRevid}"; } if ($ns == NS_FAMILY) { $baseStdData = MergeForm::standardizeFamilyData($baseData); } else { $baseStdData = MergeForm::standardizePersonData($baseData); } $data = array(); for ($p = 0; $p < count($merge->sources); $p++) { $data[$p] = $this->readData($merge->sources[$p]->title, $merge->sources[$p]->preRevid); if (!$data[$p]) { return "unable to read data for {$merge->sources[$p]->title->getPrefixedText()} revid={$merge->sources[$p]->preRevid}"; } if ($ns == NS_FAMILY) { $stdData = MergeForm::standardizeFamilyData($data[$p]); } else { $stdData = MergeForm::standardizePersonData($data[$p]); } $totalScore += MergeForm::calcMatchScore($baseStdData, $stdData); $totalCount++; } } if ($foundFamilyTitle && $ns == NS_FAMILY) { // use pre-merge family revisions to get roles, row numbers $this->recordFamilyMembers($baseData['husbands'], 'husband', 0, $userMerge->merges, $preMergeTimestamp, $familyCount, $mergeRows, $seenRevids); $this->recordFamilyMembers($baseData['wives'], 'wife', 0, $userMerge->merges, $preMergeTimestamp, $familyCount, $mergeRows, $seenRevids); $this->recordFamilyMembers($baseData['children'], 'child', 0, $userMerge->merges, $preMergeTimestamp, $familyCount, $mergeRows, $seenRevids); for ($p = 0; $p < count($data); $p++) { $this->recordFamilyMembers($data[$p]['husbands'], 'husband', $p + 1, $userMerge->merges, $preMergeTimestamp, $familyCount, $mergeRows, $seenRevids); $this->recordFamilyMembers($data[$p]['wives'], 'wife', $p + 1, $userMerge->merges, $preMergeTimestamp, $familyCount, $mergeRows, $seenRevids); $this->recordFamilyMembers($data[$p]['children'], 'child', $p + 1, $userMerge->merges, $preMergeTimestamp, $familyCount, $mergeRows, $seenRevids); } } if (!$foundFamilyTitle || $ns != NS_PERSON) { // handle people in families above $mergeRows[$m]->revids[0] = array(); $mergeRows[$m]->revids[0][] = $merge->target->preRevid; for ($p = 0; $p < count($merge->sources); $p++) { $mergeRows[$m]->revids[$p + 1] = array(); $mergeRows[$m]->revids[$p + 1][] = $merge->sources[$p]->preRevid; } if ($ns == NS_PERSON_TALK || $ns == NS_FAMILY_TALK) { $mergeRows[$m]->role = 'talk'; } else { if ($ns == NS_PERSON) { $mergeRows[$m]->role = 'Person'; } else { if ($ns == NS_FAMILY) { $mergeRows[$m]->role = 'Family'; } } } } if ($ns == NS_FAMILY || $ns == NS_PERSON && !$foundFamilyTitle) { $mainTitle = $merge->target->title; } } if ($foundFamilyTitle && $mainTitle->getPrefixedText() != $foundFamilyTitle->getPrefixedText()) { return "family titles not equal: {$mainTitle->getPrefixedText()} and {$foundFamilyTitle->getPrefixedText()}"; } if ($foundFamilyTitle) { // verify that all merging people have been recorded in mergeRows somewhere foreach ($userMerge->merges as &$merge) { if ($merge->target->title->getNamespace() == NS_PERSON) { if (!@$seenRevids[$merge->target->preRevid]) { return "target person not found: {$merge->target->title->getPrefixedText()}"; } foreach ($merge->sources as &$source) { if (!@$seenRevids[$source->preRevid]) { return "source person not found: {$source->title->getPrefixedText()}"; } } } } } // write mergelog record $mergeScore = $totalCount > 0 ? $totalScore / $totalCount : 0; $isTrustedUser = CompareForm::isTrustedMerger(User::newFromName(User::whois($userid))); $isTrustedMerge = MergeForm::isTrustedMerge($mergeScore, $isTrustedUser); $mergeId = $this->writeMergelog($userid, $userMerge, $mergeScore, $isTrustedMerge, $mainTitle, $mergeRows); // update post-merge comments with ml_id $this->updateMergeComments($userMerge, $mainTitle, $mergeId); $this->log("INFO", "writeMerge id={$mergeId} score={$mergeScore} isTrusted={$isTrustedMerge} merges={$mergeCount} title={$mainTitle->getPrefixedText()}", $userid, $userMerge->firstTimestamp); return ''; }