PageRenderTime 54ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/html/AppCode/expressionengine/modules/wiki/mod.wiki.php

https://github.com/w3bg/www.hsifin.com
PHP | 6074 lines | 5015 code | 575 blank | 484 comment | 387 complexity | 7f10bbf7bb9ad73c18dd5b361923102e MD5 | raw file
Possible License(s): AGPL-3.0
  1. <?php
  2. /*
  3. =====================================================
  4. ExpressionEngine - by EllisLab
  5. -----------------------------------------------------
  6. http://expressionengine.com/
  7. -----------------------------------------------------
  8. Copyright (c) 2003 - 2010, EllisLab, Inc.
  9. =====================================================
  10. THIS IS COPYRIGHTED SOFTWARE
  11. PLEASE READ THE LICENSE AGREEMENT
  12. http://expressionengine.com/user_guide/license.html
  13. =====================================================
  14. File: mod.wiki.php
  15. -----------------------------------------------------
  16. Purpose: Wiki class
  17. =====================================================
  18. */
  19. if ( ! defined('EXT'))
  20. {
  21. exit('Invalid file request');
  22. }
  23. class Wiki {
  24. var $version = '1.2';
  25. var $base_path = '';
  26. var $profile_path = '';
  27. var $base_url = '';
  28. var $seg_parts = array();
  29. var $admins = array('1');
  30. var $users = array('1', '5');
  31. var $conditionals = array();
  32. var $title = '';
  33. var $topic = '';
  34. var $revision_id = '';
  35. var $theme_path = '';
  36. var $theme_url = '';
  37. var $image_url = '';
  38. // Namespaces
  39. var $main_ns = 'Main';
  40. var $special_ns = 'Special'; // Deutsch: Spezial
  41. var $file_ns = 'File';
  42. var $category_ns = 'Category'; // Deutsch: Kategorie
  43. var $image_ns = 'Image';
  44. var $current_namespace = '';
  45. var $namespaces = array();
  46. // Settings
  47. var $wiki_id = 1;
  48. var $label_name = 'EE Wiki';
  49. var $use_captchas = 'n';
  50. var $text_format = 'xhtml';
  51. var $html_format = 'safe';
  52. var $auto_links = "n";
  53. var $upload_dir = '';
  54. var $valid_upload_dir = 'n';
  55. var $can_upload = 'n';
  56. var $moderation_emails = '';
  57. var $revision_limit = 100;
  58. var $author_limit = 75;
  59. var $min_length_keywords = 3;
  60. var $cats_separator = '::';
  61. var $cats_display_separator = ' -> ';
  62. var $cats_use_namespaces = 'n';
  63. var $cats_assign_parents = 'y';
  64. // Category Retrieval
  65. var $temp_array = array();
  66. var $cat_array = array();
  67. var $show_these = FALSE;
  68. var $cat_depth = 0;
  69. var $parent_cats = array();
  70. // Pagination variables
  71. var $paginate = FALSE;
  72. var $pagination_links = '';
  73. var $page_next = '';
  74. var $page_previous = '';
  75. var $current_page = 1;
  76. var $total_pages = 1;
  77. var $total_rows = 0;
  78. var $p_limit = '';
  79. var $p_page = '';
  80. var $pagination_sql = '';
  81. var $return_data = '';
  82. /** ----------------------------------------
  83. /** Constructor
  84. /** ----------------------------------------*/
  85. function Wiki($return = FALSE)
  86. {
  87. // Make a local reference to the ExpressionEngine super object
  88. $this->EE =& get_instance();
  89. if ($return === TRUE)
  90. {
  91. return;
  92. }
  93. $this->EE->lang->loadfile('wiki');
  94. /** ----------------------------------------
  95. /** Update Module Code
  96. /** ----------------------------------------*/
  97. if (isset($this->EE->TMPL->module_data['Wiki']['version']) && $this->version > $this->EE->TMPL->module_data['Wiki']['version'])
  98. {
  99. $this->update_module($this->EE->TMPL->module_data['Wiki']['version']);
  100. }
  101. /* ----------------------------------------
  102. /*
  103. /* There are five main kinds of pages in the ExpressionEngine Wiki:
  104. /*
  105. /* - Main/Index
  106. /* - Article Page (Including Namespaces)
  107. /* - Edit Topic Page
  108. /* - History Topic Page
  109. /* - Special Page (ex: Uploads, Search Results, Recent Changes)
  110. /*
  111. /* Now, the {exp:wiki} tag will be put into a template group
  112. /* and a template, which is set in base_path="" so that
  113. /* we can discover the structure of the URLs and what segments
  114. /* to read for what.
  115. /* ----------------------------------------*/
  116. if (($this->base_path = $this->EE->TMPL->fetch_param('base_path')) === FALSE)
  117. {
  118. return $this->return_data = $this->EE->lang->line('basepath_unset');
  119. }
  120. $this->base_path = rtrim($this->base_path, '/').'/';
  121. $this->base_url = $this->EE->functions->create_url($this->base_path).'/';
  122. /* ----------------------------------------
  123. Creating this array once is very useful and since I do my sanitization
  124. again here as well as in the Input class, I am sure that the
  125. segments are clean and ready to use on a page.
  126. /* ----------------------------------------*/
  127. $x = explode('/', $this->base_path);
  128. $this->seg_parts = explode('/', $this->EE->security->xss_clean(strip_tags(stripslashes($this->EE->uri->query_string))));
  129. /* ----------------------------------------
  130. Fixes a minor bug in ExpressionEngine where the QSTR variable
  131. has the template name included when there is no third segment
  132. on a non-index template - Paul
  133. /* ----------------------------------------*/
  134. if (isset($x['1']))
  135. {
  136. if ($this->seg_parts['0'] == $x['1'])
  137. {
  138. array_shift($this->seg_parts);
  139. }
  140. }
  141. /** ----------------------------------------
  142. /** Preferences and Language
  143. /** ----------------------------------------*/
  144. if ($this->EE->TMPL->fetch_param('wiki') !== FALSE)
  145. {
  146. $query = $this->EE->db->query("SELECT * FROM exp_wikis WHERE wiki_short_name = '".$this->EE->db->escape_str($this->EE->TMPL->fetch_param('wiki'))."'");
  147. }
  148. else
  149. {
  150. $query = $this->EE->db->query("SELECT * FROM exp_wikis WHERE wiki_short_name = 'default_wiki'");
  151. }
  152. if ($query->num_rows() == 0)
  153. {
  154. return $this->return_data = 'No Valid Wiki Specified';
  155. }
  156. foreach($query->row_array() as $field => $value)
  157. {
  158. if ($field != 'wiki_id')
  159. {
  160. $field = substr($field, 5);
  161. }
  162. if ($field == 'users' OR $field == 'admins')
  163. {
  164. $value = explode('|', $value);
  165. }
  166. $this->{$field} = $value;
  167. }
  168. /** ------------------------------------
  169. /** Retrieve Our Namespaces
  170. /** ------------------------------------*/
  171. $namespace_query = $this->EE->db->query("SELECT * FROM exp_wiki_namespaces WHERE wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."' ORDER BY namespace_name");
  172. if ($namespace_query->num_rows() > 0)
  173. {
  174. foreach($namespace_query->result_array() as $row)
  175. {
  176. $this->namespaces[strtolower($row['namespace_name'])] = array($row['namespace_name'], $row['namespace_label']);
  177. if (isset($this->seg_parts['0']) && strcasecmp($this->prep_title(substr($this->seg_parts['0'], 0, strlen($row['namespace_label'].':'))), $row['namespace_label'].':') == 0)
  178. {
  179. $this->admins = explode('|', $row['namespace_admins']);
  180. $this->users = explode('|', $row['namespace_users']);
  181. }
  182. }
  183. }
  184. if ($this->EE->TMPL->fetch_param('profile_path') !== FALSE)
  185. {
  186. $this->profile_path = $this->EE->functions->remove_double_slashes('/'.$this->EE->TMPL->fetch_param('profile_path').'/'.$this->EE->config->item('profile_trigger').'/');
  187. }
  188. else
  189. {
  190. $this->profile_path = $this->EE->functions->remove_double_slashes('/'.$this->EE->config->item('profile_trigger').'/');
  191. }
  192. /** ----------------------------------------
  193. /** Namespaces Localization
  194. /** ----------------------------------------*/
  195. $this->main_ns = (isset($this->EE->lang->language['main_ns'])) ? $this->EE->lang->line('main_ns') : $this->main_ns;
  196. $this->file_ns = (isset($this->EE->lang->language['file_ns'])) ? $this->EE->lang->line('file_ns') : $this->file_ns;
  197. $this->image_ns = (isset($this->EE->lang->language['image_ns'])) ? $this->EE->lang->line('image_ns') : $this->image_ns;
  198. $this->special_ns = (isset($this->EE->lang->language['special_ns'])) ? $this->EE->lang->line('special_ns') : $this->special_ns;
  199. $this->category_ns = (isset($this->EE->lang->language['category_ns'])) ? $this->EE->lang->line('category_ns') : $this->category_ns;
  200. /* ----------------------------------------
  201. /* Category namespace actually has articles so it is put into the
  202. /* namespaces array. However, instead of the localized name we use
  203. /* the relatively simple 'category' in the page_namespace field.
  204. /* ---------------------------------------*/
  205. $this->namespaces['category'] = array('category', $this->category_ns);
  206. /** ----------------------------------------
  207. /** Tag Settings
  208. /** ----------------------------------------*/
  209. if ( ! in_array('1', $this->admins)) $this->admins[] = "1";
  210. if ( ! in_array('1', $this->users)) $this->users[] = "1";
  211. foreach($this->admins as $key => $value)
  212. {
  213. if (in_array($value, array('2', '3', '4')))
  214. {
  215. unset($this->admins[$key]);
  216. }
  217. }
  218. foreach($this->users as $key => $value)
  219. {
  220. if (in_array($value, array('2', '3', '4')))
  221. {
  222. unset($this->users[$key]);
  223. }
  224. }
  225. /** ----------------------------------------
  226. /** Valid Upload Directory?
  227. /** ----------------------------------------*/
  228. if ( ! empty($this->upload_dir) && is_numeric($this->upload_dir))
  229. {
  230. $query = $this->EE->db->query("SELECT COUNT(*) AS count FROM exp_upload_prefs
  231. WHERE id = '".$this->EE->db->escape_str($this->upload_dir)."'");
  232. if ($query->row('count') > 0)
  233. {
  234. $this->valid_upload_dir = 'y';
  235. $this->can_upload = 'y';
  236. if (in_array($this->EE->session->userdata['group_id'], array(2, 3, 4)))
  237. {
  238. $this->can_upload = 'n';
  239. }
  240. elseif ($this->EE->session->userdata['group_id'] != 1)
  241. {
  242. $query = $this->EE->db->query("SELECT upload_id FROM exp_upload_no_access WHERE member_group = '".$this->EE->session->userdata['group_id']."'");
  243. if ($query->num_rows() > 0)
  244. {
  245. foreach($query->result_array() as $row)
  246. {
  247. if ($query->row('upload_id') == $this->upload_dir)
  248. {
  249. $this->can_upload = 'n';
  250. break;
  251. }
  252. }
  253. }
  254. }
  255. }
  256. }
  257. /** ----------------------------------------
  258. /** Set theme, load file helper
  259. /** ----------------------------------------*/
  260. $this->EE->load->helper('file');
  261. $this->theme_path = PATH_THEMES.'wiki_themes/default/';
  262. $this->image_url = $this->EE->config->slash_item('theme_folder_url').'wiki_themes/default/images/';
  263. $this->theme_url = $this->EE->config->slash_item('theme_folder_url').'wiki_themes/default/';
  264. if ($this->EE->TMPL->fetch_param('theme') !== FALSE && $this->EE->TMPL->fetch_param('theme') != '' && $this->EE->TMPL->fetch_param('theme') != 'default')
  265. {
  266. $theme = $this->EE->security->sanitize_filename($this->EE->TMPL->fetch_param('theme'));
  267. if (is_dir(PATH_THEMES.'/wiki_themes/'.$theme))
  268. {
  269. $this->theme_path = PATH_THEMES.'wiki_themes/'.$theme.'/';
  270. $this->image_url = $this->EE->config->slash_item('theme_folder_url').'wiki_themes/'.$theme.'/images/';
  271. $this->theme_url = $this->EE->config->slash_item('theme_folder_url').'wiki_themes/'.$theme.'/';
  272. }
  273. else
  274. {
  275. $this->EE->TMPL->log_item('Wiki module: theme not found - "'.htmlentities($theme).'"');
  276. }
  277. }
  278. /** ----------------------------------------
  279. /** Editing Article
  280. /** ----------------------------------------*/
  281. if ($this->EE->input->post('editing') == 'y' && $this->EE->input->post('preview') === FALSE)
  282. {
  283. return $this->edit_article();
  284. }
  285. /** ----------------------------------------
  286. /** Displaying Page
  287. /** ----------------------------------------*/
  288. $this->return_data = str_replace(array('{module_version}'), array($this->version), $this->_fetch_template('wiki_page.html'));
  289. $this->return_data = $this->active_members($this->return_data);
  290. /* -------------------------------------
  291. /* 'wiki_start' hook.
  292. /* - Allows page template to be modified prior to article processing
  293. /* - Added 1.6.0
  294. */
  295. if ($this->EE->extensions->active_hook('wiki_start') === TRUE)
  296. {
  297. $this->return_data = $this->EE->extensions->universal_call('wiki_start', $this);
  298. if ($this->EE->extensions->end_script === TRUE) return;
  299. }
  300. /*
  301. /* -------------------------------------*/
  302. /** ----------------------------------------
  303. /** Determine Page to Show
  304. /** ----------------------------------------*/
  305. // Index Page
  306. if (count($this->seg_parts) == 0 OR $this->EE->uri->query_string == '' OR $this->EE->uri->query_string == 'index')
  307. {
  308. $this->title = 'index';
  309. $this->article('index');
  310. }
  311. // File Page
  312. elseif (substr($this->seg_parts['0'], 0, strlen($this->file_ns.':')) == $this->file_ns.':')
  313. {
  314. $this->title = $this->seg_parts['0'];
  315. $this->current_namespace = $this->file_ns;
  316. $this->file(substr($this->seg_parts['0'], strlen($this->file_ns.':')));
  317. }
  318. // Image
  319. elseif (substr($this->seg_parts['0'], 0, strlen($this->image_ns.':')) == $this->image_ns.':')
  320. {
  321. $this->title = $this->seg_parts['0'];
  322. $this->current_namespace = $this->image_ns;
  323. $this->image(substr($this->seg_parts['0'], strlen($this->image_ns.':')));
  324. }
  325. // Special Page
  326. elseif (substr($this->seg_parts['0'], 0, strlen($this->special_ns.':')) == $this->special_ns.':')
  327. {
  328. $this->title = $this->seg_parts['0'];
  329. $this->current_namespace = $this->special_ns;
  330. $this->special(substr($this->seg_parts['0'], strlen($this->special_ns.':')));
  331. }
  332. // Download!
  333. elseif (isset($this->seg_parts['0']) && strlen($this->seg_parts['0']) == 32 && preg_match("/^[a-z0-9]+$/i", $this->seg_parts['0']))
  334. {
  335. $this->display_attachment();
  336. exit;
  337. }
  338. // Typical Boring Article. Yawn!
  339. else
  340. {
  341. if (in_array($this->seg_parts['0'], array('edit', 'history', 'revision', 'noredirect')))
  342. {
  343. $this->title = 'index';
  344. if ($this->seg_parts['0'] == 'noredirect')
  345. {
  346. $this->article('index');
  347. }
  348. else
  349. {
  350. $this->{$this->seg_parts['0']}('index');
  351. }
  352. }
  353. else
  354. {
  355. $this->title = $this->seg_parts['0'];
  356. if ($this->valid_title($this->title) != $this->title)
  357. {
  358. $this->redirect('', $this->title);
  359. }
  360. if (isset($this->seg_parts['1']) && $this->seg_parts['1'] == 'edit')
  361. {
  362. $this->edit($this->title);
  363. }
  364. elseif (isset($this->seg_parts['1']) && $this->seg_parts['1'] == 'history')
  365. {
  366. $this->history($this->title);
  367. }
  368. elseif (isset($this->seg_parts['1']) && $this->seg_parts['1'] == 'revision')
  369. {
  370. $this->revision($this->title);
  371. }
  372. else
  373. {
  374. $this->article($this->title);
  375. }
  376. }
  377. }
  378. if ($this->can_upload == 'y')
  379. {
  380. $this->return_data = $this->_allow_if('uploads', $this->return_data);
  381. }
  382. else
  383. {
  384. $this->return_data = $this->_deny_if('uploads', $this->return_data);
  385. }
  386. /** ----------------------------------------
  387. /** Global Tags
  388. /** ----------------------------------------*/
  389. if (preg_match_all("/\{wiki:custom_namespaces_list(.*?)\}(.*?)\{\/wiki:custom_namespaces_list\}/s", $this->return_data, $matches))
  390. {
  391. for($i = 0, $s = count($matches[0]); $i < $s; ++$i)
  392. {
  393. $output = '';
  394. if (count($this->namespaces) > 0)
  395. {
  396. foreach($this->namespaces as $name => $label)
  397. {
  398. $selected = (isset($this->seg_parts['1']) && strtolower($this->seg_parts['1']) == $name) ? 'selected="selected"' : '';
  399. $output .= str_replace(array('{namespace_short_name}', '{namespace_label}', '{namespace_selected}'), array($label['0'], $label['1'], $selected), $matches['2'][$i]);
  400. }
  401. }
  402. $this->return_data = str_replace($matches['0'][$i], $output, $this->return_data);
  403. }
  404. }
  405. if (preg_match("/\{wiki:categories_list(.*?)\}(.*?)\{\/wiki:categories_list\}/s", $this->return_data))
  406. {
  407. $this->categories_list();
  408. }
  409. /** ----------------------------------------
  410. /** Global Conditionals
  411. /** ----------------------------------------*/
  412. if ($this->EE->session->userdata('member_id') == 0)
  413. {
  414. $this->return_data = $this->_deny_if('logged_in', $this->return_data);
  415. $this->return_data = $this->_allow_if('logged_out', $this->return_data);
  416. }
  417. else
  418. {
  419. $this->return_data = $this->_allow_if('logged_in', $this->return_data);
  420. $this->return_data = $this->_deny_if('logged_out', $this->return_data);
  421. }
  422. if (in_array($this->EE->session->userdata['group_id'], $this->admins))
  423. {
  424. $this->return_data = $this->_deny_if('cannot_admin', $this->return_data);
  425. $this->return_data = $this->_allow_if('can_admin', $this->return_data);
  426. }
  427. else
  428. {
  429. $this->return_data = $this->_allow_if('cannot_admin', $this->return_data);
  430. $this->return_data = $this->_deny_if('can_admin', $this->return_data);
  431. }
  432. /** ----------------------------------------
  433. /** Global Variables
  434. /** ----------------------------------------*/
  435. $link = $this->create_url($this->current_namespace, $this->topic);
  436. // Load the XML Helper
  437. $this->EE->load->helper('xml');
  438. $data = array( '{charset}' => $this->EE->config->item('output_charset'),
  439. '{wiki_name}' => $this->label_name,
  440. '{title}' => xml_convert($this->prep_title($this->title)),
  441. '{url_title}' => xml_convert($this->valid_title($this->title)),
  442. '{topic}' => xml_convert($this->prep_title($this->topic)),
  443. '{namespace}' => xml_convert($this->current_namespace),
  444. '{special_namespace}' => xml_convert($this->special_ns),
  445. '{main_namespace}' => xml_convert($this->main_ns),
  446. '{file_namespace}' => xml_convert($this->file_ns),
  447. '{category_namespace}' => xml_convert($this->category_ns),
  448. '{image_namespace}' => xml_convert($this->image_ns),
  449. '{revision_id}' => $this->revision_id,
  450. '{screen_name}' => $this->prep_screen_name($this->EE->session->userdata('screen_name')),
  451. '{path:wiki_home}' => $this->EE->functions->create_url($this->base_path),
  452. '{path:wiki_base_url}' => $this->base_url,
  453. '{path:article_history}' => $link.'/history',
  454. '{path:view_article}' => $link,
  455. '{path:edit_article}' => $link.'/edit',
  456. '{path:logout}' => $this->EE->functions->fetch_site_index(0, 0).QUERY_MARKER.'ACT='.$this->EE->functions->fetch_action_id('Member', 'member_logout'),
  457. '{path:your_control_panel}' => $this->EE->functions->create_url($this->profile_path.'profile'),
  458. '{path:your_profile}' => $this->EE->functions->create_url($this->profile_path.$this->EE->session->userdata('member_id')),
  459. '{path:login}' => $this->EE->functions->create_url($this->profile_path.'login'),
  460. '{path:register}' => $this->EE->functions->create_url($this->profile_path.'register'),
  461. '{path:memberlist}' => $this->EE->functions->create_url($this->profile_path.'memberlist'),
  462. '{path:forgot}' => $this->EE->functions->create_url($this->profile_path.'forgot_password'),
  463. '{path:private_messages}' => $this->EE->functions->create_url($this->profile_path.'messages/view_folder/1'),
  464. '{path:image_url}' => $this->image_url,
  465. '{path:theme_url}' => $this->theme_url,
  466. '{text_format}' => ucwords(str_replace('_', ' ', $this->text_format))
  467. );
  468. /** -------------------------------------
  469. /** Parse URI segments
  470. /** -------------------------------------*/
  471. // This code lets admins fetch URI segments which become
  472. // available as: {segment_1} {segment_2}
  473. for ($i = 1; $i < 9; $i++)
  474. {
  475. $data[LD.'segment_'.$i.RD] = $this->EE->uri->segment($i);
  476. }
  477. /** -------------------------------------
  478. /** Parse Snippets
  479. /** -------------------------------------*/
  480. foreach ($this->EE->config->_global_vars as $key => $val)
  481. {
  482. $data[LD.$key.RD] = $val;
  483. }
  484. /** -------------------------------------
  485. /** Parse manual variables
  486. /** -------------------------------------*/
  487. if (count($this->EE->TMPL->global_vars) > 0)
  488. {
  489. foreach ($this->EE->TMPL->global_vars as $key => $val)
  490. {
  491. $data[LD.$key.RD] = $val;
  492. }
  493. }
  494. /* -------------------------------------
  495. /* We reset some of these because in $data we are converting them
  496. /* for display purposes and we would rather have the conditionals
  497. /* use the unmodified versions
  498. /* -------------------------------------*/
  499. $this->conditionals['title'] = $this->title;
  500. $this->conditionals['topic'] = $this->topic;
  501. $this->conditionals['namespace'] = $this->current_namespace;
  502. $this->return_data = $this->prep_conditionals($this->return_data, array_merge($data, $this->conditionals));
  503. $this->return_data = str_replace(array_keys($data), array_values($data), $this->return_data);
  504. /** ----------------------------------------
  505. /** Cleanup
  506. /** ----------------------------------------*/
  507. $this->return_data = $this->_deny_if('redirected', $this->return_data);
  508. $this->return_data = $this->_deny_if('redirect_page', $this->return_data);
  509. }
  510. // --------------------------------------------------------------------
  511. /**
  512. * Fetch Template
  513. *
  514. * Fetches a template fragment
  515. *
  516. * @access public
  517. * @param string
  518. * @return string
  519. */
  520. function _fetch_template($which)
  521. {
  522. return read_file($this->theme_path.$which);
  523. }
  524. // --------------------------------------------------------------------
  525. /** ----------------------------------------
  526. /** Redirect for the Wiki
  527. /** ----------------------------------------*/
  528. function redirect($namespace='', $title)
  529. {
  530. $this->EE->functions->redirect($this->create_url($namespace, $title));
  531. exit;
  532. }
  533. /** ----------------------------------------
  534. /** Creat URL for the Wiki
  535. /** ----------------------------------------*/
  536. function create_url($namespace='', $title)
  537. {
  538. if ($namespace == '' && stristr($title, ':') && count($this->namespaces) > 0)
  539. {
  540. foreach($this->namespaces as $possible)
  541. {
  542. if (substr($title, 0, strlen($possible['1'].':')) == $possible['1'].':')
  543. {
  544. $namespace = $possible['1'];
  545. $title = substr($title, strlen($possible['1'].':'));
  546. break;
  547. }
  548. }
  549. }
  550. if ($namespace != '')
  551. {
  552. /*
  553. Convert any colons back because of Category articles
  554. */
  555. $link = $this->EE->functions->create_url($this->base_path.
  556. urlencode($this->valid_title($namespace)).
  557. ':'.
  558. str_replace('%3A', ':', urlencode($this->valid_title($title))));
  559. }
  560. else
  561. {
  562. $link = $this->EE->functions->create_url($this->base_path.
  563. urlencode($this->valid_title($title)));
  564. }
  565. return $link;
  566. }
  567. /** ----------------------------------------
  568. /** Prep Screen Name for Display
  569. /** ----------------------------------------*/
  570. function prep_screen_name($str)
  571. {
  572. return str_replace(array('<', '>', '{', '}', '\'', '"', '?'), array('&lt;', '&gt;', '&#123;', '&#125;', '&#146;', '&quot;', '&#63;'), $str);
  573. }
  574. /** ----------------------------------------
  575. /** Prep Title Display
  576. /** ----------------------------------------*/
  577. function prep_title($str)
  578. {
  579. if ($this->EE->config->item('word_separator') == 'dash')
  580. {
  581. return str_replace(array('-', $this->cats_separator), array(' ', $this->cats_display_separator), $str);
  582. }
  583. else
  584. {
  585. return str_replace(array('_', $this->cats_separator), array(' ', $this->cats_display_separator), $str);
  586. }
  587. }
  588. /** ----------------------------------------
  589. /** Create Valid Topic Name
  590. /** ----------------------------------------*/
  591. function valid_title($str)
  592. {
  593. // Remove all numeric entities
  594. $str = preg_replace('/&#x([0-9a-f]{2,5});{0,1}|&#([0-9]{2,4});{0,1}/', '', $str);
  595. /*
  596. The PCRE_UTF8 ('u') modifier is not available until PHP 4.2.3 for Windows, so if it is not
  597. available, then for the time being we are not allowing those higher end characters. We
  598. will change this once the character library is finished and ready for prime time.
  599. UPDATE: Well, while the PHP documentation says the flag is "available", this does not seem
  600. to denote that it will actually "work". Seems with the myriad of problems with servers
  601. having the correct PCRE library *and* compiling PHP with it correctly (RedHat Enterprise 3, for example),
  602. we cannot realistically do this until a version of PHP greater than PHP 4.3.2. Sheesh...
  603. */
  604. $trans = array();
  605. if (is_php('4.3.2') === TRUE)
  606. {
  607. $trans["#[^a-z0-9\-\_@&\'\"!\.:\+\x{A1}-\x{44F}\s]#iu"] = '';
  608. }
  609. else
  610. {
  611. $trans["#[^a-z0-9\-\_@&\'\"!\.:\+\xA1-\xFF\s]#i"] = '';
  612. }
  613. // Use dash or underscore as separator
  614. $replace = ($this->EE->config->item('word_separator') == 'dash') ? '-' : '_';
  615. $trans = array_merge($trans, array(
  616. '/\s+/' => $replace,
  617. "/{$replace}+/" => $replace,
  618. "/{$replace}$/" => $replace,
  619. "/^{$replace}/" => $replace
  620. ));
  621. return preg_replace(array_keys($trans), array_values($trans), urldecode($str));
  622. }
  623. /** ----------------------------------------
  624. /** Take Namespace's Short Name and Convert to Label
  625. /** ----------------------------------------*/
  626. function namespace_label($short_name)
  627. {
  628. if ($short_name != '')
  629. {
  630. $short_name = strtolower($short_name);
  631. $short_name = (isset($this->namespaces[$short_name])) ? $this->namespaces[$short_name]['1'] : '';
  632. }
  633. return $short_name;
  634. }
  635. /** ----------------------------------------
  636. /** Encode EE Tags
  637. /** ----------------------------------------*/
  638. function encode_ee_tags($str)
  639. {
  640. return str_replace(array('{','}'), array('&#123;','&#125;'), $str);
  641. }
  642. /* ----------------------------------------
  643. /* Topic Request!
  644. /*
  645. /* - Title = Namespace:Topic
  646. /* - If no namespace, then Title and Topic are
  647. /* the same thing
  648. /* ----------------------------------------*/
  649. function topic_request($title)
  650. {
  651. $title = $this->valid_title($title);
  652. $xsql = " AND page_namespace = '' ";
  653. // In the beginning, these are the same thing
  654. $this->topic = $title;
  655. $this->title = $title;
  656. if (stristr($title, ':') && count($this->namespaces) > 0)
  657. {
  658. $parts = explode(':', $title, 2);
  659. /* In PHP 5.1 this loop was consistently faster than array_search() */
  660. foreach($this->namespaces as $name => $label)
  661. {
  662. if (strcasecmp($label['1'], $this->prep_title($parts['0'])) == 0)
  663. {
  664. $xsql = " AND LOWER(page_namespace) = '".$this->EE->db->escape_str($name)."' ";
  665. $this->topic = substr($this->topic, strlen($label['1'].':'));
  666. $this->current_namespace = $label['1'];
  667. $this->title = $this->current_namespace.':'.$this->topic;
  668. break;
  669. }
  670. }
  671. }
  672. return $this->EE->db->query("SELECT * FROM exp_wiki_page
  673. WHERE wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  674. AND LOWER(page_name) = '".strtolower($this->EE->db->escape_str($this->topic))."'
  675. {$xsql}");
  676. }
  677. /** ----------------------------------------
  678. /** Load Image
  679. /** ----------------------------------------*/
  680. function image($topic, $return=FALSE)
  681. {
  682. if ($return === FALSE)
  683. {
  684. $this->title = $this->image_ns.':'.$topic;
  685. }
  686. /*
  687. No way to show the image if we do not have a valid upload directory
  688. because we need the URL for that directory.
  689. */
  690. if ($this->valid_upload_dir != 'y')
  691. {
  692. if ($return === TRUE) return FALSE;
  693. $this->redirect($this->file_ns, $topic);
  694. }
  695. /** ----------------------------------------
  696. /** Does File Exist? Is It An Image?
  697. /** ----------------------------------------*/
  698. $query = $this->EE->db->query("SELECT * FROM exp_wiki_uploads
  699. WHERE file_name = '".$this->EE->db->escape_str($topic)."'");
  700. if ($query->num_rows() == 0)
  701. {
  702. if ($return === TRUE) return FALSE;
  703. $this->redirect($this->file_ns, $topic);
  704. }
  705. $x = explode('/',$query->row('file_type') );
  706. if ($x['0'] != 'image')
  707. {
  708. if ($return === TRUE) return FALSE;
  709. $this->redirect($this->file_ns, $topic);
  710. }
  711. /** ----------------------------------------
  712. /** Create Our URL
  713. /** ----------------------------------------*/
  714. if ($return === TRUE)
  715. {
  716. $file_url = $this->base_url.$query->row('file_hash');
  717. }
  718. else
  719. {
  720. $results = $this->EE->db->query("SELECT url FROM exp_upload_prefs
  721. WHERE id = '".$this->EE->db->escape_str($this->upload_dir)."'");
  722. $file_url = (substr($results->row('url') , -1) == '/') ? $results->row('url') : $results->row('url') .'/';
  723. $file_url .= $query->row('file_name') ;
  724. }
  725. /* ----------------------------------------
  726. /* Display Our Image
  727. /* - Now in the future we might be clever and obfuscate the location
  728. /* - of images, if it is requested, by using fopen to get the image
  729. /* - data and displaying it instead of doing a redirect to the URL
  730. /* ----------------------------------------*/
  731. if ($return === TRUE)
  732. {
  733. return array('url' => $file_url,
  734. 'width' => $query->row('image_width') ,
  735. 'height' => $query->row('image_height') ,
  736. 'name' => $query->row('file_name') );
  737. }
  738. $this->EE->functions->redirect($file_url);
  739. exit;
  740. }
  741. /** ----------------------------------------
  742. /** File
  743. /** ----------------------------------------*/
  744. function file($topic)
  745. {
  746. $this->title = $this->file_ns.':'.$topic;
  747. $this->topic = $topic;
  748. /** ----------------------------------------
  749. /** Delete File? Admins Only!
  750. /** ----------------------------------------*/
  751. if (isset($this->seg_parts['1']) && strtolower($this->seg_parts['1']) == 'delete')
  752. {
  753. if ($this->can_upload == 'y' && in_array($this->EE->session->userdata['group_id'], $this->admins))
  754. {
  755. $query = $this->EE->db->query("SELECT COUNT(*) AS count FROM exp_wiki_uploads
  756. WHERE file_name = '".$this->EE->db->escape_str($topic)."'");
  757. if ($query->row('count') > 0)
  758. {
  759. $query = $this->EE->db->query("SELECT * FROM exp_upload_prefs
  760. WHERE id = '".$this->EE->db->escape_str($this->upload_dir)."'");
  761. $server_path = $query->row('server_path');
  762. if (substr($server_path , -1) != '/')
  763. {
  764. $server_path .= '/';
  765. }
  766. @unlink($server_path.$topic);
  767. $query = $this->EE->db->query("DELETE FROM exp_wiki_uploads
  768. WHERE file_name = '".$this->EE->db->escape_str($topic)."'");
  769. // Clear wiki cache
  770. $this->EE->functions->clear_caching('db');
  771. $this->redirect($this->special_ns, 'Files');
  772. }
  773. }
  774. }
  775. $this->return_data = $this->_deny_if('new_article', $this->return_data);
  776. $this->return_data = $this->_deny_if('article', $this->return_data);
  777. $this->return_data = $this->_deny_if('revision', $this->return_data);
  778. $this->return_data = $this->_deny_if('edit_article', $this->return_data);
  779. $this->return_data = $this->_deny_if('article_history', $this->return_data);
  780. $this->return_data = $this->_deny_if('special_page', $this->return_data);
  781. $this->return_data = $this->_allow_if('file_page', $this->return_data);
  782. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_file.html'), $this->return_data);
  783. $query = $this->EE->db->query("SELECT u.*, m.member_id, m.screen_name, m.email, m.url
  784. FROM exp_wiki_uploads u, exp_members m
  785. WHERE u.file_name = '".$this->EE->db->escape_str($topic)."'
  786. AND u.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  787. AND u.upload_author = m.member_id");
  788. /** ----------------------------------------
  789. /** Does File Exist? What Kind?
  790. /** ----------------------------------------*/
  791. if ($query->num_rows() == 0)
  792. {
  793. $this->return_data = $this->_deny_if('file_exists', $this->return_data);
  794. return;
  795. }
  796. else
  797. {
  798. $this->return_data = $this->_allow_if('file_exists', $this->return_data);
  799. }
  800. $x = explode('/',$query->row('file_type') );
  801. if ($x['0'] == 'image')
  802. {
  803. $this->return_data = $this->_allow_if('is_image', $this->return_data);
  804. }
  805. else
  806. {
  807. $this->return_data = $this->_deny_if('is_image', $this->return_data);
  808. }
  809. /** ----------------------------------------
  810. /** Date Formats
  811. /** ----------------------------------------*/
  812. if (preg_match_all("/".LD."(upload_date)\s+format=[\"'](.*?)[\"']".RD."/s", $this->return_data, $matches))
  813. {
  814. for ($j = 0; $j < count($matches['0']); $j++)
  815. {
  816. switch ($matches['1'][$j])
  817. {
  818. case 'upload_date' : $upload_date[$matches['0'][$j]] = array($matches['2'][$j], $this->EE->localize->fetch_date_params($matches['2'][$j]));
  819. break;
  820. }
  821. }
  822. foreach($upload_date as $key => $value)
  823. {
  824. $temp_date = $value['0'];
  825. foreach ($value['1'] as $dvar)
  826. {
  827. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $row['upload_date'], FALSE), $temp_date);
  828. }
  829. $this->return_data = str_replace($key, $temp_date, $this->return_data);
  830. }
  831. }
  832. /** ----------------------------------------
  833. /** Parse Variables
  834. /** ----------------------------------------*/
  835. $this->EE->load->library('typography');
  836. $this->EE->typography->initialize();
  837. $this->EE->typography->parse_images = FALSE;
  838. $this->EE->typography->parse_smileys = FALSE;
  839. $summary = $this->convert_curly_brackets($this->EE->typography->parse_type( $this->wiki_syntax($query->row('upload_summary') ),
  840. array(
  841. 'text_format' => $this->text_format,
  842. 'html_format' => $this->html_format,
  843. 'auto_links' => $this->auto_links,
  844. 'allow_img_url' => 'y'
  845. )
  846. ));
  847. $delete_url = '';
  848. if ($this->valid_upload_dir != 'y')
  849. {
  850. $file_url = $query->row('file_name') ;
  851. }
  852. else
  853. {
  854. $file_url = $this->base_url.$query->row('file_hash');
  855. if (in_array($this->EE->session->userdata['group_id'], $this->admins))
  856. {
  857. $delete_url = $this->base_url.$this->file_ns.':'.$query->row('file_name').'/delete';
  858. }
  859. }
  860. $this->conditionals['summary'] = $summary;
  861. $this->conditionals['delete_url'] = $delete_url;
  862. $this->conditionals = array_merge($this->conditionals, $query->row_array());
  863. /** ----------------------------------------
  864. /** Can User Edit File?
  865. /** ----------------------------------------*/
  866. if(in_array($this->EE->session->userdata['group_id'], $this->users) OR in_array($this->EE->session->userdata['group_id'], $this->admins))
  867. {
  868. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  869. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  870. }
  871. else
  872. {
  873. $this->return_data = $this->_deny_if('can_edit', $this->return_data);
  874. $this->return_data = $this->_allow_if('cannot_edit', $this->return_data);
  875. }
  876. $this->return_data = str_replace(array('{file_url}','{delete_url}','{file_name}','{summary}', '{image_width}', '{image_height}', '{file_type}'),
  877. array($file_url, $delete_url, $query->row('file_name') , $summary, $query->row('image_width') , $query->row('image_height') , $query->row('file_type') ),
  878. $this->return_data);
  879. }
  880. /** ----------------------------------------
  881. /** Special
  882. /** ----------------------------------------*/
  883. function special($topic)
  884. {
  885. $this->topic = $topic;
  886. $this->title = $this->special_ns.':'.$topic;
  887. $this->return_data = $this->_deny_if('new_article', $this->return_data);
  888. $this->return_data = $this->_deny_if('article', $this->return_data);
  889. $this->return_data = $this->_deny_if('revision', $this->return_data);
  890. $this->return_data = $this->_deny_if('edit_article', $this->return_data);
  891. $this->return_data = $this->_deny_if('article_history', $this->return_data);
  892. $this->return_data = $this->_allow_if('special_page', $this->return_data);
  893. /* -------------------------------------
  894. /* 'wiki_special_page' hook.
  895. /* - Allows complete takeover of special pages
  896. /* - Added 1.6.0
  897. */
  898. $edata = $this->EE->extensions->universal_call('wiki_special_page', $this, $topic);
  899. if ($this->EE->extensions->end_script === TRUE) return;
  900. /*
  901. /* -------------------------------------*/
  902. switch(strtolower($topic))
  903. {
  904. case 'recentchanges' :
  905. $this->recent_changes();
  906. break;
  907. case 'search_results' :
  908. $this->search_results();
  909. break;
  910. case 'random_page' :
  911. $this->random_page();
  912. break;
  913. case 'categories' :
  914. $this->categories();
  915. break;
  916. case 'files' :
  917. $this->files();
  918. break;
  919. case 'find_page' :
  920. $this->find_page();
  921. break;
  922. case 'uploads' :
  923. $this->upload_form();
  924. break;
  925. case 'recentchanges_rss' :
  926. $this->EE->output->out_type = 'feed';
  927. $this->EE->TMPL->template_type = 'feed';
  928. $this->return_data = $this->_fetch_template('wiki_special_rss.html');
  929. $this->recent_changes('rss');
  930. break;
  931. case 'recentchanges_atom' :
  932. $this->EE->output->out_type = 'feed';
  933. $this->EE->TMPL->template_type = 'feed';
  934. $this->return_data = $this->_fetch_template('wiki_special_atom.html');
  935. $this->recent_changes('atom');
  936. break;
  937. case 'titles' :
  938. $this->title_list();
  939. break;
  940. case 'associated_pages' :
  941. $this->associated_pages();
  942. break;
  943. case 'uncategorized' :
  944. $this->uncategorized_pages();
  945. break;
  946. case 'css' :
  947. $this->wiki_css();
  948. break;
  949. default:
  950. $this->return_data = str_replace('{wiki:page}', '', $this->return_data);
  951. break;
  952. }
  953. $this->return_data = $this->_deny_if('can_edit', $this->return_data);
  954. $this->return_data = $this->_allow_if('cannot_edit', $this->return_data);
  955. }
  956. // --------------------------------------------------------------------
  957. /**
  958. * Wiki CSS
  959. *
  960. * Outputs the default Wiki CSS theme file with proper headers
  961. *
  962. * @access public
  963. * @return void
  964. */
  965. function wiki_css()
  966. {
  967. // reset! We just want the CSS
  968. $this->return_data = $this->_fetch_template('wiki_style.css');
  969. if ($this->return_data === FALSE)
  970. {
  971. // no point
  972. exit;
  973. }
  974. // replace image paths
  975. $this->return_data = str_replace('{path:image_url}', $this->image_url, $this->return_data);
  976. $last_modified = filemtime($this->theme_path.'wiki_style.css');
  977. $this->EE->load->library('stylesheet');
  978. $this->EE->stylesheet->_send_css($this->return_data, $last_modified);
  979. }
  980. // --------------------------------------------------------------------
  981. /** ---------------------------------------
  982. /** Uncategorized Pages
  983. /** ---------------------------------------*/
  984. function uncategorized_pages()
  985. {
  986. return $this->title_list('uncategorized_pages');
  987. }
  988. /* END */
  989. /** ----------------------------------------
  990. /** Recent Changes Processing
  991. /** ----------------------------------------*/
  992. function title_list($type = '')
  993. {
  994. /** ---------------------------------------
  995. /** Initialize the correct template and do any
  996. /** prep work needed prior to our title query
  997. /** ---------------------------------------*/
  998. switch ($type)
  999. {
  1000. case 'uncategorized_pages' :
  1001. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_special_uncategorized_pages.html'), $this->return_data);
  1002. /** ---------------------------------------
  1003. /** Get categorized page ids
  1004. /** ---------------------------------------*/
  1005. $query = $this->EE->db->query("SELECT DISTINCT(exp_wiki_category_articles.page_id)
  1006. FROM exp_wiki_category_articles
  1007. LEFT JOIN exp_wiki_page ON exp_wiki_page.page_id = exp_wiki_category_articles.page_id
  1008. WHERE exp_wiki_page.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'");
  1009. if ($query->num_rows() > 0)
  1010. {
  1011. $page_ids = array();
  1012. foreach ($query->result() as $row)
  1013. {
  1014. $page_ids[] = $row->page_id;
  1015. }
  1016. $xsql = " AND p.page_id NOT IN (".implode(',', $page_ids).")
  1017. AND p.page_redirect = '' ";
  1018. }
  1019. break;
  1020. default :
  1021. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_special_titles.html'), $this->return_data);
  1022. break;
  1023. }
  1024. if ( ! preg_match("/\{wiki:title_list(.*?)\}(.*?)\{\/wiki:title_list\}/s", $this->return_data, $match))
  1025. {
  1026. return $this->return_data = '';
  1027. }
  1028. if ( ! preg_match("/\{articles\}(.*?)\{\/articles\}/s", $match['2'], $topics))
  1029. {
  1030. return $this->return_data = '';
  1031. }
  1032. /** ----------------------------------------
  1033. /** Parameters
  1034. /** ----------------------------------------*/
  1035. $columns = 3;
  1036. if (trim($match['1']) != '' && ($params = $this->EE->functions->assign_parameters($match['1'])) !== FALSE)
  1037. {
  1038. $columns = (isset($params['columns']) && is_numeric($params['columns'])) ? $params['columns'] : $limit;
  1039. }
  1040. /** ----------------------------------------
  1041. /** Date Formats
  1042. /** ----------------------------------------*/
  1043. $dates = $this->parse_dates($this->return_data);
  1044. /** ----------------------------------------
  1045. /** Our Query
  1046. /** ----------------------------------------*/
  1047. if ( ! isset($xsql))
  1048. {
  1049. $xsql = '';
  1050. }
  1051. if (isset($this->seg_parts['1']) && isset($this->namespaces[strtolower($this->seg_parts['1'])]))
  1052. {
  1053. $xsql = "AND LOWER(p.page_namespace) = '".$this->EE->db->escape_str(strtolower($this->seg_parts['1']))."'";
  1054. }
  1055. else
  1056. {
  1057. $xsql = "AND p.page_namespace = ''";
  1058. }
  1059. $results = $this->EE->db->query("SELECT r.*,
  1060. m.member_id, m.screen_name, m.email, m.url,
  1061. p.page_namespace, p.page_name AS topic
  1062. FROM exp_wiki_revisions r, exp_members m, exp_wiki_page p
  1063. WHERE p.last_updated = r.revision_date
  1064. {$xsql}
  1065. AND m.member_id = r.revision_author
  1066. AND r.page_id = p.page_id
  1067. AND r.revision_status = 'open'
  1068. AND r.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  1069. ORDER BY p.page_name");
  1070. if ($results->num_rows() == 0)
  1071. {
  1072. if (preg_match("|".LD."if\s+no_results".RD."(.*?)".LD."\/if".RD."|s",$match['2'], $block))
  1073. {
  1074. $this->return_data = str_replace($match['0'], $block['1'], $this->return_data);
  1075. }
  1076. else
  1077. {
  1078. $this->return_data = str_replace($match['0'], str_replace($topics['0'], '', $match['2']), $this->return_data);
  1079. }
  1080. return;
  1081. }
  1082. /** ----------------------------------------
  1083. /** Template Parts
  1084. /** ----------------------------------------*/
  1085. $our_template = $topics['1'];
  1086. $row_start = '';
  1087. $row_end = '';
  1088. $row_blank = '';
  1089. $row_column = '';
  1090. foreach(array('row_start', 'row_end', 'row_blank', 'row_column') as $val)
  1091. {
  1092. if (preg_match("/\{".preg_quote($val)."\}(.*?)\{\/".preg_quote($val)."\}/s", $our_template, $matching))
  1093. {
  1094. $$val = $matching['1'];
  1095. }
  1096. }
  1097. $template = $row_column;
  1098. /** ----------------------------------------
  1099. /** Parsing of the Recent Changes Tag Pair
  1100. /** ----------------------------------------*/
  1101. $parse_article = stristr($template, '{article}');
  1102. $this->EE->load->library('typography');
  1103. $this->EE->typography->initialize();
  1104. $this->EE->typography->parse_images = FALSE;
  1105. $this->EE->typography->parse_smileys = FALSE;
  1106. $titles = $row_start;
  1107. $i = 0;
  1108. $count = 0;
  1109. // added in 1.6 for {switch} variable and for future use
  1110. $vars = $this->EE->functions->assign_variables($template);
  1111. $this->EE->load->helper('url');
  1112. foreach($results->result_array() as $row)
  1113. {
  1114. $count++;
  1115. $titles .= ($i % $columns != 0) ? '' : $row_end.$row_start; ++$i;
  1116. $temp = $template;
  1117. if (isset($this->seg_parts['1']) && isset($this->namespaces[strtolower($this->seg_parts['1'])]))
  1118. {
  1119. $title = $row['topic'];
  1120. }
  1121. else
  1122. {
  1123. $title = ($row['page_namespace'] != '') ? $this->namespace_label($row['page_namespace']).':'.$row['topic'] : $row['topic'];
  1124. }
  1125. $link = $this->create_url($this->namespace_label($row['page_namespace']), $row['topic']);
  1126. $data = array( '{title}' => $this->prep_title($title),
  1127. '{revision_id}' => $row['revision_id'],
  1128. '{page_id}' => $row['page_id'],
  1129. '{author}' => $row['screen_name'],
  1130. '{path:author_profile}' => $this->EE->functions->create_url($this->profile_path.$row['member_id']),
  1131. '{path:member_profile}' => $this->EE->functions->create_url($this->profile_path.$row['member_id']),
  1132. '{email}' => $this->EE->typography->encode_email($row['email']),
  1133. '{url}' => prep_url($row['url']),
  1134. '{revision_notes}' => $row['revision_notes'],
  1135. '{path:view_article}' => $link,
  1136. '{content}' => $row['page_content'],
  1137. '{count}' => $count);
  1138. if ($parse_article !== FALSE)
  1139. {
  1140. $data['{article}'] = $this->convert_curly_brackets($this->EE->typography->parse_type( $this->wiki_syntax($row['page_content'], FALSE),
  1141. array(
  1142. 'text_format' => $this->text_format,
  1143. 'html_format' => $this->html_format,
  1144. 'auto_links' => $this->auto_links,
  1145. 'allow_img_url' => 'y'
  1146. )
  1147. ));
  1148. }
  1149. $temp = $this->prep_conditionals($temp, array_merge($data, $this->conditionals));
  1150. if (isset($dates['last_updated']))
  1151. {
  1152. foreach($dates['last_updated'] as $key => $value)
  1153. {
  1154. $temp_date = $value['0'];
  1155. // Do this once here, to save energy
  1156. $row['revision_date'] = $this->EE->localize->set_localized_time($row['revision_date']);
  1157. foreach ($value['1'] as $dvar)
  1158. {
  1159. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $row['revision_date'], FALSE), $temp_date);
  1160. }
  1161. $data[$key] = $temp_date;
  1162. }
  1163. }
  1164. foreach ($vars['var_single'] as $key => $val)
  1165. {
  1166. /** ----------------------------------------
  1167. /** parse {switch} variable
  1168. /** ----------------------------------------*/
  1169. if (preg_match("/^switch\s*=.+/i", $key))
  1170. {
  1171. $sparam = $this->EE->functions->assign_parameters($key);
  1172. $sw = '';
  1173. if (isset($sparam['switch']))
  1174. {
  1175. $sopt = explode("|", $sparam['switch']);
  1176. $sw = $sopt[($count-1 + count($sopt)) % count($sopt)];
  1177. }
  1178. $temp = $this->EE->TMPL->swap_var_single($key, $sw, $temp);
  1179. }
  1180. }
  1181. $titles .= str_replace(array_keys($data), array_values($data), $temp);
  1182. }
  1183. while($i % $columns != 0)
  1184. {
  1185. $titles .= $row_blank; ++$i;
  1186. }
  1187. $titles .= $row_end;
  1188. $this->return_data = str_replace($match['0'], str_replace($topics['0'], $titles, $match['2']), $this->return_data);
  1189. }
  1190. /** ----------------------------------------
  1191. /** Recent Changes Processing
  1192. /** ----------------------------------------*/
  1193. function recent_changes($type='')
  1194. {
  1195. /** ----------------------------------------
  1196. /** Load Template, Check for Valid Tag
  1197. /** ----------------------------------------*/
  1198. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_special_recent_changes.html'), $this->return_data);
  1199. if ( ! preg_match("/\{wiki:recent_changes(.*?)\}(.*?)\{\/wiki:recent_changes\}/s", $this->return_data, $match))
  1200. {
  1201. return $this->return_data = '';
  1202. }
  1203. /** ----------------------------------------
  1204. /** Parameters
  1205. /** ----------------------------------------*/
  1206. $parameters['limit'] = 10;
  1207. $parameters['paginate'] = 'bottom';
  1208. if (trim($match['1']) != '' && ($params = $this->EE->functions->assign_parameters($match['1'])) !== FALSE)
  1209. {
  1210. $parameters['limit'] = (isset($params['limit']) && is_numeric($params['limit'])) ? $params['limit'] : $parameters['limit'];
  1211. $parameters['paginate'] = (isset($params['paginate']) && is_numeric($params['paginate'])) ? $params['paginate'] : $parameters['paginate'];
  1212. }
  1213. /** ----------------------------------------
  1214. /** Date Formats
  1215. /** ----------------------------------------*/
  1216. $dates = $this->parse_dates($this->return_data);
  1217. /** ----------------------------------------
  1218. /** Our Query
  1219. /** ----------------------------------------*/
  1220. if (isset($this->seg_parts['1']) && $this->seg_parts['1'] != '' && ! preg_match("/^P[0-9]+$/", $this->seg_parts['1']))
  1221. {
  1222. $query = $this->topic_request($this->seg_parts['1']);
  1223. $sql = "FROM exp_wiki_revisions r, exp_members m, exp_wiki_page p
  1224. WHERE p.page_id = '".(($query->num_rows() > 0) ? $query->row('page_id') : '0')."'
  1225. AND r.page_id = p.page_id
  1226. AND r.revision_status = 'open'
  1227. AND r.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  1228. AND m.member_id = r.revision_author
  1229. ORDER BY r.revision_date DESC";
  1230. }
  1231. else
  1232. {
  1233. $sql = "FROM exp_wiki_revisions r, exp_members m, exp_wiki_page p
  1234. WHERE p.last_updated = r.revision_date
  1235. AND m.member_id = r.revision_author
  1236. AND r.page_id = p.page_id
  1237. AND r.revision_status = 'open'
  1238. AND r.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  1239. ORDER BY p.last_updated DESC";
  1240. }
  1241. $results = $this->EE->db->query("SELECT COUNT(*) AS count ".$sql);
  1242. if ($results->row('count') == 0)
  1243. {
  1244. return $this->return_data = '';
  1245. }
  1246. $this->pagination($results->row('count') , $parameters['limit'], $this->base_url.$this->special_ns.':Recentchanges/');
  1247. // Pagination code removed, rerun template preg_match()
  1248. if ($this->paginate === TRUE)
  1249. {
  1250. preg_match("/\{wiki:recent_changes(.*?)\}(.*?)\{\/wiki:recent_changes\}/s", $this->return_data, $match);
  1251. }
  1252. else
  1253. {
  1254. $this->pagination_sql .= " LIMIT ".$parameters['limit'];
  1255. }
  1256. $results = $this->EE->db->query("SELECT r.*,
  1257. m.member_id, m.screen_name, m.email, m.url,
  1258. p.page_namespace, p.page_name AS topic ".
  1259. $sql.
  1260. $this->pagination_sql);
  1261. /** ----------------------------------------
  1262. /** Global Last Updated
  1263. /** ----------------------------------------*/
  1264. if (isset($dates['last_updated']))
  1265. {
  1266. foreach($dates['last_updated'] as $key => $value)
  1267. {
  1268. $temp_date = $value['0'];
  1269. foreach ($value['1'] as $dvar)
  1270. {
  1271. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $results->row('revision_date') , TRUE), $temp_date);
  1272. }
  1273. $this->return_data = str_replace($key, $temp_date, $this->return_data);
  1274. }
  1275. }
  1276. if (isset($dates['gmt_last_updated']))
  1277. {
  1278. foreach($dates['gmt_last_updated'] as $key => $value)
  1279. {
  1280. $temp_date = $value['0'];
  1281. foreach ($value['1'] as $dvar)
  1282. {
  1283. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $results->row('revision_date') , FALSE), $temp_date);
  1284. }
  1285. $this->return_data = str_replace($key, $temp_date, $this->return_data);
  1286. }
  1287. }
  1288. /** ----------------------------------------
  1289. /** Parsing of the Recent Changes Tag Pair
  1290. /** ----------------------------------------*/
  1291. $this->EE->load->library('typography');
  1292. $this->EE->typography->initialize();
  1293. $this->EE->typography->parse_images = FALSE;
  1294. $this->EE->typography->parse_smileys = FALSE;
  1295. if ($type == 'rss' OR $type == 'atom')
  1296. {
  1297. $this->EE->typography->encode_email = FALSE;
  1298. }
  1299. $changes = '';
  1300. $count = 0;
  1301. // added in 1.6 for {switch} variable and for future use
  1302. $vars = $this->EE->functions->assign_variables($match['2']);
  1303. $this->EE->load->helper('url');
  1304. foreach($results->result_array() as $row)
  1305. {
  1306. $count++;
  1307. $temp = $match['2'];
  1308. $title = ($row['page_namespace'] != '') ? $this->namespace_label($row['page_namespace']).':'.$row['topic'] : $row['topic'];
  1309. $link = $this->create_url($this->namespace_label($row['page_namespace']), $row['topic']);
  1310. $data = array( '{title}' => $this->prep_title($title),
  1311. '{revision_id}' => $row['revision_id'],
  1312. '{page_id}' => $row['page_id'],
  1313. '{author}' => $row['screen_name'],
  1314. '{path:author_profile}' => $this->EE->functions->create_url($this->profile_path.$row['member_id']),
  1315. '{path:member_profile}' => $this->EE->functions->create_url($this->profile_path.$row['member_id']),
  1316. '{email}' => ($type == 'rss' OR $type == 'atom') ? $row['email'] : $this->EE->typography->encode_email($row['email']), // No encoding for RSS/Atom
  1317. '{url}' => prep_url($row['url']),
  1318. '{revision_notes}' => $row['revision_notes'],
  1319. '{path:view_article}' => $link,
  1320. '{content}' => $row['page_content'],
  1321. '{count}' => $count);
  1322. $data['{article}'] = $this->convert_curly_brackets($this->EE->typography->parse_type( $this->wiki_syntax($row['page_content']),
  1323. array(
  1324. 'text_format' => $this->text_format,
  1325. 'html_format' => $this->html_format,
  1326. 'auto_links' => $this->auto_links,
  1327. 'allow_img_url' => 'y'
  1328. )
  1329. ));
  1330. $temp = $this->prep_conditionals($temp, array_merge($data, $this->conditionals));
  1331. if (isset($dates['revision_date']))
  1332. {
  1333. foreach($dates['revision_date'] as $key => $value)
  1334. {
  1335. $temp_date = $value['0'];
  1336. foreach ($value['1'] as $dvar)
  1337. {
  1338. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $row['revision_date'], TRUE), $temp_date);
  1339. }
  1340. $data[$key] = $temp_date;
  1341. }
  1342. }
  1343. if (isset($dates['gmt_revision_date']))
  1344. {
  1345. foreach($dates['gmt_revision_date'] as $key => $value)
  1346. {
  1347. $temp_date = $value['0'];
  1348. foreach ($value['1'] as $dvar)
  1349. {
  1350. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $row['revision_date'], FALSE), $temp_date);
  1351. }
  1352. $data[$key] = $temp_date;
  1353. }
  1354. }
  1355. foreach ($vars['var_single'] as $key => $val)
  1356. {
  1357. /** ----------------------------------------
  1358. /** parse {switch} variable
  1359. /** ----------------------------------------*/
  1360. if (preg_match("/^switch\s*=.+/i", $key))
  1361. {
  1362. $sparam = $this->EE->functions->assign_parameters($key);
  1363. $sw = '';
  1364. if (isset($sparam['switch']))
  1365. {
  1366. $sopt = explode("|", $sparam['switch']);
  1367. $sw = $sopt[($count-1 + count($sopt)) % count($sopt)];
  1368. }
  1369. $temp = $this->EE->TMPL->swap_var_single($key, $sw, $temp);
  1370. }
  1371. if ($key == 'absolute_count')
  1372. {
  1373. $temp = $this->EE->TMPL->swap_var_single($key, $count + ($this->current_page * $parameters['limit']) - $parameters['limit'], $temp);
  1374. }
  1375. }
  1376. $changes .= str_replace(array_keys($data), array_values($data), $temp);
  1377. }
  1378. /** ----------------------------------------
  1379. /** Pagination
  1380. /** ----------------------------------------*/
  1381. if ($this->paginate === TRUE)
  1382. {
  1383. $this->paginate_data = str_replace(LD.'current_page'.RD, $this->current_page, $this->paginate_data);
  1384. $this->paginate_data = str_replace(LD.'total_pages'.RD, $this->total_pages, $this->paginate_data);
  1385. $this->paginate_data = str_replace(LD.'pagination_links'.RD, $this->pagination_links, $this->paginate_data);
  1386. if (preg_match("/".LD."if previous_page".RD."(.+?)".LD.'\/'."if".RD."/s", $this->paginate_data, $matches))
  1387. {
  1388. if ($this->page_previous == '')
  1389. {
  1390. $this->paginate_data = preg_replace("/".LD."if previous_page".RD.".+?".LD.'\/'."if".RD."/s", '', $this->paginate_data);
  1391. }
  1392. else
  1393. {
  1394. $matches['1'] = preg_replace("/".LD.'path.*?'.RD."/", $this->page_previous, $matches['1']);
  1395. $matches['1'] = preg_replace("/".LD.'auto_path'.RD."/", $this->page_previous, $matches['1']);
  1396. $this->paginate_data = str_replace($matches['0'], $matches['1'], $this->paginate_data);
  1397. }
  1398. }
  1399. if (preg_match("/".LD."if next_page".RD."(.+?)".LD.'\/'."if".RD."/s", $this->paginate_data, $matches))
  1400. {
  1401. if ($this->page_next == '')
  1402. {
  1403. $this->paginate_data = preg_replace("/".LD."if next_page".RD.".+?".LD.'\/'."if".RD."/s", '', $this->paginate_data);
  1404. }
  1405. else
  1406. {
  1407. $matches['1'] = preg_replace("/".LD.'path.*?'.RD."/", $this->page_next, $matches['1']);
  1408. $matches['1'] = preg_replace("/".LD.'auto_path'.RD."/", $this->page_next, $matches['1']);
  1409. $this->paginate_data = str_replace($matches['0'], $matches['1'], $this->paginate_data);
  1410. }
  1411. }
  1412. switch ($parameters['paginate'])
  1413. {
  1414. case "top" : $changes = $this->paginate_data.$changes;
  1415. break;
  1416. case "both" : $changes = $this->paginate_data.$changes.$this->paginate_data;
  1417. break;
  1418. default : $changes .= $this->paginate_data;
  1419. break;
  1420. }
  1421. }
  1422. $this->return_data = str_replace($match['0'], $changes, $this->return_data);
  1423. $ex = explode("/", str_replace(array('http://', 'www.'), '', $this->EE->functions->create_url($this->base_path)));
  1424. $this->return_data = str_replace(array('{trimmed_url}', '{language}'), array(current($ex), $this->EE->config->item('xml_lang')), $this->return_data);
  1425. }
  1426. /** ----------------------------------------
  1427. /** Our List of Categories
  1428. /** ----------------------------------------*/
  1429. function categories_list()
  1430. {
  1431. $this->show_these = FALSE;
  1432. $this->categories('', TRUE);
  1433. }
  1434. function categories($page_id='', $list=FALSE)
  1435. {
  1436. /** ----------------------------------------
  1437. /** Load Template, Check for Valid Tag
  1438. /** ----------------------------------------*/
  1439. if ($page_id == '' && $list == FALSE)
  1440. {
  1441. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_special_categories.html'), $this->return_data);
  1442. }
  1443. if ($list === TRUE)
  1444. {
  1445. if ( ! preg_match_all("/\{wiki:categories_list\s(.*?)\}(.*?)\{\/wiki:categories_list\}/s", $this->return_data, $matches))
  1446. {
  1447. return;
  1448. }
  1449. }
  1450. else
  1451. {
  1452. if ( ! preg_match_all("/\{wiki:categories\s(.*?)\}(.*?)\{\/wiki:categories\}/s", $this->return_data, $matches))
  1453. {
  1454. return $this->return_data = '';
  1455. }
  1456. }
  1457. for($i=0, $s = count($matches[0]); $i < $s; ++$i)
  1458. {
  1459. $match = array($matches[0][$i], $matches[1][$i], $matches[2][$i]);
  1460. /** ----------------------------------------
  1461. /** Parameters
  1462. /** ----------------------------------------*/
  1463. $limit = 10;
  1464. $backspace = '';
  1465. $show_empty = 'y';
  1466. $style = '';
  1467. if (trim($match['1']) != '' && ($params = $this->EE->functions->assign_parameters($match['1'])) !== FALSE)
  1468. {
  1469. $limit = (isset($params['limit']) && is_numeric($params['limit'])) ? $params['limit'] : $limit;
  1470. $backspace = (isset($params['backspace']) && is_numeric($params['backspace'])) ? $params['backspace'] : $backspace;
  1471. $show_empty = (isset($params['show_empty'])) ? $params['show_empty'] : $show_empty;
  1472. $style = (isset($params['style'])) ? $params['style'] : $style;
  1473. }
  1474. /** ----------------------------------------
  1475. /** Our Query
  1476. /** ----------------------------------------*/
  1477. $namespace = '';
  1478. if ($page_id == '' && isset($this->seg_parts['1']) && count($this->namespaces) > 0)
  1479. {
  1480. if (isset($this->namespaces[strtolower($this->seg_parts['1'])]))
  1481. {
  1482. $namespace = $this->namespaces[strtolower($this->seg_parts['1'])]['0'];
  1483. }
  1484. }
  1485. $categories = $this->retrieve_categories($namespace, $page_id, $show_empty);
  1486. if ($categories === FALSE OR count($categories) == 0)
  1487. {
  1488. $output = '';
  1489. }
  1490. else
  1491. {
  1492. $output = $this->parse_categories($categories, $match['2'], $style, $backspace);
  1493. }
  1494. $this->return_data = str_replace($match['0'], $output, $this->return_data);
  1495. }
  1496. }
  1497. /** ----------------------------------------
  1498. /** Parsing of the Categories
  1499. /** ----------------------------------------*/
  1500. function parse_categories($categories, $template, $style, $backspace, $ancestry=array())
  1501. {
  1502. $output = ($style == 'nested') ? "<ul id='nav_categories'>\n" : '';
  1503. // added in 1.6 for {switch} and {count} variables and for future use
  1504. $vars = $this->EE->functions->assign_variables($template);
  1505. $count = 0;
  1506. foreach($categories as $key => $category_data)
  1507. {
  1508. if ($this->show_these !== FALSE && ! in_array($category_data['0']['cat_id'], $this->show_these))
  1509. {
  1510. continue;
  1511. }
  1512. $count++;
  1513. $children = array();
  1514. if ($this->show_these !== FALSE)
  1515. {
  1516. foreach($category_data['1'] as $key2 => $cat)
  1517. {
  1518. if (in_array($cat['data']['cat_id'], $this->show_these))
  1519. {
  1520. $children[$key2] = $cat;
  1521. }
  1522. }
  1523. }
  1524. else
  1525. {
  1526. $children = $category_data['1'];
  1527. }
  1528. $output .= $this->category_process($template, $category_data['0'], $ancestry, '0', '0', '0', (count($children) > 0) ? 'y' : 'n', $style);
  1529. foreach ($vars['var_single'] as $k => $v)
  1530. {
  1531. /** ----------------------------------------
  1532. /** parse {switch} variable
  1533. /** ----------------------------------------*/
  1534. if (preg_match("/^switch\s*=.+/i", $k))
  1535. {
  1536. $sparam = $this->EE->functions->assign_parameters($k);
  1537. $sw = '';
  1538. if (isset($sparam['switch']))
  1539. {
  1540. $sopt = explode("|", $sparam['switch']);
  1541. $sw = $sopt[($count-1 + count($sopt)) % count($sopt)];
  1542. }
  1543. $output = $this->EE->TMPL->swap_var_single($k, $sw, $output);
  1544. }
  1545. if ($k == 'count')
  1546. {
  1547. $output = $this->EE->TMPL->swap_var_single($k, $count, $output);
  1548. }
  1549. }
  1550. $last_depth = 0;
  1551. foreach($children as $key2 => $cat)
  1552. {
  1553. $has_children = 'n';
  1554. $next_depth = 0;
  1555. $count++;
  1556. // If the next array member has this category as its parent,
  1557. // then we have kids! Get the cigars!
  1558. if (isset($children[$key2+1]))
  1559. {
  1560. if ($children[$key2+1]['data']['parent_id'] == $cat['data']['cat_id'])
  1561. {
  1562. $has_children = 'y';
  1563. }
  1564. $next_depth = $children[$key2+1]['depth'];
  1565. }
  1566. $output .= $this->category_process( $template,
  1567. $cat['data'],
  1568. $cat['parents'],
  1569. $cat['depth'],
  1570. $last_depth,
  1571. $next_depth,
  1572. $has_children,
  1573. $style);
  1574. foreach ($vars['var_single'] as $k => $v)
  1575. {
  1576. /** ----------------------------------------
  1577. /** parse {switch} variable
  1578. /** ----------------------------------------*/
  1579. if (preg_match("/^switch\s*=.+/i", $k))
  1580. {
  1581. $sparam = $this->EE->functions->assign_parameters($k);
  1582. $sw = '';
  1583. if (isset($sparam['switch']))
  1584. {
  1585. $sopt = explode("|", $sparam['switch']);
  1586. $sw = $sopt[($count-1 + count($sopt)) % count($sopt)];
  1587. }
  1588. $output = $this->EE->TMPL->swap_var_single($k, $sw, $output);
  1589. }
  1590. if ($k == 'count')
  1591. {
  1592. $output = $this->EE->TMPL->swap_var_single($k, $count, $output);
  1593. }
  1594. }
  1595. $last_depth = $cat['depth'];
  1596. }
  1597. }
  1598. if ($style == 'nested')
  1599. {
  1600. $output .= "</ul>\n";
  1601. }
  1602. if ($backspace != '')
  1603. {
  1604. $output = substr($output, 0, - $backspace);
  1605. }
  1606. return $output;
  1607. }
  1608. /** -------------------------------------------
  1609. /** Process a Category for Output
  1610. /** -------------------------------------------*/
  1611. function category_process($template, $data, $parents, $depth, $last_depth='0', $next_depth='0', $children='n', $style='')
  1612. {
  1613. if ($this->show_these !== FALSE && ! in_array($data['cat_id'], $this->show_these))
  1614. {
  1615. return '';
  1616. }
  1617. $cdata = array( '{category_name}' => $this->prep_title($data['cat_name']),
  1618. '{category_id}' => $data['cat_id'],
  1619. '{parent_id}' => $data['parent_id'],
  1620. '{depth}' => $depth,
  1621. '{last_depth}' => $last_depth,
  1622. '{next_depth}' => $next_depth,
  1623. '{path:view_category}' => $this->base_url.
  1624. $this->category_ns.':'.
  1625. ((count($parents) > 0) ? implode($this->cats_separator, $parents).$this->cats_separator : '').
  1626. $data['cat_name']);
  1627. $this->conditionals['children'] = ($children == 'y') ? 'TRUE' : 'FALSE';
  1628. $this->conditionals['first_child'] = ($depth > $last_depth) ? 'TRUE' : 'FALSE';
  1629. $this->conditionals['last_child'] = ($depth > $next_depth) ? 'TRUE' : 'FALSE';
  1630. $template = $this->prep_conditionals($template, array_merge($cdata, $this->conditionals));
  1631. $template = str_replace(array_keys($cdata), array_values($cdata), $template);
  1632. if ($style == 'nested')
  1633. {
  1634. $template = str_repeat("\t", ($depth == 0) ? 1 : $depth+1)."<li>".trim($template);
  1635. if ($children == "y")
  1636. {
  1637. $template .= str_repeat("\t", $depth+1)."<ul>\n";
  1638. }
  1639. else
  1640. {
  1641. $template .= "</li>\n";
  1642. }
  1643. if ($depth > $next_depth)
  1644. {
  1645. for($i=$depth-$next_depth; $i > 0; --$i)
  1646. {
  1647. $template .= str_repeat("\t", $i+$next_depth)."</ul>\n";
  1648. $template .= str_repeat("\t", $i+$next_depth)."</li>\n";
  1649. }
  1650. }
  1651. return $template;
  1652. }
  1653. else
  1654. {
  1655. return $template;
  1656. }
  1657. }
  1658. /** -------------------------------------------
  1659. /** Retrieve Wiki Categories
  1660. /** -------------------------------------------*/
  1661. function retrieve_categories($namespace, $page_id='', $show_empty='y')
  1662. {
  1663. /** --------------------------------------
  1664. /** Find Assigned Cats and Only Fetch Those
  1665. /** --------------------------------------*/
  1666. $xsql = '';
  1667. if ($page_id != '' OR $show_empty == 'n' OR $show_empty == 'no')
  1668. {
  1669. $this->show_these = array();
  1670. if ($page_id != '')
  1671. {
  1672. $query = $this->EE->db->query("SELECT cat_id FROM exp_wiki_category_articles WHERE page_id = '".$this->EE->db->escape_str($page_id)."'");
  1673. }
  1674. else
  1675. {
  1676. $query = $this->EE->db->query("SELECT DISTINCT cat_id FROM exp_wiki_category_articles");
  1677. }
  1678. if ($query->num_rows() == 0)
  1679. {
  1680. return FALSE;
  1681. }
  1682. foreach($query->result_array() as $row)
  1683. {
  1684. $this->show_these[] = $row['cat_id'];
  1685. }
  1686. }
  1687. $sql = "SELECT * FROM exp_wiki_categories
  1688. WHERE wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  1689. ORDER BY parent_id, cat_name";
  1690. $query = $this->EE->db->query($sql);
  1691. if ($query->num_rows() == 0)
  1692. {
  1693. return FALSE;
  1694. }
  1695. return $this->structure_categories($query);
  1696. }
  1697. /* -------------------------------------------
  1698. /* Structure Wiki Categories
  1699. /*
  1700. /* For the categories in the category array:
  1701. /* data => category data ($row)
  1702. /* depth => 0 (1, 2, etc.)
  1703. /* -------------------------------------------*/
  1704. function structure_categories($query, $start_cat='0')
  1705. {
  1706. $this->temp_array = array();
  1707. $parents = array();
  1708. foreach ($query->result_array() as $row)
  1709. {
  1710. $this->temp_array[$row['cat_id']] = array($row['cat_id'], $row['parent_id'], $row);
  1711. if ($row['parent_id'] > 0 && ! isset($this->temp_array[$row['parent_id']]))
  1712. {
  1713. $parents[$row['parent_id']] = '';
  1714. }
  1715. unset($parents[$row['cat_id']]);
  1716. }
  1717. $categories = array();
  1718. $last_parent = 0;
  1719. foreach($this->temp_array as $k => $v)
  1720. {
  1721. $this->cat_array = array();
  1722. $this->cat_depth = 0;
  1723. // If a child is missing its parent, then we assign it to the most
  1724. // recent top level parent.
  1725. if (isset($parents[$v['1']]))
  1726. {
  1727. $v['1'] = $last_parent;
  1728. }
  1729. if ($start_cat != $v['1'])
  1730. {
  1731. continue;
  1732. }
  1733. $last_parent = $k;
  1734. $p_cats = array($v['2']['cat_name']);
  1735. // If we are only showing some of the categories, collect all of the parent
  1736. // category names to send to process_subcategories
  1737. if ($start_cat != 0)
  1738. {
  1739. $this->find_parents($k, $k);
  1740. $p_cats = array_reverse($this->parent_cats[$k]);
  1741. }
  1742. $this->process_subcategories($k, $p_cats);
  1743. $categories[] = array($v['2'], $this->cat_array);
  1744. }
  1745. unset($this->temp_array);
  1746. unset($this->cat_array);
  1747. return $categories;
  1748. }
  1749. /** -------------------------------------------
  1750. /** Process Subcategories
  1751. /** -------------------------------------------*/
  1752. function process_subcategories($parent_id, $parents=array())
  1753. {
  1754. $this->cat_depth++;
  1755. foreach($this->temp_array as $key => $val)
  1756. {
  1757. if ($parent_id == $val['1'])
  1758. {
  1759. $this->cat_array[] = array('data' => $val['2'], 'depth' => $this->cat_depth, 'parents' => $parents);
  1760. $this->process_subcategories($key, array_merge($parents, array($val['2']['cat_name'])));
  1761. }
  1762. }
  1763. $this->cat_depth--;
  1764. }
  1765. /** -------------------------------------------
  1766. /** Find Parent Categories
  1767. /** -------------------------------------------*/
  1768. function find_parents($cat_id, $base_cat)
  1769. {
  1770. foreach ($this->temp_array as $v)
  1771. {
  1772. if ($cat_id == $v['0'])
  1773. {
  1774. $this->parent_cats[$base_cat][] = $v['2']["cat_name"];
  1775. if ($v['2']["parent_id"] != 0)
  1776. {
  1777. $this->find_parents($v['2']["parent_id"], $base_cat);
  1778. }
  1779. }
  1780. }
  1781. }
  1782. /* END */
  1783. /** ----------------------------------------
  1784. /** Edit
  1785. /** ----------------------------------------*/
  1786. function edit($title)
  1787. {
  1788. /** ----------------------------------------
  1789. /** Revision Edit
  1790. /** ----------------------------------------*/
  1791. if (preg_match("|revision\/([0-9]+)|i", $this->EE->uri->query_string, $url))
  1792. {
  1793. $revision_id = $url['1'];
  1794. $this->edit_revision($revision_id, $title);
  1795. return;
  1796. }
  1797. $this->return_data = $this->_deny_if('new_article', $this->return_data);
  1798. $this->return_data = $this->_deny_if('article', $this->return_data);
  1799. $this->return_data = $this->_deny_if('revision', $this->return_data);
  1800. $this->return_data = $this->_allow_if('edit_article', $this->return_data);
  1801. $this->return_data = $this->_deny_if('article_history', $this->return_data);
  1802. $this->return_data = $this->_deny_if('special_page', $this->return_data);
  1803. $this->return_data = $this->_deny_if('file_page', $this->return_data);
  1804. $this->return_data = $this->_deny_if('old_revision', $this->return_data);
  1805. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_edit.html'), $this->return_data);
  1806. $query = $this->topic_request($title);
  1807. /* -------------------------------------
  1808. /* 'edit_wiki_article_form_start' hook.
  1809. /* - Allows complete takeover of the wiki article edit form
  1810. /* - Added 1.6.0
  1811. */
  1812. $edata = $this->EE->extensions->universal_call('edit_wiki_article_form_start', $this, $title, $query);
  1813. if ($this->EE->extensions->end_script === TRUE) return;
  1814. /*
  1815. /* -------------------------------------*/
  1816. /** ----------------------------------------
  1817. /** Locked Article?
  1818. /** ----------------------------------------*/
  1819. if ($query->num_rows() == 0 OR $query->row('page_locked') != 'y')
  1820. {
  1821. $this->return_data = $this->_deny_if('locked', $this->return_data);
  1822. }
  1823. else
  1824. {
  1825. $this->return_data = $this->_allow_if('locked', $this->return_data);
  1826. }
  1827. /** ----------------------------------------
  1828. /** Moderated Article?
  1829. /** ----------------------------------------*/
  1830. if ($query->num_rows() == 0 OR $query->row('page_moderated') != 'y')
  1831. {
  1832. $this->return_data = $this->_deny_if('moderated', $this->return_data);
  1833. }
  1834. else
  1835. {
  1836. $this->return_data = $this->_allow_if('moderated', $this->return_data);
  1837. }
  1838. /** ----------------------------------------
  1839. /** Revision?
  1840. /** ----------------------------------------*/
  1841. if (preg_match("|revision\/([0-9]+)|i", $this->EE->uri->query_string, $url))
  1842. {
  1843. $revision_id = $url['1'];
  1844. }
  1845. /* ----------------------------------------
  1846. /* Can User Edit Article?
  1847. /*
  1848. /* If a Revision, No One Can Edit
  1849. /* If New Topic, Users and Admins Can Edit
  1850. /* If Unlocked Topic, Users and Admins Can Edit
  1851. /* If Locked Topic, Only Admins Can Edit
  1852. /* Everyone Else, No EDIT!
  1853. /* ----------------------------------------*/
  1854. if (isset($revision_id))
  1855. {
  1856. $this->return_data = $this->_deny_if('can_edit', $this->return_data);
  1857. $this->return_data = $this->_allow_if('cannot_edit', $this->return_data);
  1858. }
  1859. elseif($query->num_rows() == 0 && (in_array($this->EE->session->userdata['group_id'], $this->users) OR in_array($this->EE->session->userdata['group_id'], $this->admins)))
  1860. {
  1861. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  1862. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  1863. }
  1864. elseif($query->num_rows() == 0)
  1865. {
  1866. $this->return_data = $this->_deny_if('can_edit', $this->return_data);
  1867. $this->return_data = $this->_allow_if('cannot_edit', $this->return_data);
  1868. }
  1869. elseif($query->row('page_locked') != 'y' && (in_array($this->EE->session->userdata['group_id'], $this->users) OR in_array($this->EE->session->userdata['group_id'], $this->admins)))
  1870. {
  1871. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  1872. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  1873. }
  1874. elseif($query->row('page_locked') == 'y' && in_array($this->EE->session->userdata['group_id'], $this->admins))
  1875. {
  1876. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  1877. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  1878. }
  1879. else
  1880. {
  1881. $this->return_data = $this->_deny_if('can_edit', $this->return_data);
  1882. $this->return_data = $this->_allow_if('cannot_edit', $this->return_data);
  1883. }
  1884. /** ----------------------------------------
  1885. /** Current Revision's Content
  1886. /** ----------------------------------------*/
  1887. if ($query->num_rows() > 0)
  1888. {
  1889. if ($query->row('page_redirect') != '')
  1890. {
  1891. $content = '#REDIRECT [['.$query->row('page_redirect') .']]';
  1892. }
  1893. else
  1894. {
  1895. $results = $this->EE->db->query("SELECT page_content
  1896. FROM exp_wiki_revisions
  1897. WHERE page_id = '".$query->row('page_id') ."'
  1898. AND revision_status = 'open'
  1899. AND wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  1900. ORDER BY revision_date DESC LIMIT 1");
  1901. $content = ($results->num_rows() == 0) ? '' : $results->row('page_content') ;
  1902. }
  1903. $this->conditionals['redirect_page'] = $query->row('page_redirect') ;
  1904. $redirect_page = $query->row('page_redirect') ;
  1905. }
  1906. else
  1907. {
  1908. $content = '';
  1909. $redirect_page = '';
  1910. $this->conditionals['redirect_page'] = '';
  1911. }
  1912. /** ----------------------------------------
  1913. /** Bits of Data
  1914. /** ----------------------------------------*/
  1915. $data['action'] = $this->base_url.$title;
  1916. $data['id'] = 'edit_article_form';
  1917. $data['onsubmit'] = "if (is_preview) { this.action = '".$this->base_url.$title."/edit/'; }";
  1918. $data['hidden_fields'] = array(
  1919. 'title' => $title,
  1920. 'editing' => 'y'
  1921. );
  1922. $this->files();
  1923. $preview = '';
  1924. $revision_notes = '';
  1925. $rename = '';
  1926. /** ---------------------------------------
  1927. /** Preview?
  1928. /** ---------------------------------------*/
  1929. if ($this->EE->input->post('preview') === FALSE OR ! isset($_POST['article_content']))
  1930. {
  1931. $this->return_data = $this->_deny_if('preview', $this->return_data);
  1932. }
  1933. else
  1934. {
  1935. $this->return_data = $this->_allow_if('preview', $this->return_data);
  1936. $this->EE->load->library('typography');
  1937. $this->EE->typography->initialize();
  1938. $this->EE->typography->parse_images = FALSE;
  1939. $this->EE->typography->parse_smileys = FALSE;
  1940. $preview = $this->convert_curly_brackets($this->EE->typography->parse_type($this->wiki_syntax($_POST['article_content']),
  1941. array(
  1942. 'text_format' => $this->text_format,
  1943. 'html_format' => $this->html_format,
  1944. 'auto_links' => $this->auto_links,
  1945. 'allow_img_url' => 'y'
  1946. )
  1947. ));
  1948. $content = $_POST['article_content'];
  1949. $revision_notes = (isset($_POST['revision_notes'])) ? $_POST['revision_notes'] : '';
  1950. $rename = (isset($_POST['rename'])) ? $_POST['rename'] : '';
  1951. $redirect_page = (isset($_POST['redirect'])) ? $_POST['redirect'] : $redirect_page;
  1952. }
  1953. // Load the form helper
  1954. $this->EE->load->helper('form');
  1955. $this->return_data = str_replace(array(
  1956. '{form_declaration:wiki:edit}',
  1957. '{content}',
  1958. '{preview}',
  1959. '{redirect_page}',
  1960. '{path:redirect_page}',
  1961. '{revision_notes}',
  1962. '{rename}'
  1963. ),
  1964. array(
  1965. $this->EE->functions->form_declaration($data),
  1966. $this->encode_ee_tags(form_prep($content)),
  1967. $preview,
  1968. $this->encode_ee_tags(form_prep($this->prep_title($redirect_page))),
  1969. $this->EE->functions->create_url($this->base_path).$this->valid_title($redirect_page),
  1970. $this->encode_ee_tags(form_prep($revision_notes)),
  1971. $this->encode_ee_tags(form_prep($rename))
  1972. ),
  1973. $this->return_data);
  1974. /* -------------------------------------
  1975. /* 'edit_wiki_article_form_end' hook.
  1976. /* - Allows edit page to be modified
  1977. /* - Added 1.6.0
  1978. */
  1979. if ($this->EE->extensions->active_hook('edit_wiki_article_form_end') === TRUE)
  1980. {
  1981. $this->return_data = $this->EE->extensions->universal_call('edit_wiki_article_form_end', $this, $query);
  1982. if ($this->EE->extensions->end_script === TRUE) return;
  1983. }
  1984. /*
  1985. /* -------------------------------------*/
  1986. }
  1987. /** ----------------------------------------
  1988. /** Edit Revision
  1989. /** ----------------------------------------*/
  1990. function edit_revision($revision_id, $title)
  1991. {
  1992. $this->return_data = $this->_deny_if('new_article', $this->return_data);
  1993. $this->return_data = $this->_deny_if('article', $this->return_data);
  1994. $this->return_data = $this->_deny_if('revision', $this->return_data);
  1995. $this->return_data = $this->_allow_if('edit_article', $this->return_data);
  1996. $this->return_data = $this->_deny_if('article_history', $this->return_data);
  1997. $this->return_data = $this->_deny_if('special_page', $this->return_data);
  1998. $this->return_data = $this->_deny_if('file_page', $this->return_data);
  1999. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_edit.html'), $this->return_data);
  2000. $query = $this->topic_request($title);
  2001. if ($query->num_rows() == 0)
  2002. {
  2003. return FALSE;
  2004. }
  2005. /** ----------------------------------------
  2006. /** Locked Article?
  2007. /** ----------------------------------------*/
  2008. if ($query->row('page_locked') != 'y')
  2009. {
  2010. $this->return_data = $this->_deny_if('locked', $this->return_data);
  2011. }
  2012. else
  2013. {
  2014. $this->return_data = $this->_allow_if('locked', $this->return_data);
  2015. }
  2016. /** ----------------------------------------
  2017. /** Moderated Article?
  2018. /** ----------------------------------------*/
  2019. if ($query->row('page_moderated') != 'y')
  2020. {
  2021. $this->return_data = $this->_deny_if('moderated', $this->return_data);
  2022. }
  2023. else
  2024. {
  2025. $this->return_data = $this->_allow_if('moderated', $this->return_data);
  2026. }
  2027. /* ----------------------------------------
  2028. /* Can User Edit Revision?
  2029. /*
  2030. /* If Unlocked Topic, Users and Admins Can Edit
  2031. /* If Locked Topic, Only Admins Can Edit
  2032. /* Everyone Else, No EDIT!
  2033. /* ----------------------------------------*/
  2034. if($query->row('page_locked') != 'y' && (in_array($this->EE->session->userdata['group_id'], $this->users) OR in_array($this->EE->session->userdata['group_id'], $this->admins)))
  2035. {
  2036. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  2037. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  2038. }
  2039. elseif($query->row('page_locked') == 'y' && in_array($this->EE->session->userdata['group_id'], $this->admins))
  2040. {
  2041. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  2042. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  2043. }
  2044. else
  2045. {
  2046. $this->return_data = $this->_deny_if('can_edit', $this->return_data);
  2047. $this->return_data = $this->_allow_if('cannot_edit', $this->return_data);
  2048. }
  2049. /** ----------------------------------------
  2050. /** Current Revision's Content
  2051. /** ----------------------------------------*/
  2052. $results = $this->EE->db->query("SELECT page_content, revision_date, revision_notes, page_redirect
  2053. FROM exp_wiki_page p LEFT JOIN exp_wiki_revisions r ON r.page_id = p.page_id
  2054. WHERE p.page_id = '".$query->row('page_id')."'
  2055. AND revision_id = '".$this->EE->db->escape_str($revision_id)."'
  2056. AND p.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  2057. ORDER BY revision_date DESC LIMIT 1");
  2058. if ($results->row('revision_date') < $query->row('last_updated') )
  2059. {
  2060. $this->return_data = $this->_allow_if('old_revision', $this->return_data);
  2061. }
  2062. else
  2063. {
  2064. $this->return_data = $this->_deny_if('old_revision', $this->return_data);
  2065. }
  2066. $content = ($results->num_rows() == 0) ? '' : $results->row('page_content');
  2067. $revision_notes = ($results->num_rows() == 0) ? '' : $results->row('revision_notes');
  2068. $redirect = ($results->num_rows() == 0) ? '' : $results->row('page_redirect');
  2069. $this->conditionals['redirect_page'] = '';
  2070. /** ----------------------------------------
  2071. /** Bits of Data
  2072. /** ----------------------------------------*/
  2073. $data['action'] = $this->base_url.$title;
  2074. $data['id'] = 'edit_revision_form';
  2075. $data['hidden_fields'] = array(
  2076. 'title' => $title,
  2077. 'editing' => 'y'
  2078. );
  2079. $this->files();
  2080. // Load the form helper
  2081. $this->EE->load->helper('form');
  2082. $this->return_data = str_replace(array('{form_declaration:wiki:edit}', '{content}', '{redirect_page}', '{revision_notes}', '{rename}'), array($this->EE->functions->form_declaration($data), $this->encode_ee_tags(form_prep($content)), $redirect, $revision_notes, ''),
  2083. $this->return_data);
  2084. }
  2085. /** ----------------------------------------
  2086. /** History
  2087. /** ----------------------------------------*/
  2088. function history($title)
  2089. {
  2090. $this->return_data = $this->_deny_if('new_article', $this->return_data);
  2091. $this->return_data = $this->_deny_if('article', $this->return_data);
  2092. $this->return_data = $this->_deny_if('revision', $this->return_data);
  2093. $this->return_data = $this->_deny_if('edit_article', $this->return_data);
  2094. $this->return_data = $this->_allow_if('article_history', $this->return_data);
  2095. $this->return_data = $this->_deny_if('special_page', $this->return_data);
  2096. $this->return_data = $this->_deny_if('file_page', $this->return_data);
  2097. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_history.html'), $this->return_data);
  2098. $query = $this->topic_request($title);
  2099. if ($query->num_rows() > 0)
  2100. {
  2101. $xsql = (in_array($this->EE->session->userdata['group_id'], $this->admins)) ? '' : " AND r.revision_status = 'open' ";
  2102. $results = $this->EE->db->query("SELECT r.*, m.screen_name
  2103. FROM exp_wiki_revisions r, exp_members m
  2104. WHERE r.page_id = '".$query->row('page_id') ."'
  2105. AND r.revision_author = m.member_id
  2106. AND r.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  2107. {$xsql}
  2108. ORDER BY r.revision_date DESC");
  2109. }
  2110. if ($query->num_rows() == 0)
  2111. {
  2112. $this->return_data = $this->_deny_if('history', $this->return_data);
  2113. $this->return_data = $this->_allow_if('no_history', $this->return_data);
  2114. }
  2115. elseif ($results->num_rows() == 0)
  2116. {
  2117. $this->return_data = $this->_deny_if('history', $this->return_data);
  2118. $this->return_data = $this->_allow_if('no_history', $this->return_data);
  2119. }
  2120. else
  2121. {
  2122. $this->return_data = $this->_allow_if('history', $this->return_data);
  2123. $this->return_data = $this->_deny_if('no_history', $this->return_data);
  2124. }
  2125. /** ----------------------------------------
  2126. /** Redirects
  2127. /** ----------------------------------------*/
  2128. if ($query->num_rows() > 0 && $query->row('page_redirect') != '')
  2129. {
  2130. // There should be no revisions
  2131. }
  2132. /** ----------------------------------------
  2133. /** Locked Article?
  2134. /** ----------------------------------------*/
  2135. if ($query->num_rows() == 0 OR $query->row('page_locked') != 'y')
  2136. {
  2137. $this->return_data = $this->_deny_if('locked', $this->return_data);
  2138. }
  2139. else
  2140. {
  2141. $this->return_data = $this->_allow_if('locked', $this->return_data);
  2142. }
  2143. /* ----------------------------------------
  2144. /* Can User Edit Article?
  2145. /*
  2146. /* If New Topic, Users and Admins Can Edit
  2147. /* If Unlocked Topic, Users and Admins Can Edit
  2148. /* If Locked Topic, Only Admins Can Edit
  2149. /* Everyone Else, No EDIT!
  2150. /* ----------------------------------------*/
  2151. if($query->num_rows() == 0 && (in_array($this->EE->session->userdata['group_id'], $this->users) OR in_array($this->EE->session->userdata['group_id'], $this->admins)))
  2152. {
  2153. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  2154. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  2155. }
  2156. elseif($query->row('page_locked') != 'y' && (in_array($this->EE->session->userdata['group_id'], $this->users) OR in_array($this->EE->session->userdata['group_id'], $this->admins)))
  2157. {
  2158. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  2159. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  2160. }
  2161. elseif($query->row('page_locked') == 'y' && in_array($this->EE->session->userdata['group_id'], $this->admins))
  2162. {
  2163. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  2164. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  2165. }
  2166. else
  2167. {
  2168. $this->return_data = $this->_deny_if('can_edit', $this->return_data);
  2169. $this->return_data = $this->_allow_if('cannot_edit', $this->return_data);
  2170. }
  2171. /** ----------------------------------------
  2172. /** Current Revision's Content
  2173. /** ----------------------------------------*/
  2174. if (preg_match("/\{wiki:revisions.*?\}(.*?)\{\/wiki:revisions\}/s", $this->return_data, $match))
  2175. {
  2176. if ($query->num_rows() == 0)
  2177. {
  2178. $this->return_data = str_replace($match['0'], '', $this->return_data);
  2179. }
  2180. else
  2181. {
  2182. if ($results->num_rows() == 0)
  2183. {
  2184. $this->return_data = str_replace($match['0'], '', $this->return_data);
  2185. return;
  2186. }
  2187. if (preg_match("/\{revision_date.*?format=[\"|'](.*?)[\"|'].*?\}/", $match['1'], $date))
  2188. {
  2189. $date_format = ($date['1'] == '') ? array() : $this->EE->localize->fetch_date_params(str_replace(array(LD, RD), '', $date['1']));
  2190. }
  2191. /** ---------------------------------
  2192. /** Parse Our Results
  2193. /** ---------------------------------*/
  2194. $revisions = '';
  2195. $count = 0;
  2196. $vars = $this->EE->functions->assign_variables($match['1']);
  2197. foreach ($results->result_array() as $row)
  2198. {
  2199. $count++;
  2200. $temp = $match['1'];
  2201. if ($row['revision_notes'] == '')
  2202. {
  2203. $temp = $this->_deny_if('notes', $temp);
  2204. }
  2205. else
  2206. {
  2207. $temp = $this->_allow_if('notes', $temp);
  2208. }
  2209. $data = array( '{revision_author}' => $this->prep_screen_name($row['screen_name']),
  2210. '{revision_notes}' => $row['revision_notes'],
  2211. '{revision_status}' => $row['revision_status'],
  2212. '{path:member_profile}' => $this->EE->functions->create_url($this->profile_path.$row['revision_author']),
  2213. '{path:revision_link}' => $this->base_url.$title.'/revision/'.$row['revision_id'],
  2214. '{path:close_revision}' => $this->base_url.$title.'/revision/'.$row['revision_id'].'/close',
  2215. '{path:open_revision}' => $this->base_url.$title.'/revision/'.$row['revision_id'].'/open',
  2216. '{count}' => $count);
  2217. $temp = $this->prep_conditionals($temp, $data);
  2218. $temp = str_replace(array_keys($data), array_values($data), $temp);
  2219. foreach ($vars['var_single'] as $key => $val)
  2220. {
  2221. /** ----------------------------------------
  2222. /** parse {switch} variable
  2223. /** ----------------------------------------*/
  2224. if (preg_match("/^switch\s*=.+/i", $key))
  2225. {
  2226. $sparam = $this->EE->functions->assign_parameters($key);
  2227. $sw = '';
  2228. if (isset($sparam['switch']))
  2229. {
  2230. $sopt = explode("|", $sparam['switch']);
  2231. $sw = $sopt[($count-1 + count($sopt)) % count($sopt)];
  2232. }
  2233. $temp = $this->EE->TMPL->swap_var_single($key, $sw, $temp);
  2234. }
  2235. }
  2236. if (isset($date_format))
  2237. {
  2238. $temp_date = $date['1'];
  2239. foreach ($date_format as $dvar)
  2240. {
  2241. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $row['revision_date'], TRUE), $temp_date);
  2242. }
  2243. $temp = str_replace($date['0'], $temp_date, $temp);
  2244. }
  2245. $revisions .= $temp;
  2246. }
  2247. if (preg_match("/\{wiki:revisions.+?backspace=[\"|'](.+?)[\"|']/", $this->return_data, $backspace))
  2248. {
  2249. $revisions = substr($revisions, 0, - $backspace['1']);
  2250. }
  2251. $this->return_data = str_replace($match['0'], $revisions, $this->return_data);
  2252. }
  2253. }
  2254. }
  2255. /** ----------------------------------------
  2256. /** New Article
  2257. /** ----------------------------------------*/
  2258. function new_article($title, $original_page='')
  2259. {
  2260. $this->title = $title;
  2261. $this->return_data = $this->_allow_if('new_article', $this->return_data);
  2262. $this->return_data = $this->_allow_if('article', $this->return_data);
  2263. $this->return_data = $this->_deny_if('revision', $this->return_data);
  2264. $this->return_data = $this->_deny_if('edit_article', $this->return_data);
  2265. $this->return_data = $this->_deny_if('article_history', $this->return_data);
  2266. $this->return_data = $this->_deny_if('special_page', $this->return_data);
  2267. $this->return_data = $this->_deny_if('file_page', $this->return_data);
  2268. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_article.html'), $this->return_data);
  2269. $this->return_data = $this->_deny_if('categories', $this->return_data);
  2270. /* ----------------------------------------
  2271. /* Can User Edit Article?
  2272. /*
  2273. /* If New Topic, Users and Admins Can Edit
  2274. /* Everyone Else, No EDIT!
  2275. /* ----------------------------------------*/
  2276. if(in_array($this->EE->session->userdata['group_id'], $this->users) OR in_array($this->EE->session->userdata['group_id'], $this->admins))
  2277. {
  2278. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  2279. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  2280. }
  2281. else
  2282. {
  2283. $this->return_data = $this->_deny_if('can_edit', $this->return_data);
  2284. $this->return_data = $this->_allow_if('cannot_edit', $this->return_data);
  2285. }
  2286. if ($original_page != '')
  2287. {
  2288. $this->conditionals['original_page'] = $original_page;
  2289. $this->return_data = $this->_allow_if('redirected', $this->return_data);
  2290. $this->return_data = str_replace(array('{original_page}', '{path:original_page}'),
  2291. array($this->prep_title($original_page), $this->base_url.$original_page.'/noredirect'),
  2292. $this->return_data);
  2293. }
  2294. else
  2295. {
  2296. $this->return_data = $this->_deny_if('redirected', $this->return_data);
  2297. }
  2298. if ($this->current_namespace == $this->category_ns &&
  2299. (stristr($this->return_data, '{/wiki:category_subcategories}') OR stristr($this->return_data, '{wiki:category_articles}'))
  2300. )
  2301. {
  2302. $this->category_page();
  2303. }
  2304. $this->conditionals['author'] = '';
  2305. $this->return_data = str_replace(array('{author}', '{article}', '{content}'), '', $this->return_data);
  2306. }
  2307. /** ----------------------------------------
  2308. /** Article
  2309. /** ----------------------------------------*/
  2310. function article($title)
  2311. {
  2312. $redirects = array();
  2313. $query = $this->topic_request($title);
  2314. if ($query->num_rows() == 0)
  2315. {
  2316. return $this->new_article($title);
  2317. }
  2318. /* -------------------------------------
  2319. /* 'wiki_article_start' hook.
  2320. /* - Allows takeover of wiki article display
  2321. /* - Added 1.6.0
  2322. */
  2323. $edata = $this->EE->extensions->universal_call('wiki_article_start', $this, $title, $query);
  2324. if ($this->EE->extensions->end_script === TRUE) return;
  2325. /*
  2326. /* -------------------------------------*/
  2327. /** ----------------------------------------
  2328. /** Cancel Redirect?
  2329. /** ----------------------------------------*/
  2330. if ($query->row('page_redirect') != '' && preg_match("|".preg_quote($title)."/noredirect|i", $this->EE->uri->uri_string, $url))
  2331. {
  2332. $this->return_data = $this->_deny_if('new_article', $this->return_data);
  2333. $this->return_data = $this->_allow_if('article', $this->return_data);
  2334. $this->return_data = $this->_deny_if('revision', $this->return_data);
  2335. $this->return_data = $this->_deny_if('edit_article', $this->return_data);
  2336. $this->return_data = $this->_deny_if('article_history', $this->return_data);
  2337. $this->return_data = $this->_deny_if('special_page', $this->return_data);
  2338. $this->return_data = $this->_deny_if('file_page', $this->return_data);
  2339. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_article.html'), $this->return_data);
  2340. /* ----------------------------------------
  2341. /* Can User Edit Article?
  2342. /*
  2343. /* If Unlocked Topic, Users and Admins Can Edit
  2344. /* If Locked Topic, Only Admins Can Edit
  2345. /* Everyone Else, No EDIT!
  2346. /* ----------------------------------------*/
  2347. if($query->row('page_locked') != 'y' && (in_array($this->EE->session->userdata['group_id'], $this->users) OR in_array($this->EE->session->userdata['group_id'], $this->admins)))
  2348. {
  2349. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  2350. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  2351. }
  2352. elseif($query->row('page_locked') == 'y' && in_array($this->EE->session->userdata['group_id'], $this->admins))
  2353. {
  2354. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  2355. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  2356. }
  2357. else
  2358. {
  2359. $this->return_data = $this->_deny_if('can_edit', $this->return_data);
  2360. $this->return_data = $this->_allow_if('cannot_edit', $this->return_data);
  2361. }
  2362. $this->return_data = $this->_allow_if('redirect_page', $this->return_data);
  2363. $this->return_data = $this->_deny_if('redirected', $this->return_data);
  2364. $this->conditionals['redirect_page'] = $query->row('page_redirect') ;
  2365. $this->conditionals['author'] = ''; // No author for redirect
  2366. if ($this->current_namespace == $this->category_ns &&
  2367. (stristr($this->return_data, '{/wiki:category_'))
  2368. )
  2369. {
  2370. $this->return_data = preg_replace("/\{wiki:category_(.*?)\}(.*?)\{\/wiki:category_(.*?)\}/s", '', $this->return_data);
  2371. }
  2372. $this->return_data = str_replace(array('{author}', '{article}', '{content}', '{redirect_page}', '{path:redirect_page}'),
  2373. array('', '', '', $this->prep_title($query->row('page_redirect') ), $this->base_url.$this->valid_title($query->row('page_redirect'))),
  2374. $this->return_data);
  2375. /* -------------------------------------
  2376. /* 'wiki_article_end' hook.
  2377. /* - Allows article page to be modified
  2378. /* - Added 1.6.0
  2379. */
  2380. if ($this->EE->extensions->active_hook('wiki_article_end') === TRUE)
  2381. {
  2382. $this->return_data = $this->EE->extensions->universal_call('wiki_article_end', $this, $query);
  2383. if ($this->EE->extensions->end_script === TRUE) return;
  2384. }
  2385. /*
  2386. /* -------------------------------------*/
  2387. return;
  2388. }
  2389. /** ----------------------------------------
  2390. /** Follow the Redirects
  2391. /** ----------------------------------------*/
  2392. if ($query->row('page_redirect') != '')
  2393. {
  2394. $original_page = $title;
  2395. while($query->row('page_redirect') != '')
  2396. {
  2397. $redirects[] = $query->row('page_id') ;
  2398. $redirect_page = $query->row('page_redirect') ;
  2399. $query = $this->topic_request($query->row('page_redirect') );
  2400. if ($query->num_rows() == 0)
  2401. {
  2402. return $this->new_article($redirect_page, $title);
  2403. }
  2404. elseif(in_array($query->row('page_id') , $redirects))
  2405. {
  2406. break;
  2407. }
  2408. }
  2409. }
  2410. /** ----------------------------------------
  2411. /** Display Our Article
  2412. /** ----------------------------------------*/
  2413. $results = $this->EE->db->query("SELECT r.*, m.screen_name
  2414. FROM exp_wiki_revisions r, exp_members m
  2415. WHERE m.member_id = r.revision_author
  2416. AND r.page_id = '".$query->row('page_id') ."'
  2417. AND r.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  2418. AND r.revision_status = 'open'
  2419. ORDER BY r.revision_date DESC LIMIT 1");
  2420. if ($results->num_rows() == 0)
  2421. {
  2422. return $this->new_article($title);
  2423. }
  2424. $this->EE->load->library('typography');
  2425. $this->EE->typography->initialize();
  2426. $this->EE->typography->parse_images = FALSE;
  2427. $this->EE->typography->parse_smileys = FALSE;
  2428. $article = $this->convert_curly_brackets($this->EE->typography->parse_type( $this->wiki_syntax($results->row('page_content') ),
  2429. array(
  2430. 'text_format' => $this->text_format,
  2431. 'html_format' => $this->html_format,
  2432. 'auto_links' => $this->auto_links,
  2433. 'allow_img_url' => 'y'
  2434. )
  2435. ));
  2436. $this->return_data = $this->_deny_if('new_article', $this->return_data);
  2437. $this->return_data = $this->_allow_if('article', $this->return_data);
  2438. $this->return_data = $this->_deny_if('revision', $this->return_data);
  2439. $this->return_data = $this->_deny_if('edit_article', $this->return_data);
  2440. $this->return_data = $this->_deny_if('article_history', $this->return_data);
  2441. $this->return_data = $this->_deny_if('special_page', $this->return_data);
  2442. $this->return_data = $this->_deny_if('file_page', $this->return_data);
  2443. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_article.html'), $this->return_data);
  2444. if ($query->row('has_categories') == 'y')
  2445. {
  2446. $this->return_data = $this->_allow_if('categories', $this->return_data);
  2447. if (stristr($this->return_data, '{/wiki:categories'))
  2448. {
  2449. $this->categories($query->row('page_id') );
  2450. }
  2451. }
  2452. else
  2453. {
  2454. $this->return_data = $this->_deny_if('categories', $this->return_data);
  2455. }
  2456. /* ----------------------------------------
  2457. /* Can User Edit Article?
  2458. /*
  2459. /* If Unlocked Topic, Users and Admins Can Edit
  2460. /* If Locked Topic, Only Admins Can Edit
  2461. /* Everyone Else, No EDIT!
  2462. /* ----------------------------------------*/
  2463. if($query->row('page_locked') != 'y' && (in_array($this->EE->session->userdata['group_id'], $this->users) OR in_array($this->EE->session->userdata['group_id'], $this->admins)))
  2464. {
  2465. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  2466. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  2467. }
  2468. elseif($query->row('page_locked') == 'y' && in_array($this->EE->session->userdata['group_id'], $this->admins))
  2469. {
  2470. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  2471. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  2472. }
  2473. else
  2474. {
  2475. $this->return_data = $this->_deny_if('can_edit', $this->return_data);
  2476. $this->return_data = $this->_allow_if('cannot_edit', $this->return_data);
  2477. }
  2478. if (isset($original_page))
  2479. {
  2480. $this->return_data = $this->_allow_if('redirected', $this->return_data);
  2481. $this->conditionals['original_page'] = $original_page;
  2482. $this->return_data = str_replace(array('{original_page}', '{path:original_page}'),
  2483. array($this->prep_title($original_page), $this->base_url.$original_page.'/noredirect'),
  2484. $this->return_data);
  2485. }
  2486. else
  2487. {
  2488. $this->return_data = $this->_deny_if('redirected', $this->return_data);
  2489. }
  2490. $this->conditionals['author'] = $results->row('screen_name') ;
  2491. if ($this->current_namespace == $this->category_ns &&
  2492. (stristr($this->return_data, '{/wiki:category_subcategories}') OR stristr($this->return_data, '{wiki:category_articles}'))
  2493. )
  2494. {
  2495. $this->category_page();
  2496. }
  2497. $this->return_data = str_replace(array('{author}', '{article}', '{content}'), array($results->row('screen_name') , $article, $results->row('page_content') ), $this->return_data);
  2498. /* -------------------------------------
  2499. /* 'wiki_article_end' hook.
  2500. /* - Allows article page to be modified
  2501. /* - Added 1.6.0
  2502. */
  2503. if ($this->EE->extensions->active_hook('wiki_article_end') === TRUE)
  2504. {
  2505. $this->return_data = $this->EE->extensions->universal_call('wiki_article_end', $this, $query);
  2506. if ($this->EE->extensions->end_script === TRUE) return;
  2507. }
  2508. /*
  2509. /* -------------------------------------*/
  2510. }
  2511. /* END */
  2512. /** ---------------------------------------
  2513. /** Associated Pages, i.e. "What Links Here?"
  2514. /** ---------------------------------------*/
  2515. function associated_pages()
  2516. {
  2517. if ( ! isset($this->seg_parts['1']))
  2518. {
  2519. return;
  2520. }
  2521. $article_title = $this->prep_title($this->valid_title($this->EE->security->xss_clean(strip_tags($this->seg_parts['1']))));
  2522. $this->return_data = str_replace(LD.'wiki:page'.RD, $this->_fetch_template('wiki_special_associated_pages.html'), $this->return_data);
  2523. $this->return_data = str_replace(LD.'article_title'.RD, $article_title, $this->return_data);
  2524. $this->return_data = str_replace(LD.'path:view_orig_article'.RD, $this->create_url('', $article_title), $this->return_data);
  2525. if (preg_match("/\{wiki:associated_pages(.*?)\}(.*?)\{\/wiki:associated_pages\}/s", $this->return_data, $match))
  2526. {
  2527. $no_results = '';
  2528. $header = '';
  2529. $footer = '';
  2530. if (preg_match("|".LD."if\s+no_results".RD."(.*?)".LD."\/if".RD."|s",$match['2'], $block))
  2531. {
  2532. $no_results = $block['1'];
  2533. $match['2'] = str_replace($block['0'],'', $match['2']);
  2534. }
  2535. if (preg_match("|".LD."header".RD."(.*?)".LD."\/header".RD."|s",$match['2'], $block))
  2536. {
  2537. $header = $block['1'];
  2538. $match['2'] = str_replace($block['0'],'', $match['2']);
  2539. }
  2540. if (preg_match("|".LD."footer".RD."(.*?)".LD."\/footer".RD."|s",$match['2'], $block))
  2541. {
  2542. $footer = $block['1'];
  2543. $match['2'] = str_replace($block['0'],'', $match['2']);
  2544. }
  2545. // The last line of this query deserves some commenting.
  2546. // MySQL uses a POSIX regex implementation, one in particular that uses [[:>:]] to match the null
  2547. // string at the end of a word, i.e. the word boundary. There is no ereg_quote(), but preg_quote()
  2548. // escapes all of the necessary characters.
  2549. $query = $this->EE->db->query("SELECT p.page_name, n.namespace_label
  2550. FROM exp_wiki_page AS p
  2551. LEFT JOIN exp_wiki_namespaces AS n ON n.namespace_name = p.page_namespace
  2552. LEFT JOIN exp_wiki_revisions AS r ON r.revision_id = p.last_revision_id
  2553. WHERE r.page_content REGEXP '".$this->EE->db->escape_str(preg_quote('[['.$article_title))."[[:>:]].*".$this->EE->db->escape_str(preg_quote(']]'))."'
  2554. AND p.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'");
  2555. if ($query->num_rows() == 0)
  2556. {
  2557. $this->return_data = str_replace($match['0'], $no_results, $this->return_data);
  2558. return;
  2559. }
  2560. $output = '';
  2561. $count = 0;
  2562. $vars = $this->EE->functions->assign_variables($match['2']);
  2563. foreach ($query->result() as $row)
  2564. {
  2565. $temp = $match['2'];
  2566. $title = ($row->namespace_label != '') ? $row->namespace_label.':'.$row->page_name : $row->page_name;
  2567. $data = array(
  2568. 'title' => $this->prep_title($title),
  2569. 'count' => ++$count,
  2570. 'path:view_article' => $this->base_url.$title
  2571. );
  2572. foreach ($vars['var_single'] as $key => $val)
  2573. {
  2574. /** ----------------------------------------
  2575. /** parse {switch} variable
  2576. /** ----------------------------------------*/
  2577. if (preg_match("/^switch\s*=.+/i", $key))
  2578. {
  2579. $sparam = $this->EE->functions->assign_parameters($key);
  2580. $sw = '';
  2581. if (isset($sparam['switch']))
  2582. {
  2583. $sopt = explode("|", $sparam['switch']);
  2584. $sw = $sopt[($count-1 + count($sopt)) % count($sopt)];
  2585. }
  2586. $temp = $this->EE->TMPL->swap_var_single($key, $sw, $temp);
  2587. }
  2588. if (isset($data[$key]))
  2589. {
  2590. $temp = $this->EE->TMPL->swap_var_single($key, $data[$key], $temp);
  2591. }
  2592. }
  2593. $output .= $temp;
  2594. }
  2595. $this->return_data = str_replace($match['0'], $header.$output.$footer, $this->return_data);
  2596. }
  2597. }
  2598. /* END */
  2599. /** ----------------------------------------
  2600. /** Determine What Category
  2601. /** ----------------------------------------*/
  2602. function determine_category($topic)
  2603. {
  2604. $cats = explode($this->cats_separator, strtolower($topic));
  2605. $parent_id = 0;
  2606. /* ----------------------------------------
  2607. /* First We Find Our Category Based on Its Ancestory
  2608. /*
  2609. /* - Basically, we retrieve all of the categories for the category names
  2610. /* in the topic. As we allow nesting of categories, we might have
  2611. /* categories with the same name so we have to go through the categories
  2612. /* following the nesting to find the correct category at the bottom.
  2613. /* ----------------------------------------*/
  2614. $xsql = " AND LOWER(cat_name) IN ('";
  2615. foreach($cats as $cat)
  2616. {
  2617. $xsql .= $this->EE->db->escape_str($this->valid_title($cat))."','";
  2618. }
  2619. $xsql = substr($xsql, 0, -2).") ";
  2620. $query = $this->EE->db->query("SELECT cat_id, parent_id, cat_name
  2621. FROM exp_wiki_categories
  2622. WHERE wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  2623. {$xsql}
  2624. ORDER BY parent_id, cat_name");
  2625. $ancestry = array();
  2626. if ($query->num_rows() > 0)
  2627. {
  2628. while(count($cats) > 0)
  2629. {
  2630. $current = array_shift($cats);
  2631. $found = 'n';
  2632. foreach($query->result_array() as $row)
  2633. {
  2634. if (strtolower($this->valid_title($row['cat_name'])) == $current)
  2635. {
  2636. if (( ! isset($cat_id) && $row['parent_id'] == 0) OR (isset($cat_id) && $cat_id == $row['parent_id']))
  2637. {
  2638. $parent_id = $row['parent_id'];
  2639. $cat_id = $row['cat_id'];
  2640. $ancestry[] = $row['cat_name'];
  2641. $found = 'y';
  2642. continue;
  2643. }
  2644. }
  2645. }
  2646. if ($found == 'n' OR ! isset($cat_id))
  2647. {
  2648. $cat_id = 0;
  2649. $parent_id = 0;
  2650. break;
  2651. }
  2652. }
  2653. }
  2654. else
  2655. {
  2656. $cat_id = 0;
  2657. }
  2658. return array('cat_id' => $cat_id, 'parent_id' => $parent_id, 'ancestry' => $ancestry);
  2659. }
  2660. /** ----------------------------------------
  2661. /** Category Page Processing
  2662. /** ----------------------------------------*/
  2663. function category_page()
  2664. {
  2665. $cat_data = $this->determine_category($this->topic);
  2666. extract($cat_data);
  2667. /** ----------------------------------------
  2668. /** Display All of the Subcategories for a Category
  2669. /** ----------------------------------------*/
  2670. if (preg_match("/\{wiki:category_subcategories(.*?)\}(.*?)\{\/wiki:category_subcategories\}/s", $this->return_data, $match))
  2671. {
  2672. /** ----------------------------------------
  2673. /** Parameters and Variables
  2674. /** ----------------------------------------*/
  2675. $no_results = '';
  2676. $header = '';
  2677. $footer = '';
  2678. $backspace = '';
  2679. $style = '';
  2680. if (trim($match['1']) != '' && ($params = $this->EE->functions->assign_parameters($match['1'])) !== FALSE)
  2681. {
  2682. $backspace = (isset($params['backspace']) && is_numeric($params['backspace'])) ? $params['backspace'] : $backspace;
  2683. $style = (isset($params['style'])) ? $params['style'] : $style;
  2684. }
  2685. if (preg_match("|".LD."if\s+no_results".RD."(.*?)".LD."\/if".RD."|s",$match['2'], $block))
  2686. {
  2687. $no_results = $block['1'];
  2688. $match['2'] = str_replace($block['0'],'', $match['2']);
  2689. }
  2690. if (preg_match("|".LD."header".RD."(.*?)".LD."\/header".RD."|s",$match['2'], $block))
  2691. {
  2692. $header = $block['1'];
  2693. $match['2'] = str_replace($block['0'],'', $match['2']);
  2694. }
  2695. if (preg_match("|".LD."footer".RD."(.*?)".LD."\/footer".RD."|s",$match['2'], $block))
  2696. {
  2697. $footer = $block['1'];
  2698. $match['2'] = str_replace($block['0'],'', $match['2']);
  2699. }
  2700. /** ----------------------------------------
  2701. /** Parsing and Output
  2702. /** ----------------------------------------*/
  2703. $data = $no_results;
  2704. $subs = 0;
  2705. if ($cat_id !== 0)
  2706. {
  2707. $query = $this->EE->db->query("SELECT COUNT(*) AS count FROM exp_wiki_categories
  2708. WHERE wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  2709. AND parent_id = '".$this->EE->db->escape_str($cat_id)."'
  2710. ORDER BY parent_id, cat_name");
  2711. if ($query->row('count') > 0)
  2712. {
  2713. $subs = $query->row('count') ;
  2714. $query = $this->EE->db->query("SELECT * FROM exp_wiki_categories
  2715. WHERE wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  2716. ORDER BY parent_id, cat_name");
  2717. $data = $header;
  2718. $data .= $this->parse_categories($this->structure_categories($query, $cat_id), $match['2'], 'nested', 0, $ancestry);
  2719. $data .= $footer;
  2720. }
  2721. }
  2722. $this->conditionals['subcategory_total'] = $subs;
  2723. $this->return_data = str_replace($match['0'], str_replace('{subcategory_total}', $subs, $data), $this->return_data);
  2724. }
  2725. /** ----------------------------------------
  2726. /** Display All of Articles for the Category
  2727. /** ----------------------------------------*/
  2728. if (preg_match("/\{wiki:category_articles(.*?)\}(.*?)\{\/wiki:category_articles\}/s", $this->return_data, $match))
  2729. {
  2730. /** ----------------------------------------
  2731. /** Parameters and Variables
  2732. /** ----------------------------------------*/
  2733. $no_results = '';
  2734. $header = '';
  2735. $footer = '';
  2736. $parameters['backspace'] = '';
  2737. $parameters['limit'] = 100;
  2738. $parameters['paginate'] = 'bottom';
  2739. if (trim($match['1']) != '' && ($params = $this->EE->functions->assign_parameters($match['1'])) !== FALSE)
  2740. {
  2741. $parameters['backspace'] = (isset($params['backspace']) && is_numeric($params['backspace'])) ? $params['backspace'] : $parameters['backspace'];
  2742. $parameters['limit'] = (isset($params['limit'])) ? $params['limit'] : $parameters['limit'];
  2743. $parameters['paginate'] = (isset($params['paginate'])) ? $params['paginate'] : $parameters['paginate'];
  2744. }
  2745. if (preg_match("|".LD."if\s+no_results".RD."(.*?)".LD."\/if".RD."|s",$match['2'], $block))
  2746. {
  2747. $no_results = $block['1'];
  2748. $match['2'] = str_replace($block['0'],'', $match['2']);
  2749. }
  2750. if (preg_match("|".LD."header".RD."(.*?)".LD."\/header".RD."|s",$match['2'], $block))
  2751. {
  2752. $header = $block['1'];
  2753. $match['2'] = str_replace($block['0'],'', $match['2']);
  2754. }
  2755. if (preg_match("|".LD."footer".RD."(.*?)".LD."\/footer".RD."|s",$match['2'], $block))
  2756. {
  2757. $footer = $block['1'];
  2758. $match['2'] = str_replace($block['0'],'', $match['2']);
  2759. }
  2760. /** ----------------------------------------
  2761. /** Parsing and Output
  2762. /** ----------------------------------------*/
  2763. $data = $no_results;
  2764. $articles_total = 0;
  2765. if ($cat_id !== 0)
  2766. {
  2767. $sql = "FROM exp_wiki_category_articles ca, exp_wiki_page p, exp_wiki_revisions r, exp_members m
  2768. WHERE ca.cat_id = '".$this->EE->db->escape_str($cat_id)."'
  2769. AND ca.page_id = p.page_id
  2770. AND p.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  2771. AND p.page_id = r.page_id
  2772. AND p.last_updated = r.revision_date
  2773. AND m.member_id = r.revision_author
  2774. AND r.revision_status = 'open'";
  2775. $query = $this->EE->db->query("SELECT COUNT(p.page_id) AS count ".$sql);
  2776. if ($query->row('count') > 0)
  2777. {
  2778. $articles_total = $query->row('count') ;
  2779. $this->pagination($query->row('count') , $parameters['limit'], $this->base_url.$this->category_ns.':'.$this->topic);
  2780. // Pagination code removed, rerun template preg_match()
  2781. if ($this->paginate === TRUE)
  2782. {
  2783. preg_match("/\{wiki:category_articles(.*?)\}(.*?)\{\/wiki:category_articles\}/s", $this->return_data, $match);
  2784. if (preg_match("|".LD."if\s+no_results".RD."(.*?)".LD."\/if".RD."|s",$match['2'], $block))
  2785. {
  2786. $no_results = $block['1'];
  2787. $match['2'] = str_replace($block['0'],'', $match['2']);
  2788. }
  2789. if (preg_match("|".LD."header".RD."(.*?)".LD."\/header".RD."|s",$match['2'], $block))
  2790. {
  2791. $header = $block['1'];
  2792. $match['2'] = str_replace($block['0'],'', $match['2']);
  2793. }
  2794. if (preg_match("|".LD."footer".RD."(.*?)".LD."\/footer".RD."|s",$match['2'], $block))
  2795. {
  2796. $footer = $block['1'];
  2797. $match['2'] = str_replace($block['0'],'', $match['2']);
  2798. }
  2799. }
  2800. else
  2801. {
  2802. $this->pagination_sql .= " LIMIT ".$parameters['limit'];
  2803. }
  2804. $query = $this->EE->db->query("SELECT r.*, m.member_id, m.screen_name, m.email, m.url, p.page_namespace, p.page_name AS topic ".
  2805. $sql.
  2806. " ORDER BY topic ".
  2807. $this->pagination_sql);
  2808. $data = $header;
  2809. $data .= $this->parse_results($match, $query, $parameters, $this->parse_dates($match['2']));
  2810. $data .= $footer;
  2811. }
  2812. }
  2813. $this->conditionals['articles_total'] = $articles_total;
  2814. $this->return_data = str_replace($match['0'], str_replace('{articles_total}', $articles_total, $data), $this->return_data);
  2815. }
  2816. }
  2817. /** ----------------------------------------
  2818. /** Parse Dates Out of String
  2819. /** ----------------------------------------*/
  2820. function parse_dates($str)
  2821. {
  2822. $dates = array();
  2823. if (preg_match_all("/".LD."(gmt_last_updated|gmt_revision_date|last_updated|revision_date)\s+format=[\"'](.*?)[\"']".RD."/s", $this->return_data, $matches))
  2824. {
  2825. for ($j = 0; $j < count($matches['0']); $j++)
  2826. {
  2827. switch ($matches['1'][$j])
  2828. {
  2829. case 'gmt_last_updated' : $dates['gmt_last_updated'][$matches['0'][$j]] = array($matches['2'][$j], $this->EE->localize->fetch_date_params($matches['2'][$j]));
  2830. break;
  2831. case 'last_updated' : $dates['last_updated'][$matches['0'][$j]] = array($matches['2'][$j], $this->EE->localize->fetch_date_params($matches['2'][$j]));
  2832. break;
  2833. case 'gmt_revision_date' : $dates['gmt_revision_date'][$matches['0'][$j]] = array($matches['2'][$j], $this->EE->localize->fetch_date_params($matches['2'][$j]));
  2834. break;
  2835. case 'revision_date' : $dates['revision_date'][$matches['0'][$j]] = array($matches['2'][$j], $this->EE->localize->fetch_date_params($matches['2'][$j]));
  2836. break;
  2837. }
  2838. }
  2839. }
  2840. return $dates;
  2841. }
  2842. /** ----------------------------------------
  2843. /** Revision
  2844. /** ----------------------------------------*/
  2845. function revision($title)
  2846. {
  2847. $redirects = array();
  2848. $query = $this->topic_request($title);
  2849. if ($query->num_rows() == 0)
  2850. {
  2851. return $this->article($title);
  2852. }
  2853. /** ----------------------------------------
  2854. /** Do Not Follow Redirects
  2855. /** ----------------------------------------*/
  2856. if ($query->row('page_redirect') != '')
  2857. {
  2858. }
  2859. /** ----------------------------------------
  2860. /** Display Our Revision
  2861. /** ----------------------------------------*/
  2862. if (preg_match("|revision\/([0-9]+)|i", $this->EE->uri->query_string, $url))
  2863. {
  2864. $revision_id = $url['1'];
  2865. if (preg_match("|revision\/".$revision_id."\/([a-z]+)|i", $this->EE->uri->query_string, $url))
  2866. {
  2867. switch($url['1'])
  2868. {
  2869. case 'edit' :
  2870. $this->edit_revision($revision_id, $title);
  2871. return;
  2872. break;
  2873. case 'open' :
  2874. $this->open_close_revision($title, $revision_id, 'open');
  2875. break;
  2876. case 'close' :
  2877. $this->open_close_revision($title, $revision_id, 'closed');
  2878. break;
  2879. }
  2880. }
  2881. }
  2882. else
  2883. {
  2884. return $this->article($title);
  2885. }
  2886. $xsql = (in_array($this->EE->session->userdata['group_id'], $this->admins)) ? '' : " AND r.revision_status = 'open' ";
  2887. $results = $this->EE->db->query("SELECT r.*, m.screen_name
  2888. FROM exp_wiki_revisions r, exp_members m
  2889. WHERE m.member_id = r.revision_author
  2890. AND r.page_id = '".$query->row('page_id') ."'
  2891. AND r.revision_id = '".$this->EE->db->escape_str($revision_id)."'
  2892. AND r.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  2893. {$xsql}
  2894. ORDER BY r.revision_date DESC LIMIT 1");
  2895. if ($results->num_rows() == 0)
  2896. {
  2897. return $this->article($title);
  2898. }
  2899. $this->return_data = $this->_deny_if('new_article', $this->return_data);
  2900. $this->return_data = $this->_deny_if('article', $this->return_data);
  2901. $this->return_data = $this->_allow_if('revision', $this->return_data);
  2902. $this->return_data = $this->_deny_if('edit_article', $this->return_data);
  2903. $this->return_data = $this->_deny_if('article_history', $this->return_data);
  2904. $this->return_data = $this->_deny_if('special_page', $this->return_data);
  2905. $this->return_data = $this->_deny_if('file_page', $this->return_data);
  2906. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_article.html'), $this->return_data);
  2907. if ($query->row('has_categories') == 'y')
  2908. {
  2909. $this->return_data = $this->_allow_if('categories', $this->return_data);
  2910. if (stristr($this->return_data, '{/wiki:categories'))
  2911. {
  2912. $this->categories($query->row('page_id') );
  2913. }
  2914. }
  2915. else
  2916. {
  2917. $this->return_data = $this->_deny_if('categories', $this->return_data);
  2918. }
  2919. /** ----------------------------------------
  2920. /** Date Formats
  2921. /** ----------------------------------------*/
  2922. if (preg_match_all("/".LD."(revision_date)\s+format=[\"'](.*?)[\"']".RD."/s", $this->return_data, $matches))
  2923. {
  2924. $revision_date = array();
  2925. for ($j = 0; $j < count($matches['0']); $j++)
  2926. {
  2927. switch ($matches['1'][$j])
  2928. {
  2929. case 'revision_date' : $revision_date[$matches['0'][$j]] = array($matches['2'][$j], $this->EE->localize->fetch_date_params($matches['2'][$j]));
  2930. break;
  2931. }
  2932. }
  2933. foreach($revision_date as $key => $value)
  2934. {
  2935. $temp_date = $value['0'];
  2936. foreach ($value['1'] as $dvar)
  2937. {
  2938. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $results->row('revision_date') , TRUE), $temp_date);
  2939. }
  2940. $this->return_data = str_replace($key, $temp_date, $this->return_data);
  2941. }
  2942. }
  2943. $this->EE->load->library('typography');
  2944. $this->EE->typography->initialize();
  2945. $this->EE->typography->parse_images = FALSE;
  2946. $this->EE->typography->parse_smileys = FALSE;
  2947. $article = $this->convert_curly_brackets($this->EE->typography->parse_type( $this->wiki_syntax($results->row('page_content') ),
  2948. array(
  2949. 'text_format' => $this->text_format,
  2950. 'html_format' => $this->html_format,
  2951. 'auto_links' => $this->auto_links,
  2952. 'allow_img_url' => 'y'
  2953. )
  2954. ));
  2955. /* ----------------------------------------
  2956. /* Can User Edit Article?
  2957. /*
  2958. /* If Unlocked Topic, Users and Admins Can Edit
  2959. /* If Locked Topic, Only Admins Can Edit
  2960. /* Everyone Else, No EDIT!
  2961. /* ----------------------------------------*/
  2962. if($query->row('page_locked') != 'y' && (in_array($this->EE->session->userdata['group_id'], $this->users) OR in_array($this->EE->session->userdata['group_id'], $this->admins)))
  2963. {
  2964. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  2965. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  2966. }
  2967. elseif($query->row('page_locked') == 'y' && in_array($this->EE->session->userdata['group_id'], $this->admins))
  2968. {
  2969. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  2970. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  2971. }
  2972. else
  2973. {
  2974. $this->return_data = $this->_deny_if('can_edit', $this->return_data);
  2975. $this->return_data = $this->_allow_if('cannot_edit', $this->return_data);
  2976. }
  2977. $this->return_data = preg_replace('/\{wiki:(category_articles|category_subcategories)[^\}]*\}.*?\{\/wiki:\\1\}/si', '', $this->return_data);
  2978. $this->revision_id = $revision_id;
  2979. $this->return_data = str_replace(array('{article}', '{content}'), array($article, $results->row('page_content') ), $this->return_data);
  2980. }
  2981. /** ----------------------------------------
  2982. /** Active Members
  2983. /** ----------------------------------------*/
  2984. function active_members($str)
  2985. {
  2986. if ( ! preg_match("/\{wiki:active_members.*?\}(.*?)\{\/wiki:active_members\}/s", $str, $match))
  2987. {
  2988. return $str;
  2989. }
  2990. if (count($this->EE->stats->statdata('current_names')) == 0)
  2991. {
  2992. return str_replace($match['0'], '', $str);
  2993. }
  2994. /** ---------------------------------
  2995. /** Parse the Names Out Into Template
  2996. /** ---------------------------------*/
  2997. $names = '';
  2998. foreach ($this->EE->stats->statdata('current_names') as $k => $v)
  2999. {
  3000. $temp = $match['1'];
  3001. if ($v['1'] == 'y')
  3002. {
  3003. if ($this->EE->session->userdata['group_id'] == 1)
  3004. {
  3005. $temp = str_replace('{name}', $v['0'].'*', $temp);
  3006. }
  3007. elseif ($this->EE->session->userdata['member_id'] == $k)
  3008. {
  3009. $temp = str_replace('{name}', $v['0'].'*', $temp);
  3010. }
  3011. else
  3012. {
  3013. continue;
  3014. }
  3015. }
  3016. else
  3017. {
  3018. $temp = str_replace('{name}', $v['0'], $temp);
  3019. }
  3020. $temp = str_replace('{path:member_profile}', $this->EE->functions->create_url($this->profile_path.$k), $temp);
  3021. $names .= $temp;
  3022. }
  3023. if (preg_match("/\{wiki:active_members.+?backspace=[\"|'](.+?)[\"|']/", $str, $backspace))
  3024. {
  3025. $names = substr($names, 0, - $backspace['1']);
  3026. }
  3027. return str_replace($match['0'], $names, $str);
  3028. }
  3029. /* -------------------------------------
  3030. /* Conditional Helpers
  3031. /* - Since we are putting the wiki into a template
  3032. /* then I thought we might want to use the already existing
  3033. /* conditional parser and evaluator to do conditionals for us.
  3034. /* -------------------------------------*/
  3035. function _deny_if($cond, $str)
  3036. {
  3037. $this->conditionals[$cond] = 'FALSE';
  3038. return preg_replace("/\{if\s+".$cond."\}/si", "{if FALSE}", $str);
  3039. }
  3040. function _allow_if($cond, $str)
  3041. {
  3042. $this->conditionals[$cond] = 'TRUE';
  3043. return preg_replace("/\{if\s+".$cond."\}/si", "{if TRUE}", $str);
  3044. }
  3045. /** -------------------------------------
  3046. /** Edit Article
  3047. /** -------------------------------------*/
  3048. function edit_article()
  3049. {
  3050. if ($this->EE->input->post('editing') === FALSE OR $this->EE->input->get_post('title') === FALSE OR $this->EE->input->get_post('title') == '' OR $this->EE->input->get_post('article_content') === FALSE)
  3051. {
  3052. return $this->EE->output->show_user_error('general', array($this->EE->lang->line('invalid_permissions')));
  3053. }
  3054. if ( ! in_array($this->EE->session->userdata['group_id'], $this->users) && ! in_array($this->EE->session->userdata['group_id'], $this->admins))
  3055. {
  3056. return $this->EE->output->show_user_error('general', array($this->EE->lang->line('invalid_permissions')));
  3057. }
  3058. /** -------------------------------------
  3059. /** Edit Limit
  3060. /** -------------------------------------*/
  3061. $this->edit_limit();
  3062. /** -------------------------------------
  3063. /** Secure Forms
  3064. /** -------------------------------------*/
  3065. // If the hash is not found we'll simply reload the page.
  3066. if ($this->EE->config->item('secure_forms') == 'y')
  3067. {
  3068. $query = $this->EE->db->query("SELECT COUNT(*) AS count FROM exp_security_hashes
  3069. WHERE hash='".$this->EE->db->escape_str($_POST['XID'])."'
  3070. AND ip_address = '".$this->EE->input->ip_address()."'
  3071. AND date > UNIX_TIMESTAMP()-7200");
  3072. if ($query->row('count') == 0)
  3073. {
  3074. $this->redirect('', $this->EE->input->get_post('title'));
  3075. }
  3076. $this->EE->db->query("DELETE FROM exp_security_hashes WHERE (hash='".$this->EE->db->escape_str($_POST['XID'])."' AND ip_address = '".$this->EE->input->ip_address()."') OR date < UNIX_TIMESTAMP()-7200");
  3077. }
  3078. /** -------------------------------------
  3079. /** Process Edit Form
  3080. /** -------------------------------------*/
  3081. $query = $this->topic_request($this->valid_title($this->EE->input->get_post('title')));
  3082. if ($query->num_rows() == 0)
  3083. {
  3084. $current_name = strtolower($this->current_namespace);
  3085. $key = '';
  3086. foreach ($this->namespaces as $name => $label)
  3087. {
  3088. if ($current_name == strtolower($label['1']))
  3089. {
  3090. $key = $label['0'];
  3091. break;
  3092. }
  3093. }
  3094. $data = array('page_name' => $this->topic,
  3095. 'page_namespace' => $key, // Namespace's Short Name from Label
  3096. 'last_updated' => $this->EE->localize->now,
  3097. 'wiki_id' => $this->wiki_id);
  3098. if (in_array($this->EE->session->userdata['group_id'], $this->admins))
  3099. {
  3100. if ($this->EE->input->get_post('delete_article') == 'y' && $this->current_namespace == $this->category_ns)
  3101. {
  3102. $cat_data = $this->determine_category($this->topic);
  3103. if ($cat_data['cat_id'] != 0)
  3104. {
  3105. $results = $this->EE->db->query("SELECT page_id FROM exp_wiki_category_articles WHERE cat_id = '".$this->EE->db->escape_str($cat_data['cat_id'])."'");
  3106. if ($results->num_rows() > 0)
  3107. {
  3108. foreach($results->result_array() as $row)
  3109. {
  3110. $count = $this->EE->db->query("SELECT (COUNT(*) - 1) AS count FROM exp_wiki_category_articles WHERE page_id = '".$this->EE->db->escape_str($row['page_id'])."'");
  3111. if ($count->row('count') == 0)
  3112. {
  3113. $this->EE->db->query("UPDATE exp_wiki_page SET has_categories = 'n' WHERE page_id = '".$this->EE->db->escape_str($row['page_id'])."'");
  3114. }
  3115. }
  3116. }
  3117. $this->EE->db->query("DELETE FROM exp_wiki_category_articles WHERE cat_id = '".$this->EE->db->escape_str($cat_data['cat_id'])."'");
  3118. $this->EE->db->query("DELETE FROM exp_wiki_categories WHERE cat_id = '".$this->EE->db->escape_str($cat_data['cat_id'])."'");
  3119. $this->EE->db->query("UPDATE exp_wiki_categories SET parent_id = '0' WHERE parent_id = '".$this->EE->db->escape_str($cat_data['cat_id'])."'");
  3120. }
  3121. }
  3122. elseif ($this->EE->input->get_post('delete_article') == 'y')
  3123. {
  3124. $this->redirect('', $this->title);
  3125. }
  3126. if ($this->EE->input->get_post('lock_article') == 'y')
  3127. {
  3128. $data['page_locked'] = 'y';
  3129. }
  3130. if ($this->EE->input->get_post('moderate_article') == 'y')
  3131. {
  3132. $data['page_moderated'] = 'y';
  3133. }
  3134. }
  3135. if ($this->EE->input->get_post('redirect') !== FALSE)
  3136. {
  3137. $data['page_redirect'] = $this->valid_title($this->EE->input->get_post('redirect'));
  3138. }
  3139. $data['last_updated'] = $this->EE->localize->now;
  3140. $this->EE->db->query($this->EE->db->insert_string('exp_wiki_page', $data));
  3141. $page_id = $this->EE->db->insert_id();
  3142. }
  3143. else
  3144. {
  3145. $page_id = $query->row('page_id') ;
  3146. if ($this->EE->input->get_post('delete_article') == 'y' && in_array($this->EE->session->userdata['group_id'], $this->admins))
  3147. {
  3148. if ($this->current_namespace == $this->category_ns)
  3149. {
  3150. $cat_data = $this->determine_category($this->topic);
  3151. if ($cat_data['cat_id'] != 0)
  3152. {
  3153. $results = $this->EE->db->query("SELECT page_id FROM exp_wiki_category_articles WHERE cat_id = '".$this->EE->db->escape_str($cat_data['cat_id'])."'");
  3154. if ($results->num_rows() > 0)
  3155. {
  3156. foreach($results->result_array() as $row)
  3157. {
  3158. $count = $this->EE->db->query("SELECT (COUNT(*) - 1) AS count FROM exp_wiki_category_articles WHERE page_id = '".$this->EE->db->escape_str($row['page_id'])."'");
  3159. if ($count->row('count') == 0)
  3160. {
  3161. $this->EE->db->query("UPDATE exp_wiki_page SET has_categories = 'n' WHERE page_id = '".$this->EE->db->escape_str($row['page_id'])."'");
  3162. }
  3163. }
  3164. }
  3165. $this->EE->db->query("DELETE FROM exp_wiki_category_articles WHERE cat_id = '".$this->EE->db->escape_str($cat_data['cat_id'])."'");
  3166. $this->EE->db->query("DELETE FROM exp_wiki_categories WHERE cat_id = '".$this->EE->db->escape_str($cat_data['cat_id'])."'");
  3167. $this->EE->db->query("UPDATE exp_wiki_categories SET parent_id = '0' WHERE parent_id = '".$this->EE->db->escape_str($cat_data['cat_id'])."'");
  3168. }
  3169. }
  3170. $this->EE->db->query("DELETE FROM exp_wiki_page WHERE page_id = '".$this->EE->db->escape_str($page_id)."'");
  3171. $this->EE->db->query("DELETE FROM exp_wiki_revisions WHERE page_id = '".$this->EE->db->escape_str($page_id)."'");
  3172. $this->EE->db->query("DELETE FROM exp_wiki_category_articles WHERE page_id = '".$this->EE->db->escape_str($page_id)."'");
  3173. $this->redirect('', $this->title);
  3174. }
  3175. if ($query->row('page_locked') == 'y' && ! in_array($this->EE->session->userdata['group_id'], $this->admins))
  3176. {
  3177. return $this->EE->output->show_user_error('general', array($this->EE->lang->line('invalid_permissions')));
  3178. }
  3179. if ($query->row('page_moderated') == 'y' && ! in_array($this->EE->session->userdata['group_id'], $this->admins))
  3180. {
  3181. $data = array('last_updated' => $query->row('last_updated') );
  3182. }
  3183. else
  3184. {
  3185. $data = array('last_updated' => $this->EE->localize->now);
  3186. }
  3187. if ($this->EE->input->get_post('redirect') !== FALSE)
  3188. {
  3189. $data['page_redirect'] = $this->valid_title($this->EE->input->get_post('redirect'));
  3190. }
  3191. if (in_array($this->EE->session->userdata['group_id'], $this->admins))
  3192. {
  3193. $data['page_locked'] = ($this->EE->input->get_post('lock_article') == 'y') ? 'y' : 'n';
  3194. $data['page_moderated'] = ($this->EE->input->get_post('moderate_article') == 'y') ? 'y' : 'n';
  3195. if ($this->EE->input->get_post('rename') !== FALSE && $this->EE->input->get_post('rename') != '')
  3196. {
  3197. // Default
  3198. $this->topic = $this->valid_title($this->EE->input->get_post('rename'));
  3199. $this->title = $this->topic;
  3200. $this->current_namespace = '';
  3201. $data['page_name'] = $this->topic;
  3202. $data['page_namespace'] = '';
  3203. if (stristr($this->EE->input->get_post('rename'), ':') && count($this->namespaces) > 0)
  3204. {
  3205. $parts = explode(':', $this->EE->input->get_post('rename'), 2);
  3206. foreach($this->namespaces as $name => $label)
  3207. {
  3208. if ($label['1'] == $parts['0'])
  3209. {
  3210. $data['page_namespace'] = $name;
  3211. $data['page_name'] = $this->valid_title(substr($this->EE->input->get_post('rename'), strlen($label.':')));
  3212. $this->title = $label['1'].':'.$data['page_name'];
  3213. $this->topic = $data['page_name'];
  3214. $this->current_namespace = $label['1'];
  3215. break;
  3216. }
  3217. }
  3218. }
  3219. $t_query = $this->EE->db->query("SELECT COUNT(*) AS count FROM exp_wiki_page WHERE page_name = '".$this->EE->db->escape_str($data['page_name'])."' AND LOWER(page_namespace) = '".$this->EE->db->escape_str($data['page_namespace'])."'");
  3220. if ($t_query->row('count') > 0)
  3221. {
  3222. return $this->EE->output->show_user_error('general', array($this->EE->lang->line('duplicate_article')));
  3223. }
  3224. }
  3225. }
  3226. $this->EE->db->query($this->EE->db->update_string('exp_wiki_page', $data, "page_id = '".$this->EE->db->escape_str($page_id)."'"));
  3227. }
  3228. /** -------------------------------------
  3229. /** Process Revision a Bit and Insert
  3230. /** -------------------------------------*/
  3231. if (isset($data['page_redirect']) && preg_match("|\#REDIRECT \[\[.*?\]\]|s", $this->EE->input->get_post('article_content'), $match))
  3232. {
  3233. $content = str_replace($match['0'], '', $this->EE->input->get_post('article_content'));
  3234. }
  3235. else
  3236. {
  3237. $content = $this->EE->input->get_post('article_content');
  3238. }
  3239. $revision = array( 'page_id' => $page_id,
  3240. 'wiki_id' => $this->wiki_id,
  3241. 'revision_date' => $this->EE->localize->now,
  3242. 'revision_author' => $this->EE->session->userdata['member_id'],
  3243. 'revision_notes' => ($this->EE->input->get_post('revision_notes') !== FALSE) ? $this->EE->input->get_post('revision_notes') : '',
  3244. 'page_content' => $this->EE->security->xss_clean($content)
  3245. );
  3246. if ($query->num_rows() > 0 && $query->row('page_moderated') == 'y' && ! in_array($this->EE->session->userdata['group_id'], $this->admins))
  3247. {
  3248. $revision['revision_status'] = 'closed';
  3249. }
  3250. else
  3251. {
  3252. $revision['revision_status'] = 'open';
  3253. }
  3254. $this->EE->db->query($this->EE->db->insert_string('exp_wiki_revisions', $revision));
  3255. $revision['revision_id'] = $this->EE->db->insert_id();
  3256. /** -------------------------------------
  3257. /** Check and Add Categories - But Not For Categories Namespace
  3258. /** -------------------------------------*/
  3259. if ($revision['revision_status'] == 'open')
  3260. {
  3261. $cats = $this->check_categories($page_id, $revision['page_content'], $this->current_namespace);
  3262. }
  3263. /** ---------------------------------------
  3264. /** Update last_revision_id
  3265. /** ---------------------------------------*/
  3266. $this->EE->db->query($this->EE->db->update_string('exp_wiki_page', array('last_revision_id' => $revision['revision_id']), array('page_id' => $page_id)));
  3267. /** -------------------------------------
  3268. /** Moderator Notifications?
  3269. /** -------------------------------------*/
  3270. if ($revision['revision_status'] == 'closed' && trim($this->moderation_emails) != '')
  3271. {
  3272. /** ----------------------------
  3273. /** Send Emails to Moderators
  3274. /** ----------------------------*/
  3275. $replyto = ($this->EE->session->userdata['email'] == '') ? $this->EE->config->item('webmaster_email') : $this->EE->session->userdata['email'];
  3276. $link = $this->create_url($this->current_namespace, $this->topic);
  3277. $revision['author'] = $this->EE->session->userdata['screen_name'];
  3278. $revision['email'] = $this->EE->session->userdata['email'];
  3279. $revision['title'] = $this->title;
  3280. $revision['content'] = $this->EE->security->xss_clean($content);
  3281. $revision['path:view_article'] = $link;
  3282. $revision['path:view_revision'] = $link.'/revision/'.$revision['revision_id'];
  3283. $revision['path:open_revision'] = $link.'/revision/'.$revision['revision_id'].'/open';
  3284. $revision['path:close_revision'] = $link.'/revision/'.$revision['revision_id'].'/close';
  3285. $this->EE->load->library('typography');
  3286. $this->EE->typography->initialize();
  3287. $this->EE->typography->parse_images = FALSE;
  3288. $this->EE->typography->parse_smileys = FALSE;
  3289. $revision['article'] = $this->convert_curly_brackets($this->EE->typography->parse_type( $this->wiki_syntax($this->EE->security->xss_clean($content)),
  3290. array(
  3291. 'text_format' => $this->text_format,
  3292. 'html_format' => $this->html_format,
  3293. 'auto_links' => $this->auto_links,
  3294. 'allow_img_url' => 'y'
  3295. )
  3296. ));
  3297. $subject = $this->EE->functions->var_swap($this->_fetch_template('wiki_email_moderation_subject.html'), $revision);
  3298. $message = $this->EE->functions->var_swap($this->_fetch_template('wiki_email_moderation_message.html'), $revision);
  3299. $this->EE->load->library('email');
  3300. // Load the text helper
  3301. $this->EE->load->helper('text');
  3302. $sent = array();
  3303. foreach (explode(',', $this->moderation_emails) as $addy)
  3304. {
  3305. if (in_array($addy, $sent))
  3306. {
  3307. continue;
  3308. }
  3309. $this->EE->email->EE_initialize();
  3310. $this->EE->email->wordwrap = false;
  3311. $this->EE->email->from($this->EE->config->item('webmaster_email'), $this->EE->config->item('webmaster_name'));
  3312. $this->EE->email->to($addy);
  3313. $this->EE->email->reply_to($replyto);
  3314. $this->EE->email->subject($subject);
  3315. $this->EE->email->message(entities_to_ascii($message));
  3316. $this->EE->email->send();
  3317. $sent[] = $addy;
  3318. }
  3319. }
  3320. /* -------------------------------------
  3321. /* 'edit_wiki_article_end' hook.
  3322. /* - Add more things to do for wiki articles
  3323. /* - Added 1.6.0
  3324. */
  3325. $edata = $this->EE->extensions->universal_call('edit_wiki_article_end', $this, $query);
  3326. if ($this->EE->extensions->end_script === TRUE) return;
  3327. /*
  3328. /* -------------------------------------*/
  3329. $query = $this->EE->db->query("SELECT COUNT(revision_id) AS count FROM exp_wiki_revisions
  3330. WHERE page_id = '".$this->EE->db->escape_str($page_id)."'
  3331. AND wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'");
  3332. if ($query->row('count') > $this->revision_limit)
  3333. {
  3334. $query = $this->EE->db->query("SELECT revision_id FROM exp_wiki_revisions
  3335. WHERE page_id = '".$this->EE->db->escape_str($page_id)."'
  3336. AND wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  3337. LIMIT $this->revision_limit, 1");
  3338. if ($query->num_rows() > 0)
  3339. {
  3340. $this->EE->db->query("DELETE FROM exp_wiki_revisions
  3341. WHERE page_id = '".$this->EE->db->escape_str($page_id)."'
  3342. AND wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  3343. AND revision_id < '".$query->row('revision_id') ."'");
  3344. }
  3345. }
  3346. // Clear wiki cache
  3347. $this->EE->functions->clear_caching('db');
  3348. $this->redirect($this->current_namespace, $this->topic);
  3349. }
  3350. /* -------------------------------------
  3351. /* Check String for Category Tags.
  3352. /* - If category does not exist create
  3353. /* - Insert Found Categories into exp_wiki_category_articles table
  3354. /* -------------------------------------*/
  3355. function check_categories($page_id, $str, $namespace='')
  3356. {
  3357. $all_cats = array();
  3358. $cats_found = array();
  3359. $str = preg_replace("/\[code\](.+?)\[\/code\]/si", '', $str);
  3360. // Old preg_match_all before we added support for alternate text links, e.g. [[Category:Foo | Bar]]
  3361. //if (preg_match_all("|\[\[".preg_quote($this->category_ns)."(ID)*\:([^\|])*?.*?\]\]|", $str, $matches))
  3362. if (preg_match_all("/\[\[Category(ID)*\:([^\OR\]]*)/", $str, $matches))
  3363. {
  3364. if ($this->cats_use_namespaces == 'n')
  3365. {
  3366. $namespace = '';
  3367. }
  3368. for($i=0, $s = count($matches['0']); $i < $s; ++$i)
  3369. {
  3370. /* -------------------------------------
  3371. /* Takes the Categories from the last loop and adds them
  3372. /* to those we are inserting. Because of the nesting, we
  3373. /* do it this way so that we do not have the exact same code
  3374. /* many many times throughout the loop
  3375. /* -------------------------------------*/
  3376. if (count($cats_found) > 0)
  3377. {
  3378. if ($this->cats_assign_parents == 'n')
  3379. {
  3380. $all_cats[] = array_pop($cats_found);
  3381. }
  3382. else
  3383. {
  3384. $all_cats = array_merge($all_cats, $cats_found);
  3385. }
  3386. }
  3387. $cats_found = array();
  3388. if (trim($matches['2'][$i]) == '')
  3389. {
  3390. continue;
  3391. }
  3392. /** -------------------------------------
  3393. /** Category ID specified directly
  3394. /** -------------------------------------*/
  3395. if ($matches['1'][$i] != '')
  3396. {
  3397. $query = $this->EE->db->query("SELECT cat_id
  3398. FROM exp_wiki_categories
  3399. WHERE cat_id = '".$this->EE->db->escape_str($matches['2'][$i])."'
  3400. AND wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'");
  3401. if ($query->num_rows() > 0)
  3402. {
  3403. $cats_found[] = $query->row('cat_id') ;
  3404. }
  3405. continue;
  3406. }
  3407. /** -------------------------------------
  3408. /** Check for Nested Categories
  3409. /** -------------------------------------*/
  3410. if (stristr($matches['2'][$i], $this->cats_separator))
  3411. {
  3412. $cats = explode($this->cats_separator,
  3413. preg_replace("/".preg_quote($this->cats_separator.$this->cats_separator)."+/",
  3414. $this->cats_separator,
  3415. $matches['2'][$i]));
  3416. }
  3417. else
  3418. {
  3419. $cats = array($matches['2'][$i]);
  3420. }
  3421. /* -----------------------------------------------
  3422. /* Check for Parent Category
  3423. /* - If the parent category DOES NOT exist, then we are
  3424. /* starting a new branch of category so they are all new.
  3425. /* - If the parent category DOES exist, then we have to
  3426. /* cycle throw the kids to see if they exist or not too.
  3427. /* ----------------------------------------------*/
  3428. $query = $this->EE->db->query("SELECT cat_id
  3429. FROM exp_wiki_categories
  3430. WHERE cat_name = '".$this->EE->db->escape_str($this->valid_title($cats['0']))."'
  3431. AND wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  3432. LIMIT 1");
  3433. if ($query->num_rows() == 0)
  3434. {
  3435. $data = array( 'cat_name' => $this->valid_title($cats['0']),
  3436. 'parent_id' => 0,
  3437. 'wiki_id' => $this->wiki_id,
  3438. 'cat_namespace' => '');
  3439. $this->EE->db->query($this->EE->db->insert_string('exp_wiki_categories', $data));
  3440. $parent_cat = $this->EE->db->insert_id();
  3441. $cats_found[] = $parent_cat;
  3442. if (count($cats) > 1)
  3443. {
  3444. array_shift($cats);
  3445. foreach($cats as $cat)
  3446. {
  3447. if (trim($cat) == '')
  3448. {
  3449. continue(2);
  3450. }
  3451. $data['cat_name'] = $this->valid_title($cat);
  3452. $data['parent_id'] = $parent_cat;
  3453. $data['wiki_id'] = $this->wiki_id;
  3454. $data['cat_namespace'] = '';
  3455. $this->EE->db->query($this->EE->db->insert_string('exp_wiki_categories', $data));
  3456. $parent_cat = $this->EE->db->insert_id();
  3457. $cats_found[] = $parent_cat;
  3458. }
  3459. }
  3460. }
  3461. elseif (count($cats) == 1)
  3462. {
  3463. $parent_cat = $query->row('cat_id') ;
  3464. $cats_found[] = $parent_cat;
  3465. }
  3466. elseif (count($cats) > 1)
  3467. {
  3468. array_shift($cats);
  3469. $parent_cat = $query->row('cat_id') ;
  3470. $cats_found[] = $parent_cat;
  3471. foreach($cats as $cat)
  3472. {
  3473. if (trim($cat) == '')
  3474. {
  3475. continue(2);
  3476. }
  3477. $query = $this->EE->db->query("SELECT cat_id
  3478. FROM exp_wiki_categories
  3479. WHERE cat_name = '".$this->EE->db->escape_str($this->valid_title($cat))."'
  3480. AND parent_id = '".$this->EE->db->escape_str($parent_cat)."'
  3481. AND wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  3482. LIMIT 1");
  3483. if ($query->num_rows() > 0)
  3484. {
  3485. $parent_cat = $query->row('cat_id') ;
  3486. $cats_found[] = $parent_cat;
  3487. continue;
  3488. }
  3489. $data['cat_name'] = $this->valid_title($cat);
  3490. $data['parent_id'] = $parent_cat;
  3491. $data['wiki_id'] = $this->wiki_id;
  3492. $data['cat_namespace'] = '';
  3493. $this->EE->db->query($this->EE->db->insert_string('exp_wiki_categories', $data));
  3494. $parent_cat = $this->EE->db->insert_id();
  3495. $cats_found[] = $parent_cat;
  3496. }
  3497. }
  3498. }
  3499. }
  3500. /* -------------------------------------
  3501. /* Takes the Categories from the final loop and adds them
  3502. /* to those we are inserting.
  3503. /* -------------------------------------*/
  3504. if (count($cats_found) > 0)
  3505. {
  3506. if ($this->cats_assign_parents == 'n')
  3507. {
  3508. $all_cats[] = array_pop($cats_found);
  3509. }
  3510. else
  3511. {
  3512. $all_cats = array_merge($all_cats, $cats_found);
  3513. }
  3514. }
  3515. /** -------------------------------------
  3516. /** Insert Fresh Categories!
  3517. /** -------------------------------------*/
  3518. $this->EE->db->query("DELETE FROM exp_wiki_category_articles WHERE page_id = '".$this->EE->db->escape_str($page_id)."'");
  3519. if (count($all_cats) > 0)
  3520. {
  3521. $cats_insert = '';
  3522. foreach(array_unique($all_cats) as $cat_id)
  3523. {
  3524. $cats_insert .= "('{$page_id}', '{$cat_id}'),";
  3525. }
  3526. $this->EE->db->query("INSERT INTO exp_wiki_category_articles (page_id, cat_id) VALUES ".substr($cats_insert,0,-1));
  3527. $this->EE->db->query("UPDATE exp_wiki_page SET has_categories = 'y' WHERE page_id = '".$this->EE->db->escape_str($page_id)."'");
  3528. }
  3529. else
  3530. {
  3531. $this->EE->db->query("UPDATE exp_wiki_page SET has_categories = 'n' WHERE page_id = '".$this->EE->db->escape_str($page_id)."'");
  3532. }
  3533. return $all_cats;
  3534. }
  3535. /** -------------------------------------
  3536. /** Prep Conditionals
  3537. /** -------------------------------------*/
  3538. function prep_conditionals($str, $data)
  3539. {
  3540. if (count($data) == 0) return $str;
  3541. $cleaned = array();
  3542. foreach($data as $key => $value)
  3543. {
  3544. $cleaned[str_replace(array(RD,LD), '', $key)] = $value;
  3545. }
  3546. return $this->EE->functions->prep_conditionals($str, $cleaned);
  3547. }
  3548. /** -------------------------------------
  3549. /** New Page Creator
  3550. /** -------------------------------------*/
  3551. function find_page()
  3552. {
  3553. /** -------------------------------------
  3554. /** Secure Forms
  3555. /** -------------------------------------*/
  3556. // If the hash is not found we'll simply reload the page.
  3557. if ($this->EE->config->item('secure_forms') == 'y')
  3558. {
  3559. $query = $this->EE->db->query("SELECT COUNT(*) AS count FROM exp_security_hashes
  3560. WHERE hash='".$this->EE->db->escape_str($_POST['XID'])."'
  3561. AND ip_address = '".$this->EE->input->ip_address()."'
  3562. AND date > UNIX_TIMESTAMP()-7200");
  3563. if ($query->row('count') == 0)
  3564. {
  3565. $this->redirect('', 'index');
  3566. }
  3567. $this->EE->db->query("DELETE FROM exp_security_hashes WHERE (hash='".$this->EE->db->escape_str($_POST['XID'])."' AND ip_address = '".$this->EE->input->ip_address()."') OR date < UNIX_TIMESTAMP()-7200");
  3568. }
  3569. if ($this->EE->input->post('title') !== FALSE && $this->EE->input->get_post('title') != '')
  3570. {
  3571. $title = $this->valid_title($this->EE->security->xss_clean(strip_tags($this->EE->input->post('title'))));
  3572. $this->redirect('', $title);
  3573. }
  3574. else
  3575. {
  3576. $this->redirect('', 'index');
  3577. }
  3578. exit;
  3579. }
  3580. /** -------------------------------------
  3581. /** Random Page Redirect
  3582. /** -------------------------------------*/
  3583. function random_page()
  3584. {
  3585. /*
  3586. Had a bit of an ongoing debate on whether to include redirected
  3587. pages or not in the random page function. Ultimately, I decided
  3588. not to because it will really just be displaying the same exact
  3589. content and I think this feature is more about showing content that
  3590. is "new" to the user. -Paul
  3591. */
  3592. $query = $this->EE->db->query("SELECT page_name, page_namespace
  3593. FROM exp_wiki_page
  3594. WHERE (page_redirect = '' OR page_redirect IS NULL)
  3595. AND wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  3596. ORDER BY rand() LIMIT 1");
  3597. $this->redirect($this->namespace_label($query->row('page_namespace') ), $query->row('page_name') );
  3598. }
  3599. /** -------------------------------------
  3600. /** Search Some Content!
  3601. /** -------------------------------------*/
  3602. function search_results($keywords='')
  3603. {
  3604. /** ----------------------------------------
  3605. /** Check for Pagination
  3606. /** ----------------------------------------*/
  3607. $search_paginate = FALSE;
  3608. if ($this->EE->input->get_post('keywords') === FALSE && $keywords == '')
  3609. {
  3610. if ( ! isset($this->seg_parts['1']) OR strlen($this->seg_parts['1']) < 20)
  3611. {
  3612. return $this->return_data = '';
  3613. }
  3614. $query = $this->EE->db->query("SELECT * FROM exp_wiki_search
  3615. WHERE wiki_search_id = '".$this->EE->db->escape_str($this->seg_parts['1'])."'");
  3616. if ($query->num_rows() > 0)
  3617. {
  3618. $search_paginate = TRUE;
  3619. $paginate_sql = $query->row('wiki_search_query') ;
  3620. $paginate_hash = $query->row('wiki_search_id') ;
  3621. $keywords = $query->row('wiki_search_keywords') ;
  3622. }
  3623. }
  3624. /** ----------------------------------------
  3625. /** Work Up the Keywords A Bit, Know What I'm Saying?
  3626. /** ----------------------------------------*/
  3627. $keywords = ($this->EE->input->get_post('keywords') !== FALSE) ? $this->EE->input->get_post('keywords') : $keywords;
  3628. // Load the search helper so we can filter the keywords
  3629. $this->EE->load->helper('search');
  3630. $keywords = $this->EE->functions->encode_ee_tags(sanitize_search_terms($keywords), TRUE);
  3631. if ($keywords == '')
  3632. {
  3633. $this->redirect('', 'index');
  3634. }
  3635. elseif(strlen($keywords) < $this->min_length_keywords)
  3636. {
  3637. return $this->EE->output->show_user_error('general', array(str_replace("%x", $this->min_length_keywords, $this->EE->lang->line('search_min_length'))));
  3638. }
  3639. $this->return_data = str_replace(array('{wiki:page}', '{keywords}'),
  3640. array($this->_fetch_template('wiki_special_search_results.html'), stripslashes($keywords)),
  3641. $this->return_data);
  3642. /** ----------------------------------------
  3643. /** Parse Results Tag Pair
  3644. /** ----------------------------------------*/
  3645. if ( ! preg_match("/\{wiki:search_results(.*?)\}(.*?)\{\/wiki:search_results\}/s", $this->return_data, $match))
  3646. {
  3647. return $this->return_data = '';
  3648. }
  3649. /** ----------------------------------------
  3650. /** Parameters
  3651. /** ----------------------------------------*/
  3652. $parameters['limit'] = 20;
  3653. $parameters['switch1'] = '';
  3654. $parameters['switch2'] = '';
  3655. $parameters['paginate'] = 'bottom';
  3656. if (trim($match['1']) != '' && ($params = $this->EE->functions->assign_parameters($match['1'])) !== FALSE)
  3657. {
  3658. $parameters['limit'] = (isset($params['limit']) && is_numeric($params['limit'])) ? $params['limit'] : $parameters['limit'];
  3659. $parameters['paginate'] = (isset($params['paginate']) && is_numeric($params['paginate'])) ? $params['paginate'] : $parameters['paginate'];
  3660. if (isset($params['switch']))
  3661. {
  3662. if (strpos($params['switch'], '|') !== FALSE)
  3663. {
  3664. $x = explode("|", $params['switch']);
  3665. $parameters['switch1'] = $x['0'];
  3666. $parameters['switch2'] = $x['1'];
  3667. }
  3668. else
  3669. {
  3670. $parameters['switch1'] = $params['switch'];
  3671. }
  3672. }
  3673. }
  3674. /* ----------------------------------------
  3675. /* Date Formats
  3676. /* - Those GMT dates are not typical for results, but I thought it might
  3677. /* be the case that there will be dynamic RSS/Atom searches in the
  3678. /* future so I added them just in case.
  3679. /* ----------------------------------------*/
  3680. $dates = $this->parse_dates($this->return_data);
  3681. /** -------------------------------------
  3682. /** Secure Forms
  3683. /** -------------------------------------*/
  3684. // If the hash is not found we'll simply reload the page.
  3685. if ($this->EE->config->item('secure_forms') == 'y' && $search_paginate === FALSE)
  3686. {
  3687. $query = $this->EE->db->query("SELECT COUNT(*) AS count FROM exp_security_hashes
  3688. WHERE hash='".$this->EE->db->escape_str($_POST['XID'])."'
  3689. AND ip_address = '".$this->EE->input->ip_address()."'
  3690. AND date > UNIX_TIMESTAMP()-7200");
  3691. if ($query->row('count') == 0)
  3692. {
  3693. $this->redirect('', $this->EE->input->get_post('title'));
  3694. }
  3695. $this->EE->db->query("DELETE FROM exp_security_hashes WHERE (hash='".$this->EE->db->escape_str($_POST['XID'])."' AND ip_address = '".$this->EE->input->ip_address()."') OR date < UNIX_TIMESTAMP()-7200");
  3696. }
  3697. /** ----------------------------------------
  3698. /** Our Query
  3699. /** ----------------------------------------*/
  3700. if ($search_paginate === TRUE)
  3701. {
  3702. $sql = $paginate_sql;
  3703. }
  3704. else
  3705. {
  3706. $sql = "FROM exp_wiki_revisions r, exp_members m, exp_wiki_page p
  3707. WHERE p.page_id = r.page_id
  3708. AND p.last_updated = r.revision_date
  3709. AND p.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  3710. AND (";
  3711. /** -------------------------------------
  3712. /** Get our keywords into search terms
  3713. /** -------------------------------------*/
  3714. $terms = array();
  3715. $keywords = stripslashes($keywords);
  3716. $nsql = '';
  3717. if (stristr(strtolower($keywords), 'namespace:'))
  3718. {
  3719. $namespaces = array('Category' => 'category');
  3720. $nquery = $this->EE->db->query("SELECT namespace_label, namespace_name FROM exp_wiki_namespaces");
  3721. if ($nquery->num_rows() > 0)
  3722. {
  3723. foreach ($nquery->result_array() as $row)
  3724. {
  3725. $namespaces[$row['namespace_label']] = $row['namespace_name'];
  3726. }
  3727. }
  3728. foreach ($namespaces as $key => $val)
  3729. {
  3730. if (preg_match("/namespace:\s*(\-)*\s*[\'\"]?(".preg_quote($key, '/').")[\'\"]?/", $keywords, $nmatch))
  3731. {
  3732. $keywords = str_replace($nmatch['0'], '', $keywords);
  3733. $compare = ($nmatch['1'] == "-") ? '!=' : '=';
  3734. $nsql = "AND p.page_namespace {$compare} '".$namespaces[$nmatch['2']]."' \n";
  3735. }
  3736. }
  3737. }
  3738. // in case they searched with only "namespace:namespace_label" and no keywords
  3739. if (trim($keywords) == '')
  3740. {
  3741. return $this->EE->output->show_user_error('general', array($this->EE->lang->line('no_search_terms')));
  3742. }
  3743. if (preg_match_all("/\-*\"(.*?)\"/", $keywords, $matches))
  3744. {
  3745. for($m=0; $m < count($matches['1']); $m++)
  3746. {
  3747. $terms[] = trim(str_replace('"','',$matches['0'][$m]));
  3748. $keywords = str_replace($matches['0'][$m],'', $keywords);
  3749. }
  3750. }
  3751. if (trim($keywords) != '')
  3752. {
  3753. $terms = array_merge($terms, preg_split("/\s+/", trim($keywords)));
  3754. }
  3755. $not_and = (count($terms) > 2) ? ') AND (' : 'AND';
  3756. rsort($terms);
  3757. /** -------------------------------------
  3758. /** Log Search Terms
  3759. /** -------------------------------------*/
  3760. $this->EE->functions->log_search_terms(implode(' ', $terms), 'wiki');
  3761. /** -------------------------------------
  3762. /** Search in content and article title
  3763. /** -------------------------------------*/
  3764. $mysql_function = (substr($terms['0'], 0,1) == '-') ? 'NOT LIKE' : 'LIKE';
  3765. $search_term = (substr($terms['0'], 0,1) == '-') ? substr($terms['0'], 1) : $terms['0'];
  3766. $connect = ($mysql_function == 'LIKE') ? 'OR' : 'AND';
  3767. $sql .= "\n(r.page_content {$mysql_function} '%".$this->EE->db->escape_like_str($search_term)."%' ";
  3768. $sql .= "{$connect} p.page_name {$mysql_function} '%".$this->EE->db->escape_like_str($search_term)."%') ";
  3769. for ($i=1; $i < count($terms); $i++)
  3770. {
  3771. $mysql_criteria = ($mysql_function == 'NOT LIKE' OR substr($terms[$i], 0,1) == '-') ? $not_and : 'AND';
  3772. $mysql_function = (substr($terms[$i], 0,1) == '-') ? 'NOT LIKE' : 'LIKE';
  3773. $search_term = (substr($terms[$i], 0,1) == '-') ? substr($terms[$i], 1) : $terms[$i];
  3774. $connect = ($mysql_function == 'LIKE') ? 'OR' : 'AND';
  3775. $sql .= "{$mysql_criteria} (r.page_content {$mysql_function} '%".$this->EE->db->escape_like_str($search_term)."%' ";
  3776. $sql .= "{$connect} p.page_name {$mysql_function} '%".$this->EE->db->escape_like_str($search_term)."%') ";
  3777. }
  3778. // close it up, and add our namespace clause
  3779. $sql .= "\n) \n{$nsql}";
  3780. $sql .= "AND m.member_id = r.revision_author
  3781. AND r.revision_status = 'open'
  3782. ORDER BY r.revision_date";
  3783. }
  3784. $query = $this->EE->db->query("SELECT COUNT(*) AS count ".$sql);
  3785. if ($query->row('count') == 0)
  3786. {
  3787. $this->return_data = $this->_deny_if('results', $this->return_data);
  3788. $this->return_data = $this->_allow_if('no_results', $this->return_data);
  3789. $this->return_data = str_replace($match['0'], '', $this->return_data);
  3790. return;
  3791. }
  3792. else
  3793. {
  3794. $this->return_data = $this->_allow_if('results', $this->return_data);
  3795. $this->return_data = $this->_deny_if('no_results', $this->return_data);
  3796. }
  3797. /** ----------------------------------------
  3798. /** Store Pagination Hash and Query
  3799. /** ----------------------------------------*/
  3800. if ($query->row('count') > $parameters['limit'] && $search_paginate === FALSE)
  3801. {
  3802. $paginate_hash = $this->EE->functions->random('md5');
  3803. $this->EE->db->query($this->EE->db->insert_string('exp_wiki_search',
  3804. array('wiki_search_id' => $paginate_hash,
  3805. 'wiki_search_query' => $sql,
  3806. 'wiki_search_keywords' => $keywords)
  3807. )
  3808. );
  3809. }
  3810. $base_paginate = $this->base_url.$this->special_ns.':Search_results/';
  3811. if (isset($paginate_hash))
  3812. {
  3813. $base_paginate .= $paginate_hash.'/';
  3814. }
  3815. $this->pagination($query->row('count') , $parameters['limit'], $base_paginate);
  3816. /** ----------------------------------------
  3817. /** Rerun Query This Time With Our Data
  3818. /** ----------------------------------------*/
  3819. if ($this->paginate === TRUE)
  3820. {
  3821. // Now that the Paginate code is removed, we run this again
  3822. preg_match("/\{wiki:search_results(.*?)\}(.*?)\{\/wiki:search_results\}/s", $this->return_data, $match);
  3823. }
  3824. else
  3825. {
  3826. $this->pagination_sql .= " LIMIT ".$parameters['limit'];
  3827. }
  3828. $query = $this->EE->db->query("SELECT r.*, m.member_id, m.screen_name, m.email, m.url, p.page_namespace, p.page_name AS topic ".$sql.$this->pagination_sql);
  3829. /** ----------------------------------------
  3830. /** Global Last Updated
  3831. /** ----------------------------------------*/
  3832. if (isset($dates['last_updated']))
  3833. {
  3834. foreach($dates['last_updated'] as $key => $value)
  3835. {
  3836. $temp_date = $value['0'];
  3837. foreach ($value['1'] as $dvar)
  3838. {
  3839. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $results->row('revision_date') , TRUE), $temp_date);
  3840. }
  3841. $this->return_data = str_replace($key, $temp_date, $this->return_data);
  3842. }
  3843. }
  3844. if (isset($dates['gmt_last_updated']))
  3845. {
  3846. foreach($dates['gmt_last_updated'] as $key => $value)
  3847. {
  3848. $temp_date = $value['0'];
  3849. foreach ($value['1'] as $dvar)
  3850. {
  3851. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $results->row('revision_date') , FALSE), $temp_date);
  3852. }
  3853. $this->return_data = str_replace($key, $temp_date, $this->return_data);
  3854. }
  3855. }
  3856. /** ----------------------------------------
  3857. /** Parsing of the Results
  3858. /** ----------------------------------------*/
  3859. $results = $this->parse_results($match, $query, $parameters, $dates);
  3860. $this->return_data = str_replace($match['0'], $results, $this->return_data);
  3861. }
  3862. /* ----------------------------------------
  3863. /* Parsing of the Results
  3864. /* - Use for Search and Category Page Articles
  3865. /* ----------------------------------------*/
  3866. function parse_results($match, $query, $parameters, $dates)
  3867. {
  3868. if (preg_match("|".LD."letter_header".RD."(.*?)".LD."\/letter_header".RD."|s",$match['2'], $block))
  3869. {
  3870. $letter_header = $block['1'];
  3871. $match['2'] = str_replace($block['0'],'', $match['2']);
  3872. }
  3873. $this->EE->load->library('typography');
  3874. $this->EE->typography->initialize();
  3875. $this->EE->typography->parse_images = FALSE;
  3876. $this->EE->typography->parse_smileys = FALSE;
  3877. $results = '';
  3878. $i = 0;
  3879. $last_letter = '';
  3880. $count = 0;
  3881. // added in 1.6 for {switch} variable and for future use
  3882. $vars = $this->EE->functions->assign_variables($match['2']);
  3883. $this->EE->load->helper('url');
  3884. foreach($query->result_array() as $row)
  3885. {
  3886. $temp = $match['2'];
  3887. $count++;
  3888. $title = ($row['page_namespace'] != '') ? $this->namespace_label($row['page_namespace']).':'.$row['topic'] : $row['topic'];
  3889. $link = $this->create_url($this->namespace_label($row['page_namespace']), $row['topic']);
  3890. $data = array( '{title}' => $this->prep_title($title),
  3891. '{revision_id}' => $row['revision_id'],
  3892. '{page_id}' => $row['page_id'],
  3893. '{author}' => $row['screen_name'],
  3894. '{path:author_profile}' => $this->EE->functions->create_url($this->profile_path.$row['member_id']),
  3895. '{email}' => $this->EE->typography->encode_email($row['email']),
  3896. '{url}' => prep_url($row['url']),
  3897. '{revision_notes}' => $row['revision_notes'],
  3898. '{path:view_article}' => $link,
  3899. '{content}' => $row['page_content'],
  3900. '{count}' => $count);
  3901. if (isset($parameters['switch1']))
  3902. {
  3903. $data['{switch}'] = ($i++ % 2) ? $parameters['switch1'] : $parameters['switch2'];
  3904. }
  3905. if (isset($letter_header))
  3906. {
  3907. $this_letter = (function_exists('mb_strtoupper')) ? mb_strtoupper(substr($row['topic'], 0, 1), $this->EE->config->item('charset')) : strtoupper(substr($row['topic'], 0));
  3908. if ($last_letter != $this_letter)
  3909. {
  3910. $temp = str_replace('{letter}', $this_letter, $letter_header).$temp;
  3911. $last_letter = $this_letter;
  3912. }
  3913. }
  3914. if (strpos($temp, '{article}') !== FALSE)
  3915. {
  3916. $data['{article}'] = $this->convert_curly_brackets($this->EE->typography->parse_type( $this->wiki_syntax($row['page_content']),
  3917. array(
  3918. 'text_format' => $this->text_format,
  3919. 'html_format' => $this->html_format,
  3920. 'auto_links' => $this->auto_links,
  3921. 'allow_img_url' => 'y'
  3922. )
  3923. ));
  3924. }
  3925. if (strpos($temp, '{excerpt}') !== FALSE)
  3926. {
  3927. if ( ! isset($data['{article}']))
  3928. {
  3929. $data['{article}'] = $this->convert_curly_brackets($this->EE->typography->parse_type( $this->wiki_syntax($row['page_content']),
  3930. array(
  3931. 'text_format' => $this->text_format,
  3932. 'html_format' => $this->html_format,
  3933. 'auto_links' => $this->auto_links,
  3934. 'allow_img_url' => 'y'
  3935. )
  3936. ));
  3937. }
  3938. $excerpt = trim(strip_tags($data['{article}']));
  3939. if (strpos($excerpt, "\r") !== FALSE OR strpos($excerpt, "\n") !== FALSE)
  3940. {
  3941. $excerpt = str_replace(array("\r\n", "\r", "\n"), " ", $excerpt);
  3942. }
  3943. $data['{excerpt}'] = $this->EE->functions->word_limiter($excerpt, 50);
  3944. }
  3945. $temp = $this->prep_conditionals($temp, array_merge($data, $this->conditionals));
  3946. if (isset($dates['revision_date']))
  3947. {
  3948. foreach($dates['revision_date'] as $key => $value)
  3949. {
  3950. $temp_date = $value['0'];
  3951. foreach ($value['1'] as $dvar)
  3952. {
  3953. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $row['revision_date'], TRUE), $temp_date);
  3954. }
  3955. $data[$key] = $temp_date;
  3956. }
  3957. }
  3958. if (isset($dates['gmt_revision_date']))
  3959. {
  3960. foreach($dates['gmt_revision_date'] as $key => $value)
  3961. {
  3962. $temp_date = $value['0'];
  3963. foreach ($value['1'] as $dvar)
  3964. {
  3965. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $row['revision_date'], FALSE), $temp_date);
  3966. }
  3967. $data[$key] = $temp_date;
  3968. }
  3969. }
  3970. foreach ($vars['var_single'] as $key => $val)
  3971. {
  3972. /** ----------------------------------------
  3973. /** parse {switch} variable
  3974. /** ----------------------------------------*/
  3975. if (preg_match("/^switch\s*=.+/i", $key))
  3976. {
  3977. $sparam = $this->EE->functions->assign_parameters($key);
  3978. $sw = '';
  3979. if (isset($sparam['switch']))
  3980. {
  3981. $sopt = explode("|", $sparam['switch']);
  3982. $sw = $sopt[($count-1 + count($sopt)) % count($sopt)];
  3983. }
  3984. $temp = $this->EE->TMPL->swap_var_single($key, $sw, $temp);
  3985. }
  3986. if ($key == 'absolute_count')
  3987. {
  3988. $temp = $this->EE->TMPL->swap_var_single($key, $count + ($this->current_page * $parameters['limit']) - $parameters['limit'], $temp);
  3989. }
  3990. }
  3991. $results .= str_replace(array_keys($data), array_values($data), $temp);
  3992. }
  3993. /** ----------------------------------------
  3994. /** Pagination
  3995. /** ----------------------------------------*/
  3996. if ($this->paginate === TRUE)
  3997. {
  3998. $this->paginate_data = str_replace(LD.'current_page'.RD, $this->current_page, $this->paginate_data);
  3999. $this->paginate_data = str_replace(LD.'total_pages'.RD, $this->total_pages, $this->paginate_data);
  4000. $this->paginate_data = str_replace(LD.'pagination_links'.RD, $this->pagination_links, $this->paginate_data);
  4001. if (preg_match("/".LD."if previous_page".RD."(.+?)".LD.'\/'."if".RD."/s", $this->paginate_data, $matches))
  4002. {
  4003. if ($this->page_previous == '')
  4004. {
  4005. $this->paginate_data = preg_replace("/".LD."if previous_page".RD.".+?".LD.'\/'."if".RD."/s", '', $this->paginate_data);
  4006. }
  4007. else
  4008. {
  4009. $matches['1'] = preg_replace("/".LD.'path.*?'.RD."/", $this->page_previous, $matches['1']);
  4010. $matches['1'] = preg_replace("/".LD.'auto_path'.RD."/", $this->page_previous, $matches['1']);
  4011. $this->paginate_data = str_replace($matches['0'], $matches['1'], $this->paginate_data);
  4012. }
  4013. }
  4014. if (preg_match("/".LD."if next_page".RD."(.+?)".LD.'\/'."if".RD."/s", $this->paginate_data, $matches))
  4015. {
  4016. if ($this->page_next == '')
  4017. {
  4018. $this->paginate_data = preg_replace("/".LD."if next_page".RD.".+?".LD.'\/'."if".RD."/s", '', $this->paginate_data);
  4019. }
  4020. else
  4021. {
  4022. $matches['1'] = preg_replace("/".LD.'path.*?'.RD."/", $this->page_next, $matches['1']);
  4023. $matches['1'] = preg_replace("/".LD.'auto_path'.RD."/", $this->page_next, $matches['1']);
  4024. $this->paginate_data = str_replace($matches['0'], $matches['1'], $this->paginate_data);
  4025. }
  4026. }
  4027. switch ($parameters['paginate'])
  4028. {
  4029. case "top" : $results = $this->paginate_data.$results;
  4030. break;
  4031. case "both" : $results = $this->paginate_data.$results.$this->paginate_data;
  4032. break;
  4033. default : $results .= $this->paginate_data;
  4034. break;
  4035. }
  4036. }
  4037. return $results;
  4038. }
  4039. /** ----------------------------------------
  4040. /** List Of Files
  4041. /** ----------------------------------------*/
  4042. function files()
  4043. {
  4044. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_special_files.html'), $this->return_data);
  4045. /** ----------------------------------------
  4046. /** Parse Results Tag Pair
  4047. /** ----------------------------------------*/
  4048. if ( ! preg_match("/\{wiki:files(.*?)\}(.*?)\{\/wiki:files\}/s", $this->return_data, $match))
  4049. {
  4050. return $this->return_data = '';
  4051. }
  4052. /** ----------------------------------------
  4053. /** Parameters
  4054. /** ----------------------------------------*/
  4055. $limit = 20;
  4056. $paginate = 'bottom';
  4057. $orderby = 'file_name';
  4058. $sort = 'asc';
  4059. $switch1 = '';
  4060. $switch2 = '';
  4061. if (trim($match['1']) != '' && ($params = $this->EE->functions->assign_parameters($match['1'])) !== FALSE)
  4062. {
  4063. $limit = (isset($params['limit']) && is_numeric($params['limit'])) ? $params['limit'] : $limit;
  4064. $paginate = (isset($params['paginate']) && is_numeric($params['paginate'])) ? $params['paginate'] : $paginate;
  4065. $orderby = (isset($params['orderby'])) ? $params['orderby'] : $orderby;
  4066. $sort = (isset($params['sort'])) ? $params['sort'] : $sort;
  4067. if (isset($params['switch']))
  4068. {
  4069. if (strpos($params['switch'], '|') !== FALSE)
  4070. {
  4071. $x = explode("|", $params['switch']);
  4072. $switch1 = $x['0'];
  4073. $switch2 = $x['1'];
  4074. }
  4075. else
  4076. {
  4077. $switch1 = $params['switch'];
  4078. }
  4079. }
  4080. }
  4081. /** ----------------------------------------
  4082. /** Pagination
  4083. /** ----------------------------------------*/
  4084. $sql = "SELECT u.*,
  4085. m.member_id, m.screen_name, m.email, m.url
  4086. FROM exp_wiki_uploads u, exp_members m
  4087. WHERE m.member_id = u.upload_author
  4088. AND u.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  4089. ORDER BY u.{$orderby} {$sort}
  4090. LIMIT {$limit}";
  4091. if (stristr($this->return_data, 'paginate}'))
  4092. {
  4093. $query = $this->EE->db->query("SELECT COUNT(*) AS count FROM exp_wiki_uploads WHERE wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'");
  4094. $this->pagination($query->row('count') , $limit, $this->base_url.$this->special_ns.':Files/');
  4095. if ($this->paginate === TRUE)
  4096. {
  4097. // Not that the Paginate code is removed, we run this again
  4098. preg_match("/\{wiki:files(.*?)\}(.*?)\{\/wiki:files\}/s", $this->return_data, $match);
  4099. $sql = "SELECT u.*,
  4100. m.member_id, m.screen_name, m.email, m.url
  4101. FROM exp_wiki_uploads u, exp_members m
  4102. WHERE m.member_id = u.upload_author
  4103. AND u.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  4104. ORDER BY u.{$orderby} {$sort} ".$this->pagination_sql;
  4105. }
  4106. }
  4107. /** ----------------------------------------
  4108. /** Date Formats
  4109. /** ----------------------------------------*/
  4110. if (preg_match_all("/".LD."(upload_date)\s+format=[\"'](.*?)[\"']".RD."/s", $this->return_data, $matches))
  4111. {
  4112. for ($j = 0; $j < count($matches['0']); $j++)
  4113. {
  4114. switch ($matches['1'][$j])
  4115. {
  4116. case 'upload_date' : $upload_date[$matches['0'][$j]] = array($matches['2'][$j], $this->EE->localize->fetch_date_params($matches['2'][$j]));
  4117. break;
  4118. }
  4119. }
  4120. }
  4121. /** ----------------------------------------
  4122. /** Our Query
  4123. /** ----------------------------------------*/
  4124. $query = $this->EE->db->query($sql);
  4125. if ($query->num_rows() == 0)
  4126. {
  4127. $this->return_data = $this->_deny_if('files', $this->return_data);
  4128. $this->return_data = $this->_allow_if('no_files', $this->return_data);
  4129. $this->return_data = str_replace($match['0'], '', $this->return_data);
  4130. return;
  4131. }
  4132. else
  4133. {
  4134. $this->return_data = $this->_allow_if('files', $this->return_data);
  4135. $this->return_data = $this->_deny_if('no_files', $this->return_data);
  4136. }
  4137. /** ----------------------------------------
  4138. /** Display Some Files, Captain Proton!
  4139. /** ----------------------------------------*/
  4140. $this->EE->load->library('typography');
  4141. $this->EE->typography->initialize();
  4142. $this->EE->typography->parse_images = FALSE;
  4143. $this->EE->typography->parse_smileys = FALSE;
  4144. $files = '';
  4145. $count = 0;
  4146. // added in 1.6 for {switch} variable and for future use
  4147. $vars = $this->EE->functions->assign_variables($match['2']);
  4148. $this->EE->load->helper('url');
  4149. foreach($query->result_array() as $row)
  4150. {
  4151. $count++;
  4152. $temp = $match['2'];
  4153. $data = array( '{file_name}' => $row['file_name'],
  4154. '{path:view_file}' => $this->base_url.$this->file_ns.':'.$row['file_name'],
  4155. '{file_type}' => $row['file_type'],
  4156. '{author}' => $row['screen_name'],
  4157. '{path:author_profile}' => $this->EE->functions->create_url($this->profile_path.$row['member_id']),
  4158. '{email}' => $this->EE->typography->encode_email($row['email']),
  4159. '{url}' => prep_url($row['url']),
  4160. '{count}' => $count);
  4161. $x = explode('/',$row['file_type']);
  4162. if ($x['0'] == 'image')
  4163. {
  4164. $temp = $this->_allow_if('is_image', $temp);
  4165. }
  4166. else
  4167. {
  4168. $temp = $this->_deny_if('is_image', $temp);
  4169. }
  4170. $data['{summary}'] = $this->convert_curly_brackets($this->EE->typography->parse_type( $this->wiki_syntax($row['upload_summary']),
  4171. array(
  4172. 'text_format' => $this->text_format,
  4173. 'html_format' => $this->html_format,
  4174. 'auto_links' => $this->auto_links,
  4175. 'allow_img_url' => 'y'
  4176. )
  4177. ));
  4178. $temp = $this->prep_conditionals($temp, array_merge($data, $this->conditionals));
  4179. if (isset($upload_date))
  4180. {
  4181. foreach($upload_date as $key => $value)
  4182. {
  4183. $temp_date = $value['0'];
  4184. foreach ($value['1'] as $dvar)
  4185. {
  4186. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $row['upload_date'], FALSE), $temp_date);
  4187. }
  4188. $data[$key] = $temp_date;
  4189. }
  4190. }
  4191. foreach ($vars['var_single'] as $key => $val)
  4192. {
  4193. /** ----------------------------------------
  4194. /** parse {switch} variable
  4195. /** ----------------------------------------*/
  4196. if (preg_match("/^switch\s*=.+/i", $key))
  4197. {
  4198. $sparam = $this->EE->functions->assign_parameters($key);
  4199. $sw = '';
  4200. if (isset($sparam['switch']))
  4201. {
  4202. $sopt = explode("|", $sparam['switch']);
  4203. $sw = $sopt[($count-1 + count($sopt)) % count($sopt)];
  4204. }
  4205. $temp = $this->EE->TMPL->swap_var_single($key, $sw, $temp);
  4206. }
  4207. if ($key == 'absolute_count')
  4208. {
  4209. $temp = $this->EE->TMPL->swap_var_single($key, $count + ($this->current_page * $parameters['limit']) - $parameters['limit'], $temp);
  4210. }
  4211. }
  4212. $files .= str_replace(array_keys($data), array_values($data), $temp);
  4213. }
  4214. /** ----------------------------------------
  4215. /** Pagination - Files
  4216. /** ----------------------------------------*/
  4217. if ($this->paginate === TRUE)
  4218. {
  4219. $this->paginate_data = str_replace(LD.'current_page'.RD, $this->current_page, $this->paginate_data);
  4220. $this->paginate_data = str_replace(LD.'total_pages'.RD, $this->total_pages, $this->paginate_data);
  4221. $this->paginate_data = str_replace(LD.'pagination_links'.RD, $this->pagination_links, $this->paginate_data);
  4222. if (preg_match("/".LD."if previous_page".RD."(.+?)".LD.'\/'."if".RD."/s", $this->paginate_data, $matches))
  4223. {
  4224. if ($this->page_previous == '')
  4225. {
  4226. $this->paginate_data = preg_replace("/".LD."if previous_page".RD.".+?".LD.'\/'."if".RD."/s", '', $this->paginate_data);
  4227. }
  4228. else
  4229. {
  4230. $matches['1'] = preg_replace("/".LD.'path.*?'.RD."/", $this->page_previous, $matches['1']);
  4231. $matches['1'] = preg_replace("/".LD.'auto_path'.RD."/", $this->page_previous, $matches['1']);
  4232. $this->paginate_data = str_replace($matches['0'], $matches['1'], $this->paginate_data);
  4233. }
  4234. }
  4235. if (preg_match("/".LD."if next_page".RD."(.+?)".LD.'\/'."if".RD."/s", $this->paginate_data, $matches))
  4236. {
  4237. if ($this->page_next == '')
  4238. {
  4239. $this->paginate_data = preg_replace("/".LD."if next_page".RD.".+?".LD.'\/'."if".RD."/s", '', $this->paginate_data);
  4240. }
  4241. else
  4242. {
  4243. $matches['1'] = preg_replace("/".LD.'path.*?'.RD."/", $this->page_next, $matches['1']);
  4244. $matches['1'] = preg_replace("/".LD.'auto_path'.RD."/", $this->page_next, $matches['1']);
  4245. $this->paginate_data = str_replace($matches['0'], $matches['1'], $this->paginate_data);
  4246. }
  4247. }
  4248. switch ($paginate)
  4249. {
  4250. case "top" : $files = $this->paginate_data.$files;
  4251. break;
  4252. case "both" : $files = $this->paginate_data.$files.$this->paginate_data;
  4253. break;
  4254. default : $files .= $this->paginate_data;
  4255. break;
  4256. }
  4257. }
  4258. $this->return_data = str_replace($match['0'], $files, $this->return_data);
  4259. }
  4260. /** ----------------------------------------
  4261. /** Upload Form
  4262. /** ----------------------------------------*/
  4263. function upload_form()
  4264. {
  4265. /** -------------------------------------
  4266. /** In the Beginning...
  4267. /** -------------------------------------*/
  4268. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_special_upload_form.html'), $this->return_data);
  4269. if ($this->can_upload != 'y')
  4270. {
  4271. return;
  4272. }
  4273. $this->EE->db->where('id', $this->upload_dir);
  4274. $query = $this->EE->db->get('upload_prefs');
  4275. /** -------------------------------------
  4276. /** Uploading
  4277. /** -------------------------------------*/
  4278. if ($this->EE->input->post('upload') == 'y')
  4279. {
  4280. if( ! in_array($this->EE->session->userdata('group_id'), $this->users) && ! in_array($this->EE->session->userdata('group_id'), $this->admins))
  4281. {
  4282. return FALSE;
  4283. }
  4284. $this->EE->lang->loadfile('upload');
  4285. // Secure Forms
  4286. if ($this->EE->config->item('secure_forms') == 'y')
  4287. {
  4288. $this->EE->db->select('COUNT(*) as count');
  4289. $this->EE->db->where('ip_address', $this->EE->input->ip_address());
  4290. $this->EE->db->where('date >', 'UNIX_TIMESTAMP()-7200');
  4291. $results = $this->EE->db->get('security_hashes');
  4292. if ($results->row('count') == 0)
  4293. {
  4294. $this->redirect($this->special_ns, 'Uploads');
  4295. }
  4296. }
  4297. /** -------------------------------------
  4298. /** Edit Limit
  4299. /** -------------------------------------*/
  4300. $this->edit_limit();
  4301. /** -------------------------------------
  4302. /** Upload File
  4303. /** -------------------------------------*/
  4304. $filename = $this->EE->input->get_post('new_filename');
  4305. if ($filename !== FALSE && $filename != '')
  4306. {
  4307. $new_name = $this->valid_title($this->EE->security->sanitize_filename(strip_tags($filename)));
  4308. }
  4309. elseif ( ! is_uploaded_file($_FILES['userfile']['tmp_name']))
  4310. {
  4311. $new_name = $this->valid_title($this->EE->security->sanitize_filename(strip_tags($_FILES['userfile']['name'])));
  4312. }
  4313. $server_path = $query->row('server_path');
  4314. switch($query->row('allowed_types'))
  4315. {
  4316. case 'all' : $allowed_types = '*';
  4317. break;
  4318. case 'img' : $allowed_types = 'jpg|png|gif';
  4319. break;
  4320. default :
  4321. $allowed_types = $query->row('allowed_types');
  4322. }
  4323. // Upload the image
  4324. $config = array(
  4325. 'file_name' => $new_name,
  4326. 'upload_path' => $server_path,
  4327. 'allowed_types' => $allowed_types,
  4328. 'max_size' => $query->row('max_size'),
  4329. 'max_width' => $query->row('max_width'),
  4330. 'max_height' => $query->row('max_height'),
  4331. );
  4332. if ($this->EE->config->item('xss_clean_uploads') == 'n')
  4333. {
  4334. $config['xss_clean'] = FALSE;
  4335. }
  4336. else
  4337. {
  4338. $config['xss_clean'] = ($this->EE->session->userdata('group_id') == 1) ? FALSE : TRUE;
  4339. }
  4340. $this->EE->load->library('upload', $config);
  4341. if (file_exists($server_path.$new_name))
  4342. {
  4343. return $this->EE->output->show_user_error('general', array(
  4344. $this->EE->lang->line('file_exists')
  4345. )
  4346. );
  4347. }
  4348. if (strlen($new_name) > 60)
  4349. {
  4350. return $this->EE->output->show_user_error('general', array(
  4351. $this->EE->lang->line('filename_too_long')
  4352. )
  4353. );
  4354. }
  4355. if ($this->EE->upload->do_upload() === FALSE)
  4356. {
  4357. @unlink($this->EE->upload->file_name);
  4358. return $this->EE->output->show_user_error('general',
  4359. array($this->EE->lang->line($this->EE->upload->display_errors())));
  4360. }
  4361. $file_data = $this->EE->upload->data();
  4362. @chmod($file_data['full_path'], DIR_WRITE_MODE);
  4363. $data = array( 'wiki_id' => $this->wiki_id,
  4364. 'file_name' => $new_name,
  4365. 'upload_summary' => ($this->EE->input->get_post('summary') !== FALSE) ? $this->EE->security->xss_clean($this->EE->input->get_post('summary')) : '',
  4366. 'upload_author' => $this->EE->session->userdata('member_id'),
  4367. 'upload_date' => $this->EE->localize->now,
  4368. 'image_width' => $file_data['image_width'],
  4369. 'image_height' => $file_data['image_height'],
  4370. 'file_type' => $file_data['file_type'],
  4371. 'file_size' => $file_data['file_size'],
  4372. 'file_hash' => $this->EE->functions->random('md5')
  4373. );
  4374. $this->EE->db->insert('wiki_uploads', $data);
  4375. if ($this->EE->config->item('secure_forms') == 'y')
  4376. {
  4377. $this->EE->db->where('hash', $_POST['XID']);
  4378. $this->EE->db->where('ip_address', $this->EE->input->ip_address());
  4379. $this->EE->db->or_where('date', 'UNIX_TIMESTAMP()-7200');
  4380. $this->EE->db->delete('security_hashes');
  4381. }
  4382. $this->redirect($this->file_ns, $new_name);
  4383. }
  4384. /** ----------------------------------------
  4385. /** Can User Edit Articles and Thus Upload?
  4386. /** ----------------------------------------*/
  4387. if (in_array($this->EE->session->userdata['group_id'], $this->users) OR in_array($this->EE->session->userdata['group_id'], $this->admins))
  4388. {
  4389. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  4390. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  4391. }
  4392. else
  4393. {
  4394. $this->return_data = $this->_deny_if('can_edit', $this->return_data);
  4395. $this->return_data = $this->_allow_if('cannot_edit', $this->return_data);
  4396. }
  4397. $file_types = 'images';
  4398. if ($query->row('allowed_types') == 'all')
  4399. {
  4400. include(APPPATH.'config/mimes.php');
  4401. foreach ($mimes as $key => $val)
  4402. {
  4403. $file_types .= ', '.$key;
  4404. }
  4405. }
  4406. $this->conditionals['file_types'] = $file_types;
  4407. /** ----------------------------------------
  4408. /** Bits of Data
  4409. /** ----------------------------------------*/
  4410. $data['action'] = $this->base_url.$this->special_ns.':Uploads/';
  4411. $data['enctype'] = 'multi';
  4412. $data['id'] = 'upload_file_form';
  4413. $data['hidden_fields'] = array('upload' => 'y');
  4414. $this->return_data = str_replace(array('{form_declaration:wiki:uploads}', '{file_types}'),
  4415. array($this->EE->functions->form_declaration($data), $file_types),
  4416. $this->return_data);
  4417. }
  4418. /** -------------------------------------
  4419. /** Pagination
  4420. /** -------------------------------------*/
  4421. function pagination($count, $limit, $base_path)
  4422. {
  4423. if (preg_match("/".LD."paginate".RD."(.+?)".LD."\/paginate".RD."/s", $this->return_data, $match))
  4424. {
  4425. $this->paginate = TRUE;
  4426. $this->paginate_data = $match['1'];
  4427. $this->return_data = str_replace($match['0'], '', $this->return_data);
  4428. if ($this->EE->uri->query_string != '' && preg_match("#^P(\d+)|/P(\d+)#", $this->EE->uri->query_string, $match))
  4429. {
  4430. $this->p_page = (isset($match['2'])) ? $match['2'] : $match['1'];
  4431. $base_path = $this->EE->functions->remove_double_slashes(str_replace($match['0'], '', $base_path));
  4432. }
  4433. $this->p_page = ($this->p_page == '' OR ($limit > 1 AND $this->p_page == 1)) ? 0 : $this->p_page;
  4434. if ($this->p_page > $count)
  4435. {
  4436. $this->p_page = 0;
  4437. }
  4438. $this->current_page = floor(($this->p_page / $limit) + 1);
  4439. $this->total_pages = intval(floor($count / $limit));
  4440. /** ----------------------------------------
  4441. /** Create the pagination
  4442. /** ----------------------------------------*/
  4443. if ($count % $limit)
  4444. {
  4445. $this->total_pages++;
  4446. }
  4447. if ($count > $limit)
  4448. {
  4449. $this->EE->load->library('pagination');
  4450. if (strpos($base_path, SELF) === FALSE && $this->EE->config->item('site_index') != '')
  4451. {
  4452. $base_path .= SELF;
  4453. }
  4454. $config['base_url'] = $base_path;
  4455. $config['prefix'] = 'P';
  4456. $config['total_rows'] = $count;
  4457. $config['per_page'] = $limit;
  4458. $config['cur_page'] = $this->p_page;
  4459. $config['first_link'] = $this->EE->lang->line('pag_first_link');
  4460. $config['last_link'] = $this->EE->lang->line('pag_last_link');
  4461. $config['first_url'] = rtrim($base_path, '/');
  4462. // Allows $config['cur_page'] to override
  4463. $config['uri_segment'] = 0;
  4464. $this->EE->pagination->initialize($config);
  4465. $this->pagination_links = $this->EE->pagination->create_links();
  4466. if ((($this->total_pages * $limit) - $limit) > $this->p_page)
  4467. {
  4468. $this->page_next = $base_path.'P'.($this->p_page + $limit);
  4469. }
  4470. if (($this->p_page - $limit ) >= 0)
  4471. {
  4472. $this->page_previous = $base_path.'P'.($this->p_page - $limit);
  4473. }
  4474. $this->pagination_sql = " LIMIT ".$this->p_page.', '.$limit;
  4475. }
  4476. else
  4477. {
  4478. $this->p_page = '';
  4479. }
  4480. }
  4481. }
  4482. /* -------------------------------------
  4483. /* Edit Limit
  4484. /* - Not specifying wiki_id in here because
  4485. /* that would allow spammers to harass people with
  4486. /* multiple wikis even more, and I simply cannot allow that
  4487. /* -------------------------------------*/
  4488. function edit_limit()
  4489. {
  4490. if ( ! in_array($this->EE->session->userdata['group_id'], $this->admins))
  4491. {
  4492. $query = $this->EE->db->query("SELECT COUNT(revision_id) AS count FROM exp_wiki_revisions
  4493. WHERE revision_author = '".$this->EE->db->escape_str($this->EE->session->userdata['member_id'])."'
  4494. AND revision_date > '".($this->EE->localize->now-24*60*60)."'");
  4495. $query2 = $this->EE->db->query("SELECT COUNT(wiki_upload_id) AS count FROM exp_wiki_uploads
  4496. WHERE upload_author = '".$this->EE->db->escape_str($this->EE->session->userdata['member_id'])."'
  4497. AND upload_date > '".($this->EE->localize->now-24*60*60)."'");
  4498. if (($query2->row('count') + $query->row('count') ) > $this->author_limit)
  4499. {
  4500. return $this->EE->output->show_user_error('general', array($this->EE->lang->line('submission_limit')));
  4501. }
  4502. }
  4503. }
  4504. /** -------------------------------------
  4505. /** Open or Close a Revision
  4506. /** -------------------------------------*/
  4507. function open_close_revision($title, $revision_id, $new_status)
  4508. {
  4509. if (in_array($this->EE->session->userdata['group_id'], $this->admins))
  4510. {
  4511. $query = $this->EE->db->query("SELECT r.page_id, r.page_content, p.page_namespace FROM exp_wiki_revisions r, exp_wiki_page p
  4512. WHERE r.revision_id = '".$this->EE->db->escape_str($revision_id)."'
  4513. ANd p.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  4514. AND r.page_id = p.page_id");
  4515. if ($query->num_rows() > 0)
  4516. {
  4517. $page_id = $query->row('page_id') ;
  4518. if ($new_status == 'open')
  4519. {
  4520. $cats = $this->check_categories($page_id, $query->row('page_content') , $query->row('page_namespace') );
  4521. }
  4522. $this->EE->db->query("UPDATE exp_wiki_revisions
  4523. SET revision_status = '".$this->EE->db->escape_str($new_status)."'
  4524. WHERE revision_id = '".$this->EE->db->escape_str($revision_id)."'
  4525. AND wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'");
  4526. $query = $this->EE->db->query("SELECT revision_date, page_id
  4527. FROM exp_wiki_revisions
  4528. WHERE page_id = '".$this->EE->db->escape_str($page_id)."'
  4529. AND revision_status = 'open'
  4530. AND wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  4531. ORDER BY revision_date DESC LIMIT 1");
  4532. $date = ($query->num_rows() == 0) ? 0 : $query->row('revision_date') ;
  4533. $this->EE->db->query($this->EE->db->update_string('exp_wiki_page', array('last_updated' => $date), "page_id='".$this->EE->db->escape_str($page_id)."'"));
  4534. }
  4535. }
  4536. // Clear wiki cache
  4537. $this->EE->functions->clear_caching('db');
  4538. $this->redirect('', $title);
  4539. }
  4540. /** -------------------------------------
  4541. /** Prevents EE Tags and Variables from being parsed
  4542. /** -------------------------------------*/
  4543. function convert_curly_brackets($str)
  4544. {
  4545. /** ------------------------------------
  4546. /** Protect <script> tags
  4547. /** ------------------------------------*/
  4548. $protected = array();
  4549. $front_protect = '89Protect17';
  4550. $back_protect = '21Me01Please47';
  4551. if (stristr($str, '<script') && preg_match_all("/<script.*?".">.*?<\/script>/is", $str, $matches))
  4552. {
  4553. for($i=0, $s=count($matches['0']); $i < $s; ++$i)
  4554. {
  4555. $protected[$front_protect.$i.$back_protect] = $matches['0'][$i];
  4556. }
  4557. $str = str_replace(array_values($protected), array_keys($protected), $str);
  4558. }
  4559. /** ------------------------------------
  4560. /** Encode all other curly brackets
  4561. /** ------------------------------------*/
  4562. $str = str_replace(array(LD, RD), array('&#123;', '&#125;'), $str);
  4563. /** ------------------------------------
  4564. /** Convert back and return
  4565. /** ------------------------------------*/
  4566. if (count($protected) > 0)
  4567. {
  4568. $str = str_replace(array_keys($protected), array_values($protected), $str);
  4569. }
  4570. return $str;
  4571. }
  4572. /** ------------------------------------
  4573. /** Display Attachment
  4574. /** ------------------------------------*/
  4575. function display_attachment()
  4576. {
  4577. if ( ! isset($this->seg_parts['0']) OR strlen($this->seg_parts['0']) != 32)
  4578. {
  4579. exit;
  4580. }
  4581. $query = $this->EE->db->query("SELECT file_name, image_width, image_height, file_type, file_hash FROM exp_wiki_uploads
  4582. WHERE file_hash = '".$this->EE->db->escape_str($this->seg_parts['0'])."'
  4583. AND wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'");
  4584. if ($query->num_rows() == 0)
  4585. {
  4586. exit;
  4587. }
  4588. /** ----------------------------------------
  4589. /** Create Our URL
  4590. /** ----------------------------------------*/
  4591. $results = $this->EE->db->query("SELECT server_path FROM exp_upload_prefs
  4592. WHERE id = '".$this->EE->db->escape_str($this->upload_dir)."'");
  4593. $filepath = (substr($results->row('server_path') , -1) == '/') ? $results->row('server_path') : $results->row('server_path') .'/';
  4594. $filepath .= $query->row('file_name') ;
  4595. if ( ! file_exists($filepath))
  4596. {
  4597. exit;
  4598. }
  4599. /** ----------------------------------------
  4600. /** Is It An Image?
  4601. /** ----------------------------------------*/
  4602. $x = explode('/',$query->row('file_type') );
  4603. if ($x['0'] == 'image')
  4604. $attachment = '';
  4605. else
  4606. $attachment = (isset($_SERVER['HTTP_USER_AGENT']) AND strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) ? "" : " attachment;";
  4607. header('Content-Disposition: '.$attachment.' filename="'.$query->row('file_name') .'"');
  4608. header('Content-Type: '.$query->row('file_type') );
  4609. header('Content-Transfer-Encoding: binary');
  4610. header('Content-Length: '.filesize($filepath));
  4611. header('Last-Modified: '.gmdate('D, d M Y H:i:s', $this->EE->localize->now).' GMT');
  4612. header("Cache-Control: public");
  4613. if ( ! $fp = @fopen($filepath, FOPEN_READ))
  4614. {
  4615. exit;
  4616. }
  4617. // success, so let's make remove this request from the tracker so login redirects don't go here
  4618. array_shift($this->EE->session->tracker);
  4619. $this->EE->functions->set_cookie('tracker', serialize($this->EE->session->tracker), '0');
  4620. fpassthru($fp);
  4621. @fclose($fp);
  4622. exit;
  4623. }
  4624. /** -------------------------------------
  4625. /** Wiki Syntax Manager
  4626. /** -------------------------------------*/
  4627. function wiki_syntax($str, $existence_check=TRUE, $allow_embeds=TRUE)
  4628. {
  4629. /* ------------------------------------
  4630. /* We don't want BBCode parsed if it's within code examples so we'll
  4631. /* convert the brackets
  4632. /* ------------------------------------*/
  4633. if (preg_match_all("/\[code\](.+?)\[\/code\]/si", $str, $matches))
  4634. {
  4635. for ($i = 0; $i < count($matches['1']); $i++)
  4636. {
  4637. $str = str_replace($matches['0'][$i], '[code]'.str_replace(array('[', ']'), array('&#91;', '&#93;'), $matches['1'][$i]).'[/code]', $str);
  4638. }
  4639. }
  4640. /** ------------------------------------
  4641. /** Automatic Wiki Linking
  4642. /** ------------------------------------*/
  4643. $regular = array();
  4644. $display_title = array();
  4645. if (preg_match_all("/\[\[(.*?)\]\]/i", $str, $matches))
  4646. {
  4647. for($i=0, $s=count($matches['0']); $i < $s; ++$i)
  4648. {
  4649. /*
  4650. If colon at the beginning, then we remove as it was indicating
  4651. that it was a link and not something to be processed on edit
  4652. */
  4653. if (substr($matches['1'][$i], 0, 1) == ':')
  4654. {
  4655. $matches['1'][$i] = substr($matches['1'][$i], 1);
  4656. }
  4657. if (stristr($matches['1'][$i], ':'))
  4658. {
  4659. $x = explode(':', $matches['1'][$i], 2);
  4660. $title = $this->valid_title($this->EE->security->xss_clean(strip_tags($x['1'])));
  4661. switch($x['0'])
  4662. {
  4663. case $this->category_ns :
  4664. if (($pipe_pos = strpos($matches['1'][$i], '|')) !== FALSE)
  4665. {
  4666. $link = trim(substr($matches['1'][$i], 0, $pipe_pos));
  4667. $display = trim(substr($matches['1'][$i], $pipe_pos + 1));
  4668. $title = $this->EE->db->escape_str($this->valid_title($this->EE->security->xss_clean(strip_tags($link))));
  4669. $matches['1'][$i] = '[url="'.$this->base_url.$title.'" title="'.$title.'"]'.
  4670. $this->prep_title($display).
  4671. '[/url]';
  4672. }
  4673. else
  4674. {
  4675. $matches['1'][$i] = '[url="'.$this->base_url.$this->category_ns.':'.$title.'" title="'.$this->category_ns.':'.$title.'"]'.
  4676. $this->category_ns.':'.$this->prep_title($title).
  4677. '[/url]';
  4678. }
  4679. break;
  4680. case $this->category_ns.'ID' :
  4681. $query = $this->EE->db->query("SELECT cat_name FROM exp_wiki_categories WHERE cat_id = '".$this->EE->db->escape_str($x['1'])."' AND wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'");
  4682. if ($query->num_rows() == 0) continue(2);
  4683. $title = $query->row('cat_name') ;
  4684. $matches['1'][$i] = '[url="'.$this->base_url.$this->category_ns.':'.$title.'" title="'.$this->category_ns.':'.$title.'"]'.
  4685. $this->category_ns.':'.$this->prep_title($title).
  4686. '[/url]';
  4687. break;
  4688. case $this->image_ns :
  4689. if ($data = $this->image($x['1'], TRUE))
  4690. {
  4691. if ($this->html_format == 'all')
  4692. {
  4693. $matches['1'][$i] = '<img src="'.$data['url'].'" alt="'.$data['name'].'" width="'.$data['width'].'" height="'.$data['height'].'" />';
  4694. }
  4695. else
  4696. {
  4697. $matches['1'][$i] = '[img]'.$data['url'].'[/img]';
  4698. }
  4699. }
  4700. break;
  4701. default :
  4702. if (($pipe_pos = strpos($matches['1'][$i], '|')) !== FALSE)
  4703. {
  4704. $link = trim(substr($matches['1'][$i], 0, $pipe_pos));
  4705. $display_title[$i] = trim(substr($matches['1'][$i], $pipe_pos + 1));
  4706. $regular[$i] = $this->valid_title($this->EE->security->xss_clean(strip_tags($link)));
  4707. }
  4708. else
  4709. {
  4710. $regular[$i] = $this->valid_title($matches['1'][$i]);
  4711. }
  4712. break;
  4713. }
  4714. }
  4715. else
  4716. {
  4717. if (($pipe_pos = strpos($matches['1'][$i], '|')) !== FALSE)
  4718. {
  4719. $link = trim(substr($matches['1'][$i], 0, $pipe_pos));
  4720. $display_title[$i] = trim(substr($matches['1'][$i], $pipe_pos + 1));
  4721. $regular[$i] = $this->valid_title($this->EE->security->xss_clean(strip_tags($link)));
  4722. }
  4723. else
  4724. {
  4725. $regular[$i] = $this->valid_title($this->EE->security->xss_clean(strip_tags($matches['1'][$i])));
  4726. }
  4727. }
  4728. }
  4729. /** ------------------------------------
  4730. /** Adds a Bit of CSS for Non-Existent Pages
  4731. /** ------------------------------------*/
  4732. if (count($regular) > 0)
  4733. {
  4734. $exists = array();
  4735. $replace = ($this->EE->config->item('word_separator') == 'dash') ? '-' : '_';
  4736. if ($existence_check == TRUE)
  4737. {
  4738. // Most...annoying...query...ever.
  4739. $query = $this->EE->db->query("SELECT wn.namespace_label, wp.page_name
  4740. FROM exp_wiki_page wp
  4741. LEFT JOIN exp_wiki_namespaces wn ON wp.page_namespace = wn.namespace_name
  4742. WHERE wp.wiki_id = '" . $this->EE->db->escape_str($this->wiki_id) . "'
  4743. AND
  4744. (
  4745. wn.wiki_id = wp.wiki_id
  4746. OR
  4747. wn.namespace_name IS NULL
  4748. )
  4749. AND
  4750. (
  4751. LOWER(CONCAT_WS(':', REPLACE(wn.namespace_label, ' ', '{$replace}'), wp.page_name)) IN ('".strtolower(implode("','", $this->EE->db->escape_str($regular)))."')
  4752. OR
  4753. LOWER(wp.page_name) IN ('".strtolower(implode("','", $this->EE->db->escape_str($regular)))."') )
  4754. ");
  4755. if (isset($query) && $query->num_rows() > 0)
  4756. {
  4757. foreach($query->result_array() as $row)
  4758. {
  4759. $e_link = ($row['namespace_label'] != '') ? $row['namespace_label'].':'.$row['page_name'] : $row['page_name'];
  4760. $exists[strtolower($this->valid_title($e_link))] = $this->valid_title($e_link);
  4761. }
  4762. }
  4763. }
  4764. $this->EE->load->helper('form');
  4765. foreach($regular as $key => $title)
  4766. {
  4767. $article = FALSE;
  4768. if (isset($exists[strtolower($title)]))
  4769. {
  4770. $title = $exists[strtolower($title)];
  4771. $article = TRUE;
  4772. }
  4773. $display = (isset($display_title[$key])) ? $display_title[$key] : $title;
  4774. $css = ($article) ? '' : 'class="noArticle"';
  4775. $matches['1'][$key] = '[url="'.$this->base_url.urlencode($title).'" '.$css.' title="'.form_prep($title).'"]'.$this->prep_title($display).'[/url]';
  4776. }
  4777. }
  4778. $str = str_replace($matches['0'], $matches['1'], $str);
  4779. }
  4780. /** ------------------------------------
  4781. /** Embeds
  4782. /** ------------------------------------*/
  4783. if ($allow_embeds === TRUE && preg_match_all("@\{embed=(\042|\047)([^\\1]*?)\\1\}@", $str, $matches))
  4784. {
  4785. $pages = array();
  4786. foreach($matches['2'] as $val)
  4787. {
  4788. if (stristr($val, ':'))
  4789. {
  4790. $x = explode(':', $val, 2);
  4791. $pages[] = "(n.namespace_label = '".$this->EE->db->escape_str($x['0'])."' AND p.page_name = '".$this->EE->db->escape_str($x['1'])."')";
  4792. }
  4793. else
  4794. {
  4795. $pages[] = "p.page_name = '".$this->EE->db->escape_str($val)."'";
  4796. }
  4797. }
  4798. $query = $this->EE->db->query("SELECT r.page_content, n.namespace_label, p.page_name, p.page_namespace
  4799. FROM exp_wiki_revisions r, exp_wiki_page p
  4800. LEFT JOIN exp_wiki_namespaces as n ON (p.page_namespace = n.namespace_name)
  4801. WHERE r.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  4802. AND r.revision_status = 'open'
  4803. AND (".implode(" OR ", $pages).")
  4804. AND p.last_updated = r.revision_date
  4805. AND r.page_id = p.page_id");
  4806. if ($query->num_rows() > 0)
  4807. {
  4808. foreach($query->result_array() as $row)
  4809. {
  4810. if ($row['page_namespace'] != '')
  4811. {
  4812. $row['page_name'] = $row['namespace_label'].':'.$row['page_name'];
  4813. }
  4814. $str = str_replace(array('{embed="'.$row['page_name'].'"}', "{embed='".$row['page_name']."'}"),
  4815. $this->wiki_syntax($row['page_content'], TRUE, FALSE),
  4816. $str);
  4817. }
  4818. }
  4819. $str = str_replace($matches['0'], '', $str);
  4820. }
  4821. /* ------------------------------------
  4822. /* We don't want BBCode parsed if it's within code examples so we'll
  4823. /* convert the brackets
  4824. /* ------------------------------------*/
  4825. if (preg_match_all("/\[code\](.+?)\[\/code\]/si", $str, $matches))
  4826. {
  4827. for ($i = 0; $i < count($matches['1']); $i++)
  4828. {
  4829. $str = str_replace($matches['0'][$i], '[code]'.str_replace(array('&#91;', '&#93;'), array('[', ']'), $matches['1'][$i]).'[/code]', $str);
  4830. }
  4831. }
  4832. return $str;
  4833. }
  4834. /** ------------------------------------
  4835. /** Update Module
  4836. /** ------------------------------------*/
  4837. function update_module($current='')
  4838. {
  4839. if ($current == '' OR $current == $this->version)
  4840. {
  4841. return FALSE;
  4842. }
  4843. if ($current < '1.1')
  4844. {
  4845. $this->EE->db->query("ALTER TABLE `exp_wikis` DROP `wiki_namespaces_list`");
  4846. $this->EE->db->query("CREATE TABLE `exp_wiki_namespaces` (
  4847. `namespace_id` int(6) NOT NULL auto_increment,
  4848. `wiki_id` int(10) UNSIGNED NOT NULL,
  4849. `namespace_name` varchar(100) NOT NULL,
  4850. `namespace_label` varchar(150) NOT NULL,
  4851. `namespace_users` TEXT,
  4852. `namespace_admins` TEXT,
  4853. PRIMARY KEY `namespace_id` (`namespace_id`),
  4854. KEY `wiki_id` (`wiki_id`))");
  4855. /* -------------------------------
  4856. /* The Category NS needs a non-changing short name, so we use
  4857. /* 'category'. Prior to this it was using the Label, so we need
  4858. /* to do a conversion for any category articles already in the
  4859. /* exp_wiki_page database table.
  4860. /* -------------------------------*/
  4861. $this->EE->lang->loadfile('wiki');
  4862. $this->category_ns = (isset($this->EE->lang->language['category_ns'])) ? $this->EE->lang->line('category_ns') : $this->category_ns;
  4863. $this->EE->db->query("UPDATE exp_wiki_page SET page_namespace = 'category' WHERE page_namespace = '".$this->EE->db->escape_str($this->category_ns)."'");
  4864. }
  4865. if ($current < '1.2')
  4866. {
  4867. $this->EE->db->query("ALTER TABLE `exp_wiki_page` ADD `last_revision_id` INT(10) NOT NULL AFTER `last_updated`");
  4868. // Multiple table UPDATES are not supported until 4.0 and subqueries not until 4.1
  4869. if (version_compare(mysql_get_server_info(), '4.1-alpha', '>='))
  4870. {
  4871. $this->EE->db->query("UPDATE exp_wiki_page, exp_wiki_revisions
  4872. SET exp_wiki_page.last_revision_id =
  4873. (SELECT MAX(exp_wiki_revisions.revision_id)
  4874. FROM exp_wiki_revisions
  4875. WHERE exp_wiki_revisions.page_id = exp_wiki_page.page_id)
  4876. WHERE exp_wiki_page.page_id = exp_wiki_revisions.page_id");
  4877. }
  4878. else
  4879. {
  4880. // Slower, loopy-er method for older servers
  4881. $query = $this->EE->db->query("SELECT MAX(revision_id) AS last_revision_id, page_id FROM exp_wiki_revisions GROUP BY page_id");
  4882. foreach ($query->result() as $row)
  4883. {
  4884. $this->EE->db->query($this->EE->db->update_string('exp_wiki_page', array('last_revision_id' => $row->last_revision_id), "page_id = '{$row->page_id}'"));
  4885. }
  4886. }
  4887. }
  4888. $this->EE->db->query("UPDATE exp_modules
  4889. SET module_version = '".$this->EE->db->escape_str($this->version)."'
  4890. WHERE module_name = 'Wiki'");
  4891. }
  4892. }
  4893. /* END Class */
  4894. /* End of file mod.wiki.php */
  4895. /* Location: ./system/expressionengine/modules/wiki/mod.wiki.php */