1
+ − 1
<?php
+ − 2
/**
+ − 3
* Parse structured wiki text and render into arbitrary formats such as XHTML.
+ − 4
*
+ − 5
* PHP versions 4 and 5
+ − 6
*
+ − 7
* @category Text
+ − 8
* @package Text_Wiki
+ − 9
* @author Paul M. Jones <pmjones@php.net>
+ − 10
* @license http://www.gnu.org/licenses/lgpl.html
+ − 11
* @version CVS: $Id: Wiki.php,v 1.44 2006/03/02 04:04:59 justinpatrin Exp $
+ − 12
* @link http://wiki.ciaweb.net/yawiki/index.php?area=Text_Wiki
+ − 13
*
+ − 14
* This code was modified for use in Enano. The Text_Wiki engine is licensed
+ − 15
* under the GNU Lesser General Public License; see
+ − 16
* http://www.gnu.org/licenses/lgpl.html for details.
+ − 17
*
+ − 18
*/
+ − 19
+ − 20
require_once ENANO_ROOT.'/includes/wikiengine/Parse.php';
+ − 21
require_once ENANO_ROOT.'/includes/wikiengine/Render.php';
+ − 22
+ − 23
class Text_Wiki {
+ − 24
+ − 25
var $rules = array(
+ − 26
'Prefilter',
+ − 27
'Delimiter',
+ − 28
'Code',
+ − 29
'Function',
+ − 30
'Html',
+ − 31
'Raw',
+ − 32
'Include',
+ − 33
'Embed',
+ − 34
'Anchor',
+ − 35
'Heading',
+ − 36
'Toc',
+ − 37
'Horiz',
+ − 38
'Break',
+ − 39
'Blockquote',
+ − 40
'List',
+ − 41
'Deflist',
+ − 42
'Table',
+ − 43
'Image',
+ − 44
'Phplookup',
+ − 45
'Center',
+ − 46
'Newline',
+ − 47
'Paragraph',
+ − 48
'Url',
+ − 49
'Freelink',
+ − 50
'Interwiki',
+ − 51
'Wikilink',
+ − 52
'Colortext',
+ − 53
'Strong',
+ − 54
'Bold',
+ − 55
'Emphasis',
+ − 56
'Italic',
+ − 57
'Underline',
+ − 58
'Tt',
+ − 59
'Superscript',
+ − 60
'Subscript',
+ − 61
'Revise',
+ − 62
'Tighten'
+ − 63
);
+ − 64
+ − 65
var $disable = array(
+ − 66
'Html',
+ − 67
'Include',
32
4d87aad3c4c0
Finished everything on the TODO list (yay!); several CSS cleanups; tons more changes in this commit - see the patch for details
Dan
diff
changeset
+ − 68
'Embed',
35
+ − 69
'Tighten',
142
ca9118d9c0f2
Rebrand as 1.0.2 (Coblynau); internal links are now parsed by RenderMan::parse_internal_links()
Dan
diff
changeset
+ − 70
'Image',
ca9118d9c0f2
Rebrand as 1.0.2 (Coblynau); internal links are now parsed by RenderMan::parse_internal_links()
Dan
diff
changeset
+ − 71
'Wikilink'
1
+ − 72
);
+ − 73
+ − 74
var $parseConf = array();
+ − 75
+ − 76
var $renderConf = array(
+ − 77
'Docbook' => array(),
+ − 78
'Latex' => array(),
+ − 79
'Pdf' => array(),
+ − 80
'Plain' => array(),
+ − 81
'Rtf' => array(),
+ − 82
'Xhtml' => array()
+ − 83
);
+ − 84
+ − 85
var $formatConf = array(
+ − 86
'Docbook' => array(),
+ − 87
'Latex' => array(),
+ − 88
'Pdf' => array(),
+ − 89
'Plain' => array(),
+ − 90
'Rtf' => array(),
+ − 91
'Xhtml' => array()
+ − 92
);
+ − 93
var $delim = "\xFF";
+ − 94
var $tokens = array();
+ − 95
var $_countRulesTokens = array();
+ − 96
var $source = '';
+ − 97
var $parseObj = array();
+ − 98
var $renderObj = array();
+ − 99
var $formatObj = array();
+ − 100
var $path = array(
+ − 101
'parse' => array(),
+ − 102
'render' => array()
+ − 103
);
+ − 104
var $_dirSep = DIRECTORY_SEPARATOR;
+ − 105
function Text_Wiki($rules = null)
+ − 106
{
+ − 107
if (is_array($rules)) {
+ − 108
$this->rules = $rules;
+ − 109
}
+ − 110
+ − 111
$this->addPath(
+ − 112
'parse',
+ − 113
$this->fixPath(ENANO_ROOT) . 'includes/wikiengine/Parse/Default/'
+ − 114
);
+ − 115
$this->addPath(
+ − 116
'render',
+ − 117
$this->fixPath(ENANO_ROOT) . 'includes/wikiengine/Render/'
+ − 118
);
+ − 119
+ − 120
}
+ − 121
+ − 122
function &singleton($parser = 'Default', $rules = null)
+ − 123
{
+ − 124
static $only = array();
+ − 125
if (!isset($only[$parser])) {
+ − 126
$ret =& Text_Wiki::factory($parser, $rules);
+ − 127
if (!$ret) {
+ − 128
return $ret;
+ − 129
}
+ − 130
$only[$parser] =& $ret;
+ − 131
}
+ − 132
return $only[$parser];
+ − 133
}
+ − 134
+ − 135
function &factory($parser = 'Default', $rules = null)
+ − 136
{
+ − 137
$d=getcwd();
+ − 138
chdir(ENANO_ROOT);
+ − 139
+ − 140
$class = 'Text_Wiki_' . $parser;
+ − 141
$c2 = '._includes_wikiengine_' . $parser;
+ − 142
$file = str_replace('_', '/', $c2).'.php';
+ − 143
if (!class_exists($class)) {
+ − 144
$fp = @fopen($file, 'r', true);
+ − 145
if ($fp === false) {
+ − 146
die_semicritical('Wiki formatting engine error', '<p>Could not find file '.$file.' in include_path</p>');
+ − 147
}
+ − 148
fclose($fp);
+ − 149
include_once($file);
+ − 150
if (!class_exists($class)) {
+ − 151
die_semicritical('Wiki formatting engine error', '<p>Class '.$class.' does not exist after including '.$file.'</p>');
+ − 152
}
+ − 153
}
+ − 154
+ − 155
chdir($d);
+ − 156
297
+ − 157
$obj = new $class($rules);
1
+ − 158
return $obj;
+ − 159
}
+ − 160
+ − 161
function setParseConf($rule, $arg1, $arg2 = null)
+ − 162
{
+ − 163
$rule = ucwords(strtolower($rule));
+ − 164
+ − 165
if (! isset($this->parseConf[$rule])) {
+ − 166
$this->parseConf[$rule] = array();
+ − 167
}
+ − 168
+ − 169
if (is_array($arg1)) {
+ − 170
$this->parseConf[$rule] = $arg1;
+ − 171
} else {
+ − 172
$this->parseConf[$rule][$arg1] = $arg2;
+ − 173
}
+ − 174
}
+ − 175
+ − 176
function getParseConf($rule, $key = null)
+ − 177
{
+ − 178
$rule = ucwords(strtolower($rule));
+ − 179
+ − 180
if (! isset($this->parseConf[$rule])) {
+ − 181
return null;
+ − 182
}
+ − 183
+ − 184
if (is_null($key)) {
+ − 185
return $this->parseConf[$rule];
+ − 186
}
+ − 187
+ − 188
if (isset($this->parseConf[$rule][$key])) {
+ − 189
return $this->parseConf[$rule][$key];
+ − 190
} else {
+ − 191
return null;
+ − 192
}
+ − 193
}
+ − 194
+ − 195
function setRenderConf($format, $rule, $arg1, $arg2 = null)
+ − 196
{
+ − 197
$format = ucwords(strtolower($format));
+ − 198
$rule = ucwords(strtolower($rule));
+ − 199
+ − 200
if (! isset($this->renderConf[$format])) {
+ − 201
$this->renderConf[$format] = array();
+ − 202
}
+ − 203
+ − 204
if (! isset($this->renderConf[$format][$rule])) {
+ − 205
$this->renderConf[$format][$rule] = array();
+ − 206
}
+ − 207
+ − 208
if (is_array($arg1)) {
+ − 209
$this->renderConf[$format][$rule] = $arg1;
+ − 210
} else {
+ − 211
$this->renderConf[$format][$rule][$arg1] = $arg2;
+ − 212
}
+ − 213
}
+ − 214
+ − 215
function getRenderConf($format, $rule, $key = null)
+ − 216
{
+ − 217
$format = ucwords(strtolower($format));
+ − 218
$rule = ucwords(strtolower($rule));
+ − 219
+ − 220
if (! isset($this->renderConf[$format]) ||
+ − 221
! isset($this->renderConf[$format][$rule])) {
+ − 222
return null;
+ − 223
}
+ − 224
+ − 225
if (is_null($key)) {
+ − 226
return $this->renderConf[$format][$rule];
+ − 227
}
+ − 228
+ − 229
if (isset($this->renderConf[$format][$rule][$key])) {
+ − 230
return $this->renderConf[$format][$rule][$key];
+ − 231
} else {
+ − 232
return null;
+ − 233
}
+ − 234
+ − 235
}
+ − 236
+ − 237
function setFormatConf($format, $arg1, $arg2 = null)
+ − 238
{
+ − 239
if (! is_array($this->formatConf[$format])) {
+ − 240
$this->formatConf[$format] = array();
+ − 241
}
+ − 242
+ − 243
if (is_array($arg1)) {
+ − 244
$this->formatConf[$format] = $arg1;
+ − 245
} else {
+ − 246
$this->formatConf[$format][$arg1] = $arg2;
+ − 247
}
+ − 248
}
+ − 249
+ − 250
function getFormatConf($format, $key = null)
+ − 251
{
+ − 252
if (! isset($this->formatConf[$format])) {
+ − 253
return null;
+ − 254
}
+ − 255
+ − 256
if (is_null($key)) {
+ − 257
return $this->formatConf[$format];
+ − 258
}
+ − 259
+ − 260
if (isset($this->formatConf[$format][$key])) {
+ − 261
return $this->formatConf[$format][$key];
+ − 262
} else {
+ − 263
return null;
+ − 264
}
+ − 265
}
+ − 266
+ − 267
function insertRule($name, $tgt = null)
+ − 268
{
+ − 269
$name = ucwords(strtolower($name));
+ − 270
if (! is_null($tgt)) {
+ − 271
$tgt = ucwords(strtolower($tgt));
+ − 272
}
+ − 273
if (in_array($name, $this->rules)) {
+ − 274
return null;
+ − 275
}
+ − 276
+ − 277
if (! is_null($tgt) && $tgt != '' &&
+ − 278
! in_array($tgt, $this->rules)) {
+ − 279
return false;
+ − 280
}
+ − 281
+ − 282
if (is_null($tgt)) {
+ − 283
$this->rules[] = $name;
+ − 284
return true;
+ − 285
}
+ − 286
+ − 287
if ($tgt == '') {
+ − 288
array_unshift($this->rules, $name);
+ − 289
return true;
+ − 290
}
+ − 291
+ − 292
$tmp = $this->rules;
+ − 293
$this->rules = array();
+ − 294
+ − 295
foreach ($tmp as $val) {
+ − 296
$this->rules[] = $val;
+ − 297
if ($val == $tgt) {
+ − 298
$this->rules[] = $name;
+ − 299
}
+ − 300
}
+ − 301
+ − 302
return true;
+ − 303
}
+ − 304
+ − 305
function deleteRule($name)
+ − 306
{
+ − 307
$name = ucwords(strtolower($name));
+ − 308
$key = array_search($name, $this->rules);
+ − 309
if ($key !== false) {
+ − 310
unset($this->rules[$key]);
+ − 311
}
+ − 312
}
+ − 313
+ − 314
function changeRule($old, $new)
+ − 315
{
+ − 316
$old = ucwords(strtolower($old));
+ − 317
$new = ucwords(strtolower($new));
+ − 318
$key = array_search($old, $this->rules);
+ − 319
if ($key !== false) {
+ − 320
$this->deleteRule($new);
+ − 321
$this->rules[$key] = $new;
+ − 322
}
+ − 323
}
+ − 324
+ − 325
function enableRule($name)
+ − 326
{
+ − 327
$name = ucwords(strtolower($name));
+ − 328
$key = array_search($name, $this->disable);
+ − 329
if ($key !== false) {
+ − 330
unset($this->disable[$key]);
+ − 331
}
+ − 332
}
+ − 333
+ − 334
function disableRule($name)
+ − 335
{
+ − 336
$name = ucwords(strtolower($name));
+ − 337
$key = array_search($name, $this->disable);
+ − 338
if ($key === false) {
+ − 339
$this->disable[] = $name;
+ − 340
}
+ − 341
}
+ − 342
+ − 343
function transform($text, $format = 'Xhtml')
+ − 344
{
+ − 345
$this->parse($text);
+ − 346
return $this->render($format);
+ − 347
}
+ − 348
+ − 349
function parse($text)
+ − 350
{
+ − 351
$this->source = $text;
+ − 352
+ − 353
$this->tokens = array();
+ − 354
$this->_countRulesTokens = array();
+ − 355
+ − 356
foreach ($this->rules as $name) {
+ − 357
if (! in_array($name, $this->disable)) {
+ − 358
$this->loadParseObj($name);
+ − 359
+ − 360
if (is_object($this->parseObj[$name])) {
+ − 361
$this->parseObj[$name]->parse();
+ − 362
}
32
4d87aad3c4c0
Finished everything on the TODO list (yay!); several CSS cleanups; tons more changes in this commit - see the patch for details
Dan
diff
changeset
+ − 363
// For debugging
4d87aad3c4c0
Finished everything on the TODO list (yay!); several CSS cleanups; tons more changes in this commit - see the patch for details
Dan
diff
changeset
+ − 364
// echo('<p>' . $name . ':</p><pre>'.htmlspecialchars($this->source).'</pre>');
1
+ − 365
}
+ − 366
}
+ − 367
}
+ − 368
+ − 369
function render($format = 'Xhtml')
+ − 370
{
+ − 371
$format = ucwords(strtolower($format));
+ − 372
+ − 373
$output = '';
+ − 374
+ − 375
$in_delim = false;
+ − 376
+ − 377
$key = '';
+ − 378
+ − 379
$result = $this->loadFormatObj($format);
+ − 380
if ($this->isError($result)) {
+ − 381
return $result;
+ − 382
}
78
4df25dfdde63
Modified Text_Wiki parser to fully support UTF-8 strings; several other UTF-8 fixes, international characters seem to work reasonably well now
Dan
diff
changeset
+ − 383
1
+ − 384
if (is_object($this->formatObj[$format])) {
+ − 385
$output .= $this->formatObj[$format]->pre();
+ − 386
}
+ − 387
+ − 388
foreach (array_keys($this->_countRulesTokens) as $rule) {
+ − 389
$this->loadRenderObj($format, $rule);
+ − 390
}
78
4df25dfdde63
Modified Text_Wiki parser to fully support UTF-8 strings; several other UTF-8 fixes, international characters seem to work reasonably well now
Dan
diff
changeset
+ − 391
1
+ − 392
$k = strlen($this->source);
+ − 393
for ($i = 0; $i < $k; $i++) {
+ − 394
+ − 395
$char = $this->source{$i};
+ − 396
+ − 397
if ($in_delim) {
+ − 398
+ − 399
if ($char == $this->delim) {
+ − 400
+ − 401
$key = (int)$key;
+ − 402
$rule = $this->tokens[$key][0];
+ − 403
$opts = $this->tokens[$key][1];
+ − 404
$output .= $this->renderObj[$rule]->token($opts);
+ − 405
$in_delim = false;
+ − 406
+ − 407
} else {
+ − 408
+ − 409
$key .= $char;
+ − 410
+ − 411
}
+ − 412
+ − 413
} else {
+ − 414
+ − 415
if ($char == $this->delim) {
+ − 416
$key = '';
+ − 417
$in_delim = true;
+ − 418
} else {
+ − 419
$output .= $char;
+ − 420
}
+ − 421
}
+ − 422
}
+ − 423
+ − 424
if (is_object($this->formatObj[$format])) {
+ − 425
$output .= $this->formatObj[$format]->post();
+ − 426
}
+ − 427
+ − 428
return $output;
+ − 429
}
+ − 430
+ − 431
function getSource()
+ − 432
{
+ − 433
return $this->source;
+ − 434
}
+ − 435
+ − 436
function getTokens($rules = null)
+ − 437
{
+ − 438
if (is_null($rules)) {
+ − 439
return $this->tokens;
+ − 440
} else {
+ − 441
settype($rules, 'array');
+ − 442
$result = array();
+ − 443
foreach ($this->tokens as $key => $val) {
+ − 444
if (in_array($val[0], $rules)) {
+ − 445
$result[$key] = $val;
+ − 446
}
+ − 447
}
+ − 448
return $result;
+ − 449
}
+ − 450
}
+ − 451
+ − 452
function addToken($rule, $options = array(), $id_only = false)
+ − 453
{
+ − 454
static $id;
+ − 455
if (! isset($id)) {
+ − 456
$id = 0;
+ − 457
} else {
+ − 458
$id ++;
+ − 459
}
+ − 460
+ − 461
settype($options, 'array');
+ − 462
+ − 463
$this->tokens[$id] = array(
+ − 464
0 => $rule,
+ − 465
1 => $options
+ − 466
);
+ − 467
if (!isset($this->_countRulesTokens[$rule])) {
+ − 468
$this->_countRulesTokens[$rule] = 1;
+ − 469
} else {
+ − 470
++$this->_countRulesTokens[$rule];
+ − 471
}
+ − 472
+ − 473
if ($id_only) {
+ − 474
return $id;
+ − 475
} else {
+ − 476
return $this->delim . $id . $this->delim;
+ − 477
}
+ − 478
}
+ − 479
+ − 480
function setToken($id, $rule, $options = array())
+ − 481
{
+ − 482
$oldRule = $this->tokens[$id][0];
+ − 483
$this->tokens[$id] = array(
+ − 484
0 => $rule,
+ − 485
1 => $options
+ − 486
);
+ − 487
if ($rule != $oldRule) {
+ − 488
if (!($this->_countRulesTokens[$oldRule]--)) {
+ − 489
unset($this->_countRulesTokens[$oldRule]);
+ − 490
}
+ − 491
if (!isset($this->_countRulesTokens[$rule])) {
+ − 492
$this->_countRulesTokens[$rule] = 1;
+ − 493
} else {
+ − 494
++$this->_countRulesTokens[$rule];
+ − 495
}
+ − 496
}
+ − 497
}
+ − 498
+ − 499
function loadParseObj($rule)
+ − 500
{
+ − 501
$rule = ucwords(strtolower($rule));
+ − 502
$file = $rule . '.php';
+ − 503
$class = "Text_Wiki_Parse_$rule";
+ − 504
+ − 505
if (! class_exists($class)) {
+ − 506
$loc = $this->findFile('parse', $file);
+ − 507
if ($loc) {
+ − 508
include_once $loc;
+ − 509
} else {
+ − 510
$this->parseObj[$rule] = null;
+ − 511
return $this->error(
+ − 512
"Parse rule '$rule' not found"
+ − 513
);
+ − 514
}
+ − 515
}
+ − 516
297
+ − 517
$this->parseObj[$rule] = new $class($this);
1
+ − 518
+ − 519
}
+ − 520
+ − 521
function loadRenderObj($format, $rule)
+ − 522
{
+ − 523
$format = ucwords(strtolower($format));
+ − 524
$rule = ucwords(strtolower($rule));
+ − 525
$file = "$format/$rule.php";
+ − 526
$class = "Text_Wiki_Render_$format" . "_$rule";
+ − 527
+ − 528
if (! class_exists($class)) {
+ − 529
$loc = $this->findFile('render', $file);
+ − 530
if ($loc) {
+ − 531
include_once $loc;
+ − 532
} else {
+ − 533
return $this->error(
+ − 534
"Render rule '$rule' in format '$format' not found"
+ − 535
);
+ − 536
}
+ − 537
}
+ − 538
297
+ − 539
$this->renderObj[$rule] = new $class($this);
1
+ − 540
}
+ − 541
+ − 542
function loadFormatObj($format)
+ − 543
{
+ − 544
$format = ucwords(strtolower($format));
+ − 545
$file = $format . '.php';
+ − 546
$class = "Text_Wiki_Render_$format";
+ − 547
+ − 548
if (! class_exists($class)) {
+ − 549
$loc = $this->findFile('render', $file);
+ − 550
if ($loc) {
+ − 551
include_once $loc;
+ − 552
} else {
+ − 553
return $this->error(
+ − 554
"Rendering format class '$class' not found"
+ − 555
);
+ − 556
}
+ − 557
}
+ − 558
297
+ − 559
$this->formatObj[$format] = new $class($this);
1
+ − 560
}
+ − 561
+ − 562
function addPath($type, $dir)
+ − 563
{
+ − 564
$dir = $this->fixPath($dir);
+ − 565
if (! isset($this->path[$type])) {
+ − 566
$this->path[$type] = array($dir);
+ − 567
} else {
+ − 568
array_unshift($this->path[$type], $dir);
+ − 569
}
+ − 570
}
+ − 571
+ − 572
function getPath($type = null)
+ − 573
{
+ − 574
if (is_null($type)) {
+ − 575
return $this->path;
+ − 576
} elseif (! isset($this->path[$type])) {
+ − 577
return array();
+ − 578
} else {
+ − 579
return $this->path[$type];
+ − 580
}
+ − 581
}
+ − 582
+ − 583
function findFile($type, $file)
+ − 584
{
+ − 585
$set = $this->getPath($type);
+ − 586
+ − 587
foreach ($set as $path) {
+ − 588
$fullname = $path . $file;
+ − 589
if (file_exists($fullname) && is_readable($fullname)) {
+ − 590
return $fullname;
+ − 591
}
+ − 592
}
+ − 593
+ − 594
return false;
+ − 595
}
+ − 596
+ − 597
function fixPath($path)
+ − 598
{
+ − 599
$len = strlen($this->_dirSep);
+ − 600
+ − 601
if (! empty($path) &&
+ − 602
substr($path, -1 * $len, $len) != $this->_dirSep) {
+ − 603
return $path . $this->_dirSep;
+ − 604
} else {
+ − 605
return $path;
+ − 606
}
+ − 607
}
+ − 608
+ − 609
function &error($message)
+ − 610
{
+ − 611
die($message);
+ − 612
}
+ − 613
+ − 614
function isError(&$obj)
+ − 615
{
+ − 616
return is_a($obj, 'PEAR_Error');
+ − 617
}
+ − 618
}
+ − 619
+ − 620
?>