/** * Try to disambiguate the ambiguous values. If not possible, pass the values to the successor and try to * disambiguate with the successor. If possible, store ambiguous and disambiguated values. */ public function disambiguate() { Container::getContext()->removeDisambiguationOptions('Geissler\\CSL\\Names\\Name'); $this->tmpDisambiguate = $this->getDisambiguate(); $this->tmpAmbiguous = $this->getAmbiguous(); $firstDifferent = false; // disambiguate years and missing years $this->regExp = '/([0-9]{2,4}'; if (Container::getLocale()->getTerms('do date', 'short') !== null) { $this->regExp .= '|' . Container::getLocale()->getTerms('do date', 'short'); } elseif (Container::getLocale()->getTerms('do date', 'short') !== null) { $this->regExp .= '|' . Container::getLocale()->getTerms('do date'); } $this->regExp .= ')/'; // disambiguate only where names and year are identical foreach ($this->tmpAmbiguous as $id => $name) { if (preg_match($this->regExp, $name) == 0) { $citation = Container::getRendered()->getFirstById($id); if (preg_match($this->regExp, $citation) == 1 && preg_match('/^' . preg_quote($this->tmpAmbiguous[$id], '/') . '/', $citation) == 1) { $this->tmpAmbiguous[$id] = $citation; } } } $ambiguous = ArrayData::ambiguous($this->tmpAmbiguous); if (count($ambiguous) > 0) { $this->tmpAmbiguous = $ambiguous; $this->addYearSuffix(); } elseif ($firstDifferent == true) { // test if second citation is ambiguous $this->tmpAmbiguous = $this->getAmbiguous(); $this->addYearSuffix(); } elseif (is_array($this->tmpDisambiguate) == true) { $this->tmpDisambiguate = array_merge($this->tmpDisambiguate, $this->getAmbiguous()); } else { $this->tmpDisambiguate = $this->getAmbiguous(); } if (count($ambiguous) > 0) { // store already disambiguated values $succeedAmbiguous = array(); if ($this->getAmbiguous() == $ambiguous) { $succeedAmbiguous = $ambiguous; } $this->succeed($this->getDisambiguate(), $succeedAmbiguous); } }
/** * Add by et-al suppressed names to disambiguate the cites. * * @param array $ambiguous * @return array */ private function addNames($ambiguous) { $last = ''; $original = $this->renderNames($ambiguous); $highestEtAl = $this->etAl; $names = array(); do { $this->etAl++; Container::getContext()->setDisambiguationOptions('Geissler\\CSL\\Names\\Name', array('etAlUseFirst' => $this->etAl)); $values = $this->renderNames($ambiguous); // keep disambiguate values $keep = ArrayData::disambiguate($values); foreach ($keep as $id => $newValue) { $this->tmpDisambiguate[$id] = str_replace($original[$id], $newValue, $this->tmpAmbiguous[$id]); unset($this->tmpAmbiguous[$id]); $highestEtAl = $this->etAl; $names[$id] = $newValue; } $ambiguous = ArrayData::ambiguous($values); if ($last == implode('', $ambiguous)) { break; } else { $last = implode('', $ambiguous); } } while (1 == 1); return array('etAl' => $highestEtAl, 'ambiguous' => $ambiguous, 'names' => $names); }
/** * Disambiguate citations if citation-label is used but no name. * * @param array $citations */ private function disambiguateByCitationLabel($citations) { $ambiguous = ArrayData::ambiguous($citations); new Chain($ambiguous); }
/** * Render names in all possible forms an pick the right one. * * @param $ambiguous * @return bool */ protected function addGivenName(array $ambiguous) { $layout = Container::getContext()->get('layout', 'layout'); $originalFull = array(); foreach (array_keys($ambiguous) as $id) { $originalFull[$id] = $layout->renderById($id, ''); } // render standard form $standard = $this->renderNames($ambiguous, true); // render long form Container::getContext()->setDisambiguationOptions('Geissler\\CSL\\Names\\Name', array('form' => 'long')); // long form with spaces in given names $longGivenNames = $this->renderNames($ambiguous, true); Container::getContext()->setDisambiguationOptions('Geissler\\CSL\\Names\\Name', array('trimGivenName' => true)); $longForm = $this->renderNames($ambiguous, true); // render not initialized form Container::getContext()->removeDisambiguationOption('Geissler\\CSL\\Names\\Name', 'trimGivenName'); Container::getContext()->setDisambiguationOptions('Geissler\\CSL\\Names\\Name', array('initialize' => false)); // given names with normal spaces $notInitTrimNames = $this->renderNames($ambiguous, true); Container::getContext()->setDisambiguationOptions('Geissler\\CSL\\Names\\Name', array('trimGivenName' => true)); $notInitForm = $this->renderNames($ambiguous, true); $disambiguate = array(); $numberOfAmbiguous = count($standard); $disambiguationRule = Container::getContext()->getValue('givennameDisambiguationRule', 'citation'); if ($numberOfAmbiguous > 0 && is_array(current($standard)) == true) { $numberOfNames = count(current($standard)); for ($i = 0; $i < $numberOfNames; $i++) { $actualStandard = $this->createArrayWithDataFromPosition($standard, $i); $actualLong = $this->createArrayWithDataFromPosition($longForm, $i); $actualInit = $this->createArrayWithDataFromPosition($notInitForm, $i); $actualLongTrim = $this->createArrayWithDataFromPosition($longGivenNames, $i); $actualInitTrim = $this->createArrayWithDataFromPosition($notInitTrimNames, $i); // check which standard forms are already ambiguous $standardAmbiguous = ArrayData::disambiguate($actualStandard); if (count($standardAmbiguous) > 0) { foreach (array_keys($standardAmbiguous) as $id) { if (isset($actualLong[$id]) == true) { unset($actualLong[$id]); } if (isset($actualInit[$id]) == true) { unset($actualInit[$id]); } } } // disambiguate by long form $longAmbiguous = ArrayData::disambiguate($actualLong); if (count($longAmbiguous) > 0) { foreach ($longAmbiguous as $id => $name) { if (isset($disambiguate[$id]) == false) { $disambiguate[$id] = array(); } $disambiguate[$id][] = array('position' => $i, 'value' => $actualLongTrim[$id], 'form' => 'long'); if (isset($actualInit[$id]) == true) { unset($actualInit[$id]); } } } // disambiguate by initialize set to false if ($disambiguationRule !== 'all-names-with-initials' && $disambiguationRule !== 'primary-name-with-initials') { $initAmbiguous = ArrayData::disambiguate($actualInit); if (count($initAmbiguous) > 0) { foreach ($initAmbiguous as $id => $name) { if (isset($disambiguate[$id]) == false) { $disambiguate[$id] = array(); } $disambiguate[$id][] = array('position' => $i, 'value' => $actualInitTrim[$id], 'form' => 'init'); } } } $stop = false; switch ($disambiguationRule) { case 'all-names': break; case 'by-cite': if (count($disambiguate) > 0) { $stop = true; } break; case 'primary-name': case 'primary-name-with-initials': $stop = true; break; } if ($stop == true) { break; } } } // change disambiguated names $highestPosition = 0; $form = ''; foreach ($disambiguate as $id => $changes) { $originalValue = $originalFull[$id]; // replace previously modified names if (isset($this->replaceNames[$id]) == true) { foreach ($this->replaceNames[$id] as $replace => $replaceBy) { $originalValue = str_replace($replace, $replaceBy, $originalValue); } } foreach ($changes as $options) { $replace = $standard[$id][$options['position']]; $originalValue = str_replace($replace, $options['value'], $originalValue); if ($highestPosition < $options['position']) { $highestPosition = $options['position']; $form = $options['form']; } } $this->tmpDisambiguate[$id] = $originalValue; unset($this->tmpAmbiguous[$id]); } // other ambiguous cites muss at least contain the same number of names if ($highestPosition > 0) { Container::getContext()->removeDisambiguationOptions('Geissler\\CSL\\Names\\Name'); $etAl = Container::getContext()->getValue('etAlUseFirst', 'citation'); Container::getContext()->setDisambiguationOptions('Geissler\\CSL\\Names\\Name', array('etAlUseFirst' => $etAl + $highestPosition)); foreach (array_keys($this->tmpAmbiguous) as $id) { $this->tmpAmbiguous[$id] = $layout->renderById($id, ''); // replace ambiguous names at position of disambiguate value foreach ($disambiguate as $changes) { foreach ($changes as $options) { $replace = $standard[$id][$options['position']]; if ($form == 'long') { $replaceBy = $longForm[$id][$options['position']]; } else { $replaceBy = $notInitForm[$id][$options['position']]; } $this->tmpAmbiguous[$id] = str_replace($replace, $replaceBy, $this->tmpAmbiguous[$id]); // store name replacement if (isset($this->replaceNames[$id]) == false) { $this->replaceNames[$id] = array(); } $this->replaceNames[$id][$replace] = $replaceBy; } } } } if (count($this->tmpAmbiguous) > 0) { return false; } return true; }