164ab5140SAndreas Gohr<?php 264ab5140SAndreas Gohr 364ab5140SAndreas Gohrnamespace dokuwiki\Action; 464ab5140SAndreas Gohr 564ab5140SAndreas Gohruse dokuwiki\Action\Exception\ActionAbort; 60cba610bSSatoshi Saharause dokuwiki\Search\FulltextSearch; 70cba610bSSatoshi Saharause dokuwiki\Search\MetadataSearch; 80b1bbbbbSAndreas Gohruse dokuwiki\Search\Query\QueryParser; 964ab5140SAndreas Gohr 10ab583a1bSAndreas Gohr/** 11ab583a1bSAndreas Gohr * Class Search 12ab583a1bSAndreas Gohr * 13ab583a1bSAndreas Gohr * Search for pages and content 14ab583a1bSAndreas Gohr * 15ab583a1bSAndreas Gohr * @package dokuwiki\Action 16ab583a1bSAndreas Gohr */ 178c7c53b0SAndreas Gohrclass Search extends AbstractAction 188c7c53b0SAndreas Gohr{ 196723156fSAndreas Gohr protected $pageLookupResults = []; 206723156fSAndreas Gohr protected $fullTextResults = []; 216723156fSAndreas Gohr protected $highlight = []; 226639a152SMichael Große 2364ab5140SAndreas Gohr /** @inheritdoc */ 24d868eb89SAndreas Gohr public function minimumPermission() 25d868eb89SAndreas Gohr { 2664ab5140SAndreas Gohr return AUTH_NONE; 2764ab5140SAndreas Gohr } 2864ab5140SAndreas Gohr 2964ab5140SAndreas Gohr /** 3064ab5140SAndreas Gohr * we only search if a search word was given 3164ab5140SAndreas Gohr * 3264ab5140SAndreas Gohr * @inheritdoc 3364ab5140SAndreas Gohr */ 34d868eb89SAndreas Gohr public function checkPreconditions() 35d868eb89SAndreas Gohr { 36b2c9cd19SAndreas Gohr parent::checkPreconditions(); 3764ab5140SAndreas Gohr } 3864ab5140SAndreas Gohr 39d09b5b64SMichael Große public function preProcess() 40d09b5b64SMichael Große { 41d22b78c8SMichael Große global $QUERY, $ID, $conf, $INPUT; 42d22b78c8SMichael Große $s = cleanID($QUERY); 43d22b78c8SMichael Große 443286c65dSMichael Große if ($ID !== $conf['start'] && !$INPUT->has('q')) { 45d22b78c8SMichael Große parse_str($INPUT->server->str('QUERY_STRING'), $urlParts); 46d22b78c8SMichael Große $urlParts['q'] = $urlParts['id']; 47918638dcSSchplurtz le Déboulonné unset($urlParts['id']); 48cc21cb50SAndreas Gohr $url = wl($ID, $urlParts, true, '&'); 49d22b78c8SMichael Große send_redirect($url); 50d22b78c8SMichael Große } 51d22b78c8SMichael Große 52d22b78c8SMichael Große if ($s === '') throw new ActionAbort(); 53d09b5b64SMichael Große $this->adjustGlobalQuery(); 54d09b5b64SMichael Große } 55d09b5b64SMichael Große 5664ab5140SAndreas Gohr /** @inheritdoc */ 57d09b5b64SMichael Große public function tplContent() 58d09b5b64SMichael Große { 596639a152SMichael Große $this->execute(); 606639a152SMichael Große 616639a152SMichael Große $search = new \dokuwiki\Ui\Search($this->pageLookupResults, $this->fullTextResults, $this->highlight); 6221fcef82SMichael Große $search->show(); 6364ab5140SAndreas Gohr } 64d09b5b64SMichael Große 656639a152SMichael Große 666639a152SMichael Große /** 676639a152SMichael Große * run the search 686639a152SMichael Große */ 696639a152SMichael Große protected function execute() 706639a152SMichael Große { 716639a152SMichael Große global $INPUT, $QUERY; 72422bbbc6SMichael Große $after = $INPUT->str('min'); 73422bbbc6SMichael Große $before = $INPUT->str('max'); 74*8788dbbdSsplitbrain $this->pageLookupResults = (new MetadataSearch())->pageLookup( 75*8788dbbdSsplitbrain $QUERY, 76*8788dbbdSsplitbrain true, 77*8788dbbdSsplitbrain useHeading('navigation'), 78*8788dbbdSsplitbrain $after, 79*8788dbbdSsplitbrain $before 809329b002SSatoshi Sahara ); 819313ce6dSAndreas Gohr $highlight = []; 82*8788dbbdSsplitbrain $this->fullTextResults = (new FulltextSearch())->pageSearch( 83*8788dbbdSsplitbrain $QUERY, 84*8788dbbdSsplitbrain $highlight, 85*8788dbbdSsplitbrain $INPUT->str('srt'), 86*8788dbbdSsplitbrain $after, 87*8788dbbdSsplitbrain $before 889329b002SSatoshi Sahara ); 896639a152SMichael Große $this->highlight = $highlight; 906639a152SMichael Große } 916639a152SMichael Große 92d09b5b64SMichael Große /** 9313ce475dSAndreas Gohr * Adjust the global query accordingly to the config search_nslimit and search_fragment 94d09b5b64SMichael Große * 95d09b5b64SMichael Große * This will only do something if the search didn't originate from the form on the searchpage itself 96d09b5b64SMichael Große */ 97d09b5b64SMichael Große protected function adjustGlobalQuery() 98d09b5b64SMichael Große { 99340f849aSMichael Große global $conf, $INPUT, $QUERY, $ID; 100d09b5b64SMichael Große 1011265b193SMichael Große if ($INPUT->bool('sf')) { 102d09b5b64SMichael Große return; 103d09b5b64SMichael Große } 104d09b5b64SMichael Große 105*8788dbbdSsplitbrain $parsedQuery = (new QueryParser())->convert($QUERY); 106d09b5b64SMichael Große 107d09b5b64SMichael Große if (empty($parsedQuery['ns']) && empty($parsedQuery['notns'])) { 10813ce475dSAndreas Gohr if ($conf['search_nslimit'] > 0) { 109340f849aSMichael Große if (getNS($ID) !== false) { 110340f849aSMichael Große $nsParts = explode(':', getNS($ID)); 11113ce475dSAndreas Gohr $ns = implode(':', array_slice($nsParts, 0, $conf['search_nslimit'])); 112d09b5b64SMichael Große $QUERY .= " @$ns"; 113d09b5b64SMichael Große } 114d09b5b64SMichael Große } 115d09b5b64SMichael Große } 116d09b5b64SMichael Große 11713ce475dSAndreas Gohr if ($conf['search_fragment'] !== 'exact') { 118d09b5b64SMichael Große if (empty(array_diff($parsedQuery['words'], $parsedQuery['and']))) { 119093fe67eSAndreas Gohr if (!str_contains($QUERY, '*')) { 120d09b5b64SMichael Große $queryParts = explode(' ', $QUERY); 121d09b5b64SMichael Große $queryParts = array_map(function ($part) { 122093fe67eSAndreas Gohr if (str_starts_with($part, '@')) { 123d09b5b64SMichael Große return $part; 124d09b5b64SMichael Große } 125093fe67eSAndreas Gohr if (str_starts_with($part, 'ns:')) { 126d09b5b64SMichael Große return $part; 127d09b5b64SMichael Große } 128093fe67eSAndreas Gohr if (str_starts_with($part, '^')) { 129d09b5b64SMichael Große return $part; 130d09b5b64SMichael Große } 131093fe67eSAndreas Gohr if (str_starts_with($part, '-ns:')) { 132d09b5b64SMichael Große return $part; 133d09b5b64SMichael Große } 134d09b5b64SMichael Große 135d09b5b64SMichael Große global $conf; 136d09b5b64SMichael Große 13713ce475dSAndreas Gohr if ($conf['search_fragment'] === 'starts_with') { 138d09b5b64SMichael Große return $part . '*'; 139d09b5b64SMichael Große } 14013ce475dSAndreas Gohr if ($conf['search_fragment'] === 'ends_with') { 141d09b5b64SMichael Große return '*' . $part; 142d09b5b64SMichael Große } 143d09b5b64SMichael Große 144d09b5b64SMichael Große return '*' . $part . '*'; 145d09b5b64SMichael Große }, $queryParts); 146d09b5b64SMichael Große $QUERY = implode(' ', $queryParts); 147d09b5b64SMichael Große } 148d09b5b64SMichael Große } 149d09b5b64SMichael Große } 150d09b5b64SMichael Große } 15164ab5140SAndreas Gohr} 152