$this->resultsPerPage) { $totalPages = (int)ceil($totalResults / $this->resultsPerPage); } if ($currentPage < 1) { $currentPage = 1; } elseif ($currentPage > $totalPages) { $currentPage = $totalPages; } // Set pages obtained so far, start with 1 since we have currentPage $pagesCount = 1; // Maintain a copy of pagesCount. // Used to detect whether any new pages were added in the iteration $newPagesCount = 1; // Set beginning and end as currentPage $start = $currentPage; $end = $currentPage; // Continue iteration till enough pages are obtained while ($pagesCount < $this->maxPages) { if ($end + 1 <= $totalPages) { // Ok to take one more page towards end $end++; $newPagesCount++; } if ($start - 1 > 0) { //Ok to take one more page towards start $start--; $newPagesCount++; } // Break loop if no additional pages were // obtained in this iteration // We have obtained maximum number of possible pages if ($newPagesCount == $pagesCount) { break; } else { $pagesCount = $newPagesCount; } } $result = [ 'currentPage' => $currentPage, 'totalResults' => $totalResults, 'totalPages' => $totalPages, 'start' => $start, 'end' => $end, 'url' => $this->staticSiteBuilder->staticDomain . 'search/?s=' . $searchPhrase . '&p=' ]; return $result; } private function isPageExcluded(string $haystack, array $needles): bool { return array_reduce($needles, fn($a, $n) => $a || str_contains($haystack, $n), false); } private function search(string $searchPhrase, int $currentPage) : Response { $searchPhrase = preg_replace('/[^a-zA-Z0-9 ]/', '', $searchPhrase); $searchResults = []; $baseDir = $this->staticSiteBuilder->projectDir . $this->staticSiteBuilder->staticVarPath; //effed up dir names... double slash when staticVarPath and metaTitlesPath (for example) are concatenated //remove trailing slash if ($baseDir[(strlen($baseDir) - 1)] == '/') { $baseDir = substr($baseDir, 0, (strlen($baseDir) - 1)); } if ($searchPhrase != '' && strlen($searchPhrase) >= 3 && strlen($searchPhrase) <= 32) { //search titles first $metaTitlesPath = $baseDir . $this->staticSiteBuilder->metaTitlesPath; $output = shell_exec('grep -ril \'' . $metaTitlesPath . '\' -e "\b'. $searchPhrase . '\b"'); $arr1 = explode(PHP_EOL, $output); //then search text body $metaContentsPath = $baseDir . $this->staticSiteBuilder->metaContentsPath; $output = shell_exec('grep -ril \'' . $metaContentsPath . '\' -e "\b'. $searchPhrase . '\b"'); $arr2 = explode(PHP_EOL, $output); //merge outputs $___results = array_merge($arr1, $arr2); $exclusions = StaticSiteBuilderConfig::$excludeDocumentsFromSearch; foreach ($___results as $filename) { $pathinfo = pathinfo($filename); //convert filename into url $filenameAsUrl = str_replace($this->staticSiteBuilder->slashReplace, '/', $pathinfo['filename']); if ( !isset($pathinfo['filename']) || $pathinfo['filename'] == '' || $this->isPageExcluded('/'.$pathinfo['filename'].'/', $exclusions) //add aslashes to filenameAsUrl so it matches paths ) { continue; } $url = $this->staticSiteBuilder->staticDomain . $filenameAsUrl; $title = ''; $image = ''; $excerpt = ''; $title = @file_get_contents($baseDir . $this->staticSiteBuilder->metaTitlesPath . $pathinfo['filename']); $image = @file_get_contents($baseDir . $this->staticSiteBuilder->metaImagesPath . $pathinfo['filename']); $excerpt = @file_get_contents($baseDir . $this->staticSiteBuilder->metaExcerptsPath . $pathinfo['filename']); $key = md5($pathinfo['basename']); if (!isset($searchResults[$key])) { $searchResults[$key] = [ 'url' => $url, 'title' => $title, 'image' => $image, 'excerpt' => $excerpt ]; } } } //do pagination werk $totalResults = count($searchResults); $pagination = $this->generatePagination($searchPhrase, $currentPage, $totalResults); if ($totalResults > $this->resultsPerPage) { $searchResults = array_slice( $searchResults, (($pagination['currentPage'] - 1) * $this->resultsPerPage), $this->resultsPerPage ); } return $this->render( '/static/search.html', [ 'searchPhrase' => $searchPhrase, 'searchResults' => $searchResults, 'pagination' => $pagination ] ); } #[Route('/search/', name: 'search_page')] public function index(Request $request): Response { $this->checkPost($request); $searchPhrase = (string)$request->query->get('s'); //wordpress search query $currentPage = (int)$request->query->get('p'); //our search pagination query if ($currentPage == 0) { $currentPage = 1; } return $this->search($searchPhrase, $currentPage); } }