1<?php 2 3namespace dokuwiki\Action; 4 5use dokuwiki\Action\Exception\ActionAbort; 6use dokuwiki\Search\FulltextSearch; 7use dokuwiki\Search\MetadataSearch; 8use dokuwiki\Search\QueryParser; 9 10/** 11 * Class Search 12 * 13 * Search for pages and content 14 * 15 * @package dokuwiki\Action 16 */ 17class Search extends AbstractAction { 18 19 protected $pageLookupResults = array(); 20 protected $fullTextResults = array(); 21 protected $highlight = array(); 22 23 /** @inheritdoc */ 24 public function minimumPermission() { 25 return AUTH_NONE; 26 } 27 28 /** 29 * we only search if a search word was given 30 * 31 * @inheritdoc 32 */ 33 public function checkPreconditions() { 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 $MetadataSearch = MetadataSearch::getInstance(); 73 $this->pageLookupResults = $MetadataSearch->pageLookup( 74 $QUERY, true, useHeading('navigation'), $after, $before 75 ); 76 $FulltextSearch = FulltextSearch::getInstance(); 77 $this->fullTextResults = $FulltextSearch->pageSearch( 78 $QUERY, $highlight, $INPUT->str('srt'), $after, $before 79 ); 80 $this->highlight = $highlight; 81 } 82 83 /** 84 * Adjust the global query accordingly to the config search_nslimit and search_fragment 85 * 86 * This will only do something if the search didn't originate from the form on the searchpage itself 87 */ 88 protected function adjustGlobalQuery() 89 { 90 global $conf, $INPUT, $QUERY, $ID; 91 92 if ($INPUT->bool('sf')) { 93 return; 94 } 95 96 $parsedQuery = (new QueryParser)->convert($QUERY); 97 98 if (empty($parsedQuery['ns']) && empty($parsedQuery['notns'])) { 99 if ($conf['search_nslimit'] > 0) { 100 if (getNS($ID) !== false) { 101 $nsParts = explode(':', getNS($ID)); 102 $ns = implode(':', array_slice($nsParts, 0, $conf['search_nslimit'])); 103 $QUERY .= " @$ns"; 104 } 105 } 106 } 107 108 if ($conf['search_fragment'] !== 'exact') { 109 if (empty(array_diff($parsedQuery['words'], $parsedQuery['and']))) { 110 if (strpos($QUERY, '*') === false) { 111 $queryParts = explode(' ', $QUERY); 112 $queryParts = array_map(function ($part) { 113 if (strpos($part, '@') === 0) { 114 return $part; 115 } 116 if (strpos($part, 'ns:') === 0) { 117 return $part; 118 } 119 if (strpos($part, '^') === 0) { 120 return $part; 121 } 122 if (strpos($part, '-ns:') === 0) { 123 return $part; 124 } 125 126 global $conf; 127 128 if ($conf['search_fragment'] === 'starts_with') { 129 return $part . '*'; 130 } 131 if ($conf['search_fragment'] === 'ends_with') { 132 return '*' . $part; 133 } 134 135 return '*' . $part . '*'; 136 137 }, $queryParts); 138 $QUERY = implode(' ', $queryParts); 139 } 140 } 141 } 142 } 143} 144