Gentics Portal.Node PHP API
 All Classes Namespaces Functions Variables Pages
SearchApi.php
1 <?php
2 /**
3  * Gentics Portal.Node PHP
4  * Author & Copyright (c) by Gentics Software GmbH
5  * sales@gentics.com
6  * http://www.gentics.com
7  * Licenses can be found in the LICENSE.txt file in the root-folder of this installation
8  * You must not use this software without a valid license agreement.
9  *
10  */
11 class SearchApi extends CComponent
12 {
13  /**
14  * Overrided search url
15  *
16  * @public string
17  **/
18  public $searchUrl;
19 
20  /**
21  * Overrided autosuggest url
22  *
23  * @public string
24  **/
26 
27  private $_repositoryApi;
28 
29  /**
30  * Internal getter for repository api.
31  * It used to allows overriding of RepositoryApi properties by SearchApi properties
32  *
33  * @public RepositoryApi
34  **/
35  public function getRepositoryApi()
36  {
37  if(!$this->_repositoryApi) {
38  if(!empty($this->searchUrl) || !empty($this->autosuggestUrl)) {
39  $repositoryApi = clone Yii::app()->repositoryApi;
40  if(!empty($this->searchUrl)){
41  $repositoryApi->search = $this->searchUrl;
42  }
43  if(!empty($this->autosuggestUrl)){
44  $repositoryApi->autosuggest = $this->autosuggestUrl;
45  }
46  $this->_repositoryApi = $repositoryApi;
47  } else {
48  $this->_repositoryApi = Yii::app()->repositoryApi;
49  }
50  }
51  return $this->_repositoryApi;
52  }
53 
54  /**
55  * Counstructor
56  *
57  * @return void
58  **/
59  public function __construct($searchUrl = null, $autosuggestUrl = null)
60  {
61  $this->searchUrl = $searchUrl;
62  $this->autosuggestUrl = $autosuggestUrl;
63  }
64 
65 
66  /**
67  * method for search
68  *
69  * @param string $phrase text to find
70  * @param bool $usePersonalisation defines if personalization
71  *
72  * @return array
73  */
74  public function search($phrase, $params = array(), $start = null, $count = null)
75  {
76  if (!$this->_checkPhrase($phrase)) {
77  return false;
78  }
79  $whereToSearch = isset($params['whereToSearch']) ? $params['whereToSearch'] : Yii::app()->getModule('search')->whereToSearch['default'];
80  $mimetype = isset($params['mimetype']) ? $params['mimetype'] : Yii::app()->getModule('search')->mimetype['default'];
81  $searchType = isset($params['searchType']) ? $params['searchType'] : Yii::app()->getModule('search')->searchType['default'];
82  $urlLimiter = isset($params['urlLimiter']) ? $params['urlLimiter'] : Yii::app()->getModule('search')->urlLimiter['default'];
83  $enableSearchOperators = isset($params['enableSearchOperators']) ? $params['enableSearchOperators'] : Yii::app()->getModule('search')->searchType['enableSearchOperators'];
84 
85 
86  $data = array(
87  'results' => array(),
88  'metaresolvable' => array()
89  );
90  $data = $this->_preformSearch($phrase, $whereToSearch, $mimetype, $searchType, $urlLimiter, $start, $count, $enableSearchOperators);
91  if($data['status'] != 'ok'){
92  return false;
93  }
94  unset($data['status']);
95  $meta = $data['10001']['attributes'];
96  unset($data['10001']);
97 
98  return array(
99  'meta' => $meta,
100  'results' => $data
101  );
102  }
103 
104 
105  /**
106  * Function checks cache if result for given parameters exists and if not - performs API request for it.
107  *
108  * @param string $phrase a phrase to search
109  * @param string $whereToSearch where to search
110  * @param string $mimetype mimetype of searched content
111  * @param string $searchType search type (AND / OR / NOT / EXACT)
112  * @param string $urlLimiter url of result must contain this
113  * @param boolean $enableSearchOperators precondition to understand OR, AND, NOT as operators
114  *
115  * @return array|bool
116  */
117  private function _preformSearch($phrase, $whereToSearch, $mimetype, $searchType, $urlLimiter, $start = null, $count = null, $enableSearchOperators = false)
118  {
119  // if there are more than 4 words, we search for phrase
120  if ($searchType == 'EXACT' || count( explode(' ', $phrase) ) > 4) {
121 
122  $phrase = '"'.$phrase.'"';
123 
124  } else {
125 
126  $phrase = preg_replace('/([\ ]+)/', ' ', $phrase);
127 
128  /* gettings quoted phrases */
129  $wordGroups = $this->_extractWordGroups($phrase);
130 
131  /* replacing spaces in quoted phrases to avoid splitting */
132  if (!empty($wordGroups)) {
133  $phrase = str_replace(array_keys($wordGroups), $wordGroups, $phrase);
134  }
135 
136  /*
137  * Feature OR,AND,NOT to understand words OR, AND, NOT as operators
138  */
139  if (!$enableSearchOperators) {
140 
141  $phrase = explode(' ', $phrase);
142  $phrase = implode(' '.$searchType.' ', $phrase);
143 
144  } else {
145 
146  $tmpPhrase = explode(' ', $phrase);
147  $phrase = array();
148  $keywordFlag = false;
149 
150  foreach ($tmpPhrase as $i => $word) {
151  if (in_array($word, array('AND', 'OR', 'NOT'))) {
152  $keywordFlag = true;
153  $phrase[] = $word;
154  continue;
155  }
156 
157  if ($keywordFlag || $i == 0) {
158  $keywordFlag = false;
159  $phrase[] = $word;
160  } else {
161  $phrase[] = $searchType.' '.$word;
162  }
163  }
164 
165  $phrase = implode(' ', $phrase);
166  }
167  /*
168  * End of feature
169  */
170  /* return spaces in their places */
171  if (!empty($wordGroups)) {
172  $phrase = str_replace($wordGroups, array_keys($wordGroups), $phrase);
173  }
174  }
175 
176  $staticString = Yii::app()->getModule('search')->staticString;
177  if (trim($staticString)!='') {
178  $phrase .= ' '.$staticString;
179  }
180 
181  $lang = substr(Yii::app()->language, 0, 2);
182  $params = array(
183  'type' => 'php',
184  'metaresolvable' => 'true',
185  'filter' => 'languagecode:'.$lang,
186  );
187 
188  if (!empty($this->getRepositoryApi()->additionalRequestParameters['search'])) {
189  $additional = $this->getRepositoryApi()->additionalRequestParameters['search'];
190  foreach ($additional as $item=>$val) {
191  $params[$item] = !empty($params[$item]) ? $params[$item].' AND '.$val : $params[$item];
192  }
193  }
194 
195  if ($whereToSearch != 'all') {
196  $params['filter'] .= ' AND '.$whereToSearch.':('.$phrase.')';
197  } else {
198  $whereToSearchAll = Yii::app()->getModule('search')->whereToSearch['options'];
199  if (isset($whereToSearchAll['all'])) {
200  unset($whereToSearchAll['all']);
201  }
202 
203  $aWhereToSearchAll = array();
204 
205  foreach ($whereToSearchAll as $key=>$val) {
206  $aWhereToSearchAll[] = $key.':('.$phrase.')';
207  }
208 
209  $params['filter'] .= ' AND ('.implode(' OR ', $aWhereToSearchAll).')';
210  }
211 
212  if ($mimetype!='all') {
213  $params['filter'] .= ' AND mimetype:'.$mimetype;
214  }
215 
216  if ($urlLimiter!='all') {
217  $params['filter'] .= ' AND url:'.$urlLimiter;
218  }
219 
220  if($start !== null){
221  $params['start'] = $start;
222  }
223 
224  if($count !== null){
225  $params['count'] = $count;
226  }
227 
228  $cacheId = md5(serialize($params));
229 
230  if (($data = Yii::app()->cache->get($cacheId)) === false) {
231  $data = $this->getRepositoryApi()->requestSearch($params);
232 
233  $data = unserialize($data);
234 
235  /* store all recieved data in cache */
236  Yii::app()->cache->set($cacheId, $data, Yii::app()->getModule('search')->cacheTime);
237  }
238  return $data;
239  }
240 
241  /**
242  * Checks given phrase for correct syntax
243  *
244  * @param string $phrase a phrase to search
245  *
246  * @return bool
247  */
248  private function _checkPhrase($phrase)
249  {
250  if (trim($phrase) == '') {
251  return false;
252  }
253  return true;
254  }
255 
256  private function _extractWordGroups($phrase, $quotes=array('"'))
257  {
258  if (empty($phrase)) {
259  return array();
260  }
261 
262  $wordGroups = array();
263 
264  foreach ($quotes as $quote) {
265  $reg = preg_quote($quote);
266  preg_match_all('/['.$quote.'](.*)['.$quote.']/sU', $phrase, $matches);
267 
268  if(!empty($matches[1])) {
269  foreach ($matches[1] as $match) {
270  $wordGroups[$match] = str_replace(' ', '_', $match);
271  }
272  }
273  }
274  return $wordGroups;
275  }
276 }
277 
278 ?>