/extensions/WikiCitation/includes/data/WCName.php

https://github.com/ChuguluGames/mediawiki-svn · PHP · 385 lines · 276 code · 41 blank · 68 comment · 88 complexity · f4d94653d300b8472b54af22c2f2fe40 MD5 · raw file

  1. <?php
  2. /**
  3. * Part of WikiCitation extension for Mediawiki.
  4. *
  5. * @ingroup WikiCitation
  6. * @file
  7. */
  8. /**
  9. * parts structure WCName.
  10. * Contains all information needed to be known about one name,
  11. * such as an author, editor, translator, composer, etc.
  12. */
  13. class WCName extends WCData implements Iterator {
  14. # The numerical order of the name.
  15. public $nameNumber;
  16. /**
  17. * An array of name parts keyed to WCNamePartEnum keys
  18. */
  19. protected $parts = array();
  20. /**
  21. * Constructor.
  22. * @param WCScopeEnum $scope = the scope (i.e., work, container, series, etc.)
  23. * @param WCNameTypeEnum $nameType = the type of name.
  24. * @param integer $nameNumber = the numerical order of the name.
  25. */
  26. public function __construct( $nameNumber ) {
  27. $this->nameNumber = $nameNumber;
  28. }
  29. /**
  30. * Implements Iterator interface method.
  31. * @return type
  32. */
  33. public function key() {
  34. return key( $this->parts );
  35. }
  36. /**
  37. * Implements Iterator interface method.
  38. * @return type
  39. */
  40. public function current() {
  41. return current( $this->parts );
  42. }
  43. /**
  44. * Implements Iterator interface method.
  45. * @return type
  46. */
  47. public function next() {
  48. return next( $this->parts );
  49. }
  50. /**
  51. * Implements Iterator interface method.
  52. * @return type
  53. */
  54. public function valid() {
  55. return (bool) current( $this->parts );
  56. }
  57. /**
  58. * Implements Iterator interface method.
  59. * @return type
  60. */
  61. public function rewind() {
  62. return reset( $this->parts );
  63. }
  64. public function getPart( $partKey ) {
  65. if ( isset( $this->parts[ $partKey ] ) ) {
  66. return $this->parts[ $partKey ];
  67. } else {
  68. return Null;
  69. }
  70. }
  71. public function setPart( WCNamePartEnum $part, $value ) {
  72. $this->parts[ $part->key ] = $value;
  73. }
  74. /**
  75. * Determine if $this can be considered a short form of argument.
  76. * If so, then determine the number of matches.
  77. *
  78. * @param WCName $name
  79. * @return integer|boolean
  80. */
  81. public function shortFormMatches( WCData $name ) {
  82. $matches = 0;
  83. foreach( $this->parts as $partKey => $part ) {
  84. $otherPart = $name->getPart( $partKey );
  85. if ( isset( $otherPart ) && strnatcasecmp( $part, $otherPart ) === 0 ) {
  86. ++$matches;
  87. } else {
  88. return False;
  89. }
  90. }
  91. return $matches;
  92. }
  93. /**
  94. * Composes a single name based on name parts and flags
  95. *
  96. * @param boolean $namesort = whether the surname appears first
  97. * @return string = composed name
  98. */
  99. public function render(
  100. WCStyle $style,
  101. WCCitationLengthEnum $citationLength,
  102. $endSeparator = '',
  103. $namesort = False ) {
  104. $surname = isset( $this->parts[ WCNamePartEnum::surname ] ) ?
  105. $this->parts[ WCNamePartEnum::surname ] : Null;
  106. $given = isset( $this->parts[ WCNamePartEnum::given ] ) ?
  107. $this->transformGivenNames( $this->parts[ WCNamePartEnum::given ] ) : Null;
  108. $link = isset( $this->parts[ WCNamePartEnum::nameLink ] ) ?
  109. $this->parts[ WCNamePartEnum::nameLink ] : Null;
  110. $dp = isset( $this->parts[ WCNamePartEnum::droppingParticle ] ) ?
  111. $this->parts[ WCNamePartEnum::droppingParticle ] : Null;
  112. $dpSpace = $ndpSpace = $suffixSpace = '';
  113. if ( $dp ) {
  114. # if the dropping particle ends in punctuation, there is no space between it and the surname or dropping particle.
  115. if ( preg_match( '/\p{P}$/u', $dp, $matches ) ) {
  116. $dpSpace = '';
  117. } else {
  118. $dpSpace = $style->nameWhitespace;
  119. }
  120. }
  121. $ndp = isset( $this->parts[ WCNamePartEnum::nonDroppingParticle ] ) ?
  122. $this->parts[ WCNamePartEnum::nonDroppingParticle ] : Null;
  123. if ( $ndp ) {
  124. # if the non-dropping particle ends in punctuation, there is no space between it and the surname.
  125. if ( preg_match( '/\p{P}$/u', $ndp, $matches ) ) {
  126. $ndpSpace = '';
  127. } else {
  128. $ndpSpace = $style->nameWhitespace;
  129. }
  130. }
  131. $suffix = isset( $this->parts[ WCNamePartEnum::suffix ] ) ?
  132. $this->parts[ WCNamePartEnum::suffix ] : Null;
  133. if ( $suffix ) {
  134. $suffixSpace = $style->nameSuffixDelimiter;
  135. }
  136. $literal = isset( $this->parts[ WCNamePartEnum::literal ] ) ?
  137. $this->parts[ WCNamePartEnum::literal ] : Null;
  138. # literal/organizational name
  139. if ( $literal ) {
  140. # Trim redundant separator characters
  141. $chrL = mb_substr( $literal, -1, 1 );
  142. $chrR = mb_substr( $endSeparator, 0, 1 );
  143. if ( $chrL == $chrR ) {
  144. $endSeparator = ltrim( $endSeparator, $chrR );
  145. }
  146. return WCStyle::makeWikiLink( $link, $literal, WCStyle::nameHTML ) . $endSeparator;
  147. };
  148. $pre = $post = '';
  149. # short form
  150. if ( $citationLength->key == WCCitationLengthEnum::short ) {
  151. if ( $surname ) {
  152. if ( $ndp ) {
  153. $surname = $ndp . $ndpSpace . $surname;
  154. }
  155. } else {
  156. if ( $link ) {
  157. $post = $link;
  158. } elseif ( $given ) {
  159. $post = $given;
  160. } else {
  161. $post = $dp . $dpSpace . $ndp . $ndpSpace . $style->missingName . $suffixSpace . $suffix;
  162. }
  163. }
  164. }
  165. # long form, name sort order
  166. elseif ( $namesort ) {
  167. if ( $surname ) {
  168. if ( !$style->demoteNonDroppingParticle && $ndp ) {
  169. $pre = $ndp . $ndpSpace;
  170. }
  171. if ( $given ) {
  172. $post = $style->sortOrderSurnameDelimiter . $given;
  173. if ( $dp ) {
  174. $post .= $style->nameWhitespace . $dp;
  175. }
  176. if ( $style->demoteNonDroppingParticle && $ndp ) {
  177. if ( $dp ) {
  178. $post .= $dpSpace;
  179. } else {
  180. $post .= $style->nameWhitespace;
  181. }
  182. $post .= $ndp;
  183. }
  184. } else {
  185. if ( $dp ) {
  186. $post .= $style->sortOrderSurnameDelimiter . $dp;
  187. }
  188. if ( $style->demoteNonDroppingParticle && $ndp ) {
  189. if ( $dp ) {
  190. $post .= $dpSpace;
  191. } else {
  192. $post .= $style->nameWhitespace;
  193. }
  194. $post .= $ndp;
  195. }
  196. }
  197. if ( $suffix ) {
  198. $post .= $suffixSpace . $suffix;
  199. }
  200. } elseif ( $link ) {
  201. $post = $link;
  202. } elseif ( $given ) {
  203. if ( $dp || $ndp || $suffix ) {
  204. if ( !$style->demoteNonDroppingParticle && $ndp ) {
  205. $post = $ndp . $ndpSpace;
  206. }
  207. $post = $style->missingName . $style->sortOrderSurnameDelimiter . $given;
  208. if ( $dp ) {
  209. $post .= $style->nameWhitespace . $dp;
  210. }
  211. if ( $style->demoteNonDroppingParticle && $ndp ) {
  212. if ( $dp ) {
  213. $post .= $dpSpace;
  214. } else {
  215. $post .= $style->nameWhitespace;
  216. }
  217. $post .= $ndp;
  218. }
  219. if ( $suffix ) {
  220. $post .= $suffixSpace . $suffix;
  221. }
  222. } else {
  223. $post = $given;
  224. }
  225. } else {
  226. if ( !$style->demoteNonDroppingParticle && $ndp ) {
  227. $post = $ndp . $ndpSpace;
  228. } else {
  229. $post = '';
  230. }
  231. $post = $style->missingName . $style->sortOrderSurnameDelimiter . $style->missingName;
  232. if ( $dp ) {
  233. $post .= $style->nameWhitespace . $dp;
  234. }
  235. if ( $style->demoteNonDroppingParticle && $ndp ) {
  236. if ( $dp ) {
  237. $post .= $dpSpace;
  238. } else {
  239. $post .= $style->nameWhitespace;
  240. }
  241. $post .= $ndp;
  242. }
  243. if ( $suffix ) {
  244. $post .= $suffixSpace . $suffix;
  245. }
  246. }
  247. }
  248. # long form, non-name sort order
  249. else {
  250. if ( $surname ) {
  251. if ( $given ) {
  252. $pre = $given . $style->nameWhitespace;
  253. }
  254. $pre .= $dp . $dpSpace . $ndp . $ndpSpace;
  255. $post = $suffixSpace . $suffix;
  256. } elseif ( $link ) {
  257. $post = $link;
  258. } elseif ( $given ) {
  259. $post = $given . $style->nameWhitespace;
  260. if ( $dp || $ndp || $suffix ) {
  261. $post .= $dp . $dpSpace . $ndp . $ndpSpace . $style->missingName . $suffixSpace . $suffix;
  262. }
  263. } else {
  264. $post = $style->missingName . $style->nameWhitespace;
  265. if ( $dp ) {
  266. $post .= $dp . $dpSpace . $ndp . $ndpSpace . $style->missingName . $suffixSpace . $suffix;
  267. }
  268. }
  269. }
  270. $htmlClass = WCStyle::nameHTML;
  271. if ( $namesort ) {
  272. $surnameClass = WCStyle::surnameSortOrderHTML;
  273. } else {
  274. $surnameClass = WCStyle::surnameHTML;
  275. }
  276. # Trim redundant separator characters
  277. if ( $post ) {
  278. $chrL = mb_substr( $post, -1, 1 );
  279. $chrR = mb_substr( $endSeparator, 0, 1 );
  280. if ( $chrL == $chrR ) {
  281. $endSeparator = ltrim( $endSeparator, $chrR );
  282. }
  283. if ( $surname) {
  284. $nameText = $pre . WCStyle::wrapHTMLSpan( $surname, $surnameClass ) . $post;
  285. } else {
  286. $nameText = $pre . $post;
  287. }
  288. } elseif ( $surname) {
  289. $chrL = mb_substr( $surname, -1, 1 );
  290. $chrR = mb_substr( $endSeparator, 0, 1 );
  291. if ( $chrL == $chrR ) {
  292. $endSeparator = ltrim( $endSeparator, $chrR );
  293. }
  294. if ( $pre ) {
  295. $nameText = $pre . WCStyle::wrapHTMLSpan( $surname, $surnameClass );
  296. } else {
  297. $nameText = $surname;
  298. $htmlClass .= ' ' . $surnameClass;
  299. }
  300. } else {
  301. $chrL = mb_substr( $pre, -1, 1 );
  302. $chrR = mb_substr( $endSeparator, 0, 1 );
  303. if ( $chrL == $chrR ) {
  304. $endSeparator = ltrim( $endSeparator, $chrR );
  305. }
  306. $nameText = $pre;
  307. }
  308. return WCStyle::makeWikiLink( $link, $nameText, $htmlClass ) . $endSeparator;
  309. }
  310. public function __toString() {
  311. return implode( ' ', $this->parts );
  312. }
  313. public function getSortingParts() {
  314. if ( isset( $this->parts[ WCNamePartEnum::literal ] ) ) {
  315. return array( $this->parts[ WCNamePartEnum::literal ] );
  316. }
  317. $sortName = '';
  318. if ( isset( $this->parts[ WCNamePartEnum::surname ] ) ) {
  319. if ( isset( $this->parts[ WCNamePartEnum::nonDroppingParticle ] ) ) {
  320. $sortName = $this->parts[ WCNamePartEnum::nonDroppingParticle ] . ' ';
  321. }
  322. $sortName .= $this->parts[ WCNamePartEnum::surname ];
  323. }
  324. if ( isset( $this->parts[ WCNamePartEnum::given ] ) ) {
  325. $sortName .= ' ' . $this->parts[ WCNamePartEnum::given ];
  326. }
  327. if ( isset( $this->parts[ WCNamePartEnum::suffix ] ) ) {
  328. $sortName .= ' ' . $this->parts[ WCNamePartEnum::suffix ];
  329. }
  330. if ( isset( $this->parts[ WCNamePartEnum::droppingParticle ] ) ) {
  331. $sortName .= ' ' . $this->parts[ WCNamePartEnum::droppingParticle ];
  332. }
  333. return array( $sortName );
  334. }
  335. /**
  336. * Transform the given names, such as by shortening them to initials only.
  337. *
  338. * To be defined by child classes. An idname function by default.
  339. * @return string
  340. */
  341. protected function transformGivenNames( $givenNames ) {
  342. return $givenNames;
  343. }
  344. }