1<?php 2/** 3 * DokuWiki Plugin bible (Syntax Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author Allen Stetson <allen.stetson@gmail.com> 7 */ 8 9// must be run within Dokuwiki 10if (!defined('DOKU_INC')) die(); 11 12if (!defined('DOKU_LF')) define('DOKU_LF', "\n"); 13if (!defined('DOKU_TAB')) define('DOKU_TAB', "\t"); 14if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 15 16require_once DOKU_PLUGIN.'syntax.php'; 17 18class syntax_plugin_bible extends DokuWiki_Syntax_Plugin { 19 # Required. Define plugin type (see https://www.dokuwiki.org/devel:syntax_plugins) 20 public function getType() { 21 return 'substition'; 22 } 23 24 # Required. Define paragraph handling (see https://www.dokuwiki.org/devel:syntax_plugins) 25 public function getPType() { 26 return 'normal'; 27 } 28 29 # Required. Define sort order to determine which plugin trumps which. This value was somewhat arbitrary 30 ## And can be changed without really affecting the plugin. (see https://www.dokuwiki.org/devel:syntax_plugins) 31 public function getSort() { 32 return 275; 33 } 34 35 #Plugin Part 1 of 3. This is the actual plugin. This part defines how to invoke the plugin 36 public function connectTo($mode) { 37 # Define all 73 books of the Catholic Bible. 38 ## There are 66 books in the Protestant Bible, so this list will need altering if you plan to use that. 39 $validBibleBooksArr = array("Genesis", "Exodus", "Leviticus", "Numbers", "Deuteronomy", "Josue", "Judges", "Ruth", 40 "1 Kings", "2 Kings", "3 Kings", "4 Kings", "1 Paralipomenon", "2 Paralipomenon", "1 Esdras", "2 Esdras", "Tobias", 41 "Judith", "Esther", "Job", "Psalms", "Proverbs", "Ecclesiastes", "Canticles", "Wisdom", "Ecclesiasticus", 42 "Isaias", "Jeremias", "Lamentations", "Baruch", "Ezechiel", "Daniel", "Osee", "Joel", "Amos", "Abdias", "Jonas", 43 "Micheas", "Nahum", "Habacuc", "Sophonias", "Aggeus", "Zacharias", "Malachias", "1 Machabees", "2 Machabees", 44 "Matthew", "Mark", "Luke", "John", "Acts", "Romans", "1 Corinthians", "2 Corinthians", "Galatians", "Ephesians", 45 "Philippians", "Colossians", "1 Thessalonians", "2 Thessalonians", "1 Timothy", "2 Timothy", "Titus", 46 "Philemon", "Hebrews", "James", "1 Peter", "2 Peter", "1 John", "2 John", "3 John", "Jude", "Apocalypse"); 47 48 # Now, for each of those books, register two regular expressions: 49 ## One for "through verses" like chapter 2 verses 19 through 24 (Mark 2:19-24) 50 ## One for just a single verse (Mark 2:19) 51 ## The order of registry is important! Make sure the through-verse is first or else the single verse will gobble everything. 52 foreach ($validBibleBooksArr as $bibleBook){ 53 $this->Lexer->addSpecialPattern($bibleBook . ' \d+:\d+-\d+',$mode,'plugin_bible'); 54 $this->Lexer->addSpecialPattern($bibleBook . ' \d+:\d+',$mode,'plugin_bible'); 55 } 56 } 57 58 #Plugin Part 2 of 3. This is the handler - the workhorse - which takes the matched result from part 1 and modifies it. 59 public function handle($match, $state, $pos, &$handler){ 60 $data = array(); # Blank array 61 # Make sure that we're dealing with the match from our regexp in part 1, which is in the DOKU_LEXER_SPECIAL context. 62 switch ($state){ 63 case DOKU_LEXER_SPECIAL : 64 # Okay awesome, lets process that regexp match. Call my custom function called _fetchBibleVerse(). 65 $bibleLink = $this->_fetchBibleVerse($match); 66 # Modified match obtained! Now return that to Dokuwiki for collection in Part 3. 67 return array($bibleLink, $state, $pos); 68 } 69 return $data; # Upon failure, return that blank array 70 } 71 72 #Plugin part 3 of 3. This takes that result from part 2 and actually renders it to the page. 73 public function render($mode, &$renderer, $data) { 74 if($mode != 'xhtml') return false; # If mode is not html, like if it is metadata, just return. 75 $renderer->doc .= $data[0]; # Otherwise, fetch that $bibleLink (stored in $data[0]) and pass it to the dokuwiki renderer. 76 return true; 77 } 78 79 # This custom function takes a matched input value (like Mark 2:19-24 or Amos 1:1) and returns HTML code 80 ## which turns that input into an <acronym> with the bible verse as the hover-text. 81 function _fetchBibleVerse($inputVerse) { 82 # Set up variables for later 83 $thisChapterName = ""; 84 $thisChapterNum = ""; 85 $thisVerse = ""; 86 $throughVerse = ""; 87 $matchingVerses = array(); 88 $inputVerses = array(); 89 90 # Have a look at that input and try to determine chapter name, number, verse number, and through-verse if it exists. 91 ## Groups are defined by parenthesis. Group one is catching the Chapter Name, accounting for the fact that some chapters 92 ## begin with a number. 93 ## Group two is catching the chapter number 94 ## Group three is catching the verse number 95 ## Group 4 is required so that I can put a * after it, indicating that it may or may not be present 96 ## Group 5 catches the "through verse" if it should exist. 97 $result = preg_match("/^.*?(\d*?\s*?\w+) (\d+):(\d+)(-(\d+))*$/", $inputVerse, $matches); 98 if ($result){ 99 $chapterName = trim($matches[1]); 100 $thisChapterName = $chapterName; 101 $thisChapterNum = $matches[2]; 102 $thisVerseNum = $matches[3]; 103 $throughVerse = $matches[5]; 104 105 # Define which bible text file matches the result 106 ## Here is where you'll plug in a different version of the bible, should you desire. 107 ## Make sure that the syntax of the text files matches that of the Douay Rhiems bible 108 ## provided with this plugin. 109 ## PLEASE NOTE -- The bible cannot be all in one text file or the memory limit imposed upon 110 ## plugins by Dokuwiki will be reached, and the plugin will fail. You MUST separate by chapter. 111 $filename = DOKU_PLUGIN . "bible/bible_douayRheims/" . $thisChapterName . ".txt"; 112 $filename = str_replace(' ','_',$filename); # The user entered spaces, but filenames use underscores. 113 114 if(!file_exists($filename)){ 115 echo "ERROR, can't find matching bible file: " . $filename . "<br />\n"; 116 return; 117 } 118 119 # Check for a through verse (like, Mark 2:7-9), expand it if found 120 if ($throughVerse != ""){ 121 # Through Verse supplied 122 foreach (range($thisVerseNum, $throughVerse) as $verseNum){ 123 # Push each valid verse defined by the range provided onto the inputVerses array 124 array_push($inputVerses, $thisChapterName . " " . $thisChapterNum . ":" . $verseNum); 125 } 126 } else { 127 # No through verse, just take the input 128 array_push($inputVerses, $inputVerse); 129 } 130 131 # Now for each of the verses supplied (multiples are from through-verses), 132 ## look for a match in the bible file, collect it for return. 133 foreach ($inputVerses as $thisInputVerse){ 134 foreach (file($filename) as $linenum => $line){ 135 # Find matching verse 136 ## Here is where the syntax of the bible text files is important. Every line must be: 137 ## "CHAPTER:VERSE. CONTENT" 138 $result = preg_match("/^.*?(\d+:\d+)\.(.*?)$/", $line, $matches); 139 if ($result){ 140 # looks like a verse 141 $thisVerse = $matches[1]; 142 $content = $matches[2]; 143 $constructedVerse = $thisChapterName . " " . $thisVerse; # Form the verse into something similar to user input 144 $constructedVerse = strtolower($constructedVerse); # Force it to lower case for comparison 145 $lowInputVerse = strtolower($thisInputVerse); # Force user input to lower case for comparison 146 if($lowInputVerse == $constructedVerse){ # Do they match? 147 # This verse matches one of the verses that the user asked for! Push its contents into our matchingVerses array 148 array_push($matchingVerses, $content); 149 } 150 } 151 #Not a chapter or verse? Skip it. 152 } 153 } 154 $matchingVersesOutput = implode(" ", $matchingVerses); # Flatten our matching verses array into a string joined by spaces. 155 $matchingVersesOutput = trim($matchingVersesOutput); # Make it look pretty by trimming off any leading or trailing whitespace 156 157 # FINALLY, return all matching verses smooshed together as the "title" or hover-text to an <acronym>. 158 return "<acronym title=\"" . $matchingVersesOutput . "\">" . $inputVerse . "</acronym>"; 159 } else { 160 # Warn the user that some match is not a valid bible verse (Mark 445:9833) 161 echo "Input does not appear to be a valid bible verse: " . $inputVerse . "<br />\n"; 162 } 163 } 164} 165 166// vim:ts=4:sw=4:et: 167