From 42e31f1063bfb821326e99733bca3d30cad86345 Mon Sep 17 00:00:00 2001
From: Dominik Hebeler <dominik@suma-ev.de>
Date: Mon, 18 Feb 2019 14:29:41 +0100
Subject: [PATCH] Added Filter Options to the Websearch

---
 app/MetaGer.php                               | 34 ++++++++
 app/Models/Searchengine.php                   |  8 +-
 app/Models/parserSkripte/Bing.php             | 84 +++++++++++++++++++
 app/Models/parserSkripte/BingBilder.php       |  1 +
 app/Models/parserSkripte/Overture.php         | 20 +++--
 resources/lang/de/metaGer.php                 | 42 ++++++++++
 resources/less/metager/general/general.less   |  1 +
 .../metager/pages/resultpage/result-page.less | 47 +++++++----
 .../less/metager/pages/resultpage/result.less |  2 +-
 .../views/layouts/researchandtabs.blade.php   | 24 ++++--
 resources/views/parts/foki.blade.php          |  7 --
 11 files changed, 237 insertions(+), 33 deletions(-)
 create mode 100644 app/Models/parserSkripte/Bing.php

diff --git a/app/MetaGer.php b/app/MetaGer.php
index 5fe8044c5..65a1e4a69 100644
--- a/app/MetaGer.php
+++ b/app/MetaGer.php
@@ -28,6 +28,7 @@ class MetaGer
     protected $stopWords = [];
     protected $phrases = [];
     protected $engines = [];
+    protected $totalResults = 0;
     protected $results = [];
     protected $queryFilter = [];
     protected $parameterFilter = [];
@@ -562,6 +563,21 @@ class MetaGer
                     }
                 }
             }
+            # Check if this engine should only be active when filter is used
+            if ($this->sumaFile->sumas->{$suma}->{"filter-opt-in"}) {
+                # This search engine should only be used when a parameter filter of it is used
+                $validTmp = false;
+                foreach ($this->parameterFilter as $filterName => $filter) {
+                    if (!empty($filter->sumas->{$suma})) {
+                        $validTmp = true;
+                        break;
+                    }
+                }
+                if (!$validTmp) {
+                    $valid = false;
+                }
+
+            }
             # If it can we add it
             if ($valid) {
                 $this->enabledSearchengines[$suma] = $this->sumaFile->sumas->{$suma};
@@ -621,6 +637,11 @@ class MetaGer
         $this->waitForResults($enginesToLoad, $overtureEnabled, $canBreak);
 
         $this->retrieveResults($engines);
+        foreach ($engines as $engine) {
+            if (!empty($engine->totalResults) && $engine->totalResults > $this->totalResults) {
+                $this->totalResults = $engine->totalResults;
+            }
+        }
     }
 
     # Spezielle Suchen und Sumas
@@ -685,6 +706,14 @@ class MetaGer
                     $availableFilter[$filterName] = $filter;
                 }
             }
+            # We will also add the filter from the opt-in search engines (the searchengines that are only used when a filter of it is too)
+            foreach ($this->sumaFile->foki->{$this->fokus}->sumas as $suma) {
+                if ($this->sumaFile->sumas->{$suma}->{"filter-opt-in"}) {
+                    if (!empty($filter->sumas->{$suma})) {
+                        $availableFilter[$filterName] = $filter;
+                    }
+                }
+            }
         }
 
         return $availableFilter;
@@ -1541,6 +1570,11 @@ class MetaGer
         return $this->sumaFile;
     }
 
