PageRenderTime 53ms CodeModel.GetById 53ms RepoModel.GetById 1ms app.codeStats 1ms

/system/expressionengine/modules/wiki/mod.wiki.php

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