public static function readFamilyData($titleString, &$data, &$gedcomData, $includeRelativeData = false, $includeNonCompareData = false, $revid = 0, $timestamp = '') { $children = array(); $data['familyTitle'][] = $titleString; if (GedcomUtil::isGedcomTitle($titleString)) { $title = null; $data['Exists'] = true; $xml = GedcomUtil::getGedcomXml($gedcomData, $titleString); $data['GedcomMatchTitle'] = (string) $xml['match']; $contents = GedcomUtil::getGedcomContents($gedcomData, $titleString); } else { $title = Title::newFromText($titleString, NS_FAMILY); $data['Exists'] = $title->exists(); $p = new Family($titleString); $p->loadPage($revid); if ($revid) { $data['Revid'][] = $revid; } // for consistency with readPersonData $xml = $p->getPageXml(); $contents = $p->getPageContents(); } $husbandFound = $wifeFound = false; if ($includeRelativeData) { CompareForm::initPersonData('husband', $data); CompareForm::initPersonData('wife', $data); } if (isset($xml)) { foreach ($xml->event_fact as $ef) { $type = (string) $ef['type']; if ($type == Family::$MARRIAGE_TAG || $type == Family::$ALT_MARRIAGE_TAG) { CompareForm::getDatePlace($ef, 'Marriagedate', 'Marriageplace', $data); } else { if ($includeNonCompareData) { CompareForm::getOtherEvent($ef, '', $data); } } } if ($includeNonCompareData) { CompareForm::getSINContents($xml, $contents, '', $data); } if ($includeRelativeData) { $husbandFound = CompareForm::readRelativeData('husband', $xml->husband, $data, $gedcomData, true, false, $includeNonCompareData, $timestamp); $wifeFound = CompareForm::readRelativeData('wife', $xml->wife, $data, $gedcomData, true, false, $includeNonCompareData, $timestamp); $i = 0; foreach ($xml->child as $c) { $childTitle = (string) $c['title']; if ($childTitle) { $children[$i] = array(); CompareForm::initPersonData('child', $children[$i]); if (GedcomUtil::isGedcomTitle($childTitle)) { $childRevid = 0; } else { $t = Title::newFromText($childTitle, NS_PERSON); $childRevid = $timestamp ? StructuredData::getRevidForTimestamp($t, $timestamp) : 0; } CompareForm::readPersonData('child', $childTitle, $children[$i], $gedcomData, false, false, true, $includeNonCompareData, $childRevid); $i++; } } } else { $data['husbandTitle'] = array(); foreach ($xml->husband as $m) { $data['husbandTitle'][] = (string) $m['title']; } $data['wifeTitle'] = array(); foreach ($xml->wife as $m) { $data['wifeTitle'][] = (string) $m['title']; } $data['childTitle'] = array(); foreach ($xml->child as $m) { $data['childTitle'][] = (string) $m['title']; } } } else { if ($title && StructuredData::isRedirect($contents)) { $data['Redirect'] = true; } } if ($includeRelativeData && (!$husbandFound || !$wifeFound)) { list($fg, $fs, $mg, $ms) = StructuredData::parseFamilyTitle($titleString); if (!$husbandFound) { if ($fg) { $data['husbandGiven'][] = $fg; } if ($fs) { $data['husbandSurname'][] = $fs; } } if (!$wifeFound) { if ($mg) { $data['wifeGiven'][] = $mg; } if ($ms) { $data['wifeSurname'][] = $ms; } } } $data['Nomerge'] = CompareForm::getNomergeTitleStrings($title); if ($title) { $data['Updatable'] = CompareForm::isUpdatable($title, $contents); } return $children; }
/** * Return true if xml property is valid */ protected function validateData(&$textbox1) { global $wgUser; if (!StructuredData::titleStringHasId($this->titleString)) { return false; } if (ESINHandler::hasAmbiguousDates($this->xml)) { return false; } if (!StructuredData::isRedirect($textbox1)) { $husbands = StructuredData::getTitlesAsArray($this->xml->husband); $wives = StructuredData::getTitlesAsArray($this->xml->wife); $children = StructuredData::getTitlesAsArray($this->xml->child); return !StructuredData::titlesOverlap($husbands, $wives) && !StructuredData::titlesOverlap($husbands, $children) && !StructuredData::titlesOverlap($wives, $children) && ($this->isGedcomPage || !StructuredData::titlesMissingId($husbands)) && ($this->isGedcomPage || !StructuredData::titlesMissingId($wives)) && ($this->isGedcomPage || !StructuredData::titlesMissingId($children)) && ($wgUser->isAllowed('patrol') || StructuredData::titlesExist(NS_PERSON, $husbands)) && ($wgUser->isAllowed('patrol') || StructuredData::titlesExist(NS_PERSON, $wives)) && ($wgUser->isAllowed('patrol') || StructuredData::titlesExist(NS_PERSON, $children)); } return true; }
/** * Return true if xml property is valid */ protected function validateData(&$textbox1) { if (!StructuredData::isRedirect($textbox1)) { return StructuredData::isValidUrl((string) $this->xml->url); } return true; }
private function readData() { $first = true; $familyMembers = array(); foreach ($this->data as &$datai) { $j = 0; while ($j < count($datai)) { $dataij =& $datai[$j]; if (GedcomUtil::isGedcomTitle($dataij['title'])) { $xml = GedcomUtil::getGedcomXml($this->gedcomData, $dataij['title']); if ($xml['merged'] == 'true' && (string) $xml['match'] == (string) $datai[count($datai) - 1]['title']) { $this->redirects[] = Title::newFromText($dataij['title'], $this->namespace == 'Family' && $first ? NS_FAMILY : NS_PERSON); array_splice($datai, $j, 1); // remove this page from the merge $j--; } else { $dataij['gedcom'] = true; $dataij['object'] = null; $dataij['revid'] = false; $dataij['talkrevid'] = false; MergeForm::readXmlData($this->namespace == 'Family' && $first, $xml, $dataij); $dataij['contents'] = GedcomUtil::getGedcomContents($this->gedcomData, $dataij['title']); } } else { $dataij['gedcom'] = false; if ($this->namespace == 'Family' && $first) { $title = Title::newFromText($dataij['title'], NS_FAMILY); $dataij['object'] = new Family($dataij['title']); } else { $title = Title::newFromText($dataij['title'], NS_PERSON); $dataij['object'] = new Person($dataij['title']); } $dataij['revid'] = $title->getLatestRevID(GAID_FOR_UPDATE); // make sure you read the master db $dataij['object']->loadPage($dataij['revid']); $xml = $dataij['object']->getPageXml(); $talkTitle = $title->getTalkPage(); $dataij['talkrevid'] = $talkTitle->getLatestRevID(GAID_FOR_UPDATE); // make sure you read the master db // this must be a family member // non-family members can appear in gedcom updates -- gedcom page has been matched to a page in another family // or they can appear when the family is do not merge if ($this->namespace == 'Family' && !$first && !@$familyMembers[$dataij['title']]) { array_splice($datai, $j, 1); // remove this page from the merge $j--; } else { if ($this->doNotMerge($datai, $title)) { $this->nomerges[] = $title; } else { if (isset($xml)) { MergeForm::readXmlData($this->namespace == 'Family' && $first, $xml, $dataij); $dataij['contents'] =& $dataij['object']->getPageContents(); if ($this->namespace == 'Family' && $first) { foreach ($xml->husband as $m) { $familyMembers[(string) $m['title']] = 1; } $data['wifeTitle'] = array(); foreach ($xml->wife as $m) { $familyMembers[(string) $m['title']] = 1; } $data['childTitle'] = array(); foreach ($xml->child as $m) { $familyMembers[(string) $m['title']] = 1; } } } else { if (StructuredData::isRedirect($dataij['object']->getPageContents())) { $this->redirects[] = $title; array_splice($datai, $j, 1); // remove this page from the merge $j--; } else { if ($dataij['revid']) { // page exists but doesn't have xml and is not a redirect array_splice($datai, $j, 1); // remove this page from the merge $j--; error_log("ERROR: Merging page exists without XML: " . $title->getPrefixedText() . "\n"); } } } } } } $j++; } $first = false; } $this->removeSingletonFamilyMemberRows(); }
private function getEditText(&$request, &$text) { // If there is a redirect, don't add anything, even the surrounding tag. // This makes #redirect directives still work, since redirect pages don't have any data in the edit fields, // so the #redirect directive remains the first (and only) thing on the page if (!StructuredData::isRedirect($text)) { if ($this->footer && mb_strpos($text, $this->footer) === false) { $ftr = ($text && !StructuredData::endsWith($text, "\n") ? "\n" : '') . $this->footer; } else { $ftr = ''; } $xmlElementsString = $this->fromEditFields($request); return "<{$this->tagName}>\n{$xmlElementsString}</{$this->tagName}>\n{$text}{$ftr}"; } else { return $text; } }
/** * Return true if xml property is valid * textbox1 passed by reference for efficiency; don't change it */ protected function validateData(&$textbox1) { global $wgUser; if (!StructuredData::titleStringHasId($this->titleString)) { return false; } if (ESINHandler::hasAmbiguousDates($this->xml)) { return false; } if (!StructuredData::isRedirect($textbox1)) { $parentFamilies = StructuredData::getTitlesAsArray($this->xml->child_of_family); $spouseFamilies = StructuredData::getTitlesAsArray($this->xml->spouse_of_family); return !ESINHandler::isLiving($this->xml) && strlen((string) $this->xml->gender) > 0 && !StructuredData::titlesOverlap($parentFamilies, $spouseFamilies) && ($this->isGedcomPage || !StructuredData::titlesMissingId($parentFamilies)) && ($this->isGedcomPage || !StructuredData::titlesMissingId($spouseFamilies)) && ($wgUser->isAllowed('patrol') || StructuredData::titlesExist(NS_FAMILY, $parentFamilies)) && ($wgUser->isAllowed('patrol') || StructuredData::titlesExist(NS_FAMILY, $spouseFamilies)); } return true; }
/** * Propagate data in xml property to other articles if necessary * @param string $oldText contains text being replaced * @param String $text which we never touch when propagating places * @param bool $textChanged which we never touch when propagating places * @return bool true if propagation was successful */ protected function propagateEditData($oldText, &$text, &$textChanged) { $result = true; // determine current parents and type and lat and lng list($alsoLocatedIn, $type, $lat, $lng, $fromYear, $toYear) = Place::getPropagatedData($this->xml); // determine original parents by retrieving current version list($origAlsoLocatedIn, $origType, $origLat, $origLng, $origFromYear, $origToYear) = array(array(), null, null, null, null, null); if ($oldText) { $origXml = StructuredData::getXml('place', $oldText); if (isset($origXml)) { list($origAlsoLocatedIn, $origType, $origLat, $origLng, $origFromYear, $origToYear) = Place::getPropagatedData($origXml); // maintain place_abbrevs if (!isset($this->xml) || Place::placeAbbrevsChanged($origXml, $this->xml)) { Place::placeAbbrevsDelete($this->titleString); if (isset($this->xml)) { Place::placeAbbrevsAdd($this->titleString, $this->xml); } } } else { // new place comes here or below // add to place_abbrevs Place::placeAbbrevsDelete($this->titleString); Place::placeAbbrevsAdd($this->titleString, $this->xml); } } else { // add to place_abbrevs Place::placeAbbrevsDelete($this->titleString); Place::placeAbbrevsAdd($this->titleString, $this->xml); } // $delAlsoLocatedIn = StructuredData::mapDiff($origAlsoLocatedIn, $alsoLocatedIn, 'place'); // don't remove from X if this place is locatedIn X // if ($this->locatedIn) { // $key = StructuredData::mapSearch($this->locatedIn, $delAlsoLocatedIn, 'place'); // if ($key!==false) { // array_splice($delAlsoLocatedIn, $key, 1); // } // } // if ($type != $origType || $lat != $origLat || $lng != $origLng) { // $updAlsoLocatedIn = $alsoLocatedIn; // } // else { // $updAlsoLocatedIn = array_diff($alsoLocatedIn, $origAlsoLocatedIn); // } // remove from original parent if necessary (don't remove from X if this place is now prevLocatedIn X) // if ($origLocatedIn && $origLocatedIn != $locatedIn && array_search($origLocatedIn, $alsoLocatedIn)===false) { // $parentArticle = StructuredData::getArticle(Title::newFromText((string)$origLocatedIn, NS_PLACE), true); // if ($parentArticle) { // $content =& $parentArticle->fetchContent(); // $updatedContent =& $this->updateContainedPlace(null, null, null, null, $content); // if ($updatedContent) { // $updateResult = $parentArticle->doEdit($updatedContent, self::PROPAGATE_MESSAGE, PROPAGATE_EDIT_FLAGS); // $result = $result && $updateResult; // } // } // } $isRedirect = StructuredData::isRedirect($text); if ($isRedirect) { // add alt name to redirect target list($prefName, $locatedIn) = Place::getPrefNameLocatedIn($this->titleString); $prefName = StructuredData::mb_str_replace($prefName, '_', ' '); // convert _'s back to spaces $newTitle = Title::newFromRedirect($text); $targetArticle = StructuredData::getArticle($newTitle, true); $targetContent =& $targetArticle->fetchContent(); $targetXml = StructuredData::getXml('place', $targetContent); $found = false; foreach ($targetXml->alternate_name as $an) { $altName = (string) $an['name']; if ($altName == $prefName) { $found = true; break; } } if (!$found) { $altName = '<alternate_name name="' . StructuredData::escapeXml($prefName) . '" source="from redirect"/>'; $targetContent = StructuredData::mb_str_replace($targetContent, "<place>", "<place>\n" . $altName); $targetArticle->doEdit($targetContent, 'Add alternate name from redirect', PROPAGATE_EDIT_FLAGS); } // edit wlh pages to point to the target title $job = new PlaceRedirectJob(array('old_title' => $this->titleString, 'new_title' => $newTitle->getText())); $job->insert(); } // update type, lat, or lng if changed, or this place has been redirected or this place is new if ($this->locatedIn && ($isRedirect || !isset($origXml) || $type != $origType || $lat != $origLat || $lng != $origLng || $fromYear != $origFromYear || $toYear != $origToYear)) { $parentArticle = StructuredData::getArticle(Title::newFromText($this->locatedIn, NS_PLACE), true); if ($parentArticle) { $content =& $parentArticle->fetchContent(); if ($isRedirect) { // remove from parent $updatedContent =& $this->updateContainedPlace(null, null, null, null, null, null, $content); } else { $updatedContent =& $this->updateContainedPlace($this->titleString, $type, $lat, $lng, $fromYear, $toYear, $content); } if ($updatedContent) { $updateResult = $parentArticle->doEdit($updatedContent, self::PROPAGATE_MESSAGE . ' [[' . $this->title->getPrefixedText() . ']]', PROPAGATE_EDIT_FLAGS); $result = $result && $updateResult; } } } // remove from deleted previous parents foreach ($origAlsoLocatedIn as $pli) { if ($this->locatedIn != (string) $pli['place'] && StructuredData::mapArraySearch((string) $pli['place'], $alsoLocatedIn, 'place') === false) { $parentArticle = StructuredData::getArticle(Title::newFromText((string) $pli['place'], NS_PLACE), true); if ($parentArticle) { $content =& $parentArticle->fetchContent(); $updatedContent =& $this->updateContainedPlace(null, null, null, null, null, null, $content); if ($updatedContent) { $updateResult = $parentArticle->doEdit($updatedContent, self::PROPAGATE_MESSAGE . ' [[' . $this->title->getPrefixedText() . ']]', PROPAGATE_EDIT_FLAGS); $result = $result && $updateResult; } } } } // add to new previous parents or update type, lat, lng on same previous-parents foreach ($alsoLocatedIn as $pli) { $origKey = StructuredData::mapArraySearch((string) $pli['place'], $origAlsoLocatedIn, 'place'); if ($origKey !== false) { $origPli = $origAlsoLocatedIn[$origKey]; } if ($this->locatedIn != (string) $pli['place'] && ($origKey === false || $type != $origType || $lat != $origLat || $lng != $origLng || (string) $pli['from_year'] != (string) $origPli['from_year'] || (string) $pli['to_year'] != (string) $origPli['to_year'])) { $parentArticle = StructuredData::getArticle(Title::newFromText((string) $pli['place'], NS_PLACE), true); if ($parentArticle) { $content =& $parentArticle->fetchContent(); $updatedContent =& $this->updateContainedPlace($this->titleString, $type, $lat, $lng, (string) $pli['from_year'], (string) $pli['to_year'], $content); if ($updatedContent) { $updateResult = $parentArticle->doEdit($updatedContent, self::PROPAGATE_MESSAGE . ' [[' . $this->title->getPrefixedText() . ']]', PROPAGATE_EDIT_FLAGS); $result = $result && $updateResult; } } } } if (!$result) { error_log("ERROR! Place edit/rollback not propagated: {$this->titleString}\n"); } return $result; }
/** * Return true if xml property is valid */ protected function validateData(&$textbox1) { if (!StructuredData::isRedirect($textbox1)) { foreach ($this->xml->repository as $repository) { if (!(string) $repository['availability']) { return false; } } return StructuredData::isValidYear((string) $this->xml->from_year) && StructuredData::isValidYear((string) $this->xml->to_year); } return true; }