Autodoc
  • Namespace
  • Class
  • Tree

Namespaces

  • BlueTihi
    • Context
  • Brickrouge
    • Element
      • Nodes
    • Renderer
    • Widget
  • ICanBoogie
    • ActiveRecord
    • AutoConfig
    • CLDR
    • Composer
    • Core
    • Event
    • Exception
    • HTTP
      • Dispatcher
      • Request
    • I18n
      • Translator
    • Mailer
    • Modules
      • Taxonomy
        • Support
      • Thumbnailer
        • Versions
    • Object
    • Operation
      • Dispatcher
    • Prototype
    • Routes
    • Routing
      • Dispatcher
    • Session
  • Icybee
    • ActiveRecord
      • Model
    • ConfigOperation
    • Document
    • EditBlock
    • Element
      • ActionbarContextual
      • ActionbarSearch
      • ActionbarToolbar
    • FormBlock
    • Installer
    • ManageBlock
    • Modules
      • Articles
      • Cache
        • Collection
        • ManageBlock
      • Comments
        • ManageBlock
      • Contents
        • ManageBlock
      • Dashboard
      • Editor
        • Collection
      • Files
        • File
        • ManageBlock
      • Forms
        • Form
        • ManageBlock
      • I18n
      • Images
        • ManageBlock
      • Members
      • Modules
        • ManageBlock
      • Nodes
        • ManageBlock
        • Module
      • Pages
        • BreadcrumbElement
        • LanguagesElement
        • ManageBlock
        • NavigationBranchElement
        • NavigationElement
        • Page
        • PageController
      • Registry
      • Search
      • Seo
      • Sites
        • ManageBlock
      • Taxonomy
        • Terms
          • ManageBlock
        • Vocabulary
          • ManageBlock
      • Users
        • ManageBlock
        • NonceLogin
        • Roles
      • Views
        • ActiveRecordProvider
        • Collection
        • View
    • Operation
      • ActiveRecord
      • Constructor
      • Module
      • Widget
    • Rendering
  • None
  • Patron
  • PHP

Classes

  • Markdown_Parser
  • MarkdownExtra_Parser
  • PasswordGetInfoTest
  • PasswordHashTest
  • PasswordNeedsRehashTest
  • PasswordVerifyTest
  • taxonomy_support_WdMarkups
  • Textile
  • Textmark_Parser
  • WdEMailNotifyElement

