PageRenderTime 40ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/frontend/modules/search/ajax/autosuggest.php

http://github.com/forkcms/forkcms
PHP | 223 lines | 88 code | 38 blank | 97 comment | 18 complexity | 8dd2fd0ac33acf78c9f4e37266c688cb MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, MIT, AGPL-3.0, LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /*
  3. * This file is part of Fork CMS.
  4. *
  5. * For the full copyright and license information, please view the license
  6. * file that was distributed with this source code.
  7. */
  8. /**
  9. * This is the autosuggest-action, it will output a list of results for a certain search
  10. *
  11. * @author Matthias Mullie <matthias@mullie.eu>
  12. */
  13. class FrontendSearchAjaxAutosuggest extends FrontendBaseAJAXAction
  14. {
  15. /**
  16. * Name of the cachefile
  17. *
  18. * @var string
  19. */
  20. private $cacheFile;
  21. /**
  22. * The items
  23. *
  24. * @var array
  25. */
  26. private $items;
  27. /**
  28. * Limit of data to fetch
  29. *
  30. * @var int
  31. */
  32. private $limit;
  33. /**
  34. * Offset of data to fetch
  35. *
  36. * @var int
  37. */
  38. private $offset;
  39. /**
  40. * The pagination array
  41. * It will hold all needed parameters, some of them need initialization.
  42. *
  43. * @var array
  44. */
  45. protected $pagination = array('limit' => 20, 'offset' => 0, 'requested_page' => 1, 'num_items' => null, 'num_pages' => null);
  46. /**
  47. * The requested page
  48. *
  49. * @var int
  50. */
  51. private $requestedPage;
  52. /**
  53. * The search term
  54. *
  55. * @var string
  56. */
  57. private $term = '';
  58. /**
  59. * Display
  60. */
  61. private function display()
  62. {
  63. // set variables
  64. $this->requestedPage = 1;
  65. $this->limit = (int) FrontendModel::getModuleSetting('search', 'autosuggest_num_items', 10);
  66. $this->offset = ($this->requestedPage * $this->limit) - $this->limit;
  67. $this->cacheFile = FRONTEND_CACHE_PATH . '/' . $this->getModule() . '/' . FRONTEND_LANGUAGE . '_' . md5($this->term) . '_' . $this->offset . '_' . $this->limit . '.php';
  68. // load the cached data
  69. if(!$this->getCachedData())
  70. {
  71. // ... or load the real data
  72. $this->getRealData();
  73. }
  74. // parse
  75. $this->parse();
  76. }
  77. /**
  78. * Execute the action
  79. */
  80. public function execute()
  81. {
  82. parent::execute();
  83. $this->validateForm();
  84. $this->display();
  85. }
  86. /**
  87. * Load the cached data
  88. *
  89. * @return bool
  90. */
  91. private function getCachedData()
  92. {
  93. // no search term = no search
  94. if(!$this->term) return false;
  95. // debug mode = no cache
  96. if(SPOON_DEBUG) return false;
  97. // check if cachefile exists
  98. if(!SpoonFile::exists($this->cacheFile)) return false;
  99. // get cachefile modification time
  100. $cacheInfo = @filemtime($this->cacheFile);
  101. // check if cache file is recent enough (1 hour)
  102. if(!$cacheInfo || $cacheInfo < strtotime('-1 hour')) return false;
  103. // include cache file
  104. require_once $this->cacheFile;
  105. // set info
  106. $this->pagination = $pagination;
  107. $this->items = $items;
  108. return true;
  109. }
  110. /**
  111. * Load the data
  112. */
  113. private function getRealData()
  114. {
  115. // no search term = no search
  116. if(!$this->term) return;
  117. // set url
  118. $this->pagination['url'] = FrontendNavigation::getURLForBlock('search') . '?form=search&q=' . $this->term;
  119. $this->pagination['limit'] = FrontendModel::getModuleSetting('search', 'overview_num_items', 20);
  120. // populate calculated fields in pagination
  121. $this->pagination['requested_page'] = $this->requestedPage;
  122. $this->pagination['offset'] = ($this->pagination['requested_page'] * $this->pagination['limit']) - $this->pagination['limit'];
  123. // get items
  124. $this->items = FrontendSearchModel::search($this->term, $this->pagination['limit'], $this->pagination['offset']);
  125. // populate count fields in pagination
  126. // this is done after actual search because some items might be activated/deactivated (getTotal only does rough checking)
  127. $this->pagination['num_items'] = FrontendSearchModel::getTotal($this->term);
  128. $this->pagination['num_pages'] = (int) ceil($this->pagination['num_items'] / $this->pagination['limit']);
  129. // num pages is always equal to at least 1
  130. if($this->pagination['num_pages'] == 0) $this->pagination['num_pages'] = 1;
  131. // redirect if the request page doesn't exist
  132. if($this->requestedPage > $this->pagination['num_pages'] || $this->requestedPage < 1) $this->redirect(FrontendNavigation::getURL(404));
  133. // debug mode = no cache
  134. if(!SPOON_DEBUG)
  135. {
  136. // set cache content
  137. SpoonFile::setContent($this->cacheFile, "<?php\n" . '$pagination = ' . var_export($this->pagination, true) . ";\n" . '$items = ' . var_export($this->items, true) . ";\n?>");
  138. }
  139. }
  140. public function parse()
  141. {
  142. // more matches to be found than?
  143. if($this->pagination['num_items'] > count($this->items))
  144. {
  145. // remove last result (to add this reference)
  146. array_pop($this->items);
  147. // add reference to full search results page
  148. $this->items[] = array(
  149. 'title' => FL::lbl('More'),
  150. 'text' => FL::msg('MoreResults'),
  151. 'full_url' => FrontendNavigation::getURLForBlock('search') . '?form=search&q=' . $this->term
  152. );
  153. }
  154. // format data
  155. foreach($this->items as &$item)
  156. {
  157. // full url is set?
  158. if(!isset($item['full_url'])) continue;
  159. // build utm array
  160. $utm['utm_source'] = SpoonFilter::urlise(FrontendModel::getModuleSetting('core', 'site_title_' . FRONTEND_LANGUAGE, SITE_DEFAULT_TITLE));
  161. $utm['utm_medium'] = 'fork-search';
  162. $utm['utm_term'] = $this->term;
  163. // get parameters in url already
  164. if(strpos($item['full_url'], '?') !== false) $glue = '&';
  165. else $glue = '?';
  166. // add utm to url
  167. $item['full_url'] .= $glue . http_build_query($utm, '', '&');
  168. // format description
  169. $item['text'] = !empty($item['text']) ? (mb_strlen($item['text']) > $this->length ? mb_substr(strip_tags($item['text']), 0, $this->length, SPOON_CHARSET) . 'รข&#x20AC;?' : $item['text']) : '';
  170. }
  171. // output
  172. $this->output(self::OK, $this->items);
  173. }
  174. /**
  175. * Validate the form
  176. */
  177. private function validateForm()
  178. {
  179. // set values
  180. $this->term = SpoonFilter::getPostValue('term', null, '');
  181. $this->length = (int) SpoonFilter::getPostValue('length', null, 50);
  182. // validate
  183. if($this->term == '') $this->output(self::BAD_REQUEST, null, 'term-parameter is missing.');
  184. }
  185. }