/** * Renders the citation and stores the result in $this->citation. * @param WCStyle $style * @return array = the rendered citation and sorting parts. */ public function render() { # Build the citation if ( $this->citationLength->key == WCCitationLengthEnum::short ) { switch ( $this->citationType->key ) { case WCCitationTypeEnum::note: list( $citation, $sortingParts ) = $this->style->renderShortNoteCitation( $this ); break; case WCCitationTypeEnum::inline: list( $citation, $sortingParts ) = $this->style->renderShortInlineCitation( $this ); break; case WCCitationTypeEnum::authorDate: list( $citation, $sortingParts ) = $this->style->renderShortAuthorDateCitation( $this ); } } else { switch ( $this->citationType->key ) { case WCCitationTypeEnum::note: list( $citation, $sortingParts ) = $this->style->renderLongNoteCitation( $this ); break; case WCCitationTypeEnum::biblio: list( $citation, $sortingParts ) = $this->style->renderLongBiblioCitation( $this ); break; case WCCitationTypeEnum::authorDate: list( $citation, $sortingParts ) = $this->style->renderLongAuthorDateCitation( $this ); break; default: # case WCCitationTypeEnum::inline: list( $citation, $sortingParts ) = $this->style->renderLongInlineCitation( $this ); } } # Wrap the entire citation in an HTML span element with classes. $classHTML = WCStyle::citationHTML . ' ' . $this->style->styleHTML . ' ' . $this->reference->getWorkType() . ' ' . $this->citationType . ' ' . $this->citationLength; return array( WCStyle::wrapHTMLSpan( $citation, $classHTML ), $sortingParts ); }
/** * Add a reference to the cache, checking for prior duplicates. * @param integer $key = a unique key * @param WCReference $reference * @return integer = number of citations from last use of this reference. */ public function addUniqueReference( $key, WCReference $reference ) { $referenceKey = array( $key ); $hash = $reference->getHash(); if ( empty( $hash ) ) { # If empty hash, search all prior hashed references. foreach( $this->hashTable as &$hashArray ) { foreach( $hashArray as &$testKey ) { $testReference = $this->references[ $testKey ]; # If $reference can be considered a short form of prior reference: if ( $reference->shortFormMatches( $testReference ) ) { $lastKey = end( $testReference ->keys ); $testReference->keys += $referenceKey; # Forget this reference: $this->references[ $key ] = $testReference; return $key - $lastKey; } # If prior reference can be considered a short form of $reference: elseif ( $testReference->shortFormMatches( $reference ) ) { $lastKey = end( $testReference ->keys ); $reference->keys = $testReference->keys + $referenceKey; # Forget the earlier reference. unset( $this->referenceList [ $testKey ] ); $this->referenceList[ $key ] = $reference; $this->references[ $testKey ] = $reference; $this->references[ $key ] = $reference; $testKey = $key; return $key - $lastKey; } } } } # Handle hash table collisions. elseif ( isset( $this->hashTable[ $hash ] ) ) { # Search collision entries. foreach( $this->hashTable[ $hash ] as &$testKey ) { $testReference = $this->references[ $testKey ]; # If $reference can be considered a short form of prior reference: if ( $reference->shortFormMatches( $testReference ) ) { $lastKey = end( $testReference ->keys ); $testReference->keys += $referenceKey; # Forget this reference: $this->references[ $key ] = $testReference; return $key - $lastKey; } # if prior reference can be considered a short form of $reference: elseif ( $testReference->shortFormMatches( $reference ) ) { $lastKey = end( $testReference ->keys ); $reference->keys = $testReference->keys + $referenceKey; # Forget the earlier reference. unset( $this->referenceList [ $testKey ] ); $this->referenceList[ $key ] = $reference; $this->references[ $testKey ] = $reference; $this->references[ $key ] = $reference; $testKey = $key; return $key - $lastKey; } } # If no collision yet, search prior empty hashes. foreach( $this->hashTable[ '' ] as $id => &$testKey ) { $testReference = $this->references[ $testKey ]; if ( $testReference->shortFormMatches( $reference ) ) { $lastKey = end( $testReference ->keys ); $reference->keys = $testReference->keys + $referenceKey; # Forget the earlier reference. unset( $this->referenceList [ $testKey ] ); $this->referenceList [ $key ] = $reference; $this->references[ $testKey ] = $reference; $this->references[ $key ] = $reference; # Correct hash table unset( $this->hashTable[ '' ][ $id ] ); $this->hashTable[ $hash ][] = $key; return $key - $lastKey; } } } # If no hash table match: $reference->keys = $referenceKey; $this->referenceList[ $key ] = $reference; $this->references[ $key ] = $reference; $this->hashTable[ $hash ][] = $key; return 0; }
/** * Creates a citation object for each citation parser function. * * Reads flags and parameters from WCArgumentReader object, * then creates an appropriate child of class WCStyle based on the * first parameter after the colon, then returns the citation as text. * @remark Note that this $parser is guaranteed to be the same parser that * initialized the object. * * @param WCArgumentReader $argumentReader * @return string Unique marker for citation. */ public function parseCitation( WCArgumentReader $argumentReader ) { # Use the explicit citation style if defined, or use last style. $styleClassName = $argumentReader->getStyleClassName(); if ( $styleClassName ) { # Store citation style in a running database of style object singlets. $this->currentDefaultStyle = self::getStyle($styleClassName); } # A citation function, with no data, may exist merely to define the citation style. if ( $argumentReader->isEmpty() ) { ++$this->citationCount; return ''; } $reference = new WCReference(); $citation = new WCCitation( $reference ); $citation->readArguments( $argumentReader ); $reference->finalize(); # Store reference in database that checks for uniqueness. # $citation->reference will be reloaded later, after all citations are read. $citation->distance = $this->referenceStore->addUniqueReference( $this->citationCount, $reference ); # Is this a citation explicitly inserted in bibliography tags? # If so, then we will not be leaving behind a marker. if ( $this->bibliographyLevel > 0 ) { ++$this->citationCount; return ''; # Only a single marker is left behind per bibliography. } # Determine whether the citation is in a note, or inline. $section = $this->sectionStack[ $this->sectionStackPointer ]; if ( $this->noteLevel > 0 ) { $section->addNoteCite( $this->citationCount, $citation ); } else { $section->addInlineCite( $this->citationCount, $citation ); } # Store citation and leave behind a random marker for later replacement by the citation: $this->citations[ $this->citationCount++ ] = $citation; return $citation->marker; }
/** * Determine if $this can be considered a short form of the argument. * If so, then determine the number of matches. * * @param WCNames $names * @return integer|boolean */ public function shortFormMatches( WCReference $reference ) { $matches = 0; # Compare names. foreach( $this->names as $scopeKey => $nameTypes ) { foreach( $nameTypes as $nameTypeKey => $thisNames ) { $otherNames = $reference->getNames( new WCScopeEnum( $scopeKey ), new WCNameTypeEnum( $nameTypeKey ) ); if ( isset( $otherNames ) ) { $subMatches = $thisNames->shortFormMatches( $otherNames ); if ( $subMatches === False ) { return False; } else { $matches += $subMatches; } } } } # Compare properties. foreach( $this->properties as $scopeKey => $propertyTypes ) { foreach( $propertyTypes as $propertyTypeKey => $thisProperty ) { $otherProperty = $reference->getProperty( new WCScopeEnum( $scopeKey ), new WCPropertyEnum( $propertyTypeKey ) ); if ( isset( $otherProperty ) ) { $subMatches = $thisProperty->shortFormMatches( $otherProperty ); if ( $subMatches === False ) { return False; } else { $matches += $subMatches; } } } } return $matches; }