PageRenderTime 103ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 2ms

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

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