Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/mod/wiki/parser/markups/wikimarkup.php
Go to the documentation of this file.
00001 <?php
00002 
00012 abstract class wiki_markup_parser extends generic_parser {
00013 
00014     protected $pretty_print = false;
00015     protected $printable = false;
00016 
00017     //page id
00018     protected $wiki_page_id;
00019 
00020     //sections
00021     protected $section_edit_text = "[edit]";
00022     protected $repeated_sections;
00023 
00024     protected $section_editing = true;
00025 
00026     //header & ToC
00027     protected $toc = array();
00028 
00034     private $linkgeneratorcallback = array('parser_utils', 'wiki_parser_link_callback');
00035     private $linkgeneratorcallbackargs = array();
00036 
00041     private $tablegeneratorcallback = array('parser_utils', 'wiki_parser_table_callback');
00042 
00046     private $realpathcallback = array('parser_utils', 'wiki_parser_real_path');
00047     private $realpathcallbackargs = array();
00048 
00053     protected function before_parsing() {
00054         $this->toc = array();
00055 
00056         $this->string = preg_replace('/\r\n/', "\n", $this->string);
00057         $this->string = preg_replace('/\r/', "\n", $this->string);
00058 
00059         $this->string .= "\n\n";
00060 
00061         if (!$this->printable && $this->section_editing) {
00062             $this->returnvalues['unparsed_text'] = $this->string;
00063             $this->string = $this->get_repeated_sections($this->string);
00064         }
00065     }
00066 
00067     protected function after_parsing() {
00068         if (!$this->printable) {
00069             $this->returnvalues['repeated_sections'] = array_unique($this->returnvalues['repeated_sections']);
00070         }
00071 
00072         $this->process_toc();
00073 
00074         $this->string = preg_replace("/\n\s/", "\n", $this->string);
00075         $this->string = preg_replace("/\n{2,}/", "\n", $this->string);
00076         $this->string = trim($this->string);
00077         $this->string .= "\n";
00078     }
00079 
00084     protected function set_options($options) {
00085         parent::set_options($options);
00086 
00087         $this->returnvalues['link_count'] = array();
00088         $this->returnvalues['repeated_sections'] = array();
00089         $this->returnvalues['toc'] = "";
00090 
00091         foreach ($options as $name => $o) {
00092             switch ($name) {
00093             case 'link_callback':
00094                 $callback = explode(':', $o);
00095 
00096                 global $CFG;
00097                 require_once($CFG->dirroot . $callback[0]);
00098 
00099                 if (function_exists($callback[1])) {
00100                     $this->linkgeneratorcallback = $callback[1];
00101                 }
00102                 break;
00103             case 'link_callback_args':
00104                 if (is_array($o)) {
00105                     $this->linkgeneratorcallbackargs = $o;
00106                 }
00107                 break;
00108             case 'real_path_callback':
00109                 $callback = explode(':', $o);
00110 
00111                 global $CFG;
00112                 require_once($CFG->dirroot . $callback[0]);
00113 
00114                 if (function_exists($callback[1])) {
00115                     $this->realpathcallback = $callback[1];
00116                 }
00117                 break;
00118             case 'real_path_callback_args':
00119                 if (is_array($o)) {
00120                     $this->realpathcallbackargs = $o;
00121                 }
00122                 break;
00123             case 'table_callback':
00124                 $callback = explode(':', $o);
00125 
00126                 global $CFG;
00127                 require_once($CFG->dirroot . $callback[0]);
00128 
00129                 if (function_exists($callback[1])) {
00130                     $this->tablegeneratorcallback = $callback[1];
00131                 }
00132                 break;
00133             case 'pretty_print':
00134                 if ($o) {
00135                     $this->pretty_print = true;
00136                 }
00137                 break;
00138             case 'pageid':
00139                 $this->wiki_page_id = $o;
00140                 break;
00141             case 'printable':
00142                 if ($o) {
00143                     $this->printable = true;
00144                 }
00145                 break;
00146             }
00147         }
00148     }
00149 
00154     protected function line_break_block_rule($match) {
00155         return '<hr />';
00156     }
00157 
00158     protected function list_block_rule($match) {
00159         preg_match_all("/^\ *([\*\#]{1,5})\ *((?:[^\n]|\n(?!(?:\ *[\*\#])|\n))+)/im", $match[1], $listitems, PREG_SET_ORDER);
00160 
00161         return $this->process_block_list($listitems) . $match[2];
00162     }
00163 
00164     protected function nowiki_block_rule($match) {
00165         return parser_utils::h('pre', $this->protect($match[1]));
00166     }
00167 
00172     protected function nowiki_tag_rule($match) {
00173         return parser_utils::h('tt', $this->protect($match[1]));
00174     }
00175 
00180     protected function generate_header($text, $level) {
00181         $text = trim($text);
00182 
00183         if (!$this->pretty_print && $level == 1) {
00184             $text .= parser_utils::h('a', $this->section_edit_text, array('href' => "edit.php?pageid={$this->wiki_page_id}&section=" . urlencode($text), 'class' => 'wiki_edit_section'));
00185         }
00186 
00187         if ($level < 4) {
00188             $this->toc[] = array($level, $text);
00189             $num = count($this->toc);
00190             $text = parser_utils::h('a', "", array('name' => "toc-$num")) . $text;
00191         }
00192 
00193         return parser_utils::h('h' . $level, $text) . "\n\n";
00194     }
00195 
00199     protected function process_toc() {
00200         if (empty($this->toc)) {
00201             return;
00202         }
00203 
00204         $toc = "";
00205         $currentsection = array(0, 0, 0);
00206         $i = 1;
00207         foreach ($this->toc as & $header) {
00208             switch ($header[0]) {
00209             case 1:
00210                 $currentsection = array($currentsection[0] + 1, 0, 0);
00211                 break;
00212             case 2:
00213                 $currentsection[1]++;
00214                 $currentsection[2] = 0;
00215                 if ($currentsection[0] == 0) {
00216                     $currentsection[0]++;
00217                 }
00218                 break;
00219             case 3:
00220                 $currentsection[2]++;
00221                 if ($currentsection[1] == 0) {
00222                     $currentsection[1]++;
00223                 }
00224                 if ($currentsection[0] == 0) {
00225                     $currentsection[0]++;
00226                 }
00227                 break;
00228             default:
00229                 continue;
00230             }
00231             $number = "$currentsection[0]";
00232             if (!empty($currentsection[1])) {
00233                 $number .= ".$currentsection[1]";
00234                 if (!empty($currentsection[2])) {
00235                     $number .= ".$currentsection[2]";
00236                 }
00237             }
00238             $toc .= parser_utils::h('p', $number . ". " . parser_utils::h('a', $header[1], array('href' => "#toc-$i")), array('class' => 'wiki-toc-section-' . $header[0] . " wiki-toc-section"));
00239             $i++;
00240         }
00241 
00242         $this->returnvalues['toc'] = "<div class=\"wiki-toc\"><p class=\"wiki-toc-title\">Table of contents</p>$toc</div>";
00243     }
00244 
00249     private function process_block_list($listitems) {
00250         $list = array();
00251         foreach ($listitems as $li) {
00252             $text = str_replace("\n", "", $li[2]);
00253             $this->rules($text);
00254 
00255             if ($li[1][0] == '*') {
00256                 $type = 'ul';
00257             } else {
00258                 $type = 'ol';
00259             }
00260 
00261             $list[] = array(strlen($li[1]), $text, $type);
00262         }
00263         $type = $list[0][2];
00264         return "<$type>" . "\n" . $this->generate_list($list) . "\n" . "</$type>" . "\n";
00265     }
00266 
00271     protected function generate_list($listitems) {
00272         $list = "";
00273         $current_depth = 1;
00274         $next_depth = 1;
00275         $liststack = array();
00276         for ($lc = 0; $lc < count($listitems) && $next_depth; $lc++) {
00277             $cli = $listitems[$lc];
00278             $nli = isset($listitems[$lc + 1]) ? $listitems[$lc + 1] : null;
00279 
00280             $text = $cli[1];
00281 
00282             $current_depth = $next_depth;
00283             $next_depth = $nli ? $nli[0] : null;
00284 
00285             if ($next_depth == $current_depth || $next_depth == null) {
00286                 $list .= parser_utils::h('li', $text) . "\n";
00287             } else if ($next_depth > $current_depth) {
00288                 $next_depth = $current_depth + 1;
00289 
00290                 $list .= "<li>" . $text . "\n";
00291                 $list .= "<" . $nli[2] . ">" . "\n";
00292                 $liststack[] = $nli[2];
00293             } else {
00294                 $list .= parser_utils::h('li', $text) . "\n";
00295 
00296                 for ($lv = $next_depth; $lv < $current_depth; $lv++) {
00297                     $type = array_pop($liststack);
00298                     $list .= "</$type>" . "\n" . "</li>" . "\n";
00299                 }
00300             }
00301         }
00302 
00303         for ($lv = 1; $lv < $current_depth; $lv++) {
00304             $type = array_pop($liststack);
00305             $list .= "</$type>" . "\n" . "</li>" . "\n";
00306         }
00307 
00308         return $list;
00309     }
00310 
00315     protected function generate_table($table) {
00316         $table_html = call_user_func_array($this->tablegeneratorcallback, array($table));
00317 
00318         return $table_html;
00319     }
00320 
00321     protected function format_image($src, $alt, $caption = "", $align = 'left') {
00322         $src = $this->real_path($src);
00323         return parser_utils::h('div', parser_utils::h('p', $caption) . '<img src="' . $src . '" alt="' . $alt . '" />', array('class' => 'wiki_image_' . $align));
00324     }
00325 
00326     protected function real_path($url) {
00327         $callbackargs = array_merge(array($url), $this->realpathcallbackargs);
00328         return call_user_func_array($this->realpathcallback, $callbackargs);
00329     }
00330 
00335     protected function link($link, $anchor = "") {
00336         $link = trim($link);
00337         if (preg_match("/^(https?|s?ftp):\/\/.+$/i", $link)) {
00338             $link = trim($link, ",.?!");
00339             return array('content' => $link, 'url' => $link);
00340         } else {
00341             $callbackargs = $this->linkgeneratorcallbackargs;
00342             $callbackargs['anchor'] = $anchor;
00343             $link = call_user_func_array($this->linkgeneratorcallback, array($link, $callbackargs));
00344 
00345             if (isset($link['link_info'])) {
00346                 $l = $link['link_info']['link'];
00347                 unset($link['link_info']['link']);
00348                 $this->returnvalues['link_count'][$l] = $link['link_info'];
00349             }
00350             return $link;
00351         }
00352     }
00353 
00358     protected function format_link($text) {
00359         $matches = array();
00360         if (preg_match("/^([^\|]+)\|(.+)$/i", $text, $matches)) {
00361             $link = $matches[1];
00362             $content = trim($matches[2]);
00363             if (preg_match("/(.+)#(.*)/is", $link, $matches)) {
00364                 $link = $this->link($matches[1], $matches[2]);
00365             } else if ($link[0] == '#') {
00366                 $link = array('url' => "#" . urlencode(substr($link, 1)));
00367             } else {
00368                 $link = $this->link($link);
00369             }
00370 
00371             $link['content'] = $content;
00372         } else {
00373             $link = $this->link($text);
00374         }
00375 
00376         if (isset($link['new']) && $link['new']) {
00377             $options = array('class' => 'wiki_newentry');
00378         } else {
00379             $options = array();
00380         }
00381 
00382         $link['content'] = $this->protect($link['content']);
00383         $link['url'] = $this->protect($link['url']);
00384 
00385         $options['href'] = $link['url'];
00386 
00387         if ($this->printable) {
00388             $options['href'] = '#'; //no target for the link
00389             }
00390         return array($link['content'], $options);
00391     }
00392 
00397     public function get_section($header, $text, $clean = false) {
00398         if ($clean) {
00399             $text = preg_replace('/\r\n/', "\n", $text);
00400             $text = preg_replace('/\r/', "\n", $text);
00401             $text .= "\n\n";
00402         }
00403 
00404         preg_match("/(.*?)(=\ *\Q$header\E\ *=*\n.*?)((?:\n=[^=]+.*)|$)/is", $text, $match);
00405 
00406         if (!empty($match)) {
00407             return array($match[1], $match[2], $match[3]);
00408         } else {
00409             return false;
00410         }
00411     }
00412 
00413     protected function get_repeated_sections(&$text, $repeated = array()) {
00414         $this->repeated_sections = $repeated;
00415         return preg_replace_callback($this->blockrules['header']['expression'], array($this, 'get_repeated_sections_callback'), $text);
00416     }
00417 
00418     protected function get_repeated_sections_callback($match) {
00419         $num = strlen($match[1]);
00420         $text = trim($match[2]);
00421         if ($num == 1) {
00422             if (in_array($text, $this->repeated_sections)) {
00423                 $this->returnvalues['repeated_sections'][] = $text;
00424                 return $text . "\n";
00425             } else {
00426                 $this->repeated_sections[] = $text;
00427             }
00428         }
00429 
00430         return $match[0];
00431     }
00432 
00433 }
 All Data Structures Namespaces Files Functions Variables Enumerations