config_file = $dataDir . '/data/_site/config_search.php'; $this->GetConfig(); if( $this->Admin() ){ return; } //admin popup or visitor $_REQUEST += array('q' => ''); if( \gp\tool::LoggedIn() && isset($_REQUEST['gpx_content']) && $_REQUEST['gpx_content'] == 'gpabox' ){ $this->AdminSearch(); }else{ $this->Search(); } } public function AdminSearch(){ global $langmessage; $this->gpabox = true; $this->show_stats = true; $this->search_hidden = true; echo '
'; echo ''; echo '
'; } public function Search(){ global $langmessage; $placeholder = $langmessage['Search'] . '…'; $custom_text = \gp\tool\Output::SelectText('Search'); if( $custom_text != '' ){ $placeholder = htmlspecialchars($custom_text) . '…'; } echo ''; } public static function Gadget(){ global $langmessage; $query = ''; if( isset($_GET['q']) ){ $query = $_GET['q']; } $placeholder = $langmessage['Search'] . '…'; $custom_text = \gp\tool\Output::SelectText('Search'); if( $custom_text != '' ){ $placeholder = htmlspecialchars($custom_text) . '…'; } echo '

'; echo \gp\tool\Output::GetAddonText('Search'); echo '

'; echo '
'; echo '
'; echo ''; echo ''; $html = ''; echo \gp\tool\Output::GetAddonText('Search', $html); echo '
'; echo '
'; } public function RunQuery(){ if( !empty($_REQUEST['q']) ){ $this->SearchPattern(); $this->SearchPages(); \gp\tool\Plugins::Action('Search', array($this)); } $this->ShowResults(); } public function ShowResults(){ global $langmessage; if( !count($this->results) ){ if( !empty($_REQUEST['q']) ){ echo '

'; echo \gp\tool\Output::GetAddonText($langmessage['search_no_results']); echo '

'; } return; } $this->RemoveDups(); usort( $this->results, array($this, 'sort') ); $total = count($this->results); $len = 20; $total_pages = ceil($total/$len); $current_page = self::ReqPage('pg', $total_pages ); $start = $current_page * $len; $end = min($start+$len, $total); $this->results = array_slice($this->results, $start, $len, true); echo '

'; echo sprintf($langmessage['SHOWING'], ($start + 1), $end, $total); echo '

'; echo '
'; foreach($this->results as $result){ echo '

'; echo isset($result['link']) ? $result['link'] : \gp\tool::Link( $result['slug'], $result['label'], 'highlight=' . rawurlencode($_REQUEST['q']) ); // $result['query'] if( $this->show_stats ){ echo ' ' . $result['matches'] . '' ; } echo '

