/** * Test if label is equal to the variable. * * @param string $variable * @return bool */ protected function validateVariable($variable) { if (Container::getData()->getVariable('label') == $variable || is_object(Container::getCitationItem()) == true && Container::getCitationItem()->get('label') == $variable) { return true; } return false; }
/** * Use only some child elements for rendering if author-only or suppress-author is used. * * @param array $children * @return array */ public function getRenderClasses(array $children) { // render just child elements of a given class (@see Macro) if (Container::getContext()->in('sort') == true && Container::getContext()->get('renderJust', 'sort') !== null) { $toRender = Container::getContext()->get('renderJust', 'sort'); $render = array(); foreach ($children as $child) { if (in_array(get_class($child), $toRender) == true || $child instanceof \Geissler\CSL\Interfaces\Parental) { $render[] = $child; } } return $render; } elseif (Container::getCitationItem() !== false) { if (Container::getCitationItem()->get('author-only') == 1) { $render = array(); foreach ($children as $child) { if (in_array('Geissler\\CSL\\Interfaces\\Variable', class_implements($child)) == true && $child->isAccessingVariable('author') == true) { $render[] = $child; } } if (count($render) == 0) { foreach ($children as $child) { if (in_array('Geissler\\CSL\\Interfaces\\Variable', class_implements($child)) == true && $child->isAccessingVariable('citation-number') == true) { $render[] = new Value(new \SimpleXMLElement('<value value="Reference " />')); $render[] = $child; } } } return $render; } elseif (Container::getCitationItem()->get('suppress-author') == 1) { return $this->suppressAuthor($children); } } return $children; }
/** * Replacing the id's by the rendered and disambiguated values and add the delimiter. * * @param array $data * @return array|string */ public function apply(array $data) { $delimiter = Container::getContext()->get('delimiter', 'layout'); $layout = Container::getContext()->get('layout', 'layout'); // move to starting position for citations and citations items $citationData = false; if (Container::getCitationItem() !== false) { $citationData = true; Container::getCitationItem()->moveToFirst(); } // remove all additional temporary disambiguation options Container::getContext()->clearDisambiguationOptions(); // replace item ids by disambiguate cite $length = count($data); for ($i = 0; $i < $length; $i++) { if (is_array($data[$i]) == true) { $innerLength = count($data[$i]); for ($j = 0; $j < $innerLength; $j++) { // add existing prefix and/or suffixes to the rendered value $actualCitation = Container::getRendered()->get($data[$i][$j]); // re-render citation if missing if ($actualCitation == false) { Container::getContext()->enter('disambiguation'); $data[$i][$j] = array('value' => $layout->renderJustActualEntry(''), 'delimiter' => ''); Container::getContext()->leave(); } else { $data[$i][$j] = array('value' => $actualCitation, 'delimiter' => ''); } // Add delimiter at end if not ending with a dot // (see affix_SuppressDelimiterCharsWhenFullStopInSuffix.txt) if ($j < $innerLength - 1) { if (preg_match('/\\.$/', $data[$i][$j]['value']) == 0) { $data[$i][$j]['delimiter'] = $delimiter; } else { $data[$i][$j]['delimiter'] = ' '; } } // move to next in group if ($citationData == true) { Container::getCitationItem()->nextInGroup(); } } } else { // re-render citation if missing $actualCitation = Container::getRendered()->get($data[$i]); if ($actualCitation == false) { Container::getContext()->enter('disambiguation'); $data[$i] = array('value' => $layout->renderJustActualEntry(''), 'delimiter' => ''); Container::getContext()->leave(); } else { $data[$i] = array('value' => $actualCitation, 'delimiter' => ''); } } if ($citationData == true) { Container::getCitationItem()->next(); } } return $data; }
/** * 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'); Container::getContext()->setChooseDisambiguateValue(true); $layout = Container::getContext()->get('layout', 'layout'); $secondary = Container::getCitationItem()->getWithIds(array_keys($this->getAmbiguous())); foreach ($secondary as $entry) { Container::getCitationItem()->moveTo($entry['id'], $entry['citationID']); Container::getData()->moveToId($entry['id']); Container::getRendered()->set($entry['id'], $entry['citationID'], $layout->renderById($entry['id'], '')); } }
/** * Render the citations. * * @param string $data * @return string */ public function render($data) { Container::getContext()->enter('citation'); // sort if (isset($this->sort) == true) { $this->sort->sort('citation'); } // render citation $result = $this->layout->render($data); // The assignment of the year-suffixes follows the order of the bibliographies entries, // so sort if disambiguation by year-suffixes is needed, sort the data by the bibliography // and re-render citations if (Container::hasBibliography() == true && Container::getContext()->getValue('disambiguateAddYearSuffix', 'citation') === true && Container::getContext()->getLastDisambiguation() == 'Geissler\\CSL\\Options\\Disambiguation\\AddYearSuffix' && Container::getBibliography()->sort() == true) { Container::getRendered()->clear(); // re-render citation $result = $this->layout->render($data); } if (Container::getCitationItem() !== false) { // apply additional citation formatting options Container::getCitationItem()->moveToFirst(); if (Container::getCitationItem()->get('noteIndex') !== null || Container::getCitationItem()->get('index') !== null) { $citation = array(); $length = count($result); $prefix = '..'; for ($i = 0; $i < $length; $i++) { if ($i + 1 == $length) { $prefix = '>>'; } // Therefore, the first character of a citation should preferably be uppercased $citation[] = $prefix . '[' . $i . '] ' . $this->upperCase($result[$i]); } $return = implode("\n", $citation); } else { array_walk($result, array($this, 'upperCase')); $return = implode("\n", $result); } } else { array_walk($result, array($this, 'upperCase')); $return = implode("\n", $result); } Container::getContext()->leave(); return $return; }
/** * With cite grouping, cites in in-text citations with identical rendered names are grouped together. * * @param array $data * @return array */ public function apply(array $data) { $names = Container::getContext()->get('layout', 'layout')->getChildElement('\\Geissler\\CSL\\Names\\Names'); if ($this->active == false || is_object($names) == false || Container::getCitationItem() === false) { return $data; } Container::getCitationItem()->moveToFirst(); $delimiter = Container::getContext()->get('delimiter', 'layout'); if (isset($this->citeGroupDelimiter) == false) { $this->citeGroupDelimiter = $delimiter; $this->citeGroupDelimiter = ', '; } $length = count($data); $newData = array(); for ($i = 0; $i < $length; $i++) { // get all names in citation group $namesAsArray = array(); $namesFull = array(); do { Container::getData()->moveToId(Container::getActualId()); $namesAsArray[] = $names->renderAsArray(''); $namesFull[] = $names->render(''); } while (Container::getCitationItem()->nextInGroup() == true); $newData[$i] = array(); $citeLength = count($namesAsArray); for ($j = 0; $j < $citeLength; $j++) { $actualName = $namesAsArray[$j][0]; // check if name already used if ($actualName !== '' && isset($data[$i][$j]) == true) { $actualGroup = array($data[$i][$j]); $groupPosition = 0; for ($k = $j + 1; $k < $citeLength; $k++) { if ($actualName == $namesAsArray[$k][0] && $namesFull[$j] == $namesFull[$k] && isset($data[$i][$k]) == true) { // replace delimiter in previous group entry with cite group delimiter $actualGroup[$groupPosition]['delimiter'] = $this->citeGroupDelimiter; $actualGroup[] = $data[$i][$k]; $namesAsArray[$k][0] = ''; $groupPosition++; // Add delimiter to values without one if ($actualGroup[$groupPosition]['delimiter'] == '') { $actualGroup[$groupPosition]['delimiter'] = $delimiter; } } } $newData[$i] = array_merge($newData[$i], $actualGroup); } } // remove delimiter from last entry in group $newData[$i][count($newData[$i]) - 1]['delimiter'] = ''; Container::getCitationItem()->next(); } return $newData; }
/** * Add an alphabetic year-suffix to ambiguous cites. * * @return void */ private function addYearSuffix() { // test if year is rendered, if not try if year is rendered through choose disambiguate $layout = Container::getContext()->get('layout', 'layout'); if (preg_match($this->regExp, current($this->tmpAmbiguous)) == 0 && Container::getContext()->isChooseDisambiguationActive() == true) { Container::getContext()->setChooseDisambiguateValue(true); foreach (array_keys($this->tmpAmbiguous) as $id) { $reRendered = $layout->renderById($id, ''); if (isset($this->tmpAmbiguous[$id]) == true && $reRendered !== $this->tmpAmbiguous[$id]) { $this->tmpAmbiguous[$id] = $reRendered; } } } if (array_values($this->tmpAmbiguous) > array_unique(array_values($this->tmpAmbiguous))) { $useYearSuffix = $layout->isAccessingVariable('year-suffix'); $suffix = 'a'; foreach (array_keys($this->tmpAmbiguous) as $id) { Container::getData()->moveToId($id); $actualSuffix = Container::getData()->getVariable('year-suffix'); if ($actualSuffix === null) { // store year-suffix variable Container::getData()->setVariable('year-suffix', $suffix); $actualSuffix = $suffix; } if (Container::getCitationItem() !== false) { $cites = Container::getCitationItem()->getWithIds(array($id)); foreach ($cites as $entry) { Container::getCitationItem()->moveTo($id, $entry['citationID']); if ($useYearSuffix == true) { Container::getRendered()->clearById($id); Container::getRendered()->set($id, $entry['citationID'], $layout->renderById($id, '')); } else { Container::getRendered()->set($id, $entry['citationID'], $this->addYearSuffixToValue($this->tmpAmbiguous[$id], $actualSuffix)); } } } else { $cites = Container::getRendered()->getAllById(); foreach ($cites as $itemId => $value) { if ($itemId == $id) { if ($useYearSuffix == true) { Container::getRendered()->clearById($id); Container::getRendered()->set($id, 0, $layout->renderById($id, '')); } else { $newValue = $this->addYearSuffixToValue($value, $actualSuffix); Container::getRendered()->set($id, 0, $newValue); $this->tmpDisambiguate[$id] = $newValue; } } } } unset($this->tmpAmbiguous[$id]); $suffix++; } } }
/** * Retrieve a variable from a previous cite. * * @param string $variable * @return int|string */ private function getVariableForPrevious($variable) { $position = Container::getCitationItem()->getPosition(); $groupPosition = Container::getCitationItem()->getGroupPosition(); if ($groupPosition > 0) { return Container::getCitationItem()->getAtPosition($variable, $position, $groupPosition - 1); } elseif ($position > 0) { return Container::getCitationItem()->getAtPosition($variable, $position - 1, 0); } return ''; }
/** * Renders the names. * * @param array $data * @return string */ public function render($data) { $this->apply(); $names = array(); $length = count($data); if ($length == 0) { return ''; } for ($i = 0; $i < $length; $i++) { $names[] = $this->formatName($data[$i], $i); } $etAl = false; $etAlUseFirst = $this->etAlUseFirst; $etAlMin = $this->etAlMin; // If used, the values of these attributes replace those of respectively et-al-min and et-al-use-first // for subsequent cites (cites referencing earlier cited items) if (Container::getRendered()->get(Container::getActualId(), Container::getActualCitationId()) !== false) { if ($this->etAlSubsequentMin > 0) { $etAlMin = $this->etAlSubsequentMin; } if ($this->etAlSubsequentUseFirst !== '') { $etAlUseFirst = $this->etAlSubsequentUseFirst; } } if ($etAlMin > 0 && $length > 1 && $etAlMin <= $length && $etAlUseFirst < $length) { $etAl = true; } $namesAndSplitter = array(); $and = $this->getAndDelimiter(); $countNames = 0; for ($i = 0; $i < $length; $i++) { $namesAndSplitter[] = $names[$i]; $countNames++; if ($etAl == true && $i == $etAlUseFirst - 1) { switch ($this->delimiterPrecedesEtAl) { case 'contextual': if ($etAlUseFirst >= 2) { $namesAndSplitter[] = $this->delimiter; } break; case 'after-inverted-name': if ($this->nameAsSortOrder == 'first') { $namesAndSplitter[] = $this->delimiter; } break; case 'always': $namesAndSplitter[] = $this->delimiter; break; } // et-al Term $namesAndSplitter[] = ' '; $namesAndSplitter[] = Container::getLocale()->getTerms('et-al'); break; } // The delimiter between the second to last and last name of the names in a name variable if ($i == $length - 2 && $and !== '' && in_array($names[$i], $this->literals) == false) { switch ($this->delimiterPrecedesLast) { case 'contextual': if ($length >= 3) { $namesAndSplitter[] = $this->delimiter; } break; case 'after-inverted-name': if ($this->nameAsSortOrder == 'first') { $namesAndSplitter[] = $this->delimiter; } break; case 'always': $namesAndSplitter[] = $this->delimiter; break; case 'never': break; } if ($this->and !== '') { $namesAndSplitter[] = ' '; $namesAndSplitter[] = $and; $namesAndSplitter[] = ' '; } } elseif ($i < $length - 1) { $namesAndSplitter[] = $this->delimiter; } } // returns the total number of names that would otherwise be rendered if ($this->form == 'count') { return (int) $countNames; } $return = str_replace(' ', ' ', implode('', $namesAndSplitter)); // do not connect literals with an and if (count($this->literals) > 0) { $and = $and . ' '; foreach ($this->literals as $literal) { $return = str_replace($and . $literal, $literal, $return); } } // name lists truncated by et-al abbreviation are followed by the name delimiter, the ellipsis character, // and the last name of the original name list. if ($this->etAlUseLast == true && count($names) + 2 >= $countNames) { $return = str_replace(Container::getLocale()->getTerms('et-al'), ' … ' . end($names), $return); } // no formatting while sorting if (Container::getContext()->in('sort') == true) { return $return; } // no formatting while author-only is set for actual cite if (Container::getCitationItem() !== false && Container::getCitationItem()->get('author-only') == 1) { return $this->affix->render($return, true); } $return = $this->formatting->render($return); return $this->affix->render($return, true); }
/** * Apply additional formatting and remove duplicated spaces and dots. * * @param $data * @return string */ private function format($data) { $data = preg_replace('/[ ][ ]+/', ' ', $data); $data = preg_replace('/[\\.][\\.]+/', '.', $data); $data = preg_replace('/( ,)/', ',', $data); $data = preg_replace('/[;|,]([;|,])/', '$1', $data); $data = preg_replace('/\\.(<\\/[a-z]+>)\\./', '.$1', $data); $data = $this->expand->render($data); if (Container::getCitationItem() !== false) { // suppress affixes if author-only is set and there is only one cite in the actual citation $ids = Container::getRendered()->getIdByValue($data); Container::getCitationItem()->moveTo($ids['id'], $ids['citationId']); if (Container::getCitationItem()->get('author-only') == 1) { return $data; } } $data = $this->affix->render($data, true); return $this->formatting->render($data); }
/** * Sort the bibliography entries. */ private function bibliography() { $order = $this->multiSort($this->generateBibliographySort()); Container::getData()->sort($order); if (Container::getCitationItem() !== false) { Container::getCitationItem()->sort($order); } }
/** * Render the names. * * @param string|array $data * @return string */ public function render($data) { $returns = array(); $compare = array(); $lastSubstitute = Container::getContext()->getSubstitute()->getVariable(); foreach ($this->variables as $variable) { // don't render if variable is already used as substitute value if ($lastSubstitute === $variable) { return ''; } $names = Container::getData()->getVariable($variable); $content = $this->name->render($names); // et-al if (isset($this->etAl) == true && Container::getContext()->getValue('etAlMin', Container::getContext()->getName()) !== null && Container::getContext()->getValue('etAlMin', Container::getContext()->getName()) <= count($names)) { $content = $this->etAl->render($content); } if ($content !== '') { $compare[$variable] = $content; } // use substitute if ($content == '' && isset($this->substitute) == true) { $content = $this->substitute->render(''); if (Container::getContext()->getSubstitute()->getVariable() !== '') { $variable = Container::getContext()->getSubstitute()->getVariable(); } } if ($content !== '' && isset($this->label) == true && Container::getContext()->in('sort') == false) { $this->label->setVariable($variable); if ($this->labelBeforeName == false) { $content .= $this->label->render($content); } else { $content = $this->label->render($content) . $content; } } if ($content !== '') { $returns[] = $content; } } // The one exception: when the selection consists of "editor" and "translator", and when the contents // of these two name variables is identical, then the contents of only one name variable is rendered. if (in_array('editor', $this->variables) == true && in_array('translator', $this->variables) == true && isset($compare['editor']) == true && $compare['editor'] == $compare['translator']) { $editorTrans = $compare['translator']; if (isset($this->label) == true) { $plural = 'singular'; if (count(Container::getData()->getVariable('editor')) > 1 || count(Container::getData()->getVariable('translator')) > 1) { $plural = 'multiple'; } $this->label->setVariable('editortranslator')->setPlural($plural); $editorTrans .= $this->label->render(''); } $returns = array($editorTrans); } $return = implode($this->delimiter, $returns); // no formatting while author-only is set for actual cite if (Container::getCitationItem() == false || Container::getCitationItem()->get('author-only') == 0 || Container::getCitationItem()->get('author-only') === null) { $return = $this->formatting->render($return); } $return = $this->display->render($return); return $this->affix->render($return); }
/** * Renders the variable. * * @param string $data * @return string */ public function render($data) { if ($this->form !== '') { $return = Container::getData()->getVariable($this->name . '-' . $this->form); if ($return !== null) { return $return; } if (is_object(Container::getAbbreviation()) == true) { $return = Container::getAbbreviation()->get($this->name, $this->form); } if ($return !== null) { return $return; } } // special cases switch ($this->name) { case 'title-short': $return = Container::getData()->getVariable('shortTitle'); if ($return !== null) { return $return; } break; case 'title': if ($this->form == 'short') { $return = Container::getData()->getVariable('shortTitle'); if ($return !== null) { return $return; } } break; case 'citation-label': $return = Container::getData()->getVariable($this->name); if ($return !== null) { return $return; } // first 4 letters from the first two author family names and last to year digits $authors = Container::getData()->getVariable('author'); $format = new Format(); if (isset($authors[0]['family']) == true && $format->format('issued') == true) { $year = $format->getData(); if (isset($year[0]['year']) == true) { switch (count($authors)) { case 1: $author = substr($authors[0]['family'], 0, 4); break; case 2: $author = substr($authors[0]['family'], 0, 2) . substr($authors[1]['family'], 0, 2); break; default: $author = ''; for ($i = 0; $i < 4; $i++) { if (preg_match('/[A-Z]/', $authors[$i]['family'], $match) == 1) { $author .= $match[0]; } } break; } $length = strlen($year[0]['year']); return $author . substr($year[0]['year'], $length - 2, $length); } } break; case 'page': $format = Container::getContext()->getValue('pageRangeFormat'); if (is_object($format) == true) { return $format->format(Container::getData()->getVariable($this->name)); } break; case 'first-reference-note-number': // number of a preceding note containing the first reference to the item if (Container::getCitationItem()->get('noteIndex') !== null || Container::getCitationItem()->get('index') !== null) { $first = Container::getRendered()->getPositionOfFirstId(Container::getActualId()); if ($first !== null && $first < Container::getRendered()->getLength()) { return $first; } } break; } $return = Container::getData()->getVariable($this->name); if ($return !== null) { return $return; } // retrieve variables form citations if (Container::getContext()->getName() == 'citation' && Container::getCitationItem() !== false) { $return = Container::getCitationItem()->get($this->name); if ($return !== null) { return $return; } } return ''; }
/** * Renders the label. * * @param string|array $data * @return string * @throws \ErrorException If the variable parameter is not set */ public function render($data) { if (isset($this->variable) == false) { throw new \ErrorException('variable is not set!'); } $content = Container::getData()->getVariable($this->variable); $variable = $this->variable; if ($this->variable == 'locator') { // Must be accompanied in the input data by a label indicating the locator type, which determines which // term is rendered by cs:label when the "locator" variable is selected if (is_object(Container::getCitationItem()) == true && Container::getCitationItem()->get('label') !== null) { $variable = Container::getCitationItem()->get('label'); $content = Container::getCitationItem()->get('locator'); } else { return ''; } } // The term is only rendered if the selected variable is non-empty. if ($content == '' && $variable !== 'editortranslator') { return ''; } $plural = 'single'; switch ($this->plural) { case 'contextual': if (is_array($content) == true) { if (count($content) > 1) { $plural = 'multiple'; } } elseif (($this->variable == 'number-of-pages' || $this->variable == 'number-of-volumes') && preg_match_all('/([0-9])/', $content) > 1) { $plural = 'multiple'; } elseif (preg_match('/^[0-9]+$/', $content, $match) == 0) { $plural = 'multiple'; } break; case 'always': case 'multiple': $plural = 'multiple'; break; } $form = ''; if ($this->form !== 'long') { $form = $this->form; } $return = Container::getLocale()->getTerms($variable, $form, $plural); if ($return !== '') { $return = $this->formatting->render($return); $return = $this->textCase->render($return); $return = $this->stripPeriods->render($return); $return = $this->affix->render($return, true); } return $return; }