r96347 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r96346‎ | r96347 | r96348 >
Date:15:57, 6 September 2011
Author:cogden
Status:deferred
Tags:
Comment:
Publish version 0.8.1 (experimental but should be working)
Modified paths:
  • /trunk/extensions/WikiCitation/WikiCitation.body.php (added) (history)
  • /trunk/extensions/WikiCitation/WikiCitation.css (added) (history)
  • /trunk/extensions/WikiCitation/WikiCitation.i18n.magic.php (added) (history)
  • /trunk/extensions/WikiCitation/WikiCitation.i18n.php (added) (history)
  • /trunk/extensions/WikiCitation/WikiCitation.php (added) (history)
  • /trunk/extensions/WikiCitation/WikiCitationTests.txt (added) (history)
  • /trunk/extensions/WikiCitation/includes (added) (history)
  • /trunk/extensions/WikiCitation/includes/WCArgumentReader.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/WCArticle.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/WCBibliography.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/WCCitation.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/WCEnum.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/WCException.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/WCNote.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/WCReference.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/WCReferenceStore.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/WCSection.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/WCStyle.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/data (added) (history)
  • /trunk/extensions/WikiCitation/includes/data/WCData.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/data/WCDate.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/data/WCLocator.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/data/WCName.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/data/WCNames.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/data/WCText.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/data/WCTitle.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/data/WCTypeData.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/parameters (added) (history)
  • /trunk/extensions/WikiCitation/includes/parameters/WCAttributeEnum.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/parameters/WCCitationLengthEnum.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/parameters/WCCitationTypeEnum.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/parameters/WCDateTermsEnum.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/parameters/WCNamePartEnum.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/parameters/WCNameTypeEnum.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/parameters/WCParameterEnum.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/parameters/WCPropertyEnum.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/parameters/WCScopeEnum.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/parameters/WCSeasonEnum.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/parameters/WCSourceTypeEnum.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/segments (added) (history)
  • /trunk/extensions/WikiCitation/includes/segments/WCAlternativeSegment.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/segments/WCConditionalSegment.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/segments/WCDataSegment.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/segments/WCDateSegment.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/segments/WCGroupSegment.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/segments/WCLabelSegment.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/segments/WCLiteralSegment.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/segments/WCLocatorSegment.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/segments/WCNamesSegment.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/segments/WCSegment.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/segments/WCTextSegment.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/segments/WCTitleSegment.php (added) (history)
  • /trunk/extensions/WikiCitation/includes/segments/WCWrapperSegment.php (added) (history)
  • /trunk/extensions/WikiCitation/styles (added) (history)
  • /trunk/extensions/WikiCitation/styles/WCChicagoStyle.php (added) (history)

Diff [purge]

Index: trunk/extensions/WikiCitation/WikiCitationTests.txt
@@ -0,0 +1,50 @@
 2+!! test
 3+A single author author with no other data.
 4+!! input
 5+{{#cite:Chicago|long|note
 6+ | first=Gérard
 7+ | dropping-particle=de
 8+ | non-dropping-particle=la
 9+ | last=Martinière
 10+ | suffix=III
 11+}}
 12+!! result
 13+<p><span class="citation">Wales, Jimmy.</span>
 14+</p>
 15+!! end
 16+
 17+!! test
 18+Just an author by surname and given
 19+!! input
 20+{{#citation:|given=Jimmy|surname=Wales}}
 21+!! result
 22+<p><span class="citation">Wales, Jimmy.</span>
 23+</p>
 24+!! end
 25+
 26+!! test
 27+Two authors by surname and given
 28+!! input
 29+{{#citation:|given 1=Jimmy|surname 1=Wales|given 2=Jimmy|surname 2=Wales}}
 30+!! result
 31+<p><span class="citation">Wales, Jimmy &amp; Wales, Jimmy.</span>
 32+</p>
 33+!! end
 34+
 35+!! test
 36+Three authors by surname and given
 37+!! input
 38+{{#citation:|given=Jimmy|surname=Wales|given 2=Jimmy|surname 2=Wales|given 3=Jimmy|surname 3=Wales}}
 39+!! result
 40+<p><span class="citation">Wales, Jimmy; Wales, Jimmy &amp; Wales, Jimmy.</span>
 41+</p>
 42+!! end
 43+
 44+!! test
 45+An author with a link
 46+!! input
 47+{{#citation:|author=Wales, Jimmy |url=http://example.com/ |title=Example}}
 48+!! result
 49+<p><span class="citation">Wales, Jimmy. <a href="http://example.com/" class="external text" rel="nofollow">Example</a>
 50+</p>
 51+!! end
\ No newline at end of file
Property changes on: trunk/extensions/WikiCitation/WikiCitationTests.txt
___________________________________________________________________
Added: svn:eol-style
152 + native
Index: trunk/extensions/WikiCitation/WikiCitation.body.php
@@ -0,0 +1,287 @@
 2+<?php
 3+/**
 4+ * Entry point file for the WikiCitation extension.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * Entry-point class for the WikiCitation extension.
 13+ *
 14+ * This is a static factory class, containing necessary entry points for
 15+ * parser hooks. The class creates a parser (WCArgumentReader) to parse
 16+ * the parser function. This class then calls the parser to create an
 17+ * appropriate citation styler (children of WCStyle). This class also
 18+ * creates an object (WCArticle) representing all the citations on a
 19+ * single page.
 20+ */
 21+class WikiCitation {
 22+
 23+ /**
 24+ * @var string citeID String containing a magic word representing the
 25+ * parser function name. In English, it will be "cite", as in
 26+ * {{#cite:...|...}.
 27+ */
 28+ const citeID = 'wc_cite_tag';
 29+
 30+ /**
 31+ * @var string biblioID String containing a magic word representing the
 32+ * tag extension name. In English, it will be "biblio", as in
 33+ * <biblio>...</biblio>.
 34+ */
 35+ const biblioID = 'wc_biblio_tag';
 36+
 37+ /**
 38+ * @var string noteID String containing a magic word representing the
 39+ * tag extension name for notes. In English, it will be "note", as in
 40+ * <note>...</note>.
 41+ */
 42+ const noteID = 'wc_note_tag';
 43+
 44+ /**
 45+ * @var string notesID String containing a magic word representing the
 46+ * tag extension name for endnotes. In English, it will be "notes",
 47+ * as in <notes>...</notes>.
 48+ */
 49+ const endnotesID = 'wc_notes_tag';
 50+
 51+ /**
 52+ * @var string notesID String containing a magic word representing the
 53+ * tag extension name for a note section. In English, it will be
 54+ * "notesection", as in <notesection>...</notesection>.
 55+ */
 56+ const noteSectionID = 'wc_note_section_tag';
 57+
 58+ /**
 59+ * An object representing a single article containing citations and/or
 60+ * a bibliography.
 61+ *
 62+ * @static
 63+ * @var WCArticle $article
 64+ */
 65+ protected static $article;
 66+
 67+
 68+ /**
 69+ * Handler for 'ParserFirstCallInit' parser hook.
 70+ *
 71+ * Called by Parser object to initialize the WikiCitation extension.
 72+ * Sets up parser hook, so that WikiCitation::parse(...) will be called
 73+ * whenever the parser encounters "{{#cite:...}}" or an equivalent
 74+ * localized expression, or the "<biblio>" tag.
 75+ *
 76+ * @static
 77+ * @param Parser $parser the Parser object calling this hook
 78+ */
 79+ public static function onParserFirstCallInit( Parser $parser ) {
 80+
 81+ # Construct WCArticle object $article. The old $article, if it exists,
 82+ # will be recovered by garbage collector.
 83+ self::$article = new WCArticle();
 84+
 85+ # Create parser function hook to $article->parseFunctionTemplate(...).
 86+ $parser->setFunctionHook(
 87+ self::citeID, # citeID is the magic word representing the parser function.
 88+ 'WikiCitation::parseFunctionTemplate', # the function Parser will call
 89+ SFH_OBJECT_ARGS # The function call will be via PPNode_DOM arguments, rather than text,
 90+ # except for the first argument after the colon.
 91+ );
 92+
 93+ # Set hooks for biblio tag and its synonyms, if any.
 94+ foreach( MagicWord::get( self::biblioID )->getSynonyms() as $synonym ) {
 95+ $parser->setHook(
 96+ $synonym,
 97+ 'WikiCitation::parseBibliographyTag'
 98+ );
 99+ }
 100+
 101+ # Set hooks for note tag and its synonyms, if any.
 102+ foreach( MagicWord::get( self::noteID )->getSynonyms() as $synonym ) {
 103+ $parser->setHook(
 104+ $synonym,
 105+ 'WikiCitation::parseNoteTag'
 106+ );
 107+ }
 108+
 109+ # Set hooks for note section tag and its synonyms, if any.
 110+ foreach( MagicWord::get( self::noteSectionID )->getSynonyms() as $synonym ) {
 111+ $parser->setHook(
 112+ $synonym,
 113+ 'WikiCitation::parseSectionTag'
 114+ );
 115+ }
 116+
 117+ # Set hooks for endnote tag and its synonyms, if any.
 118+ foreach( MagicWord::get( self::endnotesID )->getSynonyms() as $synonym ) {
 119+ $parser->setHook(
 120+ $synonym,
 121+ 'WikiCitation::parseNotesTag'
 122+ );
 123+ }
 124+
 125+ # Associate style sheet with page.
 126+ global $wgOut, $wgWCStyleSheet;
 127+ $wgOut->addExtensionStyle( $wgWCStyleSheet );
 128+ #$wgOut->addScript( '<link rel="stylesheet" type="text/css" media="any" href="' . $wgWCStyleSheet . '" />' );
 129+
 130+ return True;
 131+ }
 132+
 133+
 134+ /**
 135+ * Parses the WikiCitation parser function and leaves marker in wikitext.
 136+ *
 137+ * This function is called by the Parser when it encounters the parser
 138+ * function "{{#cite:...}}" or an equivalent localized expression)
 139+ * Creates WCArgumentReader object to parse flags and parameters,
 140+ * then creates an appropriate child of class WCStyle based on the
 141+ * first parameter after the colon, then returns the citation as text.
 142+ * @remark Note that this $parser is guaranteed to be the same parser that
 143+ * initialized the object.
 144+ *
 145+ * @param Parser $parser = the parser
 146+ * @param PPFrame_DOM $frame = the DOM frame
 147+ * @param array $args = arguments
 148+ * @return array text
 149+ */
 150+ public static function parseFunctionTemplate( Parser $parser, PPFrame_DOM $frame, array $args ) {
 151+ if ( count( $args ) == 0 ) {
 152+ return '';
 153+ }
 154+ try {
 155+ $argumentReader = new WCArgumentReader( $parser, $frame, $args );
 156+ $text = self::$article->parseCitation( $argumentReader );
 157+ } catch ( WCException $e ) {
 158+ # Exception messages appear in place of the citation.
 159+ $text = '<strong class="' . WCStyle::citationHTML . ' ' . WCStyle::errorHTML . '">' . $e->getMessage() . '</strong>';
 160+ }
 161+ return $text;
 162+ }
 163+
 164+
 165+ /**
 166+ * Parses the <biblio> tag extension and leaves a marker in the wikitext.
 167+ *
 168+ * This function is called by the Parser when it encounters the parser
 169+ * function "<biblio>...</biblio>" or an equivalent localized expression).
 170+ *
 171+ * @param type $input = the text within the tags
 172+ * @param array $args = the HTML attributes
 173+ * @param Parser $parser = the parser object
 174+ * @param PPFrame $frame = the frame
 175+ * @return string
 176+ */
 177+ public static function parseBibliographyTag( $input, array $args, Parser $parser, PPFrame $frame ) {
 178+ self::$article->startBibliography( $args );
 179+ # Parse the text inside the <biblio> tags, which will contain embedded citations parser functions.
 180+ $parser->recursiveTagParse( $input, $frame );
 181+ return self::$article->endBibliography();
 182+ }
 183+
 184+
 185+ /**
 186+ * Parses the <note> tag extension and leaves a marker in the wikitext.
 187+ *
 188+ * This function is called by the Parser when it encounters the parser
 189+ * function "<note>...</note>" or an equivalent localized expression).
 190+ *
 191+ * @param type $input = the text within the tags
 192+ * @param array $args = the HTML attributes
 193+ * @param Parser $parser = the parser object
 194+ * @param PPFrame $frame = the frame
 195+ * @return string
 196+ */
 197+ public static function parseNoteTag( $input, array $args, Parser $parser, PPFrame $frame ) {
 198+ self::$article->startNote( $args );
 199+ # Parse the text inside the <note> tags, which will contain embedded citations.
 200+ $output = $parser->recursiveTagParse( $input, $frame );
 201+ # Leaves behind a single marker for the (probably subscripted) endnote marker.
 202+ return self::$article->finishNote( $output );
 203+ }
 204+
 205+
 206+ /**
 207+ * Parses the <notesection> tag extension and returns an endnote section.
 208+ *
 209+ * This function is called by the Parser when it encounters the parser
 210+ * function "<notesection>...</notesection>" or an equivalent localized expression).
 211+ *
 212+ * @param type $input = the text within the tags
 213+ * @param array $args = the HTML attributes
 214+ * @param Parser $parser = the parser object
 215+ * @param PPFrame $frame = the frame
 216+ * @return string
 217+ */
 218+ public static function parseSectionTag( $input, array $args, Parser $parser, PPFrame $frame ) {
 219+ if ( $input ) {
 220+ # If text is presented inside the <notes> tags, the text will appear first, followed
 221+ # by the associated endnotes.
 222+ self::$article->startSection( $args );
 223+ # Parse the text inside the <notes> tags, which may contain embedded
 224+ # parser functions.
 225+ $output = $parser->recursiveTagParse( $input, $frame );
 226+ # End the note section.
 227+ self::$article->endSection();
 228+ return output;
 229+ } else {
 230+ return '';
 231+ }
 232+ }
 233+
 234+
 235+ /**
 236+ * Parses the <notes> tag extension and returns the endnote section.
 237+ *
 238+ * This function is called by the Parser when it encounters the parser
 239+ * function "<notes/>" or an equivalent localized expression).
 240+ *
 241+ * @param type $input = the text within the tags
 242+ * @param array $args = the HTML attributes
 243+ * @param Parser $parser = the parser object
 244+ * @param PPFrame $frame = the frame
 245+ * @return string
 246+ */
 247+ public static function parseNotesTag( $input, array $args, Parser $parser, PPFrame $frame ) {
 248+ # Leaves a marker for all prior notes to this point within the notes section.
 249+ return self::$article->markEndnotes();
 250+ }
 251+
 252+
 253+ /**
 254+ * Handler for 'ParseClearState' hook.
 255+ *
 256+ * Called by parser to clear the parser state. This function clears the
 257+ * WCArticle object.
 258+ *
 259+ * @static
 260+ * @param Parser $parser = the parser
 261+ */
 262+ public static function onParserClearState( Parser $parser ) {
 263+ self::$article->clear();
 264+ return True;
 265+ }
 266+
 267+
 268+ /**
 269+ * Handler for 'ParserBeforeTidy' parser hook.
 270+ *
 271+ * Called by Parser object near the end of parsing. Renders citations in
 272+ * html and replaces the citation markers with the html citations.
 273+ * Also, this method links a style sheet to pages containing citations.
 274+ *
 275+ * @static
 276+ * @global type $wgOut
 277+ * @global type $wgWCStyleSheet
 278+ * @param Parser $parser = the parser
 279+ * @param string $text = the current parsed text of the article
 280+ */
 281+ public static function onParserBeforeTidy( Parser $parser, &$text ) {
 282+ # Insert citations.
 283+ self::$article->render( $text );
 284+ return True;
 285+ }
 286+
 287+
 288+}
Property changes on: trunk/extensions/WikiCitation/WikiCitation.body.php
___________________________________________________________________
Added: svn:eol-style
1289 + native
Index: trunk/extensions/WikiCitation/WikiCitation.i18n.magic.php
@@ -0,0 +1,253 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+$magicWords = array();
 11+
 12+$magicWords['en'] = array(
 13+
 14+ /**
 15+ * Parser function and tag extension elements and attributes.
 16+ */
 17+ 'wc_cite_tag' => array( 1, 'cite' ), # {{#cite:______}}
 18+ 'wc_biblio_tag' => array( 1, 'biblio' ), # <biblio>...</biblio>
 19+ 'wc_note_tag' => array( 1, 'note' ), # <note>...</note>
 20+ 'wc_notes_tag' => array( 1, 'notes' ), # <notes/>
 21+ 'wc_section_tag' => array( 1, 'notesection'), # <notesection>...</notesection>
 22+
 23+ 'wc_citestyle_attrib' => array( 1, 'citestyle' ), # attribute for <biblio> and <section> tags
 24+ 'wc_type_attrib' => array( 1, 'type' ), # attribute for <biblio> and <section> tags
 25+
 26+
 27+ /**
 28+ * Words used by WCArgumentReader.php
 29+ */
 30+ # name of defined styles, including default
 31+ 'wc_default' => array( 0, 'default' ),
 32+ 'wc_Chicago' => array( 0, 'Chicago' ),
 33+ 'wc_Bluebook' => array( 0, 'Bluebook' ),
 34+
 35+
 36+ /**
 37+ * Flags
 38+ */
 39+ # citation type
 40+ 'wc_inline' => array( 0, 'inline' ),
 41+ 'wc_bibliography' => array( 0, 'bibliography', 'biblio' ),
 42+ 'wc_note' => array( 0, 'note' ),
 43+ 'wc_author_date' => array( 0, 'author-date' ), # indicates author-date style variant
 44+
 45+ # citation length
 46+ 'wc_long' => array( 0, 'long' ),
 47+ 'wc_short' => array( 0, 'short' ),
 48+
 49+ /**
 50+ * Scope and type parameters
 51+ */
 52+ # Combining parameters denoting works or names relating to the work. These
 53+ # will be prefixes.
 54+ 'wc_work' => array( 0, 'work' ), # This will be the default.
 55+ 'wc_container' => array( 0, 'container' ),
 56+ 'wc_series' => array( 0, 'series', 'periodical', 'journal' ),
 57+ 'wc_original' => array( 0, 'original' ),
 58+ 'wc_subject' => array( 0, 'subject' ),
 59+
 60+ /**
 61+ * Parameters defining data about the work as a whole.
 62+ */
 63+ # Type of reference (e.g., book, article, etc.). See below
 64+ 'wc_type' => array( 0, 'type' ),
 65+
 66+ # links
 67+ 'wc_link' => array( 0, 'link' ), # wikilink to page about source. In English, this needs to be processed before authors, to avoid conflict.
 68+ 'wc_URL' => array( 0, 'url', 'uri' ),
 69+
 70+ # reference numbers
 71+ 'wc_call_number' => array( 0, 'call-number' ),
 72+ 'wc_DOI' => array( 0, 'DOI' ),
 73+ 'wc_ISBN' => array( 0, 'ISBN' ),
 74+
 75+ # date variables
 76+ 'wc_date' => array( 0, 'date', 'dates', 'year', 'years' ),
 77+ 'wc_accessed' => array( 0, 'accessed' ),
 78+ 'wc_issued' => array( 0, 'issued' ),
 79+ 'wc_filed' => array( 0, 'filed' ),
 80+
 81+ # other data parameters
 82+ 'wc_title' => array( 0, 'title' ),
 83+ 'wc_short_title' => array( 0, 'short-title' ),
 84+ 'wc_place' => array( 0, 'place', 'publisher-place', 'publication-place', 'archive-location', 'archive-place' ),
 85+ 'wc_edition' => array( 0, 'edition' ),
 86+ 'wc_volume' => array( 0, 'volume' ),
 87+ 'wc_issue' => array( 0, 'issue' ),
 88+ 'wc_first_page' => array( 0, 'first-page' ),
 89+ 'wc_version' => array( 0, 'version' ),
 90+ 'wc_number' => array( 0, 'number' ),
 91+ 'wc_opus' => array( 0, 'opus' ),
 92+ 'wc_archive' => array( 0, 'archive' ),
 93+ 'wc_jurisdiction' => array( 0, 'jurisdiction' ),
 94+ 'wc_keyword' => array( 0, 'keyword' ),
 95+
 96+ /**
 97+ * Parameters denoting one or more locations within a work (i.e., locators).
 98+ */
 99+ 'wc_book_loc' => array( 0, 'book', 'books' ), # i.e., biblical "book," book III of Lord of the Rings, etc.
 100+ 'wc_part' => array( 0, 'part', 'parts' ),
 101+ 'wc_chapter_loc' => array( 0, 'chapter', 'chapters' ),
 102+ 'wc_page' => array( 0, 'page', 'pages' ),
 103+ 'wc_page_range' => array( 0, 'page-range' ),
 104+ 'wc_folio' => array( 0, 'folio', 'folios' ),
 105+ 'wc_column' => array( 0, 'column', 'columns' ),
 106+ 'wc_table' => array( 0, 'table', 'tables' ),
 107+ 'wc_figure' => array( 0, 'figure', 'figures' ),
 108+ 'wc_section' => array( 0, 'section', 'sections' ),
 109+ 'wc_paragraph' => array( 0, 'paragraph', 'paragraphs' ),
 110+ 'wc_note_loc' => array( 0, 'note', 'notes' ),
 111+ 'wc_footnote' => array( 0, 'footnote', 'footnotes' ),
 112+ 'wc_endnote' => array( 0, 'endnote', 'endnotes' ),
 113+ 'wc_verse' => array( 0, 'verse', 'verses' ),
 114+ 'wc_line' => array( 0, 'line', 'lines' ),
 115+ 'wc_locator' => array( 0, 'locator', 'locators' ), # a generic or descriptive locator
 116+
 117+ # Values for type of reference
 118+ 'wc_general' => array( 0, 'general' ), # the default: could be any type of reference
 119+ 'wc_book' => array( 0, 'book' ),
 120+ 'wc_dictionary' => array( 0, 'dictionary' ),
 121+ 'wc_encyclopedia' => array( 0, 'encyclopedia' ),
 122+ 'wc_periodical' => array( 0, 'periodical' ),
 123+ 'wc_magazine' => array( 0, 'magazine' ),
 124+ 'wc_newspaper' => array( 0, 'newspaper' ),
 125+ 'wc_journal' => array( 0, 'journal' ),
 126+ 'wc_entry' => array( 0, 'entry' ),
 127+ 'wc_article' => array( 0, 'article' ),
 128+ 'wc_chapter' => array( 0, 'chapter' ),
 129+ 'wc_review' => array( 0, 'review' ),
 130+ 'wc_paper' => array( 0, 'paper' ),
 131+ 'wc_manuscript' => array( 0, 'manuscript' ),
 132+ 'wc_musical_score' => array( 0, 'musical-score' ),
 133+ 'wc_pamphlet' => array( 0, 'pamphlet' ),
 134+ 'wc_conference_paper' => array( 0, 'conference-paper' ),
 135+ 'wc_thesis' => array( 0, 'thesis' ),
 136+ 'wc_dissertation' => array( 0, 'PhD-dissertation' ),
 137+ 'wc_report' => array( 0, 'report' ),
 138+ 'wc_poem' => array( 0, 'poem' ),
 139+ 'wc_song' => array( 0, 'song' ),
 140+ 'wc_enactment' => array( 0, 'enactment', 'legislation' ),
 141+ 'wc_bill' => array( 0, 'bill' ),
 142+ 'wc_statute' => array( 0, 'statute' ),
 143+ 'wc_treaty' => array( 0, 'treaty' ),
 144+ 'wc_rule' => array( 0, 'rule' ),
 145+ 'wc_regulation' => array( 0, 'regulation' ),
 146+ 'wc_legal_document' => array( 0, 'legal-document' ),
 147+ 'wc_patent' => array( 0, 'patent' ),
 148+ 'wc_deed' => array( 0, 'deed' ),
 149+ 'wc_government_grant' => array( 0, 'government-grant' ),
 150+ 'wc_filing' => array( 0, 'filing' ),
 151+ 'wc_patent_application' => array( 0, 'patent-application' ),
 152+ 'wc_regulatory_filing' => array( 0, 'regulatory-filing' ),
 153+ 'wc_litigation' => array( 0, 'litigation' ),
 154+ 'wc_legal_opinion' => array( 0, 'legal-opinion' ),
 155+ 'wc_legal_case' => array( 0, 'legal-case' ),
 156+ 'wc_graphic' => array( 0, 'graphic' ),
 157+ 'wc_photograph' => array( 0, 'photograph' ),
 158+ 'wc_map' => array( 0, 'map' ),
 159+ 'wc_statement' => array( 0, 'statement'),
 160+ 'wc_press_release' => array( 0, 'press-release'),
 161+ 'wc_interview' => array( 0, 'interview' ),
 162+ 'wc_speech' => array( 0, 'speech' ),
 163+ 'wc_personal_communication' => array( 0, 'personal-communication' ),
 164+ 'wc_internet_resource' => array( 0, 'internet-resource' ),
 165+ 'wc_web_page' => array( 0, 'web-page', 'webpage' ),
 166+ 'wc_post' => array( 0, 'post' ),
 167+ 'wc_production' => array( 0, 'production' ),
 168+ 'wc_motion_picture' => array( 0, 'motion-picture' ),
 169+ 'wc_recording' => array( 0, 'recording' ),
 170+ 'wc_play' => array( 0, 'play' ),
 171+ 'wc_broadcast' => array( 0, 'broadcast' ),
 172+ 'wc_television_broadcast' => array( 0, 'television-broadcast' ),
 173+ 'wc_radio_broadcast' => array( 0, 'radio-broadcast' ),
 174+ 'wc_internet_broadcast' => array( 0, 'internet-broadcast' ),
 175+ 'wc_object' => array( 0, 'object' ),
 176+ 'wc_star' => array( 0, 'star' ),
 177+ 'wc_gravestone' => array( 0, 'gravestone', 'headstone' ),
 178+ 'wc_monument' => array( 0, 'monument' ),
 179+ 'wc_real_property' => array( 0, 'real-property' ),
 180+
 181+ /**
 182+ * Name parameters
 183+ */
 184+ # Parameters denoting names, including persons
 185+ 'wc_author' => array( 0, 'author' ),
 186+ 'wc_publisher' => array( 0, 'publisher' ),
 187+ 'wc_editor_translator' => array( 0, 'editor-translator', 'translator-editor' ),
 188+ 'wc_editor' => array( 0, 'editor' ),
 189+ 'wc_translator' => array( 0, 'translator' ),
 190+ 'wc_interviewer' => array( 0, 'interviewer' ),
 191+ 'wc_recipient' => array( 0, 'recipient' ),
 192+ 'wc_composer' => array( 0, 'composer' ),
 193+
 194+ # words denoting types of name data
 195+ 'wc_surname' => array( 0, 'surname', 'last' ),
 196+ 'wc_given' => array( 0, 'given', 'first' ),
 197+ 'wc_namelink' => array( 0, 'link' ),
 198+ 'wc_suffix' => array( 0, 'suffix' ),
 199+ 'wc_droppingparticle' => array( 0, 'dropping-particle' ),
 200+ 'wc_nondroppingparticle' => array( 0, 'non-dropping-particle' ),
 201+ 'wc_literalname' => array( 0, 'literal', 'organization' ),
 202+
 203+
 204+ /**
 205+ * Other magic words
 206+ */
 207+ 'wc_ad_magic_word' => array( 1, 'A.D.', 'AD', 'C.E.', 'CE' ),
 208+ 'wc_bc_magic_word' => array( 1, 'B.C.', 'BC', 'B.C.E.', 'BCE' ),
 209+ 'wc_circa' => array( 0, 'circa', 'c.', 'around', 'about' ),
 210+ 'wc_spring' => array( 0, 'spring' ),
 211+ 'wc_summer' => array( 0, 'summer' ),
 212+ 'wc_autumn' => array( 0, 'autumn', 'fall' ),
 213+ 'wc_winter' => array( 0, 'winter' ),
 214+ 'wc_year' => array( 0, 'year' ), # 年
 215+ 'wc_month' => array( 0, 'month' ), # 月
 216+ 'wc_day' => array( 0, 'day' ), # 日
 217+
 218+ 'wc_list_delimiter' => array( 0, ',', 'and', '&' ), # Delimits various discrete numbers or number ranges
 219+ 'wc_range_delimiter' => array( 0, 'to' ), # Indicates a continuous number range
 220+
 221+ 'wc_initial_exterior_quote' => array( 0, '"', '“', ), # initial exterior quote symbol for input purposes
 222+ 'wc_final_exterior_quote' => array( 0, '"', '”', ), # final exterior quote symbol
 223+ 'wc_initial_interior_quote' => array( 0, "'", '‘', ), # initial interior quote symbol
 224+ 'wc_final_interior_quote' => array( 0, "'", '’', ), # final interior quote symbol
 225+ 'wc_articles' => array( 0, 'a', 'an', 'the', 'el', 'la' ),
 226+ 'wc_prepositions' => array( 0, 'aboard', 'about', 'abaft', 'aboard', 'about', 'above', 'absent', 'across', 'afore', 'after', 'against', 'along', 'alongside', 'amid', 'amidst', 'among', 'amongst', 'apropos', 'around', 'as', 'aside', 'astride', 'at', 'athwart', 'atop',
 227+ 'barring', 'before', 'behind', 'below', 'beneath', 'beside', 'besides', 'between', 'betwixt', 'beyond', 'but', 'by',
 228+ 'circa', 'c.', 'ca.', 'concerning',
 229+ 'despite', 'down', 'during',
 230+ 'except', 'excluding',
 231+ 'failing', 'following', 'for', 'from',
 232+ 'given',
 233+ 'in', 'including', 'inside', 'into',
 234+ 'like',
 235+ 'mid,', 'midst', 'minus',
 236+ 'near', 'next', 'notwithstanding',
 237+ 'of', 'off', 'on', 'onto', 'opposite', 'out', 'outside', 'over',
 238+ 'pace', 'past', 'per', 'plus', 'pro',
 239+ 'qua',
 240+ 'regarding', 'round',
 241+ 'sans', 'save', 'since',
 242+ 'than', 'through,', 'thru,', 'throughout,', 'thruout', 'till', 'times', 'to', 'toward', 'towards',
 243+ 'under', 'underneath', 'unlike', 'until', 'up', 'upon',
 244+ 'versus', 'vs.', 'v.', 'via', 'vice',
 245+ 'with', 'within', 'without', 'worth'
 246+ ),
 247+ 'wc_coordinating_conjunctions' => array( 0, 'and', 'but', 'for', 'nor', 'or', 'so', 'yet' ),
 248+ 'wc_subordinating_conjunctions' => array( 0, 'after', 'although', 'as', 'because', 'before', 'both', 'either',
 249+ 'how', 'however', 'if', 'neither', 'now', 'once', 'only', 'provided',
 250+ 'since', 'than', 'that', 'though', 'till', 'unless', 'until',
 251+ 'when', 'whenever', 'where', 'whereas', 'wherever', 'whether', 'while' ),
 252+
 253+
 254+);
Property changes on: trunk/extensions/WikiCitation/WikiCitation.i18n.magic.php
___________________________________________________________________
Added: svn:eol-style
1255 + native
Index: trunk/extensions/WikiCitation/WikiCitation.i18n.php
@@ -0,0 +1,240 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+$messages = array ();
 11+
 12+
 13+/** Pseudo-language with explanations */
 14+$messages['qqq'] = array(
 15+ 'wc-description' => 'Description of the WikiCitation extension.',
 16+ 'wc-ws' => 'The normal delimiter or punctuation between two names. For example, if there are two authors, text would be placed between them, except when the citation is presented with surname first, for sorting within a bibliography (in which case "wc-name-punct" would be used).',
 17+ 'wc-name-punct' => 'The normal delimiter or punctuation between two names, when the citation is presented with surname first, for sorting within a bibliography',
 18+ );
 19+
 20+
 21+/** English */
 22+$messages['en'] = array (
 23+
 24+ # Extension description
 25+ 'wc-description' => 'Adds tags for fast standard reference citations and automatic bibliographies',
 26+
 27+
 28+ # Name separators
 29+ 'wc-name-whitespace' => ' ', # whitespace, if any, between names
 30+ 'wc-name-sort-order-delimiter' => ', ', # punctuation between names in name-sort mode
 31+ 'wc-surname-delimiter' => ', ', # punctuation after surname in name-sort mode
 32+ 'wc-name-suffix-delimiter' => ' ', # Delimiter before name suffix
 33+ 'wc-name-missing' => '___', # blank to represent a missing name
 34+
 35+ 'wc-names-delim' => ', ', # the normal delimiter between names
 36+ 'wc-names-et-al-delim' => ', ', # the delimiter before the "and others" designation
 37+ 'wc-names-and-2' => ' and ', # the delimiter between two names if there are only two
 38+ 'wc-names-and-3' => ', and ', # the last delimiter for three or more names
 39+ 'wc-names-and-others' => 'et al.', # "and others"
 40+
 41+ # Citation separators and punctuation
 42+ 'wc-initial-exterior-quote' => '"', # initial exterior quote symbol. (Note: for now, typewriter quotes are widely used in English wikis.)
 43+ 'wc-final-exterior-quote' => '"', # final exterior quote symbol
 44+ 'wc-initial-interior-quote' => "'", # initial interior quote symbol
 45+ 'wc-final-interior-quote' => "'", # final interior quote symbol
 46+ 'wc-segment-missing' => '___', # blank to represent a missing segment
 47+ 'wc-range-delimiter' => '–', # delimiter for ranges (usually en-dash).
 48+
 49+ # Date localization
 50+ 'wc-ad' => 'A.D.',
 51+ 'wc-ad-no-punct' => 'AD',
 52+ 'wc-ce' => 'C.E.',
 53+ 'wc-ce-no-punct' => 'CE',
 54+ 'wc-bc' => 'B.C.',
 55+ 'wc-bc-no-punct' => 'BC',
 56+ 'wc-bce' => 'B.C.E.',
 57+ 'wc-bce-no-punct' => 'BCE',
 58+ 'wc_spring' => 'spring',
 59+ 'wc_summer' => 'summer',
 60+ 'wc_autumn' => 'fall',
 61+ 'wc_winter' => 'winter',
 62+ 'wc_year' => 'year', # 年
 63+ 'wc_month' => 'month', # 月
 64+ 'wc_day' => 'day', # 日
 65+
 66+ /*
 67+ * Literal text
 68+ */
 69+ 'wc-personal-communication' => 'personal communication',
 70+
 71+
 72+ /*
 73+ * Labels
 74+ */
 75+ 'wc-author-long-singular' => 'author',
 76+ 'wc-author-long-plural' => 'authors',
 77+ 'wc-author-verb-singular' => 'authored by',
 78+ 'wc-author-verb-plural' => 'authored by',
 79+ 'wc-author-short-singular' => 'auth.',
 80+ 'wc-author-short-plural' => 'auths.',
 81+ 'wc-author-verb-short-singular' => 'auth.',
 82+ 'wc-author-verb-short-plural' => 'auth.',
 83+ 'wc-author-symbol-singular' => 'auth.',
 84+ 'wc-author-symbol-plural' => 'auths.',
 85+
 86+ 'wc-editor-long-singular' => 'editor',
 87+ 'wc-editor-long-plural' => 'editors',
 88+ 'wc-editor-verb-singular' => 'edited by',
 89+ 'wc-editor-verb-plural' => 'edited by',
 90+ 'wc-editor-short-singular' => 'ed.',
 91+ 'wc-editor-short-plural' => 'eds.',
 92+ 'wc-editor-verb-short-singular' => 'ed.',
 93+ 'wc-editor-verb-short-plural' => 'eds.',
 94+ 'wc-editor-symbol-singular' => 'ed.',
 95+ 'wc-editor-symbol-plural' => 'eds.',
 96+
 97+ 'wc-translator-long-singular' => 'translator',
 98+ 'wc-translator-long-plural' => 'translators',
 99+ 'wc-translator-verb-singular' => 'translated by',
 100+ 'wc-translator-verb-plural' => 'translated by',
 101+ 'wc-translator-short-singular' => 'trans.',
 102+ 'wc-translator-short-plural' => 'trans.',
 103+ 'wc-translator-verb-short-singular' => 'trans.',
 104+ 'wc-translator-verb-short-plural' => 'trans.',
 105+ 'wc-translator-symbol-singular' => 'trans.',
 106+ 'wc-translator-symbol-plural' => 'trans.',
 107+
 108+ 'wc-editor-translator-long-singular' => 'editor and translator',
 109+ 'wc-editor-translator-long-plural' => 'editors and translators',
 110+ 'wc-editor-translator-verb-singular' => 'edited and translated by',
 111+ 'wc-editor-translator-verb-plural' => 'edited and translated by',
 112+ 'wc-editor-translator-short-singular' => 'ed. and trans.',
 113+ 'wc-editor-translator-short-plural' => 'eds. and trans.',
 114+ 'wc-editor-translator-verb-short-singular' => 'ed. and trans.',
 115+ 'wc-editor-translator-verb-short-plural' => 'eds. and trans.',
 116+ 'wc-editor-translator-symbol-singular' => 'ed. & trans.',
 117+ 'wc-editor-translator-symbol-plural' => 'ed. & trans.',
 118+
 119+ 'wc-publisher-long-singular' => 'publisher',
 120+ 'wc-publisher-long-plural' => 'publishers',
 121+ 'wc-publisher-verb-singular' => 'published by',
 122+ 'wc-publisher-verb-plural' => 'published by',
 123+ 'wc-publisher-short-singular' => 'pub.',
 124+ 'wc-publisher-short-plural' => 'pubs.',
 125+ 'wc-publisher-verb-short-singular' => 'pub. by',
 126+ 'wc-publisher-verb-short-plural' => 'pubs. by',
 127+ 'wc-publisher-symbol-singular' => 'pub.',
 128+ 'wc-publisher-symbol-plural' => 'pubs.',
 129+
 130+ 'wc-interviewer-long-singular' => 'interviewer',
 131+ 'wc-interviewer-long-plural' => 'interviewers',
 132+ 'wc-interviewer-verb-singular' => 'interview by',
 133+ 'wc-interviewer-verb-plural' => 'interview by',
 134+ 'wc-interviewer-short-singular' => 'interviewer',
 135+ 'wc-interviewer-short-plural' => 'interviewers',
 136+ 'wc-interviewer-verb-short-singular' => 'interview by',
 137+ 'wc-interviewer-verb-short-plural' => 'interview by',
 138+ 'wc-interviewer-symbol-singular' => 'interviewer',
 139+ 'wc-interviewer-symbol-plural' => 'interviewers',
 140+
 141+ 'wc-recipient-long-singular' => 'recipient',
 142+ 'wc-recipient-long-plural' => 'recipients',
 143+ 'wc-recipient-verb-singular' => 'received by',
 144+ 'wc-recipient-verb-plural' => 'received by',
 145+ 'wc-recipient-short-singular' => 'to',
 146+ 'wc-recipient-short-plural' => 'to',
 147+ 'wc-recipient-verb-short-singular' => 'to',
 148+ 'wc-recipient-verb-short-plural' => 'to',
 149+ 'wc-recipient-symbol-singular' => 'to',
 150+ 'wc-recipient-symbol-plural' => 'to',
 151+
 152+ 'wc-composer-long-singular' => 'composer',
 153+ 'wc-composer-long-plural' => 'composers',
 154+ 'wc-composer-verb-singular' => 'composed by',
 155+ 'wc-composer-verb-plural' => 'composed by',
 156+ 'wc-composer-short-singular' => 'composer',
 157+ 'wc-composer-short-plural' => 'composers',
 158+ 'wc-composer-verb-short-singular' => 'composed by',
 159+ 'wc-composer-verb-short-plural' => 'composed by',
 160+ 'wc-composer-symbol-singular' => 'composer',
 161+ 'wc-composer-symbol-plural' => 'composers',
 162+
 163+ 'wc-page-long-singular' => 'page',
 164+ 'wc-page-long-plural' => 'pages',
 165+ 'wc-page-verb-singular' => 'page',
 166+ 'wc-page-verb-plural' => 'pages',
 167+ 'wc-page-short-singular' => 'p.',
 168+ 'wc-page-short-plural' => 'pp.',
 169+ 'wc-page-verb-short-singular' => 'p.',
 170+ 'wc-page-verb-short-plural' => 'pp.',
 171+ 'wc-page-symbol-singular' => 'p.',
 172+ 'wc-page-symbol-plural' => 'pp.',
 173+
 174+ 'wc-section-long-singular' => 'section',
 175+ 'wc-section-long-plural' => 'sections',
 176+ 'wc-section-verb-singular' => 'section',
 177+ 'wc-section-verb-plural' => 'sections',
 178+ 'wc-section-short-singular' => 'sec.',
 179+ 'wc-section-short-plural' => 'secs.',
 180+ 'wc-section-verb-short-singular' => 'sec.',
 181+ 'wc-section-verb-short-plural' => 'sec.',
 182+ 'wc-section-symbol-singular' => '§',
 183+ 'wc-section-symbol-plural' => '§§',
 184+
 185+ 'wc-paragraph-long-singular' => 'paragraph',
 186+ 'wc-paragraph-long-plural' => 'paragraphs',
 187+ 'wc-paragraph-verb-singular' => 'paragraph',
 188+ 'wc-paragraph-verb-plural' => 'paragraphs',
 189+ 'wc-paragraph-short-singular' => 'para.',
 190+ 'wc-paragraph-short-plural' => 'paras.',
 191+ 'wc-paragraph-verb-short-singular' => 'para.',
 192+ 'wc-paragraph-verb-short-plural' => 'paras.',
 193+ 'wc-paragraph-symbol-singular' => '¶',
 194+ 'wc-paragraph-symbol-plural' => '¶¶',
 195+
 196+ 'wc-volume-long-singular' => 'volume',
 197+ 'wc-volume-long-plural' => 'volumes',
 198+ 'wc-volume-verb-singular' => 'volume',
 199+ 'wc-volume-verb-plural' => 'volumes',
 200+ 'wc-volume-short-singular' => 'vol.',
 201+ 'wc-volume-short-plural' => 'volss.',
 202+ 'wc-volume-verb-short-singular' => 'vol.',
 203+ 'wc-volume-verb-short-plural' => 'vols.',
 204+ 'wc-volume-symbol-singular' => 'vol.',
 205+ 'wc-volume-symbol-plural' => 'vols.',
 206+
 207+ 'wc-issue-long-singular' => 'issue',
 208+ 'wc-issue-long-plural' => 'issues',
 209+ 'wc-issue-verb-singular' => 'issue',
 210+ 'wc-issue-verb-plural' => 'issue',
 211+ 'wc-issue-short-singular' => 'no.',
 212+ 'wc-issue-short-plural' => 'nos.',
 213+ 'wc-issue-verb-short-singular' => 'no.',
 214+ 'wc-issue-verb-short-plural' => 'nos.',
 215+ 'wc-issue-symbol-singular' => 'no.',
 216+ 'wc-issue-symbol-plural' => 'nos.',
 217+
 218+ 'wc-circa-long-singular' => 'circa',
 219+ 'wc-circa-long-plural' => 'circa',
 220+ 'wc-circa-verb-singular' => 'about',
 221+ 'wc-circa-verb-plural' => 'about',
 222+ 'wc-circa-short-singular' => 'c.',
 223+ 'wc-circa-short-plural' => 'c.',
 224+ 'wc-circa-verb-short-singular' => 'abt.',
 225+ 'wc-circa-verb-short-plural' => 'abt.',
 226+ 'wc-circa-symbol-singular' => 'c.',
 227+ 'wc-circa-symbol-plural' => 'c.',
 228+
 229+ /*
 230+ * Error messages
 231+ */
 232+ 'wc-style-not-recognized' => 'Cite error: <code>$1</code> citation style not recognized.',
 233+ 'wc-flag-unknown' => 'Cite error: unknown <code>$1</code>.',
 234+ 'wc-incompatible-flags' => 'Cite error: citation cannot be <code>$1</code> and <code>$2</code>.',
 235+ 'wc-parameter_defined_twice' => 'Cite error: <code>$1</code> defined twice.',
 236+ 'wc-parameter-unknown' => 'Cite error: <code>$1</code> not a recognized property.',
 237+ 'wc-type-parameter-unknown' => 'Cite error: <code>$1</code> not a recognized <code>type</code>.',
 238+
 239+
 240+);
 241+
Property changes on: trunk/extensions/WikiCitation/WikiCitation.i18n.php
___________________________________________________________________
Added: svn:eol-style
1242 + native
Index: trunk/extensions/WikiCitation/styles/WCChicagoStyle.php
@@ -0,0 +1,511 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCChicagoStyle extends WCStyle {
 12+
 13+ public static $titleFormatArray = array (
 14+ WCSourceTypeEnum::general => WCTitleFormat::italic,
 15+ WCSourceTypeEnum::book => WCTitleFormat::italic,
 16+ WCSourceTypeEnum::dictionary => WCTitleFormat::italic,
 17+ WCSourceTypeEnum::encyclopedia => WCTitleFormat::italic,
 18+ WCSourceTypeEnum::periodical => WCTitleFormat::italic,
 19+ WCSourceTypeEnum::magazine => WCTitleFormat::italic,
 20+ WCSourceTypeEnum::newspaper => WCTitleFormat::italic,
 21+ WCSourceTypeEnum::journal => WCTitleFormat::italic,
 22+ WCSourceTypeEnum::entry => WCTitleFormat::quoted,
 23+ WCSourceTypeEnum::article => WCTitleFormat::quoted,
 24+ WCSourceTypeEnum::chapter => WCTitleFormat::quoted,
 25+ WCSourceTypeEnum::review => WCTitleFormat::quoted,
 26+ WCSourceTypeEnum::paper => WCTitleFormat::quoted,
 27+ WCSourceTypeEnum::manuscript => WCTitleFormat::quoted,
 28+ WCSourceTypeEnum::musicalScore => WCTitleFormat::quoted,
 29+ WCSourceTypeEnum::pamphlet => WCTitleFormat::italic,
 30+ WCSourceTypeEnum::conferencePaper => WCTitleFormat::quoted,
 31+ WCSourceTypeEnum::thesis => WCTitleFormat::quoted,
 32+ WCSourceTypeEnum::report => WCTitleFormat::italic,
 33+ WCSourceTypeEnum::poem => WCTitleFormat::quoted,
 34+ WCSourceTypeEnum::song => WCTitleFormat::italic,
 35+ WCSourceTypeEnum::enactment => WCTitleFormat::quoted,
 36+ WCSourceTypeEnum::bill => WCTitleFormat::quoted,
 37+ WCSourceTypeEnum::statute => WCTitleFormat::quoted,
 38+ WCSourceTypeEnum::treaty => WCTitleFormat::quoted,
 39+ WCSourceTypeEnum::rule => WCTitleFormat::quoted,
 40+ WCSourceTypeEnum::regulation => WCTitleFormat::quoted,
 41+ WCSourceTypeEnum::legalDocument => WCTitleFormat::quoted,
 42+ WCSourceTypeEnum::patent => WCTitleFormat::quoted,
 43+ WCSourceTypeEnum::deed => WCTitleFormat::quoted,
 44+ WCSourceTypeEnum::governmentGrant => WCTitleFormat::quoted,
 45+ WCSourceTypeEnum::filing => WCTitleFormat::quoted,
 46+ WCSourceTypeEnum::patentApplication => WCTitleFormat::quoted,
 47+ WCSourceTypeEnum::regulatoryFiling => WCTitleFormat::quoted,
 48+ WCSourceTypeEnum::litigation => WCTitleFormat::italic,
 49+ WCSourceTypeEnum::legalOpinion => WCTitleFormat::italic,
 50+ WCSourceTypeEnum::legalCase => WCTitleFormat::italic,
 51+ WCSourceTypeEnum::graphic => WCTitleFormat::italic,
 52+ WCSourceTypeEnum::photograph => WCTitleFormat::italic,
 53+ WCSourceTypeEnum::map => WCTitleFormat::italic,
 54+ WCSourceTypeEnum::statement => WCTitleFormat::quoted,
 55+ WCSourceTypeEnum::pressRelease => WCTitleFormat::quoted,
 56+ WCSourceTypeEnum::interview => WCTitleFormat::quoted,
 57+ WCSourceTypeEnum::speech => WCTitleFormat::quoted,
 58+ WCSourceTypeEnum::personalCommunication => WCTitleFormat::quoted,
 59+ WCSourceTypeEnum::internetResource => WCTitleFormat::quoted,
 60+ WCSourceTypeEnum::webpage => WCTitleFormat::quoted,
 61+ WCSourceTypeEnum::post => WCTitleFormat::quoted,
 62+ WCSourceTypeEnum::production => WCTitleFormat::italic,
 63+ WCSourceTypeEnum::motionPicture => WCTitleFormat::italic,
 64+ WCSourceTypeEnum::recording => WCTitleFormat::italic,
 65+ WCSourceTypeEnum::play => WCTitleFormat::italic,
 66+ WCSourceTypeEnum::broadcast => WCTitleFormat::italic,
 67+ WCSourceTypeEnum::televisionBroadcast => WCTitleFormat::italic,
 68+ WCSourceTypeEnum::radioBroadcast => WCTitleFormat::italic,
 69+ WCSourceTypeEnum::internetBroadcast => WCTitleFormat::italic,
 70+ WCSourceTypeEnum::object => WCTitleFormat::quoted,
 71+ WCSourceTypeEnum::star => WCTitleFormat::quoted,
 72+ WCSourceTypeEnum::gravestone => WCTitleFormat::quoted,
 73+ WCSourceTypeEnum::monument => WCTitleFormat::quoted,
 74+ WCSourceTypeEnum::realProperty => WCTitleFormat::quoted,
 75+ );
 76+
 77+
 78+ /**
 79+ * Constructor. Overwrites a few style properties of parent class, but
 80+ * otherwise keeps everything the same as default.
 81+ */
 82+ public function __construct() {
 83+ parent::__construct();
 84+ $this->punctuationInQuotes = True;
 85+ $this->replaceAmpersands = False;
 86+ $this->eraWithoutPunctuation = True;
 87+ $this->eraNoSpace = False;
 88+ $this->eraBeforeYear = False;
 89+ $this->styleHTML = 'Chicago';
 90+
 91+ }
 92+
 93+
 94+ /**
 95+ * Composes a short inline citation.
 96+ * In the Chicago Manual of Style, inline citations are only used as part of
 97+ * author-date system. Thus, this calls $this->renderShortInlineCitation.
 98+ * is set.
 99+ * @return array
 100+ */
 101+ public function renderShortInlineCitation( WCCitation $citation ) {
 102+ return $this->renderShortAuthorDateCitation( $citation );
 103+ }
 104+
 105+
 106+ /**
 107+ * Renders a short citation for use in a footnote or endnote.
 108+ * The resulting citation includes closing sentence punctuation.
 109+ * @return array
 110+ */
 111+ public function renderShortNoteCitation( WCCitation $citation ) {
 112+ $workTypeEnum = $citation->reference->getWorkType();
 113+
 114+ $titleFormat = new WCTitleFormat( self::$titleFormatArray[ $workTypeEnum->key ] );
 115+
 116+ $cite = new WCGroupSegment(
 117+ array(
 118+ new WCNamesSegment( $citation, $this->important, WCScopeEnum::$work, WCNameTypeEnum::$author, $this->first, WCCitationLengthEnum::$short, False ),
 119+ new WCTitleSegment( $citation, $this->important, WCScopeEnum::$work, WCPropertyEnum::$shortTitle, $titleFormat ),
 120+ new WCLocatorSegment( $citation, $this->important, WCPropertyEnum::$page ),
 121+ ),
 122+ ', ' # delimiter
 123+ );
 124+
 125+ return array( $cite->render( $this, '.' ), $cite );
 126+ }
 127+
 128+
 129+ /**
 130+ * Composes a short author-date citation.
 131+ * @return string
 132+ */
 133+ public function renderShortAuthorDateCitation( WCCitation $citation ) {
 134+ $workTypeEnum = $citation->reference->getWorkType();
 135+
 136+ if ( $workTypeEnum->key == WCSourceTypeEnum::personalCommunication ) {
 137+ $locator = new WCAlternativeSegment(
 138+ array (
 139+ new WCLocatorSegment( $citation, $this->important, WCPropertyEnum::$page ),
 140+ new WCLiteralSegment( $this->personalCommunitation ),
 141+ )
 142+ );
 143+ } else {
 144+ $locator = new WCLocatorSegment( $citation, $this->important, WCPropertyEnum::$page );
 145+ }
 146+
 147+ $cite = new WCGroupSegment(
 148+ array(
 149+ new WCGroupSegment(
 150+ array(
 151+ new WCNamesSegment( $citation, $this->mandatory, WCScopeEnum::$work, WCNameTypeEnum::$author, $this->first, WCCitationLengthEnum::$short, False ),
 152+ new WCDateSegment( $citation, $this->important, WCScopeEnum::$work, WCPropertyEnum::$date, new WCDateParts( WCDateParts::year ), new WCDateOrder( WCDateOrder::littleEndian ), new WCDateForm( WCDateForm::numeric ), new WCDateRange( WCDateRange::range ), '', '' ),
 153+ ), ' '
 154+ ),
 155+ $locator,
 156+ ),
 157+ ', ', # delimiter
 158+ '(', # prefix
 159+ ')' # suffix
 160+ );
 161+
 162+ return array( $cite->render( $this ), $cite );
 163+ }
 164+
 165+
 166+ /**
 167+ * Renders a long inline citation.
 168+ * This citation should omit ending punctuation, and be suitable for
 169+ * inclusion in inline text as part of a larger sentence.
 170+ * @return string
 171+ */
 172+ public function renderLongInlineCitation( WCCitation $citation, $endPunctuation = '' ) {
 173+ return $this->renderLongCitation( $citation, WCCitationTypeEnum::$inline, ', ', $endPunctuation );
 174+ }
 175+
 176+
 177+ /**
 178+ * Composes a long citation for a bibliography
 179+ * By default, this calls renderLongInlineCitation().
 180+ * @return string
 181+ */
 182+ public function renderLongBiblioCitation( WCCitation $citation ) {
 183+ return $this->renderLongCitation( $citation, WCCitationTypeEnum::$biblio, '. ', '.' );
 184+ }
 185+
 186+
 187+ /**
 188+ * Composes a long note citation
 189+ * By default, this calls renderLongInlineCitation().
 190+ * @return string
 191+ */
 192+ public function renderLongNoteCitation( WCCitation $citation ) {
 193+ return $this->renderLongCitation( $citation, WCCitationTypeEnum::$note, ', ', '.' );
 194+ }
 195+
 196+
 197+ /**
 198+ * Composes a long author-date citation
 199+ * By default, this calls renderLongInlineCitation().
 200+ * @return string
 201+ */
 202+ public function renderLongAuthorDateCitation( WCCitation $citation ) {
 203+ return $this->renderLongCitation( $citation, WCCitationTypeEnum::$authorDate, '. ', '.' );
 204+ }
 205+
 206+
 207+ /**
 208+ * Renders a long inline citation.
 209+ * @return string
 210+ */
 211+ protected function renderLongCitation( WCCitation $citation, WCCitationTypeEnum $citationType, $segmentSeparator, $endPunctuation ) {
 212+ switch ( $citation->reference->getWorkType()->key ) {
 213+
 214+ /************************
 215+ * Books and book-like sources
 216+ ************************/
 217+ case WCSourceTypeEnum::general:
 218+
 219+ case WCSourceTypeEnum::book:
 220+ case WCSourceTypeEnum::dictionary:
 221+ case WCSourceTypeEnum::encyclopedia:
 222+ case WCSourceTypeEnum::pamphlet:
 223+ case WCSourceTypeEnum::report:
 224+ switch ( $citationType->key ) {
 225+ case WCCitationTypeEnum::biblio:
 226+ case WCCitationTypeEnum::authorDate:
 227+ $ed2LabelForm = $this->labelFormVerb;
 228+ $ed2Case = $this->capitalizeFirst;
 229+ $nameSort = True;
 230+ break;
 231+ default:
 232+ $ed2LabelForm = $this->labelFormVerbShort;
 233+ $ed2Case = $this->normalCase;
 234+ $nameSort = False;
 235+ }
 236+
 237+ $editorTranslators1 = new WCLabelSegment(
 238+ new WCNamesSegment( $citation, $this->optional, WCScopeEnum::$work, WCNameTypeEnum::$editorTranslator, $this->first, WCCitationLengthEnum::$long, $nameSort, '', '' ),
 239+ $this->after, $this->labelFormShort, $this->normalCase, $this->contextual
 240+ );
 241+ $editors1 = new WCLabelSegment(
 242+ new WCNamesSegment( $citation, $this->optional, WCScopeEnum::$work, WCNameTypeEnum::$editor, $this->first, WCCitationLengthEnum::$long, $nameSort, '', '' ),
 243+ $this->after, $this->labelFormShort, $this->normalCase, $this->contextual
 244+ );
 245+ $translators1 = new WCLabelSegment(
 246+ new WCNamesSegment( $citation, $this->optional, WCScopeEnum::$work, WCNameTypeEnum::$translator, $this->first, WCCitationLengthEnum::$long, $nameSort, '', '' ),
 247+ $this->after, $this->labelFormShort, $this->normalCase, $this->contextual
 248+ );
 249+
 250+ $editorTranslators2 = new WCLabelSegment(
 251+ new WCNamesSegment( $citation, $this->optional, WCScopeEnum::$work, WCNameTypeEnum::$editorTranslator, $this->first, WCCitationLengthEnum::$long, False, '', '' ),
 252+ $this->before, $ed2LabelForm, $ed2Case, new WCLabelPluralEnum( WCLabelPluralEnum::contextual )
 253+ );
 254+ $editors2 = new WCLabelSegment(
 255+ new WCNamesSegment( $citation, $this->optional, WCScopeEnum::$work, WCNameTypeEnum::$editor, $this->first, WCCitationLengthEnum::$long, False, '', '' ),
 256+ $this->before, $ed2LabelForm, $ed2Case, $this->contextual
 257+ );
 258+ $translators2 = new WCLabelSegment(
 259+ new WCNamesSegment( $citation, $this->optional, WCScopeEnum::$work, WCNameTypeEnum::$translator, $this->first, WCCitationLengthEnum::$long, False, '', '' ),
 260+ $this->before, $ed2LabelForm, $ed2Case, $this->contextual
 261+ );
 262+ $date = new WCDateSegment( $citation, $this->important, WCScopeEnum::$work, WCPropertyEnum::$date, new WCDateParts( WCDateParts::year ), new WCDateOrder( WCDateOrder::littleEndian ), new WCDateForm( WCDateForm::numeric ), new WCDateRange( WCDateRange::range ), '', '' );
 263+
 264+ $authorsAndTitles = new WCGroupSegment(
 265+ array(
 266+ new WCAlternativeSegment(
 267+ array (
 268+ new WCNamesSegment( $citation, $this->optional, WCScopeEnum::$work, WCNameTypeEnum::$author, $this->first, WCCitationLengthEnum::$long, $nameSort, '', '' ),
 269+ $editorTranslators1,
 270+ $editors1,
 271+ $translators1,
 272+ )
 273+ ),
 274+ new WCConditionalSegment( $citationType->key == WCCitationTypeEnum::authorDate, $date ),
 275+ new WCTitleSegment( $citation, $this->mandatory, WCScopeEnum::$work, WCPropertyEnum::$title, new WCTitleFormat( WCTitleFormat::italic ), '', '' ),
 276+ $editorTranslators2,
 277+ $editors2,
 278+ $translators2,
 279+ ),
 280+ $segmentSeparator, # delimiter
 281+ '', # prefix
 282+ '' # suffix
 283+ );
 284+ if ( $editorTranslators1->exists() ) $editorTranslators2->cancel();
 285+ if ( $editors1->exists() ) $editors2->cancel();
 286+ if ( $translators1->exists() ) $translators2->cancel();
 287+
 288+ $bookPart = $this->bookPart( $citation, $citationType, $segmentSeparator );
 289+
 290+ switch ( $citationType->key ) {
 291+ case WCCitationTypeEnum::biblio:
 292+ case WCCitationTypeEnum::authorDate:
 293+ $cite = new WCGroupSegment(
 294+ array(
 295+ $authorsAndTitles,
 296+ $bookPart,
 297+ ), '. '
 298+ );
 299+ break;
 300+ default: # note and inline
 301+ $cite = new WCGroupSegment(
 302+ array(
 303+ $authorsAndTitles,
 304+ $bookPart,
 305+ ), ' '
 306+ );
 307+ }
 308+ return array( $cite->render( $this, $endPunctuation ), $cite );
 309+
 310+ case WCSourceTypeEnum::periodical:
 311+ case WCSourceTypeEnum::magazine:
 312+ case WCSourceTypeEnum::newspaper:
 313+ case WCSourceTypeEnum::journal:
 314+
 315+
 316+ case WCSourceTypeEnum::chapter:
 317+ case WCSourceTypeEnum::entry:
 318+
 319+
 320+ /************************
 321+ * Articles
 322+ ************************/
 323+ case WCSourceTypeEnum::article:
 324+ $date = new WCDateSegment( $citation, $this->important, WCScopeEnum::$work, WCPropertyEnum::$date, new WCDateParts( WCDateParts::year ), new WCDateOrder( WCDateOrder::littleEndian ), new WCDateForm( WCDateForm::numeric ), new WCDateRange( WCDateRange::range ), '(', ')' );
 325+ switch ( $citationType->key ) {
 326+ case WCCitationTypeEnum::biblio:
 327+ case WCCitationTypeEnum::authorDate:
 328+ $artPages = new WCLocatorSegment( $citation, $this->important, WCPropertyEnum::$pageRange, '', '' );
 329+ $nameSort = True;
 330+ break;
 331+ default: # This includes WCCitationTypeEnum::note and inline
 332+ $artPages = new WCLocatorSegment( $citation, $this->important, WCPropertyEnum::$page, '', '' );
 333+ $nameSort = False;
 334+ }
 335+ switch( $citation->reference->getSeriesType()->key ) {
 336+ case WCSourceTypeEnum::magazine:
 337+ case WCSourceTypeEnum::newspaper:
 338+ case WCSourceTypeEnum::journal:
 339+ $cite = new WCGroupSegment(
 340+ array(
 341+ new WCNamesSegment( $citation, $this->optional, WCScopeEnum::$work, WCNameTypeEnum::$author, $this->first, WCCitationLengthEnum::$long, $nameSort, '', '' ),
 342+ new WCConditionalSegment( $citationType->key == WCCitationTypeEnum::authorDate, new WCDateSegment( $citation, $this->important, WCScopeEnum::$work, WCPropertyEnum::$date, new WCDateParts( WCDateParts::year ), new WCDateOrder( WCDateOrder::littleEndian ), new WCDateForm( WCDateForm::numeric ), new WCDateRange( WCDateRange::range ), '(', ')' ) ),
 343+ new WCTitleSegment( $citation, $this->mandatory, WCScopeEnum::$work, WCPropertyEnum::$title, new WCTitleFormat( WCTitleFormat::quoted ), '', '' ),
 344+ new WCGroupSegment(
 345+ array(
 346+ new WCGroupSegment(
 347+ array(
 348+ new WCTitleSegment( $citation, $this->mandatory, WCScopeEnum::$series, WCPropertyEnum::$title, new WCTitleFormat( WCTitleFormat::italic ), '', '' ),
 349+ new WCGroupSegment(
 350+ array(
 351+ new WCLocatorSegment( $citation, $this->important, WCPropertyEnum::$volume, '', '' ),
 352+ new WCLabelSegment(
 353+ new WCLocatorSegment( $citation, $this->optional, WCPropertyEnum::$issue, '', '' ),
 354+ $this->before, $this->labelFormShort, $this->normalCase, $this->contextual
 355+ ),
 356+ ), ', ', '', ''
 357+ ),
 358+ new WCConditionalSegment( $citationType->key != WCCitationTypeEnum::authorDate, new WCDateSegment( $citation, $this->important, WCScopeEnum::$work, WCPropertyEnum::$date, new WCDateParts( WCDateParts::year ), new WCDateOrder( WCDateOrder::littleEndian ), new WCDateForm( WCDateForm::numeric ), new WCDateRange( WCDateRange::range ), '(', ')' ) ),
 359+ ), ' ', '', ''
 360+ ),
 361+ $artPages,
 362+ ), ': ', '', ''
 363+ )
 364+ ),
 365+ $segmentSeparator, # delimiter
 366+ '', # prefix
 367+ '' # suffix
 368+ );
 369+ return array( $cite->render( $this, $endPunctuation ), $cite );
 370+ default: #includes magazine, newspaper, and periodical
 371+ $cite = new WCGroupSegment(
 372+ array(
 373+ new WCNamesSegment( $citation, $this->optional, WCScopeEnum::$work, WCNameTypeEnum::$author, $this->first, WCCitationLengthEnum::$long, $nameSort, '', '' ),
 374+ new WCConditionalSegment( $citationType->key == WCCitationTypeEnum::authorDate, new WCDateSegment( $citation, $this->important, WCScopeEnum::$work, WCPropertyEnum::$date, new WCDateParts( WCDateParts::year ), new WCDateOrder( WCDateOrder::littleEndian ), new WCDateForm( WCDateForm::numeric ), new WCDateRange( WCDateRange::range ), '(', ')' ) ),
 375+ new WCTitleSegment( $citation, $this->mandatory, WCScopeEnum::$work, WCPropertyEnum::$title, new WCTitleFormat( WCTitleFormat::quoted ), '', '' ),
 376+ new WCGroupSegment(
 377+ array(
 378+ new WCGroupSegment(
 379+ array(
 380+ new WCTitleSegment( $citation, $this->mandatory, WCScopeEnum::$series, WCPropertyEnum::$title, new WCTitleFormat( WCTitleFormat::italic ), '', '' ),
 381+ new WCGroupSegment(
 382+ array(
 383+ new WCTextSegment( $citation, $this->important, WCScopeEnum::$work, WCPropertyEnum::$place, '(', ')' ),
 384+ new WCDateSegment( $citation, $this->important, WCScopeEnum::$work, WCPropertyEnum::$date, new WCDateParts( WCDateParts::year ), new WCDateOrder( WCDateOrder::littleEndian ), new WCDateForm( WCDateForm::numeric ), new WCDateRange( WCDateRange::range ), '', '' ), # this date should be a full date, or month and day if author-date system.
 385+ ), ' ', '', ''
 386+ ),
 387+ new WCConditionalSegment( $citationType->key != WCCitationTypeEnum::authorDate, new WCDateSegment( $citation, $this->important, WCScopeEnum::$work, WCPropertyEnum::$date, new WCDateParts( WCDateParts::year ), new WCDateOrder( WCDateOrder::littleEndian ), new WCDateForm( WCDateForm::numeric ), new WCDateRange( WCDateRange::range ), '(', ')' ) ),
 388+ ), ' ', '', ''
 389+ ),
 390+ $artPages,
 391+ ), ': ', '', ''
 392+ )
 393+ ),
 394+ $segmentSeparator, # delimiter
 395+ '', # prefix
 396+ '' # suffix
 397+ );
 398+ return array( $cite->render( $this, $endPunctuation ), $cite );
 399+ }
 400+
 401+/* case WCTypeEnum::review:
 402+ case WCTypeEnum::paper:
 403+ case WCTypeEnum::manuscript:
 404+ case WCTypeEnum::musicalScore:
 405+ case WCTypeEnum::conferencePaper:
 406+ case WCTypeEnum::thesis:
 407+ case WCTypeEnum::poem:
 408+ case WCTypeEnum::song:
 409+ case WCTypeEnum::enactment:
 410+ case WCTypeEnum::bill:
 411+ case WCTypeEnum::statute:
 412+ case WCTypeEnum::treaty:
 413+ case WCTypeEnum::rule:
 414+ case WCTypeEnum::regulation:
 415+ case WCTypeEnum::legalDocument:
 416+ case WCTypeEnum::patent:
 417+ case WCTypeEnum::deed:
 418+ case WCTypeEnum::governmentGrant:
 419+ case WCTypeEnum::filing:
 420+ case WCTypeEnum::patentApplication:
 421+ case WCTypeEnum::regulatoryFiling:
 422+ case WCTypeEnum::litigation:
 423+ case WCTypeEnum::legalOpinion:
 424+ case WCTypeEnum::legalCase:
 425+ case WCTypeEnum::graphic:
 426+ case WCTypeEnum::photograph:
 427+ case WCTypeEnum::map:
 428+ case WCTypeEnum::statement:
 429+ case WCTypeEnum::pressRelease:
 430+ case WCTypeEnum::interview:
 431+ case WCTypeEnum::speech:
 432+ case WCTypeEnum::personalCommunication:
 433+ case WCTypeEnum::internetResource:
 434+ case WCTypeEnum::webpage:
 435+ case WCTypeEnum::post:
 436+ case WCTypeEnum::production:
 437+ case WCTypeEnum::motionPicture:
 438+ case WCTypeEnum::recording:
 439+ case WCTypeEnum::play:
 440+ case WCTypeEnum::broadcast:
 441+ case WCTypeEnum::televisionBroadcast:
 442+ case WCTypeEnum::radioBroadcast:
 443+ case WCTypeEnum::internetBroadcast:
 444+ case WCTypeEnum::object:
 445+ case WCTypeEnum::star:
 446+ case WCTypeEnum::gravestone:
 447+ case WCTypeEnum::monument:
 448+ case WCTypeEnum::realProperty:
 449+*/
 450+ }
 451+ }
 452+
 453+
 454+ protected function bookPart( WCCitation $citation, WCCitationTypeEnum $citationType, $segmentSeparator ) {
 455+ # publisher-place: publisher
 456+ $placePublisher = new WCGroupSegment(
 457+ array(
 458+ new WCTextSegment( $citation, $this->important, WCScopeEnum::$work, WCPropertyEnum::$place ),
 459+ new WCNamesSegment( $citation, $this->important, WCScopeEnum::$work, WCNameTypeEnum::$publisher, $this->first, WCCitationLengthEnum::$long, False ),
 460+ ), ': '
 461+ );
 462+ $year = new WCDateSegment( $citation, $this->important, WCScopeEnum::$work, WCPropertyEnum::$date, new WCDateParts( WCDateParts::year ), new WCDateOrder( WCDateOrder::littleEndian ), new WCDateForm( WCDateForm::numeric ), new WCDateRange( WCDateRange::range ) );
 463+
 464+ switch ( $citationType->key ) {
 465+ case WCCitationTypeEnum::biblio: # publisher-place: publisher, year.
 466+ $placePublisherDate = new WCGroupSegment(
 467+ array(
 468+ $placePublisher,
 469+ $year,
 470+ ), ', '
 471+ );
 472+ break;
 473+ case WCCitationTypeEnum::authorDate: # publisher-place: publisher
 474+ $placePublisherDate = $placePublisher;
 475+ break;
 476+ default: # note, inline -- (publisher-place: publisher, year), page
 477+ $placePublisherDate = new WCGroupSegment(
 478+ array(
 479+ new WCGroupSegment(
 480+ array(
 481+ $placePublisher,
 482+ $year,
 483+ ), ', ', '(', ')'
 484+ ),
 485+ new WCLocatorSegment( $citation, $this->important, WCPropertyEnum::$page ),
 486+ ), ', '
 487+ );
 488+ }
 489+ return new WCGroupSegment(
 490+ array(
 491+ $placePublisherDate,
 492+ $this->urlPart( $citation, $citationType, $segmentSeparator ),
 493+ ), $segmentSeparator
 494+ );
 495+ }
 496+
 497+
 498+ protected function urlPart( WCCitation $citation, WCCitationTypeEnum $citationType, $segmentSeparator ) {
 499+ $url = new WCTextSegment( $citation, $this->optional, WCScopeEnum::$work, WCPropertyEnum::$url );
 500+ return new WCConditionalSegment(
 501+ $url->exists(),
 502+ new WCGroupSegment(
 503+ array(
 504+ new WCDateSegment( $citation, $this->optional, WCScopeEnum::$work, WCPropertyEnum::$accessed, new WCDateParts( WCDateParts::yearMonthDay ), new WCDateOrder( WCDateOrder::middleEndian ), new WCDateForm( WCDateForm::long ), new WCDateRange( WCDateRange::range ) ),
 505+ $url,
 506+ ), $segmentSeparator
 507+ )
 508+ );
 509+ }
 510+
 511+
 512+}
Property changes on: trunk/extensions/WikiCitation/styles/WCChicagoStyle.php
___________________________________________________________________
Added: svn:eol-style
1513 + native
Property changes on: trunk/extensions/WikiCitation/styles
___________________________________________________________________
Added: bugtraq:number
2514 + true
Index: trunk/extensions/WikiCitation/WikiCitation.php
@@ -0,0 +1,171 @@
 2+<?php
 3+/**
 4+ * WikiCitation extension for Mediawiki.
 5+ *
 6+ * The extension implements a parser function to create and use citations
 7+ * in various styling standards, such as the Chicago Manual of Style, MLA, APA,
 8+ * Bluebook, etc.
 9+ * A citation has the following Backus-Naur form:
 10+ * @code
 11+ * <citation> ::= "{{#cite:" <data> "}}"
 12+ * <data> ::= <flags> "|" <parameters>
 13+ * | <parameters>
 14+ * <flags> ::= <flag>
 15+ * | <flag> "|" <flags>
 16+ * <parameters> ::= <parameter>
 17+ * | <parameter> "|" <parameters>
 18+ * @endcode
 19+ * The extension also implements the following tag extension (in English):
 20+ * @code
 21+ * <biblio style="..." type="..."></biblio>
 22+ * @endcode
 23+ * where the style and type attributes define the citation style (e.g.
 24+ * Chicago Manual of style) and type (e.g., author-date). Citations within
 25+ * this biblio tag will be sorted alphabetically.
 26+ * For more detailed documentation, see the extension's MediaWiki entry at
 27+ * http://www.mediawiki.org/wiki/Extension:WikiCitation
 28+ *
 29+ * @defgroup WikiCitation
 30+ * @author 'COGDEN' and others
 31+ * @copyright Copyright (c) 2011 by authors
 32+ * @license http://www.gnu.org/copyright/gpl.html
 33+ * This program is free software; you can redistribute it and/or modify
 34+ * it under the terms of the GNU General Public License as published by
 35+ * the Free Software Foundation, either version 2 of the License, or
 36+ * (at your option) any later version.
 37+ * This program is distributed in the hope that it will be useful,
 38+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 39+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 40+ * GNU General Public License for more details.
 41+ * You should have received a copy of the GNU General Public License along
 42+ * with this program; if not, write to the Free Software Foundation, Inc.,
 43+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 44+ * See http://www.gnu.org/copyright/gpl.html
 45+ */
 46+
 47+/**
 48+ * Setup file for WikiCitation extension.
 49+ *
 50+ * @file
 51+ */
 52+
 53+
 54+if ( !defined( 'MEDIAWIKI' ) ) {
 55+ echo( "Not a valid entry point.\n" );
 56+ die( 1 );
 57+}
 58+
 59+
 60+$wgExtensionCredits[ 'parserhook' ][] = array(
 61+ 'path' => __FILE__,
 62+ 'name' => 'WikiCitation',
 63+ 'author' => array( 'COGDEN' ),
 64+ 'url' => 'http://www.mediawiki.org/wiki/Extension:WikiCitation',
 65+ 'descriptionmsg' => 'wc-description',
 66+ 'version' => '0.8.1'
 67+);
 68+
 69+
 70+/**
 71+ * Global settings
 72+ */
 73+$wikiCitationValidateArguments = False;
 74+
 75+$mDir = dirname(__FILE__);
 76+
 77+/**
 78+ * Array for defining allowable referencing styles, and setting a default.
 79+ *
 80+ * Array of recognized children of WCCitation, keyed to magic words used to
 81+ * invoke that style. For example, the magic word 'wcChicago'
 82+ * ('Chicago' in English) is keyed to the class 'WCChicagoCitation'
 83+ *
 84+ * To disallow particular styles, comment them out or remove them from this
 85+ * list.
 86+ * @var
 87+ */
 88+$wgWCCitationStyles = array(
 89+ 'wc_default' => 'WCChicagoStyle', # default style is defined here
 90+ 'wc_Chicago' => 'WCChicagoStyle',
 91+ 'wc_Bluebook' => 'WCBluebookStyle',
 92+);
 93+
 94+# Styles
 95+$wgAutoloadClasses['WCChicagoStyle'] = $mDir . '/styles/WCChicagoStyle.php';
 96+$wgAutoloadClasses['WCBluebookStyle'] = $mDir . '/styles/WCBluebookStyle.php';
 97+
 98+
 99+/**
 100+ * Localization files
 101+ */
 102+$wgExtensionMessagesFiles['WikiCitation'] = $mDir . '/WikiCitation.i18n.php';
 103+$wgExtensionMessagesFiles['WikiCitationMagic'] = $mDir . '/WikiCitation.i18n.magic.php';
 104+
 105+/**
 106+ * Autoload classes
 107+ */
 108+# main directory
 109+$wgAutoloadClasses['WikiCitation'] = $mDir . '/WikiCitation.body.php';
 110+
 111+# includes
 112+$wgAutoloadClasses['WCArgumentReader'] = $mDir . '/includes/WCArgumentReader.php';
 113+$wgAutoloadClasses['WCArticle'] = $mDir . '/includes/WCArticle.php';
 114+$wgAutoloadClasses['WCBibliography'] = $mDir . '/includes/WCBibliography.php';
 115+$wgAutoloadClasses['WCCitation'] = $mDir . '/includes/WCCitation.php';
 116+ $wgAutoloadClasses['WCCitationPosition'] = $mDir . '/includes/WCCitation.php';
 117+$wgAutoloadClasses['WCEnum'] = $mDir . '/includes/WCEnum.php';
 118+$wgAutoloadClasses['WCException'] = $mDir . '/includes/WCException.php';
 119+$wgAutoloadClasses['WCNote'] = $mDir . '/includes/WCNote.php';
 120+$wgAutoloadClasses['WCReference'] = $mDir . '/includes/WCReference.php';
 121+$wgAutoloadClasses['WCReferenceStore'] = $mDir . '/includes/WCReferenceStore.php';
 122+$wgAutoloadClasses['WCSection'] = $mDir . '/includes/WCSection.php';
 123+$wgAutoloadClasses['WCStyle'] = $mDir . '/includes/WCStyle.php';
 124+
 125+# data
 126+$wgAutoloadClasses['WCData'] = $mDir . '/includes/data/WCData.php';
 127+$wgAutoloadClasses['WCDate'] = $mDir . '/includes/data/WCDate.php';
 128+$wgAutoloadClasses['WCLocator'] = $mDir . '/includes/data/WCLocator.php';
 129+$wgAutoloadClasses['WCName'] = $mDir . '/includes/data/WCName.php';
 130+$wgAutoloadClasses['WCNames'] = $mDir . '/includes/data/WCNames.php';
 131+$wgAutoloadClasses['WCTypeData'] = $mDir . '/includes/data/WCTypeData.php';
 132+$wgAutoloadClasses['WCText'] = $mDir . '/includes/data/WCText.php';
 133+$wgAutoloadClasses['WCTitle'] = $mDir . '/includes/data/WCTitle.php';
 134+$wgAutoloadClasses['WCTitleFormat'] = $mDir . '/includes/data/WCTitle.php';
 135+
 136+# parameters
 137+$wgAutoloadClasses['WCAttributeEnum'] = $mDir . '/includes/parameters/WCAttributeEnum.php';
 138+$wgAutoloadClasses['WCCitationLengthEnum'] = $mDir . '/includes/parameters/WCCitationLengthEnum.php';
 139+$wgAutoloadClasses['WCCitationTypeEnum'] = $mDir . '/includes/parameters/WCCitationTypeEnum.php';
 140+$wgAutoloadClasses['WCDateTermsEnum'] = $mDir . '/includes/parameters/WCDateTermsEnum.php';
 141+$wgAutoloadClasses['WCNamePartEnum'] = $mDir . '/includes/parameters/WCNamePartEnum.php';
 142+$wgAutoloadClasses['WCNameTypeEnum'] = $mDir . '/includes/parameters/WCNameTypeEnum.php';
 143+$wgAutoloadClasses['WCParameterEnum'] = $mDir . '/includes/parameters/WCParameterEnum.php';
 144+$wgAutoloadClasses['WCPropertyEnum'] = $mDir . '/includes/parameters/WCPropertyEnum.php';
 145+$wgAutoloadClasses['WCScopeEnum'] = $mDir . '/includes/parameters/WCScopeEnum.php';
 146+$wgAutoloadClasses['WCSourceTypeEnum'] = $mDir . '/includes/parameters/WCSourceTypeEnum.php';
 147+
 148+# segments
 149+$wgAutoloadClasses['WCAlternativeSegment'] = $mDir . '/includes/segments/WCAlternativeSegment.php';
 150+$wgAutoloadClasses['WCConditionalSegment'] = $mDir . '/includes/segments/WCConditionalSegment.php';
 151+$wgAutoloadClasses['WCDataSegment'] = $mDir . '/includes/segments/WCDataSegment.php';
 152+$wgAutoloadClasses['WCDateSegment'] = $mDir . '/includes/segments/WCDateSegment.php';
 153+$wgAutoloadClasses['WCGroupSegment'] = $mDir . '/includes/segments/WCGroupSegment.php';
 154+$wgAutoloadClasses['WCLabelFormEnum'] = $mDir . '/includes/segments/WCLabelSegment.php';
 155+$wgAutoloadClasses['WCLabelSegment'] = $mDir . '/includes/segments/WCLabelSegment.php';
 156+$wgAutoloadClasses['WCLiteralSegment'] = $mDir . '/includes/segments/WCLiteralSegment.php';
 157+$wgAutoloadClasses['WCLocatorSegment'] = $mDir . '/includes/segments/WCLocatorSegment.php';
 158+$wgAutoloadClasses['WCNamesSegment'] = $mDir . '/includes/segments/WCNamesSegment.php';
 159+$wgAutoloadClasses['WCSegment'] = $mDir . '/includes/segments/WCSegment.php';
 160+$wgAutoloadClasses['WCTextSegment'] = $mDir . '/includes/segments/WCTextSegment.php';
 161+$wgAutoloadClasses['WCTitleSegment'] = $mDir . '/includes/segments/WCTitleSegment.php';
 162+$wgAutoloadClasses['WCWrapperSegment'] = $mDir . '/includes/segments/WCWrapperSegment.php';
 163+
 164+# Set up parser hooks
 165+$wgHooks[ 'ParserFirstCallInit' ][] = 'WikiCitation::onParserFirstCallInit';
 166+$wgHooks[ 'ParserClearState' ][] = 'WikiCitation::onParserClearState';
 167+$wgHooks[ 'ParserBeforeTidy' ][] = 'WikiCitation::onParserBeforeTidy';
 168+
 169+# Location of the CSS style sheet for this extension
 170+$wgWCStyleSheet = $wgScriptPath . '/extensions/WikiCitation/WikiCitation.css';
 171+
 172+#$wgParserTestFiles[] = $mDir . "/WikiCitationTests.txt";
Property changes on: trunk/extensions/WikiCitation/WikiCitation.php
___________________________________________________________________
Added: svn:eol-style
1173 + native
Index: trunk/extensions/WikiCitation/WikiCitation.css
@@ -0,0 +1,93 @@
 2+/**
 3+ * CSS for the WikiCitation extension.
 4+ *
 5+ * @ingroup WikiCitation
 6+ * @file
 7+ */
 8+
 9+/**
 10+ * CSS definitions for citations.
 11+ * these terms are defined as constants in the class WCStyle
 12+ */
 13+
 14+.citation .error,
 15+.citation.error {
 16+ font-size: smaller;
 17+ font-weight: bold;
 18+ color: red;
 19+}
 20+
 21+.citation cite,
 22+.citation cite.quoted {
 23+ font-style: normal;
 24+}
 25+
 26+.citation cite.italic {
 27+ font-style: italic;
 28+}
 29+
 30+.citation .name {
 31+}
 32+
 33+.citation .name .surname {
 34+}
 35+
 36+.citation .name .sortorder {
 37+}
 38+
 39+/* CSS3. Breaks long urls, etc., rather than overflowing box */
 40+.citation {
 41+ word-wrap: break-word;
 42+}
 43+
 44+/* Hides test that should be shown in interactive media, but not in print */
 45+@media screen, handheld {
 46+ .citation *.printonly {
 47+ display: none;
 48+ }
 49+}
 50+
 51+sup.notesuperscript {
 52+ vertical-align: super;
 53+ font-size: .83em;
 54+ white-space: nowrap;
 55+ font-weight: normal;
 56+ font-style: normal;
 57+}
 58+
 59+sup.notesuperscript a:visited {
 60+ color: inherit;
 61+}
 62+
 63+sup.notesuperscript a:hover,
 64+sup.notesuperscript:target { /* target is CSS3 */
 65+ background-color: #DEF;
 66+ text-decoration: none;
 67+}
 68+
 69+ol.endnotes {
 70+ list-style-type: none;
 71+ padding-left: 0em;
 72+ margin-left: 0em;
 73+}
 74+
 75+ol.endnotes li {
 76+ padding-left: 0em;
 77+ margin-left: 0em;
 78+ text-indent: 2em;
 79+}
 80+
 81+/* CSS3. Highlight clicked reference in blue to help navigation */
 82+ol.endnotes li:target {
 83+ background-color: #DEF;
 84+}
 85+
 86+ol.endnotes li a.notenumber:visited {
 87+ color: inherit;
 88+}
 89+
 90+/* Hanging indent for bibliography entries */
 91+ul.bibliography li {
 92+ text-indent: -2em;
 93+ padding-left: 2em;
 94+}
\ No newline at end of file
Property changes on: trunk/extensions/WikiCitation/WikiCitation.css
___________________________________________________________________
Added: svn:eol-style
195 + native
Index: trunk/extensions/WikiCitation/includes/WCStyle.php
@@ -0,0 +1,506 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+class WCSegmentImportance extends WCEnum {
 11+ const mandatory = 0; # The segment must be present, and if not, will show a visible blank.
 12+ const important = 1; # The segment should be present, but will be omitted if it cannot be inferred.
 13+ const optional = 2; # The segment is optional. If not present, it will not be inferred.
 14+ const __default = self::mandatory;
 15+}
 16+
 17+
 18+class WCTextCaseEnum extends WCEnum {
 19+ const normal = 0;
 20+ const lowercase = 1;
 21+ const uppercase = 2;
 22+ const capitalizeFirst = 3;
 23+ const capitalizeAll = 4;
 24+ const title = 5;
 25+ const __default = self::normal;
 26+}
 27+
 28+
 29+/**
 30+ * An abstract class providing some of the functionality of its
 31+ * child referencing styles.
 32+ *
 33+ * @abstract
 34+ */
 35+abstract class WCStyle {
 36+
 37+ /**
 38+ * Constants
 39+ */
 40+ const citationHTML = 'citation'; # HTML class for a citation as a whole
 41+ const errorHTML = 'error'; # class for validation errors in citation template
 42+ const italicTitleHTML = 'italic'; # class for italic titles
 43+ const quotedTitleHTML = 'quoted'; # class for quoted titles
 44+ const nameHTML = 'name'; # class for names
 45+ const surnameHTML = 'surname'; # class for surnames
 46+ const surnameSortOrderHTML = 'sortorder'; # class for surnames in sort order
 47+
 48+ /**
 49+ * General style variables.
 50+ */
 51+ # HTML class (must be redefined by children)
 52+ public $styleHTML = ''; # class representing the citation style--children should redefine
 53+
 54+ # citation separators and punctuation
 55+ public $segmentMissing; # blank to indicate missing segment
 56+ public $rangeDelimiter; # delimiter for ranges
 57+
 58+ # Labels
 59+ public $nameLabels, $propertyLabels, $circaLabels;
 60+
 61+ /**
 62+ * Title style variables.
 63+ */
 64+ # switch
 65+ public $punctuationInQuotes = False; # whether punctuation such as commas or periods is inside quotes, or outside
 66+ public $replaceAmpersands = False; # whether ampersand ("&") is replaced with "and"
 67+ public $eraWithoutPunctuation = False; # whether the era is written as AD, BC, BCE, etc. rather than A.D., etc.
 68+ public $eraNoSpace = False; # whether there is a space between the year and the era
 69+ public $eraBeforeYear = False; # whether the era appears before or after the year
 70+
 71+
 72+ # citation separators and punctuation
 73+ public $iExQuote; # initial exterior quote symbol
 74+ public $fExQuote; # final exterior quote symbol
 75+ public $iInQuote; # initial interior quote symbol
 76+ public $fInQuote; # final interior quote symbol
 77+
 78+ /**
 79+ * Date style variables.
 80+ */
 81+ # flags
 82+ public $stripMonthPeriods; # boolean; e.g. Jan or Feb
 83+
 84+ # citation text, separators, and punctuation
 85+ public $ad, $adNoPunct; # AD
 86+ public $ce, $ceNoPunct; # CE
 87+ public $bc, $bcNoPunct; # BC
 88+ public $bce, $bceNoPunct; # BCE
 89+
 90+ # literal text
 91+ public $personalCommunication;
 92+
 93+ /**
 94+ * Name style variables
 95+ */
 96+ # name formatting flag
 97+ public $demoteNonDroppingParticle;
 98+
 99+ # formatting strings:
 100+ public $nameWhitespace; # whitespace between name name parts
 101+ public $sortOrderDelimiter; # punctuation between name name parts in name-sort mode
 102+ public $missingName; # blank to represent a missing name
 103+ public $sortOrderSurnameDelimiter; # punctuation after surname in name-sort mode
 104+ public $nameSuffixDelimiter; # delimiter before name suffix
 105+
 106+ /**
 107+ * Names style variables
 108+ */
 109+ # name formatting flags
 110+ public $etAlMin; # when names exceeds this value, 'et al.' is used...
 111+ public $etAlUseFirst; # ...and the number of names is dropped to this number.
 112+ public $etAlSubsequentMin; # same as $etAlMin, except applies in later cites referencing earlier cites
 113+ public $etAlSubsequentUseFirst; # same as $etAlUseFirst, except applies in later cites referencing earlier cites
 114+
 115+ # name formatting delimiters and punctuation:
 116+ public $namesDelimiter; # the normal punctuation between names
 117+ public $etAlDelimiter; # the punctuation before "et al." or equivalent
 118+ public $and2; # the delimiter between two names if there are only two
 119+ public $and3; # the last delimiter for three or more names
 120+ public $etAl; # "and others"
 121+
 122+ /**
 123+ * Convenience variables
 124+ */
 125+ protected $mandatory, $important, $optional;
 126+ protected $normalCase, $lowercase, $uppercase, $capitalizeFirst, $capitalizeAll, $titleCase;
 127+ protected $labelFormNone, $labelFormLong, $labelFormVerb, $labelFormShort, $labelFormVerbShort, $labelFormSymbol;
 128+ protected $singular, $plural;
 129+ protected $contextual, $alwaysPlural, $neverPlural;
 130+ protected $before, $after;
 131+
 132+
 133+ /**
 134+ * Constructor.
 135+ */
 136+ public function __construct() {
 137+
 138+ # Convenience variables
 139+ $this->mandatory = new WCSegmentImportance( WCSegmentImportance::mandatory );
 140+ $this->important = new WCSegmentImportance( WCSegmentImportance::important );
 141+ $this->optional = new WCSegmentImportance( WCSegmentImportance::optional );
 142+ $this->first = new WCCitationPosition( WCCitationPosition::first );
 143+ $this->subsequent = new WCCitationPosition( WCCitationPosition::subsequent );
 144+ $this->normalCase = new WCTextCaseEnum( WCTextCaseEnum::normal );
 145+ $this->lowercase = new WCTextCaseEnum( WCTextCaseEnum::lowercase );
 146+ $this->uppercase = new WCTextCaseEnum( WCTextCaseEnum::uppercase );
 147+ $this->capitalizeFirst = new WCTextCaseEnum( WCTextCaseEnum::capitalizeFirst );
 148+ $this->capitalizeAll = new WCTextCaseEnum( WCTextCaseEnum::capitalizeAll );
 149+ $this->titleCase = new WCTextCaseEnum( WCTextCaseEnum::title );
 150+ $this->labelFormNone = new WCLabelFormEnum( WCLabelFormEnum::none );
 151+ $this->labelFormLong = new WCLabelFormEnum( WCLabelFormEnum::long );
 152+ $this->labelFormVerb = new WCLabelFormEnum( WCLabelFormEnum::verb );
 153+ $this->labelFormShort = new WCLabelFormEnum( WCLabelFormEnum::short );
 154+ $this->labelFormVerbShort = new WCLabelFormEnum( WCLabelFormEnum::verbShort );
 155+ $this->labelFormSymbol = new WCLabelFormEnum( WCLabelFormEnum::symbol );
 156+ $this->singular = new WCPluralEnum( WCPluralEnum::singular );
 157+ $this->plural = new WCPluralEnum( WCPluralEnum::plural );
 158+ $this->contextual = new WCLabelPluralEnum( WCLabelPluralEnum::contextual );
 159+ $this->alwaysPlural = new WCLabelPluralEnum( WCLabelPluralEnum::always );
 160+ $this->neverPlural = new WCLabelPluralEnum( WCLabelPluralEnum::never );
 161+ $this->before = new WCRelativePositionEnum( WCRelativePositionEnum::before );
 162+ $this->after = new WCRelativePositionEnum( WCRelativePositionEnum::after );
 163+
 164+
 165+ # General style variables.
 166+ $this->biblioSegSep = wfMsg( 'wc-biblio-segment-separator' );
 167+ $this->noteSegSep = wfMsg( 'wc-note-segment-separator' );
 168+ $this->inlineSegSep = wfMsg( 'wc-inline-segment-separator' );
 169+ $this->biblioEndPunct = wfMsg( 'wc-biblio-segment-end-punct' );
 170+ $this->noteEndPunct = wfMsg( 'wc-note-segment-end-punct' );
 171+ $this->segmentMissing = wfMsg( 'wc-segment-missing' );
 172+ $this->rangeDelimiter = wfMsg( 'wc-range-delimiter' );
 173+
 174+ # Labels.
 175+ $this->nameLabels = array();
 176+ foreach( array(
 177+ WCNameTypeEnum::author => 'author',
 178+ WCNameTypeEnum::publisher => 'publisher',
 179+ WCNameTypeEnum::editorTranslator => 'editor-translator',
 180+ WCNameTypeEnum::editor => 'editor',
 181+ WCNameTypeEnum::translator => 'translator',
 182+ WCNameTypeEnum::interviewer => 'interviewer',
 183+ WCNameTypeEnum::recipient => 'recipient',
 184+ WCNameTypeEnum::composer => 'composer',
 185+ ) as $key => $name ) {
 186+ foreach ( array(
 187+ WCLabelFormEnum::long => 'long',
 188+ WCLabelFormEnum::verb => 'verb',
 189+ WCLabelFormEnum::short => 'short',
 190+ WCLabelFormEnum::verbShort => 'verb-short',
 191+ WCLabelFormEnum::symbol => 'symbol',
 192+ ) as $form => $formText ) {
 193+ foreach ( array(
 194+ WCPluralEnum::singular => 'singular',
 195+ WCPluralEnum::plural => 'plural',
 196+ ) as $num => $numText ) {
 197+ $this->nameLabels[ $key ][ $form ][ $num ] = wfMsg( 'wc-' . $name . '-' . $formText . '-' . $numText );
 198+ }
 199+ }
 200+ }
 201+ $this->propertyLabels = array();
 202+ foreach( array(
 203+ WCPropertyEnum::page => 'page',
 204+ WCPropertyEnum::section => 'section',
 205+ WCPropertyEnum::paragraph => 'paragraph',
 206+ WCPropertyEnum::volume => 'volume',
 207+ WCPropertyEnum::issue => 'issue',
 208+ ) as $key => $name ) {
 209+ foreach ( array(
 210+ WCLabelFormEnum::long => 'long',
 211+ WCLabelFormEnum::verb => 'verb',
 212+ WCLabelFormEnum::short => 'short',
 213+ WCLabelFormEnum::verbShort => 'verb-short',
 214+ WCLabelFormEnum::symbol => 'symbol',
 215+ ) as $form => $formText ) {
 216+ foreach ( array(
 217+ WCPluralEnum::singular => 'singular',
 218+ WCPluralEnum::plural => 'plural',
 219+ ) as $num => $numText ) {
 220+ $this->propertyLabels[ $key ][ $form ][ $num ] = wfMsg( 'wc-' . $name . '-' . $formText . '-' . $numText );
 221+ }
 222+ }
 223+ }
 224+ $this->circaLabels = array();
 225+ foreach ( array(
 226+ WCLabelFormEnum::long => 'long',
 227+ WCLabelFormEnum::verb => 'verb',
 228+ WCLabelFormEnum::short => 'short',
 229+ WCLabelFormEnum::verbShort => 'verb-short',
 230+ WCLabelFormEnum::symbol => 'symbol',
 231+ ) as $form => $formText ) {
 232+ foreach ( array(
 233+ WCPluralEnum::singular => 'singular',
 234+ WCPluralEnum::plural => 'plural',
 235+ ) as $num => $numText ) {
 236+ $this->dateTermLabels[ $key ][ $form ][ $num ] = wfMsg( 'wc-circa-' . $formText . '-' . $numText );
 237+ }
 238+ }
 239+
 240+ # Title style variables.
 241+ $this->iExQuote = wfMsg( 'wc-initial-exterior-quote' );
 242+ $this->fExQuote = wfMsg( 'wc-final-exterior-quote' );
 243+ $this->iInQuote = wfMsg( 'wc-initial-interior-quote' );
 244+ $this->fInQuote = wfMsg( 'wc-final-interior-quote' );
 245+
 246+ # Date style variables.
 247+ $this->stripMonthPeriods = False;
 248+ $this->monthDayYear = True; # Whether month-day-year is preferred over day-month-year
 249+ $this->ad = wfMsg( 'wc-ad' );
 250+ $this->adNoPunct = wfMsg( 'wc-ad-no-punct' );
 251+ $this->ce = wfMsg( 'wc-ce' );
 252+ $this->ceNoPunct = wfMsg( 'wc-ce-no-punct' );
 253+ $this->bc = wfMsg( 'wc-bc' );
 254+ $this->bcNoPunct = wfMsg( 'wc-bc-no-punct' );
 255+ $this->bce = wfMsg( 'wc-bce' );
 256+ $this->bceNoPunct = wfMsg( 'wc-bce-no-punct' );
 257+
 258+ $this->spring = wfMsg( 'wc_spring' );
 259+ $this->summer = wfMsg( 'wc_summer' );
 260+ $this->autumn = wfMsg( 'wc_autumn' );
 261+ $this->winter = wfMsg( 'wc_winter' );
 262+ $this->year = wfMsg( 'wc_year' );
 263+ $this->month = wfMsg( 'wc_month' );
 264+ $this->day = wfMsg( 'wc_day' );
 265+
 266+ # Literal text
 267+ $this->personalCommunitation = wfMsg( 'wc-personal-communication' );
 268+
 269+ # Name style variables.
 270+ $this->demoteNonDroppingParticle = False;
 271+ $this->nameWhitespace = wfMsg( 'wc-name-whitespace' );
 272+ $this->sortOrderDelimiter = wfMsg( 'wc-name-sort-order-delimiter' );
 273+ $this->missingName = wfMsg( 'wc-name-missing' );
 274+ $this->sortOrderSurnameDelimiter = wfMsg( 'wc-surname-delimiter' );
 275+ $this->nameSuffixDelimiter = wfMsg( 'wc-name-suffix-delimiter' );
 276+
 277+ # Names style variables.
 278+ $this->etAlMin = 3;
 279+ $this->etAlUseFirst = 1;
 280+ $this->etAlSubsequentMin = 3;
 281+ $this->etAlSubsequentUseFirst = 1;
 282+ $this->namesDelimiter = wfMsg( 'wc-names-delim' );
 283+ $this->etAlDelimiter = wfMsg( 'wc-names-et-al-delim' );
 284+ $this->and2 = wfMsg( 'wc-names-and-2' );
 285+ $this->and3 = wfMsg( 'wc-names-and-3' );
 286+ $this->etAl = wfMsg( 'wc-names-and-others' );
 287+ }
 288+
 289+
 290+ /**
 291+ * Composes a short citation for in-text use.
 292+ * The resulting citation should omit closing punctuation, and be suitable
 293+ * for inclusion as part of a larger sentence.
 294+ * @abstract
 295+ * @return string
 296+ */
 297+ abstract public function renderShortInlineCitation( WCCitation $citation );
 298+
 299+
 300+ /**
 301+ * Composes a short citation for use in a footnote or endnote.
 302+ * The resulting citation should include closing sentence punctuation.
 303+ * @abstract
 304+ * @return string
 305+ */
 306+ abstract public function renderShortNoteCitation( WCCitation $citation );
 307+
 308+
 309+ /**
 310+ * Composes a short citation for use in an author-date system.
 311+ * The resulting citation should omit closing sentence punctuation.
 312+ * @abstract
 313+ * @return string
 314+ */
 315+ abstract public function renderShortAuthorDateCitation( WCCitation $citation );
 316+
 317+
 318+ /**
 319+ * Composes a long inline citation.
 320+ * This citation should omit ending punctuation, and be suitable for
 321+ * inclusion in inline text as part of a larger sentence.
 322+ * @abstract
 323+ * @return string
 324+ */
 325+ abstract public function renderLongInlineCitation( WCCitation $citation );
 326+
 327+
 328+ /**
 329+ * Composes a long citation for a bibliography
 330+ * @abstract
 331+ * @return string
 332+ */
 333+ abstract public function renderLongBiblioCitation( WCCitation $citation );
 334+
 335+
 336+ /**
 337+ * Composes a long note citation
 338+ * @abstract
 339+ * @return string
 340+ */
 341+ abstract public function renderLongNoteCitation( WCCitation $citation );
 342+
 343+
 344+ /**
 345+ * Composes a long author-date citation
 346+ * @abstract
 347+ * @return string
 348+ */
 349+ abstract public function renderLongAuthorDateCitation( WCCitation $citation );
 350+
 351+
 352+ /**
 353+ * Create a wikilink. If no article, the function returns the $title.
 354+ *
 355+ * @param string $article = the wikipedia article name
 356+ * @param string $text = text for the link
 357+ * @param string $classes = the HTML classes.
 358+ * @return string $text if no $article, otherwise wrap $text in anchor
 359+ */
 360+ public static function makeWikiLink( $article, $text, $classes = '' ) {
 361+ if ( $article ) {
 362+ $title = Title::newFromText( $article );
 363+ $attribs = array( 'class' => $classes );
 364+ global $wgVersion;
 365+ if ( version_compare( $wgVersion, '1.18', '<' ) ) {
 366+ global $wgUser;
 367+ return $wgUser->getSkin()->link( $title, $text, $attribs );
 368+ } else {
 369+ return Linker::link( $title, $text, $attribs );
 370+ }
 371+ } elseif ( $classes ) {
 372+ return self::wrapHTMLSpan( $text, $classes );
 373+ } else {
 374+ return $text;
 375+ }
 376+ }
 377+
 378+
 379+ /**
 380+ * Wrap text in an HTML span element.
 381+ * @param string $text
 382+ * @param string $htmlClasses
 383+ * @return string
 384+ */
 385+ public static function wrapHTMLSpan( $text, $htmlClasses ) {
 386+ return '<span class="' . $htmlClasses . '">' . $text . '</span>';
 387+ }
 388+
 389+
 390+ /**
 391+ * Stylize text as a quotation.
 392+ *
 393+ * Eventually, literal quoting might be replaced by html <q> tags, which
 394+ * are already localized and are more accessible. When browser
 395+ * compatibility increases, this function will simply wrap the text in
 396+ * <q>..</q> tags.
 397+ *
 398+ * @param string $text
 399+ * @return string
 400+ */
 401+ public function quote( $text ) {
 402+ return $this->iExQuote . $text . $this->fExQuote;
 403+ }
 404+
 405+ /**
 406+ * Perform any text transformations of a title that a style may require.
 407+ * @param string $title
 408+ * @return string
 409+ */
 410+ public function transformTitle( $title ) {
 411+ if ( $this->replaceAmpersands ) {
 412+ $title = str_replace( ' &amp; ', ' and ', $title );
 413+ }
 414+ #$title = $wgContLang->ucwords( $title );
 415+ /*
 416+ * The following are not capitalized:
 417+ * both definite and indefinite articles
 418+ * prepositions
 419+ * coordinating conjunctions
 420+ * to when used in infinitives
 421+ * In foreign languages, capitalization follows foreign practice.
 422+ * After hypen, capitalize if it is a noun, proper adjective, or it has
 423+ * equal force with the first word.
 424+ */
 425+ return $title;
 426+ }
 427+
 428+
 429+ /**
 430+ * Convert semantic quotes to localized character-based quotes.
 431+ * When old browsers die, at some point this method will not be necessary,
 432+ * because the browser should do this conversion itself.
 433+ *
 434+ * @param string $text
 435+ * @param boolean $internal
 436+ * @return string
 437+ */
 438+ public function convertSemanticToCharacterQuotes( $text, $internal = False ) {
 439+ if( ! $text ) return '';
 440+
 441+ $openPos = mb_stripos( $text, '<q>');
 442+ $closePos = mb_stripos( $text, '</q>');
 443+ if ( is_int( $openPos ) ) {
 444+ if ( is_int( $closePos ) && $closePos < $openPos ) {
 445+ # Next quote is a close quote.
 446+ $head = mb_substr( $text, 0, $closePos );
 447+ $tail = mb_substr( $text, $closePos + 4 );
 448+ $quote = $internal ? $this->fExQuote : $this->fInQuote;
 449+ return $head . $quote . $this->convertSemanticToCharacterQuotes( $tail, ! $internal );
 450+ } else {
 451+ # Next quote is an open quote.
 452+ $head = mb_substr( $text, 0, $openPos );
 453+ $tail = mb_substr( $text, $openPos + 3 );
 454+ $quote = $internal ? $this->iInQuote : $this->iExQuote;
 455+ return $head . $quote . $this->convertSemanticToCharacterQuotes( $tail, ! $internal );
 456+ }
 457+ } elseif ( is_int( $closePos ) ) {
 458+ # Next quote is a close quote.
 459+ $head = mb_substr( $text, 0, $closePos );
 460+ $tail = mb_substr( $text, $closePos + 4 );
 461+ $quote = $internal ? $this->fExQuote : $this->fInQuote;
 462+ return $head . $quote . $this->convertSemanticToCharacterQuotes( $tail, ! $internal );
 463+ } else {
 464+ # No more quotes.
 465+ return $text;
 466+ }
 467+ }
 468+
 469+
 470+ public function capitalize( $text, WCTextCaseEnum $case ) {
 471+ switch ( $case->key ) {
 472+ case WCTextCaseEnum::normal:
 473+ return $text;
 474+
 475+ case WCTextCaseEnum::lowercase:
 476+ return mb_strtolower( $text );
 477+
 478+ case WCTextCaseEnum::uppercase:
 479+ return mb_strtoupper( $text );
 480+
 481+ case WCTextCaseEnum::capitalizeFirst:
 482+ return mb_strtoupper( mb_substr( $text, 0, 1 ) ) . mb_substr( $text, 1 );
 483+
 484+ case WCTextCaseEnum::capitalizeAll: # capitalize every first letter
 485+ $arr = preg_split('/u', $text, -1, PREG_SPLIT_NO_EMPTY);
 486+ $result = '';
 487+ $mode = false;
 488+ foreach ($arr as $char) {
 489+ $res = preg_match( '/\p{Mn}|\p{Me}|\p{Cf}|\p{Lm}|\p{Sk}|\p{Lu}|\p{Ll}|\p{Lt}|\p{Sk}|\p{Cs}/uS', $char ) == 1;
 490+ if ($mode) {
 491+ if (!$res)
 492+ $mode = false;
 493+ } elseif ($res) {
 494+ $mode = true;
 495+ $char = mb_strtoupper( $char );
 496+ }
 497+ $result .= $char;
 498+ }
 499+ return $result;
 500+
 501+ case WCTextCaseEnum::title:
 502+ # This is not implemented yet.
 503+ return mb_strtoupper( mb_substr( $text, 0, 1 ) ) . mb_substr( $text, 1 );
 504+ }
 505+ }
 506+
 507+}
\ No newline at end of file
Property changes on: trunk/extensions/WikiCitation/includes/WCStyle.php
___________________________________________________________________
Added: svn:eol-style
1508 + native
Index: trunk/extensions/WikiCitation/includes/WCArticle.php
@@ -0,0 +1,286 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * Represents a page with citations.
 13+ */
 14+class WCArticle implements Countable {
 15+
 16+ /**
 17+ * Constants
 18+ */
 19+ const defaultStyleID = 'wc_default'; # magic word for default citation style:
 20+ const noteMarkerHTML = 'notemarker'; # HTML class for the note marker
 21+ const endnotesHTML = 'endnotes'; # HTML class for endnotes list
 22+ const noteNumberHTML = 'notenumber'; # HTML class for the note number
 23+
 24+ public static $defaultStyle;
 25+
 26+ /**
 27+ * Style objects.
 28+ * These are created as needed, and then kept in memory.
 29+ * @var array Array in the form of string class name => WCStyle object.
 30+ */
 31+ protected static $styleObjects = array();
 32+
 33+ /**
 34+ * Database of unique references.
 35+ * @var WCReferenceStore
 36+ */
 37+ protected $referenceStore;
 38+
 39+ /**
 40+ * Arrays keyed to the citation key.
 41+ * These represent a master database of all citations in the article.
 42+ * @var array
 43+ */
 44+ public $citations = array();
 45+ public $styles = array();
 46+ public $citationTypes = array(), $citationLengths = array();
 47+
 48+ protected $currentDefaultStyle;
 49+
 50+ protected $bibliography;
 51+
 52+ protected $bibliographyLevel = 0, $noteLevel = 0;
 53+
 54+ /**
 55+ * Stack containing note text and markers
 56+ * @var array = ( level => ( note number => note text ) )
 57+ */
 58+ protected $sectionStack;
 59+
 60+ protected $sectionStackPointer = 0;
 61+
 62+ /**
 63+ * Keeps a running count fo the number of $citations.
 64+ * @var int
 65+ */
 66+ protected $citationCount = 0;
 67+
 68+
 69+ /**
 70+ * Static initializer.
 71+ */
 72+ public static function init() {
 73+ global $wgWCCitationStyles;
 74+ $defaultStyleName = $wgWCCitationStyles[ self::defaultStyleID ];
 75+ self::$defaultStyle = self::getStyle( $defaultStyleName );
 76+ }
 77+
 78+
 79+ /**
 80+ * Construct article.
 81+ * @global type $wgWCCitationStyles
 82+ */
 83+ public function __construct() {
 84+ $this->currentDefaultStyle = self::$defaultStyle;
 85+ # Create an initial section, representing the entire article.
 86+ $this->sectionStack[0] = new WCSection( self::$defaultStyle, WCCitationTypeEnum::$inline );
 87+ $this->referenceStore = new WCReferenceStore();
 88+ }
 89+
 90+
 91+ /**
 92+ * Creates a citation object for each citation parser function.
 93+ *
 94+ * Reads flags and parameters from WCArgumentReader object,
 95+ * then creates an appropriate child of class WCStyle based on the
 96+ * first parameter after the colon, then returns the citation as text.
 97+ * @remark Note that this $parser is guaranteed to be the same parser that
 98+ * initialized the object.
 99+ *
 100+ * @param WCArgumentReader $argumentReader
 101+ * @return string Unique marker for citation.
 102+ */
 103+ public function parseCitation( WCArgumentReader $argumentReader ) {
 104+
 105+ # Use the explicit citation style if defined, or use last style.
 106+ $styleClassName = $argumentReader->getStyleClassName();
 107+ if ( $styleClassName ) {
 108+ # Store citation style in a running database of style object singlets.
 109+ $this->currentDefaultStyle = self::getStyle($styleClassName);
 110+ }
 111+
 112+ # A citation function, with no data, may exist merely to define the citation style.
 113+ if ( $argumentReader->isEmpty() ) {
 114+ ++$this->citationCount;
 115+ return '';
 116+ }
 117+
 118+ $reference = new WCReference();
 119+ $citation = new WCCitation( $reference );
 120+ $citation->readArguments( $argumentReader );
 121+ $reference->finalize();
 122+
 123+ # Store reference in database that checks for uniqueness.
 124+ # $citation->reference will be reloaded later, after all citations are read.
 125+ $citation->distance = $this->referenceStore->addUniqueReference( $this->citationCount, $reference );
 126+
 127+ # Is this a citation explicitly inserted in bibliography tags?
 128+ # If so, then we will not be leaving behind a marker.
 129+ if ( $this->bibliographyLevel > 0 ) {
 130+ ++$this->citationCount;
 131+ return ''; # Only a single marker is left behind per bibliography.
 132+ }
 133+
 134+ # Determine whether the citation is in a note, or inline.
 135+ $section = $this->sectionStack[ $this->sectionStackPointer ];
 136+ if ( $this->noteLevel > 0 ) {
 137+ $section->addNoteCite( $this->citationCount, $citation );
 138+ } else {
 139+ $section->addInlineCite( $this->citationCount, $citation );
 140+ }
 141+
 142+ # Store citation and leave behind a random marker for later replacement by the citation:
 143+ $this->citations[ $this->citationCount++ ] = $citation;
 144+ return $citation->marker;
 145+
 146+ }
 147+
 148+
 149+ /**
 150+ * Begin a new endnote section.
 151+ * Citation style and type may be inherited from enclosing section, if undefined.
 152+ * @param array $args = HTML attributes
 153+ */
 154+ public function startSection( array $args ) {
 155+ $superSection = $this->sectionStack[ $this->sectionStackPointer ];
 156+ $this->sectionStack[ ++$this->sectionStackPointer ] =
 157+ WCSection::getSection( $args, $superSection->citationStyle, $superSection->citationType );
 158+ }
 159+
 160+
 161+ /**
 162+ * End the existing endnote section.
 163+ */
 164+ public function endSection() {
 165+ --$this->sectionStackPointer;
 166+ }
 167+
 168+
 169+ public function startNote( array $args ) {
 170+ ++$this->noteLevel;
 171+ # If a note tag is nested, ignore it but keep track of nesting level.
 172+ if ( $this->noteLevel > 1 || $this->bibliographyLevel > 0 ) {
 173+ return;
 174+ }
 175+ $this->sectionStack[ $this->sectionStackPointer ]->startNote( $args );
 176+ }
 177+
 178+
 179+ /**
 180+ * Parse endnote text and save. Leave behind a marker for later replacement.
 181+ * @param string $text Parsed text of the endnote.
 182+ * @return string Marker to later be replaced with subscripted note mark.
 183+ */
 184+ public function finishNote( $text ) {
 185+ # Do not insert footnote if nested, or within biblio tags
 186+ if ( --$this->noteLevel > 0 || $this->bibliographyLevel > 0) {
 187+ return $text;
 188+ }
 189+ return $this->sectionStack[ $this->sectionStackPointer ]->finishNote( $text );
 190+ }
 191+
 192+
 193+ public function markEndnotes() {
 194+ return $this->sectionStack[ $this->sectionStackPointer ]->addEndnotes();
 195+ }
 196+
 197+
 198+ public function startBibliography( array $args ) {
 199+ ++$this->bibliographyLevel;
 200+ # If a bibliography already exists, or is nested, ignore it, but keep track of nesting level.
 201+ if ( isset( $this->bibliography ) || $this->bibliographyLevel > 1 ) {
 202+ return;
 203+ }
 204+ $this->bibliography = WCBibliography::getBibliography( $args, $this->currentDefaultStyle );
 205+ }
 206+
 207+
 208+ public function endBibliography() {
 209+ # If the bibliography end tag is nested, ignore it. Otherwise, leave marker.
 210+ if ( --$this->bibliographyLevel > 0 ) {
 211+ return '';
 212+ } else {
 213+ return $this->bibliography->getMarker();
 214+ }
 215+ }
 216+
 217+
 218+ /**
 219+ * Renders and inserts citations and other material, replacing all markers.
 220+ *
 221+ * @global type $wgWCCitationStyles
 222+ * @param string $text = the current parsed text of the article
 223+ */
 224+ public function render( &$text ) {
 225+
 226+ # Update references, which might have changed due to consolidation, from referenceStore.
 227+ foreach( $this->citations as $key => $citation ) {
 228+ $citation->reference = $this->referenceStore->getReference($key);
 229+ }
 230+
 231+ # Render note marks, free-standing citations, and endnotes.
 232+ $this->sectionStack[ $this->sectionStackPointer ]->render(
 233+ $text,
 234+ $this->citations,
 235+ (boolean) $this->bibliography
 236+ );
 237+
 238+ # Render bibliography.
 239+ if ( $this->bibliography ) {
 240+ $this->bibliography->render( $text, $this->referenceStore );
 241+ }
 242+ }
 243+
 244+
 245+ /**
 246+ * Given a style name, return the style object singlet.
 247+ * @param string $styleClassName = Style class name (e.g., "WCChicagoStyle")
 248+ * @return WCStyle
 249+ */
 250+ public static function getStyle( $styleClassName ) {
 251+ $styleObject = & self::$styleObjects[ $styleClassName ];
 252+ if ( is_null( $styleObject ) ) {
 253+ $styleObject = new $styleClassName();
 254+ }
 255+ return $styleObject;
 256+ }
 257+
 258+
 259+ /**
 260+ * Clear page of citations.
 261+ * @param PPFrame_DOM $frame
 262+ * @param array $args
 263+ */
 264+ public function clear() {
 265+ $this->citations = array();
 266+ $this->citationCount = $this->bibliographyLevel = 0;
 267+ $this->sectionStackPointer = $this->noteLevel = 0;
 268+ $this->currentDefaultStyle = self::$defaultStyle;
 269+ $this->sectionStack[0] = new WCSection( self::$defaultStyle, WCCitationTypeEnum::$inline );
 270+ $this->referenceStore = new WCReferenceStore();
 271+ }
 272+
 273+
 274+ /**
 275+ * Implements the count() function in the Countable interface (SPL).
 276+ * @return int
 277+ */
 278+ public function count() {
 279+ return $this->citationCount;
 280+ }
 281+
 282+}
 283+
 284+/**
 285+ * Static initializer.
 286+ */
 287+WCArticle::init();
Property changes on: trunk/extensions/WikiCitation/includes/WCArticle.php
___________________________________________________________________
Added: svn:eol-style
1288 + native
Index: trunk/extensions/WikiCitation/includes/parameters/WCCitationLengthEnum.php
@@ -0,0 +1,105 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * The length of the citation, either short of long. Short citations are used
 13+ * after the initial full cite.
 14+ */
 15+class WCCitationLengthEnum extends WCParameterEnum {
 16+ const long = 0;
 17+ const short = 1;
 18+ const __default = self::long;
 19+
 20+ public static $long;
 21+ public static $short;
 22+
 23+ public static $magicWordKeys = array(
 24+ self::long => 'wc_long',
 25+ self::short => 'wc_short'
 26+ );
 27+ public static $substitutes = array();
 28+ public static $magicWordArray;
 29+ public static $flipMagicWordKeys = array();
 30+
 31+ public static function init() {
 32+ parent::init( self::$magicWordKeys, self::$substitutes,
 33+ self::$magicWordArray, self::$flipMagicWordKeys );
 34+ self::$long = new self( self::long );
 35+ self::$short = new self( self::short );
 36+ }
 37+
 38+ /**
 39+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 40+ */
 41+ public function __construct( $key = self::__default ) {
 42+ parent::__construct( $key );
 43+ $subs = &self::$substitutes[ $this->key ];
 44+ if ( $subs ) {
 45+ $this->substituteArray = $subs;
 46+ }
 47+ }
 48+ /**
 49+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 50+ */
 51+ public static function match( $parameterText ) {
 52+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 53+ if ( $id ) {
 54+ return new self( self::$flipMagicWordKeys[ $id ] );
 55+ } else {
 56+ return Null;
 57+ }
 58+ }
 59+ /**
 60+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 61+ */
 62+ public static function matchVariable( $parameterText ) {
 63+ list( $id, $var ) = self::$magicWordArray->matchVariableStartToEnd( $parameterText );
 64+ if ( $id ) {
 65+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $var );
 66+ } else {
 67+ return Null;
 68+ }
 69+ }
 70+ /**
 71+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 72+ */
 73+ public static function matchPrefix( $parameterText ) {
 74+ $id = self::$magicWordArray->matchStartAndRemove( $parameterText );
 75+ if ( $id ) {
 76+ # Remove any initial punctuation or spaces
 77+ $parameterText = preg_replace( '/^[\p{P}\p{Z}\p{C}]+/u', '', $parameterText );
 78+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $parameterText );
 79+ } else {
 80+ return array( Null, $parameterText );
 81+ }
 82+ }
 83+ /**
 84+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 85+ */
 86+ public static function matchPartAndNumber( $parameterText ) {
 87+ # Extract number and remove number, white spaces and punctuation.
 88+ if ( preg_match( '/\d+/u', $parameterText, $matches ) ) {
 89+ $numString = $matches[0];
 90+ $num = (int) $numString;
 91+ $parameterText = preg_replace( '/' . $numString . '|[\p{P}\p{Z}\p{C}]+/uS', '', $parameterText );
 92+ } else {
 93+ $num = 1;
 94+ }
 95+ # Match what remains.
 96+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 97+ if ( $id ) {
 98+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $num );
 99+ } else {
 100+ return array( Null, $num );
 101+ }
 102+ }
 103+
 104+
 105+}
 106+WCCitationLengthEnum::init();
Property changes on: trunk/extensions/WikiCitation/includes/parameters/WCCitationLengthEnum.php
___________________________________________________________________
Added: svn:eol-style
1107 + native
Index: trunk/extensions/WikiCitation/includes/parameters/WCCitationTypeEnum.php
@@ -0,0 +1,114 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * The type of the citation, either note, biblio, or inline. Note citations
 13+ * are found in footnotes and endnotes. Biblio citations are found in
 14+ * bibliographies. Inline citations are found in the main text.
 15+ */
 16+class WCCitationTypeEnum extends WCParameterEnum {
 17+ const inline = 0;
 18+ const note = 1;
 19+ const biblio = 2;
 20+ const authorDate = 3;
 21+ const __default = 0;
 22+
 23+ public static $inline;
 24+ public static $note;
 25+ public static $biblio;
 26+ public static $authorDate;
 27+
 28+ public static $magicWordKeys = array(
 29+ self::inline => 'wc_inline',
 30+ self::note => 'wc_note',
 31+ self::biblio => 'wc_bibliography',
 32+ self::authorDate => 'wc_author_date',
 33+ );
 34+ public static $substitutes = array();
 35+ public static $magicWordArray;
 36+ public static $flipMagicWordKeys = array();
 37+
 38+ public static function init() {
 39+ parent::init( self::$magicWordKeys, self::$substitutes,
 40+ self::$magicWordArray, self::$flipMagicWordKeys );
 41+ self::$inline = new self( self::inline );
 42+ self::$note = new self( self::note );
 43+ self::$biblio = new self( self::biblio );
 44+ self::$authorDate = new self( self::authorDate );
 45+ }
 46+
 47+ /**
 48+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 49+ */
 50+ public function __construct( $key = self::__default ) {
 51+ parent::__construct( $key );
 52+ $subs = &self::$substitutes[ $this->key ];
 53+ if ( $subs ) {
 54+ $this->substituteArray = $subs;
 55+ }
 56+ }
 57+ /**
 58+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 59+ */
 60+ public static function match( $parameterText ) {
 61+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 62+ if ( $id ) {
 63+ return new self( self::$flipMagicWordKeys[ $id ] );
 64+ } else {
 65+ return Null;
 66+ }
 67+ }
 68+ /**
 69+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 70+ */
 71+ public static function matchVariable( $parameterText ) {
 72+ list( $id, $var ) = self::$magicWordArray->matchVariableStartToEnd( $parameterText );
 73+ if ( $id ) {
 74+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $var );
 75+ } else {
 76+ return Null;
 77+ }
 78+ }
 79+ /**
 80+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 81+ */
 82+ public static function matchPrefix( $parameterText ) {
 83+ $id = self::$magicWordArray->matchStartAndRemove( $parameterText );
 84+ if ( $id ) {
 85+ # Remove any initial punctuation or spaces
 86+ $parameterText = preg_replace( '/^[\p{P}\p{Z}\p{C}]+/u', '', $parameterText );
 87+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $parameterText );
 88+ } else {
 89+ return array( Null, $parameterText );
 90+ }
 91+ }
 92+ /**
 93+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 94+ */
 95+ public static function matchPartAndNumber( $parameterText ) {
 96+ # Extract number and remove number, white spaces and punctuation.
 97+ if ( preg_match( '/\d+/u', $parameterText, $matches ) ) {
 98+ $numString = $matches[0];
 99+ $num = (int) $numString;
 100+ $parameterText = preg_replace( '/' . $numString . '|[\p{P}\p{Z}\p{C}]+/uS', '', $parameterText );
 101+ } else {
 102+ $num = 1;
 103+ }
 104+ # Match what remains.
 105+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 106+ if ( $id ) {
 107+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $num );
 108+ } else {
 109+ return array( Null, $num );
 110+ }
 111+ }
 112+
 113+
 114+}
 115+WCCitationTypeEnum::init();
Property changes on: trunk/extensions/WikiCitation/includes/parameters/WCCitationTypeEnum.php
___________________________________________________________________
Added: svn:eol-style
1116 + native
Index: trunk/extensions/WikiCitation/includes/parameters/WCParameterEnum.php
@@ -0,0 +1,207 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * A WCEnum with each enumerated value keyed to a magic word.
 13+ * Each enumerated value may be traversible among zero or more substitute
 14+ * enumerated values.
 15+ */
 16+abstract class WCParameterEnum extends WCEnum implements Iterator {
 17+
 18+ /**
 19+ * Array of magic word keys.
 20+ * @var array
 21+ */
 22+ public static $magicWordKeys = array();
 23+
 24+ /**
 25+ * Array of substitute parameters.
 26+ * This array contains fallback elements. If the editor has not supplied
 27+ * the information, and it is needed, the scopes will be tried in the order
 28+ * of the array.
 29+ * @var array
 30+ */
 31+ public static $substitutes = array();
 32+
 33+ /**
 34+ * MagicWordArray object.
 35+ * Must be initalized statically by ::init().
 36+ * @var MagicWordArray
 37+ */
 38+ public static $magicWordArray;
 39+
 40+ /**
 41+ * A flipped version of $magicWordKeys.
 42+ * Must be initalized statically by ::init().
 43+ * @var array
 44+ */
 45+ public static $flipMagicWordKeys;
 46+
 47+ /**
 48+ * An array of substitute enumerated values for $this->value.
 49+ * Initialized by the constructor.
 50+ * @var array
 51+ */
 52+ protected $substituteArray;
 53+
 54+ /**
 55+ * Static initializer.
 56+ * Delete extra parameters and convert to "static::" keyword when moving to PHP 3.3.
 57+ */
 58+ public static function init( array $magicWordKeys, array $substitutes,
 59+ &$magicWordArray, array &$flipMagicWordKeys ) {
 60+ /*static::*/$magicWordArray = new MagicWordArray( /*static::*/$magicWordKeys );
 61+ /*static::*/$flipMagicWordKeys = array_flip( /*static::*/$magicWordKeys );
 62+ }
 63+
 64+ public function __construct( $key = self::__default ) {
 65+ parent::__construct( $key );
 66+ /* Uncomment the following when moving to PHP 3.3:
 67+ $subs = &static::$substitutes[ $this->key ];
 68+ if ( $subs ) {
 69+ $this->substituteArray = $subs;
 70+ }*/
 71+ }
 72+
 73+ /**
 74+ * Use these functions, with late static binding, when moving to PHP 3.3.
 75+ */
 76+ public static function match( $parameterText ) {
 77+/* $id = static::$magicWordArray->matchStartToEnd( $parameterText );
 78+ if ( $id ) {
 79+ return new self( static::$flipMagicWordKeys[ $id ] );
 80+ } else {
 81+ return Null;
 82+ }
 83+*/ }
 84+
 85+ public static function matchVariable( $parameterText ) {
 86+/* list( $id, $var ) = static::$magicWordArray->matchVariableStartToEnd( $parameterText );
 87+ if ( $id ) {
 88+ return array( new self( static::$flipMagicWordKeys[ $id ] ), $var );
 89+ } else {
 90+ return Null;
 91+ }
 92+*/ }
 93+
 94+ /**
 95+ * Match to a magic word prefix.
 96+ * Returns the remainder in the second element of the array.
 97+ * @param string $parameterText
 98+ * @return array Array of ( enum key of the prefix, remainder string)
 99+ */
 100+ public static function matchPrefix( $parameterText ) {
 101+/* $id = static::$magicWordArray->matchStartAndRemove( $parameterText );
 102+ if ( $id ) {
 103+ # Remove any initial punctuation or spaces
 104+ $parameterText = preg_replace( '/^[\p{P}\p{Z}\p{C}]+/u', '', $parameterText );
 105+ return array( new self( static::$flipMagicWordKeys[ $id ] ), $parameterText );
 106+ } else {
 107+ return array( Null, $parameterText );
 108+ }
 109+*/ }
 110+
 111+
 112+ public static function matchPartAndNumber( $parameterText ) {
 113+/* # Extract number and remove number, white spaces and punctuation.
 114+ if ( preg_match( '/\d+/u', $parameterText, $matches ) ) {
 115+ $numString = $matches[0];
 116+ $num = (int) $numString;
 117+ $parameterText = preg_replace( '/' . $numString . '|[\p{P}\p{Z}\p{C}]+/uS', '', $parameterText );
 118+ } else {
 119+ $num = 1;
 120+ }
 121+ # Match what remains.
 122+ $id = static::$magicWordArray->matchStartToEnd( $parameterText );
 123+ if ( $id ) {
 124+ return array( new self( static::$flipMagicWordKeys[ $id ] ), $num );
 125+ } else {
 126+ return array( Null, $num );
 127+ }
 128+*/ }
 129+
 130+
 131+/* public function __toString() {
 132+ $magicWordID = static::$magicWordKeys[ $this->key ];
 133+ return MagicWord::get( $magicWordID )->getSynonym( 0 );
 134+ }
 135+*/
 136+ /**
 137+ * Get the magic word key for this enumerated parameter.
 138+ *
 139+ public function getMagicWordKey() {
 140+ return static::$magicWordKeys[ $this->key ];
 141+ }*/
 142+
 143+ /**
 144+ * Implements Iterator interface method.
 145+ * @return type
 146+ */
 147+ public function key() {
 148+ return key( $this->substituteArray );
 149+ }
 150+
 151+ /**
 152+ * Implements Iterator interface method.
 153+ * @return type
 154+ */
 155+ public function current() {
 156+ return current( $this->substituteArray );
 157+ }
 158+
 159+ /**
 160+ * Implements Iterator interface method.
 161+ * @return type
 162+ */
 163+ public function next() {
 164+ return next( $this->substituteArray );
 165+ }
 166+
 167+ /**
 168+ * Implements Iterator interface method.
 169+ * @return type
 170+ */
 171+ public function valid() {
 172+ return ! ( current( $this->substituteArray ) === False );
 173+ }
 174+
 175+ /**
 176+ * Implements Iterator interface method.
 177+ * @return type
 178+ */
 179+ public function rewind() {
 180+ return reset( $this->substituteArray );
 181+ }
 182+
 183+ /**
 184+ * Tests if a string is a localized version of a magic word.
 185+ *
 186+ * As of this coding, MagicWord.php has no MagicWord::matchStartToEnd()
 187+ * function yet to do this simple task efficiently.
 188+ *
 189+ * @param string $text = the text to be tested
 190+ * @param string $magicWordID = the magic word ID
 191+ * @return boolean
 192+ */
 193+ final protected static function isMagicWord( $text, $magicWordID ) {
 194+ $magicWordObject = MagicWord::get( $magicWordID );
 195+ $synonyms = $magicWordObject->getSynonyms();
 196+ foreach( $synonyms as $synonym ) {
 197+ if ( !$magicWordObject->isCaseSensitive() ) {
 198+ $synonym = mb_strtolower( $synonym );
 199+ $text = mb_strtolower( $text );
 200+ }
 201+ if ( $synonym === $text ) {
 202+ return True;
 203+ }
 204+ }
 205+ return False;
 206+ }
 207+
 208+}
Property changes on: trunk/extensions/WikiCitation/includes/parameters/WCParameterEnum.php
___________________________________________________________________
Added: svn:eol-style
1209 + native
Index: trunk/extensions/WikiCitation/includes/parameters/WCNameTypeEnum.php
@@ -0,0 +1,134 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCNameTypeEnum extends WCParameterEnum {
 12+ const author = 0;
 13+ const editorTranslator = 1; # This goes before editor and translator, because otherwise, the search would stop when it reaches either of the shorter terms.
 14+ const editor = 2;
 15+ const translator = 3;
 16+ const publisher = 4;
 17+ const interviewer = 5;
 18+ const recipient = 6;
 19+ const composer = 7;
 20+ const __default = self::author;
 21+
 22+ public static $author;
 23+ public static $editorTranslator;
 24+ public static $editor;
 25+ public static $translator;
 26+ public static $publisher;
 27+ public static $interviewer;
 28+ public static $recipient;
 29+ public static $composer;
 30+
 31+ public static $magicWordKeys = array(
 32+ self::author => 'wc_author',
 33+ self::editorTranslator => 'wc_editor_translator',
 34+ self::editor => 'wc_editor',
 35+ self::translator => 'wc_translator',
 36+ self::publisher => 'wc_publisher',
 37+ self::interviewer => 'wc_interviewer',
 38+ self::recipient => 'wc_recipient',
 39+ self::composer => 'wc_composer'
 40+ );
 41+ public static $substitutes = array(
 42+ self::author => array( self::author, self::editorTranslator, self::editor, self::translator, self::interviewer, self::composer, self::recipient, self::publisher ),
 43+ self::editorTranslator => array( self::editorTranslator, self::editor, self::translator ),
 44+ self::editor => array( self::editor ),
 45+ self::translator => array( self::translator ),
 46+ self::publisher => array( self::publisher ),
 47+ self::interviewer => array( self::interviewer, self::author ),
 48+ self::recipient => array( self::recipient, self::author ),
 49+ self::composer => array( self::composer, self::author )
 50+ );
 51+ public static $magicWordArray;
 52+ public static $flipMagicWordKeys = array();
 53+
 54+ public static function init() {
 55+ parent::init( self::$magicWordKeys, self::$substitutes,
 56+ self::$magicWordArray, self::$flipMagicWordKeys );
 57+ self::$author = new self( self::author );
 58+ self::$editorTranslator = new self( self::editorTranslator );
 59+ self::$editor = new self( self::editor );
 60+ self::$translator = new self( self::translator );
 61+ self::$publisher = new self( self::publisher );
 62+ self::$interviewer = new self( self::interviewer );
 63+ self::$recipient = new self( self::recipient );
 64+ self::$composer = new self( self::composer );
 65+ }
 66+
 67+ /**
 68+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 69+ */
 70+ public function __construct( $key = self::__default ) {
 71+ parent::__construct( $key );
 72+ $subs = &self::$substitutes[ $this->key ];
 73+ if ( $subs ) {
 74+ $this->substituteArray = $subs;
 75+ }
 76+ }
 77+ /**
 78+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 79+ */
 80+ public static function match( $parameterText ) {
 81+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 82+ if ( $id ) {
 83+ return new self( self::$flipMagicWordKeys[ $id ] );
 84+ } else {
 85+ return Null;
 86+ }
 87+ }
 88+ /**
 89+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 90+ */
 91+ public static function matchVariable( $parameterText ) {
 92+ list( $id, $var ) = self::$magicWordArray->matchVariableStartToEnd( $parameterText );
 93+ if ( $id ) {
 94+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $var );
 95+ } else {
 96+ return Null;
 97+ }
 98+ }
 99+ /**
 100+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 101+ */
 102+ public static function matchPrefix( $parameterText ) {
 103+ $id = self::$magicWordArray->matchStartAndRemove( $parameterText );
 104+ if ( $id ) {
 105+ # Remove any initial punctuation or spaces
 106+ $parameterText = preg_replace( '/^[\p{P}\p{Z}\p{C}]+/u', '', $parameterText );
 107+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $parameterText );
 108+ } else {
 109+ return array( Null, $parameterText );
 110+ }
 111+ }
 112+ /**
 113+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 114+ */
 115+ public static function matchPartAndNumber( $parameterText ) {
 116+ # Extract number and remove number, white spaces and punctuation.
 117+ if ( preg_match( '/\d+/u', $parameterText, $matches ) ) {
 118+ $numString = $matches[0];
 119+ $num = (int) $numString;
 120+ $parameterText = preg_replace( '/' . $numString . '|[\p{P}\p{Z}\p{C}]+/uS', '', $parameterText );
 121+ } else {
 122+ $num = 1;
 123+ }
 124+ # Match what remains.
 125+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 126+ if ( $id ) {
 127+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $num );
 128+ } else {
 129+ return array( Null, $num );
 130+ }
 131+ }
 132+
 133+
 134+}
 135+WCNameTypeEnum::init();
Property changes on: trunk/extensions/WikiCitation/includes/parameters/WCNameTypeEnum.php
___________________________________________________________________
Added: svn:eol-style
1136 + native
Index: trunk/extensions/WikiCitation/includes/parameters/WCSourceTypeEnum.php
@@ -0,0 +1,403 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCSourceTypeEnum extends WCParameterEnum {
 12+ const general = 0;
 13+ const book = 1;
 14+ const dictionary = 2;
 15+ const encyclopedia = 3;
 16+ const periodical = 4;
 17+ const magazine = 5;
 18+ const newspaper = 6;
 19+ const journal = 7;
 20+ const entry = 8;
 21+ const article = 9;
 22+ const chapter = 10;
 23+ const review = 11;
 24+ const paper = 12;
 25+ const manuscript = 13;
 26+ const musicalScore = 14;
 27+ const pamphlet = 15;
 28+ const conferencePaper = 16;
 29+ const thesis = 17;
 30+ const report = 18;
 31+ const poem = 19;
 32+ const song = 20;
 33+ const enactment = 21;
 34+ const bill = 22;
 35+ const statute = 23;
 36+ const treaty = 24;
 37+ const rule = 25;
 38+ const regulation = 26;
 39+ const legalDocument = 27;
 40+ const patent = 28;
 41+ const deed = 29;
 42+ const governmentGrant = 30;
 43+ const filing = 31;
 44+ const patentApplication = 32;
 45+ const regulatoryFiling = 33;
 46+ const litigation = 34;
 47+ const legalOpinion = 35;
 48+ const legalCase = 36;
 49+ const graphic = 37;
 50+ const photograph = 38;
 51+ const map = 39;
 52+ const statement = 40;
 53+ const pressRelease = 41;
 54+ const interview = 42;
 55+ const speech = 43;
 56+ const personalCommunication = 44;
 57+ const internetResource = 45;
 58+ const webpage = 46;
 59+ const post = 47;
 60+ const production = 48;
 61+ const motionPicture = 49;
 62+ const recording = 50;
 63+ const play = 51;
 64+ const broadcast = 52;
 65+ const televisionBroadcast = 53;
 66+ const radioBroadcast = 54;
 67+ const internetBroadcast = 55;
 68+ const object = 56;
 69+ const star = 57;
 70+ const gravestone = 58;
 71+ const monument = 59;
 72+ const realProperty = 60;
 73+ const __default = self::general;
 74+
 75+
 76+ public static $general;
 77+ public static $book;
 78+ public static $dictionary;
 79+ public static $encyclopedia;
 80+ public static $periodical;
 81+ public static $magazine;
 82+ public static $newspaper;
 83+ public static $journal;
 84+ public static $entry;
 85+ public static $article;
 86+ public static $chapter;
 87+ public static $review;
 88+ public static $paper;
 89+ public static $manuscript;
 90+ public static $musicalScore;
 91+ public static $pamphlet;
 92+ public static $conferencePaper;
 93+ public static $thesis;
 94+ public static $report;
 95+ public static $poem;
 96+ public static $song;
 97+ public static $enactment;
 98+ public static $bill;
 99+ public static $statute;
 100+ public static $treaty;
 101+ public static $rule;
 102+ public static $regulation;
 103+ public static $legalDocument;
 104+ public static $patent;
 105+ public static $deed;
 106+ public static $governmentGrant;
 107+ public static $filing;
 108+ public static $patentApplication;
 109+ public static $regulatoryFiling;
 110+ public static $litigation;
 111+ public static $legalOpinion;
 112+ public static $legalCase;
 113+ public static $graphic;
 114+ public static $photograph;
 115+ public static $map;
 116+ public static $statement;
 117+ public static $pressRelease;
 118+ public static $interview;
 119+ public static $speech;
 120+ public static $personalCommunication;
 121+ public static $internetResource;
 122+ public static $webpage;
 123+ public static $post;
 124+ public static $production;
 125+ public static $motionPicture;
 126+ public static $recording;
 127+ public static $play;
 128+ public static $broadcast;
 129+ public static $televisionBroadcast;
 130+ public static $radioBroadcast;
 131+ public static $internetBroadcast;
 132+ public static $object;
 133+ public static $star;
 134+ public static $gravestone;
 135+ public static $monument;
 136+ public static $realProperty;
 137+
 138+
 139+ public static $magicWordKeys = array(
 140+ self::general => 'wc_general',
 141+ self::book => 'wc_book',
 142+ self::dictionary => 'wc_dictionary',
 143+ self::encyclopedia => 'wc_encyclopedia',
 144+ self::periodical => 'wc_periodical',
 145+ self::magazine => 'wc_magazine',
 146+ self::newspaper => 'wc_newspaper',
 147+ self::journal => 'wc_journal',
 148+ self::entry => 'wc_entry',
 149+ self::article => 'wc_article',
 150+ self::chapter => 'wc_chapter',
 151+ self::review => 'wc_review',
 152+ self::paper => 'wc_paper',
 153+ self::manuscript => 'wc_manuscript',
 154+ self::musicalScore => 'wc_musical_score',
 155+ self::pamphlet => 'wc_pamphlet',
 156+ self::conferencePaper => 'wc_conference_paper',
 157+ self::thesis => 'wc_thesis',
 158+ self::report => 'wc_report',
 159+ self::poem => 'wc_poem',
 160+ self::song => 'wc_song',
 161+ self::enactment => 'wc_enactment',
 162+ self::bill => 'wc_bill',
 163+ self::statute => 'wc_statute',
 164+ self::treaty => 'wc_treaty',
 165+ self::rule => 'wc_rule',
 166+ self::regulation => 'wc_regulation',
 167+ self::legalDocument => 'wc_legal_document',
 168+ self::patent => 'wc_patent',
 169+ self::deed => 'wc_deed',
 170+ self::governmentGrant => 'wc_government_grant',
 171+ self::filing => 'wc_filing',
 172+ self::patentApplication => 'wc_patent_application',
 173+ self::regulatoryFiling => 'wc_regulatory_filing',
 174+ self::litigation => 'wc_litigation',
 175+ self::legalOpinion => 'wc_legal_opinion',
 176+ self::legalCase => 'wc_legal_case',
 177+ self::graphic => 'wc_graphic',
 178+ self::photograph => 'wc_photograph',
 179+ self::map => 'wc_map',
 180+ self::statement => 'wc_statement',
 181+ self::pressRelease => 'wc_press_release',
 182+ self::interview => 'wc_interview',
 183+ self::speech => 'wc_speech',
 184+ self::personalCommunication => 'wc_personal_communication',
 185+ self::internetResource => 'wc_internet_resource',
 186+ self::webpage => 'wc_web_page',
 187+ self::post => 'wc_post',
 188+ self::production => 'wc_production',
 189+ self::motionPicture => 'wc_motion_picture',
 190+ self::recording => 'wc_recording',
 191+ self::play => 'wc_play',
 192+ self::broadcast => 'wc_broadcast',
 193+ self::televisionBroadcast => 'wc_television_broadcast',
 194+ self::radioBroadcast => 'wc_radio_broadcast',
 195+ self::internetBroadcast => 'wc_internet_broadcast',
 196+ self::object => 'wc_object',
 197+ self::star => 'wc_star',
 198+ self::gravestone => 'wc_gravestone',
 199+ self::monument => 'wc_monument',
 200+ self::realProperty => 'wc_real_property',
 201+ );
 202+
 203+ public static $substitutes = array (
 204+ self::general => array( self::general ),
 205+ self::book => array( self::book, self::general ),
 206+ self::dictionary => array( self::dictionary, self::encyclopedia, self::book ),
 207+ self::encyclopedia => array( self::encyclopedia, self::dictionary, self::book ),
 208+ self::periodical => array( self::periodical, self::journal, self::general ),
 209+ self::magazine => array( self::magazine, self::journal, self::periodical, self::general ),
 210+ self::newspaper => array( self::newspaper, self::journal, self::periodical, self::general ),
 211+ self::journal => array( self::journal, self::periodical, self::general ),
 212+ self::entry => array( self::entry, self::general ),
 213+ self::article => array( self::article, self::entry ),
 214+ self::chapter => array( self::chapter, self::entry ),
 215+ self::review => array( self::review, self::article, self::entry ),
 216+ self::paper => array( self::paper, self::general ),
 217+ self::manuscript => array( self::manuscript, self::paper, self::general ),
 218+ self::musicalScore => array( self::musicalScore, self::paper, self::general ),
 219+ self::pamphlet => array( self::pamphlet, self::paper, self::general ),
 220+ self::conferencePaper => array( self::conferencePaper, self::paper, self::general ),
 221+ self::thesis => array( self::thesis, self::paper, self::general ),
 222+ self::report => array( self::report, self::paper, self::general ),
 223+ self::poem => array( self::poem, self::paper, self::general ),
 224+ self::song => array( self::song, self::paper, self::general ),
 225+ self::enactment => array( self::enactment, self::general ),
 226+ self::bill => array( self::bill, self::enactment, self::general ),
 227+ self::statute => array( self::statute, self::enactment, self::general ),
 228+ self::treaty => array( self::treaty, self::statute, self::enactment, self::general ),
 229+ self::rule => array( self::rule, self::regulation, self::statute, self::enactment, self::general ),
 230+ self::regulation => array( self::regulation, self::statute, self::enactment, self::general ),
 231+ self::legalDocument => array( self::legalDocument, self::paper, self::general ),
 232+ self::patent => array( self::patent, self::legalDocument, self::paper, self::general ),
 233+ self::deed => array( self::deed, self::legalDocument, self::paper, self::general ),
 234+ self::governmentGrant => array( self::governmentGrant, self::legalDocument, self::paper, self::general ),
 235+ self::filing => array( self::filing, self::legalDocument, self::paper, self::general ),
 236+ self::patentApplication => array( self::patentApplication, self::filing, self::legalDocument, self::paper, self::general ),
 237+ self::regulatoryFiling => array( self::regulatoryFiling, self::filing, self::legalDocument, self::paper, self::general ),
 238+ self::litigation => array( self::litigation, self::general ),
 239+ self::legalOpinion => array( self::legalOpinion, self::legalCase, self::litigation, self::general ),
 240+ self::legalCase => array( self::legalCase, self::litigation, self::general ),
 241+ self::graphic => array( self::graphic, self::paper, self::general ),
 242+ self::photograph => array( self::photograph, self::graphic, self::paper, self::general ),
 243+ self::map => array( self::map, self::graphic, self::paper, self::general ),
 244+ self::statement => array( self::statement, self::paper, self::general ),
 245+ self::pressRelease => array( self::pressRelease, self::statement, self::paper, self::general ),
 246+ self::interview => array( self::interview, self::statement, self::paper, self::general ),
 247+ self::speech => array( self::speech, self::statement, self::paper, self::general ),
 248+ self::personalCommunication => array( self::personalCommunication, self::statement, self::paper, self::general ),
 249+ self::internetResource => array( self::internetResource, self::general ),
 250+ self::webpage => array( self::webpage, self::internetResource, self::general ),
 251+ self::post => array( self::post, self::internetResource, self::general ),
 252+ self::production => array( self::production, self::general ),
 253+ self::motionPicture => array( self::motionPicture, self::production, self::general ),
 254+ self::recording => array( self::recording, self::production, self::general ),
 255+ self::play => array( self::play, self::production, self::general ),
 256+ self::broadcast => array( self::broadcast, self::production, self::general ),
 257+ self::televisionBroadcast => array( self::televisionBroadcast, self::broadcast, self::production, self::general ),
 258+ self::radioBroadcast => array( self::radioBroadcast, self::broadcast, self::production, self::general ),
 259+ self::internetBroadcast => array( self::internetBroadcast, self::broadcast, self::production, self::webpage, self::general ),
 260+ self::object => array( self::object, self::general ),
 261+ self::star => array( self::star, self::object, self::general ),
 262+ self::gravestone => array( self::gravestone, self::object, self::general ),
 263+ self::monument => array( self::monument, self::object, self::general ),
 264+ self::realProperty => array( self::realProperty, self::object, self::general )
 265+ );
 266+
 267+ public static $magicWordArray;
 268+ public static $flipMagicWordKeys = array();
 269+
 270+ public static function init() {
 271+ parent::init( self::$magicWordKeys, self::$substitutes,
 272+ self::$magicWordArray, self::$flipMagicWordKeys );
 273+ self::$general = new self( self::general );
 274+ self::$book = new self( self::book );
 275+ self::$dictionary = new self( self::dictionary );
 276+ self::$encyclopedia = new self( self::encyclopedia );
 277+ self::$periodical = new self( self::periodical );
 278+ self::$magazine = new self( self::magazine );
 279+ self::$newspaper = new self( self::newspaper );
 280+ self::$journal = new self( self::journal );
 281+ self::$entry = new self( self::entry );
 282+ self::$article = new self( self::article );
 283+ self::$chapter = new self( self::chapter );
 284+ self::$review = new self( self::review );
 285+ self::$paper = new self( self::paper );
 286+ self::$manuscript = new self( self::manuscript );
 287+ self::$musicalScore = new self( self::musicalScore );
 288+ self::$pamphlet = new self( self::pamphlet );
 289+ self::$conferencePaper = new self( self::conferencePaper );
 290+ self::$thesis = new self( self::thesis );
 291+ self::$report = new self( self::report );
 292+ self::$poem = new self( self::poem );
 293+ self::$song = new self( self::song );
 294+ self::$enactment = new self( self::enactment );
 295+ self::$bill = new self( self::bill );
 296+ self::$statute = new self( self::statute );
 297+ self::$treaty = new self( self::treaty );
 298+ self::$rule = new self( self::rule );
 299+ self::$regulation = new self( self::regulation );
 300+ self::$legalDocument = new self( self::legalDocument );
 301+ self::$patent = new self( self::patent );
 302+ self::$deed = new self( self::deed );
 303+ self::$governmentGrant = new self( self::governmentGrant );
 304+ self::$filing = new self( self::filing );
 305+ self::$patentApplication = new self( self::patentApplication );
 306+ self::$regulatoryFiling = new self( self::regulatoryFiling );
 307+ self::$litigation = new self( self::litigation );
 308+ self::$legalOpinion = new self( self::legalOpinion );
 309+ self::$legalCase = new self( self::legalCase );
 310+ self::$graphic = new self( self::graphic );
 311+ self::$photograph = new self( self::photograph );
 312+ self::$map = new self( self::map );
 313+ self::$statement = new self( self::statement );
 314+ self::$pressRelease = new self( self::pressRelease );
 315+ self::$interview = new self( self::interview );
 316+ self::$speech = new self( self::speech );
 317+ self::$personalCommunication = new self( self::personalCommunication );
 318+ self::$internetResource = new self( self::internetResource );
 319+ self::$webpage = new self( self::webpage );
 320+ self::$post = new self( self::post );
 321+ self::$production = new self( self::production );
 322+ self::$motionPicture = new self( self::motionPicture );
 323+ self::$recording = new self( self::recording );
 324+ self::$play = new self( self::play );
 325+ self::$broadcast = new self( self::broadcast );
 326+ self::$televisionBroadcast = new self( self::televisionBroadcast );
 327+ self::$radioBroadcast = new self( self::radioBroadcast );
 328+ self::$internetBroadcast = new self( self::internetBroadcast );
 329+ self::$object = new self( self::object );
 330+ self::$star = new self( self::star );
 331+ self::$gravestone = new self( self::gravestone );
 332+ self::$monument = new self( self::monument );
 333+ self::$realProperty = new self( self::realProperty );
 334+ }
 335+
 336+ /**
 337+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 338+ */
 339+ public function __construct( $key = self::__default ) {
 340+ parent::__construct( $key );
 341+ $subs = &self::$substitutes[ $this->key ];
 342+ if ( $subs ) {
 343+ $this->substituteArray = $subs;
 344+ }
 345+ }
 346+ /**
 347+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 348+ */
 349+ public static function match( $parameterText ) {
 350+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 351+ if ( $id ) {
 352+ return new self( self::$flipMagicWordKeys[ $id ] );
 353+ } else {
 354+ return Null;
 355+ }
 356+ }
 357+ /**
 358+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 359+ */
 360+ public static function matchVariable( $parameterText ) {
 361+ list( $id, $var ) = self::$magicWordArray->matchVariableStartToEnd( $parameterText );
 362+ if ( $id ) {
 363+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $var );
 364+ } else {
 365+ return Null;
 366+ }
 367+ }
 368+ /**
 369+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 370+ */
 371+ public static function matchPrefix( $parameterText ) {
 372+ $id = self::$magicWordArray->matchStartAndRemove( $parameterText );
 373+ if ( $id ) {
 374+ # Remove any initial punctuation or spaces
 375+ $parameterText = preg_replace( '/^[\p{P}\p{Z}\p{C}]+/u', '', $parameterText );
 376+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $parameterText );
 377+ } else {
 378+ return array( Null, $parameterText );
 379+ }
 380+ }
 381+ /**
 382+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 383+ */
 384+ public static function matchPartAndNumber( $parameterText ) {
 385+ # Extract number and remove number, white spaces and punctuation.
 386+ if ( preg_match( '/\d+/u', $parameterText, $matches ) ) {
 387+ $numString = $matches[0];
 388+ $num = (int) $numString;
 389+ $parameterText = preg_replace( '/' . $numString . '|[\p{P}\p{Z}\p{C}]+/uS', '', $parameterText );
 390+ } else {
 391+ $num = 1;
 392+ }
 393+ # Match what remains.
 394+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 395+ if ( $id ) {
 396+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $num );
 397+ } else {
 398+ return array( Null, $num );
 399+ }
 400+ }
 401+
 402+
 403+}
 404+WCSourceTypeEnum::init();
Property changes on: trunk/extensions/WikiCitation/includes/parameters/WCSourceTypeEnum.php
___________________________________________________________________
Added: svn:eol-style
1405 + native
Index: trunk/extensions/WikiCitation/includes/parameters/WCAttributeEnum.php
@@ -0,0 +1,48 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCAttributeEnum extends WCEnum {
 12+ const text = 0;
 13+ const title = 1;
 14+ const date = 2;
 15+ const parameter = 3;
 16+ const name = 4;
 17+ const names = 5;
 18+ const locator = 6;
 19+ const __default = self::text;
 20+
 21+ public static $text;
 22+ public static $title;
 23+ public static $date;
 24+ public static $parameter;
 25+ public static $name;
 26+ public static $names;
 27+ public static $locator;
 28+
 29+ public static $attribute = array(
 30+ self::text => 'WCText',
 31+ self::title => 'WCTitle',
 32+ self::date => 'WCDate',
 33+ self::parameter => 'WCTypeData',
 34+ self::name => 'WCName',
 35+ self::names => 'WCNames',
 36+ self::locator => 'WCLocator',
 37+ );
 38+
 39+ public static function init() {
 40+ self::$text = new self( self::text );
 41+ self::$title = new self( self::title );
 42+ self::$date = new self( self::date );
 43+ self::$parameter = new self( self::parameter );
 44+ self::$name = new self( self::name );
 45+ self::$names = new self( self::names );
 46+ self::$locator = new self( self::locator );
 47+ }
 48+}
 49+WCAttributeEnum::init();
Property changes on: trunk/extensions/WikiCitation/includes/parameters/WCAttributeEnum.php
___________________________________________________________________
Added: svn:eol-style
150 + native
Index: trunk/extensions/WikiCitation/includes/parameters/WCPropertyEnum.php
@@ -0,0 +1,383 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCPropertyEnum extends WCParameterEnum {
 12+ const title = 0;
 13+ const shortTitle = 1;
 14+ const place = 2;
 15+ const edition = 3;
 16+ const firstPage = 4;
 17+ const version = 5;
 18+ const number = 6;
 19+ const archive = 7;
 20+ const jurisdiction = 10;
 21+ const keyword = 11;
 22+
 23+ const page = 12;
 24+ const pageRange = 13;
 25+ const volume = 14;
 26+ const issue = 15;
 27+ const opus = 16;
 28+ const bookLoc = 17; # i.e., biblical "book," book III of Lord of the Rings, etc.
 29+ const part = 18;
 30+ const chapterLoc = 19;
 31+ const folio = 20;
 32+ const column = 21;
 33+ const table = 22;
 34+ const figure = 23;
 35+ const section = 24;
 36+ const paragraph = 25;
 37+ const noteLoc = 26;
 38+ const footnote = 27;
 39+ const endnote = 28;
 40+ const verse = 29;
 41+ const line = 30;
 42+ const locator = 31;
 43+
 44+ const type = 32;
 45+
 46+ const link = 33;
 47+ const url = 34;
 48+
 49+ const callNumber = 35;
 50+ const doi = 36;
 51+ const isbn = 37;
 52+
 53+ const date = 38;
 54+ const accessed = 39;
 55+ const issued = 40;
 56+ const filed = 41;
 57+
 58+ const __default = self::title;
 59+
 60+
 61+ public static $title;
 62+ public static $shortTitle;
 63+ public static $place;
 64+ public static $edition;
 65+ public static $firstPage;
 66+ public static $version;
 67+ public static $number;
 68+ public static $archive;
 69+ public static $jurisdiction;
 70+ public static $keyword;
 71+
 72+ public static $page;
 73+ public static $pageRange;
 74+ public static $volume;
 75+ public static $issue;
 76+ public static $opus;
 77+ public static $bookLoc; # i.e., biblical "book," book III of Lord of the Rings, etc.
 78+ public static $part;
 79+ public static $chapterLoc;
 80+ public static $folio;
 81+ public static $column;
 82+ public static $table;
 83+ public static $figure;
 84+ public static $section;
 85+ public static $paragraph;
 86+ public static $noteLoc;
 87+ public static $footnote;
 88+ public static $endnote;
 89+ public static $verse;
 90+ public static $line;
 91+ public static $locator;
 92+
 93+ public static $type;
 94+
 95+ public static $link;
 96+ public static $url;
 97+
 98+ public static $callNumber;
 99+ public static $doi;
 100+ public static $isbn;
 101+
 102+ public static $date;
 103+ public static $accessed;
 104+ public static $issued;
 105+ public static $filed;
 106+
 107+
 108+ public static $magicWordKeys = array(
 109+ self::title => 'wc_title',
 110+ self::shortTitle => 'wc_short_title',
 111+ self::place => 'wc_place',
 112+ self::edition => 'wc_edition',
 113+ self::firstPage => 'wc_first_page',
 114+ self::version => 'wc_version',
 115+ self::number => 'wc_number',
 116+ self::archive => 'wc_archive',
 117+ self::jurisdiction => 'wc_jurisdiction',
 118+ self::keyword => 'wc_keyword',
 119+
 120+ self::page => 'wc_page',
 121+ self::pageRange => 'wc_page_range',
 122+ self::volume => 'wc_volume',
 123+ self::issue => 'wc_issue',
 124+ self::opus => 'wc_opus',
 125+ self::bookLoc => 'wc_book_loc', # i.e., biblical "book," book III of Lord of the Rings, etc.
 126+ self::part => 'wc_part',
 127+ self::chapterLoc => 'wc_chapter_loc',
 128+ self::folio => 'wc_folio',
 129+ self::column => 'wc_column',
 130+ self::table => 'wc_table',
 131+ self::figure => 'wc_figure',
 132+ self::section => 'wc_section',
 133+ self::paragraph => 'wc_paragraph',
 134+ self::noteLoc => 'wc_note_loc',
 135+ self::footnote => 'wc_footnote',
 136+ self::endnote => 'wc_endnote',
 137+ self::verse => 'wc_verse',
 138+ self::line => 'wc_line',
 139+ self::locator => 'wc_locator',
 140+
 141+ self::type => 'wc_type',
 142+
 143+ self::link => 'wc_link',
 144+ self::url => 'wc_URL',
 145+
 146+ self::callNumber => 'wc_call_number',
 147+ self::doi => 'wc_DOI',
 148+ self::isbn => 'wc_ISBN',
 149+
 150+ self::date => 'wc_date',
 151+ self::accessed => 'wc_accessed',
 152+ self::issued => 'wc_issued',
 153+ self::filed => 'wc_filed',
 154+ );
 155+
 156+ public static $substitutes = array(
 157+ self::title => array( self::title, self::shortTitle ),
 158+ self::shortTitle => array( self::shortTitle, self::title ),
 159+ self::place => array( self::place ),
 160+ self::edition => array( self::edition ),
 161+ self::firstPage => array( self::firstPage ),
 162+ self::version => array( self::version ),
 163+ self::number => array( self::number ),
 164+ self::archive => array( self::archive ),
 165+ self::jurisdiction => array( self::jurisdiction ),
 166+ self::keyword => array( self::keyword ),
 167+
 168+ self::page => array( self::page, self::locator, self::pageRange ),
 169+ self::pageRange => array( self::pageRange, self::page ),
 170+ self::volume => array( self::volume ),
 171+ self::issue => array( self::issue ),
 172+ self::opus => array( self::opus ),
 173+ self::bookLoc => array( self::bookLoc ),
 174+ self::part => array( self::part ),
 175+ self::chapterLoc => array( self::chapterLoc ),
 176+ self::folio => array( self::folio, self::page ),
 177+ self::column => array( self::column ),
 178+ self::table => array( self::table ),
 179+ self::figure => array( self::figure ),
 180+ self::section => array( self::section ),
 181+ self::paragraph => array( self::paragraph ),
 182+ self::noteLoc => array( self::noteLoc, self::footnote, self::endnote ),
 183+ self::footnote => array( self::footnote, self::noteLoc ),
 184+ self::endnote => array( self::endnote, self::noteLoc ),
 185+ self::verse => array( self::verse ),
 186+ self::line => array( self::line ),
 187+ self::locator => array( self::locator, self::page ),
 188+
 189+ self::type => array( self::type ),
 190+
 191+ self::link => array( self::link ),
 192+ self::url => array( self::url ),
 193+
 194+ self::callNumber => array( self::callNumber ),
 195+ self::doi => array( self::doi ),
 196+ self::isbn => array( self::isbn ),
 197+
 198+ self::date => array( self::date, self::issued, self::filed, self::accessed ),
 199+ self::accessed => array( self::accessed, self::date ),
 200+ self::issued => array( self::issued, self::date ),
 201+ self::filed => array( self::filed, self::date ),
 202+ );
 203+
 204+ public static $attributeClasses = array(
 205+ self::title => WCAttributeEnum::title,
 206+ self::shortTitle => WCAttributeEnum::title,
 207+ self::place => WCAttributeEnum::text,
 208+ self::edition => WCAttributeEnum::text,
 209+ self::firstPage => WCAttributeEnum::locator,
 210+ self::version => WCAttributeEnum::text,
 211+ self::number => WCAttributeEnum::text,
 212+ self::archive => WCAttributeEnum::text,
 213+ self::jurisdiction => WCAttributeEnum::text,
 214+ self::keyword => WCAttributeEnum::text,
 215+
 216+ self::page => WCAttributeEnum::locator,
 217+ self::pageRange => WCAttributeEnum::locator,
 218+ self::volume => WCAttributeEnum::locator,
 219+ self::issue => WCAttributeEnum::locator,
 220+ self::opus => WCAttributeEnum::locator,
 221+ self::bookLoc => WCAttributeEnum::locator,
 222+ self::part => WCAttributeEnum::locator,
 223+ self::chapterLoc => WCAttributeEnum::locator,
 224+ self::folio => WCAttributeEnum::locator,
 225+ self::column => WCAttributeEnum::locator,
 226+ self::table => WCAttributeEnum::locator,
 227+ self::figure => WCAttributeEnum::locator,
 228+ self::section => WCAttributeEnum::locator,
 229+ self::paragraph => WCAttributeEnum::locator,
 230+ self::noteLoc => WCAttributeEnum::locator,
 231+ self::footnote => WCAttributeEnum::locator,
 232+ self::endnote => WCAttributeEnum::locator,
 233+ self::verse => WCAttributeEnum::locator,
 234+ self::line => WCAttributeEnum::locator,
 235+ self::locator => WCAttributeEnum::locator,
 236+
 237+ self::type => WCAttributeEnum::parameter,
 238+
 239+ self::link => WCAttributeEnum::text,
 240+ self::url => WCAttributeEnum::text,
 241+
 242+ self::callNumber => WCAttributeEnum::text,
 243+ self::doi => WCAttributeEnum::text,
 244+ self::isbn => WCAttributeEnum::text,
 245+
 246+ self::date => WCAttributeEnum::date,
 247+ self::accessed => WCAttributeEnum::date,
 248+ self::issued => WCAttributeEnum::date,
 249+ self::filed => WCAttributeEnum::date,
 250+ );
 251+
 252+ public static $magicWordArray;
 253+ public static $flipMagicWordKeys = array();
 254+
 255+ protected $attributeEnum;
 256+
 257+ public static function init() {
 258+ parent::init( self::$magicWordKeys, self::$substitutes,
 259+ self::$magicWordArray, self::$flipMagicWordKeys );
 260+ self::$title = new self( self::title );
 261+ self::$shortTitle = new self( self::shortTitle );
 262+ self::$place = new self( self::place );
 263+ self::$edition = new self( self::edition );
 264+ self::$firstPage = new self( self::firstPage );
 265+ self::$version = new self( self::version );
 266+ self::$number = new self( self::number );
 267+ self::$archive = new self( self::archive );
 268+ self::$jurisdiction = new self( self::jurisdiction );
 269+ self::$keyword = new self( self::keyword );
 270+
 271+ self::$page = new self( self::page );
 272+ self::$pageRange = new self( self::pageRange );
 273+ self::$volume = new self( self::volume );
 274+ self::$issue = new self( self::issue );
 275+ self::$opus = new self( self::opus );
 276+ self::$bookLoc = new self( self::bookLoc );
 277+ self::$part = new self( self::part );
 278+ self::$chapterLoc = new self( self::chapterLoc );
 279+ self::$folio = new self( self::folio );
 280+ self::$column = new self( self::column );
 281+ self::$table = new self( self::table );
 282+ self::$figure = new self( self::figure );
 283+ self::$section = new self( self::section );
 284+ self::$paragraph = new self( self::paragraph );
 285+ self::$noteLoc = new self( self::noteLoc );
 286+ self::$footnote = new self( self::footnote );
 287+ self::$endnote = new self( self::endnote );
 288+ self::$verse = new self( self::verse );
 289+ self::$line = new self( self::line );
 290+ self::$locator = new self( self::locator );
 291+
 292+ self::$type = new self( self::type );
 293+
 294+ self::$link = new self( self::link );
 295+ self::$url = new self( self::url );
 296+
 297+ self::$callNumber = new self( self::callNumber );
 298+ self::$doi = new self( self::doi );
 299+ self::$isbn = new self( self::isbn );
 300+
 301+ self::$date = new self( self::date );
 302+ self::$accessed = new self( self::accessed );
 303+ self::$issued = new self( self::issued );
 304+ self::$filed = new self( self::filed );
 305+ }
 306+
 307+ /**
 308+ * Identity the appropriate WCAttributeEnum for this property.
 309+ *
 310+ * @return WCAttributeEnum
 311+ */
 312+ public function getAttribute() {
 313+ return new WCAttributeEnum( self::$attributeClasses[ $this->key ] );
 314+ }
 315+
 316+ /**
 317+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 318+ */
 319+ public function __construct( $key = self::__default ) {
 320+ parent::__construct( $key );
 321+ $subs = &self::$substitutes[ $this->key ];
 322+ if ( $subs ) {
 323+ $this->substituteArray = $subs;
 324+ }
 325+ }
 326+ /**
 327+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 328+ */
 329+ public static function match( $parameterText ) {
 330+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 331+ if ( $id ) {
 332+ return new self( self::$flipMagicWordKeys[ $id ] );
 333+ } else {
 334+ return Null;
 335+ }
 336+ }
 337+ /**
 338+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 339+ */
 340+ public static function matchVariable( $parameterText ) {
 341+ list( $id, $var ) = self::$magicWordArray->matchVariableStartToEnd( $parameterText );
 342+ if ( $id ) {
 343+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $var );
 344+ } else {
 345+ return Null;
 346+ }
 347+ }
 348+ /**
 349+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 350+ */
 351+ public static function matchPrefix( $parameterText ) {
 352+ $id = self::$magicWordArray->matchStartAndRemove( $parameterText );
 353+ if ( $id ) {
 354+ # Remove any initial punctuation or spaces
 355+ $parameterText = preg_replace( '/^[\p{P}\p{Z}\p{C}]+/u', '', $parameterText );
 356+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $parameterText );
 357+ } else {
 358+ return array( Null, $parameterText );
 359+ }
 360+ }
 361+ /**
 362+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 363+ */
 364+ public static function matchPartAndNumber( $parameterText ) {
 365+ # Extract number and remove number, white spaces and punctuation.
 366+ if ( preg_match( '/\d+/u', $parameterText, $matches ) ) {
 367+ $numString = $matches[0];
 368+ $num = (int) $numString;
 369+ $parameterText = preg_replace( '/' . $numString . '|[\p{P}\p{Z}\p{C}]+/uS', '', $parameterText );
 370+ } else {
 371+ $num = 1;
 372+ }
 373+ # Match what remains.
 374+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 375+ if ( $id ) {
 376+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $num );
 377+ } else {
 378+ return array( Null, $num );
 379+ }
 380+ }
 381+
 382+
 383+}
 384+WCPropertyEnum::init();
Property changes on: trunk/extensions/WikiCitation/includes/parameters/WCPropertyEnum.php
___________________________________________________________________
Added: svn:eol-style
1385 + native
Index: trunk/extensions/WikiCitation/includes/parameters/WCNamePartEnum.php
@@ -0,0 +1,122 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCNamePartEnum extends WCParameterEnum {
 12+ const literal = 0;
 13+ const surname = 1;
 14+ const given = 2;
 15+ const nameLink = 3;
 16+ const suffix = 4;
 17+ const droppingParticle = 5;
 18+ const nonDroppingParticle = 6;
 19+ const __default = self::literal;
 20+
 21+ public static $literal;
 22+ public static $surname;
 23+ public static $given;
 24+ public static $nameLink;
 25+ public static $suffix;
 26+ public static $droppingParticle;
 27+ public static $nonDroppingParticle;
 28+
 29+
 30+ public static $magicWordKeys = array(
 31+ self::surname => 'wc_surname',
 32+ self::given => 'wc_given',
 33+ self::literal => 'wc_literalname',
 34+ self::nameLink => 'wc_namelink',
 35+ self::suffix => 'wc_suffix',
 36+ self::droppingParticle => 'wc_droppingparticle',
 37+ self::nonDroppingParticle => 'wc_nondroppingparticle',
 38+ );
 39+ public static $substitutes = array();
 40+ public static $magicWordArray;
 41+ public static $flipMagicWordKeys = array();
 42+
 43+ public static function init() {
 44+ parent::init( self::$magicWordKeys, self::$substitutes,
 45+ self::$magicWordArray, self::$flipMagicWordKeys );
 46+ self::$surname = new self( self::surname );
 47+ self::$given = new self( self::given );
 48+ self::$literal = new self( self::literal );
 49+ self::$nameLink = new self( self::nameLink );
 50+ self::$suffix = new self( self::suffix );
 51+ self::$droppingParticle = new self( self::droppingParticle );
 52+ self::$nonDroppingParticle = new self( self::nonDroppingParticle );
 53+ }
 54+
 55+ /**
 56+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 57+ */
 58+ public function __construct( $key = self::__default ) {
 59+ parent::__construct( $key );
 60+ $subs = &self::$substitutes[ $this->key ];
 61+ if ( $subs ) {
 62+ $this->substituteArray = $subs;
 63+ }
 64+ }
 65+ /**
 66+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 67+ */
 68+ public static function match( $parameterText ) {
 69+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 70+ if ( $id ) {
 71+ return new self( self::$flipMagicWordKeys[ $id ] );
 72+ } else {
 73+ return Null;
 74+ }
 75+ }
 76+ /**
 77+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 78+ */
 79+ public static function matchVariable( $parameterText ) {
 80+ list( $id, $var ) = self::$magicWordArray->matchVariableStartToEnd( $parameterText );
 81+ if ( $id ) {
 82+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $var );
 83+ } else {
 84+ return Null;
 85+ }
 86+ }
 87+ /**
 88+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 89+ */
 90+ public static function matchPrefix( $parameterText ) {
 91+ $id = self::$magicWordArray->matchStartAndRemove( $parameterText );
 92+ if ( $id ) {
 93+ # Remove any initial punctuation or spaces
 94+ $parameterText = preg_replace( '/^[\p{P}\p{Z}\p{C}]+/u', '', $parameterText );
 95+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $parameterText );
 96+ } else {
 97+ return array( Null, $parameterText );
 98+ }
 99+ }
 100+ /**
 101+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 102+ */
 103+ public static function matchPartAndNumber( $parameterText ) {
 104+ # Extract number and remove number, white spaces and punctuation.
 105+ if ( preg_match( '/\d+/u', $parameterText, $matches ) ) {
 106+ $numString = $matches[0];
 107+ $num = (int) $numString;
 108+ $parameterText = preg_replace( '/' . $numString . '|[\p{P}\p{Z}\p{C}]+/uS', '', $parameterText );
 109+ } else {
 110+ $num = 1;
 111+ }
 112+ # Match what remains.
 113+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 114+ if ( $id ) {
 115+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $num );
 116+ } else {
 117+ return array( Null, $num );
 118+ }
 119+ }
 120+
 121+
 122+}
 123+WCNamePartEnum::init();
Property changes on: trunk/extensions/WikiCitation/includes/parameters/WCNamePartEnum.php
___________________________________________________________________
Added: svn:eol-style
1124 + native
Index: trunk/extensions/WikiCitation/includes/parameters/WCDateTermsEnum.php
@@ -0,0 +1,145 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * Magic word enumerations
 13+ */
 14+class WCDateTermsEnum extends WCParameterEnum {
 15+ const nothing = 0;
 16+ const spring = 1;
 17+ const summer = 2;
 18+ const autumn = 3;
 19+ const winter = 4;
 20+ const AD = 5;
 21+ const BC = 6;
 22+ const yearTerm = 7;
 23+ const monthTerm = 8;
 24+ const dayTerm = 9;
 25+ const circa = 10;
 26+ const number = 11;
 27+ const namedMonth = 12;
 28+
 29+ public static $nothing;
 30+ public static $spring;
 31+ public static $summer;
 32+ public static $autumn;
 33+ public static $winter;
 34+ public static $AD;
 35+ public static $BC;
 36+ public static $yearTerm;
 37+ public static $monthTerm;
 38+ public static $dayTerm;
 39+ public static $circa;
 40+ public static $number;
 41+ public static $namedMonth;
 42+
 43+ public static $magicWordKeys = array(
 44+ self::spring => 'wc_spring',
 45+ self::summer => 'wc_summer',
 46+ self::autumn => 'wc_autumn',
 47+ self::winter => 'wc_winter',
 48+ self::AD => 'wc_ad_magic_word',
 49+ self::BC => 'wc_bc_magic_word',
 50+ self::yearTerm => 'wc_year',
 51+ self::monthTerm => 'wc_month',
 52+ self::dayTerm => 'wc_day',
 53+ self::circa => 'wc_circa',
 54+# self::rangeDelimeter => 'wc_range',
 55+ );
 56+ public static $substitutes = array();
 57+ public static $magicWordArray;
 58+ public static $flipMagicWordKeys = array();
 59+
 60+ public static function init() {
 61+ parent::init( self::$magicWordKeys, self::$substitutes,
 62+ self::$magicWordArray, self::$flipMagicWordKeys );
 63+ self::$nothing = new self( self::nothing );
 64+ self::$spring = new self( self::spring );
 65+ self::$summer = new self( self::summer );
 66+ self::$autumn = new self( self::autumn );
 67+ self::$winter = new self( self::winter );
 68+ self::$AD = new self( self::AD );
 69+ self::$BC = new self( self::BC );
 70+ self::$yearTerm = new self( self::yearTerm );
 71+ self::$monthTerm = new self( self::monthTerm );
 72+ self::$dayTerm = new self( self::dayTerm );
 73+ self::$circa = new self( self::circa );
 74+ self::$number = new self( self::number );
 75+ self::$namedMonth = new self( self::namedMonth );
 76+ }
 77+
 78+ /**
 79+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 80+ */
 81+ public function __construct( $key = self::__default ) {
 82+ parent::__construct( $key );
 83+ $subs = &self::$substitutes[ $this->key ];
 84+ if ( $subs ) {
 85+ $this->substituteArray = $subs;
 86+ }
 87+ }
 88+ /**
 89+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 90+ */
 91+ public static function match( $parameterText ) {
 92+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 93+ if ( $id ) {
 94+ return new self( self::$flipMagicWordKeys[ $id ] );
 95+ } else {
 96+ return Null;
 97+ }
 98+ }
 99+ /**
 100+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 101+ */
 102+ public static function matchVariable( $parameterText ) {
 103+ list( $id, $var ) = self::$magicWordArray->matchVariableStartToEnd( $parameterText );
 104+ if ( $id ) {
 105+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $var );
 106+ } else {
 107+ return Null;
 108+ }
 109+ }
 110+ /**
 111+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 112+ */
 113+ public static function matchPrefix( $parameterText ) {
 114+ $id = self::$magicWordArray->matchStartAndRemove( $parameterText );
 115+ if ( $id ) {
 116+ # Remove any initial punctuation or spaces
 117+ $parameterText = preg_replace( '/^[\p{P}\p{Z}\p{C}]+/u', '', $parameterText );
 118+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $parameterText );
 119+ } else {
 120+ return array( Null, $parameterText );
 121+ }
 122+ }
 123+ /**
 124+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 125+ */
 126+ public static function matchPartAndNumber( $parameterText ) {
 127+ # Extract number and remove number, white spaces and punctuation.
 128+ if ( preg_match( '/\d+/u', $parameterText, $matches ) ) {
 129+ $numString = $matches[0];
 130+ $num = (int) $numString;
 131+ $parameterText = preg_replace( '/' . $numString . '|[\p{P}\p{Z}\p{C}]+/uS', '', $parameterText );
 132+ } else {
 133+ $num = 1;
 134+ }
 135+ # Match what remains.
 136+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 137+ if ( $id ) {
 138+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $num );
 139+ } else {
 140+ return array( Null, $num );
 141+ }
 142+ }
 143+
 144+
 145+}
 146+WCDateTermsEnum::init();
Property changes on: trunk/extensions/WikiCitation/includes/parameters/WCDateTermsEnum.php
___________________________________________________________________
Added: svn:eol-style
1147 + native
Index: trunk/extensions/WikiCitation/includes/parameters/WCSeasonEnum.php
@@ -0,0 +1,112 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * Magic word enumerations
 13+ */
 14+class WCSeasonEnum extends WCParameterEnum {
 15+ const spring = 0;
 16+ const summer = 1;
 17+ const autumn = 2;
 18+ const winter = 3;
 19+ const __default = self::spring;
 20+
 21+ public static $spring;
 22+ public static $summer;
 23+ public static $autumn;
 24+ public static $winter;
 25+
 26+ public static $magicWordKeys = array(
 27+ self::spring => 'wc_spring',
 28+ self::summer => 'wc_summer',
 29+ self::autumn => 'wc_autumn',
 30+ self::winter => 'wc_winter',
 31+ );
 32+ public static $substitutes = array();
 33+ public static $magicWordArray;
 34+ public static $flipMagicWordKeys = array();
 35+
 36+ public static function init() {
 37+ parent::init( self::$magicWordKeys, self::$substitutes,
 38+ self::$magicWordArray, self::$flipmagicWordKeys );
 39+ self::$spring = new self( self::spring );
 40+ self::$summer = new self( self::summer );
 41+ self::$autumn = new self( self::autumn );
 42+ self::$winter = new self( self::winter );
 43+ }
 44+
 45+ /**
 46+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 47+ */
 48+ public function __construct( $key = self::__default ) {
 49+ parent::__construct( $key );
 50+ $subs = &self::$substitutes[ $this->key ];
 51+ if ( $subs ) {
 52+ $this->substituteArray = $subs;
 53+ }
 54+ }
 55+ /**
 56+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 57+ */
 58+ public static function match( $parameterText ) {
 59+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 60+ if ( $id ) {
 61+ return new self( self::$flipMagicWordKeys[ $id ] );
 62+ } else {
 63+ return Null;
 64+ }
 65+ }
 66+ /**
 67+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 68+ */
 69+ public static function matchVariable( $parameterText ) {
 70+ list( $id, $var ) = self::$magicWordArray->matchVariableStartToEnd( $parameterText );
 71+ if ( $id ) {
 72+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $var );
 73+ } else {
 74+ return Null;
 75+ }
 76+ }
 77+ /**
 78+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 79+ */
 80+ public static function matchPrefix( $parameterText ) {
 81+ $id = self::$magicWordArray->matchStartAndRemove( $parameterText );
 82+ if ( $id ) {
 83+ # Remove any initial punctuation or spaces
 84+ $parameterText = preg_replace( '/^[\p{P}\p{Z}\p{C}]+/u', '', $parameterText );
 85+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $parameterText );
 86+ } else {
 87+ return array( Null, $parameterText );
 88+ }
 89+ }
 90+ /**
 91+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 92+ */
 93+ public static function matchPartAndNumber( $parameterText ) {
 94+ # Extract number and remove number, white spaces and punctuation.
 95+ if ( preg_match( '/\d+/u', $parameterText, $matches ) ) {
 96+ $numString = $matches[0];
 97+ $num = (int) $numString;
 98+ $parameterText = preg_replace( '/' . $numString . '|[\p{P}\p{Z}\p{C}]+/uS', '', $parameterText );
 99+ } else {
 100+ $num = 1;
 101+ }
 102+ # Match what remains.
 103+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 104+ if ( $id ) {
 105+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $num );
 106+ } else {
 107+ return array( Null, $num );
 108+ }
 109+ }
 110+
 111+
 112+}
 113+WCSeasonEnum::init();
Property changes on: trunk/extensions/WikiCitation/includes/parameters/WCSeasonEnum.php
___________________________________________________________________
Added: svn:eol-style
1114 + native
Index: trunk/extensions/WikiCitation/includes/parameters/WCScopeEnum.php
@@ -0,0 +1,119 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCScopeEnum extends WCParameterEnum {
 12+ const work = 0;
 13+ const container = 1;
 14+ const series = 2;
 15+ const original = 3;
 16+ const subject = 4;
 17+ const __default = self::work;
 18+
 19+ public static $work;
 20+ public static $container;
 21+ public static $series;
 22+ public static $original;
 23+ public static $subject;
 24+
 25+ public static $magicWordKeys = array(
 26+ self::work => 'wc_work',
 27+ self::container => 'wc_container',
 28+ self::series => 'wc_series',
 29+ self::original => 'wc_original',
 30+ self::subject => 'wc_subject'
 31+ );
 32+ public static $substitutes = array (
 33+ self::work => array( self::work, self::original, self::subject ),
 34+ self::container => array( self::container, self::series ),
 35+ self::series => array( self::series, self::container ),
 36+ self::original => array( self::original ),
 37+ self::subject => array( self::subject )
 38+ );
 39+ public static $magicWordArray;
 40+ public static $flipMagicWordKeys = array();
 41+
 42+ public static function init() {
 43+ parent::init( self::$magicWordKeys, self::$substitutes,
 44+ self::$magicWordArray, self::$flipMagicWordKeys );
 45+ self::$work = new self( self::work );
 46+ self::$container = new self( self::container );
 47+ self::$series = new self( self::series );
 48+ self::$original = new self( self::original );
 49+ self::$subject = new self( self::subject );
 50+ }
 51+
 52+ /**
 53+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 54+ */
 55+ public function __construct( $key = self::__default ) {
 56+ parent::__construct( $key );
 57+ $subs = &self::$substitutes[ $this->key ];
 58+ if ( $subs ) {
 59+ $this->substituteArray = $subs;
 60+ }
 61+ }
 62+ /**
 63+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 64+ */
 65+ public static function match( $parameterText ) {
 66+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 67+ if ( $id ) {
 68+ return new self( self::$flipMagicWordKeys[ $id ] );
 69+ } else {
 70+ return Null;
 71+ }
 72+ }
 73+ /**
 74+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 75+ */
 76+ public static function matchVariable( $parameterText ) {
 77+ list( $id, $var ) = self::$magicWordArray->matchVariableStartToEnd( $parameterText );
 78+ if ( $id ) {
 79+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $var );
 80+ } else {
 81+ return Null;
 82+ }
 83+ }
 84+ /**
 85+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 86+ */
 87+ public static function matchPrefix( $parameterText ) {
 88+ $id = self::$magicWordArray->matchStartAndRemove( $parameterText );
 89+ if ( $id ) {
 90+ # Remove any initial punctuation or spaces
 91+ $parameterText = preg_replace( '/^[\p{P}\p{Z}\p{C}]+/u', '', $parameterText );
 92+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $parameterText );
 93+ } else {
 94+ return array( Null, $parameterText );
 95+ }
 96+ }
 97+ /**
 98+ * Delete when moving to PHP 3.3 and use late static binding in WCParameterEnum.
 99+ */
 100+ public static function matchPartAndNumber( $parameterText ) {
 101+ # Extract number and remove number, white spaces and punctuation.
 102+ if ( preg_match( '/\d+/u', $parameterText, $matches ) ) {
 103+ $numString = $matches[0];
 104+ $num = (int) $numString;
 105+ $parameterText = preg_replace( '/' . $numString . '|[\p{P}\p{Z}\p{C}]+/uS', '', $parameterText );
 106+ } else {
 107+ $num = 1;
 108+ }
 109+ # Match what remains.
 110+ $id = self::$magicWordArray->matchStartToEnd( $parameterText );
 111+ if ( $id ) {
 112+ return array( new self( self::$flipMagicWordKeys[ $id ] ), $num );
 113+ } else {
 114+ return array( Null, $num );
 115+ }
 116+ }
 117+
 118+
 119+}
 120+WCScopeEnum::init();
Property changes on: trunk/extensions/WikiCitation/includes/parameters/WCScopeEnum.php
___________________________________________________________________
Added: svn:eol-style
1121 + native
Property changes on: trunk/extensions/WikiCitation/includes/parameters
___________________________________________________________________
Added: bugtraq:number
2122 + true
Index: trunk/extensions/WikiCitation/includes/WCEnum.php
@@ -0,0 +1,46 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * An enum class.
 13+ */
 14+abstract class WCEnum /* extends SplEnum {PHP 5.3} */ {
 15+
 16+ /**
 17+ * Default value if none is specified.
 18+ */
 19+ const __default = 0;
 20+
 21+
 22+ /**
 23+ * An integer key.
 24+ * @var integer
 25+ */
 26+ public $key;
 27+
 28+
 29+ /**
 30+ * Constructor.
 31+ * Takes a unique integer key, which should be defined as a class constant.
 32+ * @param integer $key
 33+ */
 34+ public function __construct( $key = self::__default ) {
 35+ $this->key = $key;
 36+ }
 37+
 38+
 39+ /**
 40+ * The string value, unless overridden, is the name of the constant.
 41+ * @return string
 42+ */
 43+ public function __toString() {
 44+ $object = new ReflectionClass( $this );
 45+ return array_search( $this->key, $object->getConstants() );
 46+ }
 47+}
Property changes on: trunk/extensions/WikiCitation/includes/WCEnum.php
___________________________________________________________________
Added: svn:eol-style
148 + native
Index: trunk/extensions/WikiCitation/includes/WCSection.php
@@ -0,0 +1,209 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCSection {
 12+
 13+ public $citationStyle, $citationType;
 14+
 15+ protected static $citeStyleAttributeWords, $typeAttributeWords;
 16+
 17+ protected $cites = array();
 18+
 19+ protected $notes = array();
 20+
 21+ protected $noteCount = 1;
 22+
 23+ protected $endnoteMarker;
 24+
 25+ protected $subsection;
 26+
 27+ protected $styleHTML;
 28+
 29+
 30+ /**
 31+ * Static initializer.
 32+ */
 33+ public static function init() {
 34+ $citeStyleMW = MagicWord::get( 'wc_citestyle_attrib' );
 35+ self::$citeStyleAttributeWords = $citeStyleMW->getSynonyms();
 36+ $typeMW = MagicWord::get( 'wc_type_attrib' );
 37+ self::$typeAttributeWords = $typeMW->getSynonyms();
 38+ }
 39+
 40+
 41+ /**
 42+ * Get a new WCSection object based on HTML arguments.
 43+ * @param array $args = "citeStyle" or "type" (or equivalent foreign words)
 44+ * @param WCStyle $defaultStyle
 45+ * @param WCCitationTypeEnum $defaultType
 46+ * @return WCSection
 47+ */
 48+ public static function getSection( array $args, $defaultStyle, $defaultType ) {
 49+ foreach( $args as $attrib => $value ) {
 50+ if ( in_array( $attrib, self::$citeStyleAttributeWords ) ) {
 51+ $styleClassName = WCArgumentReader::matchStyleClassName( $value );
 52+ } elseif ( in_array( $attrib, self::$typeAttributeWords ) ) {
 53+ $citationTypeID = WCCitationTypeEnum::match( $value );
 54+ if ( isset( $citationTypeID ) ) {
 55+ $citationType = new WCCitationTypeEnum( $citationTypeID );
 56+ }
 57+ } elseif ( $args[ 'style' ] ) {
 58+ $this->styleHTML = ' style="' . $args[ 'style' ] . '"';
 59+ } elseif ( $args[ 'id' ] ) {
 60+ $this->styleHTML = ' id="' . $args[ 'id' ] . '"';
 61+ }
 62+ }
 63+ if ( isset( $styleClassName ) ) {
 64+ # See if a specific style object has already been defined, and if so, use it.
 65+ $styleObject = WCArticle::getStyle( $styleClassName );
 66+ } else {
 67+ # Use default citation style.
 68+ $styleObject = $defaultStyle;
 69+ }
 70+ if ( isset( $citationType ) ) {
 71+ return new WCSection( $styleObject, $citationType );
 72+ } else {
 73+ return new WCSection( $styleObject, $defaultType );
 74+ }
 75+ }
 76+
 77+ /**
 78+ * Constructor.
 79+ * WCSection objects will normally be created through WCSection::getSection(...).
 80+ * @param WCStyle $style
 81+ * @param WCCitationTypeEnum $type
 82+ */
 83+ public function __construct( WCStyle $style, WCCitationTypeEnum $type ) {
 84+ $this->citationStyle = $style;
 85+ $this->citationType = $type;
 86+ }
 87+
 88+
 89+ /**
 90+ * Add an inline citation (not within an endnote).
 91+ * @param integer $key
 92+ * @param integer $distance
 93+ */
 94+ public function addInlineCite( $key, $citation ) {
 95+ $this->cites[] = $key;
 96+ # If citation length was not explicitly defined, it will be:
 97+ # long if the first citation in the section to that reference, short otherwise
 98+ if ( is_null ( $citation->citationLength) ) {
 99+ $citation->citationLength =
 100+ $citation->distance === 0 ? WCCitationLengthEnum::$long : WCCitationLengthEnum::$short;
 101+ }
 102+ }
 103+
 104+
 105+ /**
 106+ * Create a new footnote.
 107+ * @param array $args
 108+ */
 109+ public function startNote( array $args ) {
 110+ $this->notes[ $this->noteCount ] = WCNote::getNote( $args, $this->citationStyle );
 111+ }
 112+
 113+
 114+ /**
 115+ * Add a citation within an endnote.
 116+ * @param int $key
 117+ * @param boolean $isNew
 118+ * @param WCArticle $article
 119+ */
 120+ public function addNoteCite( $key, WCCitation $citation ) {
 121+ $this->notes[ $this->noteCount ]->addNoteCite( $key, $citation );
 122+ }
 123+
 124+
 125+ /**
 126+ * Store the text of the current footnote and return a marker for the subscript number.
 127+ * @param string $text
 128+ * @return string
 129+ */
 130+ public function finishNote( $text ) {
 131+ return $this->notes[ $this->noteCount ]->getSuperscript( $text, $this->noteCount++ );
 132+ }
 133+
 134+
 135+ /**
 136+ * Parse endmotes and Add an endnote citation.
 137+ * @return string
 138+ */
 139+ public function addEndnotes() {
 140+ $marker = 'EwC-' . mt_rand();
 141+ $this->endnoteMarker = $marker;
 142+ return $marker;
 143+ }
 144+
 145+
 146+ /**
 147+ * Render a section: replace markers for citations, endnote numbers, and endnotes.
 148+ * @param unknown_type $text
 149+ * @param array ( int => WCCitation )
 150+ * @param boolean bibliographyExists
 151+ */
 152+ public function render( &$text, $citations, $bibliographyExists ) {
 153+
 154+ /**
 155+ * Replace inline citation markers.
 156+ */
 157+ if ( $this->cites ) {
 158+ $currentStyle = $this->citationStyle;
 159+ $currentType = $this->citationType;
 160+ $textCitations = $markers = array();
 161+ foreach( $this->cites as $key ) {
 162+ $citation = $citations[ $key ];
 163+
 164+ # If an explicit style has been defined for $key, use it; otherwise, use the previous style.
 165+ if ( isset( $citation->style ) ) {
 166+ $currentStyle = $citation->style;
 167+ } else {
 168+ $citation->style = $currentStyle;
 169+ }
 170+ if ( isset( $citation->citationType ) ) {
 171+ $currentType = $citation->citationType;
 172+ } else {
 173+ $citation->citationType = $currentType;
 174+ }
 175+
 176+ list( $textCitation, ) = $citation->render();
 177+ $pos = strpos( $text, $citation->marker );
 178+ if ( $pos !== false ) {
 179+ $text = substr_replace( $text, $textCitation, $pos, strlen( $citation->marker ) );
 180+ }
 181+ }
 182+ }
 183+
 184+ /**
 185+ * Replace endnote marker with rendered endnotes.
 186+ */
 187+ if ( $this->endnoteMarker ) {
 188+ if ( $this->notes ) {
 189+ $endnoteText = '<ol class="endnotes"' . $this->styleHTML . '>' . PHP_EOL;
 190+ foreach( $this->notes as $key => $note ) {
 191+ $endnoteText .= $note->render( $bibliographyExists );
 192+ }
 193+ $endnoteText .= '</ol>';
 194+ } else {
 195+ $endnoteText = '';
 196+ }
 197+ $pos = strpos( $text, $this->endnoteMarker );
 198+ if ( $pos !== false ) {
 199+ $text = substr_replace( $text, $endnoteText, $pos, strlen( $this->endnoteMarker ) );
 200+ }
 201+ }
 202+ }
 203+
 204+}
 205+
 206+
 207+/**
 208+ * Static initializer.
 209+ */
 210+WCBibliography::init();
Property changes on: trunk/extensions/WikiCitation/includes/WCSection.php
___________________________________________________________________
Added: svn:eol-style
1211 + native
Index: trunk/extensions/WikiCitation/includes/WCArgumentReader.php
@@ -0,0 +1,249 @@
 2+<?php
 3+
 4+/**
 5+ * Part of WikiCitation extension for Mediawiki.
 6+ *
 7+ * @ingroup WikiCitation
 8+ * @file
 9+ */
 10+
 11+/**
 12+ * Factory function, which parses the raw parser function arguments upon construction.
 13+ * Class createWCStyle instantiates an appropriate child class based on the first
 14+ * parameter after the colon.
 15+ */
 16+class WCArgumentReader {
 17+
 18+ /**
 19+ * citation type
 20+ *
 21+ * note, biblio, or inline
 22+ * @var WCCitationTypeEnum
 23+ */
 24+ public $citationType;
 25+
 26+ /**
 27+ * Citation length
 28+ *
 29+ * long or short
 30+ * @var WCCitationLengthEnum
 31+ */
 32+ public $citationLength;
 33+
 34+ /**
 35+ * Array of flag values.
 36+ * @var array
 37+ */
 38+ public $flags = array();
 39+ /**
 40+ * Array of parameters values keyed to parameter names.
 41+ * @var array
 42+ */
 43+ public $parameters = array();
 44+
 45+ # The name of the style class (e.g., WCChicagoStyle)
 46+ private $styleClassName;
 47+
 48+ # private data
 49+ private $parser;
 50+ private $frame;
 51+ private $args;
 52+ private static $styleMagicWords;
 53+
 54+ /**
 55+ * Static initializer.
 56+ */
 57+ public static function init() {
 58+ global $wgWCCitationStyles;
 59+ $citationStyleList = array_keys( $wgWCCitationStyles );
 60+ self::$styleMagicWords = new MagicWordArray( $citationStyleList );
 61+ }
 62+
 63+ /**
 64+ * Constructor. Parses the arguments, recognizes the citation style,
 65+ * and stores flags and parameters internally.
 66+ * @param PPFrame_DOM $frame
 67+ * @param array $args
 68+ */
 69+ public function __construct(Parser $parser, PPFrame_DOM $frame, array $args) {
 70+ $this->parser = $parser;
 71+ $this->frame = $frame;
 72+ $this->args = $args;
 73+
 74+ $this->parseArguments();
 75+ }
 76+
 77+ /**
 78+ * Get the name of the style class.
 79+ * @return string|boolean
 80+ */
 81+ public function getStyleClassName() {
 82+ return $this->styleClassName;
 83+ }
 84+
 85+
 86+ public function isEmpty() {
 87+ return empty( $this->parameters );
 88+ }
 89+
 90+
 91+ public function getCitationType() {
 92+ return $this->citationType;
 93+ }
 94+
 95+
 96+ public function getCitationLength() {
 97+ return $this->citationLength;
 98+ }
 99+
 100+
 101+ /**
 102+ * Parse options from $this->mArgs.
 103+ * Sets $this->citationStyle, $this->flags, and $this->parameters
 104+ * @internal
 105+ */
 106+ private function parseArguments() {
 107+
 108+ /**
 109+ * Parameter after the colon designates an explicit citation style.
 110+ * $this->arg[0] is a string, while the other arguments are of type
 111+ * PPNode_DOM. It is expanded anyway, in case the Parser class is
 112+ * revised in the future. See documentation for
 113+ * Parser::setFunctionHook().
 114+ * @var
 115+ */
 116+ $firstArg = reset( $this->args );
 117+ $style = trim( $this->frame->expand( $firstArg ) );
 118+ $this->styleClassName = $this->matchStyleClassName( $style );
 119+
 120+ # Check args for initial flags after the colon, but prior to any named parameters.
 121+ while (( $arg = next( $this->args ) ) !== False) {
 122+ list( $var, $value ) = $this->parseArgument( $arg );
 123+ if ($var) {
 124+ $this->parameters[$var] = $value;
 125+ break;
 126+ }
 127+ $this->flags[] = $value;
 128+ }
 129+
 130+ # Match the flags and set defaults.
 131+ $this->matchFlags();
 132+
 133+ # From now on, only look for named parameters.
 134+ while (( $arg = next( $this->args ) ) !== False) {
 135+ list( $var, $value ) = $this->parseArgument($arg);
 136+ if (!$var) {
 137+ continue;
 138+ }
 139+ $this->parameters[$var] = $value;
 140+ }
 141+ }
 142+
 143+ /**
 144+ * Parses an argument to extract a variable and/or a value
 145+ *
 146+ * @internal
 147+ * @param PPNode_DOM $arg Argument
 148+ * @return array a tuple of the variable (if exists) its corresponding value
 149+ */
 150+ protected function parseArgument( PPNode_DOM $arg ) {
 151+ /* if ( $arg instanceof PPNode_DOM ) { # See below: */
 152+ $bits = $arg->splitArg();
 153+ $index = $bits['index'];
 154+ if ($index === '') {
 155+ # Found
 156+ $var = trim($this->frame->expand($bits['name']));
 157+ $value = trim($this->frame->expand($bits['value']));
 158+ } else { # Not found
 159+ $var = Null;
 160+ $value = trim($this->frame->expand($arg));
 161+ }
 162+ /* This commented-out code would be required if $this->arg[0]
 163+ * were passed to this function, since that argument is pre-expanded
 164+ * and not a PPNode_DOM object, at least in the version of MediaWiki
 165+ * when this was written.
 166+ } else {
 167+ $parts = array_map('trim', explode( '=', $arg, 2 ) );
 168+ if ( count( $parts ) == 2 ) {
 169+ # Found "="
 170+ $var = $parts[ 0 ];
 171+ $value = $parts[ 1 ];
 172+ } else {
 173+ # Not found
 174+ $var = NULL;
 175+ $value = $arg;
 176+ }
 177+ }
 178+ */
 179+ return array( $var, $value );
 180+ }
 181+
 182+
 183+ protected static function matchStyleClassName( $styleText ) {
 184+ if ( $styleText ) {
 185+ $styleID = self::$styleMagicWords->matchStartToEnd( $styleText );
 186+ if ( $styleID === False && $wikiCitationValidateArguments ) {
 187+ throw new WCException( 'wc-style-not-recognized', $styleText );
 188+ }
 189+ global $wgWCCitationStyles;
 190+ return $wgWCCitationStyles[ $styleID ];
 191+ } else {
 192+ return Null;
 193+ }
 194+ }
 195+
 196+
 197+ /**
 198+ * Recognize and process the flags.
 199+ *
 200+ * @global type $wikiCitationValidateArguments
 201+ */
 202+ protected function matchFlags() {
 203+ global $wikiCitationValidateArguments;
 204+ foreach( $this->flags as $flag ) {
 205+ # Match flag for citation type.
 206+ $citationType = WCCitationTypeEnum::match( $flag );
 207+ if ( $citationType ) {
 208+ $this->citationType = $citationType;
 209+ continue;
 210+ }
 211+ # Match flag for citation length.
 212+ $citationLength = WCCitationLengthEnum::match( $flag );
 213+ if ( $citationLength ) {
 214+ $this->citationLength = $citationLength;
 215+ continue;
 216+ }
 217+ # If the function encounters an unknown flag, an error is thrown.
 218+ if ( $wikiCitationValidateArguments ) {
 219+ throw new WCException( 'wc-flag-unknown', $flag );
 220+ }
 221+ }
 222+
 223+ # Throw exception for explicit "short bibliography" citation.
 224+ if ( isset( $this->citationLength )
 225+ && isset( $this->citationLength )
 226+ && $this->citationLength->key == WCCitationLengthEnum::short
 227+ && $this->citationType->key == WCCitationTypeEnum::biblio
 228+ && $wikiCitationValidateArguments )
 229+ {
 230+ if ( $wikiCitationValidateArguments) {
 231+ throw new WCException(
 232+ 'wc-incompatible-flags',
 233+ new WCCitationLengthEnum( WCCitationLengthEnum::short ),
 234+ new WCCitationTypeEnum( WCCitationTypeEnum::biblio )
 235+ );
 236+ } else {
 237+ $this->citationLength->key = WCCitationLengthEnum::long;
 238+ }
 239+ }
 240+
 241+ }
 242+
 243+
 244+}
 245+
 246+
 247+/**
 248+ * Static initializer.
 249+ */
 250+WCArgumentReader::init();
Property changes on: trunk/extensions/WikiCitation/includes/WCArgumentReader.php
___________________________________________________________________
Added: svn:eol-style
1251 + native
Index: trunk/extensions/WikiCitation/includes/WCNote.php
@@ -0,0 +1,153 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCNote {
 12+
 13+ public $citationStyle, $citationType;
 14+
 15+ public $marker;
 16+
 17+ public $number;
 18+
 19+ protected $cites = array();
 20+
 21+ protected static $citeStyleAttributeWords, $typeAttributeWords;
 22+
 23+ protected $style, $type;
 24+
 25+ protected $text;
 26+
 27+ /**
 28+ * Static initializer.
 29+ */
 30+ public static function init() {
 31+ $citeStyleMW = MagicWord::get( 'wc_citestyle_attrib' );
 32+ self::$citeStyleAttributeWords = $citeStyleMW->getSynonyms();
 33+ $typeMW = MagicWord::get( 'wc_type_attrib' );
 34+ self::$typeAttributeWords = $typeMW->getSynonyms();
 35+ }
 36+
 37+ /**
 38+ * Get a new WCNote object based on HTML arguments.
 39+ * @param array $args = "citeStyle" or "type" (or equivalent foreign words)
 40+ * @param WCStyle $defaultStyle
 41+ * @param WCCitationTypeEnum $defaultType
 42+ * @return WCSection
 43+ */
 44+ public static function getNote( array $args, $defaultStyle ) {
 45+ foreach( $args as $attrib => $value ) {
 46+ if ( in_array( $attrib, self::$citeStyleAttributeWords ) ) {
 47+ $styleClassName = WCArgumentReader::matchStyleClassName( $value );
 48+ } elseif ( in_array( $attrib, self::$typeAttributeWords ) ) {
 49+ $citationTypeID = WCCitationTypeEnum::match( $value );
 50+ if ( isset( $citationTypeID ) ) {
 51+ $citationType = new WCCitationTypeEnum( $citationTypeID );
 52+ }
 53+ } elseif ( $args[ 'style' ] ) {
 54+ $this->styleHTML = ' style="' . $args[ 'style' ] . '"';
 55+ } elseif ( $args[ 'id' ] ) {
 56+ $this->styleHTML = ' id="' . $args[ 'id' ] . '"';
 57+ }
 58+ }
 59+ if ( isset( $styleClassName ) ) {
 60+ # See if a specific style object has already been defined, and if so, use it.
 61+ $styleObject = WCArticle::getStyle( $styleClassName );
 62+ } else {
 63+ # Use default citation style.
 64+ $styleObject = $defaultStyle;
 65+ }
 66+ if ( isset( $citationType ) ) {
 67+ return new WCNote( $styleObject, $citationType );
 68+ } else {
 69+ return new WCNote( $styleObject, WCCitationTypeEnum::$note );
 70+ }
 71+ }
 72+
 73+ public function __construct( WCStyle $style, WCCitationTypeEnum $type ) {
 74+ $this->citationStyle = $style;
 75+ $this->citationType = $type;
 76+ # Leave behind a marker, later to be replaced by the subscript.
 77+ $this->marker = 'NwC-' . mt_rand();
 78+ }
 79+
 80+
 81+ public function getSuperscript( $text, $number ) {
 82+ # Store the text, to be inserted in endnote list during $this->render().
 83+ $this->text = $text;
 84+ $this->number = $number;
 85+ # Leave behind a marker, later to be replaced by the subscript.
 86+ return '<sup id="t' . $this->marker . '" class="notesuperscript"><a href="#n' .
 87+ $this->marker . '">' . $number . '</a></sup>';
 88+ }
 89+
 90+
 91+ /**
 92+ * Add a single citation within the note.
 93+ * @param integer $key
 94+ * @param integer $distance = # of citations from last citation to this reference
 95+ * @param WCArticle $article
 96+ */
 97+ public function addNoteCite( $key, WCCitation $citation ) {
 98+ $this->cites[ $key ] = $citation;
 99+ }
 100+
 101+
 102+ /**
 103+ * Render the note.
 104+ * @param boolean $bibliographyExists
 105+ * @return string
 106+ */
 107+ public function render( $bibliographyExists ) {
 108+ # Replace citation markers in note with rendered citations.
 109+ if ( $this->cites ) {
 110+ $currentStyle = $this->citationStyle;
 111+ $currentType = $this->citationType;
 112+ foreach( $this->cites as $key => $citation ) {
 113+ # If an explicit style has been defined for $key, use it on subsequent citations.
 114+ if ( isset( $citation->style ) ) {
 115+ $currentStyle = $citation->style;
 116+ } else {
 117+ $citation->style = $currentStyle;
 118+ }
 119+ # If an explicit type has been defined, use it on subsequent citations.
 120+ if ( isset( $citation->citationType ) ) {
 121+ $currentType = $citation->citationType;
 122+ } else {
 123+ $citation->citationType = $currentType;
 124+ }
 125+ # The first citation is long, and subsequent citations are short.
 126+ # If there is a bibliography, they are all short.
 127+ if ( is_null ( $citation->citationLength) ) {
 128+ if ( $citation->distance === 0 && !$bibliographyExists ) {
 129+ $citation->citationLength = WCCitationLengthEnum::$long;
 130+ } else {
 131+ $citation->citationLength = WCCitationLengthEnum::$short;
 132+ }
 133+ }
 134+ list( $textCitation, ) = $citation->render();
 135+ $pos = strpos( $this->text, $citation->marker );
 136+ if ( $pos !== false ) {
 137+ $text = substr_replace( $this->text, $textCitation, $pos, strlen( $citation->marker ) );
 138+ }
 139+ }
 140+ }
 141+ $markedupText = '<li id="n' . $this->marker . '">';
 142+ $markedupText .= '<a href="#t' . $this->marker . '">' . $this->number . '</a>. ';
 143+ $markedupText .= $text;
 144+ $markedupText .= '</li>' . PHP_EOL;
 145+ return $markedupText;
 146+ }
 147+
 148+}
 149+
 150+
 151+/**
 152+ * Static initializer.
 153+ */
 154+WCBibliography::init();
Property changes on: trunk/extensions/WikiCitation/includes/WCNote.php
___________________________________________________________________
Added: svn:eol-style
1155 + native
Index: trunk/extensions/WikiCitation/includes/segments/WCGroupSegment.php
@@ -0,0 +1,148 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCGroupSegment extends WCSegment implements Countable {
 12+
 13+ public $segments;
 14+
 15+ protected $delimiter;
 16+
 17+ public function __construct(
 18+ array $segments = array(),
 19+ $delimiter = '',
 20+ $prefix = '',
 21+ $suffix = '' ) {
 22+ parent::__construct( $prefix, $suffix );
 23+ $this->segments = $segments;
 24+ $this->delimiter = $delimiter;
 25+ $this->exists = True;
 26+ }
 27+
 28+
 29+ public function exists() {
 30+ if ( $this->exists ) {
 31+ foreach ( $this->segments as $segment ) {
 32+ if ( $segment->exists() ) {
 33+ return True;
 34+ }
 35+ }
 36+ }
 37+ $this->exists = False;
 38+ return False;
 39+ }
 40+
 41+
 42+ public function count() {
 43+ $count = 0;
 44+ foreach ( $this->segments as $segment ) {
 45+ if ( $segment->exists() ) {
 46+ $count++;
 47+ }
 48+ }
 49+ return $count;
 50+ }
 51+
 52+
 53+ public function render( WCStyle $style, $endSeparator = '' ) {
 54+ $segments = $this->segments;
 55+ while ( $segments ) {
 56+ $lastSegment = array_pop( $segments );
 57+ if ( $lastSegment->exists() ) break;
 58+ }
 59+ if ( $lastSegment->exists() ) {
 60+ $text = $this->prefix;
 61+ foreach( $segments as $segment ) {
 62+ if ( $segment->exists() ) {
 63+ $text .= $segment->render( $style, $this->delimiter );
 64+ }
 65+ }
 66+ return $text . $lastSegment->render( $style, $this->extendSuffix( $endSeparator ) );
 67+ }
 68+ return '';
 69+ }
 70+
 71+
 72+ public function getSortingParts() {
 73+ $parts = array();
 74+ foreach( $this->segments as $segment ) {
 75+ if ( $segment->exists() ) {
 76+ $parts += $segment->getSortingParts();
 77+ }
 78+ }
 79+ return $parts;
 80+ }
 81+
 82+
 83+ /**
 84+ * Implements Iterator interface method.
 85+ * @return string
 86+ */
 87+ public function key() {
 88+ $segment = current( $this->segments );
 89+ return key( $this->segments) . '–' . $segment->key();
 90+ }
 91+
 92+
 93+ /**
 94+ * Implements Iterator interface method.
 95+ * @return WCSegment
 96+ */
 97+ public function current() {
 98+ $segment = current( $this->segments );
 99+ return $segment->current();
 100+ }
 101+
 102+
 103+ /**
 104+ * Implements Iterator interface method.
 105+ */
 106+ public function next() {
 107+ $currentSegment = current( $this->segments );
 108+ if ( $currentSegment === False ) {
 109+ return;
 110+ } else {
 111+ $currentSegment->next();
 112+ if ( ! $currentSegment->valid() ) {
 113+ while ( ! ( ( $nextSegment = next( $this->segments ) ) === False ) ) {
 114+ if ( $nextSegment->exists() ) {
 115+ $nextSegment->rewind();
 116+ if ( $nextSegment->valid() ) {
 117+ return;
 118+ }
 119+ }
 120+ }
 121+ }
 122+ }
 123+ }
 124+
 125+
 126+ /**
 127+ * Implements Iterator interface method.
 128+ * @return boolean
 129+ */
 130+ public function valid() {
 131+ $segment = current( $this->segments );
 132+ return ( ! ( $segment === False ) ) && $segment->valid() ;
 133+ }
 134+
 135+
 136+ /**
 137+ * Implements Iterator interface method.
 138+ */
 139+ public function rewind() {
 140+ $segment = reset( $this->segments );
 141+ while ( ! $segment->exists() ) {
 142+ if ( next( $this->segments ) == False ) {
 143+ return;
 144+ }
 145+ }
 146+ $segment->rewind();
 147+ }
 148+
 149+}
Property changes on: trunk/extensions/WikiCitation/includes/segments/WCGroupSegment.php
___________________________________________________________________
Added: svn:eol-style
1150 + native
Index: trunk/extensions/WikiCitation/includes/segments/WCLiteralSegment.php
@@ -0,0 +1,81 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCLiteralSegment extends WCSegment {
 12+
 13+ protected $text;
 14+
 15+ protected $reset;
 16+
 17+ public function __construct( $text ) {
 18+ parent::__construct();
 19+ $this->text = $text;
 20+ $this->exists = True;
 21+ }
 22+
 23+ public function render( WCStyle $style, $endSeparator = '' ) {
 24+ if ( $endSeparator ) {
 25+ $chrL = mb_substr( $this->text, -1, 1 );
 26+ $chrR = mb_substr( $endSeparator, 0, 1 );
 27+ if ( $chrL == $chrR ) {
 28+ $endSeparator = ltrim( $endSeparator, $chrR );
 29+ }
 30+ return $this->text . $endSeparator;
 31+ } else {
 32+ return $this->text;
 33+ }
 34+ }
 35+
 36+ public function getSortingParts() {
 37+ return array();
 38+ }
 39+
 40+ /**
 41+ * Implements Iterator interface method.
 42+ * @return string
 43+ */
 44+ public function key() {
 45+ return '1';
 46+ }
 47+
 48+
 49+ /**
 50+ * Implements Iterator interface method.
 51+ * @return WCSegment
 52+ */
 53+ public function current() {
 54+ return '';
 55+ }
 56+
 57+
 58+ /**
 59+ * Implements Iterator interface method.
 60+ */
 61+ public function next() {
 62+ $this->reset = False;
 63+ }
 64+
 65+
 66+ /**
 67+ * Implements Iterator interface method.
 68+ * @return boolean
 69+ */
 70+ public function valid() {
 71+ return $this->exists && $this->reset;
 72+ }
 73+
 74+
 75+ /**
 76+ * Implements Iterator interface method.
 77+ */
 78+ public function rewind() {
 79+ $this->reset = True;;
 80+ }
 81+
 82+}
Property changes on: trunk/extensions/WikiCitation/includes/segments/WCLiteralSegment.php
___________________________________________________________________
Added: svn:eol-style
183 + native
Index: trunk/extensions/WikiCitation/includes/segments/WCDateSegment.php
@@ -0,0 +1,532 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * Enumerations
 13+ */
 14+class WCDateParts extends WCEnum {
 15+ const none = 0;
 16+ const year = 1;
 17+ const month = 2;
 18+ const day = 3;
 19+ const season = 4;
 20+ const yearMonth = 5;
 21+ const yearSeason = 6;
 22+ const monthDay = 7;
 23+ const yearMonthDay = 8;
 24+ const __default = self::none;
 25+}
 26+
 27+class WCDateOrder extends WCEnum {
 28+ const littleEndian = 0;
 29+ const middleEndian = 1;
 30+ const bigEndian = 2;
 31+ const __default = self::littleEndian;
 32+}
 33+
 34+class WCDateForm extends WCEnum {
 35+ const long = 0; # e.g., August
 36+ const short = 1; # e.g., Aug.
 37+ const numeric = 2; # e.g., 8
 38+ const numericLeadingZeros = 3; # e.g., 08
 39+ const ordinal = 4; # e.g., 8th -- not implemented yet
 40+ const __default = self::long;
 41+}
 42+
 43+class WCDateRange extends WCEnum {
 44+ const range = 0;
 45+ const first = 1;
 46+ const second = 2;
 47+ const __default = self::range;
 48+}
 49+
 50+class WCDateSegment extends WCDataSegment {
 51+
 52+ protected $dateObject;
 53+
 54+ protected $scope;
 55+
 56+ protected $propertyType;
 57+
 58+ protected $datePart, $dateOrder, $dateForm, $rangePart;
 59+
 60+ protected $rangePointOfDifference;
 61+
 62+ public function __construct(
 63+ WCCitation $citation,
 64+ WCSegmentImportance $importance,
 65+ WCScopeEnum $scope,
 66+ WCPropertyEnum $propertyType,
 67+ WCDateParts $datePart,
 68+ WCDateOrder $dateOrder,
 69+ WCDateForm $dateForm,
 70+ WCDateRange $dateRange,
 71+ $prefix = '',
 72+ $suffix = '' ) {
 73+ parent::__construct( $citation, $prefix, $suffix );
 74+ $this->datePart = $datePart;
 75+ $this->dateOrder = $dateOrder;
 76+ $this->dateForm = $dateForm;
 77+ $this->rangePart = $dateRange;
 78+ switch( $importance->key ) {
 79+ case WCSegmentImportance::mandatory:
 80+ $this->$dateObject = $citation->reference->inferProperty( $scope, $propertyType );
 81+ $this->exists = True;
 82+ return;
 83+ case WCSegmentImportance::important:
 84+ $this->dateObject = $citation->reference->inferProperty( $scope, $propertyType );
 85+ $this->exists = (bool) $this->dateObject;
 86+ break;
 87+ case WCSegmentImportance::optional:
 88+ $dateObject = $citation->reference->getProperty( $scope, $propertyType );
 89+ if ( isset( $dateObject ) ) {
 90+ $this->dateObject = $dateObject;
 91+ } else {
 92+ $this->exists = False;
 93+ }
 94+ }
 95+ # $scope and $propertyType may have changed as a side-effect of $citation->inferProperty.
 96+ $this->scope = $scope;
 97+ $this->propertyType = $propertyType;
 98+
 99+ # Determine if the date is a range and if so, where the point of difference is.
 100+ if ( isset ( $this->dateObject->year2 ) ) {
 101+ $this->rangePointOfDifference = WCDateParts::year;
 102+ } elseif ( isset ( $this->dateObject->month2 ) ) {
 103+ $this->rangePointOfDifference = WCDateParts::month;
 104+ } elseif ( isset ( $this->dateObject->day2 ) ) {
 105+ $this->rangePointOfDifference = WCDateParts::day;
 106+ } elseif ( isset ( $this->dateObject->season2 ) ) {
 107+ $this->rangePointOfDifference = WCDateParts::season;
 108+ } else {
 109+ $this->rangePointOfDifference = WCDateParts::none;
 110+ }
 111+
 112+ }
 113+
 114+
 115+ public function getLabel( WCStyle $style, WCLabelFormEnum $form, WCPluralEnum $plural ) {
 116+ return $style->propertyLabels[ $this->propertyType->key ][ $form->key ][ $plural->key ];
 117+ }
 118+
 119+
 120+ /**
 121+ * Set the part and form to render with any subsequent calls to render().
 122+ * @param WCDateParts $dateParts
 123+ * @param WCDateForm $dateForm
 124+ * @param int $rangePart
 125+ * @param string $prefix
 126+ * @param string $suffix
 127+ */
 128+ public function setPart( WCDateParts $datePart, $prefix = '', $suffix = '' ) {
 129+ $this->datePart = $datePart;
 130+ $this->prefix = $prefix;
 131+ $this->suffix = $suffix;
 132+ }
 133+
 134+
 135+ public function rangePointOfDifference() {
 136+ return $this->rangePointOfDifference;
 137+ }
 138+
 139+
 140+ public function count() {
 141+ return $this->rangePointOfDifference != WCDateParts::none;
 142+ }
 143+
 144+
 145+ public function getSortingParts() {
 146+ if ( $this->dateObject->era == WCDateTermsEnum::BC ) {
 147+ $arr = array( - $this->dateObject->year );
 148+ } else {
 149+ $arr = array( $this->dateObject->year );
 150+ }
 151+ if ( $this->dateObject->season ) {
 152+ $arr[] = $this->dateObject->season;
 153+ return $arr;
 154+ }
 155+ if ( $this->dateObject->month ) {
 156+ $arr[] = $this->dateObject->month;
 157+ }
 158+ if ( $this->dateObject->day ) {
 159+ $arr[] = $this->dateObject->day;
 160+ }
 161+ return $arr;
 162+
 163+ }
 164+
 165+
 166+ public function render( WCStyle $style, $endSeparator = '' ) {
 167+ if ( $this->dateObject ) {
 168+ switch( $this->rangePart->key ) {
 169+ case WCDateRange::range:
 170+ switch ( $this->datePart->key ) {
 171+ case WCDateParts::year:
 172+ $date = $this->renderYearRange();
 173+ break;
 174+ case WCDateParts::month:
 175+ $date = $this->renderMonthRange();
 176+ break;
 177+ case WCDateParts::day:
 178+ $date = $this->renderDayRange();
 179+ break;
 180+ case WCDateParts::season:
 181+ $date = $this->renderSeasonRange();
 182+ break;
 183+ case WCDateParts::yearMonthDay:
 184+ switch( $this->dateOrder->key ) {
 185+ case WCDateOrder::littleEndian:
 186+ switch ( $this->rangePointOfDifference() ) {
 187+ case WCDateParts::none:
 188+ $date = $this->renderDay() . ' ' . $this->renderMonth() . ' ' . $this->renderYear();
 189+ break;
 190+ case WCDateParts::year:
 191+ $date = $this->renderDay() . ' ' . $this->renderMonth() . ' ' . $this->renderYear() . ' – ' . $this->renderDay2() . ' ' . $this->renderMonth2() . ' ' . $this->renderYear2();
 192+ break;
 193+ case WCDateParts::month:
 194+ $date = $this->renderDay() . ' ' . $this->renderMonth() . ' – ' . $this->renderDay2() . ' ' . $this->renderMonth2() . ' ' . $this->renderYear();
 195+ break;
 196+ case WCDateParts::day:
 197+ $date = $this->renderDayRange() . ' ' . $this->renderMonth() . ' ' . $this->renderYear();
 198+ break;
 199+ case WCDateParts::season:
 200+ $date = $this->renderSeasonRange() . ' ' . $this->renderYear();
 201+ break;
 202+ default:
 203+ throw new MWException( 'Point of difference is not defined' );
 204+ }
 205+ break;
 206+ case WCDateOrder::middleEndian:
 207+ switch ( $this->rangePointOfDifference() ) {
 208+ case WCDateParts::none:
 209+ $date = $this->renderMonth() . ' ' . $this->renderDay() . ', ' . $this->renderYear();
 210+ break;
 211+ case WCDateParts::year:
 212+ $date = $this->renderMonth() . ' ' . $this->renderDay() . ', ' . $this->renderYear() . ' – ' . $this->renderMonth2() . ' ' . $this->renderDay2() . ', ' . $this->renderYear2();
 213+ break;
 214+ case WCDateParts::month:
 215+ $date = $this->renderMonth() . ' ' . $this->renderDay() . ' – ' . $this->renderMonth2() . ' ' . $this->renderDay2() . ', ' . $this->renderYear();
 216+ break;
 217+ case WCDateParts::day:
 218+ $date = $this->renderMonth() . ' ' . $this->renderDayRange() . ', ' . $this->renderYear();
 219+ break;
 220+ case WCDateParts::season:
 221+ $date = $this->renderSeasonRange() . ' ' . $this->renderYear();
 222+ default:
 223+ throw new MWException( 'Point of difference is not defined' );
 224+ }
 225+ break;
 226+ case WCDateOrder::bigEndian:
 227+ switch ( $this->rangePointOfDifference() ) {
 228+ case WCDateParts::none:
 229+ $date = $this->renderYear() . ' ' . $this->renderMonth() . ' ' . $this->renderDay();
 230+ break;
 231+ case WCDateParts::year:
 232+ $date = $this->renderYear() . ' ' . $this->renderMonth() . ' ' . $this->renderDay() . ' – ' . $this->renderYear2() . ' ' . $this->renderMonth2() . ' ' . $this->renderDay2();
 233+ break;
 234+ case WCDateParts::month:
 235+ $date = $this->renderYear() . ' ' . $this->renderMonth() . ' ' . $this->renderDay() . ' – ' . $this->renderMonth2() . ' ' . $this->renderDay2();
 236+ break;
 237+ case WCDateParts::day:
 238+ $date = $this->renderYear() . ' ' . $this->renderMonth() . ' ' . $this->renderDayRange();
 239+ break;
 240+ case WCDateParts::season:
 241+ $date = $this->renderYear() . ' ' . $this->renderSeasonRange();
 242+ break;
 243+ default:
 244+ throw new MWException( 'Point of difference is not defined' );
 245+ }
 246+ break;
 247+ default:
 248+ $date = $this->renderDayFirstFull();
 249+ }
 250+ break;
 251+ default:
 252+ throw new MWException( 'Date part is not defined' );
 253+ }
 254+ break;
 255+ case WCDateRange::first:
 256+ switch ( $this->datePart->key ) {
 257+ case WCDateParts::year:
 258+ $date = $this->renderYear();
 259+ break;
 260+ case WCDateParts::month:
 261+ $date = $this->renderMonth();
 262+ break;
 263+ case WCDateParts::day:
 264+ $date = $this->renderDay();
 265+ break;
 266+ case WCDateParts::season:
 267+ $date = $this->renderSeason();
 268+ break;
 269+ default:
 270+ throw new MWException( '$this->datePart is not defined' );
 271+ }
 272+ break;
 273+ case WCDateRange::second:
 274+ switch ( $this->datePart->key ) {
 275+ case WCDateParts::year:
 276+ $date = $this->renderYear2();
 277+ break;
 278+ case WCDateParts::month:
 279+ $date = $this->renderMonth2();
 280+ break;
 281+ case WCDateParts::day:
 282+ $date = $this->renderDay2();
 283+ break;
 284+ case WCDateParts::season:
 285+ $date = $this->renderSeason2();
 286+ break;
 287+ default:
 288+ throw new MWException( 'Date part is not defined' );
 289+ }
 290+ }
 291+ $endSeparator = $this->extendSuffix( $endSeparator );
 292+ if ( $endSeparator ) {
 293+ $chrL = mb_substr( $date, -1, 1 );
 294+ $chrR = mb_substr( $endSeparator, 0, 1 );
 295+ if ( $chrL == $chrR ) {
 296+ $endSeparator = ltrim( $endSeparator, $chrR );
 297+ }
 298+ $date .= $endSeparator;
 299+ }
 300+ return $this->prefix . $date;
 301+ } else {
 302+ return $this->prefix . $style->segmentMissing . $this->extendSuffix( $endSeparator );
 303+ }
 304+ }
 305+
 306+
 307+ protected function renderYearRange() {
 308+ if ( isset ( $this->dateObject->year ) ) {
 309+ if ( isset( $this->dateObject->year2 ) ) {
 310+ switch ( $this->dateForm->key ) {
 311+ case WCDateForm::long:
 312+ case WCDateForm::numeric:
 313+ return $this->dateObject->year . '–' . $this->dateObject->year2;
 314+ case WCDateForm::short:
 315+ case WCDateForm::leadingZeros:
 316+ if ( $this->dateObject->year >= 1900 ) {
 317+ return str_pad( $this->dateObject->year % 100, 2, '0', STR_PAD_LEFT ) . '–'
 318+ . str_pad( $this->dateObject->year2 % 100, 2, '0', STR_PAD_LEFT );
 319+ }
 320+ else {
 321+ return $this->dateObject->year . '–' . $this->dateObject->year2;
 322+ }
 323+ }
 324+ }
 325+ else {
 326+ switch ( $this->dateForm->key ) {
 327+ case WCDateForm::long:
 328+ case WCDateForm::numeric:
 329+ return (string) $this->dateObject->year;
 330+ case WCDateForm::short:
 331+ case WCDateForm::leadingZeros:
 332+ if ( $this->dateObject->year >= 1900 ) return str_pad( $this->dateObject->year % 100, 2, '0', STR_PAD_LEFT );
 333+ else return (string) $this->dateObject->year;
 334+ }
 335+ }
 336+ }
 337+ else {
 338+ return Null;
 339+ }
 340+ }
 341+
 342+
 343+ protected function renderYear() {
 344+ if ( isset ( $this->dateObject->year ) ) {
 345+ switch ( $this->dateForm->key ) {
 346+ case WCDateForm::long:
 347+ case WCDateForm::numeric:
 348+ return (string) $this->dateObject->year;
 349+ case WCDateForm::short:
 350+ case WCDateForm::leadingZeros:
 351+ if ( $this->dateObject->year >= 1900 ) return str_pad( $this->dateObject->year % 100, 2, '0', STR_PAD_LEFT );
 352+ else return (string) $this->dateObject->year;
 353+ }
 354+ }
 355+ else {
 356+ return Null;
 357+ }
 358+ }
 359+
 360+
 361+ protected function renderYear2() {
 362+ if ( isset ( $this->dateObject->year2 ) ) {
 363+ switch ( $this->dateForm->key ) {
 364+ case WCDateForm::long:
 365+ case WCDateForm::numeric:
 366+ return (string) $this->dateObject->year2;
 367+ case WCDateForm::short:
 368+ case WCDateForm::leadingZeros:
 369+ if ( $this->dateObject->year2 >= 1900 ) return str_pad( $this->dateObject->year2 % 100, 2, '0', STR_PAD_LEFT );
 370+ else return (string) $this->dateObject->year2;
 371+ }
 372+ }
 373+ else {
 374+ return Null;
 375+ }
 376+ }
 377+
 378+
 379+ protected function renderMonthRange() {
 380+ if ( isset ( $this->dateObject->month ) ) {
 381+ if ( isset( $this->dateObject->month2 ) ) {
 382+ switch ( $this->dateForm->key ) {
 383+ case WCDateForm::long:
 384+ case WCDateForm::short:
 385+ case WCDateForm::numeric:
 386+ return $this->dateObject->month . '–' . $this->month2;
 387+ case WCDateForm::numericLeadingZeros:
 388+ return str_pad( $this->dateObject->month, 2, '0', STR_PAD_LEFT ) . '–'
 389+ . str_pad( $this->dateObject->month2, 2, '0', STR_PAD_LEFT );
 390+ }
 391+ }
 392+ else {
 393+ switch ( $this->dateForm->key ) {
 394+ case WCDateForm::long:
 395+ case WCDateForm::numeric:
 396+ return (string) $this->dateObject->month;
 397+ case WCDateForm::short:
 398+ case WCDateForm::numericLeadingZeros:
 399+ return str_pad( $this->dateObject->month, 2, '0', STR_PAD_LEFT );
 400+ }
 401+ }
 402+ }
 403+ else {
 404+ return Null;
 405+ }
 406+ }
 407+
 408+
 409+ protected function renderMonth() {
 410+ if ( isset ( $this->dateObject->month ) ) {
 411+ switch ( $this->dateForm->key ) {
 412+ case WCDateForm::long:
 413+ case WCDateForm::numeric:
 414+ return (string) $this->dateObject->month;
 415+ case WCDateForm::short:
 416+ case WCDateForm::numericLeadingZeros:
 417+ return str_pad( $this->dateObject->month, 2, '0', STR_PAD_LEFT );
 418+ }
 419+ }
 420+ else {
 421+ return Null;
 422+ }
 423+ }
 424+
 425+
 426+ protected function renderMonth2() {
 427+ if ( isset ( $this->dateObject->month2 ) ) {
 428+ switch ( $this->dateForm->key ) {
 429+ case WCDateForm::long:
 430+ case WCDateForm::numeric:
 431+ return (string) $this->dateObject->month2;
 432+ case WCDateForm::short:
 433+ case WCDateForm::numericLeadingZeros:
 434+ return str_pad( $this->dateObject->month2, 2, '0', STR_PAD_LEFT );
 435+ }
 436+ }
 437+ else {
 438+ return Null;
 439+ }
 440+ }
 441+
 442+
 443+ protected function renderDayRange() {
 444+ if ( isset ( $this->dateObject->day ) ) {
 445+ if ( isset( $this->dateObject->day2 ) ) {
 446+ switch ( $this->dateForm->key ) {
 447+ case WCDateForm::numeric:
 448+ return $this->dateObject->day . '–' . $this->day2;
 449+ case WCDateForm::numericLeadingZeros:
 450+ return str_pad( $this->dateObject->day, 2, '0', STR_PAD_LEFT ) . '–'
 451+ . str_pad( $this->dateObject->day2, 2, '0', STR_PAD_LEFT );
 452+ case WCDateForm::ordinal:
 453+ # This must wait until we can use PHP 5.3 NumberFormatter.
 454+ return (string) $this->dateObject->day;
 455+ }
 456+ }
 457+ else {
 458+ switch ( $this->dateForm->key ) {
 459+ case WCDateForm::numeric:
 460+ return (string) $this->dateObject->day;
 461+ case WCDateForm::numericLeadingZeros:
 462+ return str_pad( $this->dateObject->day, 2, '0', STR_PAD_LEFT );
 463+ case WCDateForm::ordinal:
 464+ # This must wait until we can use PHP 5.3 NumberFormatter.
 465+ return $this->dateObject->day . '–' . $this->day2;
 466+ }
 467+ }
 468+ }
 469+ }
 470+
 471+
 472+ protected function renderDay() {
 473+ switch ( $this->dateForm->key ) {
 474+ case WCDateForm::numeric:
 475+ return (string) $this->dateObject->day;
 476+ case WCDateForm::numericLeadingZeros:
 477+ return str_pad( $this->dateObject->day, 2, '0', STR_PAD_LEFT );
 478+ case WCDateForm::ordinal:
 479+ # This must wait until we can use PHP 5.3 NumberFormatter.
 480+ return (string) $this->dateObject->day;
 481+ }
 482+ }
 483+
 484+
 485+ protected function renderDay2() {
 486+ switch ( $this->dateForm->key ) {
 487+ case WCDateForm::numeric:
 488+ return (string) $this->dateObject->day2;
 489+ case WCDateForm::numericLeadingZeros:
 490+ return str_pad( $this->dateObject->day2, 2, '0', STR_PAD_LEFT );
 491+ case WCDateForm::ordinal:
 492+ # This must wait until we can use PHP 5.3 NumberFormatter.
 493+ return (string) $this->dateObject->day2;
 494+ }
 495+ }
 496+
 497+
 498+ protected function renderSeasonRange() {
 499+ if ( isset( $this->dateObject->season ) ) {
 500+ if ( isset( $this->dateObject->season2 ) ) {
 501+ return $this->dateObject->season . '–' . $this->dateObject->season2;
 502+ }
 503+ else {
 504+ return $this->dateObject->season;
 505+ }
 506+ }
 507+ else {
 508+ return Null;
 509+ }
 510+ }
 511+
 512+
 513+ protected function renderSeason() {
 514+ if ( isset( $this->dateObject->season ) ) {
 515+ return $this->dateObject->season;
 516+ }
 517+ else {
 518+ return Null;
 519+ }
 520+ }
 521+
 522+
 523+ protected function renderSeason2() {
 524+ if ( isset( $this->dateObject->season2 ) ) {
 525+ return $this->dateObject->season2;
 526+ }
 527+ else {
 528+ return Null;
 529+ }
 530+ }
 531+
 532+
 533+}
Property changes on: trunk/extensions/WikiCitation/includes/segments/WCDateSegment.php
___________________________________________________________________
Added: svn:eol-style
1534 + native
Index: trunk/extensions/WikiCitation/includes/segments/WCAlternativeSegment.php
@@ -0,0 +1,39 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCAlternativeSegment extends WCWrapperSegment {
 12+
 13+ /**
 14+ * Choose the first alternative in the array that exists, and cancel all
 15+ * other alternatives.
 16+ * @param array $segments Array of WCSegment objects.
 17+ */
 18+ public function __construct( array $segments = array() ) {
 19+ $this->exists = False;
 20+ $theSegment = Null;
 21+ foreach ( $segments as $segment ) {
 22+ if ( $segment->exists() ) {
 23+ if ( $this->exists ) {
 24+ $segment->cancel();
 25+ } else {
 26+ $this->exists = True;
 27+ $theSegment = $segment;
 28+ }
 29+ }
 30+ }
 31+ parent::__construct( $theSegment );
 32+ }
 33+
 34+
 35+ public function render( WCStyle $style, $endSeparator = '' ) {
 36+ return $this->segment->render( $style, $endSeparator );
 37+ }
 38+
 39+
 40+}
Property changes on: trunk/extensions/WikiCitation/includes/segments/WCAlternativeSegment.php
___________________________________________________________________
Added: svn:eol-style
141 + native
Index: trunk/extensions/WikiCitation/includes/segments/WCLabelSegment.php
@@ -0,0 +1,99 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCLabelFormEnum extends WCEnum {
 12+ const none = 0;
 13+ const long = 1;
 14+ const verb = 2;
 15+ const short = 3;
 16+ const verbShort = 4;
 17+ const symbol = 5;
 18+ const __default = self::none;
 19+}
 20+
 21+
 22+class WCPluralEnum extends WCEnum {
 23+ const singular = 0;
 24+ const plural = 1;
 25+ const __default = self::singular;
 26+}
 27+
 28+
 29+class WCLabelPluralEnum extends WCEnum {
 30+ const contextual = 0;
 31+ const always = 1;
 32+ const never = 2;
 33+ const __default = self::contextual;
 34+}
 35+
 36+
 37+class WCRelativePositionEnum extends WCEnum {
 38+ const before = 0;
 39+ const after = 1;
 40+ const __default = self::before;
 41+}
 42+
 43+
 44+class WCLabelSegment extends WCWrapperSegment {
 45+
 46+ protected $segment;
 47+ protected $positionEnum, $labelForm, $labelTextCase, $plural;
 48+
 49+ public function __construct(
 50+ WCDataSegment $segment,
 51+ WCRelativePositionEnum $positionEnum,
 52+ WCLabelFormEnum $labelForm,
 53+ WCTextCaseEnum $labelTextCase,
 54+ WCLabelPluralEnum $labelPlural,
 55+ $prefix = '',
 56+ $suffix = '' ) {
 57+ $this->segment = $segment;
 58+ $this->positionEnum = $positionEnum;
 59+ $this->labelForm = $labelForm;
 60+ $this->labelTextCase = $labelTextCase;
 61+ if ( $segment->exists() ) {
 62+ $this->exists = True;
 63+ } else {
 64+ $this->exists = False;
 65+ return;
 66+ }
 67+ switch ( $labelPlural->key ) {
 68+ case WCLabelPluralEnum::contextual:
 69+ if ( count( $segment ) > 1 ) {
 70+ $this->plural = new WCPluralEnum( WCPluralEnum::plural );
 71+ } else {
 72+ $this->plural = new WCPluralEnum( WCPluralEnum::singular );
 73+ }
 74+ break;
 75+ case WCLabelPluralEnum::always:
 76+ $this->plural = new WCPluralEnum( WCPluralEnum::plural );
 77+ break;
 78+ case WCLabelPluralEnum::never:
 79+ $this->plural = new WCPluralEnum( WCPluralEnum::singular );
 80+ }
 81+
 82+ }
 83+
 84+
 85+ public function render( WCStyle $style, $endSeparator = '' ) {
 86+ $label = $this->segment->getLabel( $style, $this->labelForm, $this->plural );
 87+ $label = $style->capitalize( $label, $this->labelTextCase );
 88+
 89+ if ( $label ) {
 90+ if ( $this->positionEnum->key == WCRelativePositionEnum::before ) {
 91+ $this->prefix = $label . ' ' . $this->prefix;
 92+ } else { # WCRelativePositionEnum::after
 93+ $this->suffix .= ', ' . $label;
 94+ }
 95+ return $this->prefix . $this->segment->render( $style, $this->extendSuffix( $endSeparator ) );
 96+ }
 97+ }
 98+
 99+
 100+}
Property changes on: trunk/extensions/WikiCitation/includes/segments/WCLabelSegment.php
___________________________________________________________________
Added: svn:eol-style
1101 + native
Index: trunk/extensions/WikiCitation/includes/segments/WCSegment.php
@@ -0,0 +1,52 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+abstract class WCSegment implements Iterator {
 12+
 13+ protected $prefix;
 14+
 15+ protected $suffix;
 16+
 17+ protected $exists;
 18+
 19+ public function __construct( $prefix = '', $suffix = '' ) {
 20+ $this->prefix = $prefix;
 21+ $this->suffix = $suffix;
 22+ }
 23+
 24+ public function exists() {
 25+ return $this->exists;
 26+ }
 27+
 28+ public function cancel() {
 29+ $this->exists = False;
 30+ }
 31+
 32+ abstract public function render( WCStyle $style, $endSeparator = '' );
 33+
 34+ protected function extendSuffix( $endSeparator ) {
 35+ if ( $this->suffix ) {
 36+ if ( $endSeparator ) {
 37+ $chrL = mb_substr( $this->suffix, -1, 1 );
 38+ $chrR = mb_substr( $endSeparator, 0, 1 );
 39+ if ( $chrL == $chrR ) {
 40+ $endSeparator = ltrim( $endSeparator, $chrR );
 41+ }
 42+ return $this->suffix . $endSeparator;
 43+ } else {
 44+ return $this->suffix;
 45+ }
 46+ } else {
 47+ return $endSeparator;
 48+ }
 49+ }
 50+
 51+ abstract public function getSortingParts();
 52+
 53+}
Property changes on: trunk/extensions/WikiCitation/includes/segments/WCSegment.php
___________________________________________________________________
Added: svn:eol-style
154 + native
Index: trunk/extensions/WikiCitation/includes/segments/WCWrapperSegment.php
@@ -0,0 +1,87 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCWrapperSegment extends WCSegment {
 12+
 13+ protected $segment;
 14+
 15+ public function __construct( $segment, $prefix = '', $suffix = '' ) {
 16+ parent::__construct( $prefix, $suffix );
 17+ $this->segment = $segment;
 18+ }
 19+
 20+
 21+ public function exists() {
 22+ if ( $this->exists ) {
 23+ if ( $this->segment->exists() ) {
 24+ return True;
 25+ } else {
 26+ $this->exists = False;
 27+ }
 28+ }
 29+ $this->exists = False;
 30+ return False;
 31+ }
 32+
 33+
 34+ public function render( WCStyle $style, $endSeparator = '' ) {
 35+ return $this->prefix . $this->segment->render( $style, $this->extendSuffix( $endSeparator ) );
 36+ }
 37+
 38+
 39+ public function getSortingParts() {
 40+ if ( $this->exists ) {
 41+ return $this->segment->getSortingParts();
 42+ }
 43+ }
 44+
 45+
 46+ /**
 47+ * Implements Iterator interface method.
 48+ * @return string
 49+ */
 50+ public function key() {
 51+ return $this->segment->key();
 52+ }
 53+
 54+
 55+ /**
 56+ * Implements Iterator interface method.
 57+ * @return WCSegment
 58+ */
 59+ public function current() {
 60+ return $this->segment->current();
 61+ }
 62+
 63+
 64+ /**
 65+ * Implements Iterator interface method.
 66+ */
 67+ public function next() {
 68+ $this->segment->next();
 69+ }
 70+
 71+
 72+ /**
 73+ * Implements Iterator interface method.
 74+ * @return boolean
 75+ */
 76+ public function valid() {
 77+ return $this->exists && $this->segment->valid();
 78+ }
 79+
 80+
 81+ /**
 82+ * Implements Iterator interface method.
 83+ */
 84+ public function rewind() {
 85+ $this->segment->rewind();
 86+ }
 87+
 88+}
Property changes on: trunk/extensions/WikiCitation/includes/segments/WCWrapperSegment.php
___________________________________________________________________
Added: svn:eol-style
189 + native
Index: trunk/extensions/WikiCitation/includes/segments/WCTitleSegment.php
@@ -0,0 +1,139 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCTitleSegment extends WCDataSegment {
 12+
 13+ protected $titleObject;
 14+
 15+ protected $titleFormat;
 16+
 17+ protected $scope;
 18+
 19+ protected $propertyType;
 20+
 21+ public function __construct(
 22+ WCCitation $citation,
 23+ WCSegmentImportance $importance,
 24+ WCScopeEnum $scope,
 25+ WCPropertyEnum $propertyType,
 26+ WCTitleFormat $titleFormat,
 27+ $prefix = '',
 28+ $suffix = ''
 29+ ) {
 30+ parent::__construct( $citation, $prefix, $suffix );
 31+ $this->titleFormat = $titleFormat;
 32+ switch( $importance->key ) {
 33+ case WCSegmentImportance::mandatory:
 34+ $this->titleObject = $citation->reference->inferProperty( $scope, $propertyType );
 35+ $this->exists = True;
 36+ return;
 37+ case WCSegmentImportance::important:
 38+ $this->titleObject = $citation->reference->inferProperty( $scope, $propertyType );
 39+ $this->exists = (bool) $this->titleObject;
 40+ break;
 41+ case WCSegmentImportance::optional:
 42+ $titleObject = &$citation->properties[ $scope->key ][ $propertyType->key ];
 43+ if ( isset( $titleObject ) ) {
 44+ $this->titleObject = $titleObject;
 45+ $this->exists = True;
 46+ } else {
 47+ $this->exists = False;
 48+ }
 49+ }
 50+ # $scope and $propertyType may have changed by now.
 51+ $this->scope = $scope;
 52+ $this->propertyType = $propertyType;
 53+ }
 54+
 55+
 56+ public function getLabel( WCStyle $style, WCLabelFormEnum $form, WCPluralEnum $plural ) {
 57+ return $style->propertyLabels[ $this->propertyType->key ][ $form->key ][ $plural->key ];
 58+ }
 59+
 60+
 61+ /**
 62+ * Format title with quotes and other optional styling.
 63+ *
 64+ * This will wrap the title in an HTML <cite> element. The title will also
 65+ * be quoted if the reference style is designated as a quoted-style
 66+ * title in WCTypeEnum::$titleFormat.
 67+ * @param WCStyle $style
 68+ * @param string $endSeparator
 69+ * @return string
 70+ */
 71+ public function render( WCStyle $style, $endSeparator = '' ) {
 72+ $endSeparator = $this->extendSuffix( $endSeparator );
 73+ if ( $this->titleObject ) {
 74+ $title = $this->titleObject->getTitle();
 75+
 76+ # "quoted"-type title
 77+ if ( $this->titleFormat->key == WCTitleFormat::quoted ) {
 78+
 79+ if ( $style->punctuationInQuotes ) { # Punctuation is inside quotes:
 80+
 81+ # Check for final quotes at the end of the title:
 82+ $p = preg_split( '/(<\/q>+)$/uS', $title, 2, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE );
 83+ if ( count( $p ) >= 2 ) {
 84+ $title = $p[0] . mb_substr( $endSeparator, 0, 1 ) . $p[1];
 85+ $title = $style->convertSemanticToCharacterQuotes( $title, True );
 86+ $title = $style->transformTitle( $title );
 87+ $title = '<cite class="' . WCStyle::quotedTitleHTML . '">' . $title . '</cite>';
 88+ $title = $style->quote( $title );
 89+ } else {
 90+ $title = $style->convertSemanticToCharacterQuotes( $title, True );
 91+ $title = $style->transformTitle( $title );
 92+ $chrL = mb_substr( $title, -1, 1 );
 93+ $chrR = mb_substr( $endSeparator, 0, 1 );
 94+ if ( $chrR && ( $chrL === $chrR ) ) {
 95+ # Wrap <cite> tag inside the quotes.
 96+ $title = '<cite class="' . WCStyle::quotedTitleHTML . '">' . $title . '</cite>';
 97+ $title = $style->quote( $title );
 98+ } else {
 99+ $title = $style->quote( $title . mb_substr( $endSeparator, 0, 1 ) );
 100+ # Wrap <cite> tag outside the quotes.
 101+ $title = '<cite class="' . WCStyle::quotedTitleHTML . '">' . $title . '</cite>';
 102+ }
 103+ }
 104+ return $this->prefix . $title . mb_substr( $endSeparator, 1 );
 105+ } else {
 106+ # Punctuation follows quotes.
 107+ $title = $style->convertSemanticToCharacterQuotes( $title, True );
 108+ $title = $style->transformTitle( $title );
 109+ $title = '<cite class="' . WCStyle::quotedTitleHTML . '">' . $title . '</cite>';
 110+ return $this->prefix . $style->quote( $title ) . $endSeparator;
 111+ }
 112+ }
 113+
 114+ # "italic"-type title
 115+ $title = $style->convertSemanticToCharacterQuotes( $title );
 116+ $title = $style->transformTitle( $title );
 117+ $chrL = mb_substr( $title, -1, 1 );
 118+ $chrR = mb_substr( $endSeparator, 0, 1 );
 119+ if ( $chrR && $chrL == $chrR ) {
 120+ $endSeparator = ltrim( $endSeparator, $chrR );
 121+ }
 122+ if ( $this->titleFormat->key == WCTitleFormat::italic ) {
 123+ # "Italic"-type title
 124+ return $this->prefix . '<cite class="' . WCStyle::italicTitleHTML . '">' . $title . '</cite>' . $endSeparator;
 125+ } else {
 126+ # WCTitleFormat::normal:
 127+ return $this->prefix . '<cite>' . $title . '</cite>' . $endSeparator;
 128+ }
 129+ } else {
 130+ return $this->prefix . $style->segmentMissing . $endSeparator;
 131+ }
 132+ }
 133+
 134+
 135+ public function getSortingParts() {
 136+ return array( strip_tags( $this->titleObject->getTitle() ) );
 137+ }
 138+
 139+
 140+}
Property changes on: trunk/extensions/WikiCitation/includes/segments/WCTitleSegment.php
___________________________________________________________________
Added: svn:eol-style
1141 + native
Index: trunk/extensions/WikiCitation/includes/segments/WCConditionalSegment.php
@@ -0,0 +1,48 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCConditionalSegment extends WCWrapperSegment {
 12+
 13+ /**
 14+ * Construct a conditional segment.
 15+ * If $condition is true, use the first segment.
 16+ * Otherwise, use the second segment if it is defined.
 17+ * If not defined, then segment does not exist.
 18+ */
 19+ public function __construct( $condition, WCSegment $segment1, WCSegment $segment2 = Null ) {
 20+ if ( $condition ) {
 21+ parent::__construct( $segment1 );
 22+ $this->exists = True;
 23+ } elseif ( $segment2 == Null ) {
 24+ $this->exists = False;
 25+ } else {
 26+ parent::__construct( $segment2 );
 27+ $this->exists = True;
 28+ }
 29+ }
 30+
 31+
 32+ /**
 33+ * Unlike other WCWrapperSegment objects, if the wrapper does not exist,
 34+ * the underlying segment is not cancelled. Thus, one may use a reference
 35+ * to the same (non-canceled) object in multiple places within a
 36+ * WCGroupSegment, turning them off independently.
 37+ * @return boolean
 38+ */
 39+ public function exists() {
 40+ return $this->exists;
 41+ }
 42+
 43+
 44+ public function render( WCStyle $style, $endSeparator = '' ) {
 45+ return $this->segment->render( $style, $endSeparator );
 46+ }
 47+
 48+
 49+}
Property changes on: trunk/extensions/WikiCitation/includes/segments/WCConditionalSegment.php
___________________________________________________________________
Added: svn:eol-style
150 + native
Index: trunk/extensions/WikiCitation/includes/segments/WCLocatorSegment.php
@@ -0,0 +1,78 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCLocatorSegment extends WCDataSegment {
 12+
 13+ /**
 14+ * The WCLocator object
 15+ * @var WCLocator
 16+ */
 17+ protected $locatorObject;
 18+
 19+ protected $locatorType;
 20+
 21+ public function __construct(
 22+ WCCitation $citation,
 23+ WCSegmentImportance $importance,
 24+ WCPropertyEnum $locatorType,
 25+ $prefix = '',
 26+ $suffix = '' ) {
 27+ parent::__construct( $citation, $prefix, $suffix );
 28+ switch( $importance->key ) {
 29+ case WCSegmentImportance::mandatory:
 30+ $this->locatorObject = $citation->inferLocator( $locatorType );
 31+ $this->exists = True;
 32+ return;
 33+ case WCSegmentImportance::important:
 34+ $this->locatorObject = $citation->inferLocator( $locatorType );
 35+ $this->exists = (bool) $this->locatorObject;
 36+ break;
 37+ case WCSegmentImportance::optional:
 38+ $locatorObject = $citation->getLocator( $locatorType );
 39+ if ( isset( $locatorObject ) ) {
 40+ $this->locatorObject = $locatorObject;
 41+ $this->exists = True;
 42+ } else {
 43+ $this->exists = False;
 44+ }
 45+ }
 46+ # $locatorType may have changed as a side-effect of $citation->inferLocator.
 47+ $this->locatorType = $locatorType;
 48+ }
 49+
 50+ public function getLabel( WCStyle $style, WCLabelFormEnum $form, WCPluralEnum $plural ) {
 51+ return $style->propertyLabels[ $this->locatorType->key ][ $form->key ][ $plural->key ];
 52+ }
 53+
 54+
 55+ public function render( WCStyle $style, $endSeparator = '' ) {
 56+ if ( $this->locatorObject ) {
 57+ return $this->prefix . $this->locatorObject->render( $this->extendSuffix( $endSeparator ) );
 58+ } else {
 59+ return $this->prefix . $style->segmentMissing . $this->extendSuffix( $endSeparator );
 60+ }
 61+ }
 62+
 63+
 64+ public function count() {
 65+ $count = count( $this->locatorObject->ranges );
 66+ if ( $count == 1 ) {
 67+ $count = count( reset( $this->locatorObject->ranges ) );
 68+ }
 69+ return $count;
 70+ }
 71+
 72+
 73+ public function getSortingParts() {
 74+ # Locators are not considered for sorting.
 75+ return array();
 76+ }
 77+
 78+
 79+}
Property changes on: trunk/extensions/WikiCitation/includes/segments/WCLocatorSegment.php
___________________________________________________________________
Added: svn:eol-style
180 + native
Index: trunk/extensions/WikiCitation/includes/segments/WCNamesSegment.php
@@ -0,0 +1,91 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCNamesSegment extends WCDataSegment {
 12+
 13+ protected $namesObject;
 14+
 15+ protected $scope;
 16+
 17+ protected $nameType;
 18+
 19+ protected $citationPosition;
 20+
 21+ protected $citationLength;
 22+
 23+ protected $nameSort;
 24+
 25+ public function __construct(
 26+ WCCitation $citation,
 27+ WCSegmentImportance $importance,
 28+ WCScopeEnum $scope,
 29+ WCNameTypeEnum $nameType,
 30+ WCCitationPosition $citationPosition,
 31+ WCCitationLengthEnum $citationLength,
 32+ $nameSort = False,
 33+ $prefix = '',
 34+ $suffix = '' ) {
 35+ parent::__construct( $citation, $prefix, $suffix );
 36+ $this->citationPosition = $citationPosition;
 37+ $this->citationLength = $citationLength;
 38+ $this->nameSort = $nameSort;
 39+
 40+ switch( $importance->key ) {
 41+ case WCSegmentImportance::mandatory:
 42+ $this->namesObject = $citation->reference->inferNames( $scope, $nameType );
 43+ $this->exists = True;
 44+ break;
 45+ case WCSegmentImportance::important:
 46+ $this->namesObject = $citation->reference->inferNames( $scope, $nameType );
 47+ $this->exists = (bool) $this->namesObject;
 48+ break;
 49+ case WCSegmentImportance::optional:
 50+ $namesObject = $citation->reference->getNames( $scope, $nameType );
 51+ if ( isset( $namesObject ) ) {
 52+ $this->namesObject = $namesObject;
 53+ $this->exists = True;
 54+ } else {
 55+ $this->exists = False;
 56+ }
 57+ }
 58+ # $scope and $nameType may have changed as a side-effect of $citation->inferNames.
 59+ $this->scope = $scope;
 60+ $this->nameType = $nameType;
 61+ }
 62+
 63+
 64+ public function getLabel( WCStyle $style, WCLabelFormEnum $form, WCPluralEnum $plural ) {
 65+ return $style->nameLabels[ $this->nameType->key ][ $form->key ][ $plural->key ];
 66+ }
 67+
 68+
 69+ public function count() {
 70+ return count( $this->namesObject );
 71+ }
 72+
 73+
 74+ public function render( WCStyle $style, $endSeparator = '' ) {
 75+ if ( $this->namesObject ) {
 76+ return $this->prefix . $this->namesObject->render( $style, $this->citationPosition, $this->citationLength, $this->extendSuffix( $endSeparator ), $this->nameSort );
 77+ } else {
 78+ return $this->prefix . $style->segmentMissing . $this->extendSuffix( $endSeparator );
 79+ }
 80+ }
 81+
 82+
 83+ public function getSortingParts() {
 84+ $arr = array();
 85+ foreach( $this->namesObject as $name ) {
 86+ $arr += $name->getSortingParts();
 87+ }
 88+ return $arr;
 89+ }
 90+
 91+
 92+}
Property changes on: trunk/extensions/WikiCitation/includes/segments/WCNamesSegment.php
___________________________________________________________________
Added: svn:eol-style
193 + native
Index: trunk/extensions/WikiCitation/includes/segments/WCTextSegment.php
@@ -0,0 +1,82 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCTextSegment extends WCDataSegment {
 12+
 13+ protected $textObject;
 14+
 15+ protected $scope;
 16+
 17+ protected $propertyType;
 18+
 19+ protected $blank;
 20+
 21+ public function __construct(
 22+ WCCitation $citation,
 23+ WCSegmentImportance $importance,
 24+ WCScopeEnum $scope,
 25+ WCPropertyEnum $propertyType,
 26+ $prefix = '',
 27+ $suffix = '' ) {
 28+ parent::__construct( $citation, $prefix, $suffix );
 29+ switch( $importance->key ) {
 30+ case WCSegmentImportance::mandatory:
 31+ $this->textObject = $citation->reference->inferProperty( $scope, $propertyType );
 32+ $this->exists = True;
 33+ return;
 34+ case WCSegmentImportance::important:
 35+ $this->textObject = $citation->reference->inferProperty( $scope, $propertyType );
 36+ $this->exists = (bool) $this->textObject;
 37+ break;
 38+ case WCSegmentImportance::optional:
 39+ $textObject = $citation->reference->getProperty( $scope, $propertyType );
 40+ if ( isset( $textObject ) ) {
 41+ $this->textObject = $textObject;
 42+ $this->exists = True;
 43+ } else {
 44+ $this->exists = False;
 45+ }
 46+ }
 47+ # $scope and $propertyType may have changed as a side-effect of $citation->inferProperty.
 48+ $this->scope = $scope;
 49+ $this->propertyType = $propertyType;
 50+ }
 51+
 52+
 53+ public function getLabel( WCStyle $style, WCLabelFormEnum $form, WCPluralEnum $plural ) {
 54+ return $style->propertyLabels[ $this->propertyType->key ][ $form->key ][ $plural->key ];
 55+ }
 56+
 57+
 58+ public function render( WCStyle $style, $endSeparator = '' ) {
 59+ $endSeparator = $this->extendSuffix( $endSeparator );
 60+ if ( $this->textObject ) {
 61+ $text = $this->textObject->getText();
 62+ if ( $endSeparator ) {
 63+ $chrL = mb_substr( $text, -1, 1 );
 64+ $chrR = mb_substr( $endSeparator, 0, 1 );
 65+ if ( $chrL == $chrR ) {
 66+ $endSeparator = ltrim( $endSeparator, $chrR );
 67+ }
 68+ return $this->prefix . $text . $endSeparator;
 69+ } else {
 70+ return $this->prefix . $text;
 71+ }
 72+ } else {
 73+ return $this->prefix . $style->segmentMissing . $endSeparator;
 74+ }
 75+ }
 76+
 77+
 78+ public function getSortingParts() {
 79+ return array( $this->textObject->getText() );
 80+ }
 81+
 82+
 83+}
Property changes on: trunk/extensions/WikiCitation/includes/segments/WCTextSegment.php
___________________________________________________________________
Added: svn:eol-style
184 + native
Index: trunk/extensions/WikiCitation/includes/segments/WCDataSegment.php
@@ -0,0 +1,73 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+abstract class WCDataSegment extends WCSegment implements Countable {
 12+
 13+ protected $citation;
 14+
 15+ protected $sortingParts;
 16+
 17+ public function __construct( WCCitation $citation, $prefix = '', $suffix = '' ) {
 18+ $this->citation = $citation;
 19+ $this->prefix = $prefix;
 20+ $this->suffix = $suffix;
 21+ }
 22+
 23+ abstract public function getLabel( WCStyle $style, WCLabelFormEnum $form, WCPluralEnum $plural );
 24+
 25+ public function count() {
 26+ return (int) $this->exists;
 27+ }
 28+
 29+
 30+ /**
 31+ * Implements Iterator interface method.
 32+ * @return string
 33+ */
 34+ public function key() {
 35+ return key( $this->sortingParts );
 36+ }
 37+
 38+
 39+ /**
 40+ * Implements Iterator interface method.
 41+ * @return WCSegment
 42+ */
 43+ public function current() {
 44+ return current( $this->sortingParts );
 45+ }
 46+
 47+
 48+ /**
 49+ * Implements Iterator interface method.
 50+ */
 51+ public function next() {
 52+ next( $this->sortingParts );
 53+ }
 54+
 55+
 56+ /**
 57+ * Implements Iterator interface method.
 58+ * @return boolean
 59+ */
 60+ public function valid() {
 61+ return (boolean) current( $this->sortingParts );
 62+ }
 63+
 64+
 65+ /**
 66+ * Implements Iterator interface method.
 67+ */
 68+ public function rewind() {
 69+ $this->sortingParts = $this->getSortingParts();
 70+ reset( $this->sortingParts );
 71+ }
 72+
 73+}
 74+
Property changes on: trunk/extensions/WikiCitation/includes/segments/WCDataSegment.php
___________________________________________________________________
Added: svn:eol-style
175 + native
Property changes on: trunk/extensions/WikiCitation/includes/segments
___________________________________________________________________
Added: bugtraq:number
276 + true
Index: trunk/extensions/WikiCitation/includes/data/WCName.php
@@ -0,0 +1,385 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * parts structure WCName.
 13+ * Contains all information needed to be known about one name,
 14+ * such as an author, editor, translator, composer, etc.
 15+ */
 16+class WCName extends WCData implements Iterator {
 17+
 18+ # The numerical order of the name.
 19+ public $nameNumber;
 20+
 21+ /**
 22+ * An array of name parts keyed to WCNamePartEnum keys
 23+ */
 24+ protected $parts = array();
 25+
 26+ /**
 27+ * Constructor.
 28+ * @param WCScopeEnum $scope = the scope (i.e., work, container, series, etc.)
 29+ * @param WCNameTypeEnum $nameType = the type of name.
 30+ * @param integer $nameNumber = the numerical order of the name.
 31+ */
 32+ public function __construct( $nameNumber ) {
 33+ $this->nameNumber = $nameNumber;
 34+ }
 35+
 36+
 37+ /**
 38+ * Implements Iterator interface method.
 39+ * @return type
 40+ */
 41+ public function key() {
 42+ return key( $this->parts );
 43+ }
 44+
 45+ /**
 46+ * Implements Iterator interface method.
 47+ * @return type
 48+ */
 49+ public function current() {
 50+ return current( $this->parts );
 51+ }
 52+
 53+ /**
 54+ * Implements Iterator interface method.
 55+ * @return type
 56+ */
 57+ public function next() {
 58+ return next( $this->parts );
 59+ }
 60+
 61+ /**
 62+ * Implements Iterator interface method.
 63+ * @return type
 64+ */
 65+ public function valid() {
 66+ return (bool) current( $this->parts );
 67+ }
 68+
 69+ /**
 70+ * Implements Iterator interface method.
 71+ * @return type
 72+ */
 73+ public function rewind() {
 74+ return reset( $this->parts );
 75+ }
 76+
 77+
 78+ public function getPart( $partKey ) {
 79+ if ( isset( $this->parts[ $partKey ] ) ) {
 80+ return $this->parts[ $partKey ];
 81+ } else {
 82+ return Null;
 83+ }
 84+ }
 85+
 86+
 87+ public function setPart( WCNamePartEnum $part, $value ) {
 88+ $this->parts[ $part->key ] = $value;
 89+ }
 90+
 91+
 92+ /**
 93+ * Determine if $this can be considered a short form of argument.
 94+ * If so, then determine the number of matches.
 95+ *
 96+ * @param WCName $name
 97+ * @return integer|boolean
 98+ */
 99+ public function shortFormMatches( WCData $name ) {
 100+ $matches = 0;
 101+ foreach( $this->parts as $partKey => $part ) {
 102+ $otherPart = $name->getPart( $partKey );
 103+ if ( isset( $otherPart ) && strnatcasecmp( $part, $otherPart ) === 0 ) {
 104+ ++$matches;
 105+ } else {
 106+ return False;
 107+ }
 108+ }
 109+ return $matches;
 110+
 111+ }
 112+
 113+
 114+ /**
 115+ * Composes a single name based on name parts and flags
 116+ *
 117+ * @param boolean $namesort = whether the surname appears first
 118+ * @return string = composed name
 119+ */
 120+ public function render(
 121+ WCStyle $style,
 122+ WCCitationLengthEnum $citationLength,
 123+ $endSeparator = '',
 124+ $namesort = False ) {
 125+
 126+
 127+ $surname = isset( $this->parts[ WCNamePartEnum::surname ] ) ?
 128+ $this->parts[ WCNamePartEnum::surname ] : Null;
 129+ $given = isset( $this->parts[ WCNamePartEnum::given ] ) ?
 130+ $this->transformGivenNames( $this->parts[ WCNamePartEnum::given ] ) : Null;
 131+ $link = isset( $this->parts[ WCNamePartEnum::nameLink ] ) ?
 132+ $this->parts[ WCNamePartEnum::nameLink ] : Null;
 133+ $dp = isset( $this->parts[ WCNamePartEnum::droppingParticle ] ) ?
 134+ $this->parts[ WCNamePartEnum::droppingParticle ] : Null;
 135+ $dpSpace = $ndpSpace = $suffixSpace = '';
 136+ if ( $dp ) {
 137+ # if the dropping particle ends in punctuation, there is no space between it and the surname or dropping particle.
 138+ if ( preg_match( '/\p{P}$/u', $dp, $matches ) ) {
 139+ $dpSpace = '';
 140+ } else {
 141+ $dpSpace = $style->nameWhitespace;
 142+ }
 143+ }
 144+ $ndp = isset( $this->parts[ WCNamePartEnum::nonDroppingParticle ] ) ?
 145+ $this->parts[ WCNamePartEnum::nonDroppingParticle ] : Null;
 146+ if ( $ndp ) {
 147+ # if the non-dropping particle ends in punctuation, there is no space between it and the surname.
 148+ if ( preg_match( '/\p{P}$/u', $ndp, $matches ) ) {
 149+ $ndpSpace = '';
 150+ } else {
 151+ $ndpSpace = $style->nameWhitespace;
 152+ }
 153+ }
 154+ $suffix = isset( $this->parts[ WCNamePartEnum::suffix ] ) ?
 155+ $this->parts[ WCNamePartEnum::suffix ] : Null;
 156+ if ( $suffix ) {
 157+ $suffixSpace = $style->nameSuffixDelimiter;
 158+ }
 159+ $literal = isset( $this->parts[ WCNamePartEnum::literal ] ) ?
 160+ $this->parts[ WCNamePartEnum::literal ] : Null;
 161+
 162+ # literal/organizational name
 163+ if ( $literal ) {
 164+ # Trim redundant separator characters
 165+ $chrL = mb_substr( $literal, -1, 1 );
 166+ $chrR = mb_substr( $endSeparator, 0, 1 );
 167+ if ( $chrL == $chrR ) {
 168+ $endSeparator = ltrim( $endSeparator, $chrR );
 169+ }
 170+ return WCStyle::makeWikiLink( $link, $literal, WCStyle::nameHTML ) . $endSeparator;
 171+ };
 172+
 173+ $pre = $post = '';
 174+
 175+ # short form
 176+ if ( $citationLength->key == WCCitationLengthEnum::short ) {
 177+ if ( $surname ) {
 178+ if ( $ndp ) {
 179+ $surname = $ndp . $ndpSpace . $surname;
 180+ }
 181+ } else {
 182+ if ( $link ) {
 183+ $post = $link;
 184+ } elseif ( $given ) {
 185+ $post = $given;
 186+ } else {
 187+ $post = $dp . $dpSpace . $ndp . $ndpSpace . $style->missingName . $suffixSpace . $suffix;
 188+ }
 189+ }
 190+ }
 191+
 192+ # long form, name sort order
 193+ elseif ( $namesort ) {
 194+ if ( $surname ) {
 195+ if ( !$style->demoteNonDroppingParticle && $ndp ) {
 196+ $pre = $ndp . $ndpSpace;
 197+ }
 198+ if ( $given ) {
 199+ $post = $style->sortOrderSurnameDelimiter . $given;
 200+ if ( $dp ) {
 201+ $post .= $style->nameWhitespace . $dp;
 202+ }
 203+ if ( $style->demoteNonDroppingParticle && $ndp ) {
 204+ if ( $dp ) {
 205+ $post .= $dpSpace;
 206+ } else {
 207+ $post .= $style->nameWhitespace;
 208+ }
 209+ $post .= $ndp;
 210+ }
 211+ } else {
 212+ if ( $dp ) {
 213+ $post .= $style->sortOrderSurnameDelimiter . $dp;
 214+ }
 215+ if ( $style->demoteNonDroppingParticle && $ndp ) {
 216+ if ( $dp ) {
 217+ $post .= $dpSpace;
 218+ } else {
 219+ $post .= $style->nameWhitespace;
 220+ }
 221+ $post .= $ndp;
 222+ }
 223+ }
 224+ if ( $suffix ) {
 225+ $post .= $suffixSpace . $suffix;
 226+ }
 227+ } elseif ( $link ) {
 228+ $post = $link;
 229+ } elseif ( $given ) {
 230+ if ( $dp || $ndp || $suffix ) {
 231+ if ( !$style->demoteNonDroppingParticle && $ndp ) {
 232+ $post = $ndp . $ndpSpace;
 233+ }
 234+ $post = $style->missingName . $style->sortOrderSurnameDelimiter . $given;
 235+ if ( $dp ) {
 236+ $post .= $style->nameWhitespace . $dp;
 237+ }
 238+ if ( $style->demoteNonDroppingParticle && $ndp ) {
 239+ if ( $dp ) {
 240+ $post .= $dpSpace;
 241+ } else {
 242+ $post .= $style->nameWhitespace;
 243+ }
 244+ $post .= $ndp;
 245+ }
 246+ if ( $suffix ) {
 247+ $post .= $suffixSpace . $suffix;
 248+ }
 249+ } else {
 250+ $post = $given;
 251+ }
 252+ } else {
 253+ if ( !$style->demoteNonDroppingParticle && $ndp ) {
 254+ $post = $ndp . $ndpSpace;
 255+ } else {
 256+ $post = '';
 257+ }
 258+ $post = $style->missingName . $style->sortOrderSurnameDelimiter . $style->missingName;
 259+ if ( $dp ) {
 260+ $post .= $style->nameWhitespace . $dp;
 261+ }
 262+ if ( $style->demoteNonDroppingParticle && $ndp ) {
 263+ if ( $dp ) {
 264+ $post .= $dpSpace;
 265+ } else {
 266+ $post .= $style->nameWhitespace;
 267+ }
 268+ $post .= $ndp;
 269+ }
 270+ if ( $suffix ) {
 271+ $post .= $suffixSpace . $suffix;
 272+ }
 273+ }
 274+ }
 275+
 276+ # long form, non-name sort order
 277+ else {
 278+ if ( $surname ) {
 279+ if ( $given ) {
 280+ $pre = $given . $style->nameWhitespace;
 281+ }
 282+ $pre .= $dp . $dpSpace . $ndp . $ndpSpace;
 283+ $post = $suffixSpace . $suffix;
 284+ } elseif ( $link ) {
 285+ $post = $link;
 286+ } elseif ( $given ) {
 287+ $post = $given . $style->nameWhitespace;
 288+ if ( $dp || $ndp || $suffix ) {
 289+ $post .= $dp . $dpSpace . $ndp . $ndpSpace . $style->missingName . $suffixSpace . $suffix;
 290+ }
 291+ } else {
 292+ $post = $style->missingName . $style->nameWhitespace;
 293+ if ( $dp ) {
 294+ $post .= $dp . $dpSpace . $ndp . $ndpSpace . $style->missingName . $suffixSpace . $suffix;
 295+ }
 296+ }
 297+ }
 298+
 299+ $htmlClass = WCStyle::nameHTML;
 300+
 301+ if ( $namesort ) {
 302+ $surnameClass = WCStyle::surnameSortOrderHTML;
 303+ } else {
 304+ $surnameClass = WCStyle::surnameHTML;
 305+ }
 306+
 307+ # Trim redundant separator characters
 308+ if ( $post ) {
 309+ $chrL = mb_substr( $post, -1, 1 );
 310+ $chrR = mb_substr( $endSeparator, 0, 1 );
 311+ if ( $chrL == $chrR ) {
 312+ $endSeparator = ltrim( $endSeparator, $chrR );
 313+ }
 314+ if ( $surname) {
 315+ $nameText = $pre . WCStyle::wrapHTMLSpan( $surname, $surnameClass ) . $post;
 316+ } else {
 317+ $nameText = $pre . $post;
 318+ }
 319+ } elseif ( $surname) {
 320+ $chrL = mb_substr( $surname, -1, 1 );
 321+ $chrR = mb_substr( $endSeparator, 0, 1 );
 322+ if ( $chrL == $chrR ) {
 323+ $endSeparator = ltrim( $endSeparator, $chrR );
 324+ }
 325+ if ( $pre ) {
 326+ $nameText = $pre . WCStyle::wrapHTMLSpan( $surname, $surnameClass );
 327+ } else {
 328+ $nameText = $surname;
 329+ $htmlClass .= ' ' . $surnameClass;
 330+ }
 331+ } else {
 332+ $chrL = mb_substr( $pre, -1, 1 );
 333+ $chrR = mb_substr( $endSeparator, 0, 1 );
 334+ if ( $chrL == $chrR ) {
 335+ $endSeparator = ltrim( $endSeparator, $chrR );
 336+ }
 337+ $nameText = $pre;
 338+ }
 339+
 340+ return WCStyle::makeWikiLink( $link, $nameText, $htmlClass ) . $endSeparator;
 341+
 342+ }
 343+
 344+
 345+ public function __toString() {
 346+ return implode( ' ', $this->parts );
 347+ }
 348+
 349+
 350+ public function getSortingParts() {
 351+ if ( isset( $this->parts[ WCNamePartEnum::literal ] ) ) {
 352+ return array( $this->parts[ WCNamePartEnum::literal ] );
 353+ }
 354+ $sortName = '';
 355+ if ( isset( $this->parts[ WCNamePartEnum::surname ] ) ) {
 356+ if ( isset( $this->parts[ WCNamePartEnum::nonDroppingParticle ] ) ) {
 357+ $sortName = $this->parts[ WCNamePartEnum::nonDroppingParticle ] . ' ';
 358+ }
 359+ $sortName .= $this->parts[ WCNamePartEnum::surname ];
 360+ }
 361+ if ( isset( $this->parts[ WCNamePartEnum::given ] ) ) {
 362+ $sortName .= ' ' . $this->parts[ WCNamePartEnum::given ];
 363+ }
 364+ if ( isset( $this->parts[ WCNamePartEnum::suffix ] ) ) {
 365+ $sortName .= ' ' . $this->parts[ WCNamePartEnum::suffix ];
 366+ }
 367+ if ( isset( $this->parts[ WCNamePartEnum::droppingParticle ] ) ) {
 368+ $sortName .= ' ' . $this->parts[ WCNamePartEnum::droppingParticle ];
 369+ }
 370+ return array( $sortName );
 371+ }
 372+
 373+
 374+ /**
 375+ * Transform the given names, such as by shortening them to initials only.
 376+ *
 377+ * To be defined by child classes. An idname function by default.
 378+ * @return string
 379+ */
 380+ protected function transformGivenNames( $givenNames ) {
 381+ return $givenNames;
 382+ }
 383+
 384+
 385+}
 386+
Property changes on: trunk/extensions/WikiCitation/includes/data/WCName.php
___________________________________________________________________
Added: svn:eol-style
1387 + native
Index: trunk/extensions/WikiCitation/includes/data/WCTitle.php
@@ -0,0 +1,113 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCTitleFormat extends WCEnum {
 12+ const normal = 0;
 13+ const quoted = 1;
 14+ const italic = 2;
 15+ const __default = self::normal;
 16+}
 17+
 18+
 19+/**
 20+ * Data structure WCTitle.
 21+ * Contains all information needed to be known about a title.
 22+ */
 23+class WCTitle extends WCData {
 24+
 25+ # Regexes initialized by WCTitle::init()
 26+ protected static $patternExternal, $patternInternal;
 27+
 28+ # The title, as text.
 29+ protected $title;
 30+
 31+ /**
 32+ * Static initializer.
 33+ */
 34+ public static function init() {
 35+ $iExQuoteMW = MagicWord::get( 'wc_initial_exterior_quote' );
 36+ $fExQuoteMW = MagicWord::get( 'wc_final_exterior_quote' );
 37+ $iInQuoteMW = MagicWord::get( 'wc_initial_interior_quote' );
 38+ $fInQuoteMW = MagicWord::get( 'wc_final_interior_quote' );
 39+ $iExQuotes = implode( $iExQuoteMW->getSynonyms() );
 40+ $fExQuotes = implode( $fExQuoteMW->getSynonyms() );
 41+ $iInQuotes = implode( $iInQuoteMW->getSynonyms() );
 42+ $fInQuotes = implode( $fInQuoteMW->getSynonyms() );
 43+ self::$patternExternal = '/(^|[\p{Ps}\p{Zs}\p{Pd}\p{Pi}\'])[' . $iExQuotes . '](.*?)[' . $fExQuotes . ']($|[\p{Pe}\p{Zs}\.,;:?!\p{Pd}\p{Pf}\'])/usS';
 44+ self::$patternInternal = '/(^|[\p{Ps}\p{Zs}\p{Pd}\p{Pi}"])[' . $iInQuotes . '](.*?)[' . $fInQuotes . ']($|[\p{Pe}\p{Zs}\.,;:?!\p{Pd}\p{Pf}"])/usS';
 45+ }
 46+
 47+ /**
 48+ * Constructor.
 49+ *
 50+ * Converts character-based quotes to semantic HTML quotes.
 51+ * For now, this is done as an intermediate step to regularize quotes, and
 52+ * to allow quotes to be shifted if the entire title is quoted.
 53+ * This method assumes that the title does not contain quoted HTML
 54+ * attributes.
 55+ *
 56+ * @param WCCitation $citation = the WCCitation object
 57+ * @param WCScopeEnum $scope = the scope (i.e., work, container, series, etc.)
 58+ * @param WCParameterEnum $type = the type of property.
 59+ * @param string $title = the unprocessed text of the title.
 60+ */
 61+ public function __construct( $title ) {
 62+
 63+ # Regex for replacing internal quotes with markers. Searches for
 64+ # pairs of internal quotes that are closest to each other.
 65+ static $replacement = '$1<q>$2</q>$3';
 66+ do { # make substitutions for nested quotes until string stops changing.
 67+ $oldTitle = $title;
 68+ $title = preg_replace( self::$patternInternal, $replacement, $title );
 69+ } while ( $oldTitle != $title );
 70+
 71+ # replace double quotes
 72+ do { # make substitutions for nested quotes until string stops changing.
 73+ $oldTitle = $title;
 74+ $title = preg_replace( self::$patternExternal, $replacement, $title );
 75+ } while ( $oldTitle != $title );
 76+
 77+ $this->title = $title;
 78+
 79+ }
 80+
 81+
 82+ /**
 83+ * Get title.
 84+ * @return string
 85+ */
 86+ public function getTitle() {
 87+ return $this->title;
 88+ }
 89+
 90+
 91+ public function __toString() {
 92+ return $this->title;
 93+ }
 94+
 95+
 96+ /**
 97+ * Determine if $this can be considered a short form of the argument.
 98+ * If so, then determine the number of matches.
 99+ *
 100+ * @param WCTitle $title
 101+ * @return integer|boolean
 102+ */
 103+ public function shortFormMatches( WCData $title ) {
 104+ return strnatcasecmp( $this->title, $title->getTitle() ) === 0 ? 1 : False;
 105+ }
 106+
 107+
 108+}
 109+
 110+/**
 111+ * Static initializer.
 112+ */
 113+WCTitle::init();
 114+
Property changes on: trunk/extensions/WikiCitation/includes/data/WCTitle.php
___________________________________________________________________
Added: svn:eol-style
1115 + native
Index: trunk/extensions/WikiCitation/includes/data/WCLocator.php
@@ -0,0 +1,101 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * Data structure WCLocator.
 13+ * Stores and renders a location or range of locations in a source.
 14+ */
 15+class WCLocator {
 16+
 17+ public $ranges;
 18+
 19+ protected static $listTerms, $rangeTerms;
 20+
 21+ public static function init() {
 22+ $listDelimiterMW = MagicWord::get( 'wc_list_delimiter' );
 23+ $rangeDelimiterMW = MagicWord::get( 'wc_range_delimiter' );
 24+ self::$listTerms = '\s*' . implode( '\s*|\s*', $listDelimiterMW->getSynonyms() ) . '\s*|\s+';
 25+ self::$rangeTerms = '/^\p{Zs}*[\p{Pi}"\']?((?(?<=[\p{Pi}"\']).*?(?=[\p{Pf}"\'])|(?(?=\p{Ps}).+?\p{Pe}|.))*?)[\p{Pf}"\']?\p{Zs}*(?:' . implode( '|', $rangeDelimiterMW->getSynonyms() ) . '|\p{Pd})\p{Zs}*[\p{Pi}"\']*(.*?)[\p{Pf}"\']*\p{Zs}*$/uS';
 26+ }
 27+
 28+ /**
 29+ * Constructor.
 30+ * This should be able to handle complex ranges like
 31+ * "45(iv)45-(v)7, 45(ii)52-61, and 45(ix)99-100".
 32+ * A dash or hyphen will be interpreted as a range, unless the number is
 33+ * enclosed in quotation marks.
 34+ * @param WCCitation $citation = the WCCitation object
 35+ * @param WCScopeEnum $scope = the scope (i.e., work, container, series, etc.)
 36+ * @param WCParameterEnum $type = the type of property.
 37+ * @param string $text = the unprocessed locator text.
 38+ */
 39+ public function __construct( $text ) {
 40+ $this->ranges = mb_split( self::$listTerms, $text ); # Split by range-delimiting terms like comma or and
 41+ foreach( $this->ranges as &$range ) {
 42+ if ( !preg_match( self::$rangeTerms, $range, $matches ) ) {
 43+ $range = array( $range );
 44+ continue;
 45+ }
 46+ $range = array( $matches[1], $matches[2] );
 47+ }
 48+ return;
 49+ }
 50+
 51+
 52+ /**
 53+ * Render the text.
 54+ * @return string
 55+ */
 56+ public function render( $endSeparator = '' ) {
 57+ $text = '';
 58+ $rangeCount = count( $this->ranges );
 59+ # single range:
 60+ if ( $rangeCount == 1 ) {
 61+ $text = implode( '–', reset( $this->ranges ) );
 62+ }
 63+ # two ranges
 64+ elseif ( $rangeCount == 2 ) {
 65+ $text = implode( '–', reset( $this->ranges ) );
 66+ $text .= ' & ' . implode( '–', next( $this->ranges ) );
 67+ }
 68+ # three or more ranges:
 69+ else {
 70+ $text = implode( '–', reset( $this->ranges ) );
 71+ for ( $i = 2; $i < $rangeCount-1; $i++ ) {
 72+ $text .= ', ' . implode( '–', next( $this->ranges ) );
 73+ }
 74+ $text .= ' & ' . implode( '–', next( $this->ranges ) );
 75+ }
 76+ if ( $endSeparator ) {
 77+ $chrL = mb_substr( $text, -1, 1 );
 78+ $chrR = mb_substr( $endSeparator, 0, 1 );
 79+ if ( $chrL == $chrR ) {
 80+ $endSeparator = ltrim( $endSeparator, $chrR );
 81+ }
 82+ return $text . $endSeparator;
 83+ } else {
 84+ return $text;
 85+ }
 86+ }
 87+
 88+
 89+ public function __toString() {
 90+ $arr = $this->ranges;
 91+ foreach( $arr as &$range ) {
 92+ $range = implode( '–', $range );
 93+ }
 94+ return implode( ', ', $arr );
 95+ }
 96+
 97+}
 98+
 99+/**
 100+ * Static initializer
 101+ */
 102+WCLocator::init();
\ No newline at end of file
Property changes on: trunk/extensions/WikiCitation/includes/data/WCLocator.php
___________________________________________________________________
Added: svn:eol-style
1103 + native
Index: trunk/extensions/WikiCitation/includes/data/WCNames.php
@@ -0,0 +1,224 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * Data structure WCNames.
 13+ * Contains information about a group of names,
 14+ * such as authors, editors, translators, composers, etc.
 15+ */
 16+class WCNames extends WCData implements Countable, Iterator {
 17+
 18+ /**
 19+ * Array of names
 20+ * @var array
 21+ */
 22+ protected $names = array();
 23+
 24+
 25+ /**
 26+ * Implements Iterator interface method.
 27+ * @return type
 28+ */
 29+ public function count() {
 30+ return count( $this->names );
 31+ }
 32+
 33+ /**
 34+ * Implements Iterator interface method.
 35+ * @return type
 36+ */
 37+ public function key() {
 38+ return key( $this->names );
 39+ }
 40+
 41+ /**
 42+ * Implements Iterator interface method.
 43+ * @return type
 44+ */
 45+ public function current() {
 46+ return current( $this->names );
 47+ }
 48+
 49+ /**
 50+ * Implements Iterator interface method.
 51+ * @return type
 52+ */
 53+ public function next() {
 54+ return next( $this->names );
 55+ }
 56+
 57+ /**
 58+ * Implements Iterator interface method.
 59+ * @return type
 60+ */
 61+ public function valid() {
 62+ return (bool) current( $this->names );
 63+ }
 64+
 65+ /**
 66+ * Implements Iterator interface method.
 67+ * @return type
 68+ */
 69+ public function rewind() {
 70+ return reset( $this->names );
 71+ }
 72+
 73+
 74+ /**
 75+ * Sort names on the basis of number.
 76+ */
 77+ public function sort() {
 78+ ksort( $this->names );
 79+ }
 80+
 81+
 82+ /**
 83+ * Determine if $this can be considered a short form of the argument.
 84+ * If so, then determine the number of matches.
 85+ *
 86+ * @param WCNames $names
 87+ * @return integer|boolean
 88+ */
 89+ public function shortFormMatches( WCData $names ) {
 90+ $matches = 0;
 91+ foreach( $this->names as $nameKey => $thisName ) {
 92+ $otherName = $names->getName( $nameKey );
 93+ $subMatches = $thisName->shortFormMatches( $otherName );
 94+ if ( $subMatches === False ) {
 95+ return False;
 96+ } else {
 97+ $matches += $subMatches;
 98+ }
 99+ }
 100+ return $matches;
 101+
 102+ }
 103+
 104+
 105+ /**
 106+ * Renders a section of name info based on a group of names,
 107+ * such as authors, editors, etc.
 108+ *
 109+ * @param boolean $namesort = whether the surname appears first
 110+ * @return string = rendereded name section
 111+ */
 112+ public function render(
 113+ WCStyle $style,
 114+ WCCitationPosition $citationPosition,
 115+ WCCitationLengthEnum $citationLength,
 116+ $endSeparator = '',
 117+ $namesort = False ) {
 118+
 119+ $nameCount = $this->count();
 120+
 121+ # no names:
 122+ if ( !$nameCount ) {
 123+ return '';
 124+ }
 125+
 126+ # single name:
 127+ if ( $nameCount == 1 ) {
 128+ return $this->rewind()->render( $style, $citationLength, $endSeparator, $namesort );
 129+ }
 130+
 131+ # determine whether we are using "et al." or equivalent
 132+ if( $citationPosition->key == WCCitationPosition::first ) {
 133+ $etAlMin = $style->etAlMin;
 134+ $etAlUseFirst = $style->etAlUseFirst;
 135+ } else {
 136+ $etAlMin = $style->etAlSubsequentMin;
 137+ $etAlUseFirst = $style->etAlSubsequentUseFirst;
 138+ }
 139+ $usingEtAl = $nameCount > $etAlMin;
 140+ if ( $usingEtAl ) {
 141+ $nameCount = $etAlUseFirst;
 142+ }
 143+
 144+ # single name with et al.:
 145+ if ( $nameCount == 1 ) {
 146+ $text = $this->rewind()->render( $style, $citationLength, $nameStyle->$etAlDelimiter, $namesort );
 147+ }
 148+
 149+ # two names
 150+ elseif ( $nameCount == 2 ) {
 151+ $text = $this->rewind()->render( $style, $citationLength, $style->and2, $namesort );
 152+ if ( $usingEtAl ) {
 153+ $text .= $this->next()->render( $style, $citationLength, $nameStyle->$etAlDelimiter, False );
 154+ } else {
 155+ $text .= $this->next()->render( $style, $citationLength, $endSeparator, False );
 156+ }
 157+ }
 158+
 159+ # three or more names:
 160+ else {
 161+ $text = $this->rewind()->render( $style, $citationLength, $style->namesDelimiter, $namesort );
 162+ for ( $i = 2; $i < $nameCount-1; $i++ ) {
 163+ $text .= $this->next()->render( $style, $citationLength, $style->namesDelimiter, False );
 164+ }
 165+ $text .= $this->next()->render( $style, $citationLength, $style->and3, False );
 166+ if ( $usingEtAl ) {
 167+ $text .= $this->next()->render( $style, $citationLength, $nameStyle->$etAlDelimiter, False );
 168+ } else {
 169+ $text .= $this->next()->render( $style, $citationLength, $endSeparator, False );
 170+ }
 171+ }
 172+
 173+ # et al.
 174+ if ( $usingEtAl ) {
 175+ # Trim redundant separator characters
 176+ $etal = $style->etAl;
 177+ $chrL = mb_substr( $etal, -1, 1 );
 178+ $chrR = mb_substr( $endSeparator, 0, 1 );
 179+ $text .= $etal;
 180+ if ( $chrL == $chrR ) {
 181+ $endSeparator = ltrim( $endSeparator, $chrR );
 182+ }
 183+ $text .= $endSeparator;
 184+
 185+ }
 186+
 187+ return $text;
 188+ }
 189+
 190+
 191+ public function __toString() {
 192+ return implode( ' ', $this->names );
 193+ }
 194+
 195+
 196+ public function getName( $nameNumber ) {
 197+ if ( isset( $this->names[ $nameNumber ] ) ) {
 198+ return $this->names[ $nameNumber ];
 199+ } else {
 200+ return Null;
 201+ }
 202+ }
 203+
 204+ public function setName( $nameNumber, $value ) {
 205+ $this->names[ $nameNumber ] = $value;
 206+ }
 207+
 208+ public function getNamePart( $nameNumber, WCNamePartEnum $namePart ) {
 209+ if ( isset( $this->names[ $nameNumber ] ) ) {
 210+ return $this->names[ $nameNumber ]->getPart( $namePart->key );
 211+ } else {
 212+ return Null;
 213+ }
 214+ }
 215+
 216+ public function setNamePart( $nameNumber, WCNamePartEnum $namePart, $value ) {
 217+ $name = &$this->names[ $nameNumber ];
 218+ if ( is_null( $name ) ) {
 219+ $name = new WCName( $nameNumber );
 220+ }
 221+ $name->setPart( $namePart, $value );
 222+ }
 223+
 224+}
 225+
Property changes on: trunk/extensions/WikiCitation/includes/data/WCNames.php
___________________________________________________________________
Added: svn:eol-style
1226 + native
Index: trunk/extensions/WikiCitation/includes/data/WCText.php
@@ -0,0 +1,59 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * Data structure WCText.
 13+ * Stores and renders a text attribute.
 14+ */
 15+class WCText extends WCData {
 16+
 17+ # The text.
 18+ protected $text;
 19+
 20+
 21+ /**
 22+ * Constructor.
 23+ * @param WCCitation $citation = the WCCitation object
 24+ * @param WCScopeEnum $scope = the scope (i.e., work, container, series, etc.)
 25+ * @param WCParameterEnum $type = the type of property.
 26+ * @param string $text = the unprocessed text.
 27+ */
 28+ public function __construct( $text ) {
 29+ $this->text = $text;
 30+ }
 31+
 32+
 33+ /**
 34+ * Get text.
 35+ * @return string
 36+ */
 37+ public function getText() {
 38+ return $this->text;
 39+ }
 40+
 41+
 42+ public function __toString() {
 43+ return $this->text;
 44+ }
 45+
 46+
 47+ /**
 48+ * Determine if $this can be considered a short form of the argument.
 49+ * If so, then determine the number of matches.
 50+ *
 51+ * @param WCText $text
 52+ * @return integer|boolean
 53+ */
 54+ public function shortFormMatches( WCData $text ) {
 55+ if ( strnatcasecmp( $this->text === $text->getText() ) === 0 ) return 1; else return False;
 56+ }
 57+
 58+
 59+}
 60+
Property changes on: trunk/extensions/WikiCitation/includes/data/WCText.php
___________________________________________________________________
Added: svn:eol-style
161 + native
Index: trunk/extensions/WikiCitation/includes/data/WCData.php
@@ -0,0 +1,18 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+abstract class WCData {
 12+
 13+ /**
 14+ * Tests whether $this can be considered a short form of argument $data.
 15+ * @param WCData $data
 16+ */
 17+ abstract public function shortFormMatches( WCData $data );
 18+
 19+}
Property changes on: trunk/extensions/WikiCitation/includes/data/WCData.php
___________________________________________________________________
Added: svn:eol-style
120 + native
Index: trunk/extensions/WikiCitation/includes/data/WCTypeData.php
@@ -0,0 +1,65 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * Data structure WCTypeData.
 13+ * Stores and renders the work type (e.g., book, article, etc.).
 14+ */
 15+class WCTypeData extends WCData {
 16+
 17+ /**
 18+ * The enumerated attribute.
 19+ * @var WCParameterEnum
 20+ */
 21+ public $parameter;
 22+
 23+
 24+ /**
 25+ * Constructor.
 26+ *
 27+ * Tests to see whether $value is a valid parameter. If not, it throws a
 28+ * exception if $wikiCitationValidateArguments is set.
 29+ * @global $wikiCitationValidateArguments
 30+ * @param string|WCParameterEnum $value = the text, which may or may not be a
 31+ * valid parameter, or the WCParameterEnum object.
 32+ */
 33+ public function __construct( $value = Null ) {
 34+
 35+ if ( $value instanceOf WCSourceTypeEnum ) {
 36+ $parameterType = $value;
 37+ } else {
 38+ global $wikiCitationValidateArguments;
 39+ $parameterType = WCSourceTypeEnum::match( $value, WCSourceTypeEnum::$magicWordArray,
 40+ WCSourceTypeEnum::$flipMagicWordKeys, 'WCTypeEnum' );
 41+ if ( !$parameterType && $wikiCitationValidateArguments ) {
 42+ throw new WCException( 'wc-type-parameter-unknown', $parameterType );
 43+ }
 44+ }
 45+ $this->parameter = $parameterType;
 46+ }
 47+
 48+
 49+ public function __toString() {
 50+ return (string) $this->parameter;
 51+ }
 52+
 53+
 54+ /**
 55+ * Determine if $this can be considered a short form of the argument.
 56+ * If so, then determine the number of matches.
 57+ *
 58+ * @param WCTypeData $typeData
 59+ * @return integer|boolean
 60+ */
 61+ public function shortFormMatches( WCData $typeData ) {
 62+ return $this->parameter === $typeData->parameter ? 1 : False;
 63+ }
 64+
 65+}
 66+
Property changes on: trunk/extensions/WikiCitation/includes/data/WCTypeData.php
___________________________________________________________________
Added: svn:eol-style
167 + native
Index: trunk/extensions/WikiCitation/includes/data/WCDate.php
@@ -0,0 +1,1119 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCDateNumber {
 12+ const unknown = 0;
 13+ const day = 1;
 14+ const month = 2;
 15+ const year = 3;
 16+ const notDay = 4;
 17+ const notMonth = 5;
 18+ const notYear = 6;
 19+
 20+ public $key, $num;
 21+ public $numType;
 22+ public function __construct( $key, $num, $type = self::unknown ) {
 23+ $this->key = $key;
 24+ $this->num = $num;
 25+ $this->numType = $type;
 26+ }
 27+ public function setDay( array &$unknowns, array &$days ) {
 28+ switch ( $this->numType ) {
 29+ case self::unknown:
 30+ case self::notMonth:
 31+ case self::notYear:
 32+ $this->numType = self::day;
 33+ unset( $unknowns[ $this->key ] );
 34+ $days[ $this->key ] = $this->num;
 35+ return;
 36+ default:
 37+ return;
 38+ }
 39+ }
 40+ public function setMonth( array &$unknowns, array &$months ) {
 41+ switch ( $this->numType ) {
 42+ case self::unknown:
 43+ case self::notDay:
 44+ case self::notYear:
 45+ $this->numType = self::month;
 46+ unset( $unknowns[ $this->key ] );
 47+ $months[ $this->key ] = $this->num;
 48+ return;
 49+ default:
 50+ return;
 51+ }
 52+ }
 53+ public function setYear( array &$unknowns, array &$years ) {
 54+ switch ( $this->numType ) {
 55+ case self::unknown:
 56+ case self::notDay:
 57+ case self::notMonth:
 58+ $this->numType = self::year;
 59+ unset( $unknowns[ $this->key ] );
 60+ $years[ $this->key ] = $this->num;
 61+ return;
 62+ default:
 63+ return;
 64+ }
 65+ }
 66+ public function setNotDay( array &$unknowns, array &$months, array &$years ) {
 67+ switch ( $this->numType ) {
 68+ case self::unknown:
 69+ $this->numType = self::notDay;
 70+ return;
 71+ case self::notMonth:
 72+ $this->numType = self::year;
 73+ unset( $unknowns[ $this->key ] );
 74+ $years[ $this->key ] = $this->num;
 75+ return;
 76+ case self::notYear:
 77+ $this->numType = self::month;
 78+ unset( $unknowns[ $this->key ] );
 79+ $months[ $this->key ] = $this->num;
 80+ return;
 81+ default:
 82+ return;
 83+ }
 84+ }
 85+ public function setNotMonth( array &$unknowns, array &$days, array &$years ) {
 86+ switch ( $this->numType ) {
 87+ case self::unknown:
 88+ $this->numType = self::notMonth;
 89+ return;
 90+ case self::notDay:
 91+ $this->numType = self::year;
 92+ unset( $unknowns[ $this->key ] );
 93+ $years[ $this->key ] = $this->num;
 94+ return;
 95+ case self::notYear:
 96+ $this->numType = self::day;
 97+ unset( $unknowns[ $this->key ] );
 98+ $days[ $this->key ] = $this->num;
 99+ return;
 100+ default:
 101+ return;
 102+ }
 103+ }
 104+ public function setNotYear( array &$unknowns, array &$days, array &$months ) {
 105+ switch ( $this->numType ) {
 106+ case self::unknown:
 107+ $this->numType = self::notYear;
 108+ return;
 109+ case self::notDay:
 110+ $this->numType = self::month;
 111+ unset( $unknowns[ $this->key ] );
 112+ $months[ $this->key ] = $this->num;
 113+ return;
 114+ case self::notMonth:
 115+ $this->numType = self::day;
 116+ unset( $unknowns[ $this->key ] );
 117+ $days[ $this->key ] = $this->num;
 118+ return;
 119+ default:
 120+ return;
 121+ }
 122+ }
 123+
 124+ public function isNotDay() {
 125+ return $this->numType == WCDateNumber::month || $this->numType == WCDateNumber::year || $this->numType == WCDateNumber::notDay;
 126+ }
 127+ public function isNotMonth() {
 128+ return $this->numType == WCDateNumber::day || $this->numType == WCDateNumber::year || $this->numType == WCDateNumber::notMonth;
 129+ }
 130+ public function isNotYear() {
 131+ return $this->numType == WCDateNumber::day || $this->numType == WCDateNumber::month || $this->numType == WCDateNumber::notYear;
 132+ }
 133+ public function couldBeDay() {
 134+ return $this->numType == WCDateNumber::day || $this->numType == WCDateNumber::unknown || $this->numType == WCDateNumber::notMonth || $this->numType == WCDateNumber::notYear;
 135+ }
 136+ public function couldBeMonth() {
 137+ return $this->numType == WCDateNumber::month || $this->numType == WCDateNumber::unknown || $this->numType == WCDateNumber::notDay || $this->numType == WCDateNumber::notYear;
 138+ }
 139+ public function couldBeYear() {
 140+ return $this->numType == WCDateNumber::year || $this->numType == WCDateNumber::unknown || $this->numType == WCDateNumber::notDay || $this->numType == WCDateNumber::notMonth;
 141+ }
 142+
 143+}
 144+
 145+/**
 146+ * Data structure WCDate.
 147+ * Contains all information needed to be known about a title.
 148+ */
 149+class WCDate extends WCData {
 150+
 151+ # The year, or beginning year of a range.
 152+ public $year;
 153+
 154+ # The end year of a range
 155+ public $year2;
 156+
 157+ # The era (AD, BC, etc.), or beginning era of a range. WCDateTermsEnum::AD, etc.
 158+ public $era;
 159+
 160+ # The end era of a range
 161+ public $era2;
 162+
 163+ # The month, or beginning month of a range.
 164+ public $month;
 165+
 166+ # The end month of a range
 167+ public $month2;
 168+
 169+ # The season, or beginning season of a range. WCDateTermsEnum::spring, etc.
 170+ public $season;
 171+
 172+ # The end season of a range
 173+ public $season2;
 174+
 175+ # The day, or beginning day of a range.
 176+ public $day;
 177+
 178+ # The end day of a range
 179+ public $day2;
 180+
 181+ /**
 182+ * Whether the date, or beginning of date range is uncertain
 183+ * @var boolean
 184+ */
 185+ public $isUncertain;
 186+
 187+ /**
 188+ * Whether the second date is uncertain
 189+ * @var boolean
 190+ */
 191+ public $isUncertain2;
 192+
 193+ /**
 194+ * Constructor.
 195+ * @param WCCitation $citation = the WCCitation object
 196+ * @param WCScopeEnum $scope = the scope (i.e., work, container, series, etc.)
 197+ * @param WCParameterEnum $type = the type of property.
 198+ * @param string date = the unprocessed date text.
 199+ */
 200+ public function __construct( $date ) {
 201+
 202+ # Separate into segments comprising numbers, letters, or special terms.
 203+ $adTerms = MagicWord::get( WCDateTermsEnum::$magicWordKeys[ WCDateTermsEnum::AD ] )->getSynonyms();
 204+ $bcTerms = MagicWord::get( WCDateTermsEnum::$magicWordKeys[ WCDateTermsEnum::BC ] )->getSynonyms();
 205+ $circaTerms = MagicWord::get( WCDateTermsEnum::$magicWordKeys[ WCDateTermsEnum::circa ] )->getSynonyms();
 206+ $options = implode( '|', array_merge( $adTerms, $bcTerms, $circaTerms ) );
 207+ if ( !preg_match_all( '/'. $options . '|\p{N}+|\p{L}+|./uS', $date, $matches ) ) {
 208+ $this->year = 0;
 209+ $this->era = WCDateTermsEnum::AD;
 210+ $this->month = 0;
 211+ $this->day = 0;
 212+ $this->isUncertain = True;
 213+ return;
 214+ }
 215+
 216+ $chunks = $matches[0];
 217+ $numbers = $unknowns = array();
 218+ $years = $months = $days = array();
 219+ $eras = $seasons = $circas = $yearTerms = $monthTerms = $dayTerms = array();
 220+ $counter = 0;
 221+
 222+ foreach( $chunks as $chunk ) {
 223+ # Match month names.
 224+ $month = $this->matchMonths( $chunk ); # $month is integer >= 1 or False
 225+ if ( $month && count( $months ) < 2 ) {
 226+ $months[ $counter ] = $month;
 227+ $numbers[ $counter++ ] = new WCDateNumber( $counter, $month, WCDateNumber::month );
 228+ continue;
 229+ }
 230+
 231+ # Match date terms.
 232+ $dateTermEnum = WCDateTermsEnum::match( $chunk, WCDateTermsEnum::$magicWordArray,
 233+ WCDateTermsEnum::$flipMagicWordKeys, 'WCDateTermsEnum' );
 234+ if ( $dateTermEnum ) {
 235+ switch ( $dateTermEnum->key ) {
 236+ case WCDateTermsEnum::AD:
 237+ if ( count( $eras ) < 2 ) {
 238+ $eras[ $counter++ ] = WCDateTermsEnum::AD;
 239+ }
 240+ continue 2;
 241+ case WCDateTermsEnum::BC:
 242+ if ( count( $eras ) < 2 ) {
 243+ $eras[ $counter++ ] = WCDateTermsEnum::BC;
 244+ }
 245+ continue 2;
 246+ case WCDateTermsEnum::spring:
 247+ if ( count( $seasons ) < 2 ) {
 248+ $seasons[ $counter++ ] = WCDateTermsEnum::spring;
 249+ }
 250+ continue 2;
 251+ case WCDateTermsEnum::summer:
 252+ if ( count( $seasons ) < 2 ) {
 253+ $seasons[ $counter++ ] = WCDateTermsEnum::summer;
 254+ }
 255+ continue 2;
 256+ case WCDateTermsEnum::autumn:
 257+ if ( count( $seasons ) < 2 ) {
 258+ $seasons[ $counter++ ] = WCDateTermsEnum::autumn;
 259+ }
 260+ continue 2;
 261+ case WCDateTermsEnum::winter:
 262+ if ( count( $seasons ) < 2 ) {
 263+ $seasons[ $counter++ ] = WCDateTermsEnum::winter;
 264+ }
 265+ continue 2;
 266+ case WCDateTermsEnum::year:
 267+ if ( count( $yearTerms ) < 2 ) {
 268+ $yearTerms[ $counter++ ] = WCDateTermsEnum::yearTerm;
 269+ }
 270+ continue 2;
 271+ case WCDateTermsEnum::month:
 272+ if ( count( $monthTerms ) < 2 ) {
 273+ $monthTerms[ $counter++ ] = WCDateTermsEnum::monthTerm;
 274+ }
 275+ continue 2;
 276+ case WCDateTermsEnum::day:
 277+ if ( count( $dayTerms ) < 2 ) {
 278+ $dayTerms[ $counter++ ] = WCDateTermsEnum::dayTerm;
 279+ }
 280+ continue 2;
 281+ case WCDateTermsEnum::circa:
 282+ if ( count( $circas ) < 2 ) {
 283+ $circas[ $counter++ ] = WCDateTermsEnum::circa;
 284+ }
 285+ continue 2;
 286+ }
 287+ }
 288+
 289+ # Check for roman numerals (month is often Roman in Hungary, Poland, Romania).
 290+ $intTerm = $this->romanToInt( $chunk );
 291+ # Convert to integer.
 292+ if ( ! $intTerm ) {
 293+ $intTerm = (integer) $chunk; # Note, this converts ordinals too.
 294+ if ( ! $intTerm ) {
 295+ # '00' cannot be month or day, so it must be the two-digit year 2000:
 296+ if ( mb_substr( $chunk, 0, 2 ) == '00' ) {
 297+ $numbers[ $counter ] = new WCDateNumber( $counter, 2000, WCDateNumber::year );
 298+ $years[ $counter ] = 2000;
 299+ ++$counter;
 300+ continue;
 301+ } else {
 302+ continue; # not a recognized number
 303+ }
 304+ }
 305+ }
 306+ $numbers[ $counter ] = $unknowns[ $counter ] = new WCDateNumber( $counter, $intTerm );
 307+ ++$counter;
 308+ }
 309+
 310+ # Look for and handle named Year/Month/Day labels
 311+ foreach( $yearTerms as $yearTermKey => $yearTerm ) {
 312+ if ( empty( $unknowns ) ) break;
 313+ $unknown = $this->searchAdjacentTerm( $unknowns, $yearTermKey, $chunks );
 314+ if ( $unknown && count( $years ) < 2 ) {
 315+ $years[ $unknown->key ] = $unknown->num;
 316+ $unknown->setYear( $unknowns, $years );
 317+ }
 318+ }
 319+ foreach( $monthTerms as $monthTermKey => $monthTerm ) {
 320+ if ( empty( $unknowns ) ) break;
 321+ $unknown = $this->searchAdjacentTerm( $unknowns, $monthTermKey, $chunks );
 322+ if ( $unknown && count( $months ) < 2 ) {
 323+ $months[ $unknown->key ] = $unknown->num;
 324+ $unknown->setMonth( $unknowns, $months );
 325+ }
 326+ }
 327+ foreach( $dayTerms as $dayTermKey => $dayTerm ) {
 328+ if ( empty( $unknowns ) ) break;
 329+ $unknown = $this->searchAdjacentTerm( $unknowns, $dayTermKey, $chunks );
 330+ if ( $unknown && count( $days ) < 2 ) {
 331+ $days[ $unknown->key ] = $unknown->num;
 332+ $unknown->setDay( $unknowns, $days );
 333+ }
 334+ }
 335+
 336+ # If one or more seasons is specified, treat specially and return.
 337+ if ( ! empty( $seasons ) ) {
 338+ $this->season = reset( $seasons );
 339+ $season2 = next( $seasons );
 340+ # Only one season specified
 341+ if ( $season2 === False || $season2 == $this->season ) {
 342+ $isRange = False;
 343+ # Determine year.
 344+ if ( count( $years ) >= 1 ) {
 345+ $year = reset( $years ); # Use first number as year
 346+ $this->assignYearsAndEras( $eras, False, $year->num );
 347+ }
 348+ elseif ( count( $unknowns ) >= 1 ) {
 349+ $year = reset( $unknowns ); # Use first number as year
 350+ $this->assignYearsAndEras( $eras, False, $year->num );
 351+ }
 352+ else {
 353+ $curDate = getdate();
 354+ $this->year = $curDate['year'];
 355+ $this->era = WCDateTermsEnum::AD;
 356+ }
 357+ }
 358+ # Two seasons specified
 359+ else {
 360+ $isRange = True;
 361+ $this->season2 = $season2;
 362+ # Determine year
 363+ if ( count( $years ) >= 2 ) {
 364+ $year = reset( $years )->num;
 365+ $year2 = next( $years )->num;
 366+ if ( $year2 == $year ) {
 367+ $this->assignYearsAndEras( $eras, False, $year );
 368+ }
 369+ else {
 370+ $this->assignYearsAndEras( $eras, True, $year, $year2 );
 371+ }
 372+ }
 373+ elseif ( count( $years ) == 1 ) {
 374+ $yearA = reset( $years )->num;
 375+ if ( empty( $unknowns ) ) {
 376+ $this->assignYearsAndEras( $eras, False, $yearA );
 377+ }
 378+ else {
 379+ $yearB = reset( $unknowns )->num;
 380+ if ( $yearA == $yearB ) {
 381+ $this->assignYearsAndEras( $eras, False, $yearA );
 382+ }
 383+ elseif ( $yearA < $yearB ) {
 384+ $this->assignYearsAndEras( $eras, True, $yearA, $yearB );
 385+ }
 386+ else {
 387+ $this->assignYearsAndEras( $eras, True, $yearB, $yearA );
 388+ }
 389+ }
 390+ }
 391+ elseif ( count( $unknowns ) >= 2 ) {
 392+ # Use first two numbers as years.
 393+ $year = reset( $unknowns )->num;
 394+ $year2 = next( $unknowns )->num;
 395+ if ( $year2 == $year ) {
 396+ $this->assignYearsAndEras( $eras, False, $year );
 397+ }
 398+ else {
 399+ $this->assignYearsAndEras( $eras, True, $year, $year2 );
 400+ }
 401+ }
 402+ elseif ( count( $unknowns ) == 1 ) {
 403+ $year = reset( $unknowns )->num;
 404+ $this->assignYearsAndEras( $eras, False, $year );
 405+ }
 406+ else {
 407+ $curDate = getdate();
 408+ $this->year = $curDate['year'];
 409+ $this->era = WCDateTermsEnum::AD;
 410+ }
 411+ }
 412+ $this->assignUncertainty( $circas, $isRange, $numbers, $chunks );
 413+ return;
 414+ }
 415+
 416+ # Handle numbers and/or named months.
 417+ switch ( count( $numbers ) ) {
 418+
 419+ case 0: /****** CASE 0 ******/
 420+
 421+ $this->finalizeDate( $days, $months, $years, $eras );
 422+ $this->assignUncertainty( $circas, False, $numbers, $chunks );
 423+ break;
 424+
 425+ case 1: /****** CASE 1 ******/
 426+ /** Must be year
 427+ */
 428+ if ( ! empty( $unknowns ) ) {
 429+ reset( $unknowns ) -> setYear( $unknowns, $years );
 430+ }
 431+ $this->finalizeDate( $days, $months, $years, $eras );
 432+ $this->assignUncertainty( $circas, False, $numbers, $chunks );
 433+ break;
 434+
 435+ case 2: /****** CASE 2 ******/
 436+ /** Can be any of the following:
 437+ * month-year
 438+ * year-year
 439+ * year-month
 440+ */
 441+ $order1 = array( WCDateNumber::month, WCDateNumber::year );
 442+ $order2 = array( WCDateNumber::year, WCDateNumber::year );
 443+ $order3 = array( WCDateNumber::year, WCDateNumber::month );
 444+ if ( ! (
 445+ $this->monthUpTo12( $unknowns, $days, $years ) ||
 446+ $this->cannotBeDay( $unknowns, $months, $years ) ||
 447+ $this->yearAdjacentEra( $unknowns, $years, $eras, $chunks ) ||
 448+ $this->yearsInOrder( $unknowns, $days, $months, $years, $eras ) ||
 449+ $this->tryOrder( $unknowns, $days, $months, $years, $order1 ) ||
 450+ $this->tryOrder( $unknowns, $days, $months, $years, $order2 ) ||
 451+ $this->tryOrder( $unknowns, $days, $months, $years, $order3 )
 452+ ) ) {
 453+ foreach( $unknowns as $unknownKey => $unknown ) {
 454+ if ( empty( $months ) ) {
 455+ $months[ $unknownKey ] = $unknown->num;
 456+ }
 457+ elseif ( count( $years ) < 2 ) {
 458+ $years[ $unknownKey ] = $unknown->num;
 459+ }
 460+ }
 461+ }
 462+ $isRange = $this->finalizeDate( $days, $months, $years, $eras );
 463+ $this->assignUncertainty( $circas, $isRange, $numbers, $chunks );
 464+
 465+ break;
 466+
 467+ case 3: /****** CASE 3 ******/
 468+ /** Can be any of the following:
 469+ * day-month-year
 470+ * month-day-year
 471+ * year-month-day
 472+ * month-month-year
 473+ * year-month-month
 474+ */
 475+ $order1 = array( WCDateNumber::day, WCDateNumber::month, WCDateNumber::year );
 476+ $order2 = array( WCDateNumber::month, WCDateNumber::day, WCDateNumber::year );
 477+ $order3 = array( WCDateNumber::year, WCDateNumber::month, WCDateNumber::day );
 478+ $order4 = array( WCDateNumber::month, WCDateNumber::month, WCDateNumber::year );
 479+ $order5 = array( WCDateNumber::year, WCDateNumber::month, WCDateNumber::month );
 480+ if ( ! (
 481+ $this->dayUpTo31( $unknowns, $months, $years ) ||
 482+ $this->monthUpTo12( $unknowns, $days, $years ) ||
 483+ $this->yearAdjacentEra( $unknowns, $years, $eras, $chunks ) ||
 484+ $this->yearsInOrder( $unknowns, $days, $months, $years, $eras ) ||
 485+ $this->tryOrder( $unknowns, $days, $months, $years, $order1 ) ||
 486+ $this->tryOrder( $unknowns, $days, $months, $years, $order2 ) ||
 487+ $this->tryOrder( $unknowns, $days, $months, $years, $order3 ) ||
 488+ $this->tryOrder( $unknowns, $days, $months, $years, $order4 ) ||
 489+ $this->tryOrder( $unknowns, $days, $months, $years, $order5 )
 490+ ) ) {
 491+ foreach( $unknowns as $unknownKey => $unknown ) {
 492+ if ( empty( $day ) ) {
 493+ $days[ $unknownKey ] = $unknown->num;
 494+ }
 495+ elseif ( empty( $months ) ) {
 496+ $months[ $unknownKey ] = $unknown->num;
 497+ }
 498+ elseif ( empty( $years ) ) {
 499+ $years[ $unknownKey ] = $unknown->num;
 500+ }
 501+ else {
 502+ $months[ $unknownKey ] = $unknown->num;
 503+ }
 504+ }
 505+ }
 506+ $isRange = $this->finalizeDate( $days, $months, $years, $eras );
 507+ $this->assignUncertainty( $circas, $isRange, $numbers, $chunks );
 508+
 509+ break;
 510+
 511+ case 4: /****** CASE 4 ******/
 512+
 513+ /** Can be any of the following:
 514+ * day-day-month-year
 515+ * month-day-day-year
 516+ * year-month-day-day
 517+ * month-year-month-year
 518+ * year-month-year-month
 519+ */
 520+ $order1 = array( WCDateNumber::day, WCDateNumber::day, WCDateNumber::month, WCDateNumber::year );
 521+ $order2 = array( WCDateNumber::month, WCDateNumber::day, WCDateNumber::day, WCDateNumber::year );
 522+ $order3 = array( WCDateNumber::year, WCDateNumber::month, WCDateNumber::day, WCDateNumber::day );
 523+ $order4 = array( WCDateNumber::month, WCDateNumber::year, WCDateNumber::month, WCDateNumber::year );
 524+ $order5 = array( WCDateNumber::year, WCDateNumber::month, WCDateNumber::year, WCDateNumber::month );
 525+ if ( ! (
 526+ $this->dayUpTo31( $unknowns, $months, $years ) ||
 527+ $this->monthUpTo12( $unknowns, $days, $years ) ||
 528+ $this->yearAdjacentEra( $unknowns, $years, $eras, $chunks ) ||
 529+ $this->yearsInOrder( $unknowns, $days, $months, $years, $eras ) ||
 530+ $this->tryOrder( $unknowns, $days, $months, $years, $order1 ) ||
 531+ $this->tryOrder( $unknowns, $days, $months, $years, $order2 ) ||
 532+ $this->tryOrder( $unknowns, $days, $months, $years, $order3 ) ||
 533+ $this->tryOrder( $unknowns, $days, $months, $years, $order4 ) ||
 534+ $this->tryOrder( $unknowns, $days, $months, $years, $order5 )
 535+ ) ) {
 536+ foreach( $unknowns as $unknownKey => $unknown ) {
 537+ if ( count( $day ) < 2 ) {
 538+ $days[ $unknownKey ] = $unknown->num;
 539+ }
 540+ elseif ( empty( $months ) ) {
 541+ $months[ $unknownKey ] = $unknown->num;
 542+ }
 543+ elseif ( empty( $years ) ) {
 544+ $years[ $unknownKey ] = $unknown->num;
 545+ }
 546+ elseif ( count( $months ) < 2 ) {
 547+ $months[ $unknownKey ] = $unknown->num;
 548+ }
 549+ else {
 550+ $years[ $unknownKey ] = $unknown->num;
 551+ }
 552+ }
 553+ }
 554+ $isRange = $this->finalizeDate( $days, $months, $years, $eras );
 555+ $this->assignUncertainty( $circas, $isRange, $numbers, $chunks );
 556+
 557+ break;
 558+
 559+ case 5: /****** CASE 5 ******/
 560+
 561+ /** Can be any of the following:
 562+ * day-month-day-month-year
 563+ * month-day-month-day-year
 564+ * year-month-day-month-day
 565+ */
 566+ $order1 = array( WCDateNumber::day, WCDateNumber::month, WCDateNumber::day, WCDateNumber::month, WCDateNumber::year );
 567+ $order2 = array( WCDateNumber::month, WCDateNumber::day, WCDateNumber::month, WCDateNumber::day, WCDateNumber::year );
 568+ $order3 = array( WCDateNumber::year, WCDateNumber::month, WCDateNumber::day, WCDateNumber::month, WCDateNumber::day );
 569+ if ( ! (
 570+ $this->dayUpTo31( $unknowns, $months, $years ) ||
 571+ $this->monthUpTo12( $unknowns, $days, $years ) ||
 572+ $this->yearAdjacentEra( $unknowns, $years, $eras, $chunks ) ||
 573+ $this->yearsInOrder( $unknowns, $days, $months, $years, $eras ) ||
 574+ $this->tryOrder( $unknowns, $days, $months, $years, $order1 ) ||
 575+ $this->tryOrder( $unknowns, $days, $months, $years, $order2 ) ||
 576+ $this->tryOrder( $unknowns, $days, $months, $years, $order3 )
 577+ ) ) {
 578+ foreach( $unknowns as $unknownKey => $unknown ) {
 579+ if ( count( $day ) < 2 ) {
 580+ $days[ $unknownKey ] = $unknown->num;
 581+ }
 582+ elseif ( count( $months ) < 2 ) {
 583+ $months[ $unknownKey ] = $unknown->num;
 584+ }
 585+ else {
 586+ $years[ $unknownKey ] = $unknown->num;
 587+ }
 588+ }
 589+ }
 590+ $isRange = $this->finalizeDate( $days, $months, $years, $eras );
 591+ $this->assignUncertainty( $circas, $isRange, $numbers, $chunks );
 592+
 593+ break;
 594+
 595+ default: /****** CASE 6+ ******/
 596+
 597+ /** Can be one of the following:
 598+ * day-month-year-day-month-year
 599+ * month-day-year-month-day-year
 600+ * year-month-day-year-month-day
 601+ */
 602+ $order1 = array( WCDateNumber::day, WCDateNumber::month, WCDateNumber::year, WCDateNumber::day, WCDateNumber::month, WCDateNumber::year );
 603+ $order2 = array( WCDateNumber::month, WCDateNumber::day, WCDateNumber::year, WCDateNumber::month, WCDateNumber::day, WCDateNumber::year );
 604+ $order3 = array( WCDateNumber::year, WCDateNumber::month, WCDateNumber::day, WCDateNumber::year, WCDateNumber::month, WCDateNumber::day );
 605+ if ( ! (
 606+ $this->dayUpTo31( $unknowns, $months, $years ) ||
 607+ $this->monthUpTo12( $unknowns, $days, $years ) ||
 608+ $this->yearAdjacentEra( $unknowns, $years, $eras, $chunks ) ||
 609+ $this->yearsInOrder( $unknowns, $days, $months, $years, $eras ) ||
 610+ $this->tryOrder( $unknowns, $days, $months, $years, $order1 ) ||
 611+ $this->tryOrder( $unknowns, $days, $months, $years, $order2 ) ||
 612+ $this->tryOrder( $unknowns, $days, $months, $years, $order3 )
 613+ ) ) {
 614+ foreach( $unknowns as $unknownKey => $unknown ) {
 615+ if ( count( $day ) < 2 ) {
 616+ $days[ $unknownKey ] = $unknown->num;
 617+ }
 618+ elseif ( count( $months ) < 2 ) {
 619+ $months[ $unknownKey ] = $unknown->num;
 620+ }
 621+ else {
 622+ $years[ $unknownKey ] = $unknown->num;
 623+ }
 624+ }
 625+ }
 626+ $isRange = $this->finalizeDate( $days, $months, $years, $eras );
 627+ $this->assignUncertainty( $circas, $isRange, $numbers, $chunks );
 628+ }
 629+
 630+ }
 631+
 632+
 633+ /**
 634+ * Determine if $this can be considered a short form of argument $date.
 635+ * If so, then determine the number of matches.
 636+ *
 637+ * @param WCDate $date
 638+ * @return integer|boolean
 639+ */
 640+ public function shortFormMatches( WCData $date ) {
 641+ $matches = 0;
 642+ if ( isset( $this->year ) ) {
 643+ if ( $this->year === $date->year ) ++$matches;
 644+ else return False;
 645+ }
 646+ if ( isset( $this->month ) ) {
 647+ if ( $this->month === $date->month ) ++$matches;
 648+ else return False;
 649+ }
 650+ if ( isset( $this->day ) ) {
 651+ if ( $this->day === $date->day ) ++$matches;
 652+ else return False;
 653+ }
 654+ if ( isset( $this->season ) ) {
 655+ if ( $this->season === $date->season ) ++$matches;
 656+ else return False;
 657+ }
 658+ if ( isset( $this->era ) ) {
 659+ if ( $this->era === $date->era ) ++$matches;
 660+ else return False;
 661+ }
 662+ return $matches;
 663+ }
 664+
 665+
 666+ public function __toString() {
 667+ $text = $this->year;
 668+ if ( $this->year2 ) $text .= '–' . $year2;
 669+ if ( $this->season ) $text .= ' ' . $season;
 670+ if ( $this->season2 ) $text .= '–' . $season2;
 671+ if ( $this->month ) $text .= ' ' . $month;
 672+ if ( $this->month2 ) $text .= '–' . $month2;
 673+ if ( $this->day ) $text .= ' ' . $day;
 674+ if ( $this->day2 ) $text .= '–' . $day2;
 675+ return $text;
 676+ }
 677+
 678+
 679+ /**
 680+ * Match localized month names and abbreviations.
 681+ *
 682+ * @global Language $wgContLang the content Language object
 683+ * @param string $chunk the term being tested
 684+ * @return int the numerical month ( or 0 if no match)
 685+ */
 686+ protected function matchMonths( $date ) {
 687+ global $wgContLang;
 688+ for ( $i=1; $i < 13; $i++ ) {
 689+ if ( $date == $wgContLang->getMonthName( $i )
 690+ || $date == $wgContLang->getMonthAbbreviation( $i )
 691+ || $date == $wgContLang->getMonthNameGen( $i ) ) {
 692+ return $i;
 693+ }
 694+ }
 695+ return 0;
 696+ }
 697+
 698+
 699+ /**
 700+ * Convert a string Roman number to integer.
 701+ * If the string does not represent a Roman number, this function returns 0.
 702+ * @staticvar array $letters
 703+ * @param type $romanNumber = string containing the (possibly) Roman number
 704+ * @return int = the integer corresponding to the Roman number (or zero)
 705+ */
 706+ protected function romanToInt( $romanNumber ) {
 707+ static $letters = array(
 708+ 'M' => 1000, 'CM' => 900, 'D' => 500, 'CD' => 400, 'C' => 100,
 709+ 'XC' => 90, 'L' => 50, 'XL' => 40, 'X' => 10, 'IX' => 9,
 710+ 'V' => 5, 'IV' => 4, 'I' => 1,
 711+ );
 712+ $number = 0;
 713+ foreach ( $letters as $key => $value ) {
 714+ while ( mb_strpos( $romanNumber, $key ) === 0) {
 715+ $result += $value;
 716+ $romanNumber = mb_substr( $romanNumber, mb_strlen( $key ) );
 717+ }
 718+ }
 719+ return $number;
 720+ }
 721+
 722+
 723+ /**
 724+ * If it is a two-digit year, convert to a four-digit year.
 725+ * Cutoff between this and last century is 5 years in the future,
 726+ * to allow for anticipatory citations of to-be-published material.
 727+ * Thus, if in the year 2011 you cited a "01/01/16" publication, the year
 728+ * would be interpreted as 2016, but "01/01/17" would be interpreted as
 729+ * 1917.
 730+ * @param int $year = a two-digit year (this is validated by the function)
 731+ * @return int = the corresponding four-digit year
 732+ */
 733+ protected function adjust2DigitYear( $year ) {
 734+ if ( $year >= 100 ) return $year;
 735+ $curDate = getdate();
 736+ $curYear = $curDate['year'];
 737+ # Two digit year plus the current century:
 738+ $year = $curYear - $curYear % 100 + $year;
 739+ $cutoffYear = $curYear + 5;
 740+ if ( $year > $curYear + 10 ) {
 741+ return $year - 100;
 742+ }
 743+ else {
 744+ return $year;
 745+ }
 746+ }
 747+
 748+
 749+ /**
 750+ * Assign up to two years and two eras (AD or BC, etc.)
 751+ * If the era(s) are not defined, this function assumes AD and converts
 752+ * any two-digit years to full years in the current century. Thus, years
 753+ * prior to 100 AD require an explicit era designation.
 754+ * @param array $eras = array of values comprising either 1=AD or -1=BC
 755+ * @param int $isRange = whether or not the date is a range
 756+ * @param int $year = the year, or first year
 757+ * @param int $year2 = the second year
 758+ */
 759+ protected function assignYearsAndEras( array $eras, $isRange, $year, $year2 = Null ) {
 760+ if ( $isRange ) {
 761+ if ( count( $eras ) >= 2 ) {
 762+ $this->year = $year;
 763+ $this->year2 = $year2;
 764+ $this->era = reset( $eras ); # Use first two eras.
 765+ $this->era2 = next( $eras );
 766+ } elseif ( count ( $eras ) == 1 ) {
 767+ $this->year = $year;
 768+ $this->year2 = $year2;
 769+ $this->era = $this->era2 = reset( $eras );
 770+ } else {
 771+ $this->year = $this->adjust2DigitYear( $year ); # Assume small years are 2-digit years.
 772+ $this->year2 = $this->adjust2DigitYear( $year2 );
 773+ $this->era = $this->era2 = WCDateTermsEnum::AD; # Assume AD.
 774+ }
 775+ } else {
 776+ if ( count( $eras ) >= 1 ) {
 777+ $this->year = $year;
 778+ $this->era = reset( $eras ); # Use first era
 779+ } else {
 780+ $this->year = $this->adjust2DigitYear( $year ); # Assume small years are 2-digit years.
 781+ $this->era = WCDateTermsEnum::AD; # Assume AD.
 782+ }
 783+ }
 784+ }
 785+
 786+
 787+ /**
 788+ * Assign uncertainty to one or both of the dates.
 789+ * Uncertainty is indicated by "circa" or "c." or equivalent localized
 790+ * terms. If there is only one indication of uncertainty, this function
 791+ * determines whether the "circa" etc. is closer to $num1 or $num2.
 792+ * @param array $circas= a list of "circa" indicators
 793+ * @param type $isRange
 794+ * @param array $numbers = the list of all numbers that might be uncertain
 795+ * @param array $chunks = a list of date terms.
 796+ */
 797+ protected function assignUncertainty( array $circas, $isRange, array $numbers, array $chunks ) {
 798+ if ( $isRange ) {
 799+ if ( empty( $circas ) ) {
 800+ $this->isUncertain = $this->isUncertain2 = False;
 801+ }
 802+ # If there are two indications of uncertainty, both dates are uncertain.
 803+ elseif ( count( $circas ) >= 2 ) {
 804+ $this->isUncertain = $this->isUncertain2 = True;
 805+ }
 806+ # For just one indication of uncertainty in a range, the uncertain date is the one
 807+ # where the number ($num1 or $num2) is most adjacent to the indicator
 808+ # of uncertainty.
 809+ else {
 810+ $circaKey = key( reset( $circas ) );
 811+ $uncertainNumber = $this->searchAdjacentTerm( $numbers, $circaKey, $chunks );
 812+ if ( $uncertainNumber ) {
 813+ $uncertainKey = $uncertainNumber->key;
 814+ $uncertainType = $uncertainNumber->numType;
 815+ foreach( $numbers as $number ) {
 816+ if ( $number->numType == $uncertainType ) {
 817+ if ( $number->key == $uncertainKey ) {
 818+ # Key matches the first number of that type
 819+ $this->isUncertain = True;
 820+ $this->isUncertain2 = False;
 821+ }
 822+ else {
 823+ # Key does not match the first number, so probably matches the second
 824+ $this->isUncertain = False;
 825+ $this->isUncertain2 = True;
 826+ }
 827+ return;
 828+ }
 829+ }
 830+ }
 831+ else {
 832+ # None of the terms is adjacent.
 833+ $this->isUncertain = False;
 834+ return;
 835+ }
 836+ }
 837+ }
 838+ else {
 839+ $this->isUncertain = ! empty( $circas );
 840+ }
 841+ }
 842+
 843+
 844+ public function finalizeDate( array $days, array $months, array $years, array $eras ) {
 845+ $isRange = False;
 846+ $year1 = reset( $years );
 847+ if ( $year1 === False ) {
 848+ # No year specified
 849+ $curDate = getdate();
 850+ $this->year = $curDate['year'];
 851+ $this->era = WCDateTermsEnum::AD;
 852+ }
 853+ else {
 854+ # At least one year specified
 855+ $yearKey1 = key( $years );
 856+ $year2 = next( $years );
 857+ if ( $year2 === False || $year2 == $year1 ) {
 858+ # Only one year specified
 859+ $this->assignYearsAndEras( $eras, False, $year1 );
 860+ }
 861+ else {
 862+ # Two years specified
 863+ $yearKey2 = key( $years );
 864+ $isRange = True;
 865+ $this->assignYearsAndEras( $eras, True, $year1, $year2 );
 866+ }
 867+ }
 868+
 869+ $month1 = reset( $months );
 870+ if ( $month1 === False ) {
 871+ # No month specified
 872+ return $isRange;
 873+ }
 874+ else {
 875+ # Month is specified
 876+ $this->month = $month1;
 877+ $month2 = next( $months );
 878+ if ( ! ( $month2 === False ) && $month1 != $month2 ) {
 879+ # Two months specified
 880+ $this->month2 = $month2;
 881+ $isRange = True;
 882+ }
 883+ }
 884+
 885+ $day1 = reset( $days );
 886+ if ( $day1 === False ) {
 887+ # No day specified
 888+ return $isRange;
 889+ }
 890+ else {
 891+ # Day is specified
 892+ $this->day = $day1;
 893+ $day2 = next( $days );
 894+ if ( $day2 === False || $day2 == $day1 ) {
 895+ # Only one day specified
 896+ return $isRange;
 897+ }
 898+ else {
 899+ # Two days specified
 900+ $this->day2 = $day2;
 901+ return True;
 902+ }
 903+ }
 904+
 905+ }
 906+
 907+
 908+ /**
 909+ * Determine whether the term at key $termKey is adjacent to a number.
 910+ * @param array $numbers = an array of WCDateTerm objects
 911+ * @param int $termKey = the key of the term in question
 912+ * @param array $chunks = chunks of user input
 913+ * @return WCDateTerm = WCDateTerm if adjacent, Null if not
 914+ */
 915+ public function searchAdjacentTerm( array $numbers, $termKey, array $chunks ) {
 916+ $s1 = is_set( $numbers[ $termKey - 1 ] );
 917+ $s2 = is_set( $numbers[ $termKey + 1 ] );
 918+ if ( !$s1 && !$s2 ) {
 919+ return Null;
 920+ }
 921+ elseif ( !$s1 && $s2 ) {
 922+ $numberKey = $termKey + 1;
 923+ $number = $numbers[ $numberKey ];
 924+ $years[ $numberKey ] = $number->num;
 925+ return $number;
 926+ }
 927+ elseif ( $s1 && !$s2 ) {
 928+ $numberKey = $termKey - 1;
 929+ $number = $numbers[ $numberKey ];
 930+ $years[ $numberKey ] = $number->num;
 931+ return $number;
 932+ }
 933+ else {
 934+ $number1 = $numbers[ $termKey - 1 ];
 935+ $number2 = $numbers[ $termKey + 1 ];
 936+ $closestNum = $this->closestNumberToTerm( $termKey, $number1, $number2, $chunks );
 937+ if ( $closestNum->key < $termKey ) {
 938+ return $number1;
 939+ }
 940+ else {
 941+ return $number2;
 942+ }
 943+ }
 944+ }
 945+
 946+
 947+ public function closestNumberToTerm( $key, WCDateNumber $num1, WCDateNumber $num2, array $chunks ) {
 948+ $key1 = $num1->key;
 949+ $key2 = $num2->key;
 950+ $dist1 = $key - $key1;
 951+ $dist2 = $key2 - $key;
 952+ $mid1 = implode( '', array_slice( $chunks, $key1 + 1, $dist1 - 1 ) );
 953+ $mid2 = implode( '', array_slice( $chunks, $key + 1, $dist2 - 1 ) );
 954+ $sp1 = preg_match('/^\p{Zs}*$/uS', $mid1 );
 955+ $sp2 = preg_match('/^\p{Zs}*$/uS', $mid2 );
 956+ # Is one number (and not the other) separated from the term by merely space?
 957+ if ( !$sp1 && $sp2 ) {
 958+ return $num2;
 959+ }
 960+ elseif ( $sp1 && !$sp2 ) {
 961+ return $num1;
 962+ }
 963+ # Pick the number, if any, that has fewer intermediate terms.
 964+ elseif ( abs( $dist1 ) < abs( $dist2 ) ) {
 965+ return $num1;
 966+ }
 967+ elseif ( abs( $dist2 ) < abs( $dist1 ) ) {
 968+ return $num2;
 969+ }
 970+ # Pick the number, if any, that has the shortest string between itself and the term:
 971+ elseif ( mb_strlen( $mid1 ) < mb_strlen( $mid2 ) ) {
 972+ return $num1;
 973+ }
 974+ elseif ( mb_strlen( $mid2 ) < mb_strlen( $mid1 ) ) {
 975+ return $num2;
 976+ }
 977+ # Anything that makes it this far would look something like "…AAA 12 BBB…" or "…AAA-12-BBB…".
 978+ return Null;
 979+ }
 980+
 981+
 982+ public function dayUpTo31( array &$unknowns, array &$months, array &$years ) {
 983+ foreach( $unknowns as $unknown ) {
 984+ if ( $unknown->num > 31 ) {
 985+ $unknown->setNotDay( $unknowns, $months, $years );
 986+ }
 987+ }
 988+ return empty( $unknowns );
 989+ }
 990+
 991+
 992+ public function monthUpTo12( array &$unknowns, array &$days, array &$years ) {
 993+ foreach( $unknowns as $unknown ) {
 994+ if ( $unknown->num > 12 ) {
 995+ $unknown->setNotMonth( $unknowns, $days, $years );
 996+ }
 997+ }
 998+ return empty( $unknowns );
 999+ }
 1000+
 1001+
 1002+ public function yearAdjacentEra( array &$unknowns, array &$years, array $eras, array $chunks ) {
 1003+ if ( empty( $eras ) || empty( $unknowns ) ) {
 1004+ return False;
 1005+ }
 1006+ foreach ( $eras as $eraKey => $era ) {
 1007+ $unknown = $this->searchAdjacentTerm( $unknowns, $eraKey, $chunks );
 1008+ if ( $unknown ) {
 1009+ $unknown->setYear( $unknowns, $years );
 1010+ }
 1011+ }
 1012+ return empty( $unknowns );
 1013+ }
 1014+
 1015+
 1016+ public function cannotBeDay( array &$unknowns, &$months, &$years ) {
 1017+ foreach( $unknowns as $unknown ) {
 1018+ $unknown->setNotDay( $unknowns, $months, $years );
 1019+ }
 1020+ return empty( $unknowns );
 1021+ }
 1022+
 1023+
 1024+ /**
 1025+ * Determines whether number can be a year, based on relative year order.
 1026+ * This is only useful when one year has been defined, but not the other
 1027+ * year. It assumes that the user will enter a year range in the proper
 1028+ * numerical order. For example, "09-10" and "7 BC - 4 BC" are proper
 1029+ * ranges, but if the year 7 BC has already been defined, the next year
 1030+ * in the range cannot be 10 BC.
 1031+ * @param array $unknowns
 1032+ * @param array $days
 1033+ * @param array $months
 1034+ * @param array $years
 1035+ * @param array $eras
 1036+ * @return boolean = True if all the $unknowns have been exhausted
 1037+ */
 1038+ public function yearsInOrder( array &$unknowns, array &$days, array &$months, array &$years, array $eras ) {
 1039+ if ( count( $years ) == 1 ) {
 1040+ $year = reset( $years );
 1041+ $yearKey = key( $years );
 1042+ # Date range spans the BC-AD era boundary:
 1043+ if ( empty( $eras ) ) {
 1044+ foreach( $unknowns as $unknownKey => $unknown ) {
 1045+ if ( $unknownKey < $yearKey && $unknown->num > $year
 1046+ || $yearKey < $unknownKey && $year > $unknown->num ) {
 1047+ $unknown->setNotYear( $unknowns, $days, $months );
 1048+ }
 1049+ }
 1050+ }
 1051+ else {
 1052+ $era1 = reset( $eras );
 1053+ $era2 = next( $eras );
 1054+ if ( $era2 === False || $era1 === $era2 ) {
 1055+ if ( $era1 === WCDateTermsEnum::AD ) {
 1056+ foreach( $unknowns as $unknownKey => $unknown ) {
 1057+ if ( $unknownKey < $yearKey && $unknown->num > $year
 1058+ || $yearKey < $unknownKey && $year > $unknown->num ) {
 1059+ $unknown->setNotYear( $unknowns, $days, $months );
 1060+ }
 1061+ }
 1062+ }
 1063+ else {
 1064+ foreach( $unknowns as $unknownKey => $unknown ) {
 1065+ if ( $unknownKey < $yearKey && $unknown->num < $year
 1066+ || $yearKey < $unknownKey && $year < $unknown->num ) {
 1067+ $unknown->setNotYear( $unknowns, $days, $months );
 1068+ }
 1069+ }
 1070+ }
 1071+ }
 1072+ else {
 1073+ return False;
 1074+ }
 1075+ }
 1076+ return empty( $unknowns );
 1077+ }
 1078+ else {
 1079+ return False;
 1080+ }
 1081+ }
 1082+
 1083+
 1084+ public function tryOrder( array &$unknowns, array &$days, array &$months, array &$years, array $order ) {
 1085+ reset( $order );
 1086+ foreach( $unknowns as $unknown ) {
 1087+ switch ( current( $order ) ) {
 1088+ case WCDateNumber::year:
 1089+ if ( $unknown->couldBeYear() ) break;
 1090+ else return False;
 1091+ case WCDateNumber::month:
 1092+ if ( $unknown->couldBeMonth() ) break;
 1093+ else return False;
 1094+ case WCDateNumber::day:
 1095+ if ( $unknown->couldBeDay() ) break;
 1096+ else return False;
 1097+ }
 1098+ next( $order );
 1099+ }
 1100+ reset( $order );
 1101+ foreach( $unknowns as $unknown ) {
 1102+ switch ( current( $order ) ) {
 1103+ case WCDateNumber::year:
 1104+ $unknown->setYear( $unknowns, $years );
 1105+ break;
 1106+ case WCDateNumber::month:
 1107+ $unknown->setMonth( $unknowns, $months );
 1108+ break;
 1109+ case WCDateNumber::day:
 1110+ $unknown->setDay( $unknowns, $days );
 1111+ break;
 1112+ }
 1113+ next( $order );
 1114+ }
 1115+ return empty( $unknowns );
 1116+ }
 1117+
 1118+
 1119+}
 1120+
Property changes on: trunk/extensions/WikiCitation/includes/data/WCDate.php
___________________________________________________________________
Added: svn:eol-style
11121 + native
Property changes on: trunk/extensions/WikiCitation/includes/data
___________________________________________________________________
Added: bugtraq:number
21122 + true
Index: trunk/extensions/WikiCitation/includes/WCCitation.php
@@ -0,0 +1,326 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCCitationPosition extends WCEnum {
 12+ const first = 0;
 13+ const subsequent = 1;
 14+# const ibid = 2;
 15+# const ibidWithLocator = 3;
 16+# const nearNote = 4;
 17+ const __default = self::first;
 18+}
 19+
 20+/**
 21+ * Class representing the finalized citation.
 22+ *
 23+ * This class reads and processes the data from a WCArgumentReader object,
 24+ * and constructs the appropriate WCStyle child based on the referencing style
 25+ * and citation type. Ultimately, a call to WCCitation::composeCitation()
 26+ * will output the fully-formatted citation.
 27+ */
 28+class WCCitation {
 29+
 30+ /**
 31+ * Associated WCReference object, representing the unique reference source.
 32+ * For each WCReference instance, there may be many WCCitation instances.
 33+ * @var WCReference
 34+ */
 35+ public $reference;
 36+
 37+
 38+ /**
 39+ * Position of the citation
 40+ * (E.g., first, subsequent, etc.)
 41+ * @var WCCitationPosition
 42+ */
 43+ public $citationPostion;
 44+
 45+
 46+ /**
 47+ * The citation system: notes and bibliography or author-date.
 48+ * @var WCCitationSystem
 49+ */
 50+ public $citationSystem;
 51+
 52+ /**
 53+ * Marker for this citation, left behind temporarily in text, and later replaced.
 54+ * @var unknown_type
 55+ */
 56+ public $marker;
 57+
 58+ /**
 59+ * The citation style.
 60+ * @var WCStyle
 61+ */
 62+ public $style;
 63+
 64+
 65+ /**
 66+ * The citation type.
 67+ * @var WCCitationType
 68+ */
 69+ public $citationType;
 70+
 71+ /**
 72+ * The citation length.
 73+ * @var WCCitationLength
 74+ */
 75+ public $citationLength;
 76+
 77+ /**
 78+ * Distance in number of citations from last citation to this reference
 79+ * @var integer
 80+ */
 81+ public $distance;
 82+
 83+ /**
 84+ * Locators for this citation.
 85+ * @var array of WCLocator objects
 86+ */
 87+ protected $locators = array();
 88+
 89+
 90+ # output of the parser
 91+ protected $citationText;
 92+
 93+
 94+ /**
 95+ * Constructor.
 96+ */
 97+ public function __construct( WCReference $reference ) {
 98+
 99+ $this->reference = $reference;
 100+ $this->citationPosition = new WCCitationPosition();
 101+
 102+ # Construct a random marker for storage and later replacement by the citation:
 103+ $this->marker = 'wC-' . mt_rand();
 104+
 105+ }
 106+
 107+
 108+ /**
 109+ * Read and parse arguments from a WCArgumentReader object.
 110+ * @param WCArgumentReader $wcArgumentReader = the argument reader
 111+ * @global $wikiCitationValidateArguments
 112+ */
 113+ public function readArguments( WCArgumentReader $argumentReader ) {
 114+
 115+ $this->citationType = $argumentReader->getCitationType();
 116+ $this->citationLength = $argumentReader->getCitationLength();
 117+
 118+ /**
 119+ * Recognize and process the parameters and names.
 120+ */
 121+ foreach( $argumentReader->parameters as $var => $value ) {
 122+
 123+ # See if scope name only is present, in which case the parameter is assumed to be the title.
 124+ # This allows the user to enter "journal=Nature" or "work=Origin of Species", etc.
 125+ $scope = WCScopeEnum::match( $var, WCScopeEnum::$magicWordArray,
 126+ WCScopeEnum::$flipMagicWordKeys, 'WCScopeEnum' );
 127+ if ( $scope ) {
 128+ $property = WCPropertyEnum::$title;
 129+ $this->reference->setProperty( $scope, $property, new WCTitle( $value ) );
 130+ continue;
 131+ }
 132+
 133+ # Match the parameter scope.
 134+ list( $scope, $parameterText ) = WCScopeEnum::matchPrefix( $var, WCScopeEnum::$magicWordArray,
 135+ WCScopeEnum::$flipMagicWordKeys, 'WCScopeEnum' );
 136+ if ( !$scope ) {
 137+ $scope = WCScopeEnum::$work; # Set the default
 138+ }
 139+
 140+ # See if a type name is present, in which case the parameter is assumed to be the title.
 141+ # This allows the wiki editor to enter "book=Origin of Species", "pamphlet=Common Sense," etc., or even "container-encyclopedia=Encyclopedia Brittanica."
 142+ # If either the title or type have already been set, then neither will be set again.
 143+ # Thus, it will be possible to use "book" as a locator.
 144+ $type = WCSourceTypeEnum::match( $parameterText, WCSourceTypeEnum::$magicWordArray,
 145+ WCSourceTypeEnum::$flipMagicWordKeys, 'WCTypeEnum' );
 146+ if ( $type ) {
 147+ $propertyEnumTitle = WCPropertyEnum::$title;
 148+ $propertyEnumType = WCPropertyEnum::$type;
 149+ $title = $this->reference->getProperty( $scope, $propertyEnumTitle );
 150+ $type = $this->reference->getProperty( $scope, $propertyEnumType );
 151+ if ( is_null( $this->reference->getProperty( $scope, $propertyEnumTitle ) ) && is_null( $this->getProperty( $scope, $propertyEnumType ) ) ) {
 152+ $this->reference->setProperty( $scope, $propertyEnumTitle, new WCTitle( $value ) );
 153+ $this->reference->setProperty( $scope, $propertyEnumType, new WCTypeData( $type ) );
 154+ }
 155+ continue;
 156+ }
 157+
 158+ global $wikiCitationValidateArguments;
 159+
 160+ # Match properties.
 161+ $property = WCPropertyEnum::match( $parameterText, WCPropertyEnum::$magicWordArray,
 162+ WCPropertyEnum::$flipMagicWordKeys, 'WCPropertyEnum' );
 163+ if ( $property ) {
 164+ $attributeKey = $property->getAttribute()->key;
 165+ $attributeClass = WCAttributeEnum::$attribute[ $attributeKey ];
 166+ if ( $attributeKey == WCAttributeEnum::locator ) {
 167+ # Locators disregard the scope.
 168+ $locator = $this->getLocator( $property );
 169+ if ( $wikiCitationValidateArguments && isset( $locator ) ) {
 170+ throw new WCException( 'wc-parameter_defined_twice', $property );
 171+ } else {
 172+ $this->setLocator( $property, new WCLocator( $value ) );
 173+ }
 174+ } else {
 175+ $prop = $this->reference->getProperty( $scope, $property );
 176+ if ( $wikiCitationValidateArguments && isset( $prop ) ) {
 177+ throw new WCException( 'wc-parameter_defined_twice', $property );
 178+ } else {
 179+ $this->reference->setProperty( $scope, $property, new $attributeClass( $value ) );
 180+ }
 181+ }
 182+ # Set attribute
 183+ continue;
 184+ }
 185+
 186+ # Match names.
 187+ $match = False;
 188+ list( $nameEnum, $namePartText ) = WCNameTypeEnum::matchPrefix( $parameterText,
 189+ WCNameTypeEnum::$magicWordArray, WCNameTypeEnum::$flipMagicWordKeys, 'WCNameTypeEnum' );
 190+ if ( $namePartText ) {
 191+ list( $namePartEnum, $nameNum ) = WCNamePartEnum::matchPartAndNumber(
 192+ $namePartText, WCNamePartEnum::$magicWordArray, WCNamePartEnum::$flipMagicWordKeys, 'WCNamePartEnum' );
 193+ if ( $namePartEnum ) {
 194+ if ( !$nameEnum ) {
 195+ $nameEnum = new WCNameTypeEnum();
 196+ }
 197+ $match = True;
 198+ } elseif ( $nameEnum ) {
 199+ $namePartEnum = new WCNamePartEnum();
 200+ $match = True;
 201+ }
 202+ } elseif ( $nameEnum ) {
 203+ $namePartEnum = new WCNamePartEnum();
 204+ $nameNum = 1;
 205+ $match = True;
 206+ }
 207+ if ( $match ) {
 208+ if ( is_null( $this->reference->getNames( $scope, $nameEnum ) ) ) {
 209+ $this->reference->setNames( $scope, $nameEnum, new WCNames() );
 210+ }
 211+ $theNames = $this->reference->getNames( $scope, $nameEnum );
 212+ $part = $theNames->getNamePart( $nameNum, $namePartEnum );
 213+ if ( $wikiCitationValidateArguments && isset( $part ) ) {
 214+ throw new WCException( 'wc-parameter_defined_twice', $nameEnum . $nameNum. '-' . $namePartEnum );
 215+ } else {
 216+ $theNames->setNamePart( $nameNum, $namePartEnum, $value );
 217+ }
 218+ continue;
 219+ }
 220+
 221+ # Argument has no matches.
 222+ if ( $wikiCitationValidateArguments ) {
 223+ throw new WCException( 'wc-parameter-unknown', $parameterText );
 224+ }
 225+ }
 226+
 227+ }
 228+
 229+
 230+ /**
 231+ * Renders the citation and stores the result in $this->citation.
 232+ * @param WCStyle $style
 233+ * @return array = the rendered citation and sorting parts.
 234+ */
 235+ public function render() {
 236+
 237+ # Build the citation
 238+ if ( $this->citationLength->key == WCCitationLengthEnum::short ) {
 239+ switch ( $this->citationType->key ) {
 240+ case WCCitationTypeEnum::note:
 241+ list( $citation, $sortingParts ) = $this->style->renderShortNoteCitation( $this );
 242+ break;
 243+ case WCCitationTypeEnum::inline:
 244+ list( $citation, $sortingParts ) = $this->style->renderShortInlineCitation( $this );
 245+ break;
 246+ case WCCitationTypeEnum::authorDate:
 247+ list( $citation, $sortingParts ) = $this->style->renderShortAuthorDateCitation( $this );
 248+ }
 249+ } else {
 250+ switch ( $this->citationType->key ) {
 251+ case WCCitationTypeEnum::note:
 252+ list( $citation, $sortingParts ) = $this->style->renderLongNoteCitation( $this );
 253+ break;
 254+ case WCCitationTypeEnum::biblio:
 255+ list( $citation, $sortingParts ) = $this->style->renderLongBiblioCitation( $this );
 256+ break;
 257+ case WCCitationTypeEnum::authorDate:
 258+ list( $citation, $sortingParts ) = $this->style->renderLongAuthorDateCitation( $this );
 259+ break;
 260+ default: # case WCCitationTypeEnum::inline:
 261+ list( $citation, $sortingParts ) = $this->style->renderLongInlineCitation( $this );
 262+ }
 263+ }
 264+
 265+ # Wrap the entire citation in an HTML span element with classes.
 266+ $classHTML = WCStyle::citationHTML . ' ' .
 267+ $this->style->styleHTML . ' ' .
 268+ $this->reference->getWorkType() . ' ' .
 269+ $this->citationType . ' ' .
 270+ $this->citationLength;
 271+
 272+ return array( WCStyle::wrapHTMLSpan( $citation, $classHTML ), $sortingParts );
 273+
 274+ }
 275+
 276+
 277+ /**
 278+ * The string representation of this object.
 279+ * @return string citation as wikitext.
 280+ */
 281+ final public function __toString() {
 282+ return (string) $this->citationText;
 283+ }
 284+
 285+
 286+ /**
 287+ * Infer the intended locator value string based on potentially incomplete
 288+ * info. The arguments will be revised to reflect the new types.
 289+ * @param WCPropertyEnum $propertyType
 290+ * @return WCLocator
 291+ */
 292+ public function inferLocator( WCPropertyEnum &$locatorType ) {
 293+ foreach( $locatorType as $testLocatorTypeKey ) {
 294+ if ( isset( $this->locators[ $testLocatorTypeKey ] ) ) {
 295+ $locatorType->key = $testLocatorTypeKey;
 296+ return $this->locators[ $testLocatorTypeKey ];
 297+ }
 298+ }
 299+ return Null;
 300+
 301+ }
 302+
 303+
 304+ /**
 305+ * Getter for a locator.
 306+ * @param WCPropertyEnum $type
 307+ * @return WCLocator
 308+ */
 309+ public function getLocator( WCPropertyEnum $type ) {
 310+ if ( isset( $this->locators[ $type->key ] ) ) {
 311+ return $this->locators[ $type->key ];
 312+ } else {
 313+ return Null;
 314+ }
 315+ }
 316+
 317+
 318+ /**
 319+ * Setter for a locator.
 320+ * @param WCPropertyEnum $type
 321+ * @param WCLocator $locator
 322+ */
 323+ public function setLocator( WCPropertyEnum $type, WCLocator $locator ) {
 324+ $this->locators[ $type->key ] = $locator;
 325+ }
 326+
 327+}
Property changes on: trunk/extensions/WikiCitation/includes/WCCitation.php
___________________________________________________________________
Added: svn:eol-style
1328 + native
Index: trunk/extensions/WikiCitation/includes/WCBibliography.php
@@ -0,0 +1,139 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+class WCBibliography {
 12+
 13+ const bibliographyHTML = 'bibliography'; # HTML class for the note marker
 14+
 15+ protected static $citeStyleAttributeWords, $typeAttributeWords;
 16+
 17+ protected $marker;
 18+
 19+ protected $citationStyle, $citationType;
 20+
 21+ protected $styleHTML;
 22+
 23+ /**
 24+ * Static initializer.
 25+ */
 26+ public static function init() {
 27+ $citeStyleMW = MagicWord::get( 'wc_citestyle_attrib' );
 28+ self::$citeStyleAttributeWords = $citeStyleMW->getSynonyms();
 29+ $typeMW = MagicWord::get( 'wc_type_attrib' );
 30+ self::$typeAttributeWords = $typeMW->getSynonyms();
 31+ }
 32+
 33+ /**
 34+ * Get a new WCBibliography object based on HTML arguments.
 35+ * @param array $args
 36+ * @return WCBibliography
 37+ */
 38+ public static function getBibliography( array $args, WCStyle $defaultStyle ) {
 39+ foreach( $args as $attrib => $value ) {
 40+ if ( in_array( $attrib, self::$citeStyleAttributeWords ) ) {
 41+ $styleClassName = WCArgumentReader::matchStyleClassName( $value );
 42+ } elseif ( in_array( $attrib, self::$typeAttributeWords ) ) {
 43+ $citationTypeID = WCCitationTypeEnum::match( $value );
 44+ if ( isset( $citationTypeID ) ) {
 45+ $citationType = new WCCitationTypeEnum( $citationTypeID );
 46+ }
 47+ } elseif ( $args[ 'style' ] ) {
 48+ $this->styleHTML = ' style="' . $args[ 'style' ] . '"';
 49+ } elseif ( $args[ 'id' ] ) {
 50+ $this->styleHTML = ' id="' . $args[ 'id' ] . '"';
 51+ }
 52+ }
 53+
 54+ if ( isset( $styleClassName ) ) {
 55+ # See if a specific style object has already been defined, and if so, use it.
 56+ $styleObject = WCArticle::getStyle( $styleClassName );
 57+ } else {
 58+ # Use default citation style.
 59+ $styleObject = $defaultStyle;
 60+ }
 61+
 62+ if ( isset( $citationType ) && $citationTypeID === WCCitationTypeEnum::authorDate ) {
 63+ return new WCBibliography( $styleObject, WCCitationTypeEnum::$authorDate );
 64+ } else {
 65+ return new WCBibliography( $styleObject, WCCitationTypeEnum::$biblio );
 66+ }
 67+ }
 68+
 69+ public function __construct( WCStyle $style, WCCitationTypeEnum $type ) {
 70+ $this->citationStyle = $style;
 71+ $this->citationType = $type;
 72+ $this->marker = 'BwC-' . mt_rand();
 73+ }
 74+
 75+ public function getMarker() {
 76+ return $this->marker;
 77+ }
 78+
 79+ /**
 80+ * Need to create separate WCCitation object for each entry here!!
 81+ * Enter description here ...
 82+ * @param unknown_type $text
 83+ * @param WCArticle $article
 84+ */
 85+ public function render( &$text, WCReferenceStore $referenceStore ) {
 86+
 87+ $references = $referenceStore->getReferences();
 88+
 89+ $entries = array();
 90+
 91+ # Render entries in biblio format.
 92+ foreach( $references as $key => $reference ) {
 93+ $citation = new WCCitation( $reference );
 94+ $citation->style = $this->citationStyle;
 95+ $citation->citationType = $this->citationType;
 96+ $citation->citationLength = WCCitationLengthEnum::$long;
 97+ $entries[ $key ] = $citation->render();
 98+ }
 99+
 100+ # Sort bibliography.
 101+ $this->sortBibliography( $entries );
 102+
 103+ # Generate bibliography.
 104+ $bibliography = '<ul class="bibliography"' . $this->styleHTML . '>' . PHP_EOL;
 105+ foreach ( $entries as $key => $entry ) {
 106+ $bibliography .= '<li id="' . $references[ $key ]->id . '">' . $entry[0] . '</li>' . PHP_EOL;
 107+ }
 108+ $bibliography .= '</ul>';
 109+ $text = str_replace( $this->marker, $bibliography, $text );
 110+ }
 111+
 112+ protected function sortBibliography( array &$entries ) {
 113+ uasort( $entries, array( 'WCBibliography', 'compareBibliographyEntries' ) );
 114+ }
 115+
 116+ protected static function compareBibliographyEntries( array $entry1, array $entry2 ) {
 117+ $segment1 = $entry1[1]; # WCSegment objects (usually WCGroupSegment).
 118+ $segment2 = $entry2[1]; #
 119+ $segment1->rewind();
 120+ $segment2->rewind();
 121+ while ( $segment1->valid() && $segment2->valid() ) {
 122+ $part1 = $segment1->current();
 123+ $part2 = $segment2->current();
 124+ $cmp = strnatcasecmp( $part1, $part2 );
 125+ if ( $cmp ) {
 126+ return $cmp;
 127+ }
 128+ $segment1->next();
 129+ $segment2->next();
 130+ }
 131+ return 0;
 132+ }
 133+
 134+}
 135+
 136+
 137+/**
 138+ * Static initializer.
 139+ */
 140+WCBibliography::init();
Property changes on: trunk/extensions/WikiCitation/includes/WCBibliography.php
___________________________________________________________________
Added: svn:eol-style
1141 + native
Index: trunk/extensions/WikiCitation/includes/WCReferenceStore.php
@@ -0,0 +1,138 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * Represents a cache of unique WCReference objects.
 13+ */
 14+class WCReferenceStore {
 15+
 16+ /**
 17+ * List of unique references
 18+ * @var array
 19+ */
 20+ protected $referenceList = array();
 21+
 22+ /**
 23+ * Array of references keyed to ID.
 24+ * Each entry in the array is not necessarily unique
 25+ * @var array [ intR ] => WCReference
 26+ */
 27+ protected $references = array();
 28+
 29+ /**
 30+ * Hash table for references.
 31+ * @var array ( stringH => array ( int => intR ) )
 32+ */
 33+ protected $hashTable = array(); # Hash array for unique citations.
 34+
 35+ /**
 36+ * Constructor.
 37+ */
 38+# public function __construct() {
 39+# }
 40+
 41+ /**
 42+ * Add a reference to the cache, checking for prior duplicates.
 43+ * @param integer $key = a unique key
 44+ * @param WCReference $reference
 45+ * @return integer = number of citations from last use of this reference.
 46+ */
 47+ public function addUniqueReference( $key, WCReference $reference ) {
 48+ $referenceKey = array( $key );
 49+
 50+ $hash = $reference->getHash();
 51+ if ( empty( $hash ) ) {
 52+ # If empty hash, search all prior hashed references.
 53+ foreach( $this->hashTable as &$hashArray ) {
 54+ foreach( $hashArray as &$testKey ) {
 55+ $testReference = $this->references[ $testKey ];
 56+ # If $reference can be considered a short form of prior reference:
 57+ if ( $reference->shortFormMatches( $testReference ) ) {
 58+ $lastKey = end( $testReference ->keys );
 59+ $testReference->keys += $referenceKey;
 60+ # Forget this reference:
 61+ $this->references[ $key ] = $testReference;
 62+ return $key - $lastKey;
 63+ }
 64+ # If prior reference can be considered a short form of $reference:
 65+ elseif ( $testReference->shortFormMatches( $reference ) ) {
 66+ $lastKey = end( $testReference ->keys );
 67+ $reference->keys = $testReference->keys + $referenceKey;
 68+ # Forget the earlier reference.
 69+ unset( $this->referenceList [ $testKey ] );
 70+ $this->referenceList[ $key ] = $reference;
 71+ $this->references[ $testKey ] = $reference;
 72+ $this->references[ $key ] = $reference;
 73+ $testKey = $key;
 74+ return $key - $lastKey;
 75+ }
 76+ }
 77+ }
 78+ }
 79+ # Handle hash table collisions.
 80+ elseif ( isset( $this->hashTable[ $hash ] ) ) {
 81+ # Search collision entries.
 82+ foreach( $this->hashTable[ $hash ] as &$testKey ) {
 83+ $testReference = $this->references[ $testKey ];
 84+ # If $reference can be considered a short form of prior reference:
 85+ if ( $reference->shortFormMatches( $testReference ) ) {
 86+ $lastKey = end( $testReference ->keys );
 87+ $testReference->keys += $referenceKey;
 88+ # Forget this reference:
 89+ $this->references[ $key ] = $testReference;
 90+ return $key - $lastKey;
 91+ }
 92+ # if prior reference can be considered a short form of $reference:
 93+ elseif ( $testReference->shortFormMatches( $reference ) ) {
 94+ $lastKey = end( $testReference ->keys );
 95+ $reference->keys = $testReference->keys + $referenceKey;
 96+ # Forget the earlier reference.
 97+ unset( $this->referenceList [ $testKey ] );
 98+ $this->referenceList[ $key ] = $reference;
 99+ $this->references[ $testKey ] = $reference;
 100+ $this->references[ $key ] = $reference;
 101+ $testKey = $key;
 102+ return $key - $lastKey;
 103+ }
 104+ }
 105+ # If no collision yet, search prior empty hashes.
 106+ foreach( $this->hashTable[ '' ] as $id => &$testKey ) {
 107+ $testReference = $this->references[ $testKey ];
 108+ if ( $testReference->shortFormMatches( $reference ) ) {
 109+ $lastKey = end( $testReference ->keys );
 110+ $reference->keys = $testReference->keys + $referenceKey;
 111+ # Forget the earlier reference.
 112+ unset( $this->referenceList [ $testKey ] );
 113+ $this->referenceList [ $key ] = $reference;
 114+ $this->references[ $testKey ] = $reference;
 115+ $this->references[ $key ] = $reference;
 116+ # Correct hash table
 117+ unset( $this->hashTable[ '' ][ $id ] );
 118+ $this->hashTable[ $hash ][] = $key;
 119+ return $key - $lastKey;
 120+ }
 121+ }
 122+ }
 123+ # If no hash table match:
 124+ $reference->keys = $referenceKey;
 125+ $this->referenceList[ $key ] = $reference;
 126+ $this->references[ $key ] = $reference;
 127+ $this->hashTable[ $hash ][] = $key;
 128+ return 0;
 129+ }
 130+
 131+ public function getReference( $key ) {
 132+ return $this->references[ $key ];
 133+ }
 134+
 135+ public function getReferences() {
 136+ return $this->referenceList;
 137+ }
 138+
 139+}
Property changes on: trunk/extensions/WikiCitation/includes/WCReferenceStore.php
___________________________________________________________________
Added: svn:eol-style
1140 + native
Index: trunk/extensions/WikiCitation/includes/WCException.php
@@ -0,0 +1,32 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * An Exception for use within WikiCitation.
 13+ */
 14+class WCException extends UnexpectedValueException {
 15+
 16+ /**
 17+ * Constructor.
 18+ *
 19+ * In addition to a message key, the constructor may include optional
 20+ * arguments of any number, as in:
 21+ * new WCException( 'message-1', ... );
 22+ * @param messageKey string The message key
 23+ * @param optionalArgs string = any number of arguments
 24+ * @return string Value of object.
 25+ */
 26+ public function __construct( $messageKey ) {
 27+ $args = func_get_args();
 28+ array_shift( $args );
 29+ $transformedMessage = wfMsgReal( $messageKey, $args, true );
 30+ parent::__construct( $transformedMessage );
 31+ }
 32+
 33+}
\ No newline at end of file
Property changes on: trunk/extensions/WikiCitation/includes/WCException.php
___________________________________________________________________
Added: svn:eol-style
134 + native
Index: trunk/extensions/WikiCitation/includes/WCReference.php
@@ -0,0 +1,403 @@
 2+<?php
 3+/**
 4+ * Part of WikiCitation extension for Mediawiki.
 5+ *
 6+ * @ingroup WikiCitation
 7+ * @file
 8+ */
 9+
 10+
 11+/**
 12+ * Class representing a unique reference source.
 13+ *
 14+ * There should be only one instance of this object per unique reference.
 15+ * However, there may be multiple instances per WCCitation object, if the same
 16+ * reference is cited multiple times in an article.
 17+ * Instances of this class are created by the WCCitation object.
 18+ */
 19+class WCReference {
 20+
 21+ /**
 22+ * Unique random ID for this reference, for cross-referencing bibliographies.
 23+ * @var string
 24+ */
 25+ public $id;
 26+
 27+ /**
 28+ * Keys of all citations in an article that cite this reference.
 29+ * This is set by the WCReferenceStore object.
 30+ * @var unknown_type
 31+ */
 32+ public $keys = array();
 33+
 34+ /**
 35+ * A multidimensional array of WCNames objects.
 36+ * Index 1 (:: WCScopeEnum->key) is the scope of the WCNames object (e.g., work).
 37+ * Index 2 (:: WCNameTypeEnum->key) is the name type of the WCNames object (e.g., author).
 38+ * @var array [ int ] [ int ] => WCNames
 39+ */
 40+ protected $names = array();
 41+
 42+ /**
 43+ * A multidimensional array of WCData objects.
 44+ * Index 1 (:: WCScopeEnum->key) is the scope of the WCData object (e.g., work).
 45+ * Index 2 (:: WCPropertyEnum->key) is the property type of the WCData object (e.g., title).
 46+ * @var array [ int ] [ int ] => WCData
 47+ */
 48+ protected $properties = array();
 49+
 50+
 51+ /**
 52+ * Constructor.
 53+ */
 54+ public function __construct() {
 55+ # Construct a random marker for cross-referencing bibliographies:
 56+ $this->id = 'RwC-' . mt_rand();
 57+ }
 58+
 59+
 60+ /**
 61+ * Setter for reference properties.
 62+ * @param WCScopeEnum $scope
 63+ * @param WCPropertyEnum $type
 64+ * @param WCData $data
 65+ */
 66+ public function setProperty( WCScopeEnum $scope, WCPropertyEnum $type, WCData $data ) {
 67+ $this->properties[ $scope->key ][ $type->key ] = $data;
 68+ }
 69+
 70+
 71+ /**
 72+ * Getter for reference properties.
 73+ * @param WCScopeEnum $scope
 74+ * @param WCPropertyEnum $type
 75+ * @return WCData
 76+ */
 77+ public function getProperty( WCScopeEnum $scope, WCPropertyEnum $type ) {
 78+ if ( isset( $this->properties[ $scope->key ][ $type->key ] ) ) {
 79+ return $this->properties[ $scope->key ][ $type->key ];
 80+ } else {
 81+ return Null;
 82+ }
 83+ }
 84+
 85+
 86+ /**
 87+ * Setter for reference names.
 88+ * @param WCScopeEnum $scope
 89+ * @param WCNameTypeEnum $type
 90+ * @param WCNames $names
 91+ */
 92+ public function setNames( WCScopeEnum $scope, WCNameTypeEnum $type, WCNames $names ) {
 93+ $this->names[ $scope->key ][ $type->key ] = $names;
 94+ }
 95+
 96+
 97+ /**
 98+ * Getter for reference names.
 99+ * @param WCScopeEnum $scope
 100+ * @param WCNameTypeEnum $names
 101+ * @return WCNames
 102+ */
 103+ public function getNames( WCScopeEnum $scope, WCNameTypeEnum $names ) {
 104+ if ( isset( $this->names[ $scope->key ][ $names->key ] ) ) {
 105+ return $this->names[ $scope->key ][ $names->key ];
 106+ } else {
 107+ return Null;
 108+ }
 109+ }
 110+
 111+
 112+ /**
 113+ * Finalize the reference after all data has been added.
 114+ * No data about the reference should be added after this function is called.
 115+ * The function makes inferences about possible missing data.
 116+ */
 117+ public function finalize() {
 118+
 119+ # If the reference type values are not set, try to infer them.
 120+ $this->setInferredTypes();
 121+
 122+ # Make other property inferences
 123+ $this->setInferredProperties();
 124+
 125+ # Sort the names on the basis of name key order, maintaining keys.
 126+ foreach( $this->names as $nameTypes ) {
 127+ foreach( $nameTypes as $names ) {
 128+ if ( $names ) {
 129+ $names->sort();
 130+ }
 131+ }
 132+ }
 133+
 134+ }
 135+
 136+
 137+ /**
 138+ * Infer the intended WCNames object based on potentially incomplete info.
 139+ * The arguments will be revised to reflect the new types.
 140+ * @param WCScopeEnum $scope
 141+ * @param WCNameTypeEnum $nameType
 142+ * @return WCNames
 143+ */
 144+ public function inferNames( WCScopeEnum &$scope, WCNameTypeEnum &$nameType ) {
 145+ foreach( $scope as $testScopeKey ) {
 146+ foreach( $nameType as $testNameTypeKey ) {
 147+ if ( isset( $this->names[ $testScopeKey ][ $testNameTypeKey ] ) ) {
 148+ $scope->key = $testScopeKey;
 149+ $nameType->key = $testNameTypeKey;
 150+ return $this->names[ $testScopeKey ][ $testNameTypeKey ];
 151+ }
 152+ }
 153+ }
 154+ return Null;
 155+ }
 156+
 157+
 158+ /**
 159+ * Infer the intended property value string based on potentially incomplete
 160+ * info. The arguments will be revised to reflect the new types.
 161+ * This method should not be used with locator propreties.
 162+ * @param WCScopeEnum $scope
 163+ * @param WCPropertyEnum $propertyType
 164+ * @return WCData
 165+ */
 166+ public function inferProperty( WCScopeEnum &$scope, WCPropertyEnum &$propertyType ) {
 167+ foreach( $scope as $testScopeKey ) {
 168+ foreach( $propertyType as $testPropertyTypeKey ) {
 169+ if ( isset( $this->properties[ $testScopeKey ][ $testPropertyTypeKey ] ) ) {
 170+ $scope->key = $testScopeKey;
 171+ $propertyType->key = $testPropertyTypeKey;
 172+ return $this->properties[ $testScopeKey ][ $testPropertyTypeKey ];
 173+ }
 174+ }
 175+ }
 176+ return Null;
 177+
 178+ }
 179+
 180+
 181+ /**
 182+ * Gets the work type (i.e., book, article, etc.)
 183+ * @return WCSourceTypeEnum
 184+ */
 185+ public function getWorkType() {
 186+ if ( isset( $this->properties[ WCScopeEnum::work ][ WCPropertyEnum::type ] ) ) {
 187+ return $this->properties[ WCScopeEnum::work ][ WCPropertyEnum::type ]->parameter;
 188+ } else {
 189+ return WCSourceTypeEnum::$general;
 190+ }
 191+ }
 192+
 193+
 194+ /**
 195+ * Gets the container type (i.e., book, periodical, etc.)
 196+ * @return WCSourceTypeEnum
 197+ */
 198+ public function getContainerType() {
 199+ if ( isset( $this->properties[ WCScopeEnum::container ][ WCPropertyEnum::type ] ) ) {
 200+ return $this->properties[ WCScopeEnum::container ][ WCPropertyEnum::type ]->parameter;
 201+ } else {
 202+ return WCSourceTypeEnum::$general;
 203+ }
 204+ }
 205+
 206+
 207+ /**
 208+ * Gets the series type (i.e., journal, newspaper, etc.)
 209+ * @return WCSourceTypeEnum
 210+ */
 211+ public function getSeriesType() {
 212+ if ( isset( $this->properties[ WCScopeEnum::series ][ WCPropertyEnum::type ] ) ) {
 213+ return $this->properties[ WCScopeEnum::series ][ WCPropertyEnum::type ]->parameter;
 214+ } else {
 215+ return WCSourceTypeEnum::$general;
 216+ }
 217+ }
 218+
 219+
 220+ /**
 221+ * Determine if $this can be considered a short form of the argument.
 222+ * If so, then determine the number of matches.
 223+ *
 224+ * @param WCNames $names
 225+ * @return integer|boolean
 226+ */
 227+ public function shortFormMatches( WCReference $reference ) {
 228+ $matches = 0;
 229+ # Compare names.
 230+ foreach( $this->names as $scopeKey => $nameTypes ) {
 231+ foreach( $nameTypes as $nameTypeKey => $thisNames ) {
 232+ $otherNames = $reference->getNames( new WCScopeEnum( $scopeKey ), new WCNameTypeEnum( $nameTypeKey ) );
 233+ if ( isset( $otherNames ) ) {
 234+ $subMatches = $thisNames->shortFormMatches( $otherNames );
 235+ if ( $subMatches === False ) {
 236+ return False;
 237+ } else {
 238+ $matches += $subMatches;
 239+ }
 240+ }
 241+ }
 242+ }
 243+ # Compare properties.
 244+ foreach( $this->properties as $scopeKey => $propertyTypes ) {
 245+ foreach( $propertyTypes as $propertyTypeKey => $thisProperty ) {
 246+ $otherProperty = $reference->getProperty( new WCScopeEnum( $scopeKey ), new WCPropertyEnum( $propertyTypeKey ) );
 247+ if ( isset( $otherProperty ) ) {
 248+ $subMatches = $thisProperty->shortFormMatches( $otherProperty );
 249+ if ( $subMatches === False ) {
 250+ return False;
 251+ } else {
 252+ $matches += $subMatches;
 253+ }
 254+ }
 255+ }
 256+ }
 257+ return $matches;
 258+
 259+ }
 260+
 261+
 262+ /**
 263+ * Get a hash value which is roughly (though not always) unique to the citation.
 264+ * The hash value is author surname concatenated with year.
 265+ * If no author surname or year are given, the hash is an empty string.
 266+ * @return string The hash value
 267+ */
 268+ public function getHash() {
 269+ if ( isset( $this->names[ WCScopeEnum::work ][ WCNameTypeEnum::author ] ) ) {
 270+ $surname = $this->names[ WCScopeEnum::work ][ WCNameTypeEnum::author ]->getNamePart( 1, WCNamePartEnum::$surname );
 271+ if ( $surname ) {
 272+ $hash = $surname;
 273+ } else {
 274+ return '';
 275+ }
 276+ } else {
 277+ return '';
 278+ }
 279+ if ( isset( $this->properties[ WCScopeEnum::work ][ WCPropertyEnum::date ] ) ) {
 280+ $hash .= $this->properties[ WCScopeEnum::work ][ WCPropertyEnum::date ]->year;
 281+ return $hash;
 282+ } else {
 283+ return '';
 284+ }
 285+
 286+ }
 287+
 288+
 289+ /**
 290+ * Infer the intended property types for each scope, if not set.
 291+ */
 292+ protected function setInferredTypes() {
 293+
 294+ # If any series name or property has been defined:
 295+ if ( isset( $this->names[ WCScopeEnum::series ] ) || isset( $this->properties[ WCScopeEnum::series ] ) ) {
 296+ $series = &$this->properties[ WCScopeEnum::series ][ WCPropertyEnum::type ];
 297+ if ( is_null( $series ) ) {
 298+ # A series property has been defined, but the type has not been defined, assume it is a periodical:
 299+ $series = new WCTypeData( WCSourceTypeEnum::$periodical );
 300+ }
 301+ if ( isset( $this->properties[ WCScopeEnum::work ][ WCPropertyEnum::type ] ) ) {
 302+ return;
 303+ }
 304+ else {
 305+ switch ( $series->parameter->key ) {
 306+ case WCSourceTypeEnum::periodical:
 307+ case WCSourceTypeEnum::journal:
 308+ case WCSourceTypeEnum::magazine:
 309+ case WCSourceTypeEnum::newspaper:
 310+ # If the series is a periodical, the work is likely an article.
 311+ $type = WCSourceTypeEnum::$article;
 312+ break;
 313+ # If the series is designated as a book, encyclopedia or dictionary, the user probably intended it to be the container.
 314+ case WCSourceTypeEnum::book:
 315+ $type = WCSourceTypeEnum::$chapter;
 316+ $this->properties[ WCScopeEnum::container ][ WCPropertyEnum::type ] = $series;
 317+ unset( $series );
 318+ break;
 319+ case WCSourceTypeEnum::encyclopedia:
 320+ case WCSourceTypeEnum::dictionary:
 321+ $type = new WCSourceTypeEnum( WCSourceTypeEnum::entry );
 322+ $this->properties[ WCScopeEnum::container ][ WCPropertyEnum::type ] = $series;
 323+ unset( $series );
 324+ break;
 325+ default:
 326+ $type = new WCSourceTypeEnum( WCSourceTypeEnum::general );
 327+ }
 328+ $this->properties[ WCScopeEnum::work ][ WCPropertyEnum::type ] =
 329+ new WCTypeData( $type );
 330+ return;
 331+ }
 332+ }
 333+
 334+ # If any container name or property has been defined:
 335+ if ( isset( $this->names[ WCScopeEnum::container ] ) || isset( $this->properties[ WCScopeEnum::container ] ) ) {
 336+ $container = &$this->properties[ WCScopeEnum::container ][ WCPropertyEnum::type ];
 337+ if ( ! isset( $container ) ) {
 338+ # A series property has been defined, but the type has not been defined, assume it is a periodical:
 339+ $container = new WCTypeData( WCSourceTypeEnum::$book );
 340+ }
 341+ if ( isset( $this->properties[ WCScopeEnum::work ][ WCPropertyEnum::type ] ) ) {
 342+ return;
 343+ }
 344+ else {
 345+ switch ( $container->parameter->key ) {
 346+ # If the series is an encyclopedia or dictionary, the work is likely a book.
 347+ case WCSourceTypeEnum::encyclopedia:
 348+ case WCSourceTypeEnum::dictionary:
 349+ $type = WCSourceTypeEnum::$book;
 350+ break;
 351+ # If the container is designated as a periodical, the user probably intended it to be the series.
 352+ case WCSourceTypeEnum::periodical:
 353+ case WCSourceTypeEnum::journal:
 354+ case WCSourceTypeEnum::magazine:
 355+ case WCSourceTypeEnum::newspaper:
 356+ $type = WCSourceTypeEnum::$article;
 357+ $this->properties[ WCScopeEnum::series ][ WCPropertyEnum::type ] = $container;
 358+ unset( $container );
 359+ default:
 360+ $type = WCSourceTypeEnum::$general;
 361+ }
 362+ $this->properties[ WCScopeEnum::work ][ WCPropertyEnum::type ] =
 363+ new WCTypeData( $type );
 364+ return;
 365+ }
 366+ }
 367+ }
 368+
 369+ /**
 370+ * Infer certain intended property values, if the user-set values do not
 371+ * make sense.
 372+ */
 373+ protected function setInferredProperties() {
 374+ # Unlike works, containers and series should not have "authors".
 375+ if ( isset( $this->names[ WCScopeEnum::container ][ WCNameTypeEnum::author ] ) ) {
 376+ # If there is a work author, then the user probably meant that.
 377+ if ( isset( $this->names[ WCScopeEnum::work ][ WCNameTypeEnum::author ] ) ) {
 378+ $this->names[ WCScopeEnum::work ][ WCNameTypeEnum::author ] = $this->names[ WCScopeEnum::series ][ WCNameTypeEnum::author ];
 379+ unset( $this->names[ WCScopeEnum::container ][ WCNameTypeEnum::author ] );
 380+ } else {
 381+ # If there is a work author also, the user probably meant editor.
 382+ if ( isset( $this->names[ WCScopeEnum::container ][ WCNameTypeEnum::editor ] ) ) {
 383+ $this->names[ WCScopeEnum::container ][ WCNameTypeEnum::editor ] = $this->names[ WCScopeEnum::series ][ WCNameTypeEnum::author ];
 384+ unset( $this->names[ WCScopeEnum::container ][ WCNameTypeEnum::author ] );
 385+ }
 386+ }
 387+ }
 388+ if ( isset( $this->names[ WCScopeEnum::series ][ WCNameTypeEnum::author ] ) ) {
 389+ # If there is on work author, then the user probably meant that.
 390+ if ( !isset( $this->names[ WCScopeEnum::work ][ WCNameTypeEnum::author ] ) ) {
 391+ $this->names[ WCScopeEnum::work ][ WCNameTypeEnum::author ] = $this->names[ WCScopeEnum::series ][ WCNameTypeEnum::author ];
 392+ unset( $this->names[ WCScopeEnum::series ][ WCNameTypeEnum::author ] );
 393+ } else {
 394+ # If there is a work author also, the user probably meant editor.
 395+ if ( !isset( $this->names[ WCScopeEnum::series ][ WCNameTypeEnum::editor ] ) ) {
 396+ $this->names[ WCScopeEnum::series ][ WCNameTypeEnum::editor ] = $this->names[ WCScopeEnum::series ][ WCNameTypeEnum::author ];
 397+ unset( $this->names[ WCScopeEnum::series ][ WCNameTypeEnum::author ] );
 398+ }
 399+ }
 400+ }
 401+ }
 402+
 403+
 404+}
\ No newline at end of file
Property changes on: trunk/extensions/WikiCitation/includes/WCReference.php
___________________________________________________________________
Added: svn:eol-style
1405 + native
Property changes on: trunk/extensions/WikiCitation/includes
___________________________________________________________________
Added: bugtraq:number
2406 + true

Status & tagging log