'; echo $result['content']; if( $this->show_stats ){ echo ' '; echo $result['matches'] . ' match(es) out of ' . $result['words'] . ' words '; echo ' '; } echo '
'; } echo '
'; $attr = 'class="page-link"'; if( $this->gpabox ){ $attr .= ' data-cmd="gpabox"'; echo '
'; } $query = 'q=' . rawurlencode($_REQUEST['q']); self::PaginationLinks($current_page, $total_pages, 'special_gpsearch', $query, 'pg', $attr); } /** * Get the requested page number * * @param string $key * @param int $total_pages */ public static function ReqPage($key='pg', $total_pages=null){ if( isset($_REQUEST[$key]) ){ $pg = (int)$_REQUEST[$key]; if( !is_null($total_pages) && $total_pages > 0 ){ $pg = min($pg, $total_pages - 1); } return max(0,$pg); } return 0; } /** * Pagination links * */ public static function PaginationLinks($current_page, $total_pages, $slug, $query, $page_key='pg', $attr=''){ global $langmessage; if( $total_pages < 1 ){ return; } $prev_text = $langmessage['Previous']; $next_text = $langmessage['Next']; $current_text = $langmessage['Current Page']; echo ''; } public static function PaginationLink($slug, $label, $query, $page_key, $attr, $page){ if( $page > 0){ $query .= '&' . $page_key . '=' . $page; } echo '
  • ' . \gp\tool::Link($slug, $label, $query, $attr) . '
  • '; } /** * Remove duplicate matches * */ public function RemoveDups(){ $links = array(); foreach($this->results as $key => $result){ $link = isset($result['url']) ? $result['url'] : \gp\tool::GetUrl($result['slug'], $result['query']); // $link = mb_strtolower($link); if( in_array($link,$links) ){ unset($this->results[$key]); }else{ $links[] = $link; } } } public function Sort($resulta,$resultb){ return $resulta['strength'] < $resultb['strength']; } public function SearchPattern(){ // $query = mb_strtolower($_REQUEST['q']); $query = $_REQUEST['q']; // Search for the exact query when it is doubled quoted if (substr($query, 0, 1) == '"' && substr($query, -1) == '"') { $query = substr($query, 1, -1); $words = array($query); } else { preg_match_all("/\S+/", $query, $words); $words = array_unique($words[0]); } $sub_pattern1 = $sub_pattern2 = array(); foreach($words as $word){ $sub_pattern1[] = '\b' . preg_quote($word, '#') . '\b'; $sub_pattern2[] = preg_quote($word, '#'); } $this->search_pattern = '#(?:(' . implode('|', $sub_pattern1) . ')|(' . implode('|', $sub_pattern2) . '))#Siu'; } public function Admin(){ global $langmessage; if( !\gp\tool::LoggedIn() ){ return false; } $this->page->admin_links[] = array( 'special_gpsearch', $langmessage['configuration'], 'cmd=config', [ 'data-cmd' => 'gpabox', 'class' => 'admin-link-search-config' ] ); $cmd = \gp\tool::GetCommand(); switch($cmd){ case 'save_config': if( $this->SaveConfig() ){ break; } return true; case 'config': $this->Config($this->search_config); return true; } return false; } /** * Get the search configuration * */ public function GetConfig(){ $this->search_config = \gp\tool\Files::Get($this->config_file, 'search_config'); $this->search_config += array('search_hidden' => false); } public function SaveConfig(){ global $langmessage; if( isset($_POST['search_hidden']) ){ $search_config['search_hidden'] = true; }else{ $search_config['search_hidden'] = false; } if( \gp\tool\Files::SaveData($this->config_file, 'search_config', $search_config) ){ msg($langmessage['SAVED']); $this->search_config = $search_config; return true; } msg($langmessage['OOPS']); $this->Config($_POST); return false; } public function Config($array=array()){ global $langmessage, $addonFolderName, $gp_index; echo '

    ' . $langmessage['Search'] . ' » ' . $langmessage['configuration'] . '

    '; echo '
    '; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo '
    ' . $langmessage['options'] . '' . $langmessage['Value'] . '' . $langmessage['default'] . '
    ' . $langmessage['Search Hidden Files'] . ''; $checked = isset($array['search_hidden']) && $array['search_hidden'] ? ' checked="checked"' : ''; echo ''; echo '' . $langmessage['False'] . '
    '; echo '

    '; echo ''; echo ' '; echo ' '; echo '

    '; echo '
    '; } public function SearchPages(){ global $gp_index; ob_start(); foreach($gp_index as $title => $index){ if( \gp\tool::SpecialOrAdmin($title) === false ){ $this->SearchPage($title, $index); } } ob_get_clean(); } public function SearchPage($title, $index){ global $gp_menu, $gp_titles; //search hidden? if( !$this->search_hidden && !isset($gp_menu[$index]) ){ return; } //private pages if( !\gp\tool::LoggedIn() && isset($gp_titles[$index]['vis']) ){ return; } $full_path = \gp\tool\Files::PageFile($title); $file_sections = \gp\tool\Files::Get($full_path, 'file_sections'); if( !$file_sections ){ return; } $content = \gp\tool\Output\Sections::Render($file_sections, $title, \gp\tool\Files::$last_stats); $label = \gp\tool::GetLabel($title); $this->FindString($content, $label, $title); } public function FindString(&$content, $label, $slug, $link_query=''){ $this->search_count++; //search all of the content include html // $content = mb_strtolower($content); $content = $label . ' ' . $content; $match_count = preg_match_all($this->search_pattern, $content, $matches, PREG_OFFSET_CAPTURE); if( $match_count < 1 ){ return; } $words = str_word_count($content); $strength = $this->Strength($matches,$words); //format content, remove html $label_len = strlen($label); $content = preg_replace('#]*>.*?#si', '', $content); $content = preg_replace('#]*>.*?#si', '', $content); $content = substr($content, $label_len); $content = str_replace('>', '> ', $content); $content = preg_replace('/\s+/', ' ', $content); $content = strip_tags($content); preg_match($this->search_pattern, $content, $matches, PREG_OFFSET_CAPTURE); $start = isset($matches[0][1]) ? $matches[0][1] : 0; //find a space at the beginning to start from $i = 0; do{ $i++; $start_offset = $i * 10; $start = max(0, $start - $start_offset); $trimmed = substr($content, $start, 300); $space = strpos($trimmed, ' '); if( $space < $start_offset ){ $content = substr($trimmed, $space); break; } }while( ($start-$start_offset) > 0); //find a space at the end if( strlen($content) > 250 ){ $space2 = strpos($content, ' ', $space + 220); if( $space2 > 0 ){ $content = substr($content, 0, $space2); } } $result = array(); $result['label'] = $label; $result['slug'] = $slug; $result['query'] = $link_query; $result['content'] = preg_replace($this->search_pattern, '\1\2', $content); $result['words'] = $words; $result['matches'] = $match_count; $result['strength'] = $strength; $this->results[] = $result; } function Strength($matches, $len){ //space around search terms $factor = 0; foreach((array)$matches[1] as $match){ if( is_array($match) && $match[1] >= 0 ){ $factor += 3; } } //no space around search term foreach((array)$matches[2] as $match){ if( is_array($match) && $match[1] >= 0 ){ $factor += 1; } } $strength = $factor / $len; return round($strength, 8); } }