+    public function getTotalResultCount()
+    {
+        return number_format($this->totalResults, 0, ",", ".");
+    }
+
     public function getQueryFilter()
     {
         return $this->queryFilter;
diff --git a/app/Models/Searchengine.php b/app/Models/Searchengine.php
index b8a21b5a5..686268a28 100644
--- a/app/Models/Searchengine.php
+++ b/app/Models/Searchengine.php
@@ -15,6 +15,7 @@ abstract class Searchengine
 
     public $getString = ""; # Der String für die Get-Anfrage
     public $engine; # Die ursprüngliche Engine XML
+    public $totalResults = 0; # How many Results the Searchengine has found
     public $results = []; # Die geladenen Ergebnisse
     public $ads = []; # Die geladenen Werbungen
     public $products = []; # Die geladenen Produkte
@@ -48,7 +49,7 @@ abstract class Searchengine
 
         # Cache Standarddauer 60
         $this->cacheDuration = 60;
-        if (!empty($engine->{"cache-duration"}) && $engine->{"cache-duration"} >= 0) {
+        if (isset($engine->{"cache-duration"}) && $engine->{"cache-duration"} !== -1) {
             $this->cacheDuration = $engine->{"cache-duration"};
         }
 
@@ -183,6 +184,10 @@ abstract class Searchengine
     {
         foreach ($this->results as $result) {
             $result->rank($eingabe);
+            if (str_contains($this->engine->{"display-name"}, "Yahoo")) {
+                #die(var_dump($result));
+            }
+
         }
     }
 
@@ -199,6 +204,7 @@ abstract class Searchengine
         }
 
         $body = "";
+
         if ($this->canCache && $this->cacheDuration > 0 && Cache::has($this->hash)) {
             $body = Cache::get($this->hash);
         } elseif (Redis::hexists('search.' . $this->resultHash, $this->name)) {
diff --git a/app/Models/parserSkripte/Bing.php b/app/Models/parserSkripte/Bing.php
new file mode 100644
index 000000000..cda8166a7
--- /dev/null
+++ b/app/Models/parserSkripte/Bing.php
@@ -0,0 +1,84 @@
+<?php
+
+namespace app\Models\parserSkripte;
+
+use App\Models\Searchengine;
+use Log;
+
+class Bing extends Searchengine
+{
+    public $results = [];
+
+    public function __construct($name, \stdClass $engine, \App\MetaGer $metager)
+    {
+        parent::__construct($name, $engine, $metager);
+    }
+
+    public function loadResults($result)
+    {
+        try {
+            $results = json_decode($result);
+            $this->totalResults = $results->webPages->totalEstimatedMatches;
+            $results = $results->webPages->value;
+
+            foreach ($results as $result) {
+                $title = $result->name;
+                $link = $result->url;
+                $anzeigeLink = $result->displayUrl;
+                $descr = $result->snippet;
+                $this->counter++;
+                $this->results[] = new \App\Models\Result(
+                    $this->engine,
+                    $title,
+                    $link,
+                    $anzeigeLink,
+                    $descr,
+                    $this->engine->{"display-name"}, $this->engine->homepage,
+                    $this->counter,
+                    []
+                );
+
+            }
+
+        } catch (\Exception $e) {
+            Log::error("A problem occurred parsing results from $this->name:");
+            Log::error($e->getMessage());
+            return;
+        }
+    }
+
+    public function getNext(\App\MetaGer $metager, $result)
+    {
+        try {
+            $results = json_decode($result);
+
+            $totalMatches = $results->webPages->totalEstimatedMatches;
+
+            $newEngine = unserialize(serialize($this->engine));
+
+            $perPage = $newEngine->{"get-parameter"}->count;
+
+            $offset = 0;
+            if (empty($newEngine->{"get-parameter"}->offset)) {
+                $offset = $perPage;
+            } else {
+                $offset = $newEngine->{"get-parameter"}->offset + $perPage;
+            }
+
+            if ($totalMatches < ($offset + $perPage)) {
+                return;
+            } else {
+                $newEngine->{"get-parameter"}->offset = $offset;
+            }
+
+            $next = new Bing($this->name, $newEngine, $metager);
+            $this->next = $next;
+
+        } catch (\Exception $e) {
+            Log::error("A problem occurred parsing results from $this->name:");
+            Log::error($e->getMessage());
+            return;
+        }
+
+    }
+}
diff --git a/app/Models/parserSkripte/BingBilder.php b/app/Models/parserSkripte/BingBilder.php
index 1587e230f..3ccc2a3a5 100644
--- a/app/Models/parserSkripte/BingBilder.php
+++ b/app/Models/parserSkripte/BingBilder.php
@@ -18,6 +18,7 @@ class BingBilder extends Searchengine
     {
         try {
             $results = json_decode($result);
+            $this->totalResults = $results->totalEstimatedMatches;
             $results = $results->value;
 
             foreach ($results as $result) {
diff --git a/app/Models/parserSkripte/Overture.php b/app/Models/parserSkripte/Overture.php
index c8351132d..5d7a7e8eb 100644
--- a/app/Models/parserSkripte/Overture.php
+++ b/app/Models/parserSkripte/Overture.php
@@ -25,7 +25,14 @@ class Overture extends Searchengine
             if (!$content) {
                 return;
             }
-
+            # Yahoo gives us the total Result Count
+            $resultCount = $content->xpath('//Results/ResultSet[@id="inktomi"]/MetaData/TotalHits');
+            if (sizeof($resultCount) > 0) {
+                $resultCount = intval($resultCount[0]->__toString());
+            } else {
+                $resultCount = 0;
+            }
+            $this->totalResults = $resultCount;
             $results = $content->xpath('//Results/ResultSet[@id="inktomi"]/Listing');
             foreach ($results as $result) {
                 $title = $result["title"];
@@ -40,8 +47,9 @@ class Overture extends Searchengine
                     $anzeigeLink,
                     $descr,
                     $this->engine->{"display-name"},
-                    $this->engine->homepage,
-                    $this->counter
+                    $this->engine->{"homepage"},
+                    $this->counter,
+                    []
                 );
             }
 
@@ -59,8 +67,10 @@ class Overture extends Searchengine
                     $link,
                     $anzeigeLink,
                     $descr,
-                    $this->engine->{"display-name"}, $this->engine->homepage,
-                    $this->counter
+                    $this->engine->{"display-name"},
+                    $this->engine->{"homepage"},
+                    $this->counter,
+                    []
                 );
             }
         } catch (\Exception $e) {
diff --git a/resources/lang/de/metaGer.php b/resources/lang/de/metaGer.php
index 7d06f80a4..4722f9c15 100644
--- a/resources/lang/de/metaGer.php
+++ b/resources/lang/de/metaGer.php
@@ -22,7 +22,9 @@ return [
     'sitesearch.success' => 'Sie führen eine Sitesearch durch. Es werden nur Ergebnisse von der Seite: ":site" angezeigt.',
     'feedback' => 'Nichts Passendes dabei? Geben Sie uns Feedback: ',
 
+    'results' => "Ergebnisse",
     'filter.noFilter' => 'Alle',
+    'filter.reset' => 'Filter zurücksetzen',
 
     'filter.sitesearch' => 'Sitesearch',
     'filter.safesearch' => "SafeSearch",
@@ -79,4 +81,44 @@ return [
     "filter.freshness.day" => "Letzte 24h",
     "filter.freshness.week" => "Letzte Woche",
     "filter.freshness.month" => "Letzter Monat",
+
+    "filter.market" => "Sprache",
+    "filter.market.ga" => "Deutsch (Österreich)",
+    "filter.market.gg" => "Deutsch (Deutschland)",
+    "filter.market.gs" => "Deutsch (Schweiz)",
+    "filter.market.ea" => "Englisch (Australien)",
+    "filter.market.ec" => "Englisch (Kanada)",
+    "filter.market.ei" => "Englisch (Indien)",
+    "filter.market.ein" => "Englisch (Indonesien)",
+    "filter.market.em" => "Englisch (Malaysia)",
+    "filter.market.enz" => "Englisch (Neuseeland)",
+    "filter.market.ep" => "Englisch (Philippinen)",
+    "filter.market.esa" => "Englisch (Süd-Afrika)",
+    "filter.market.euk" => "Englisch (UK)",
+    "filter.market.eus" => "Englisch (US)",
+    "filter.market.sa" => "Spanisch (Argentinien)",
+    "filter.market.sc" => "Spanisch (Chile)",
+    "filter.market.sm" => "Spanisch (Mexiko)",
+    "filter.market.ss" => "Spanisch (Spanien)",
+    "filter.market.sus" => "Spanisch (US)",
+    "filter.market.fb" => "Französisch (Belgien)",
+    "filter.market.fc" => "Französisch (Kanada)",
+    "filter.market.ff" => "Französisch (Frankreich)",
+    "filter.market.fs" => "Französisch (Schweiz)",
+    "filter.market.ii" => "Italienisch (Italien)",
+    "filter.market.db" => "Niederländisch (Belgien)",
+    "filter.market.dn" => "Niederländisch (Niederlande)",
+    "filter.market.pp" => "Polnisch (Polen)",
+    "filter.market.pb" => "Portugiesisch (Brasilien)",
+    "filter.market.dd" => "Dänisch (Dänemark)",
+    "filter.market.fif" => "Finnisch (Finnland)",
+    "filter.market.nn" => "Norwegisch (Norwegen)",
+    "filter.market.scs" => "Schwedisch (Schweden)",
+    "filter.market.rr" => "Russisch (Russland)",
+    "filter.market.jj" => "Japanisch (Japan)",
+    "filter.market.kk" => "Koreanisch (Korea)",
+    "filter.market.tt" => "Türkisch (Türkei)",
+    "filter.market.chk" => "Chinesisch (Hong Kong SAR)",
+    "filter.market.cc" => "Chinesisch (China)",
+    "filter.market.ct" => "Chinesisch (Taiwan)",
 ];
diff --git a/resources/less/metager/general/general.less b/resources/less/metager/general/general.less
index 56b8dad84..7b7fe480d 100644
--- a/resources/less/metager/general/general.less
+++ b/resources/less/metager/general/general.less
@@ -77,6 +77,7 @@ body {
             background: -webkit-gradient(linear, left top, right top, from(@scrollfade-color), color-stop(fade(@scrollfade-color, 80%)), to(fade(@scrollfade-color, 0%)));
             background: linear-gradient(to right, @scrollfade-color, fade(@scrollfade-color, 80%), fade(@scrollfade-color, 0%));
             left: 1px;
+            margin-left: -20px;
         }
         &right {
             background: -webkit-gradient(linear, right top, left top, from(@scrollfade-color), color-stop(fade(@scrollfade-color, 80%)), to(fade(@scrollfade-color, 0%)));
diff --git a/resources/less/metager/pages/resultpage/result-page.less b/resources/less/metager/pages/resultpage/result-page.less
index 876a33261..80d488c6f 100644
--- a/resources/less/metager/pages/resultpage/result-page.less
+++ b/resources/less/metager/pages/resultpage/result-page.less
@@ -483,8 +483,12 @@ a {
 
 #options {
     grid-area: options;
-    display: flex;
-    justify-content: left;
+    background-color: white;
+    max-width: @results-width-max;
+    padding: 0 8px;
+    @media(max-width: @screen-mobile){
+        .card;
+    }
     input[type=checkbox]{
         display: none;
     }
@@ -498,17 +502,33 @@ a {
         max-height:200px;
         transform: scaleY(1);
     }
+    #toggle-box {
+        display: flex;
+        align-items: center;
+        #result-count {
+            flex-grow: 1;
+            text-align: right;
+        }
+        #options-reset {
+            margin-left: 10px;
+        }
+        .option-toggle {
+            text-align: center;
+            label{
+                font-weight: normal;
+                margin-bottom: 0;
+            }
+        }
+    }
     #options-box{
         width: 100%;
-        max-width: 700px;
-        background-color: white;
-        border-bottom: 1px solid #ccc;
-        @media(max-width: @screen-mobile){
-            .card;
-        }
+        display: flex;
+        justify-content: left;
         overflow: hidden;
         overflow-x: auto;
-        padding: 8px;
+        border-bottom: 1px solid #ccc;
+        padding-bottom: 8px;
+        padding-top: 8px;
         #options-items {
             display: -ms-flexbox;
             display: flex;
@@ -531,10 +551,9 @@ a {
                     border-radius: 5px;
                 }
             }
-        }
-        #options-reset {
-            margin-left: 10px;
-            margin-bottom: 8px;
+            .option-selector:nth-child(1){
+                margin-left: 0;
+            }
         }
     }
 }
