Overview

Packages

  • CONTENIDO
  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
    • ScriptCookieDirective
  • mpAutoloaderClassMap
  • None
  • PHP
  • Plugin
    • ContentAllocation
    • CronjobOverview
    • FormAssistant
    • FrontendLogic
    • FrontendUsers
    • Linkchecker
    • ModRewrite
    • Newsletter
    • Repository
      • FrontendNavigation
      • KeywordDensity
    • SmartyWrapper
    • UrlShortener
    • UserForum
    • Workflow
  • PluginManager
  • Setup
    • Form
    • GUI
    • Helper
      • Environment
      • Filesystem
      • MySQL
      • PHP
    • UpgradeJob

Classes

  • idna_convert
  • SearchResultModule
  • TinyMCE_Compressor

Functions

  • buildCategoryArray
  • decDate
  • getJobFileName
  • getLastActialRunTime
  • getLastScheduledRunTime
  • logMessage
  • lTrimZeros
  • markLastRun
  • parseCronFile
  • parseElement
  • runJob
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
  1:  <?php
  2: 
  3: /**
  4:  *
  5:  * @package Module
  6:  * @subpackage search_result
  7:  * @author marcus.gnass@4fb.de
  8:  * @copyright four for business AG
  9:  * @link http://www.4fb.de
 10:  */
 11: 
 12: /**
 13:  *
 14:  * @author marcus.gnass
 15:  */
 16: class SearchResultModule {
 17: 
 18:     /**
 19:      *
 20:      * @var unknown_type
 21:      */
 22:     protected $_countValues;
 23: 
 24:     /**
 25:      *
 26:      * @var int
 27:      */
 28:     protected $_searchResultCount = 0;
 29: 
 30:     /**
 31:      *
 32:      * @var array
 33:      */
 34:     protected $_label;
 35: 
 36:     /**
 37:      *
 38:      * @var int
 39:      */
 40:     protected $_itemsPerPage;
 41: 
 42:     /**
 43:      *
 44:      * @var int
 45:      */
 46:     protected $_maxTeaserTextLen;
 47: 
 48:     /**
 49:      *
 50:      * @var string
 51:      */
 52:     protected $_searchTerm;
 53: 
 54:     /**
 55:      *
 56:      * @var string
 57:      */
 58:     protected $_dispSearchTerm = NULL;
 59: 
 60:     /**
 61:      *
 62:      * @var string
 63:      */
 64:     protected $_prepSearchTerm = NULL;
 65: 
 66:     /**
 67:      *
 68:      * @var array
 69:      */
 70:     protected $_searchResultData = NULL;
 71: 
 72:     /**
 73:      *
 74:      * @var cSearchResult
 75:      */
 76:     protected $_searchResults = NULL;
 77: 
 78:     /**
 79:      *
 80:      * @var int
 81:      */
 82:     protected $_numberOfPages = NULL;
 83: 
 84:     /**
 85:      * @var int
 86:      */
 87:     protected $_page = 0;
 88: 
 89:     /**
 90:      * @var string
 91:      */
 92:     protected $_msgResult;
 93: 
 94:     /**
 95:      * @var string
 96:      */
 97:     protected $_msgRange;
 98: 
 99:     /**
100:      *
101:      * @param array $options
102:      */
103:     public function __construct(array $options = NULL) {
104: 
105:         // generic way to set options
106:         if (NULL !== $options) {
107:             foreach ($options as $name => $value) {
108:                 $name = '_' . $name;
109:                 $this->$name = $value;
110:             }
111:         }
112: 
113:         // get global variables from registry (the nice way)
114:         $this->_cfg = cRegistry::getConfig();
115:         $this->_db = cRegistry::getDb();
116:         $this->_client = cRegistry::getClientId();
117:         $this->_lang = cRegistry::getLanguageId();
118:         $this->_idcat = cRegistry::getCategoryId();
119:         $this->_idart = cRegistry::getArticleId();
120:         $this->_sess = cRegistry::getSession();
121:         $this->_combine = '';
122:         $this->_msgResult = '';
123:         $this->_msgRange = '';
124: 
125:         // get global variables (the ugly way)
126:         global $sArtSpecs;
127:         $this->_artSpecs = $sArtSpecs;
128: 
129:         // perform first preparation of searchterm
130:         $searchTerm = $this->_searchTerm;
131:         if (true === cRegistry::getConfigValue('simulate_magic_quotes')) {
132:             $searchTerm = stripslashes($searchTerm);
133:         }
134: 
135:         // assume search term is always url encoded
136:         // default enctype for a form is application/x-www-form-urlencoded
137:         $searchTerm = urldecode($searchTerm);
138: 
139:         $searchTerm = str_replace(' + ', ' AND ', $searchTerm);
140:         $searchTerm = str_replace(' - ', ' NOT ', $searchTerm);
141: 
142:         // escape all entities for search because content types save its values
143:         // using escaping of special chars
144:         $searchTerm = conHtmlentities($searchTerm);
145: 
146:         // that's the search term suitable for display
147:         $this->_dispSearchTerm = $searchTerm;
148: 
149:         // now parse search term and set search options
150:         if (cString::getStringLength(trim($searchTerm)) > 0) {
151:             $searchTerm = conHtmlEntityDecode($searchTerm);
152:             if (false === cString::findFirstOccurrenceCI($searchTerm, ' or ')) {
153:                 $this->_combine = 'and';
154:             } else {
155:                 $this->_combine = 'or';
156:             }
157: 
158:             // force converting string to UTF-8
159:             $searchTerm = htmlentities($searchTerm, ENT_COMPAT, 'UTF-8');
160:             // remove superfluous white space and convert search term to lowercase
161:             $searchTerm = (trim(cString::toLowerCase($searchTerm)));
162:             $searchTerm = html_entity_decode($searchTerm, ENT_COMPAT, 'UTF-8');
163: 
164:             $searchTerm = str_replace(' and ', ' ', $searchTerm);
165:             $searchTerm = str_replace(' or ', ' ', $searchTerm);
166:         }
167: 
168:         // that's the search term suitable for the search itself
169:         $this->_prepSearchTerm = $searchTerm;
170: 
171:         // perform search
172:         $this->_performSearch();
173:     }
174: 
175:     /**
176:      */
177:     public function render() {
178:         $tpl = cSmartyFrontend::getInstance(true);
179: 
180:         $tpl->assign('label', $this->_label);
181:         $tpl->assign('searchTerm', $this->_dispSearchTerm);
182:         $tpl->assign('currentPage', $this->_page);
183: 
184:         $tpl->assign('results', $this->_getResults());
185:         $tpl->assign('msgResult', $this->_msgResult);
186:         $tpl->assign('msgRange', $this->_msgRange);
187:         $tpl->assign('prev', $this->_getPreviousLink());
188:         $tpl->assign('next', $this->_getNextLink());
189:         $tpl->assign('pages', $this->_getPageLinks());
190:         $tpl->assign('method', 'post');
191: 
192:         // determine action & method for search form
193:         // depends upon if plugin mod_rewrite is enabled
194:         if (class_exists('ModRewrite') && ModRewrite::isEnabled()) {
195:             $tpl->assign('action', cUri::getInstance()->build(array(
196:                 'idart' => cRegistry::getArticleId(),
197:                 'lang' => cRegistry::getLanguageId()
198:             )));
199:         } else {
200:             $tpl->assign('action', 'front_content.php');
201:             $tpl->assign('idart', cRegistry::getArticleId());
202:             $tpl->assign('idlang', cRegistry::getLanguageId());
203:         }
204: 
205:         $tpl->display($this->_templateName);
206:     }
207: 
208:     /**
209:      */
210:     protected function _performSearch() {
211: 
212:         // build search object
213:         // only certain content types will be searched
214:         $search = new cSearch(array(
215:             // use db function regexp
216:             'db' => 'regexp',
217:             // combine searchterms with and
218:             'combine' => $this->_combine,
219:             // => searchrange specified in 'cat_tree', 'categories' and
220:             // 'articles' is excluded, otherwise included (exclusive)
221:             'exclude' => false,
222:             // searchrange
223:             'cat_tree' => $this->_getSearchableIdcats(),
224:             // array of article specifications
225:             // => search only articles with these artspecs
226:             'artspecs' => $this->_getArticleSpecs(),
227:             // => do not search articles or articles in categories which are
228:             // offline or protected
229:             'protected' => true
230:         ));
231:         $search->setCmsOptions(array(
232:             'head',
233:             'html',
234:             'htmlhead',
235:             'htmltext',
236:             'text'
237:         ));
238:         if (cString::getStringLength($this->_prepSearchTerm) > 1) {
239:             $searchResultArray = $search->searchIndex($this->_prepSearchTerm, '');
240:             
241:             if (false !== $searchResultArray) {
242: 
243:                 $this->_searchResultCount = count($searchResultArray);
244: 
245:                 // get search results
246:                 $this->_searchResults = new cSearchResult($searchResultArray, $this->_itemsPerPage);
247: 
248:                 // get number of pages
249:                 $this->_numberOfPages = $this->_searchResults->getNumberOfPages();
250: 
251:                 // html-tags to emphasize the located searchterms
252:                 $this->_searchResults->setReplacement('<strong>', '</strong>');
253:             }
254: 
255:             // create message to display
256:             if (0 === $this->_searchResultCount) {
257:                 $this->_msgResult = sprintf($this->_label['msgNoResultsFound'], $this->_dispSearchTerm);
258:             } else {
259:                 $this->_msgResult = sprintf($this->_label['msgResultsFound'], $this->_dispSearchTerm, $this->_searchResultCount);
260:             }
261:         }
262:     }
263: 
264:     /**
265:      *
266:      * @return string
267:      */
268:     protected function _getMsgResult() {
269:         return $this->_msgResult;
270:     }
271: 
272:     /**
273:      *
274:      * @param int $count
275:      * @param int $countIdarts
276:      */
277:     protected function _setMsgResult($count, $countIdarts) {
278:         $this->_countValues = $count;
279: 
280:         // $this->_numberOfPages = 1;
281:         if (0 === $this->_searchResultCount) {
282:             $this->_msgResult = sprintf($this->_label['msgNoResultsFound'], $this->_dispSearchTerm);
283:         } else {
284:             $this->_msgResult = sprintf($this->_label['msgResultsFound'], $this->_dispSearchTerm, $this->_searchResultCount);
285:         }
286:     }
287: 
288:     /**
289:      * Returns IDCATs of setting searchable/idcats as array.
290:      * Default value is 1.
291:      *
292:      * @return array
293:      */
294:     protected function _getSearchableIdcats() {
295:         $searchableIdcats = getEffectiveSetting('searchable', 'idcats', 1);
296:         $searchableIdcats = explode(',', $searchableIdcats);
297: 
298:         return $searchableIdcats;
299:     }
300: 
301:     /**
302:      * Get all article specs of current client in current language.
303:      *
304:      * TODO use cApiArticleSpecificationCollection instead
305:      *
306:      * @return array
307:      */
308:     protected function _getArticleSpecs() {
309:         $sql = "-- getArticleSpecs()
310:             SELECT
311:                 idartspec
312:                 , artspec
313:             FROM
314:                 " . $this->_cfg['tab']['art_spec'] . "
315:             WHERE
316:                 client = $this->_client
317:                 AND lang = $this->_lang
318:                 AND online = 1
319:             ;";
320: 
321:         $this->_db->query($sql);
322: 
323:         $aArtSpecs = array();
324:         while ($this->_db->next_record()) {
325:             $aArtSpecs[] = $this->_db->f('idartspec');
326:         }
327:         $aArtSpecs[] = 0;
328: 
329:         return $aArtSpecs;
330:     }
331: 
332:     /**
333:      *
334:      * @return array
335:      */
336:     protected function _getResults() {
337:         if (NULL === $this->_searchResults) {
338:             return array();
339:         }
340: 
341:         // get current result page
342:         $searchResultPage = $this->_searchResults->getSearchResultPage($this->_page);
343: 
344:         // skip if current page has no results
345:         if (0 == count($searchResultPage) > 0) {
346:             return array();
347:         }
348: 
349:         // build single search result on result page
350:         $entries = array();
351:         $i = 0;
352:         foreach (array_keys($searchResultPage) as $idart) {
353: 
354:             $i++;
355: 
356:             // get absolute number of current search result
357:             $number = $this->_itemsPerPage * ($this->_page - 1) + $i;
358: 
359:             // get headlines
360:             $headlines = $this->_searchResults->getSearchContent($idart, 'HTMLHEAD', 1);
361:             $headline = cString::trimAfterWord($headlines[0], $this->_maxTeaserTextLen);
362: 
363:             // get subheadlines
364:             $subheadlines = $this->_searchResults->getSearchContent($idart, 'HTMLHEAD', 2);
365:             $subheadline = cString::trimAfterWord($subheadlines[0], $this->_maxTeaserTextLen);
366: 
367:             // get paragraphs
368:             $paragraphs = $this->_searchResults->getSearchContent($idart, 'HTML', 1);
369:             $paragraph = cString::trimAfterWord($paragraphs[0], $this->_maxTeaserTextLen);
370: 
371:             // get similarity
372:             $similarity = $this->_searchResults->getSimilarity($idart);
373:             $similarity = sprintf("%.0f", $similarity);
374: 
375:             // build link to that result page
376:             $href = cUri::getInstance()->build(array(
377:                 'lang' => cRegistry::getLanguageId(),
378:                 'idcat' => $this->_searchResults->getArtCat($idart),
379:                 'idart' => $idart
380:             ));
381: 
382:             // assemble entry
383:             $entries[] = array(
384:                 'number' => $number,
385:                 'headline' => $headline,
386:                 'subheadline' => $subheadline,
387:                 'paragraph' => $paragraph,
388:                 'similarity' => $similarity,
389:                 'href' => $href
390:             );
391:         }
392: 
393:         $lower = ($this->_page - 1) * $this->_itemsPerPage + 1;
394:         $upper = $lower + count($entries) - 1;
395:         $total = $this->_searchResults->getNumberOfResults();
396: 
397:         $this->_msgRange = sprintf($this->_label['msgRange'], $lower, $upper, $total);
398: 
399:         return $entries;
400:     }
401: 
402:     /**
403:      *
404:      * @return string
405:      */
406:     protected function _getPreviousLink() {
407: 
408:         // skip if there are no previous pages
409:         if (1 >= $this->_page) {
410:             return '';
411:         }
412: 
413:         // build link to previous result page
414:         $url = $this->_getPageLink($this->_dispSearchTerm, $this->_page - 1);
415: 
416:         return $url;
417:     }
418: 
419:     /**
420:      *
421:      * @return string
422:      */
423:     protected function _getNextLink() {
424: 
425:         // skip if there are no next pages
426:         if ($this->_page >= $this->_numberOfPages) {
427:             return '';
428:         }
429: 
430:         // build link to next result page
431:         $url = $this->_getPageLink($this->_dispSearchTerm, $this->_page + 1);
432: 
433:         return $url;
434:     }
435: 
436:     /**
437:      * Build links to other result pages.
438:      *
439:      * @return string
440:      */
441:     protected function _getPageLinks() {
442:         $pageLinks = array();
443:         for ($i = 1; $i <= $this->_numberOfPages; $i++) {
444:             $pageLinks[$i] = $this->_getPageLink($this->_dispSearchTerm, $i);
445:         }
446: 
447:         return $pageLinks;
448:     }
449: 
450:     /**
451:      * This method builds URLs for each result link and the pagination links.
452:      *
453:      *
454:      * @param string $searchTerm
455:      * @param int $page
456:      * @return mixed
457:      */
458:     protected function _getPageLink($searchTerm = NULL, $page = NULL) {
459: 
460:         // define standard params
461:         $params = array(
462:             'lang' => $this->_lang,
463:             'idcat' => $this->_idcat,
464:             'idart' => $this->_idart
465:         );
466:         // add optional params if given
467:         if (NULL !== $searchTerm) {
468:             $params['search_term'] = conHtmlEntityDecode($searchTerm);
469:         }
470:         if (NULL !== $page) {
471:             $params['page'] = $page . $this->_artSpecs;
472:         }
473:         // store unaltered params for later use
474:         $defaultParams = $params;
475: 
476:         // define special params when 'front_content' or 'MR' url builders are
477:         // *NOT* used in this case the standard params are wrapped as 'search'
478:         // and lang, idcat & level are aded cause they are needed to build the
479:         // category path
480:         $url_builder = array(
481:             'front_content',
482:             'MR'
483:         );
484:         if (false === in_array($this->_cfg['url_builder']['name'], $url_builder)) {
485:             $params = array(
486:                 'search' => $params,
487:                 'lang' => $this->_lang,
488:                 'idcat' => $this->_idcat,
489:                 'level' => 1
490:             );
491:         }
492: 
493:         try {
494:             $url = cUri::getInstance()->build($params);
495:         } catch (cInvalidArgumentException $e) {
496:             $url = $this->_sess->url(implode('?', array(
497:                 'front_content.php',
498:                 implode('&', $defaultParams)
499:             )));
500:         }
501: 
502:         return $url;
503:     }
504: 
505: }
506: 
507: ?>
CMS CONTENIDO 4.10.0 API documentation generated by ApiGen 2.8.0