Functions

  • identify_modifier_markdown
  • Markdown
  • mdwp_add_p
  • mdwp_hide_tags
  • mdwp_MarkdownPost
  • mdwp_show_tags
  • mdwp_strip_p
  • password_get_info
  • password_hash
  • password_needs_rehash
  • password_verify
  • smarty_modifier_markdown
  • strip_comments
  • wd_spamScore
   1 <?php
   2 
   3 /*
   4  * This file is part of the Patron package.
   5  *
   6  * (c) Olivier Laviale <olivier.laviale@gmail.com>
   7  *
   8  * For the full copyright and license information, please view the LICENSE
   9  * file that was distributed with this source code.
  10  */
  11 
  12 use Patron\Hook;
  13 
  14 @define('MARKDOWN_PARSER_CLASS', 'Textmark_Parser');
  15 
  16 /*
  17  @define('txt_apostrophe',        '&rsquo;');
  18  //@define('txt_quote_single_open',  '&#8216;');
  19  //@define('txt_quote_single_close', '&#8217;');
  20  @define('txt_quote_double_open',  '&laquo;&nbsp;');
  21  @define('txt_quote_double_close', '&nbsp;&raquo;');
  22  @define('txt_prime',             '&prime;');
  23  @define('txt_prime_double',      '&Prime;');
  24  @define('txt_ellipsis',          '&hellip;');
  25  @define('txt_emdash',            '&mdash;');
  26  @define('txt_endash',            '&ndash;');
  27  @define('txt_dimension',         '&times;');
  28  @define('txt_trademark',         '&trade;');
  29  @define('txt_registered',        '&reg;');
  30  @define('txt_copyright',         '&copy;');
  31  */
  32 @define('txt_apostrophe',         '\'');
  33 @define('txt_quote_double_open',  '« ');
  34 @define('txt_quote_double_close', ' »');
  35 @define('txt_prime',              'ʹ');
  36 @define('txt_prime_double',       'ʺ');
  37 @define('txt_ellipsis',           '…');
  38 @define('txt_emdash',             '—');
  39 @define('txt_endash',             '–');
  40 @define('txt_dimension',          '×');
  41 @define('txt_trademark',          '™');
  42 @define('txt_registered',         '®');
  43 @define('txt_copyright',          '©');
  44 
  45 require_once 'markdown/markdown.php';
  46 require_once 'markdown/markdown_extras.php';
  47 
  48 class Textmark_Parser extends MarkdownExtra_Parser
  49 {
  50     const NBSP = "\xC2\xA0";
  51     const NBSP_TAB = "\xC2\xA0\xC2\xA0\xC2\xA0\xC2\xA0";
  52 
  53     static public function parse($str)
  54     {
  55         return Markdown((string) $str);
  56     }
  57 
  58     function Textmark_Parser()
  59     {
  60         $this->early_gamut += array
  61         (
  62             'doShell' => 5
  63         );
  64 
  65         $this->span_gamut += array
  66         (
  67             'doFlash' => 9, // just before doImages
  68             'doGlyphs' => 70,
  69             'doSpan' => 71
  70         );
  71 
  72         parent::MarkdownExtra_Parser();
  73     }
  74 
  75     public function doShell($text)
  76     {
  77         return preg_replace_callback
  78         (
  79             '{^\$\s+([^\n]+)\n}xm', array($this, 'doShell_callback'), $text
  80         );
  81 
  82         return $text;
  83     }
  84 
  85     protected function doShell_callback($matches)
  86     {
  87         $text = '<pre class="markdown shell">$ ' . $matches[1] . '</pre>' . PHP_EOL;
  88 
  89         return $this->hashBlock($text);
  90     }
  91 
  92     /*
  93      **
  94 
  95      SYSTEM
  96 
  97      **
  98      */
  99 
 100     function hashHTMLBlocks($text)
 101     {
 102         /*
 103         $text = preg_replace_callback
 104         (
 105             '#^\@([a-z]+)(.*?)\1\@$#sm', array(&$this, '_doSourceCode'), $text
 106         );
 107         */
 108 
 109         return parent::hashHTMLBlocks($text);
 110     }
 111 
 112     function _doSourceCode($matches)
 113     {
 114         //      \ICanBoogie\log('\1 :: matches: \2', __FUNCTION__, $matches);
 115 
 116         return $this->hashBlock($this->doSourceCode($matches[1], $matches[2]));
 117     }
 118 
 119     function doSourceCode($type, $text)
 120     {
 121         $text = trim($text);
 122 
 123         switch ($type)
 124         {
 125             case 'php': return '<pre class="php"><code>' . $this->doSourcePHP($text) . '</code></pre>';
 126             case 'html': return '<pre class="html"><code>' . $this->doSourceHTML($text) . '</code></pre>';
 127             case 'raw': return '<pre><code>' . $this->doSourceRaw($text) . '</code></pre>';
 128             case 'publish': return $this->doSourcePublish($text);
 129         }
 130 
 131         \ICanBoogie\log_error('\1: unknown source type "\1"', __FUNCTION__, $type);
 132 
 133         return $text;
 134     }
 135 
 136     private function doSourcePublish($text)
 137     {
 138         return Patron($text);
 139     }
 140 
 141     /*
 142      **
 143 
 144      HEADERS
 145 
 146      **
 147      */
 148 
 149     function doHeaders($text)
 150     {
 151         /*
 152 
 153         Setext-style headers:
 154 
 155         Header 1
 156         ########
 157 
 158         Header 2
 159         ========
 160 
 161         Header 3
 162         --------
 163 
 164         $text = preg_replace_callback
 165         (
 166         '{ ^(.+?)[ ]*\n(\#+|=+|-+)[ ]*\n+ }mx',
 167 
 168         array(&$this, '_doHeaders_callback_setext'), $text
 169         );
 170 
 171         */
 172 
 173         $text = parent::doHeaders($text);
 174 
 175         /*
 176 
 177         atx-style headers:
 178 
 179         h1. Header 1
 180         h2. Header 2
 181         ...
 182         h6. Header 6
 183 
 184         */
 185 
 186         $text = preg_replace_callback
 187         (
 188             '{
 189                 ^h([1-6])\. # $1 = string of h?
 190                 [ ]*
 191                 (.+?)       # $2 = Header text
 192                 [ ]*
 193                 \n+
 194             }xm',
 195 
 196         array(&$this, '_doHeaders_callback_tp'), $text
 197         );
 198 
 199         return $text;
 200     }
 201 
 202     function _doHeaders_callback_setext($matches)
 203     {
 204         switch ($matches[3]{0})
 205         {
 206             case '#': $level = 1; break;
 207             case '=': $level = 2; break;
 208             case '-': $level = 3; break;
 209         }
 210 
 211         $block = "<h$level>" . $this->runSpanGamut($matches[1]) . "</h$level>";
 212 
 213         return "\n" . $this->hashBlock($block) . "\n\n";
 214     }
 215 
 216     function _doHeaders_callback_tp($matches)
 217     {
 218         //      \ICanBoogie\log('<pre>doHeaders[atx]: \1</pre>', print_r($matches, true));
 219 
 220         $level = $matches[1];
 221         $block = "<h$level>" . $this->runSpanGamut($matches[2]) . "</h$level>";
 222         return "\n" . $this->hashBlock($block) . "\n\n";
 223     }
 224 
 225     /*
 226      **
 227 
 228      SPAN
 229 
 230      **
 231      */
 232 
 233     function doSpan($text)
 234     {
 235         $clas = "(?:\([^)]+\))";
 236         $styl = "(?:\{[^}]+\})";
 237         $lnge = "(?:\[[^]]+\])";
 238         $hlgn = "(?:\<(?!>)|(?<!<)\>|\<\>|\=|[()]+(?! ))";
 239 
 240         $c = "(?:{$clas}|{$styl}|{$lnge}|{$hlgn})*";
 241 
 242         $qtags = array('\*\*','\*','\?\?','-','__','_','%','\+','~','\^');
 243         $pnct = ".,\"'?!;:";
 244 
 245         foreach($qtags as $f) {
 246             $text = preg_replace_callback("/
 247                 (^|(?<=[\s>$pnct\(])|[{[])
 248                 ($f)(?!$f)
 249                 (" . $c . ")
 250                 (?::(\S+))?
 251                 ([^\s$f]+|\S.*?[^\s$f\n])
 252                 ([$pnct]*)
 253                 $f
 254                 ($|[\]}]|(?=[[:punct:]]{1,2}|\s|\)))
 255             /x", array(&$this, "fSpan"), $text);
 256         }
 257         return $text;
 258     }
 259 
 260     function fSpan($m)
 261     {
 262         $qtags = array(
 263             '*'  => 'strong',
 264             '**' => 'b',
 265             '??' => 'cite',
 266             '_'  => 'em',
 267             '__' => 'i',
 268             '-'  => 'del',
 269             '%'  => 'span',
 270             '+'  => 'ins',
 271             '~'  => 'sub',
 272             '^'  => 'sup'
 273             );
 274 
 275             list(, $pre, $tag, $atts, $cite, $content, $end, $tail) = $m;
 276             $tag = $qtags[$tag];
 277             //      $atts = $this->pba($atts);
 278             //      $atts .= ($cite != '') ? 'cite="' . $cite . '"' : '';
 279 
 280             $out = "<$tag$atts>$content$end</$tag>";
 281 
 282             if (($pre and !$tail) or ($tail and !$pre))
 283             {
 284                 $out = $pre.$out.$tail;
 285             }
 286 
 287             //      $this->dump($out);
 288 
 289             return $out;
 290 
 291     }
 292 
 293     function doGlyphs($text)
 294     {
 295         //      echo l('doGlyphs: "\1"<br />', \ICanBoogie\escape($text));
 296 
 297         $glyph_search = array
 298         (
 299         //      '/(\w)\'(\w)/',                                      // apostrophe's
 300             '/(\s)\'(\d+\w?)\b(?!\')/u',                         // back in '88
 301         //      '/(\S)\'(?=\s|[[:punct:]]|<|$)/',                        //  single closing
 302         //      '/\'/',                                              //  single opening
 303             '/(\S)\"(?=\s|[[:punct:]]|<|$)/u',                       //  double closing
 304             '/"/',                                               //  double opening
 305             '/\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/u',       //  3+ uppercase acronym
 306             '/(?<=\s|^|[>(;-])([A-Z]{3,})([a-z]*)(?=\s|[[:punct:]]|<|$)/u',  //  3+ uppercase
 307             '/([^.]?)\.{3}/u',                                   //  ellipsis
 308             '/(\s?)--(\s?)/u',                                   //  em dash
 309             '/\s-(?:\s|$)/u',                                    //  en dash
 310             '/(\d+)( ?)x( ?)(?=\d+)/u',                          //  dimension sign
 311             '/(\b ?|\s|^)[([]TM[])]/iu',                         //  trademark
 312             '/(\b ?|\s|^)[([]R[])]/iu',                          //  registered
 313             '/(\b ?|\s|^)[([]C[])]/iu',                          //  copyright
 314 
 315         #
 316         # the following is for french language
 317         #
 318 
 319             '#\s(\!|\?|\:|\;|\-)#u',
 320         );
 321 
 322         $glyph_replace = array
 323         (
 324         //      '$1'.$txt_apostrophe.'$2',           // apostrophe's
 325             '$1'.txt_apostrophe.'$2',            // back in '88
 326         //      '$1'.$txt_quote_single_close,        //  single closing
 327         //      $txt_quote_single_open,              //  single opening
 328             '$1'.txt_quote_double_close,         //  double closing
 329         txt_quote_double_open,           //  double opening
 330             '<acronym title="$2">$1</acronym>',  //  3+ uppercase acronym
 331             '<span class="caps">$1</span>$2',    //  3+ uppercase
 332             '$1'.txt_ellipsis,               //  ellipsis
 333             '$1'.txt_emdash.'$2',                //  em dash
 334             ' '.txt_endash.' ',              //  en dash
 335             '$1$2'.txt_dimension.'$3',       //  dimension sign
 336             '$1'.txt_trademark,              //  trademark
 337             '$1'.txt_registered,                 //  registered
 338             '$1'.txt_copyright,              //  copyright
 339 
 340         #
 341         # the following is for french language
 342         #
 343 
 344         self::NBSP . '$1',
 345         );
 346 
 347         return preg_replace($glyph_search, $glyph_replace, $text);
 348     }
 349 
 350     /*
 351      **
 352 
 353      BLOCS
 354 
 355      **
 356      */
 357 
 358     function formParagraphs($text)
 359     {
 360         #
 361         #   Params:
 362         #       $text - string to process with html <p> tags
 363         #
 364         # Strip leading and trailing lines:
 365 
 366         $text = preg_replace('/\A\n+|\n+\z/', '', $text);
 367         $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
 368 
 369         #
 370         # Wrap <p> tags and unhashify HTML blocks
 371         #
 372         foreach ($grafs as $key => $value)
 373         {
 374             //          \ICanBoogie\log('in \1, graf: [<tt>\2</tt>]', __FUNCTION__, $value);
 375 
 376             #
 377             # styles
 378             #
 379 
 380             $style = NULL;
 381 
 382             if (preg_match
 383             (
 384                 '{
 385                     (                       # the whole thing is saved in $1
 386                     ^p                      # start
 387                     (\<|\||\>|\=)?          # alignement $2
 388                     \.                      # separator
 389                     [ ]+                    # white space, at least one is mandatory
 390                     )
 391                 }sx', $value, $matches
 392             ))
 393             {
 394                 $value = substr($value, strlen($matches[1]));
 395                 $align = $matches[2];
 396 
 397                 if ($align)
 398                 {
 399                     switch ($align)
 400                     {
 401                         case '<': $align = 'left'; break;
 402                         case '|': $align = 'center'; break;
 403                         case '>': $align = 'right'; break;
 404                         case '=': $align = 'justify'; break;
 405                     }
 406 
 407                     $style .= "text-align: $align;";
 408                 }
 409             }
 410 
 411             //          \ICanBoogie\log('in \1, graf: <tt>\2</tt>, match: <pre>\3</pre>', __FUNCTION__, $value, $matches);
 412 
 413 
 414             #
 415             #
 416             #
 417 
 418             $value = trim($this->runSpanGamut($value));
 419 
 420             # Check if this should be enclosed in a paragraph.
 421             # Clean tag hashes & block tag hashes are left alone.
 422 
 423             $is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
 424 
 425             if ($is_p)
 426             {
 427                 if ($style)
 428                 {
 429                     $value = '<p style="' . $style . '">' . $value . '</p>';
 430                 }
 431                 else
 432                 {
 433                     $value = "<p>$value</p>";
 434                 }
 435             }
 436 
 437             $grafs[$key] = $value;
 438         }
 439 
 440         # Join grafs in one text, then unhash HTML tags.
 441         $text = implode("\n\n", $grafs);
 442 
 443         # Finish by removing any tag hashes still present in $text.
 444         $text = $this->unhash($text);
 445 
 446         return $text;
 447     }
 448 
 449     /*
 450      **
 451 
 452      STYLES
 453 
 454      **
 455      */
 456 
 457     function _doItalicAndBold_em_callback($matches)
 458     {
 459         $text = $matches[2];
 460         $text = $this->runSpanGamut($text);
 461 
 462         $tag = ($matches[1] == '*') ? 'strong' : 'em';
 463 
 464         return $this->hashPart("<$tag>$text</$tag>");
 465     }
 466 
 467     function _doItalicAndBold_strong_callback($matches)
 468     {
 469         $text = $matches[2];
 470         $text = $this->runSpanGamut($text);
 471 
 472         $tag = ($matches[1] == '**') ? 'b' : 'i';
 473 
 474         return $this->hashPart("<$tag>$text</$tag>");
 475     }
 476 
 477     /*
 478      **
 479 
 480      FLASH
 481 
 482      **
 483      */
 484 
 485     function doFlash($text)
 486     {
 487         #
 488         # Turn Textmark flash shortcuts into <object> tags.
 489         #
 490 
 491         #
 492         # Next, handle inline images:  ![alt text](url "optional title")
 493         # Don't forget: encode * and _
 494         #
 495 
 496         $text = preg_replace_callback('{
 497             (               # wrap whole match in $1
 498               @
 499                 (\<|\||\>|\=)?                          # alignment = $2
 500               \[
 501                 ('.$this->nested_brackets_re.')         # title = $3
 502               \]
 503               \s?           # One optional whitespace character
 504               \(            # literal paren
 505                 [ ]*
 506                 (?:
 507                     <(\S*)>                             # src url = $4
 508                 |
 509                     ('.$this->nested_url_parenthesis_re.')  # src url = $5
 510                 )
 511                 [ ]*
 512                 (           # $6
 513                   ([\'"])   # quote char = $7
 514                   (.*?)     # title = $8
 515                   \6        # matching quote
 516                   [ ]*
 517                 )?          # title is optional
 518               \)
 519             )
 520             }xs',
 521         array(&$this, '_doFlash_inline_callback'), $text);
 522 
 523         return $text;
 524     }
 525 
 526     function _doFlash_inline_callback($matches)
 527     {
 528         //      echo l('matches: \1', $matches);
 529 
 530         $whole_match = $matches[1];
 531         $align = $matches[2];
 532         $alt_text = $matches[3];
 533         $url = empty($matches[4]) ? $matches[5] : $matches[4];
 534         $title =& $matches[8];
 535 
 536         $parts = parse_url($url);
 537 
 538         //      echo l('parsed url: \1', $parts);
 539 
 540         $data = NULL;
 541         $width = 0;
 542         $height = 0;
 543 
 544         preg_match('#www\.([^\.]+)#', $parts['host'], $matches);
 545 
 546         //      echo l('host: \1', $matches);
 547 
 548         switch ($matches['1'])
 549         {
 550             case 'youtube':
 551                 preg_match('#v=([^\&]+)#', $parts['query'], $matches);
 552 
 553                 $data = 'http://www.youtube.com/v/' . $matches[1] . '&amp;fs=1&amp;rel=1&amp;border=0';
 554                 $width = 420;
 555                 $height = 360;
 556 
 557                 break;
 558 
 559             case 'dailymotion':
 560                 preg_match('#video\/([^_]+)#', $parts['path'], $matches);
 561 
 562                 //              echo l('query: \1', $matches);
 563 
 564                 $data = 'http://www.dailymotion.com/swf/' . $matches[1];
 565                 $width = 420;
 566                 $height = 360;
 567 
 568                 break;
 569         }
 570 
 571         $rc  = '<object width="' . $width . '" height="' . $height . '"';
 572         $rc .= ' type="application/x-shockwave-flash"';
 573 
 574         if ($align)
 575         {
 576             switch ($align)
 577             {
 578                 case '<': $align = 'left'; break;
 579                 case '=':
 580                 case '|': $align = 'middle'; break;
 581                 case '>': $align = 'right'; break;
 582             }
 583 
 584             $rc .= ' align="' . $align . '"';
 585         }
 586 
 587         $rc .= ' data="' . $data . '">';
 588         $rc .= '<param name="wmode" value="transparent" />';
 589         $rc .= '<param name="movie" value="' . $data . '" />';
 590         $rc .= '<param name="allowfullscreen" value="true" />';
 591         $rc .= '<param name="allowscriptaccess" value="always" />';
 592         $rc .= '</object>';
 593 
 594         if ($alt_text)
 595         {
 596             $rc .= '<br />';
 597             $rc .= '<a href="' . $url . '">' . \ICanBoogie\escape($alt_text) . '</a>';
 598         }
 599 
 600         return $this->hashPart($rc);
 601     }
 602 
 603     /*
 604      **
 605 
 606      IMAGES
 607 
 608      **
 609      */
 610     function doImages($text)
 611     {
 612         #
 613         # Turn Markdown image shortcuts into <img> tags.
 614         #
 615 
 616         #
 617         # gofromiel: added align options
 618         #
 619 
 620         #
 621         # First, handle reference-style labeled images: ![alt text][id]
 622         #
 623 
 624         $text = preg_replace_callback
 625         (
 626             '{
 627             (                                       # wrap whole match in $1
 628               !                                     # start
 629               (\<|\||\>|\=)?                            # alignment = $2
 630               \[
 631                 ('.$this->nested_brackets_re.')     # alt text = $3
 632               \]
 633 
 634               [ ]?              # one optional space
 635               (?:\n[ ]*)?       # one optional newline followed by spaces
 636 
 637               \[
 638                 (.*?)                               # id = $4
 639               \]
 640 
 641             )
 642             }xs', array(&$this, '_doImages_reference_callback'), $text
 643         );
 644 
 645         #
 646         # Next, handle inline images:  ![alt text](url "optional title")
 647         # Don't forget: encode * and _
 648         #
 649         $text = preg_replace_callback('{
 650             (               # wrap whole match in $1
 651               !
 652                 (\<|\||\>|\=)?                          # alignment = $2
 653               \[
 654                 ('.$this->nested_brackets_re.')     # alt text = $3
 655               \]
 656               \s?           # One optional whitespace character
 657               \(            # literal paren
 658                 [ ]*
 659                 (?:
 660                     <(\S*)> # src url = $4
 661                 |
 662                     ('.$this->nested_url_parenthesis_re.')  # src url = $5
 663                 )
 664                 [ ]*
 665                 (           # $6
 666                   ([\'"])   # quote char = $7
 667                   (.*?)     # title = $8
 668                   \6        # matching quote
 669                   [ ]*
 670                 )?          # title is optional
 671               \)
 672             )
 673             }xs',
 674         array(&$this, '_doImages_inline_callback'), $text);
 675 
 676         return $text;
 677     }
 678 
 679     static protected $images_reference_callback;
 680 
 681     function _doImages_reference_callback($matches)
 682     {
 683         if (self::$images_reference_callback === null)
 684         {
 685             $hook = false;
 686 
 687             try
 688             {
 689                 $hook = Hook::find('textmark', 'images.reference');
 690 
 691                 if (!$hook)
 692                 {
 693                     $hook = false;
 694                 }
 695             }
 696             catch (Exception $e) {}
 697 
 698             self::$images_reference_callback = $hook;
 699         }
 700 
 701         if (self::$images_reference_callback !== false)
 702         {
 703             return $this->hashPart(self::$images_reference_callback->__invoke(array(), $this, $matches));
 704         }
 705 
 706 
 707 
 708 
 709 
 710 
 711 
 712 
 713 
 714 
 715 
 716 
 717 
 718 
 719 
 720 
 721 
 722 
 723 
 724 
 725 
 726 
 727 
 728 
 729         static $module;
 730 
 731         if (!$module)
 732         {
 733             global $core;
 734 
 735             $module = $core->modules['images'];
 736         }
 737 
 738         //      echo l('<pre>in \1: \2</pre>', __FUNCTION__, $matches);
 739 
 740         $align = $matches[2];
 741         $alt = $matches[3];
 742         $id = $matches[4];
 743 
 744         # for shortcut links like ![this][].
 745 
 746         if (!$id)
 747         {
 748             $id = $alt;
 749         }
 750 
 751         $parts = explode(':', $id, 2);
 752 
 753         if (isset($parts[1]))
 754         {
 755             $entry = $module->model()->loadRange
 756             (
 757             0, 1, 'WHERE `' . $module->getConstant('TITLE') . '` = ? AND `' . $module->getConstant('ALBUM') . '` = ?', array
 758             (
 759             $parts[1], $parts[0]
 760             )
 761             )
 762             ->fetchAndClose();
 763 
 764         }
 765         else
 766         {
 767             $entry = $module->model()->loadRange
 768             (
 769             0, 1, 'WHERE `slug` = ? OR `title` = ?', array
 770             (
 771             $id, $id
 772             )
 773             )
 774             ->fetchAndClose();
 775         }
 776 
 777         if (!$entry)
 778         {
 779             $matches[2] = $matches[3];
 780             $matches[3] = $matches[4];
 781 
 782             return parent::_doImages_reference_callback($matches);
 783         }
 784 
 785         $params = array
 786         (
 787             'src' => $entry->path,
 788             'alt' => \ICanBoogie\escape($alt),
 789             'width' => $entry->width,
 790             'height' => $entry->height
 791         );
 792 
 793         if ($align)
 794         {
 795             switch ($align)
 796             {
 797                 case '<': $align = 'left'; break;
 798                 case '=':
 799                 case '|': $align = 'middle'; break;
 800                 case '>': $align = 'right'; break;
 801             }
 802 
 803             $params['align'] = $align;
 804         }
 805 
 806         # the image has been found is the database
 807 
 808         return $this->hashPart($this->createElement('img', $params));
 809     }
 810 
 811     function _doImages_inline_callback($matches)
 812     {
 813         //      \ICanBoogie\log('<pre>in \1: \2</pre>', __FUNCTION__, $matches);
 814 
 815         $whole_match    = $matches[1];
 816         $align = $matches[2];
 817         $alt_text       = $matches[3];
 818         $url            = $matches[4] == '' ? $matches[5] : $matches[4];
 819         $title          =& $matches[8];
 820 
 821         $alt_text = str_replace('"', '&quot;', $alt_text);
 822         $result = "<img src=\"$url\" alt=\"$alt_text\"";
 823 
 824         if ($align)
 825         {
 826             switch ($align)
 827             {
 828                 case '<': $align = 'left'; break;
 829                 case '=':
 830                 case '|': $align = 'middle'; break;
 831                 case '>': $align = 'right'; break;
 832             }
 833 
 834             $result .= ' align="' . $align . '"';
 835         }
 836 
 837         if (isset($title))
 838         {
 839             $title = str_replace('"', '&quot;', $title);
 840             $result .=  " title=\"$title\""; # $title already quoted
 841         }
 842 
 843         $result .= $this->empty_element_suffix;
 844 
 845         return $this->hashPart($result);
 846     }
 847 
 848     /*
 849      **
 850 
 851      NEW IMPLEMENTATIONS
 852 
 853      **
 854      */
 855 
 856     function createElement($markup, $attrs, $body=NULL)
 857     {
 858         $rc = array();
 859 
 860         foreach ($attrs as $name => $value)
 861         {
 862             $rc[] = $name . '="' . $value . '"';
 863         }
 864 
 865         return "<$markup " . implode(' ', $rc) . ($body ? ">$body</$markup>" : " />");
 866     }
 867 
 868     protected function format_codeblock($codeblock, $type)
 869     {
 870         switch ($type)
 871         {
 872             case 'html': return $this->doSourceHTML($codeblock);
 873             case 'php': return $this->doSourcePHP($codeblock);
 874             default: return $this->doSourceRaw($codeblock);
 875         }
 876     }
 877 
 878     #
 879     # raw source
 880     #
 881 
 882     function doSourceRaw($text)
 883     {
 884         $text = \ICanBoogie\escape($text);
 885         $text = str_replace("\t", self::NBSP_TAB, $text);
 886         $text = str_replace(" ", self::NBSP, $text);
 887 
 888         return $text;
 889     }
 890 
 891     #
 892     # HTML source highlighter
 893     #
 894 
 895     protected function doSourceHTML($text)
 896     {
 897         //      \ICanBoogie\log('## \1 ## <pre>\2</pre>', __FUNCTION__, $text);
 898 
 899         $text = trim($text);
 900 
 901         #
 902         # markup
 903         #
 904 
 905         $text = preg_replace_callback
 906         (
 907             '#(\<\!?[^\s^\>]+)(\s+[^\>]+)?(\/?\>)#m', array($this, '_do_html_markup'), $text
 908         );
 909 
 910         //      \ICanBoogie\log('## \1 ## <pre>\2</pre>', __FUNCTION__, $text);
 911 
 912         #
 913         # markup close
 914         #
 915 
 916         //      \ICanBoogie\log('## \1 ## <pre>\2</pre>', __FUNCTION__, $text);
 917 
 918         $text = preg_replace_callback
 919         (
 920             '#\<\/[a-zA-Z]+\>#m', array($this, '_do_html_markup_close'), $text
 921         );
 922 
 923         #
 924         # tabulations and spaces
 925         #
 926 
 927         //      \ICanBoogie\log('## \1 ## <pre>\2</pre>', __FUNCTION__, \ICanBoogie\escape($text));
 928 
 929         $text = \ICanBoogie\escape($text);
 930         $text = str_replace("\t", self::NBSP_TAB, $text);
 931         $text = str_replace(" ", self::NBSP, $text);
 932 
 933         return $text;
 934     }
 935 
 936     function _do_html_string($matches)
 937     {
 938         //      \ICanBoogie\log('<pre>in \1: \2</pre>', __FUNCTION__, $matches);
 939 
 940         return $this->hashPart('<span class="string">' . \ICanBoogie\escape($matches[0]) . '</span>');
 941     }
 942 
 943     function _do_html_attribute($matches)
 944     {
 945         //      \ICanBoogie\log('<pre>in \1: \2</pre>', __FUNCTION__, $matches);
 946 
 947         return $this->hashPart('<span class="attribute">' . \ICanBoogie\escape($matches[0]) . '</span>');
 948     }
 949 
 950     function _do_html_markup($matches)
 951     {
 952         //      \ICanBoogie\log('<pre>in \1: \2</pre>', __FUNCTION__, $matches);
 953 
 954         $text = $matches[2];
 955 
 956         #
 957         # strings
 958         #
 959 
 960         $text = preg_replace_callback
 961         (
 962             '#\"[^\"]+\"#', array(&$this, '_do_html_string'), $text
 963         );
 964 
 965         //      \ICanBoogie\log('<pre>in \1: \2</pre>', __FUNCTION__, $text);
 966 
 967         #
 968         # attributes
 969         #
 970 
 971         $text = preg_replace_callback
 972         (
 973             '#[^\s\=]+#', array(&$this, '_do_html_attribute'), $text
 974         );
 975 
 976         $rc = $this->hashPart('<span class="markup">' . \ICanBoogie\escape($matches[1]) . '</span>');
 977         $rc .= $text;
 978         $rc .= $this->hashpart('<span class="markup">' . \ICanBoogie\escape($matches[3]) . '</span>');
 979 
 980         return $rc;
 981     }
 982 
 983     function _do_html_markup_close($matches)
 984     {
 985         //      \ICanBoogie\log('<pre>in \1: \2</pre>', __FUNCTION__, $matches);
 986 
 987         return $this->hashPart('<span class="markup">' . \ICanBoogie\escape($matches[0]) . '</span>');
 988     }
 989 
 990     #
 991     # PHP source highlighter
 992     #
 993 
 994     function doSourceCommentLine($text, $marker)
 995     {
 996         $lines = explode("\n", $text);
 997 
 998         //      echo l('lines: \1', $lines);
 999 
1000         $marker_len = strlen($marker);
1001 
1002         foreach ($lines as &$line)
1003         {
1004             $in_quotes = NULL;
1005 
1006             for ($i = 0 ; $i < strlen($line) ; $i++)
1007             {
1008                 $c = $line{$i};
1009 
1010                 if (($c == $in_quotes) && (($i > 1) && ($line{$i - 1} != '\\')))
1011                 {
1012                     $in_quotes = NULL;
1013                 }
1014                 else if ($in_quotes)
1015                 {
1016                     continue;
1017                 }
1018                 else if (($c == '\'') || ($c == '"'))
1019                 {
1020                     $in_quotes = $c;
1021                 }
1022                 else if (substr($line, $i, $marker_len) == $marker)
1023                 {
1024                     //                  echo l('found marker at \1 (\2)<br />', $i, \ICanBoogie\escape(substr($line, $i, 16)));
1025 
1026                     $line =
1027 
1028                     substr($line, 0, $i) .
1029                     $this->hashPart('<code class="comment">' . \ICanBoogie\escape(substr($line, $i)) . '</code>');
1030 
1031                     break;
1032                 }
1033             }
1034         }
1035 
1036         return implode("\n", $lines);
1037     }
1038 
1039     const QUOTE_SINGLE = '\'';
1040     const QUOTE_DOUBLE = '"';
1041     const ESCAPE = '\\';
1042 
1043     function doSourceString($text)
1044     {
1045         $out = NULL;
1046         $swap = NULL;
1047 
1048         $quote = NULL;
1049         $quote_start = null;
1050         $escaped = false;
1051 
1052         $y = strlen($text);
1053 
1054         for ($i = 0 ; $i < $y ; $i++)
1055         {
1056             $c = $text{$i};
1057 
1058             if (($c == self::QUOTE_SINGLE || $c == self::QUOTE_DOUBLE) && ($quote_start === null || $quote == $c))
1059             {
1060                 if ($escaped)
1061                 {
1062                     $escaped = false;
1063 
1064                     continue;
1065                 }
1066                 else if ($quote_start !== null && $c == $quote)
1067                 {
1068                     $out .= $this->hashPart('<span class="string">' . \ICanBoogie\escape($quote . substr($text, $quote_start + 1, $i - $quote_start - 1) . $quote) . '</span>');
1069 
1070                     $quote_start = null;
1071                     $quote = null;
1072                 }
1073                 else
1074                 {
1075                     $quote = $c;
1076                     $quote_start = $i;
1077                 }
1078             }
1079             else
1080             {
1081                 if ($c == '\\')
1082                 {
1083                     $escaped = !$escaped;
1084                 }
1085                 else
1086                 {
1087                     $escaped = false;
1088                 }
1089 
1090                 if ($quote_start === null)
1091                 {
1092                     $out .= $c;
1093                 }
1094             }
1095         }
1096 
1097         return $out;
1098     }
1099 
1100     function doSourcePHP($text)
1101     {
1102         //      \ICanBoogie\log('## \1 ## <pre>\2</pre>', __FUNCTION__, $text);
1103 
1104         $text = preg_replace('#^\<\?php\s*#', '', trim($text)); // FXME-20110817: this is a compat because we don't require the <?php and we automatically add it, whereas Git requires it
1105 
1106         $text = $this->doSourceCommentLine($text, '#');
1107         $text = $this->doSourceCommentLine($text, '//');
1108 
1109         #
1110         # comment block
1111         #
1112 
1113         $text = preg_replace_callback
1114         (
1115             '#/\*.*?\*/#ms', array(&$this, '_do_php_comment'), $text
1116         );
1117 
1118         $text = $this->doSourceString($text);
1119 
1120         #
1121         # functions
1122         #
1123 
1124         $text = preg_replace_callback
1125         (
1126             '#(\$?[a-zA-z0-9_]+)\(#', array(&$this, '_do_php_function'), $text
1127         );
1128 
1129         #
1130         # variables
1131         #
1132 
1133         //      \ICanBoogie\log('## \1 ## <pre>\2</pre>', __FUNCTION__, \ICanBoogie\escape($text));
1134 
1135         $text = preg_replace_callback
1136         (
1137             '#(\$|\-\>)([a-zA-z0-9_]+)(?!\x1A)#', array(&$this, '_do_php_variable'), $text
1138         );
1139 
1140         #
1141         # numbers
1142         #
1143 
1144         $text = preg_replace_callback
1145         (
1146             '#0x[0-9a-fA-F]{1,8}#u', array(&$this, '_do_php_number'), $text
1147         );
1148 
1149         $text = preg_replace_callback
1150         (
1151             '#(?<!\x1A)\d+(?![\w])#u', array(&$this, '_do_php_number'), $text
1152         );
1153 
1154         #
1155         # reserved keywords
1156         #
1157 
1158         $reserved = array
1159         (
1160             'include_once',
1161             'require_once',
1162             'endswitch',
1163             'namespace',
1164             'protected',
1165             'continue',
1166             'endwhile',
1167             'function',
1168             'default',
1169             'include',
1170             'require',
1171             'extends',
1172             'foreach',
1173             'private',
1174             'elseif',
1175             'global',
1176             'parent',
1177             'static',
1178             'return',
1179             'switch',
1180             'public',
1181             'break',
1182             'class',
1183             'const',
1184             'endif',
1185             'case',
1186             'true',
1187             'self',
1188             'echo',
1189             'TRUE',
1190             'else',
1191             'false',
1192             'FALSE',
1193             'while',
1194             'NULL',
1195             'for',
1196             'new',
1197             'use',
1198             'var',
1199             'as',
1200             'if',
1201             'do',
1202         );
1203 
1204         foreach ($reserved as $k)
1205         {
1206             $text = preg_replace_callback
1207             (
1208                 '#' . $k . '#', array(&$this, '_do_php_reserved'), $text
1209             );
1210         }
1211 
1212         #
1213         # symbols
1214         #
1215 
1216         $text = preg_replace_callback
1217         (
1218             '#[\(\)\[\]\{\}\!\@\%\&\*\|\/\<\>\-\+\=]+#', array(&$this, '_do_php_symbol'), $text
1219         );
1220 
1221         #
1222         # tabulations and spaces
1223         #
1224 
1225         //      \ICanBoogie\log('## \1 ## <pre>\2</pre>', __FUNCTION__, \ICanBoogie\escape($text));
1226 
1227         $text = str_replace("\t", self::NBSP_TAB, $text);
1228         $text = str_replace(" ", self::NBSP, $text);
1229 
1230         //      preg_match('#\/\*(.*)\*\/#', $text, $matches);
1231 
1232         $text =
1233 
1234             '<span class="delimiter">' .
1235             "&lt;?php</span>\n\n" .
1236 
1237         $text;
1238 
1239         //          '<span class="delimiter">' .
1240         //          "\n\n?&gt;</span>" .
1241 
1242 
1243 //      $text = nl2br($text);
1244 
1245         return $text;
1246     }
1247 
1248 
1249 
1250 
1251 
1252 
1253 
1254 
1255 
1256 
1257     function _do_codeentities($text)
1258     {
1259         $text = \ICanBoogie\escape($text);
1260         $text = str_replace("\t", self::NBSP_TAB, $text);
1261         $text = str_replace(" ", self::NBSP, $text);
1262 
1263         return $text;
1264     }
1265     /*
1266      function _do_php_string($matches)
1267      {
1268      //     \ICanBoogie\log('## \1 ## \2', __FUNCTION__, $matches);
1269 
1270         return $this->hashPart('<span class="string">' . $this->_do_code\ICanBoogie\escape($matches[0]) . '</span>');
1271         }
1272         */
1273 
1274     function _do_php_comment($matches)
1275     {
1276 
1277         //      \ICanBoogie\log('## \1 ## \2', __FUNCTION__, $matches);
1278 
1279         return $this->hashPart
1280         (
1281             '<span class="comment">' .
1282         $this->_do_codeentities($matches[0]) .
1283             '</span>'
1284         );
1285     }
1286 
1287     function _do_php_variable($matches)
1288     {
1289         //      \ICanBoogie\log('## \1 ## \2', __FUNCTION__, $matches);
1290 
1291         if ($matches[1] == '->')
1292         {
1293             return '->' . $this->hashPart('<span class="variable">' . $matches[2] . '</span>');
1294         }
1295 
1296         return $this->hashPart('<span class="variable">' . $matches[0] . '</span>');
1297     }
1298 
1299     function _do_php_reserved($matches)
1300     {
1301         //      \ICanBoogie\log('## \1 ## \2', __FUNCTION__, $matches);
1302 
1303         return $this->hashPart('<span class="reserved">' . $matches[0] . '</span>');
1304     }
1305 
1306     function _do_php_function_def($matches)
1307     {
1308         //      \ICanBoogie\log('## \1 ## \2', __FUNCTION__, $matches);
1309 
1310         return $this->hashPart('<span class="function">function</span>' . $matches[1]);
1311         //      return $this->hashPart('<span class="function">' . $matches[1] . '</span>(', 'F');
1312     }
1313 
1314     function _do_php_function($matches)
1315     {
1316         //      \ICanBoogie\log('## \1 ## \2', __FUNCTION__, $matches);
1317 
1318         if ($matches[1]{0} == '$')
1319         {
1320             return $matches[0];
1321         }
1322 
1323         return $this->hashPart('<span class="function">' . $matches[1] . '</span>', 'F'). '(';
1324     }
1325 
1326     function _do_php_symbol($matches)
1327     {
1328         return $this->hashPart('<span class="symbol">' . \ICanBoogie\escape($matches[0]) . '</span>');
1329     }
1330 
1331     function _do_php_number($matches)
1332     {
1333         //      \ICanBoogie\log('## \1 ## \2', __FUNCTION__, $matches);
1334 
1335         return $this->hashPart('<span class="number">' . $matches[0] . '</span>');
1336     }
1337 
1338     /*
1339      function _do_php_callback($matches)
1340      {
1341      //     \ICanBoogie\log('<pre>in \1: \2</pre>', __FUNCTION__, $matches);
1342 
1343         return 'class="' . $this->php_colors[$matches[1]] . '"';
1344         }
1345         */
1346 
1347     function _doAnchors_inline_callback($matches)
1348     {
1349         $whole_match    =  $matches[1];
1350         $link_text      =  $this->runSpanGamut($matches[2]);
1351         $url            =  $matches[3] == '' ? $matches[4] : $matches[3];
1352         $title          =& $matches[7];
1353 
1354         if ($matches[2] == 'video:')
1355         {
1356             $w = 500;
1357             $h = 375;
1358             $rc = '<p>Video link type not recognized: ' . \ICanBoogie\escape($url) . '</p>';
1359 
1360             if (preg_match('#vimeo.com/(\d+)#', $url, $matches))
1361             {
1362                 $id = $matches[1];
1363 
1364                 $rc = <<<EOT
1365 <p align="center"><iframe src="http://player.vimeo.com/video/$id?show_title=1&show_byline=1&show_portrait=0&color=F65FB8" width="$w" height="$h" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe></p>
1366 EOT;
1367             }
1368             else if (strpos($url, 'youtube.com/watch') !== false)
1369             {
1370                 $query = parse_url($url, PHP_URL_QUERY);
1371                 parse_str($query, $params);
1372 
1373                 if (empty($params['v']))
1374                 {
1375                     $rc = \ICanBoogie\format('Missing <q>v</q> param form: %url', array('url' => $url));
1376                 }
1377                 else
1378                 {
1379                     $id = $params['v'];
1380 
1381                     $rc = <<<EOT
1382 <p align="center"><iframe type="text/html" width="$w" height="$h" src="http://www.youtube.com/embed/$id?controls=2" frameborder="0"></iframe></p>
1383 EOT;
1384                 }
1385             }
1386             else if (preg_match('#dailymotion.com/video/([^_]+)#', $url, $matches))
1387             {
1388                 $id = $matches[1];
1389                 $data = \ICanBoogie\escape("http://www.dailymotion.com/swf/$id");
1390 
1391                 $rc = <<<EOT
1392 <p align="center">
1393     <object width="$w" height="$h" data="$data" type="application/x-shockwave-flash">
1394         <param name="movie" value="$data" />
1395         <param name="wmode" value="transparent" />
1396         <param name="allowfullscreen" value="true" />
1397         <param name="allowscriptaccess" value="always" />
1398     </object>
1399 </p>
1400 EOT;
1401             }
1402 
1403             return $this->hashPart($rc, 'B');
1404         }
1405         else if ($matches[2] == 'embed:')
1406         {
1407             if (preg_match('#soundcloud.com/#', $url, $matches))
1408             {
1409                 $id = urlencode($url);
1410 
1411                 $rc = <<<EOT
1412 <p align="center"><iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=$url"></iframe></p>
1413 EOT;
1414 
1415                 return $this->hashPart($rc, 'B');
1416             }
1417         }
1418 
1419         #
1420         #
1421         #
1422 
1423         $url = $this->encodeAmpsAndAngles($url);
1424 
1425         $result = "<a href=\"$url\"";
1426         if (isset($title)) {
1427             $title = str_replace('"', '&quot;', $title);
1428             $title = $this->encodeAmpsAndAngles($title);
1429             $result .=  " title=\"$title\"";
1430         }
1431 
1432         if (substr($url, 0, 7) == 'http://')
1433         {
1434             $result .= ' target="_blank"';
1435         }
1436 
1437         $link_text = $this->runSpanGamut($link_text);
1438         $result .= ">$link_text</a>";
1439 
1440         return $this->hashPart($result);
1441     }
1442 }
1443 
Autodoc API documentation generated by ApiGen 2.8.0