PageRenderTime 68ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

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

https://bitbucket.org/tdevonshire/hoolux
PHP | 6024 lines | 4971 code | 572 blank | 481 comment | 379 complexity | 392e6a6eaba08d2529ccfcd8dfb7410f MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php if (!defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * ExpressionEngine - by EllisLab
  4. *
  5. * @package ExpressionEngine
  6. * @author EllisLab Dev Team
  7. * @copyright Copyright (c) 2003 - 2012, EllisLab, Inc.
  8. * @license http://ellislab.com/expressionengine/user-guide/license.html
  9. * @link http://ellislab.com
  10. * @since Version 2.0
  11. * @filesource
  12. */
  13. // ------------------------------------------------------------------------
  14. /**
  15. * ExpressionEngine Wiki Module
  16. *
  17. * @package ExpressionEngine
  18. * @subpackage Modules
  19. * @category Modules
  20. * @author EllisLab Dev Team
  21. * @link http://ellislab.com
  22. */
  23. class Wiki {
  24. var $version = '2.3';
  25. var $base_path = '';
  26. var $profile_path = '';
  27. var $base_url = '';
  28. var $seg_parts = array();
  29. var $admins = array('1');
  30. var $users = array('1', '5');
  31. var $conditionals = array();
  32. var $title = '';
  33. var $topic = '';
  34. var $revision_id = '';
  35. var $theme_path = '';
  36. var $theme_url = '';
  37. var $image_url = '';
  38. // Namespaces
  39. var $main_ns = 'Main';
  40. var $special_ns = 'Special'; // Deutsch: Spezial
  41. var $file_ns = 'File';
  42. var $category_ns = 'Category'; // Deutsch: Kategorie
  43. var $image_ns = 'Image';
  44. var $current_namespace = '';
  45. var $namespaces = array();
  46. // Settings
  47. var $wiki_id = 1;
  48. var $label_name = 'EE Wiki';
  49. var $use_captchas = 'n';
  50. var $text_format = 'xhtml';
  51. var $html_format = 'safe';
  52. var $auto_links = "n";
  53. var $upload_dir = '';
  54. var $valid_upload_dir = 'n';
  55. var $can_upload = 'n';
  56. var $moderation_emails = '';
  57. var $revision_limit = 100;
  58. var $author_limit = 75;
  59. var $min_length_keywords = 3;
  60. var $cache_expire = 2; // How many hours should we keep wiki search caches?
  61. var $cats_separator = '::';
  62. var $cats_display_separator = ' -> ';
  63. var $cats_use_namespaces = 'n';
  64. var $cats_assign_parents = 'y';
  65. // Category Retrieval
  66. var $temp_array = array();
  67. var $cat_array = array();
  68. var $show_these = FALSE;
  69. var $cat_depth = 0;
  70. var $parent_cats = array();
  71. // Pagination variables
  72. var $paginate = FALSE;
  73. var $pagination_links = '';
  74. var $page_next = '';
  75. var $page_previous = '';
  76. var $current_page = 1;
  77. var $total_pages = 1;
  78. var $total_rows = 0;
  79. var $p_limit = '';
  80. var $p_page = '';
  81. var $pagination_sql = '';
  82. var $return_data = '';
  83. /** ----------------------------------------
  84. /** Constructor
  85. /** ----------------------------------------*/
  86. function Wiki($return = FALSE)
  87. {
  88. // Make a local reference to the ExpressionEngine super object
  89. $this->EE =& get_instance();
  90. if ($return === TRUE)
  91. {
  92. return;
  93. }
  94. $this->EE->lang->loadfile('wiki');
  95. /** ----------------------------------------
  96. /** Update Module Code
  97. /** ----------------------------------------*/
  98. if (isset($this->EE->TMPL->module_data['Wiki']['version']) && $this->version > $this->EE->TMPL->module_data['Wiki']['version'])
  99. {
  100. $this->update_module($this->EE->TMPL->module_data['Wiki']['version']);
  101. }
  102. /* ----------------------------------------
  103. /*
  104. /* There are five main kinds of pages in the ExpressionEngine Wiki:
  105. /*
  106. /* - Main/Index
  107. /* - Article Page (Including Namespaces)
  108. /* - Edit Topic Page
  109. /* - History Topic Page
  110. /* - Special Page (ex: Uploads, Search Results, Recent Changes)
  111. /*
  112. /* Now, the {exp:wiki} tag will be put into a template group
  113. /* and a template, which is set in base_path="" so that
  114. /* we can discover the structure of the URLs and what segments
  115. /* to read for what.
  116. /* ----------------------------------------*/
  117. if (($this->base_path = $this->EE->TMPL->fetch_param('base_path')) === FALSE)
  118. {
  119. return $this->return_data = $this->EE->lang->line('basepath_unset');
  120. }
  121. $this->base_path = rtrim($this->base_path, '/').'/';
  122. $this->base_url = $this->EE->functions->create_url($this->base_path).'/';
  123. /* ----------------------------------------
  124. Creating this array once is very useful and since I do my sanitization
  125. again here as well as in the Input class, I am sure that the
  126. segments are clean and ready to use on a page.
  127. /* ----------------------------------------*/
  128. $x = explode('/', $this->base_path);
  129. $this->seg_parts = explode('/', $this->EE->security->xss_clean(strip_tags(stripslashes($this->EE->uri->query_string))));
  130. /* ----------------------------------------
  131. Fixes a minor bug in ExpressionEngine where the QSTR variable
  132. has the template name included when there is no third segment
  133. on a non-index template - Paul
  134. /* ----------------------------------------*/
  135. if (isset($x['1']))
  136. {
  137. if ($this->seg_parts['0'] == $x['1'])
  138. {
  139. array_shift($this->seg_parts);
  140. }
  141. }
  142. /** ----------------------------------------
  143. /** Preferences and Language
  144. /** ----------------------------------------*/
  145. if ($this->EE->TMPL->fetch_param('wiki') !== FALSE)
  146. {
  147. $query = $this->EE->db->query("SELECT * FROM exp_wikis WHERE wiki_short_name = '".$this->EE->db->escape_str($this->EE->TMPL->fetch_param('wiki'))."'");
  148. }
  149. else
  150. {
  151. $query = $this->EE->db->query("SELECT * FROM exp_wikis WHERE wiki_short_name = 'default_wiki'");
  152. }
  153. if ($query->num_rows() == 0)
  154. {
  155. return $this->return_data = 'No Valid Wiki Specified';
  156. }
  157. foreach($query->row_array() as $field => $value)
  158. {
  159. if ($field != 'wiki_id')
  160. {
  161. $field = substr($field, 5);
  162. }
  163. if ($field == 'users' OR $field == 'admins')
  164. {
  165. $value = explode('|', $value);
  166. }
  167. $this->{$field} = $value;
  168. }
  169. /** ------------------------------------
  170. /** Retrieve Our Namespaces
  171. /** ------------------------------------*/
  172. $namespace_query = $this->EE->db->query("SELECT * FROM exp_wiki_namespaces WHERE wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."' ORDER BY namespace_name");
  173. if ($namespace_query->num_rows() > 0)
  174. {
  175. foreach($namespace_query->result_array() as $row)
  176. {
  177. $this->namespaces[strtolower($row['namespace_name'])] = array($row['namespace_name'], $row['namespace_label']);
  178. if (isset($this->seg_parts['0']) && strcasecmp($this->prep_title(substr($this->seg_parts['0'], 0, strlen($row['namespace_label'].':'))), $row['namespace_label'].':') == 0)
  179. {
  180. $this->admins = explode('|', $row['namespace_admins']);
  181. $this->users = explode('|', $row['namespace_users']);
  182. }
  183. }
  184. }
  185. if ($this->EE->TMPL->fetch_param('profile_path') !== FALSE)
  186. {
  187. $this->profile_path = $this->EE->functions->remove_double_slashes('/'.$this->EE->TMPL->fetch_param('profile_path').'/'.$this->EE->config->item('profile_trigger').'/');
  188. }
  189. else
  190. {
  191. $this->profile_path = $this->EE->functions->remove_double_slashes('/'.$this->EE->config->item('profile_trigger').'/');
  192. }
  193. /** ----------------------------------------
  194. /** Namespaces Localization
  195. /** ----------------------------------------*/
  196. $this->main_ns = (isset($this->EE->lang->language['main_ns'])) ? $this->EE->lang->line('main_ns') : $this->main_ns;
  197. $this->file_ns = (isset($this->EE->lang->language['file_ns'])) ? $this->EE->lang->line('file_ns') : $this->file_ns;
  198. $this->image_ns = (isset($this->EE->lang->language['image_ns'])) ? $this->EE->lang->line('image_ns') : $this->image_ns;
  199. $this->special_ns = (isset($this->EE->lang->language['special_ns'])) ? $this->EE->lang->line('special_ns') : $this->special_ns;
  200. $this->category_ns = (isset($this->EE->lang->language['category_ns'])) ? $this->EE->lang->line('category_ns') : $this->category_ns;
  201. /* ----------------------------------------
  202. /* Category namespace actually has articles so it is put into the
  203. /* namespaces array. However, instead of the localized name we use
  204. /* the relatively simple 'category' in the page_namespace field.
  205. /* ---------------------------------------*/
  206. $this->namespaces['category'] = array('category', $this->category_ns);
  207. /** ----------------------------------------
  208. /** Tag Settings
  209. /** ----------------------------------------*/
  210. if ( ! in_array('1', $this->admins)) $this->admins[] = "1";
  211. if ( ! in_array('1', $this->users)) $this->users[] = "1";
  212. foreach($this->admins as $key => $value)
  213. {
  214. if (in_array($value, array('2', '3', '4')))
  215. {
  216. unset($this->admins[$key]);
  217. }
  218. }
  219. foreach($this->users as $key => $value)
  220. {
  221. if (in_array($value, array('2', '3', '4')))
  222. {
  223. unset($this->users[$key]);
  224. }
  225. }
  226. /** ----------------------------------------
  227. /** Valid Upload Directory?
  228. /** ----------------------------------------*/
  229. if ( ! empty($this->upload_dir) && is_numeric($this->upload_dir))
  230. {
  231. $query = $this->EE->db->query("SELECT COUNT(*) AS count FROM exp_upload_prefs
  232. WHERE id = '".$this->EE->db->escape_str($this->upload_dir)."'");
  233. if ($query->row('count') > 0)
  234. {
  235. $this->valid_upload_dir = 'y';
  236. $this->can_upload = 'y';
  237. if (in_array($this->EE->session->userdata['group_id'], array(2, 3, 4)))
  238. {
  239. $this->can_upload = 'n';
  240. }
  241. elseif ($this->EE->session->userdata['group_id'] != 1)
  242. {
  243. $query = $this->EE->db->query("SELECT upload_id FROM exp_upload_no_access WHERE member_group = '".$this->EE->session->userdata['group_id']."'");
  244. if ($query->num_rows() > 0)
  245. {
  246. foreach($query->result_array() as $row)
  247. {
  248. if ($query->row('upload_id') == $this->upload_dir)
  249. {
  250. $this->can_upload = 'n';
  251. break;
  252. }
  253. }
  254. }
  255. }
  256. }
  257. }
  258. /** ----------------------------------------
  259. /** Set theme, load file helper
  260. /** ----------------------------------------*/
  261. $this->EE->load->helper('file');
  262. $this->theme_path = PATH_THEMES.'wiki_themes/default/';
  263. $this->image_url = $this->EE->config->slash_item('theme_folder_url').'wiki_themes/default/images/';
  264. $this->theme_url = $this->EE->config->slash_item('theme_folder_url').'wiki_themes/default/';
  265. if ($this->EE->TMPL->fetch_param('theme') !== FALSE && $this->EE->TMPL->fetch_param('theme') != '' && $this->EE->TMPL->fetch_param('theme') != 'default')
  266. {
  267. $theme = $this->EE->security->sanitize_filename($this->EE->TMPL->fetch_param('theme'));
  268. if (is_dir(PATH_THEMES.'/wiki_themes/'.$theme))
  269. {
  270. $this->theme_path = PATH_THEMES.'wiki_themes/'.$theme.'/';
  271. $this->image_url = $this->EE->config->slash_item('theme_folder_url').'wiki_themes/'.$theme.'/images/';
  272. $this->theme_url = $this->EE->config->slash_item('theme_folder_url').'wiki_themes/'.$theme.'/';
  273. }
  274. else
  275. {
  276. $this->EE->TMPL->log_item('Wiki module: theme not found - "'.htmlentities($theme).'"');
  277. }
  278. }
  279. /** ----------------------------------------
  280. /** Editing Article
  281. /** ----------------------------------------*/
  282. if ($this->EE->input->post('editing') == 'y' && $this->EE->input->post('preview') === FALSE)
  283. {
  284. return $this->edit_article();
  285. }
  286. /** ----------------------------------------
  287. /** Displaying Page
  288. /** ----------------------------------------*/
  289. $this->return_data = str_replace(array('{module_version}'), array($this->version), $this->_fetch_template('wiki_page.html'));
  290. $this->return_data = $this->active_members($this->return_data);
  291. /* -------------------------------------
  292. /* 'wiki_start' hook.
  293. /* - Allows page template to be modified prior to article processing
  294. /* - Added 1.6.0
  295. */
  296. if ($this->EE->extensions->active_hook('wiki_start') === TRUE)
  297. {
  298. $this->return_data = $this->EE->extensions->universal_call('wiki_start', $this);
  299. if ($this->EE->extensions->end_script === TRUE) return;
  300. }
  301. /*
  302. /* -------------------------------------*/
  303. /** ----------------------------------------
  304. /** Determine Page to Show
  305. /** ----------------------------------------*/
  306. // Index Page
  307. if (count($this->seg_parts) == 0 OR $this->EE->uri->query_string == '' OR $this->EE->uri->query_string == 'index')
  308. {
  309. $this->title = 'index';
  310. $this->article('index');
  311. }
  312. // File Page
  313. elseif (substr($this->seg_parts['0'], 0, strlen($this->file_ns.':')) == $this->file_ns.':')
  314. {
  315. $this->title = $this->seg_parts['0'];
  316. $this->current_namespace = $this->file_ns;
  317. $this->file(substr($this->seg_parts['0'], strlen($this->file_ns.':')));
  318. }
  319. // Image
  320. elseif (substr($this->seg_parts['0'], 0, strlen($this->image_ns.':')) == $this->image_ns.':')
  321. {
  322. $this->title = $this->seg_parts['0'];
  323. $this->current_namespace = $this->image_ns;
  324. $this->image(substr($this->seg_parts['0'], strlen($this->image_ns.':')));
  325. }
  326. // Special Page
  327. elseif (substr($this->seg_parts['0'], 0, strlen($this->special_ns.':')) == $this->special_ns.':')
  328. {
  329. $this->title = $this->seg_parts['0'];
  330. $this->current_namespace = $this->special_ns;
  331. $this->special(substr($this->seg_parts['0'], strlen($this->special_ns.':')));
  332. }
  333. // Download!
  334. elseif (isset($this->seg_parts['0']) && strlen($this->seg_parts['0']) == 32 && preg_match("/^[a-z0-9]+$/i", $this->seg_parts['0']))
  335. {
  336. $this->display_attachment();
  337. exit;
  338. }
  339. // Typical Boring Article. Yawn!
  340. else
  341. {
  342. if (in_array($this->seg_parts['0'], array('edit', 'history', 'revision', 'noredirect')))
  343. {
  344. $this->title = 'index';
  345. if ($this->seg_parts['0'] == 'noredirect')
  346. {
  347. $this->article('index');
  348. }
  349. else
  350. {
  351. $this->{$this->seg_parts['0']}('index');
  352. }
  353. }
  354. else
  355. {
  356. $this->title = $this->seg_parts['0'];
  357. if ($this->valid_title($this->title) != $this->title)
  358. {
  359. $this->redirect('', $this->title);
  360. }
  361. if (isset($this->seg_parts['1']) && $this->seg_parts['1'] == 'edit')
  362. {
  363. $this->edit($this->title);
  364. }
  365. elseif (isset($this->seg_parts['1']) && $this->seg_parts['1'] == 'history')
  366. {
  367. $this->history($this->title);
  368. }
  369. elseif (isset($this->seg_parts['1']) && $this->seg_parts['1'] == 'revision')
  370. {
  371. $this->revision($this->title);
  372. }
  373. else
  374. {
  375. $this->article($this->title);
  376. }
  377. }
  378. }
  379. if ($this->can_upload == 'y')
  380. {
  381. $this->return_data = $this->_allow_if('uploads', $this->return_data);
  382. }
  383. else
  384. {
  385. $this->return_data = $this->_deny_if('uploads', $this->return_data);
  386. }
  387. /** ----------------------------------------
  388. /** Global Tags
  389. /** ----------------------------------------*/
  390. if (preg_match_all("/\{wiki:custom_namespaces_list(.*?)\}(.*?)\{\/wiki:custom_namespaces_list\}/s", $this->return_data, $matches))
  391. {
  392. for($i = 0, $s = count($matches[0]); $i < $s; ++$i)
  393. {
  394. $output = '';
  395. if (count($this->namespaces) > 0)
  396. {
  397. foreach($this->namespaces as $name => $label)
  398. {
  399. $selected = (isset($this->seg_parts['1']) && strtolower($this->seg_parts['1']) == $name) ? 'selected="selected"' : '';
  400. $output .= str_replace(array('{namespace_short_name}', '{namespace_label}', '{namespace_selected}'), array($label['0'], $label['1'], $selected), $matches['2'][$i]);
  401. }
  402. }
  403. $this->return_data = str_replace($matches['0'][$i], $output, $this->return_data);
  404. }
  405. }
  406. if (preg_match("/\{wiki:categories_list(.*?)\}(.*?)\{\/wiki:categories_list\}/s", $this->return_data))
  407. {
  408. $this->categories_list();
  409. }
  410. /** ----------------------------------------
  411. /** Global Conditionals
  412. /** ----------------------------------------*/
  413. if ($this->EE->session->userdata('member_id') == 0)
  414. {
  415. $this->return_data = $this->_deny_if('logged_in', $this->return_data);
  416. $this->return_data = $this->_allow_if('logged_out', $this->return_data);
  417. }
  418. else
  419. {
  420. $this->return_data = $this->_allow_if('logged_in', $this->return_data);
  421. $this->return_data = $this->_deny_if('logged_out', $this->return_data);
  422. }
  423. if (in_array($this->EE->session->userdata['group_id'], $this->admins))
  424. {
  425. $this->return_data = $this->_deny_if('cannot_admin', $this->return_data);
  426. $this->return_data = $this->_allow_if('can_admin', $this->return_data);
  427. }
  428. else
  429. {
  430. $this->return_data = $this->_allow_if('cannot_admin', $this->return_data);
  431. $this->return_data = $this->_deny_if('can_admin', $this->return_data);
  432. }
  433. /** ----------------------------------------
  434. /** Global Variables
  435. /** ----------------------------------------*/
  436. $link = $this->create_url($this->current_namespace, $this->topic);
  437. // Load the XML Helper
  438. $this->EE->load->helper('xml');
  439. $data = array( '{charset}' => $this->EE->config->item('output_charset'),
  440. '{wiki_name}' => $this->label_name,
  441. '{title}' => xml_convert($this->prep_title($this->title)),
  442. '{url_title}' => xml_convert($this->valid_title($this->title)),
  443. '{topic}' => xml_convert($this->prep_title($this->topic)),
  444. '{namespace}' => xml_convert($this->current_namespace),
  445. '{special_namespace}' => xml_convert($this->special_ns),
  446. '{main_namespace}' => xml_convert($this->main_ns),
  447. '{file_namespace}' => xml_convert($this->file_ns),
  448. '{category_namespace}' => xml_convert($this->category_ns),
  449. '{image_namespace}' => xml_convert($this->image_ns),
  450. '{revision_id}' => $this->revision_id,
  451. '{screen_name}' => $this->prep_screen_name($this->EE->session->userdata('screen_name')),
  452. '{path:wiki_home}' => $this->EE->functions->create_url($this->base_path),
  453. '{path:wiki_base_url}' => $this->base_url,
  454. '{path:article_history}' => $link.'/history',
  455. '{path:view_article}' => $link,
  456. '{path:edit_article}' => $link.'/edit',
  457. '{path:logout}' => $this->EE->functions->fetch_site_index(0, 0).QUERY_MARKER.'ACT='.$this->EE->functions->fetch_action_id('Member', 'member_logout'),
  458. '{path:your_control_panel}' => $this->EE->functions->create_url($this->profile_path.'profile'),
  459. '{path:your_profile}' => $this->EE->functions->create_url($this->profile_path.$this->EE->session->userdata('member_id')),
  460. '{path:login}' => $this->EE->functions->create_url($this->profile_path.'login'),
  461. '{path:register}' => $this->EE->functions->create_url($this->profile_path.'register'),
  462. '{path:memberlist}' => $this->EE->functions->create_url($this->profile_path.'memberlist'),
  463. '{path:forgot}' => $this->EE->functions->create_url($this->profile_path.'forgot_password'),
  464. '{path:private_messages}' => $this->EE->functions->create_url($this->profile_path.'messages/view_folder/1'),
  465. '{path:image_url}' => $this->image_url,
  466. '{path:theme_url}' => $this->theme_url,
  467. '{text_format}' => ucwords(str_replace('_', ' ', $this->text_format))
  468. );
  469. /** -------------------------------------
  470. /** Parse URI segments
  471. /** -------------------------------------*/
  472. // This code lets admins fetch URI segments which become
  473. // available as: {segment_1} {segment_2}
  474. for ($i = 1; $i < 9; $i++)
  475. {
  476. $data[LD.'segment_'.$i.RD] = $this->EE->uri->segment($i);
  477. }
  478. /** -------------------------------------
  479. /** Parse Snippets
  480. /** -------------------------------------*/
  481. foreach ($this->EE->config->_global_vars as $key => $val)
  482. {
  483. $data[LD.$key.RD] = $val;
  484. }
  485. /** -------------------------------------
  486. /** Parse manual variables
  487. /** -------------------------------------*/
  488. if (count($this->EE->TMPL->global_vars) > 0)
  489. {
  490. foreach ($this->EE->TMPL->global_vars as $key => $val)
  491. {
  492. $data[LD.$key.RD] = $val;
  493. }
  494. }
  495. /* -------------------------------------
  496. /* We reset some of these because in $data we are converting them
  497. /* for display purposes and we would rather have the conditionals
  498. /* use the unmodified versions
  499. /* -------------------------------------*/
  500. $this->conditionals['title'] = $this->title;
  501. $this->conditionals['topic'] = $this->topic;
  502. $this->conditionals['namespace'] = $this->current_namespace;
  503. $this->return_data = $this->prep_conditionals($this->return_data, array_merge($data, $this->conditionals));
  504. $this->return_data = str_replace(array_keys($data), array_values($data), $this->return_data);
  505. /** ----------------------------------------
  506. /** Cleanup
  507. /** ----------------------------------------*/
  508. $this->return_data = $this->_deny_if('redirected', $this->return_data);
  509. $this->return_data = $this->_deny_if('redirect_page', $this->return_data);
  510. }
  511. // --------------------------------------------------------------------
  512. /**
  513. * Fetch Template
  514. *
  515. * Fetches a template fragment
  516. *
  517. * @access public
  518. * @param string
  519. * @return string
  520. */
  521. function _fetch_template($which)
  522. {
  523. return read_file($this->theme_path.$which);
  524. }
  525. // --------------------------------------------------------------------
  526. /** ----------------------------------------
  527. /** Redirect for the Wiki
  528. /** ----------------------------------------*/
  529. function redirect($namespace='', $title)
  530. {
  531. $this->EE->functions->redirect($this->create_url($namespace, $title));
  532. exit;
  533. }
  534. /** ----------------------------------------
  535. /** Creat URL for the Wiki
  536. /** ----------------------------------------*/
  537. function create_url($namespace='', $title)
  538. {
  539. if ($namespace == '' && stristr($title, ':') && count($this->namespaces) > 0)
  540. {
  541. foreach($this->namespaces as $possible)
  542. {
  543. if (substr($title, 0, strlen($possible['1'].':')) == $possible['1'].':')
  544. {
  545. $namespace = $possible['1'];
  546. $title = substr($title, strlen($possible['1'].':'));
  547. break;
  548. }
  549. }
  550. }
  551. if ($namespace != '')
  552. {
  553. /*
  554. Convert any colons back because of Category articles
  555. */
  556. $link = $this->EE->functions->create_url($this->base_path.
  557. urlencode($this->valid_title($namespace)).
  558. ':'.
  559. str_replace('%3A', ':', urlencode($this->valid_title($title))));
  560. }
  561. else
  562. {
  563. $link = $this->EE->functions->create_url($this->base_path.
  564. urlencode($this->valid_title($title)));
  565. }
  566. return $link;
  567. }
  568. /** ----------------------------------------
  569. /** Prep Screen Name for Display
  570. /** ----------------------------------------*/
  571. function prep_screen_name($str)
  572. {
  573. return str_replace(array('<', '>', '{', '}', '\'', '"', '?'), array('&lt;', '&gt;', '&#123;', '&#125;', '&#146;', '&quot;', '&#63;'), $str);
  574. }
  575. /** ----------------------------------------
  576. /** Prep Title Display
  577. /** ----------------------------------------*/
  578. function prep_title($str)
  579. {
  580. if ($this->EE->config->item('word_separator') == 'dash')
  581. {
  582. return str_replace(array('-', $this->cats_separator), array(' ', $this->cats_display_separator), $str);
  583. }
  584. else
  585. {
  586. return str_replace(array('_', $this->cats_separator), array(' ', $this->cats_display_separator), $str);
  587. }
  588. }
  589. /** ----------------------------------------
  590. /** Create Valid Topic Name
  591. /** ----------------------------------------*/
  592. function valid_title($str)
  593. {
  594. // Remove all numeric entities
  595. $str = preg_replace('/&#x([0-9a-f]{2,5});{0,1}|&#([0-9]{2,4});{0,1}/', '', $str);
  596. $trans = array();
  597. $trans["#[^a-z0-9\-\_@&\'\"!\.:\+\x{A1}-\x{44F}\s]#iu"] = '';
  598. // Use dash or underscore as separator
  599. $replace = ($this->EE->config->item('word_separator') == 'dash') ? '-' : '_';
  600. $trans = array_merge($trans, array(
  601. '/\s+/' => $replace,
  602. "/{$replace}+/" => $replace,
  603. "/{$replace}$/" => $replace,
  604. "/^{$replace}/" => $replace
  605. ));
  606. return preg_replace(array_keys($trans), array_values($trans), urldecode($str));
  607. }
  608. /** ----------------------------------------
  609. /** Take Namespace's Short Name and Convert to Label
  610. /** ----------------------------------------*/
  611. function namespace_label($short_name)
  612. {
  613. if ($short_name != '')
  614. {
  615. $short_name = strtolower($short_name);
  616. $short_name = (isset($this->namespaces[$short_name])) ? $this->namespaces[$short_name]['1'] : '';
  617. }
  618. return $short_name;
  619. }
  620. /** ----------------------------------------
  621. /** Encode EE Tags
  622. /** ----------------------------------------*/
  623. function encode_ee_tags($str)
  624. {
  625. return str_replace(array('{','}'), array('&#123;','&#125;'), $str);
  626. }
  627. /* ----------------------------------------
  628. /* Topic Request!
  629. /*
  630. /* - Title = Namespace:Topic
  631. /* - If no namespace, then Title and Topic are
  632. /* the same thing
  633. /* ----------------------------------------*/
  634. function topic_request($title)
  635. {
  636. $title = $this->valid_title($title);
  637. $xsql = " AND page_namespace = '' ";
  638. // In the beginning, these are the same thing
  639. $this->topic = $title;
  640. $this->title = $title;
  641. if (stristr($title, ':') && count($this->namespaces) > 0)
  642. {
  643. $parts = explode(':', $title, 2);
  644. /* In PHP 5.1 this loop was consistently faster than array_search() */
  645. foreach($this->namespaces as $name => $label)
  646. {
  647. if (strcasecmp($label['1'], $this->prep_title($parts['0'])) == 0)
  648. {
  649. $xsql = " AND LOWER(page_namespace) = '".$this->EE->db->escape_str($name)."' ";
  650. $this->topic = substr($this->topic, strlen($label['1'].':'));
  651. $this->current_namespace = $label['1'];
  652. $this->title = $this->current_namespace.':'.$this->topic;
  653. break;
  654. }
  655. }
  656. }
  657. return $this->EE->db->query("SELECT * FROM exp_wiki_page
  658. WHERE wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  659. AND LOWER(page_name) = '".strtolower($this->EE->db->escape_str($this->topic))."'
  660. {$xsql}");
  661. }
  662. /** ----------------------------------------
  663. /** Load Image
  664. /** ----------------------------------------*/
  665. function image($topic, $return=FALSE)
  666. {
  667. if ($return === FALSE)
  668. {
  669. $this->title = $this->image_ns.':'.$topic;
  670. }
  671. /*
  672. No way to show the image if we do not have a valid upload directory
  673. because we need the URL for that directory.
  674. */
  675. if ($this->valid_upload_dir != 'y')
  676. {
  677. if ($return === TRUE) return FALSE;
  678. $this->redirect($this->file_ns, $topic);
  679. }
  680. /** ----------------------------------------
  681. /** Does File Exist? Is It An Image?
  682. /** ----------------------------------------*/
  683. $query = $this->EE->db->query("SELECT * FROM exp_wiki_uploads
  684. WHERE file_name = '".$this->EE->db->escape_str($topic)."'");
  685. if ($query->num_rows() == 0)
  686. {
  687. if ($return === TRUE) return FALSE;
  688. $this->redirect($this->file_ns, $topic);
  689. }
  690. $x = explode('/',$query->row('file_type') );
  691. if ($x['0'] != 'image')
  692. {
  693. if ($return === TRUE) return FALSE;
  694. $this->redirect($this->file_ns, $topic);
  695. }
  696. /** ----------------------------------------
  697. /** Create Our URL
  698. /** ----------------------------------------*/
  699. if ($return === TRUE)
  700. {
  701. $file_url = $this->base_url.$query->row('file_hash');
  702. }
  703. else
  704. {
  705. $this->EE->load->model('file_upload_preferences_model');
  706. $upload_prefs = $this->EE->file_upload_preferences_model->get_file_upload_preferences(1, $this->upload_dir);
  707. // Make sure we have a trailing slash on the path, then append file name
  708. $file_url = rtrim($upload_prefs['url'], '/').'/';
  709. $file_url .= $query->row('file_name') ;
  710. }
  711. /* ----------------------------------------
  712. /* Display Our Image
  713. /* - Now in the future we might be clever and obfuscate the location
  714. /* - of images, if it is requested, by using fopen to get the image
  715. /* - data and displaying it instead of doing a redirect to the URL
  716. /* ----------------------------------------*/
  717. if ($return === TRUE)
  718. {
  719. return array('url' => $file_url,
  720. 'width' => $query->row('image_width') ,
  721. 'height' => $query->row('image_height') ,
  722. 'name' => $query->row('file_name') );
  723. }
  724. $this->EE->functions->redirect($file_url);
  725. exit;
  726. }
  727. /** ----------------------------------------
  728. /** File
  729. /** ----------------------------------------*/
  730. function file($topic)
  731. {
  732. $this->title = $this->file_ns.':'.$topic;
  733. $this->topic = $topic;
  734. /** ----------------------------------------
  735. /** Delete File? Admins Only!
  736. /** ----------------------------------------*/
  737. if (isset($this->seg_parts['1']) && strtolower($this->seg_parts['1']) == 'delete')
  738. {
  739. if ($this->can_upload == 'y' && in_array($this->EE->session->userdata['group_id'], $this->admins))
  740. {
  741. $query = $this->EE->db->query("SELECT COUNT(*) AS count FROM exp_wiki_uploads
  742. WHERE file_name = '".$this->EE->db->escape_str($topic)."'");
  743. if ($query->row('count') > 0)
  744. {
  745. // Delete from file system?? Pretty much have to- nuked it
  746. $this->EE->load->model('file_model');
  747. $this->EE->file_model->delete_files_by_name($this->upload_dir, $topic);
  748. // The hook clears out wiki_uploads and the db cache
  749. $this->redirect($this->special_ns, 'Files');
  750. }
  751. }
  752. }
  753. $this->return_data = $this->_deny_if('new_article', $this->return_data);
  754. $this->return_data = $this->_deny_if('article', $this->return_data);
  755. $this->return_data = $this->_deny_if('revision', $this->return_data);
  756. $this->return_data = $this->_deny_if('edit_article', $this->return_data);
  757. $this->return_data = $this->_deny_if('article_history', $this->return_data);
  758. $this->return_data = $this->_deny_if('special_page', $this->return_data);
  759. $this->return_data = $this->_allow_if('file_page', $this->return_data);
  760. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_file.html'), $this->return_data);
  761. $query = $this->EE->db->query("SELECT u.*, m.member_id, m.screen_name, m.email, m.url
  762. FROM exp_wiki_uploads u, exp_members m
  763. WHERE u.file_name = '".$this->EE->db->escape_str($topic)."'
  764. AND u.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  765. AND u.upload_author = m.member_id");
  766. /** ----------------------------------------
  767. /** Does File Exist? What Kind?
  768. /** ----------------------------------------*/
  769. if ($query->num_rows() == 0)
  770. {
  771. $this->return_data = $this->_deny_if('file_exists', $this->return_data);
  772. return;
  773. }
  774. else
  775. {
  776. $this->return_data = $this->_allow_if('file_exists', $this->return_data);
  777. }
  778. $x = explode('/',$query->row('file_type') );
  779. if ($x['0'] == 'image')
  780. {
  781. $this->return_data = $this->_allow_if('is_image', $this->return_data);
  782. }
  783. else
  784. {
  785. $this->return_data = $this->_deny_if('is_image', $this->return_data);
  786. }
  787. /** ----------------------------------------
  788. /** Date Formats
  789. /** ----------------------------------------*/
  790. if (preg_match_all("/".LD."(upload_date)\s+format=[\"'](.*?)[\"']".RD."/s", $this->return_data, $matches))
  791. {
  792. for ($j = 0; $j < count($matches['0']); $j++)
  793. {
  794. switch ($matches['1'][$j])
  795. {
  796. case 'upload_date' : $upload_date[$matches['0'][$j]] = array($matches['2'][$j], $this->EE->localize->fetch_date_params($matches['2'][$j]));
  797. break;
  798. }
  799. }
  800. foreach($upload_date as $key => $value)
  801. {
  802. $temp_date = $value['0'];
  803. foreach ($value['1'] as $dvar)
  804. {
  805. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $row['upload_date'], FALSE), $temp_date);
  806. }
  807. $this->return_data = str_replace($key, $temp_date, $this->return_data);
  808. }
  809. }
  810. /** ----------------------------------------
  811. /** Parse Variables
  812. /** ----------------------------------------*/
  813. $this->EE->load->library('typography');
  814. $this->EE->typography->initialize(array(
  815. 'parse_images' => FALSE,
  816. 'parse_smileys' => FALSE)
  817. );
  818. $summary = $this->convert_curly_brackets($this->EE->typography->parse_type( $this->wiki_syntax($query->row('upload_summary') ),
  819. array(
  820. 'text_format' => $this->text_format,
  821. 'html_format' => $this->html_format,
  822. 'auto_links' => $this->auto_links,
  823. 'allow_img_url' => 'y'
  824. )
  825. ));
  826. $delete_url = '';
  827. if ($this->valid_upload_dir != 'y')
  828. {
  829. $file_url = $query->row('file_name') ;
  830. }
  831. else
  832. {
  833. $file_url = $this->base_url.$query->row('file_hash');
  834. if (in_array($this->EE->session->userdata['group_id'], $this->admins))
  835. {
  836. $delete_url = $this->base_url.$this->file_ns.':'.$query->row('file_name').'/delete';
  837. }
  838. }
  839. $this->conditionals['summary'] = $summary;
  840. $this->conditionals['delete_url'] = $delete_url;
  841. $this->conditionals = array_merge($this->conditionals, $query->row_array());
  842. /** ----------------------------------------
  843. /** Can User Edit File?
  844. /** ----------------------------------------*/
  845. if(in_array($this->EE->session->userdata['group_id'], $this->users) OR in_array($this->EE->session->userdata['group_id'], $this->admins))
  846. {
  847. $this->return_data = $this->_allow_if('can_edit', $this->return_data);
  848. $this->return_data = $this->_deny_if('cannot_edit', $this->return_data);
  849. }
  850. else
  851. {
  852. $this->return_data = $this->_deny_if('can_edit', $this->return_data);
  853. $this->return_data = $this->_allow_if('cannot_edit', $this->return_data);
  854. }
  855. $this->return_data = str_replace(array('{file_url}','{delete_url}','{file_name}','{summary}', '{image_width}', '{image_height}', '{file_type}'),
  856. array($file_url, $delete_url, $query->row('file_name') , $summary, $query->row('image_width') , $query->row('image_height') , $query->row('file_type') ),
  857. $this->return_data);
  858. }
  859. /** ----------------------------------------
  860. /** Special
  861. /** ----------------------------------------*/
  862. function special($topic)
  863. {
  864. $this->topic = $topic;
  865. $this->title = $this->special_ns.':'.$topic;
  866. $this->return_data = $this->_deny_if('new_article', $this->return_data);
  867. $this->return_data = $this->_deny_if('article', $this->return_data);
  868. $this->return_data = $this->_deny_if('revision', $this->return_data);
  869. $this->return_data = $this->_deny_if('edit_article', $this->return_data);
  870. $this->return_data = $this->_deny_if('article_history', $this->return_data);
  871. $this->return_data = $this->_allow_if('special_page', $this->return_data);
  872. /* -------------------------------------
  873. /* 'wiki_special_page' hook.
  874. /* - Allows complete takeover of special pages
  875. /* - Added 1.6.0
  876. */
  877. $edata = $this->EE->extensions->universal_call('wiki_special_page', $this, $topic);
  878. if ($this->EE->extensions->end_script === TRUE) return;
  879. /*
  880. /* -------------------------------------*/
  881. switch(strtolower($topic))
  882. {
  883. case 'recentchanges' :
  884. $this->recent_changes();
  885. break;
  886. case 'search_results' :
  887. $this->search_results();
  888. break;
  889. case 'random_page' :
  890. $this->random_page();
  891. break;
  892. case 'categories' :
  893. $this->categories();
  894. break;
  895. case 'files' :
  896. $this->files();
  897. break;
  898. case 'find_page' :
  899. $this->find_page();
  900. break;
  901. case 'uploads' :
  902. $this->upload_form();
  903. break;
  904. case 'recentchanges_rss' :
  905. $this->EE->output->out_type = 'feed';
  906. $this->EE->TMPL->template_type = 'feed';
  907. $this->return_data = $this->_fetch_template('wiki_special_rss.html');
  908. $this->recent_changes('rss');
  909. break;
  910. case 'recentchanges_atom' :
  911. $this->EE->output->out_type = 'feed';
  912. $this->EE->TMPL->template_type = 'feed';
  913. $this->return_data = $this->_fetch_template('wiki_special_atom.html');
  914. $this->recent_changes('atom');
  915. break;
  916. case 'titles' :
  917. $this->title_list();
  918. break;
  919. case 'associated_pages' :
  920. $this->associated_pages();
  921. break;
  922. case 'uncategorized' :
  923. $this->uncategorized_pages();
  924. break;
  925. case 'css' :
  926. $this->wiki_css();
  927. break;
  928. default:
  929. $this->return_data = str_replace('{wiki:page}', '', $this->return_data);
  930. break;
  931. }
  932. $this->return_data = $this->_deny_if('can_edit', $this->return_data);
  933. $this->return_data = $this->_allow_if('cannot_edit', $this->return_data);
  934. }
  935. // --------------------------------------------------------------------
  936. /**
  937. * Wiki CSS
  938. *
  939. * Outputs the default Wiki CSS theme file with proper headers
  940. *
  941. * @access public
  942. * @return void
  943. */
  944. function wiki_css()
  945. {
  946. // reset! We just want the CSS
  947. $this->return_data = $this->_fetch_template('wiki_style.css');
  948. if ($this->return_data === FALSE)
  949. {
  950. // no point
  951. exit;
  952. }
  953. // replace image paths
  954. $this->return_data = str_replace('{path:image_url}', $this->image_url, $this->return_data);
  955. $last_modified = filemtime($this->theme_path.'wiki_style.css');
  956. $this->EE->load->library('stylesheet');
  957. $this->EE->stylesheet->_send_css($this->return_data, $last_modified);
  958. }
  959. // --------------------------------------------------------------------
  960. /** ---------------------------------------
  961. /** Uncategorized Pages
  962. /** ---------------------------------------*/
  963. function uncategorized_pages()
  964. {
  965. return $this->title_list('uncategorized_pages');
  966. }
  967. /* END */
  968. /** ----------------------------------------
  969. /** Recent Changes Processing
  970. /** ----------------------------------------*/
  971. function title_list($type = '')
  972. {
  973. /** ---------------------------------------
  974. /** Initialize the correct template and do any
  975. /** prep work needed prior to our title query
  976. /** ---------------------------------------*/
  977. switch ($type)
  978. {
  979. case 'uncategorized_pages' :
  980. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_special_uncategorized_pages.html'), $this->return_data);
  981. /** ---------------------------------------
  982. /** Get categorized page ids
  983. /** ---------------------------------------*/
  984. $query = $this->EE->db->distinct('exp_wiki_category_articles.page_id')
  985. ->from('wiki_category_articles')
  986. ->join('wiki_page', 'exp_wiki_page.page_id = exp_wiki_category_articles.page_id')
  987. ->where('wiki_id', $this->wiki_id)
  988. ->get();
  989. if ($query->num_rows() > 0)
  990. {
  991. $page_ids = array();
  992. foreach ($query->result() as $row)
  993. {
  994. $page_ids[] = $row->page_id;
  995. }
  996. $xsql = " AND p.page_id NOT IN (".implode(',', $page_ids).")
  997. AND p.page_redirect = '' ";
  998. }
  999. break;
  1000. default :
  1001. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_special_titles.html'), $this->return_data);
  1002. break;
  1003. }
  1004. if ( ! preg_match("/\{wiki:title_list(.*?)\}(.*?)\{\/wiki:title_list\}/s", $this->return_data, $match))
  1005. {
  1006. return $this->return_data = '';
  1007. }
  1008. if ( ! preg_match("/\{articles\}(.*?)\{\/articles\}/s", $match['2'], $topics))
  1009. {
  1010. return $this->return_data = '';
  1011. }
  1012. /** ----------------------------------------
  1013. /** Parameters
  1014. /** ----------------------------------------*/
  1015. $columns = 3;
  1016. if (trim($match['1']) != '' && ($params = $this->EE->functions->assign_parameters($match['1'])) !== FALSE)
  1017. {
  1018. $columns = (isset($params['columns']) && is_numeric($params['columns'])) ? $params['columns'] : $limit;
  1019. }
  1020. /** ----------------------------------------
  1021. /** Date Formats
  1022. /** ----------------------------------------*/
  1023. $dates = $this->parse_dates($this->return_data);
  1024. /** ----------------------------------------
  1025. /** Our Query
  1026. /** ----------------------------------------*/
  1027. if ( ! isset($xsql))
  1028. {
  1029. $xsql = '';
  1030. }
  1031. if (isset($this->seg_parts['1']) && isset($this->namespaces[strtolower($this->seg_parts['1'])]))
  1032. {
  1033. $xsql .= "AND LOWER(p.page_namespace) = '".$this->EE->db->escape_str(strtolower($this->seg_parts['1']))."'";
  1034. }
  1035. else
  1036. {
  1037. $xsql .= "AND p.page_namespace = ''";
  1038. }
  1039. $results = $this->EE->db->query("SELECT r.*,
  1040. m.member_id, m.screen_name, m.email, m.url,
  1041. p.page_namespace, p.page_name AS topic
  1042. FROM exp_wiki_revisions r, exp_members m, exp_wiki_page p
  1043. WHERE p.last_updated = r.revision_date
  1044. {$xsql}
  1045. AND m.member_id = r.revision_author
  1046. AND r.page_id = p.page_id
  1047. AND r.revision_status = 'open'
  1048. AND r.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  1049. ORDER BY p.page_name");
  1050. if ($results->num_rows() == 0)
  1051. {
  1052. if (preg_match("|".LD."if\s+no_results".RD."(.*?)".LD."\/if".RD."|s",$match['2'], $block))
  1053. {
  1054. $this->return_data = str_replace($match['0'], $block['1'], $this->return_data);
  1055. }
  1056. else
  1057. {
  1058. $this->return_data = str_replace($match['0'], str_replace($topics['0'], '', $match['2']), $this->return_data);
  1059. }
  1060. return;
  1061. }
  1062. /** ----------------------------------------
  1063. /** Template Parts
  1064. /** ----------------------------------------*/
  1065. $our_template = $topics['1'];
  1066. $row_start = '';
  1067. $row_end = '';
  1068. $row_blank = '';
  1069. $row_column = '';
  1070. foreach(array('row_start', 'row_end', 'row_blank', 'row_column') as $val)
  1071. {
  1072. if (preg_match("/\{".preg_quote($val)."\}(.*?)\{\/".preg_quote($val)."\}/s", $our_template, $matching))
  1073. {
  1074. $$val = $matching['1'];
  1075. }
  1076. }
  1077. $template = $row_column;
  1078. /** ----------------------------------------
  1079. /** Parsing of the Recent Changes Tag Pair
  1080. /** ----------------------------------------*/
  1081. $parse_article = stristr($template, '{article}');
  1082. $this->EE->load->library('typography');
  1083. $this->EE->typography->initialize(array(
  1084. 'parse_images' => FALSE,
  1085. 'parse_smileys' => FALSE)
  1086. );
  1087. $titles = $row_start;
  1088. $i = 0;
  1089. $count = 0;
  1090. // added in 1.6 for {switch} variable and for future use
  1091. $vars = $this->EE->functions->assign_variables($template);
  1092. $this->EE->load->helper('url');
  1093. foreach($results->result_array() as $row)
  1094. {
  1095. $count++;
  1096. $titles .= ($i % $columns != 0) ? '' : $row_end.$row_start; ++$i;
  1097. $temp = $template;
  1098. if (isset($this->seg_parts['1']) && isset($this->namespaces[strtolower($this->seg_parts['1'])]))
  1099. {
  1100. $title = $row['topic'];
  1101. }
  1102. else
  1103. {
  1104. $title = ($row['page_namespace'] != '') ? $this->namespace_label($row['page_namespace']).':'.$row['topic'] : $row['topic'];
  1105. }
  1106. $link = $this->create_url($this->namespace_label($row['page_namespace']), $row['topic']);
  1107. $data = array( '{title}' => $this->prep_title($title),
  1108. '{revision_id}' => $row['revision_id'],
  1109. '{page_id}' => $row['page_id'],
  1110. '{author}' => $row['screen_name'],
  1111. '{path:author_profile}' => $this->EE->functions->create_url($this->profile_path.$row['member_id']),
  1112. '{path:member_profile}' => $this->EE->functions->create_url($this->profile_path.$row['member_id']),
  1113. '{email}' => $this->EE->typography->encode_email($row['email']),
  1114. '{url}' => prep_url($row['url']),
  1115. '{revision_notes}' => $row['revision_notes'],
  1116. '{path:view_article}' => $link,
  1117. '{content}' => $row['page_content'],
  1118. '{count}' => $count);
  1119. if ($parse_article !== FALSE)
  1120. {
  1121. $data['{article}'] = $this->convert_curly_brackets($this->EE->typography->parse_type( $this->wiki_syntax($row['page_content'], FALSE),
  1122. array(
  1123. 'text_format' => $this->text_format,
  1124. 'html_format' => $this->html_format,
  1125. 'auto_links' => $this->auto_links,
  1126. 'allow_img_url' => 'y'
  1127. )
  1128. ));
  1129. }
  1130. $temp = $this->prep_conditionals($temp, array_merge($data, $this->conditionals));
  1131. if (isset($dates['last_updated']))
  1132. {
  1133. foreach($dates['last_updated'] as $key => $value)
  1134. {
  1135. $temp_date = $value['0'];
  1136. // Do this once here, to save energy
  1137. $row['revision_date'] = $this->EE->localize->set_localized_time($row['revision_date']);
  1138. foreach ($value['1'] as $dvar)
  1139. {
  1140. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $row['revision_date'], FALSE), $temp_date);
  1141. }
  1142. $data[$key] = $temp_date;
  1143. }
  1144. }
  1145. foreach ($vars['var_single'] as $key => $val)
  1146. {
  1147. /** ----------------------------------------
  1148. /** parse {switch} variable
  1149. /** ----------------------------------------*/
  1150. if (preg_match("/^switch\s*=.+/i", $key))
  1151. {
  1152. $sparam = $this->EE->functions->assign_parameters($key);
  1153. $sw = '';
  1154. if (isset($sparam['switch']))
  1155. {
  1156. $sopt = explode("|", $sparam['switch']);
  1157. $sw = $sopt[($count-1 + count($sopt)) % count($sopt)];
  1158. }
  1159. $temp = $this->EE->TMPL->swap_var_single($key, $sw, $temp);
  1160. }
  1161. }
  1162. $titles .= str_replace(array_keys($data), array_values($data), $temp);
  1163. }
  1164. while($i % $columns != 0)
  1165. {
  1166. $titles .= $row_blank; ++$i;
  1167. }
  1168. $titles .= $row_end;
  1169. $this->return_data = str_replace($match['0'], str_replace($topics['0'], $titles, $match['2']), $this->return_data);
  1170. }
  1171. /** ----------------------------------------
  1172. /** Recent Changes Processing
  1173. /** ----------------------------------------*/
  1174. function recent_changes($type='')
  1175. {
  1176. /** ----------------------------------------
  1177. /** Load Template, Check for Valid Tag
  1178. /** ----------------------------------------*/
  1179. $this->return_data = str_replace('{wiki:page}', $this->_fetch_template('wiki_special_recent_changes.html'), $this->return_data);
  1180. if ( ! preg_match("/\{wiki:recent_changes(.*?)\}(.*?)\{\/wiki:recent_changes\}/s", $this->return_data, $match))
  1181. {
  1182. return $this->return_data = '';
  1183. }
  1184. /** ----------------------------------------
  1185. /** Parameters
  1186. /** ----------------------------------------*/
  1187. $parameters['limit'] = 10;
  1188. $parameters['paginate'] = 'bottom';
  1189. if (trim($match['1']) != '' && ($params = $this->EE->functions->assign_parameters($match['1'])) !== FALSE)
  1190. {
  1191. $parameters['limit'] = (isset($params['limit']) && is_numeric($params['limit'])) ? $params['limit'] : $parameters['limit'];
  1192. $parameters['paginate'] = (isset($params['paginate'])) ? $params['paginate'] : $parameters['paginate'];
  1193. }
  1194. /** ----------------------------------------
  1195. /** Date Formats
  1196. /** ----------------------------------------*/
  1197. $dates = $this->parse_dates($this->return_data);
  1198. /** ----------------------------------------
  1199. /** Our Query
  1200. /** ----------------------------------------*/
  1201. if (isset($this->seg_parts['1']) && $this->seg_parts['1'] != '' && ! preg_match("/^P[0-9]+$/", $this->seg_parts['1']))
  1202. {
  1203. $query = $this->topic_request($this->seg_parts['1']);
  1204. $sql = "FROM exp_wiki_revisions r, exp_members m, exp_wiki_page p
  1205. WHERE p.page_id = '".(($query->num_rows() > 0) ? $query->row('page_id') : '0')."'
  1206. AND r.page_id = p.page_id
  1207. AND r.revision_status = 'open'
  1208. AND r.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  1209. AND m.member_id = r.revision_author
  1210. ORDER BY r.revision_date DESC";
  1211. }
  1212. else
  1213. {
  1214. $sql = "FROM exp_wiki_revisions r, exp_members m, exp_wiki_page p
  1215. WHERE p.last_updated = r.revision_date
  1216. AND m.member_id = r.revision_author
  1217. AND r.page_id = p.page_id
  1218. AND r.revision_status = 'open'
  1219. AND r.wiki_id = '".$this->EE->db->escape_str($this->wiki_id)."'
  1220. ORDER BY p.last_updated DESC";
  1221. }
  1222. $results = $this->EE->db->query("SELECT COUNT(*) AS count ".$sql);
  1223. if ($results->row('count') == 0)
  1224. {
  1225. return $this->return_data = '';
  1226. }
  1227. $this->pagination($results->row('count') , $parameters['limit'], $this->base_url.$this->special_ns.':Recentchanges/');
  1228. // Pagination code removed, rerun template preg_match()
  1229. if ($this->paginate === TRUE)
  1230. {
  1231. preg_match("/\{wiki:recent_changes(.*?)\}(.*?)\{\/wiki:recent_changes\}/s", $this->return_data, $match);
  1232. }
  1233. else
  1234. {
  1235. $this->pagination_sql .= " LIMIT ".$parameters['limit'];
  1236. }
  1237. $results = $this->EE->db->query("SELECT r.*,
  1238. m.member_id, m.screen_name, m.email, m.url,
  1239. p.page_namespace, p.page_name AS topic ".
  1240. $sql.
  1241. $this->pagination_sql);
  1242. /** ----------------------------------------
  1243. /** Global Last Updated
  1244. /** ----------------------------------------*/
  1245. if (isset($dates['last_updated']))
  1246. {
  1247. foreach($dates['last_updated'] as $key => $value)
  1248. {
  1249. $temp_date = $value['0'];
  1250. foreach ($value['1'] as $dvar)
  1251. {
  1252. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $results->row('revision_date') , TRUE), $temp_date);
  1253. }
  1254. $this->return_data = str_replace($key, $temp_date, $this->return_data);
  1255. }
  1256. }
  1257. if (isset($dates['gmt_last_updated']))
  1258. {
  1259. foreach($dates['gmt_last_updated'] as $key => $value)
  1260. {
  1261. $temp_date = $value['0'];
  1262. foreach ($value['1'] as $dvar)
  1263. {
  1264. $temp_date = str_replace($dvar, $this->EE->localize->convert_timestamp($dvar, $results->row('revision_date') , FALSE), $temp_date);
  1265. }
  1266. $this->return_data = str_replace($key, $temp_date, $this->return_data);
  1267. }
  1268. }
  1269. /** ----------------------------------------
  1270. /** Parsing of the Recent Changes Tag Pair
  1271. /** ----------------------------------------*/
  1272. $this->EE->load->library('typography');
  1273. $this->EE->typography->initialize(array(
  1274. 'parse_images' => FALSE,
  1275. 'parse_smileys' => FALSE,
  1276. 'encode_email' => ($type == 'rss' OR $type == 'atom') ? FALSE : TRUE)
  1277. );
  1278. $changes = '';
  1279. $count = 0;
  1280. // added in 1.6 for {switch} variable and for future use
  1281. $vars = $this->EE->functions->assign_variables($match['2']);
  1282. $this->EE->load->helper('url');
  1283. foreach($results->result_array() as $row)
  1284. {
  1285. $count++;
  1286. $temp = $match['2'];
  1287. $title = ($row['page_namespace'] != '') ? $this->namespace_label($row['page_namespace']).':'.$row['topic'] : $row['topic'];
  1288. $link = $this->create_url($this->namespace_label($row['page_namespace']), $row['topic']);
  1289. $data = array( '{title}' => $this->prep_title($title),
  1290. '{revision_id}' => $row['revision_id'],
  1291. '{page_id}' => $row['page_id'],
  1292. '{author}' => $row['screen_name'],
  1293. '{path:author_profile}' => $this->EE->functions->create_url($this->profile_path.$row['member_id']),
  1294. '{path:member_profile}' => $this->EE->functions->create_ur

Large files files are truncated, but you can click here to view the full file