|
1 <?php |
|
2 |
|
3 /* |
|
4 * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between |
|
5 * Version 1.1.5 (Caoineag alpha 5) |
|
6 * Copyright (C) 2006-2008 Dan Fuhry |
|
7 * |
|
8 * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License |
|
9 * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. |
|
10 * |
|
11 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied |
|
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. |
|
13 */ |
|
14 |
|
15 /** |
|
16 * The default handler for namespaces. Basically fetches the page text from the database. Other namespaces should extend this class. |
|
17 * @package Enano |
|
18 * @subpackage PageHandler |
|
19 * @author Dan Fuhry <dan@enanocms.org> |
|
20 * @license GNU General Public License <http://www.gnu.org/licenses/gpl-2.0.html> |
|
21 */ |
|
22 |
|
23 class Namespace_Default |
|
24 { |
|
25 /** |
|
26 * Page ID |
|
27 * @var string |
|
28 */ |
|
29 |
|
30 public $page_id; |
|
31 |
|
32 /** |
|
33 * Namespace |
|
34 * @var string |
|
35 */ |
|
36 |
|
37 public $namespace; |
|
38 |
|
39 /** |
|
40 * Local copy of the page text |
|
41 */ |
|
42 |
|
43 public $text_cache; |
|
44 |
|
45 /** |
|
46 * Revision ID to send. If 0, the latest revision. |
|
47 * @var int |
|
48 */ |
|
49 |
|
50 public $revision_id = 0; |
|
51 |
|
52 /** |
|
53 * Tracks whether the page exists |
|
54 * @var bool |
|
55 */ |
|
56 |
|
57 public $exists = false; |
|
58 |
|
59 /** |
|
60 * Page title |
|
61 * @var string |
|
62 */ |
|
63 |
|
64 public $title = ''; |
|
65 |
|
66 /** |
|
67 * Constructor. |
|
68 */ |
|
69 |
|
70 public function __construct($page_id, $namespace, $revision_id = 0) |
|
71 { |
|
72 global $db, $session, $paths, $template, $plugins; // Common objects |
|
73 |
|
74 $this->page_id = sanitize_page_id($page_id); |
|
75 $this->namespace = $namespace; |
|
76 $this->revision_id = intval($revision_id); |
|
77 |
|
78 // only do this if calling from the (very heavily feature filled) abstract |
|
79 // this will still be called if you're using your own handler but not replacing the constructor |
|
80 if ( __CLASS__ == 'Namespace_Default' ) |
|
81 { |
|
82 $this->exists = false; |
|
83 // NOTE! These should already be WELL sanitized before we reach this stage. |
|
84 $q = $db->sql_query('SELECT name FROM ' . table_prefix . "pages WHERE urlname = '$this->page_id' AND namespace = '$this->namespace';"); |
|
85 if ( !$q ) |
|
86 $db->_die(); |
|
87 |
|
88 if ( $db->numrows() < 1 ) |
|
89 { |
|
90 // we still have a chance... some older databases don't do dots in the page title right |
|
91 if ( strstr(dirtify_page_id($this->page_id), '.') ) |
|
92 { |
|
93 $page_id = str_replace('.', '.2e', $page_id); |
|
94 |
|
95 $q = $db->sql_query('SELECT name FROM ' . table_prefix . "pages WHERE urlname = '$page_id' AND namespace = '$this->namespace';"); |
|
96 if ( !$q ) |
|
97 $db->_die(); |
|
98 |
|
99 if ( $db->numrows() < 1 ) |
|
100 { |
|
101 $this->title = $paths->nslist[$namespace] . dirtify_page_id($page_id); |
|
102 } |
|
103 else |
|
104 { |
|
105 list($this->title) = $db->fetchrow_num(); |
|
106 $this->exists = true; |
|
107 $this->page_id = $page_id; |
|
108 } |
|
109 } |
|
110 else |
|
111 { |
|
112 $this->title = $paths->nslist[$namespace] . dirtify_page_id($page_id); |
|
113 } |
|
114 } |
|
115 else |
|
116 { |
|
117 list($this->title) = $db->fetchrow_num(); |
|
118 $this->exists = true; |
|
119 } |
|
120 $db->free_result(); |
|
121 } |
|
122 } |
|
123 |
|
124 /** |
|
125 * Pulls the page's actual text from the database. |
|
126 */ |
|
127 |
|
128 function fetch_text() |
|
129 { |
|
130 global $db, $session, $paths, $template, $plugins; // Common objects |
|
131 |
|
132 if ( !empty($this->text_cache) ) |
|
133 { |
|
134 return $this->text_cache; |
|
135 } |
|
136 |
|
137 if ( $this->revision_id > 0 && is_int($this->revision_id) ) |
|
138 { |
|
139 |
|
140 $q = $db->sql_query('SELECT page_text, char_tag, time_id FROM '.table_prefix.'logs WHERE log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $this->page_id . '\' AND namespace=\'' . $this->namespace . '\' AND log_id=' . $this->revision_id . ';'); |
|
141 if ( !$q ) |
|
142 { |
|
143 $this->send_error('Error during SQL query.', true); |
|
144 } |
|
145 if ( $db->numrows() < 1 ) |
|
146 { |
|
147 // Compatibility fix for old pages with dots in the page ID |
|
148 if ( strstr($this->page_id, '.2e') ) |
|
149 { |
|
150 $db->free_result(); |
|
151 $page_id = str_replace('.2e', '.', $this->page_id); |
|
152 $q = $db->sql_query('SELECT page_text, char_tag, time_id FROM '.table_prefix.'logs WHERE log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $this->namespace . '\' AND log_id=' . $this->revision_id . ';'); |
|
153 if ( !$q ) |
|
154 { |
|
155 $this->send_error('Error during SQL query.', true); |
|
156 } |
|
157 if ( $db->numrows() < 1 ) |
|
158 { |
|
159 $this->page_exists = false; |
|
160 return 'err_no_text_rows'; |
|
161 } |
|
162 } |
|
163 else |
|
164 { |
|
165 $this->page_exists = false; |
|
166 return 'err_no_text_rows'; |
|
167 } |
|
168 } |
|
169 else |
|
170 { |
|
171 $row = $db->fetchrow(); |
|
172 } |
|
173 |
|
174 $db->free_result(); |
|
175 |
|
176 } |
|
177 else |
|
178 { |
|
179 $q = $db->sql_query('SELECT t.page_text, t.char_tag, l.time_id FROM '.table_prefix."page_text AS t\n" |
|
180 . " LEFT JOIN " . table_prefix . "logs AS l\n" |
|
181 . " ON ( l.page_id = t.page_id AND l.namespace = t.namespace )\n" |
|
182 . " WHERE t.page_id='$this->page_id' AND t.namespace='$this->namespace'\n" |
|
183 . " ORDER BY l.time_id DESC LIMIT 1;"); |
|
184 if ( !$q ) |
|
185 { |
|
186 $this->send_error('Error during SQL query.', true); |
|
187 } |
|
188 if ( $db->numrows() < 1 ) |
|
189 { |
|
190 // Compatibility fix for old pages with dots in the page ID |
|
191 if ( strstr($this->page_id, '.2e') ) |
|
192 { |
|
193 $db->free_result(); |
|
194 $page_id = str_replace('.2e', '.', $this->page_id); |
|
195 $q = $db->sql_query('SELECT page_text, char_tag FROM '.table_prefix.'page_text WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $this->namespace . '\';'); |
|
196 if ( !$q ) |
|
197 { |
|
198 $this->send_error('Error during SQL query.', true); |
|
199 } |
|
200 if ( $db->numrows() < 1 ) |
|
201 { |
|
202 $this->page_exists = false; |
|
203 return 'err_no_text_rows'; |
|
204 } |
|
205 } |
|
206 else |
|
207 { |
|
208 $this->page_exists = false; |
|
209 return 'err_no_text_rows'; |
|
210 } |
|
211 } |
|
212 |
|
213 $row = $db->fetchrow(); |
|
214 $db->free_result(); |
|
215 |
|
216 } |
|
217 |
|
218 if ( !empty($row['char_tag']) ) |
|
219 { |
|
220 // This page text entry uses the old text-escaping format |
|
221 $from = array( |
|
222 "{APOS:{$row['char_tag']}}", |
|
223 "{QUOT:{$row['char_tag']}}", |
|
224 "{SLASH:{$row['char_tag']}}" |
|
225 ); |
|
226 $to = array("'", '"', '\\'); |
|
227 $row['page_text'] = str_replace($from, $to, $row['page_text']); |
|
228 } |
|
229 |
|
230 $this->text_cache = $row['page_text']; |
|
231 |
|
232 if ( isset($row['time_id']) ) |
|
233 { |
|
234 $this->revision_time = intval($row['time_id']); |
|
235 } |
|
236 |
|
237 return $row['page_text']; |
|
238 } |
|
239 |
|
240 /** |
|
241 * Send the page. |
|
242 */ |
|
243 |
|
244 public function send() |
|
245 { |
|
246 global $db, $session, $paths, $template, $plugins; // Common objects |
|
247 global $output; |
|
248 |
|
249 $output->add_before_footer($this->display_categories()); |
|
250 |
|
251 if ( $this->exists ) |
|
252 $this->send_from_db(); |
|
253 else |
|
254 { |
|
255 // This is the DEPRECATED way to extend namespaces. It's left in only for compatibility with older plugins. |
|
256 ob_start(); |
|
257 $code = $plugins->setHook('page_not_found'); |
|
258 foreach ( $code as $cmd ) |
|
259 { |
|
260 eval($cmd); |
|
261 } |
|
262 $c = ob_get_contents(); |
|
263 if ( !empty($c) ) |
|
264 { |
|
265 ob_end_clean(); |
|
266 echo $c; |
|
267 } |
|
268 else |
|
269 { |
|
270 $output->header(); |
|
271 $this->error_404(); |
|
272 $output->footer(); |
|
273 } |
|
274 } |
|
275 } |
|
276 |
|
277 /** |
|
278 * The "real" send-the-page function. The reason for this is so other namespaces can re-use the code |
|
279 * to fetch the page from the DB while being able to install their own wrappers. |
|
280 */ |
|
281 |
|
282 public function send_from_db($incl_inner_headers = true, $send_headers = true) |
|
283 { |
|
284 global $db, $session, $paths, $template, $plugins; // Common objects |
|
285 global $lang; |
|
286 global $output; |
|
287 |
|
288 $text = $this->fetch_text(); |
|
289 |
|
290 $text = preg_replace('/([\s]*)__NOBREADCRUMBS__([\s]*)/', '', $text); |
|
291 $text = preg_replace('/([\s]*)__NOTOC__([\s]*)/', '', $text); |
|
292 |
|
293 $redir_enabled = false; |
|
294 if ( preg_match('/^#redirect \[\[([^\]]+?)\]\]/i', $text, $match ) ) |
|
295 { |
|
296 $redir_enabled = true; |
|
297 |
|
298 $oldtarget = RenderMan::strToPageID($match[1]); |
|
299 $oldtarget[0] = sanitize_page_id($oldtarget[0]); |
|
300 |
|
301 $url = makeUrlNS($oldtarget[1], $oldtarget[0], false, true); |
|
302 $page_id_key = $paths->nslist[ $oldtarget[1] ] . $oldtarget[0]; |
|
303 $page_data = $paths->pages[$page_id_key]; |
|
304 $title = ( isset($page_data['name']) ) ? $page_data['name'] : $paths->nslist[$oldtarget[1]] . htmlspecialchars( str_replace('_', ' ', dirtify_page_id( $oldtarget[0] ) ) ); |
|
305 if ( !isset($page_data['name']) ) |
|
306 { |
|
307 $cls = 'class="wikilink-nonexistent"'; |
|
308 } |
|
309 else |
|
310 { |
|
311 $cls = ''; |
|
312 } |
|
313 $a = '<a ' . $cls . ' href="' . $url . '">' . $title . '</a>'; |
|
314 $redir_html = '<br /><div class="mdg-infobox"> |
|
315 <table border="0" width="100%" cellspacing="0" cellpadding="0"> |
|
316 <tr> |
|
317 <td valign="top"> |
|
318 <img alt="Cute wet-floor icon" src="'.scriptPath.'/images/redirector.png" /> |
|
319 </td> |
|
320 <td valign="top" style="padding-left: 10px;"> |
|
321 ' . $lang->get('page_msg_this_is_a_redirector', array( 'redirect_target' => $a )) . ' |
|
322 </td> |
|
323 </tr> |
|
324 </table> |
|
325 </div> |
|
326 <br /> |
|
327 <hr style="margin-left: 1em; width: 200px;" />'; |
|
328 $text = str_replace($match[0], '', $text); |
|
329 $text = trim($text); |
|
330 } |
|
331 |
|
332 if ( $send_headers ) |
|
333 { |
|
334 $output->set_title($this->title); |
|
335 $output->header(); |
|
336 } |
|
337 $this->do_breadcrumbs(); |
|
338 |
|
339 if ( $incl_inner_headers ) |
|
340 { |
|
341 display_page_headers(); |
|
342 } |
|
343 |
|
344 if ( $this->revision_id ) |
|
345 { |
|
346 echo '<div class="info-box" style="margin-left: 0; margin-top: 5px;"> |
|
347 <b>' . $lang->get('page_msg_archived_title') . '</b><br /> |
|
348 ' . $lang->get('page_msg_archived_body', array( |
|
349 'archive_date' => enano_date('F d, Y', $this->revision_time), |
|
350 'archive_time' => enano_date('h:i a', $this->revision_time), |
|
351 'current_link' => makeUrlNS($this->namespace, $this->page_id), |
|
352 'restore_link' => makeUrlNS($this->namespace, $this->page_id, 'do=edit&revid='.$this->revision_id), |
|
353 'restore_onclick' => 'ajaxEditor(\''.$this->revision_id.'\'); return false;', |
|
354 )) . ' |
|
355 </div>'; |
|
356 } |
|
357 |
|
358 if ( $redir_enabled ) |
|
359 { |
|
360 echo $redir_html; |
|
361 } |
|
362 |
|
363 $code = $plugins->setHook('pageprocess_render_head'); |
|
364 foreach ( $code as $cmd ) |
|
365 { |
|
366 eval($cmd); |
|
367 } |
|
368 |
|
369 if ( $incl_inner_headers ) |
|
370 { |
|
371 $text = '?>' . RenderMan::render($text); |
|
372 } |
|
373 else |
|
374 { |
|
375 $text = '?>' . $text; |
|
376 $text = preg_replace('/<nowiki>(.*?)<\/nowiki>/s', '\\1', $text); |
|
377 } |
|
378 |
|
379 eval ( $text ); |
|
380 |
|
381 $code = $plugins->setHook('pageprocess_render_tail'); |
|
382 foreach ( $code as $cmd ) |
|
383 { |
|
384 eval($cmd); |
|
385 } |
|
386 |
|
387 if ( $incl_inner_headers ) |
|
388 { |
|
389 display_page_footers(); |
|
390 } |
|
391 |
|
392 if ( $send_headers ) |
|
393 $output->footer(); |
|
394 } |
|
395 |
|
396 /** |
|
397 * Echoes out breadcrumb data, if appropriate. |
|
398 * @access private |
|
399 */ |
|
400 |
|
401 function do_breadcrumbs() |
|
402 { |
|
403 global $db, $session, $paths, $template, $plugins; // Common objects |
|
404 global $lang; |
|
405 |
|
406 if ( strpos($this->text_cache, '__NOBREADCRUMBS__') !== false ) |
|
407 return false; |
|
408 |
|
409 $mode = getConfig('breadcrumb_mode'); |
|
410 |
|
411 if ( $mode == 'never' ) |
|
412 // Breadcrumbs are disabled |
|
413 return true; |
|
414 |
|
415 // Minimum depth for breadcrumb display |
|
416 $threshold = ( $mode == 'always' ) ? 0 : 1; |
|
417 |
|
418 $breadcrumb_data = explode('/', $this->page_id); |
|
419 if ( count($breadcrumb_data) > $threshold ) |
|
420 { |
|
421 // If we're not on a subpage of the main page, add "Home" to the list |
|
422 $show_home = false; |
|
423 if ( $mode == 'always' ) |
|
424 { |
|
425 $show_home = true; |
|
426 } |
|
427 echo '<!-- Start breadcrumbs --> |
|
428 <div class="breadcrumbs"> |
|
429 '; |
|
430 if ( $show_home ) |
|
431 { |
|
432 // Display the "home" link first. |
|
433 $pathskey = $paths->nslist[ $this->namespace ] . $this->page_id; |
|
434 if ( $pathskey !== get_main_page() ) |
|
435 echo '<a href="' . makeUrl(get_main_page(), false, true) . '">'; |
|
436 echo $lang->get('onpage_btn_breadcrumbs_home'); |
|
437 if ( $pathskey !== get_main_page() ) |
|
438 echo '</a>'; |
|
439 } |
|
440 foreach ( $breadcrumb_data as $i => $crumb ) |
|
441 { |
|
442 $cumulative = implode('/', array_slice($breadcrumb_data, 0, ( $i + 1 ))); |
|
443 if ( $show_home && $cumulative === get_main_page() ) |
|
444 continue; |
|
445 if ( $show_home || $i > 0 ) |
|
446 echo ' » '; |
|
447 $title = ( isPage($cumulative) ) ? get_page_title($cumulative) : get_page_title($crumb); |
|
448 if ( $i + 1 == count($breadcrumb_data) ) |
|
449 { |
|
450 echo htmlspecialchars($title); |
|
451 } |
|
452 else |
|
453 { |
|
454 $exists = ( isPage($cumulative) ) ? '' : ' class="wikilink-nonexistent"'; |
|
455 echo '<a href="' . makeUrl($cumulative, false, true) . '"' . $exists . '>' . htmlspecialchars($title) . '</a>'; |
|
456 } |
|
457 } |
|
458 echo '</div> |
|
459 <!-- End breadcrumbs --> |
|
460 '; |
|
461 } |
|
462 } |
|
463 |
|
464 public function error_404($userpage = false) |
|
465 { |
|
466 global $db, $session, $paths, $template, $plugins; // Common objects |
|
467 global $lang, $output; |
|
468 |
|
469 @header('HTTP/1.1 404 Not Found'); |
|
470 |
|
471 $msg = ( $pp = $paths->sysmsg('Page_not_found') ) ? $pp : '{STANDARD404}'; |
|
472 |
|
473 $standard_404 = ''; |
|
474 |
|
475 if ( $userpage ) |
|
476 { |
|
477 $standard_404 .= '<h3>' . $lang->get('page_msg_404_title_userpage') . '</h3> |
|
478 <p>' . $lang->get('page_msg_404_body_userpage'); |
|
479 } |
|
480 else |
|
481 { |
|
482 $standard_404 .= '<h3>' . $lang->get('page_msg_404_title') . '</h3> |
|
483 <p>' . $lang->get('page_msg_404_body'); |
|
484 } |
|
485 if ( $session->get_permissions('create_page') ) |
|
486 { |
|
487 $standard_404 .= ' ' . $lang->get('page_msg_404_create', array( |
|
488 'create_flags' => 'href="'.makeUrlNS($this->namespace, $this->page_id, 'do=edit', true).'" onclick="ajaxEditor(); return false;"', |
|
489 'mainpage_link' => makeUrl(get_main_page(), false, true) |
|
490 )); |
|
491 } |
|
492 else |
|
493 { |
|
494 $standard_404 .= ' ' . $lang->get('page_msg_404_gohome', array( |
|
495 'mainpage_link' => makeUrl(get_main_page(), false, true) |
|
496 )); |
|
497 } |
|
498 $standard_404 .= '</p>'; |
|
499 if ( $session->get_permissions('history_rollback') ) |
|
500 { |
|
501 $e = $db->sql_query('SELECT * FROM ' . table_prefix . 'logs WHERE action=\'delete\' AND page_id=\'' . $this->page_id . '\' AND namespace=\'' . $this->namespace . '\' ORDER BY time_id DESC;'); |
|
502 if ( !$e ) |
|
503 { |
|
504 $db->_die('The deletion log could not be selected.'); |
|
505 } |
|
506 if ( $db->numrows() > 0 ) |
|
507 { |
|
508 $r = $db->fetchrow(); |
|
509 $standard_404 .= '<p>' . $lang->get('page_msg_404_was_deleted', array( |
|
510 'delete_time' => enano_date('d M Y h:i a', $r['time_id']), |
|
511 'delete_reason' => htmlspecialchars($r['edit_summary']), |
|
512 'rollback_flags' => 'href="'.makeUrl($paths->page, 'do=rollback&id='.$r['log_id']).'" onclick="ajaxRollback(\''.$r['log_id'].'\'); return false;"' |
|
513 )) |
|
514 . '</p>'; |
|
515 if ( $session->user_level >= USER_LEVEL_ADMIN ) |
|
516 { |
|
517 $standard_404 .= '<p>' . $lang->get('page_msg_404_admin_opts', array( |
|
518 'detag_link' => makeUrl($paths->page, 'do=detag', true) |
|
519 )) |
|
520 . '</p>'; |
|
521 } |
|
522 } |
|
523 $db->free_result(); |
|
524 } |
|
525 $standard_404 .= '<p> |
|
526 ' . $lang->get('page_msg_404_http_response') . ' |
|
527 </p>'; |
|
528 |
|
529 $parser = $template->makeParserText($msg); |
|
530 $parser->assign_vars(array( |
|
531 'STANDARD404' => $standard_404 |
|
532 )); |
|
533 |
|
534 $msg = RenderMan::render($parser->run()); |
|
535 eval( '?>' . $msg ); |
|
536 } |
|
537 |
|
538 /** |
|
539 * Display the categories a page is in. If the current page is a category, its contents will also be printed. |
|
540 */ |
|
541 |
|
542 function display_categories() |
|
543 { |
|
544 global $db, $session, $paths, $template, $plugins; // Common objects |
|
545 global $lang; |
|
546 |
|
547 $html = ''; |
|
548 |
|
549 if ( $this->namespace == 'Category' ) |
|
550 { |
|
551 // Show member pages and subcategories |
|
552 $q = $db->sql_query('SELECT p.urlname, p.namespace, p.name, p.namespace=\'Category\' AS is_category FROM '.table_prefix.'categories AS c |
|
553 LEFT JOIN '.table_prefix.'pages AS p |
|
554 ON ( p.urlname = c.page_id AND p.namespace = c.namespace ) |
|
555 WHERE c.category_id=\'' . $db->escape($this->page_id) . '\' |
|
556 ORDER BY is_category DESC, p.name ASC;'); |
|
557 if ( !$q ) |
|
558 { |
|
559 $db->_die(); |
|
560 } |
|
561 $html .= '<h3>' . $lang->get('onpage_cat_heading_subcategories') . '</h3>'; |
|
562 $html .= '<div class="tblholder">'; |
|
563 $html .= '<table border="0" cellspacing="1" cellpadding="4">'; |
|
564 $html .= '<tr>'; |
|
565 $ticker = 0; |
|
566 $counter = 0; |
|
567 $switched = false; |
|
568 $class = 'row1'; |
|
569 while ( $row = $db->fetchrow() ) |
|
570 { |
|
571 if ( $row['is_category'] == 0 && !$switched ) |
|
572 { |
|
573 if ( $counter > 0 ) |
|
574 { |
|
575 // Fill-in |
|
576 while ( $ticker < 3 ) |
|
577 { |
|
578 $ticker++; |
|
579 $html .= '<td class="' . $class . '" style="width: 33.3%;"></td>'; |
|
580 } |
|
581 } |
|
582 else |
|
583 { |
|
584 $html .= '<td class="' . $class . '">' . $lang->get('onpage_cat_msg_no_subcategories') . '</td>'; |
|
585 } |
|
586 $html .= '</tr></table></div>' . "\n\n"; |
|
587 $html .= '<h3>' . $lang->get('onpage_cat_heading_pages') . '</h3>'; |
|
588 $html .= '<div class="tblholder">'; |
|
589 $html .= '<table border="0" cellspacing="1" cellpadding="4">'; |
|
590 $html .= '<tr>'; |
|
591 $counter = 0; |
|
592 $ticker = -1; |
|
593 $switched = true; |
|
594 } |
|
595 $counter++; |
|
596 $ticker++; |
|
597 if ( $ticker == 3 ) |
|
598 { |
|
599 $html .= '</tr><tr>'; |
|
600 $ticker = 0; |
|
601 $class = ( $class == 'row3' ) ? 'row1' : 'row3'; |
|
602 } |
|
603 $html .= "<td class=\"{$class}\" style=\"width: 33.3%;\">"; // " to workaround stupid jEdit bug |
|
604 |
|
605 $link = makeUrlNS($row['namespace'], sanitize_page_id($row['urlname'])); |
|
606 $html .= '<a href="' . $link . '"'; |
|
607 $key = $paths->nslist[$row['namespace']] . sanitize_page_id($row['urlname']); |
|
608 if ( !isPage( $key ) ) |
|
609 { |
|
610 $html .= ' class="wikilink-nonexistent"'; |
|
611 } |
|
612 $html .= '>'; |
|
613 $title = get_page_title_ns($row['urlname'], $row['namespace']); |
|
614 $html .= htmlspecialchars($title); |
|
615 $html .= '</a>'; |
|
616 |
|
617 $html .= "</td>"; |
|
618 } |
|
619 if ( !$switched ) |
|
620 { |
|
621 if ( $counter > 0 ) |
|
622 { |
|
623 // Fill-in |
|
624 while ( $ticker < 2 ) |
|
625 { |
|
626 $ticker++; |
|
627 $html .= '<td class="' . $class . '" style="width: 33.3%;"></td>'; |
|
628 } |
|
629 } |
|
630 else |
|
631 { |
|
632 $html .= '<td class="' . $class . '">' . $lang->get('onpage_cat_msg_no_subcategories') . '</td>'; |
|
633 } |
|
634 $html .= '</tr></table></div>' . "\n\n"; |
|
635 $html .= '<h3>' . $lang->get('onpage_cat_heading_pages') . '</h3>'; |
|
636 $html .= '<div class="tblholder">'; |
|
637 $html .= '<table border="0" cellspacing="1" cellpadding="4">'; |
|
638 $html .= '<tr>'; |
|
639 $counter = 0; |
|
640 $ticker = 0; |
|
641 $switched = true; |
|
642 } |
|
643 if ( $counter > 0 ) |
|
644 { |
|
645 // Fill-in |
|
646 while ( $ticker < 2 ) |
|
647 { |
|
648 $ticker++; |
|
649 $html .= '<td class="' . $class . '" style="width: 33.3%;"></td>'; |
|
650 } |
|
651 } |
|
652 else |
|
653 { |
|
654 $html .= '<td class="' . $class . '">' . $lang->get('onpage_cat_msg_no_pages') . '</td>'; |
|
655 } |
|
656 $html .= '</tr></table></div>' . "\n\n"; |
|
657 } |
|
658 |
|
659 if ( $this->namespace != 'Special' && $this->namespace != 'Admin' ) |
|
660 { |
|
661 $html .= '<div class="mdg-comment" style="margin: 10px 0 0 0;" id="category_box_wrapper">'; |
|
662 $html .= '<div style="float: right;">'; |
|
663 $html .= '(<a href="#" onclick="ajaxCatToTag(); return false;">' . $lang->get('tags_catbox_link') . '</a>)'; |
|
664 $html .= '</div>'; |
|
665 $html .= '<div id="mdgCatBox">' . $lang->get('catedit_catbox_lbl_categories') . ' '; |
|
666 |
|
667 $where = '( c.page_id=\'' . $db->escape($this->page_id) . '\' AND c.namespace=\'' . $db->escape($this->namespace) . '\' )'; |
|
668 $prefix = table_prefix; |
|
669 $sql = <<<EOF |
|
670 SELECT c.category_id FROM {$prefix}categories AS c |
|
671 LEFT JOIN {$prefix}pages AS p |
|
672 ON ( ( p.urlname = c.page_id AND p.namespace = c.namespace ) OR ( p.urlname IS NULL AND p.namespace IS NULL ) ) |
|
673 WHERE $where |
|
674 ORDER BY p.name ASC, c.page_id ASC; |
|
675 EOF; |
|
676 $q = $db->sql_query($sql); |
|
677 if ( !$q ) |
|
678 $db->_die(); |
|
679 |
|
680 if ( $row = $db->fetchrow() ) |
|
681 { |
|
682 $list = array(); |
|
683 do |
|
684 { |
|
685 $cid = sanitize_page_id($row['category_id']); |
|
686 $title = get_page_title_ns($cid, 'Category'); |
|
687 $link = makeUrlNS('Category', $cid); |
|
688 $list[] = '<a href="' . $link . '">' . htmlspecialchars($title) . '</a>'; |
|
689 } |
|
690 while ( $row = $db->fetchrow() ); |
|
691 $html .= implode(', ', $list); |
|
692 } |
|
693 else |
|
694 { |
|
695 $html .= $lang->get('catedit_catbox_lbl_uncategorized'); |
|
696 } |
|
697 |
|
698 $can_edit = ( $session->get_permissions('edit_cat') && ( !$paths->page_protected || $session->get_permissions('even_when_protected') ) ); |
|
699 if ( $can_edit ) |
|
700 { |
|
701 $edit_link = '<a href="' . makeUrl($paths->page, 'do=catedit', true) . '" onclick="ajaxCatEdit(); return false;">' . $lang->get('catedit_catbox_link_edit') . '</a>'; |
|
702 $html .= ' [ ' . $edit_link . ' ]'; |
|
703 } |
|
704 |
|
705 $html .= '</div></div>'; |
|
706 } |
|
707 return $html; |
|
708 } |
|
709 /** |
|
710 * Just tell us if the current page exists or not. |
|
711 * @return bool |
|
712 */ |
|
713 |
|
714 function exists() |
|
715 { |
|
716 return $this->exists; |
|
717 } |
|
718 } |
|
719 |
|
720 /** |
|
721 * The namespaces that use the default handler. |
|
722 */ |
|
723 |
|
724 class Namespace_Article extends Namespace_Default |
|
725 { |
|
726 } |
|
727 |
|
728 class Namespace_Project extends Namespace_Default |
|
729 { |
|
730 } |
|
731 |
|
732 class Namespace_Help extends Namespace_Default |
|
733 { |
|
734 } |
|
735 |