@@ -549,7 +568,7 @@ a {
 }
 
 footer.resultPageFooter {
-    max-width: 700px;
+    max-width: @results-width-max;
     margin-top: 20px;
     @media (max-width: (2 * @results-margin-left + @results-width-max - 1px)) {
         margin: 20px 0 0 0;
diff --git a/resources/less/metager/pages/resultpage/result.less b/resources/less/metager/pages/resultpage/result.less
index 2560f4954..d697d7fd0 100644
--- a/resources/less/metager/pages/resultpage/result.less
+++ b/resources/less/metager/pages/resultpage/result.less
@@ -14,7 +14,7 @@
         .card;
     }
     margin: @padding-small-default 0px;
-    padding: 8px 15px 5px 15px;
+    padding: 8px 8px 5px 8px;
     width: 100%;
     .result-header {
         display: flex;
diff --git a/resources/views/layouts/researchandtabs.blade.php b/resources/views/layouts/researchandtabs.blade.php
index 47f1ec34a..13b06bb93 100644
--- a/resources/views/layouts/researchandtabs.blade.php
+++ b/resources/views/layouts/researchandtabs.blade.php
@@ -28,15 +28,29 @@
 	</div>
 	@if(sizeof($metager->getAvailableParameterFilter()) > 0)
 	<div id="options">
+		<div id="toggle-box">
+			@if(sizeof($metager->getAvailableParameterFilter()) > 0)
+			<div class="option-toggle">
+				<label class="navigation-element" for="options-toggle">
+					<i class="fas fa-filter"></i> Filter&hellip;
+				</label>
+			</div>
+			@endif
+			@if(sizeof($metager->getParameterFilter()) > 0)
+			<div id="options-reset">
+				<a href="{{$metager->generateSearchLink($metager->getFokus())}}"><nobr>{{ trans('filter.reset') }}</nobr></a>
+			</div>
+			@endif
+			@if($metager->getTotalResultCount() > 0)
+			<div id="result-count">
+				~ {{$metager->getTotalResultCount()}} {{ trans('metaGer.results') }}
+			</div>
+			@endif
+		</div>
 		<input type="checkbox" id="options-toggle" @if(sizeof($metager->getParameterFilter()) > 0)checked @endif />
 		<div class="scrollbox">
 			<div class="scrollfade-left"></div>
 			<div id="options-box">
-				@if(sizeof($metager->getParameterFilter()) > 0)
-				<div id="options-reset">
-					<a href="{{$metager->generateSearchLink($metager->getFokus())}}"><nobr>Filter zurücksetzen</nobr></a>
-				</div>
-				@endif
 				<div id="options-items">
 				@foreach($metager->getAvailableParameterFilter() as $filterName => $filter)
 					<div class="option-selector">
diff --git a/resources/views/parts/foki.blade.php b/resources/views/parts/foki.blade.php
index 25c3bd328..cc748c53a 100644
--- a/resources/views/parts/foki.blade.php
+++ b/resources/views/parts/foki.blade.php
@@ -3,10 +3,3 @@
 		<a href="@if($metager->getFokus() === $name)#@else{!!$metager->generateSearchLink($name)!!}@endif" target="_self" tabindex="0">@lang($fokus->{"display-name"})</a>
 	</div>
 @endforeach
-@if(sizeof($metager->getAvailableParameterFilter()) > 0)
-<div class="option-toggle">
-	<label class="navigation-element" for="options-toggle">
-		<i class="fas fa-filter"></i>
-	</label>
-</div>
-@endif
-- 
GitLab