1<?php 2 3namespace dokuwiki\Action; 4 5use dokuwiki\Action\Exception\ActionAbort; 6 7/** 8 * Class Search 9 * 10 * Search for pages and content 11 * 12 * @package dokuwiki\Action 13 */ 14class Search extends AbstractAction 15{ 16 17 protected $pageLookupResults = []; 18 protected $fullTextResults = []; 19 protected $highlight = []; 20 21 /** @inheritdoc */ 22 public function minimumPermission() 23 { 24 return AUTH_NONE; 25 } 26 27 /** 28 * we only search if a search word was given 29 * 30 * @inheritdoc 31 */ 32 public function checkPreconditions() 33 { 34 parent::checkPreconditions(); 35 } 36 37 public function preProcess() 38 { 39 global $QUERY, $ID, $conf, $INPUT; 40 $s = cleanID($QUERY); 41 42 if ($ID !== $conf['start'] && !$INPUT->has('q')) { 43 parse_str($INPUT->server->str('QUERY_STRING'), $urlParts); 44 $urlParts['q'] = $urlParts['id']; 45 unset($urlParts['id']); 46 $url = wl($ID, $urlParts, true, '&'); 47 send_redirect($url); 48 } 49 50 if ($s === '') throw new ActionAbort(); 51 $this->adjustGlobalQuery(); 52 } 53 54 /** @inheritdoc */ 55 public function tplContent() 56 { 57 $this->execute(); 58 59 $search = new \dokuwiki\Ui\Search($this->pageLookupResults, $this->fullTextResults, $this->highlight); 60 $search->show(); 61 } 62 63 64 /** 65 * run the search 66 */ 67 protected function execute() 68 { 69 global $INPUT, $QUERY; 70 $after = $INPUT->str('min'); 71 $before = $INPUT->str('max'); 72 $this->pageLookupResults = ft_pageLookup($QUERY, true, useHeading('navigation'), $after, $before); 73 $this->fullTextResults = ft_pageSearch($QUERY, $highlight, $INPUT->str('srt'), $after, $before); 74 $this->highlight = $highlight; 75 } 76 77 /** 78 * Adjust the global query accordingly to the config search_nslimit and search_fragment 79 * 80 * This will only do something if the search didn't originate from the form on the searchpage itself 81 */ 82 protected function adjustGlobalQuery() 83 { 84 global $conf, $INPUT, $QUERY, $ID; 85 86 if ($INPUT->bool('sf')) { 87 return; 88 } 89 90 $Indexer = idx_get_indexer(); 91 $parsedQuery = ft_queryParser($Indexer, $QUERY); 92 93 if (empty($parsedQuery['ns']) && empty($parsedQuery['notns'])) { 94 if ($conf['search_nslimit'] > 0) { 95 if (getNS($ID) !== false) { 96 $nsParts = explode(':', getNS($ID)); 97 $ns = implode(':', array_slice($nsParts, 0, $conf['search_nslimit'])); 98 $QUERY .= " @$ns"; 99 } 100 } 101 } 102 103 if ($conf['search_fragment'] !== 'exact') { 104 if (empty(array_diff($parsedQuery['words'], $parsedQuery['and']))) { 105 if (strpos($QUERY, '*') === false) { 106 $queryParts = explode(' ', $QUERY); 107 $queryParts = array_map(function ($part) { 108 if (strpos($part, '@') === 0) { 109 return $part; 110 } 111 if (strpos($part, 'ns:') === 0) { 112 return $part; 113 } 114 if (strpos($part, '^') === 0) { 115 return $part; 116 } 117 if (strpos($part, '-ns:') === 0) { 118 return $part; 119 } 120 121 global $conf; 122 123 if ($conf['search_fragment'] === 'starts_with') { 124 return $part . '*'; 125 } 126 if ($conf['search_fragment'] === 'ends_with') { 127 return '*' . $part; 128 } 129 130 return '*' . $part . '*'; 131 132 }, $queryParts); 133 $QUERY = implode(' ', $queryParts); 134 } 135 } 136 } 137 } 138} 139