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',
+ − 70
'Image'
1
+ − 71
);
+ − 72
+ − 73
var $parseConf = array();
+ − 74
+ − 75
var $renderConf = array(
+ − 76
'Docbook' => array(),
+ − 77
'Latex' => array(),
+ − 78
'Pdf' => array(),
+ − 79
'Plain' => array(),
+ − 80
'Rtf' => array(),
+ − 81
'Xhtml' => array()
+ − 82
);
+ − 83
+ − 84
var $formatConf = array(
+ − 85
'Docbook' => array(),
+ − 86
'Latex' => array(),
+ − 87
'Pdf' => array(),
+ − 88
'Plain' => array(),
+ − 89
'Rtf' => array(),
+ − 90
'Xhtml' => array()
+ − 91
);
+ − 92
var $delim = "\xFF";
+ − 93
var $tokens = array();
+ − 94
var $_countRulesTokens = array();
+ − 95
var $source = '';
+ − 96
var $parseObj = array();
+ − 97
var $renderObj = array();
+ − 98
var $formatObj = array();
+ − 99
var $path = array(
+ − 100
'parse' => array(),
+ − 101
'render' => array()
+ − 102
);
+ − 103
var $_dirSep = DIRECTORY_SEPARATOR;
+ − 104
function Text_Wiki($rules = null)
+ − 105
{
+ − 106
if (is_array($rules)) {
+ − 107
$this->rules = $rules;
+ − 108
}
+ − 109
+ − 110
$this->addPath(
+ − 111
'parse',
+ − 112
$this->fixPath(ENANO_ROOT) . 'includes/wikiengine/Parse/Default/'
+ − 113
);
+ − 114
$this->addPath(
+ − 115
'render',
+ − 116
$this->fixPath(ENANO_ROOT) . 'includes/wikiengine/Render/'
+ − 117
);
+ − 118
+ − 119
}
+ − 120
+ − 121
function &singleton($parser = 'Default', $rules = null)
+ − 122
{
+ − 123
static $only = array();
+ − 124
if (!isset($only[$parser])) {
+ − 125
$ret =& Text_Wiki::factory($parser, $rules);
+ − 126
if (!$ret) {
+ − 127
return $ret;
+ − 128
}
+ − 129
$only[$parser] =& $ret;
+ − 130
}
+ − 131
return $only[$parser];
+ − 132
}
+ − 133
+ − 134
function &factory($parser = 'Default', $rules = null)
+ − 135
{
+ − 136
$d=getcwd();
+ − 137
chdir(ENANO_ROOT);
+ − 138
+ − 139
$class = 'Text_Wiki_' . $parser;
+ − 140
$c2 = '._includes_wikiengine_' . $parser;
+ − 141
$file = str_replace('_', '/', $c2).'.php';
+ − 142
if (!class_exists($class)) {
+ − 143
$fp = @fopen($file, 'r', true);
+ − 144
if ($fp === false) {
+ − 145
die_semicritical('Wiki formatting engine error', '<p>Could not find file '.$file.' in include_path</p>');
+ − 146
}
+ − 147
fclose($fp);
+ − 148
include_once($file);
+ − 149
if (!class_exists($class)) {
+ − 150
die_semicritical('Wiki formatting engine error', '<p>Class '.$class.' does not exist after including '.$file.'</p>');
+ − 151
}
+ − 152
}
+ − 153
+ − 154
chdir($d);
+ − 155
+ − 156
$obj =& new $class($rules);
+ − 157
return $obj;
+ − 158
}
+ − 159
+ − 160
function setParseConf($rule, $arg1, $arg2 = null)
+ − 161
{
+ − 162
$rule = ucwords(strtolower($rule));
+ − 163
+ − 164
if (! isset($this->parseConf[$rule])) {
+ − 165
$this->parseConf[$rule] = array();
+ − 166
}
+ − 167
+ − 168
if (is_array($arg1)) {
+ − 169
$this->parseConf[$rule] = $arg1;
+ − 170
} else {
+ − 171
$this->parseConf[$rule][$arg1] = $arg2;
+ − 172
}
+ − 173
}
+ − 174
+ − 175
function getParseConf($rule, $key = null)
+ − 176
{
+ − 177
$rule = ucwords(strtolower($rule));
+ − 178
+ − 179
if (! isset($this->parseConf[$rule])) {
+ − 180
return null;
+ − 181
}
+ − 182
+ − 183
if (is_null($key)) {
+ − 184
return $this->parseConf[$rule];
+ − 185
}
+ − 186
+ − 187
if (isset($this->parseConf[$rule][$key])) {
+ − 188
return $this->parseConf[$rule][$key];
+ − 189
} else {
+ − 190
return null;
+ − 191
}
+ − 192
}
+ − 193
+ − 194
function setRenderConf($format, $rule, $arg1, $arg2 = null)
+ − 195
{
+ − 196
$format = ucwords(strtolower($format));
+ − 197
$rule = ucwords(strtolower($rule));
+ − 198
+ − 199
if (! isset($this->renderConf[$format])) {
+ − 200
$this->renderConf[$format] = array();
+ − 201
}
+ − 202
+ − 203
if (! isset($this->renderConf[$format][$rule])) {
+ − 204
$this->renderConf[$format][$rule] = array();
+ − 205
}
+ − 206
+ − 207
if (is_array($arg1)) {
+ − 208
$this->renderConf[$format][$rule] = $arg1;
+ − 209
} else {
+ − 210
$this->renderConf[$format][$rule][$arg1] = $arg2;
+ − 211
}
+ − 212
}
+ − 213
+ − 214
function getRenderConf($format, $rule, $key = null)
+ − 215
{
+ − 216
$format = ucwords(strtolower($format));
+ − 217
$rule = ucwords(strtolower($rule));
+ − 218
+ − 219
if (! isset($this->renderConf[$format]) ||
+ − 220
! isset($this->renderConf[$format][$rule])) {
+ − 221
return null;
+ − 222
}
+ − 223
+ − 224
if (is_null($key)) {
+ − 225
return $this->renderConf[$format][$rule];
+ − 226
}
+ − 227
+ − 228
if (isset($this->renderConf[$format][$rule][$key])) {
+ − 229
return $this->renderConf[$format][$rule][$key];
+ − 230
} else {
+ − 231
return null;
+ − 232
}
+ − 233
+ − 234
}
+ − 235
+ − 236
function setFormatConf($format, $arg1, $arg2 = null)
+ − 237
{
+ − 238
if (! is_array($this->formatConf[$format])) {
+ − 239
$this->formatConf[$format] = array();
+ − 240
}
+ − 241
+ − 242
if (is_array($arg1)) {
+ − 243
$this->formatConf[$format] = $arg1;
+ − 244
} else {
+ − 245
$this->formatConf[$format][$arg1] = $arg2;
+ − 246
}
+ − 247
}
+ − 248
+ − 249
function getFormatConf($format, $key = null)
+ − 250
{
+ − 251
if (! isset($this->formatConf[$format])) {
+ − 252
return null;
+ − 253
}
+ − 254
+ − 255
if (is_null($key)) {
+ − 256
return $this->formatConf[$format];
+ − 257
}
+ − 258
+ − 259
if (isset($this->formatConf[$format][$key])) {
+ − 260
return $this->formatConf[$format][$key];
+ − 261
} else {
+ − 262
return null;
+ − 263
}
+ − 264
}
+ − 265
+ − 266
function insertRule($name, $tgt = null)
+ − 267
{
+ − 268
$name = ucwords(strtolower($name));
+ − 269
if (! is_null($tgt)) {
+ − 270
$tgt = ucwords(strtolower($tgt));
+ − 271
}
+ − 272
if (in_array($name, $this->rules)) {
+ − 273
return null;
+ − 274
}
+ − 275
+ − 276
if (! is_null($tgt) && $tgt != '' &&
+ − 277
! in_array($tgt, $this->rules)) {
+ − 278
return false;
+ − 279
}
+ − 280
+ − 281
if (is_null($tgt)) {
+ − 282
$this->rules[] = $name;
+ − 283
return true;
+ − 284
}
+ − 285
+ − 286
if ($tgt == '') {
+ − 287
array_unshift($this->rules, $name);
+ − 288
return true;
+ − 289
}
+ − 290
+ − 291
$tmp = $this->rules;
+ − 292
$this->rules = array();
+ − 293
+ − 294
foreach ($tmp as $val) {
+ − 295
$this->rules[] = $val;
+ − 296
if ($val == $tgt) {
+ − 297
$this->rules[] = $name;
+ − 298
}
+ − 299
}
+ − 300
+ − 301
return true;
+ − 302
}
+ − 303
+ − 304
function deleteRule($name)
+ − 305
{
+ − 306
$name = ucwords(strtolower($name));
+ − 307
$key = array_search($name, $this->rules);
+ − 308
if ($key !== false) {
+ − 309
unset($this->rules[$key]);
+ − 310
}
+ − 311
}
+ − 312
+ − 313
function changeRule($old, $new)
+ − 314
{
+ − 315
$old = ucwords(strtolower($old));
+ − 316
$new = ucwords(strtolower($new));
+ − 317
$key = array_search($old, $this->rules);
+ − 318
if ($key !== false) {
+ − 319
$this->deleteRule($new);
+ − 320
$this->rules[$key] = $new;
+ − 321
}
+ − 322
}
+ − 323
+ − 324
function enableRule($name)
+ − 325
{
+ − 326
$name = ucwords(strtolower($name));
+ − 327
$key = array_search($name, $this->disable);
+ − 328
if ($key !== false) {
+ − 329
unset($this->disable[$key]);
+ − 330
}
+ − 331
}
+ − 332
+ − 333
function disableRule($name)
+ − 334
{
+ − 335
$name = ucwords(strtolower($name));
+ − 336
$key = array_search($name, $this->disable);
+ − 337
if ($key === false) {
+ − 338
$this->disable[] = $name;
+ − 339
}
+ − 340
}
+ − 341
+ − 342
function transform($text, $format = 'Xhtml')
+ − 343
{
+ − 344
$this->parse($text);
+ − 345
return $this->render($format);
+ − 346
}
+ − 347
+ − 348
function parse($text)
+ − 349
{
+ − 350
$this->source = $text;
+ − 351
+ − 352
$this->tokens = array();
+ − 353
$this->_countRulesTokens = array();
+ − 354
+ − 355
foreach ($this->rules as $name) {
+ − 356
if (! in_array($name, $this->disable)) {
+ − 357
$this->loadParseObj($name);
+ − 358
+ − 359
if (is_object($this->parseObj[$name])) {
+ − 360
$this->parseObj[$name]->parse();
+ − 361
}
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
+ − 362
// 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
+ − 363
// echo('<p>' . $name . ':</p><pre>'.htmlspecialchars($this->source).'</pre>');
1
+ − 364
}
+ − 365
}
+ − 366
}
+ − 367
+ − 368
function render($format = 'Xhtml')
+ − 369
{
+ − 370
$format = ucwords(strtolower($format));
+ − 371
+ − 372
$output = '';
+ − 373
+ − 374
$in_delim = false;
+ − 375
+ − 376
$key = '';
+ − 377
+ − 378
$result = $this->loadFormatObj($format);
+ − 379
if ($this->isError($result)) {
+ − 380
return $result;
+ − 381
}
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
+ − 382
1
+ − 383
if (is_object($this->formatObj[$format])) {
+ − 384
$output .= $this->formatObj[$format]->pre();
+ − 385
}
+ − 386
+ − 387
foreach (array_keys($this->_countRulesTokens) as $rule) {
+ − 388
$this->loadRenderObj($format, $rule);
+ − 389
}
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
+ − 390
1
+ − 391
$k = strlen($this->source);
+ − 392
for ($i = 0; $i < $k; $i++) {
+ − 393
+ − 394
$char = $this->source{$i};
+ − 395
+ − 396
if ($in_delim) {
+ − 397
+ − 398
if ($char == $this->delim) {
+ − 399
+ − 400
$key = (int)$key;
+ − 401
$rule = $this->tokens[$key][0];
+ − 402
$opts = $this->tokens[$key][1];
+ − 403
$output .= $this->renderObj[$rule]->token($opts);
+ − 404
$in_delim = false;
+ − 405
+ − 406
} else {
+ − 407
+ − 408
$key .= $char;
+ − 409
+ − 410
}
+ − 411
+ − 412
} else {
+ − 413
+ − 414
if ($char == $this->delim) {
+ − 415
$key = '';
+ − 416
$in_delim = true;
+ − 417
} else {
+ − 418
$output .= $char;
+ − 419
}
+ − 420
}
+ − 421
}
+ − 422
+ − 423
if (is_object($this->formatObj[$format])) {
+ − 424
$output .= $this->formatObj[$format]->post();
+ − 425
}
+ − 426
+ − 427
return $output;
+ − 428
}
+ − 429
+ − 430
function getSource()
+ − 431
{
+ − 432
return $this->source;
+ − 433
}
+ − 434
+ − 435
function getTokens($rules = null)
+ − 436
{
+ − 437
if (is_null($rules)) {
+ − 438
return $this->tokens;
+ − 439
} else {
+ − 440
settype($rules, 'array');
+ − 441
$result = array();
+ − 442
foreach ($this->tokens as $key => $val) {
+ − 443
if (in_array($val[0], $rules)) {
+ − 444
$result[$key] = $val;
+ − 445
}
+ − 446
}
+ − 447
return $result;
+ − 448
}
+ − 449
}
+ − 450
+ − 451
function addToken($rule, $options = array(), $id_only = false)
+ − 452
{
+ − 453
static $id;
+ − 454
if (! isset($id)) {
+ − 455
$id = 0;
+ − 456
} else {
+ − 457
$id ++;
+ − 458
}
+ − 459
+ − 460
settype($options, 'array');
+ − 461
+ − 462
$this->tokens[$id] = array(
+ − 463
0 => $rule,
+ − 464
1 => $options
+ − 465
);
+ − 466
if (!isset($this->_countRulesTokens[$rule])) {
+ − 467
$this->_countRulesTokens[$rule] = 1;
+ − 468
} else {
+ − 469
++$this->_countRulesTokens[$rule];
+ − 470
}
+ − 471
+ − 472
if ($id_only) {
+ − 473
return $id;
+ − 474
} else {
+ − 475
return $this->delim . $id . $this->delim;
+ − 476
}
+ − 477
}
+ − 478
+ − 479
function setToken($id, $rule, $options = array())
+ − 480
{
+ − 481
$oldRule = $this->tokens[$id][0];
+ − 482
$this->tokens[$id] = array(
+ − 483
0 => $rule,
+ − 484
1 => $options
+ − 485
);
+ − 486
if ($rule != $oldRule) {
+ − 487
if (!($this->_countRulesTokens[$oldRule]--)) {
+ − 488
unset($this->_countRulesTokens[$oldRule]);
+ − 489
}
+ − 490
if (!isset($this->_countRulesTokens[$rule])) {
+ − 491
$this->_countRulesTokens[$rule] = 1;
+ − 492
} else {
+ − 493
++$this->_countRulesTokens[$rule];
+ − 494
}
+ − 495
}
+ − 496
}
+ − 497
+ − 498
function loadParseObj($rule)
+ − 499
{
+ − 500
$rule = ucwords(strtolower($rule));
+ − 501
$file = $rule . '.php';
+ − 502
$class = "Text_Wiki_Parse_$rule";
+ − 503
+ − 504
if (! class_exists($class)) {
+ − 505
$loc = $this->findFile('parse', $file);
+ − 506
if ($loc) {
+ − 507
include_once $loc;
+ − 508
} else {
+ − 509
$this->parseObj[$rule] = null;
+ − 510
return $this->error(
+ − 511
"Parse rule '$rule' not found"
+ − 512
);
+ − 513
}
+ − 514
}
+ − 515
+ − 516
$this->parseObj[$rule] =& new $class($this);
+ − 517
+ − 518
}
+ − 519
+ − 520
function loadRenderObj($format, $rule)
+ − 521
{
+ − 522
$format = ucwords(strtolower($format));
+ − 523
$rule = ucwords(strtolower($rule));
+ − 524
$file = "$format/$rule.php";
+ − 525
$class = "Text_Wiki_Render_$format" . "_$rule";
+ − 526
+ − 527
if (! class_exists($class)) {
+ − 528
$loc = $this->findFile('render', $file);
+ − 529
if ($loc) {
+ − 530
include_once $loc;
+ − 531
} else {
+ − 532
return $this->error(
+ − 533
"Render rule '$rule' in format '$format' not found"
+ − 534
);
+ − 535
}
+ − 536
}
+ − 537
+ − 538
$this->renderObj[$rule] =& new $class($this);
+ − 539
}
+ − 540
+ − 541
function loadFormatObj($format)
+ − 542
{
+ − 543
$format = ucwords(strtolower($format));
+ − 544
$file = $format . '.php';
+ − 545
$class = "Text_Wiki_Render_$format";
+ − 546
+ − 547
if (! class_exists($class)) {
+ − 548
$loc = $this->findFile('render', $file);
+ − 549
if ($loc) {
+ − 550
include_once $loc;
+ − 551
} else {
+ − 552
return $this->error(
+ − 553
"Rendering format class '$class' not found"
+ − 554
);
+ − 555
}
+ − 556
}
+ − 557
+ − 558
$this->formatObj[$format] =& new $class($this);
+ − 559
}
+ − 560
+ − 561
function addPath($type, $dir)
+ − 562
{
+ − 563
$dir = $this->fixPath($dir);
+ − 564
if (! isset($this->path[$type])) {
+ − 565
$this->path[$type] = array($dir);
+ − 566
} else {
+ − 567
array_unshift($this->path[$type], $dir);
+ − 568
}
+ − 569
}
+ − 570
+ − 571
function getPath($type = null)
+ − 572
{
+ − 573
if (is_null($type)) {
+ − 574
return $this->path;
+ − 575
} elseif (! isset($this->path[$type])) {
+ − 576
return array();
+ − 577
} else {
+ − 578
return $this->path[$type];
+ − 579
}
+ − 580
}
+ − 581
+ − 582
function findFile($type, $file)
+ − 583
{
+ − 584
$set = $this->getPath($type);
+ − 585
+ − 586
foreach ($set as $path) {
+ − 587
$fullname = $path . $file;
+ − 588
if (file_exists($fullname) && is_readable($fullname)) {
+ − 589
return $fullname;
+ − 590
}
+ − 591
}
+ − 592
+ − 593
return false;
+ − 594
}
+ − 595
+ − 596
function fixPath($path)
+ − 597
{
+ − 598
$len = strlen($this->_dirSep);
+ − 599
+ − 600
if (! empty($path) &&
+ − 601
substr($path, -1 * $len, $len) != $this->_dirSep) {
+ − 602
return $path . $this->_dirSep;
+ − 603
} else {
+ − 604
return $path;
+ − 605
}
+ − 606
}
+ − 607
+ − 608
function &error($message)
+ − 609
{
+ − 610
die($message);
+ − 611
}
+ − 612
+ − 613
function isError(&$obj)
+ − 614
{
+ − 615
return is_a($obj, 'PEAR_Error');
+ − 616
}
+ − 617
}
+ − 618
+ − 619
?>