/** * Get a new WCSection object based on HTML arguments. * @param array $args = "citeStyle" or "type" (or equivalent foreign words) * @param WCStyle $defaultStyle * @param WCCitationTypeEnum $defaultType * @return WCSection */ public static function getSection( array $args, $defaultStyle, $defaultType ) { foreach( $args as $attrib => $value ) { if ( in_array( $attrib, self::$citeStyleAttributeWords ) ) { $styleClassName = WCArgumentReader::matchStyleClassName( $value ); } elseif ( in_array( $attrib, self::$typeAttributeWords ) ) { $citationTypeID = WCCitationTypeEnum::match( $value ); if ( isset( $citationTypeID ) ) { $citationType = new WCCitationTypeEnum( $citationTypeID ); } } elseif ( $args[ 'style' ] ) { $this->styleHTML = ' style="' . $args[ 'style' ] . '"'; } elseif ( $args[ 'id' ] ) { $this->styleHTML = ' id="' . $args[ 'id' ] . '"'; } } if ( isset( $styleClassName ) ) { # See if a specific style object has already been defined, and if so, use it. $styleObject = WCArticle::getStyle( $styleClassName ); } else { # Use default citation style. $styleObject = $defaultStyle; } if ( isset( $citationType ) ) { return new WCSection( $styleObject, $citationType ); } else { return new WCSection( $styleObject, $defaultType ); } }
/** * 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; }
/** * Read and parse arguments from a WCArgumentReader object. * @param WCArgumentReader $wcArgumentReader = the argument reader * @global $wikiCitationValidateArguments */ public function readArguments( WCArgumentReader $argumentReader ) { $this->citationType = $argumentReader->getCitationType(); $this->citationLength = $argumentReader->getCitationLength(); /** * Recognize and process the parameters and names. */ foreach( $argumentReader->parameters as $var => $value ) { # See if scope name only is present, in which case the parameter is assumed to be the title. # This allows the user to enter "journal=Nature" or "work=Origin of Species", etc. $scope = WCScopeEnum::match( $var, WCScopeEnum::$magicWordArray, WCScopeEnum::$flipMagicWordKeys, 'WCScopeEnum' ); if ( $scope ) { $property = WCPropertyEnum::$title; $this->reference->setProperty( $scope, $property, new WCTitle( $value ) ); continue; } # Match the parameter scope. list( $scope, $parameterText ) = WCScopeEnum::matchPrefix( $var, WCScopeEnum::$magicWordArray, WCScopeEnum::$flipMagicWordKeys, 'WCScopeEnum' ); if ( !$scope ) { $scope = WCScopeEnum::$work; # Set the default } # See if a type name is present, in which case the parameter is assumed to be the title. # This allows the wiki editor to enter "book=Origin of Species", "pamphlet=Common Sense," etc., or even "container-encyclopedia=Encyclopedia Brittanica." # If either the title or type have already been set, then neither will be set again. # Thus, it will be possible to use "book" as a locator. $type = WCSourceTypeEnum::match( $parameterText, WCSourceTypeEnum::$magicWordArray, WCSourceTypeEnum::$flipMagicWordKeys, 'WCTypeEnum' ); if ( $type ) { $propertyEnumTitle = WCPropertyEnum::$title; $propertyEnumType = WCPropertyEnum::$type; $title = $this->reference->getProperty( $scope, $propertyEnumTitle ); $type = $this->reference->getProperty( $scope, $propertyEnumType ); if ( is_null( $this->reference->getProperty( $scope, $propertyEnumTitle ) ) && is_null( $this->getProperty( $scope, $propertyEnumType ) ) ) { $this->reference->setProperty( $scope, $propertyEnumTitle, new WCTitle( $value ) ); $this->reference->setProperty( $scope, $propertyEnumType, new WCTypeData( $type ) ); } continue; } global $wikiCitationValidateArguments; # Match properties. $property = WCPropertyEnum::match( $parameterText, WCPropertyEnum::$magicWordArray, WCPropertyEnum::$flipMagicWordKeys, 'WCPropertyEnum' ); if ( $property ) { $attributeKey = $property->getAttribute()->key; $attributeClass = WCAttributeEnum::$attribute[ $attributeKey ]; if ( $attributeKey == WCAttributeEnum::locator ) { # Locators disregard the scope. $locator = $this->getLocator( $property ); if ( $wikiCitationValidateArguments && isset( $locator ) ) { throw new WCException( 'wc-parameter_defined_twice', $property ); } else { $this->setLocator( $property, new WCLocator( $value ) ); } } else { $prop = $this->reference->getProperty( $scope, $property ); if ( $wikiCitationValidateArguments && isset( $prop ) ) { throw new WCException( 'wc-parameter_defined_twice', $property ); } else { $this->reference->setProperty( $scope, $property, new $attributeClass( $value ) ); } } # Set attribute continue; } # Match names. $match = False; list( $nameEnum, $namePartText ) = WCNameTypeEnum::matchPrefix( $parameterText, WCNameTypeEnum::$magicWordArray, WCNameTypeEnum::$flipMagicWordKeys, 'WCNameTypeEnum' ); if ( $namePartText ) { list( $namePartEnum, $nameNum ) = WCNamePartEnum::matchPartAndNumber( $namePartText, WCNamePartEnum::$magicWordArray, WCNamePartEnum::$flipMagicWordKeys, 'WCNamePartEnum' ); if ( $namePartEnum ) { if ( !$nameEnum ) { $nameEnum = new WCNameTypeEnum(); } $match = True; } elseif ( $nameEnum ) { $namePartEnum = new WCNamePartEnum(); $match = True; } } elseif ( $nameEnum ) { $namePartEnum = new WCNamePartEnum(); $nameNum = 1; $match = True; } if ( $match ) { if ( is_null( $this->reference->getNames( $scope, $nameEnum ) ) ) { $this->reference->setNames( $scope, $nameEnum, new WCNames() ); } $theNames = $this->reference->getNames( $scope, $nameEnum ); $part = $theNames->getNamePart( $nameNum, $namePartEnum ); if ( $wikiCitationValidateArguments && isset( $part ) ) { throw new WCException( 'wc-parameter_defined_twice', $nameEnum . $nameNum. '-' . $namePartEnum ); } else { $theNames->setNamePart( $nameNum, $namePartEnum, $value ); } continue; } # Argument has no matches. if ( $wikiCitationValidateArguments ) { throw new WCException( 'wc-parameter-unknown', $parameterText ); } } }
/** * Static initializer. */ public static function init() { global $wgWCCitationStyles; $citationStyleList = array_keys( $wgWCCitationStyles ); self::$styleMagicWords = new MagicWordArray( $citationStyleList ); }