PageRenderTime 26ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/extensions/WikiCitation/includes/WCCitation.php

https://github.com/ChuguluGames/mediawiki-svn
PHP | 326 lines | 169 code | 50 blank | 107 comment | 32 complexity | 72e67bf90c99703731bf8e736ad00f7c MD5 | raw file
  1. <?php
  2. /**
  3. * Part of WikiCitation extension for Mediawiki.
  4. *
  5. * @ingroup WikiCitation
  6. * @file
  7. */
  8. class WCCitationPosition extends WCEnum {
  9. const first = 0;
  10. const subsequent = 1;
  11. # const ibid = 2;
  12. # const ibidWithLocator = 3;
  13. # const nearNote = 4;
  14. const __default = self::first;
  15. }
  16. /**
  17. * Class representing the finalized citation.
  18. *
  19. * This class reads and processes the data from a WCArgumentReader object,
  20. * and constructs the appropriate WCStyle child based on the referencing style
  21. * and citation type. Ultimately, a call to WCCitation::composeCitation()
  22. * will output the fully-formatted citation.
  23. */
  24. class WCCitation {
  25. /**
  26. * Associated WCReference object, representing the unique reference source.
  27. * For each WCReference instance, there may be many WCCitation instances.
  28. * @var WCReference
  29. */
  30. public $reference;
  31. /**
  32. * Position of the citation
  33. * (E.g., first, subsequent, etc.)
  34. * @var WCCitationPosition
  35. */
  36. public $citationPostion;
  37. /**
  38. * The citation system: notes and bibliography or author-date.
  39. * @var WCCitationSystem
  40. */
  41. public $citationSystem;
  42. /**
  43. * Marker for this citation, left behind temporarily in text, and later replaced.
  44. * @var unknown_type
  45. */
  46. public $marker;
  47. /**
  48. * The citation style.
  49. * @var WCStyle
  50. */
  51. public $style;
  52. /**
  53. * The citation type.
  54. * @var WCCitationType
  55. */
  56. public $citationType;
  57. /**
  58. * The citation length.
  59. * @var WCCitationLength
  60. */
  61. public $citationLength;
  62. /**
  63. * Distance in number of citations from last citation to this reference
  64. * @var integer
  65. */
  66. public $distance;
  67. /**
  68. * Locators for this citation.
  69. * @var array of WCLocator objects
  70. */
  71. protected $locators = array();
  72. # output of the parser
  73. protected $citationText;
  74. /**
  75. * Constructor.
  76. */
  77. public function __construct( WCReference $reference ) {
  78. $this->reference = $reference;
  79. $this->citationPosition = new WCCitationPosition();
  80. # Construct a random marker for storage and later replacement by the citation:
  81. $this->marker = 'wC-' . mt_rand();
  82. }
  83. /**
  84. * Read and parse arguments from a WCArgumentReader object.
  85. * @param WCArgumentReader $wcArgumentReader = the argument reader
  86. * @global $wikiCitationValidateArguments
  87. */
  88. public function readArguments( WCArgumentReader $argumentReader ) {
  89. $this->citationType = $argumentReader->getCitationType();
  90. $this->citationLength = $argumentReader->getCitationLength();
  91. /**
  92. * Recognize and process the parameters and names.
  93. */
  94. foreach( $argumentReader->parameters as $var => $value ) {
  95. # See if scope name only is present, in which case the parameter is assumed to be the title.
  96. # This allows the user to enter "journal=Nature" or "work=Origin of Species", etc.
  97. $scope = WCScopeEnum::match( $var, WCScopeEnum::$magicWordArray,
  98. WCScopeEnum::$flipMagicWordKeys, 'WCScopeEnum' );
  99. if ( $scope ) {
  100. $property = WCPropertyEnum::$title;
  101. $this->reference->setProperty( $scope, $property, new WCTitle( $value ) );
  102. continue;
  103. }
  104. # Match the parameter scope.
  105. list( $scope, $parameterText ) = WCScopeEnum::matchPrefix( $var, WCScopeEnum::$magicWordArray,
  106. WCScopeEnum::$flipMagicWordKeys, 'WCScopeEnum' );
  107. if ( !$scope ) {
  108. $scope = WCScopeEnum::$work; # Set the default
  109. }
  110. # See if a type name is present, in which case the parameter is assumed to be the title.
  111. # This allows the wiki editor to enter "book=Origin of Species", "pamphlet=Common Sense," etc., or even "container-encyclopedia=Encyclopedia Brittanica."
  112. # If either the title or type have already been set, then neither will be set again.
  113. # Thus, it will be possible to use "book" as a locator.
  114. $type = WCSourceTypeEnum::match( $parameterText, WCSourceTypeEnum::$magicWordArray,
  115. WCSourceTypeEnum::$flipMagicWordKeys, 'WCTypeEnum' );
  116. if ( $type ) {
  117. $propertyEnumTitle = WCPropertyEnum::$title;
  118. $propertyEnumType = WCPropertyEnum::$type;
  119. $title = $this->reference->getProperty( $scope, $propertyEnumTitle );
  120. $type = $this->reference->getProperty( $scope, $propertyEnumType );
  121. if ( is_null( $this->reference->getProperty( $scope, $propertyEnumTitle ) ) && is_null( $this->getProperty( $scope, $propertyEnumType ) ) ) {
  122. $this->reference->setProperty( $scope, $propertyEnumTitle, new WCTitle( $value ) );
  123. $this->reference->setProperty( $scope, $propertyEnumType, new WCTypeData( $type ) );
  124. }
  125. continue;
  126. }
  127. global $wikiCitationValidateArguments;
  128. # Match properties.
  129. $property = WCPropertyEnum::match( $parameterText, WCPropertyEnum::$magicWordArray,
  130. WCPropertyEnum::$flipMagicWordKeys, 'WCPropertyEnum' );
  131. if ( $property ) {
  132. $attributeKey = $property->getAttribute()->key;
  133. $attributeClass = WCAttributeEnum::$attribute[ $attributeKey ];
  134. if ( $attributeKey == WCAttributeEnum::locator ) {
  135. # Locators disregard the scope.
  136. $locator = $this->getLocator( $property );
  137. if ( $wikiCitationValidateArguments && isset( $locator ) ) {
  138. throw new WCException( 'wc-parameter_defined_twice', $property );
  139. } else {
  140. $this->setLocator( $property, new WCLocator( $value ) );
  141. }
  142. } else {
  143. $prop = $this->reference->getProperty( $scope, $property );
  144. if ( $wikiCitationValidateArguments && isset( $prop ) ) {
  145. throw new WCException( 'wc-parameter_defined_twice', $property );
  146. } else {
  147. $this->reference->setProperty( $scope, $property, new $attributeClass( $value ) );
  148. }
  149. }
  150. # Set attribute
  151. continue;
  152. }
  153. # Match names.
  154. $match = False;
  155. list( $nameEnum, $namePartText ) = WCNameTypeEnum::matchPrefix( $parameterText,
  156. WCNameTypeEnum::$magicWordArray, WCNameTypeEnum::$flipMagicWordKeys, 'WCNameTypeEnum' );
  157. if ( $namePartText ) {
  158. list( $namePartEnum, $nameNum ) = WCNamePartEnum::matchPartAndNumber(
  159. $namePartText, WCNamePartEnum::$magicWordArray, WCNamePartEnum::$flipMagicWordKeys, 'WCNamePartEnum' );
  160. if ( $namePartEnum ) {
  161. if ( !$nameEnum ) {
  162. $nameEnum = new WCNameTypeEnum();
  163. }
  164. $match = True;
  165. } elseif ( $nameEnum ) {
  166. $namePartEnum = new WCNamePartEnum();
  167. $match = True;
  168. }
  169. } elseif ( $nameEnum ) {
  170. $namePartEnum = new WCNamePartEnum();
  171. $nameNum = 1;
  172. $match = True;
  173. }
  174. if ( $match ) {
  175. if ( is_null( $this->reference->getNames( $scope, $nameEnum ) ) ) {
  176. $this->reference->setNames( $scope, $nameEnum, new WCNames() );
  177. }
  178. $theNames = $this->reference->getNames( $scope, $nameEnum );
  179. $part = $theNames->getNamePart( $nameNum, $namePartEnum );
  180. if ( $wikiCitationValidateArguments && isset( $part ) ) {
  181. throw new WCException( 'wc-parameter_defined_twice', $nameEnum . $nameNum. '-' . $namePartEnum );
  182. } else {
  183. $theNames->setNamePart( $nameNum, $namePartEnum, $value );
  184. }
  185. continue;
  186. }
  187. # Argument has no matches.
  188. if ( $wikiCitationValidateArguments ) {
  189. throw new WCException( 'wc-parameter-unknown', $parameterText );
  190. }
  191. }
  192. }
  193. /**
  194. * Renders the citation and stores the result in $this->citation.
  195. * @param WCStyle $style
  196. * @return array = the rendered citation and sorting parts.
  197. */
  198. public function render() {
  199. # Build the citation
  200. if ( $this->citationLength->key == WCCitationLengthEnum::short ) {
  201. switch ( $this->citationType->key ) {
  202. case WCCitationTypeEnum::note:
  203. list( $citation, $sortingParts ) = $this->style->renderShortNoteCitation( $this );
  204. break;
  205. case WCCitationTypeEnum::inline:
  206. list( $citation, $sortingParts ) = $this->style->renderShortInlineCitation( $this );
  207. break;
  208. case WCCitationTypeEnum::authorDate:
  209. list( $citation, $sortingParts ) = $this->style->renderShortAuthorDateCitation( $this );
  210. }
  211. } else {
  212. switch ( $this->citationType->key ) {
  213. case WCCitationTypeEnum::note:
  214. list( $citation, $sortingParts ) = $this->style->renderLongNoteCitation( $this );
  215. break;
  216. case WCCitationTypeEnum::biblio:
  217. list( $citation, $sortingParts ) = $this->style->renderLongBiblioCitation( $this );
  218. break;
  219. case WCCitationTypeEnum::authorDate:
  220. list( $citation, $sortingParts ) = $this->style->renderLongAuthorDateCitation( $this );
  221. break;
  222. default: # case WCCitationTypeEnum::inline:
  223. list( $citation, $sortingParts ) = $this->style->renderLongInlineCitation( $this );
  224. }
  225. }
  226. # Wrap the entire citation in an HTML span element with classes.
  227. $classHTML = WCStyle::citationHTML . ' ' .
  228. $this->style->styleHTML . ' ' .
  229. $this->reference->getWorkType() . ' ' .
  230. $this->citationType . ' ' .
  231. $this->citationLength;
  232. return array( WCStyle::wrapHTMLSpan( $citation, $classHTML ), $sortingParts );
  233. }
  234. /**
  235. * The string representation of this object.
  236. * @return string citation as wikitext.
  237. */
  238. final public function __toString() {
  239. return (string) $this->citationText;
  240. }
  241. /**
  242. * Infer the intended locator value string based on potentially incomplete
  243. * info. The arguments will be revised to reflect the new types.
  244. * @param WCPropertyEnum $propertyType
  245. * @return WCLocator
  246. */
  247. public function inferLocator( WCPropertyEnum &$locatorType ) {
  248. foreach( $locatorType as $testLocatorTypeKey ) {
  249. if ( isset( $this->locators[ $testLocatorTypeKey ] ) ) {
  250. $locatorType->key = $testLocatorTypeKey;
  251. return $this->locators[ $testLocatorTypeKey ];
  252. }
  253. }
  254. return Null;
  255. }
  256. /**
  257. * Getter for a locator.
  258. * @param WCPropertyEnum $type
  259. * @return WCLocator
  260. */
  261. public function getLocator( WCPropertyEnum $type ) {
  262. if ( isset( $this->locators[ $type->key ] ) ) {
  263. return $this->locators[ $type->key ];
  264. } else {
  265. return Null;
  266. }
  267. }
  268. /**
  269. * Setter for a locator.
  270. * @param WCPropertyEnum $type
  271. * @param WCLocator $locator
  272. */
  273. public function setLocator( WCPropertyEnum $type, WCLocator $locator ) {
  274. $this->locators[ $type->key ] = $locator;
  275. }
  276. }