MetaGerSearch.php 7.75 KB
Newer Older
Dominik Hebeler's avatar
Dominik Hebeler committed
1
2
3
4
<?php

namespace App\Http\Controllers;

5
use App;
6
use App\MetaGer;
7
use Cache;
8
use Illuminate\Http\Request;
9
10
use Illuminate\Support\Facades\Redis;
use View;
Dominik Hebeler's avatar
Dominik Hebeler committed
11

12
const TIP_SERVER = 'http://metager3.de:63825/tips.xml';
13

Dominik Hebeler's avatar
Dominik Hebeler committed
14
15
class MetaGerSearch extends Controller
{
16
    public function search(Request $request, MetaGer $metager)
17
    {
18
        $focus = $request->input("focus", "web");
19

20
21
22
23
24
        if ($focus === "maps") {
            $searchinput = $request->input('eingabe', '');
            return redirect()->to('https://maps.metager.de/map/' . $searchinput . '/1240908.5493525574,6638783.2192695495,6');
        }

25
26
        # Mit gelieferte Formulardaten parsen und abspeichern:
        $metager->parseFormData($request);
27

28
29
        # Nach Spezialsuchen überprüfen:
        $metager->checkSpecialSearches($request);
30

31
32
33
        # Die Quicktips als Job erstellen
        $quicktips = $metager->createQuicktips();

34
        # Suche für alle zu verwendenden Suchmaschinen als Job erstellen,
35
        # auf Ergebnisse warten und die Ergebnisse laden
36
        $metager->createSearchEngines($request);
37

38
39
40
41
42
43
        $metager->startSearch();

        $metager->waitForMainResults();

        $metager->retrieveResults();

44
45
        # Versuchen die Ergebnisse der Quicktips zu laden
        $quicktipResults = $quicktips->loadResults();
46
47
48
        # Alle Ergebnisse vor der Zusammenführung ranken:
        $metager->rankAll();

49
        # Ergebnisse der Suchmaschinen kombinieren:
Phil Höfer's avatar
Phil Höfer committed
50
        $metager->prepareResults();
51

52
53
54
55
56
57
        # Save the results in Redis
        $redis = Redis::connection(env('REDIS_RESULT_CONNECTION'));
        $pipeline = $redis->pipeline();
        foreach ($metager->getResults() as $result) {
            $pipeline->rpush($metager->getRedisCurrentResultList(), base64_encode(serialize($result)));
        }
58
        $pipeline->expire($metager->getRedisCurrentResultList(), env('REDIS_RESULT_CACHE_DURATION'));
59
60
        $pipeline->execute();

61
        # Die Ausgabe erstellen:
62
        return $metager->createView($quicktipResults);
Dominik Hebeler's avatar
Dominik Hebeler committed
63
64
    }

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
    public function loadMore(Request $request)
    {
        /**
         * There are three forms of requests to the resultpage
         * 1. Initial Request: Loads the fastest searchengines and sends them to the user
         * 2. Load more results (with JS): Loads new search engines that answered after the initial request was send
         * 3. Load more results (without JS): Loads new search engines that answered within 1s timeout
         */
        if ($request->filled('loadMore') && $request->filled('script') && $request->input('script') === "yes") {
            return $this->loadMoreJS($request);
        }

    }

    private function loadMoreJS(Request $request)
    {
        # Create a MetaGer Instance with the supplied hash
        $hash = $request->input('loadMore', '');

        $metager = new MetaGer($hash);
        $redis = Redis::connection(env('REDIS_RESULT_CONNECTION'));

        $result = [];
        # Check if there should be more results
        $stats = $redis->hgetall($metager->getRedisEngineResult() . "status");
        $stats["startTime"] = floatval($stats["startTime"]);
        $stats["engineCount"] = intval($stats["engineCount"]);
        $stats["engineAnswered"] = intval($stats["engineAnswered"]);
        $stats["engineDelivered"] = intval($stats["engineDelivered"]);

        $result["finished"] = true;
        $result["engineCount"] = $stats["engineCount"];
        $result["engineAnswered"] = $stats["engineAnswered"];
        $result["engineDelivered"] = $stats["engineDelivered"];
        $result["timeWaiting"] = microtime(true) - $stats["startTime"];

        # Check if we can abort
        if ($stats["engineAnswered"] > $stats["engineDelivered"]/*&& $result["timeWaiting"] <= 10 */) {
            $metager->parseFormData($request);
            # Nach Spezialsuchen überprüfen:
            $metager->checkSpecialSearches($request);

            # Read which search engines are new
            $newEngines = [];

110
            while (($engine = $redis->lpop($metager->getRedisResultWaitingKey())) != null) {
111
112
113
                $result["engineDelivered"]++;
                $newEngines[$engine] = $metager->getSumaFile()->sumas->{$engine};
            }
114
115
116
117
118
119
120
121
122
            $cache = Cache::get($hash);
            if ($cache != null) {
                $metager->setNext(unserialize($cache)["engines"]);
            }

            # Check if this request is not for page one
            $metager->setEngines($request, $newEngines);

            # Add the results already delivered to the user
123
124
125
126
127
128
129
130
131
            $results = $redis->lrange($metager->getRedisCurrentResultList(), 0, -1);
            foreach ($results as $index => $oldResult) {
                $results[$index] = unserialize(base64_decode($oldResult));
                $results[$index]->new = false;
            }
            $metager->setResults($results);
            $metager->retrieveResults();
            $metager->rankAll();
            $metager->prepareResults();
132
            $result["nextSearchLink"] = $metager->nextSearchLink();
133
134
135
            $results = $metager->getResults();
            foreach ($results as $index => $resultTmp) {
                if ($resultTmp->new) {
136
137
138
139
140
141
142
143
144
145
146
                    if ($metager->getFokus() !== "bilder") {
                        $view = View::make('layouts.result', ['result' => $resultTmp, 'metager' => $metager]);
                        $html = $view->render();
                        $result['newResults'][$index] = $html;
                        $result["imagesearch"] = false;
                    } else {
                        $view = View::make('layouts.image_result', ['result' => $resultTmp, 'metager' => $metager]);
                        $html = $view->render();
                        $result['newResults'][$index] = $html;
                        $result["imagesearch"] = true;
                    }
147
148
                }
            }
149
150
151
152
153
154
155
156
            # Save the results in Redis
            $pipeline = $redis->pipeline();
            $pipeline->hincrby($metager->getRedisEngineResult() . "status", "engineDelivered", sizeof($newEngines));
            $pipeline->hset($metager->getRedisEngineResult() . "status", "nextSearchLink", $result["nextSearchLink"]);
            foreach ($metager->getResults() as $resultTmp) {
                $resultTmp->new = false;
                $pipeline->rpush($metager->getRedisCurrentResultList(), base64_encode(serialize($resultTmp)));
            }
157
            $pipeline->expire($metager->getRedisCurrentResultList(), env('REDIS_RESULT_CACHE_DURATION'));
158
            $pipeline->execute();
159
160
161
162
163

        }
        return response()->json($result);
    }

164
165
166
167
168
169
170
171
    public function botProtection($redirect)
    {
        $hash = md5(date('YmdHi'));
        return view('botProtection')
            ->with('hash', $hash)
            ->with('r', $redirect);
    }

172
173
    public function get($url)
    {
174
        $ctx = stream_context_create(array('http' => array('timeout' => 2)));
175
        return file_get_contents($url, false, $ctx);
176
    }
177
178
179
180
181
182

    private function startsWith($haystack, $needle)
    {
        $length = strlen($needle);
        return (substr($haystack, 0, $length) === $needle);
    }
183
184
185
186

    public function tips(Request $request)
    {
        $tips_text = file_get_contents(TIP_SERVER);
187
        $tips = [];
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
        try {
            $tips_xml = simplexml_load_string($tips_text);

            $tips_xml->registerXPathNamespace('mg', 'http://metager.de/tips/');
            $tips_xml = $tips_xml->xpath('mg:tip');
            foreach ($tips_xml as $tip_xml) {
                $tips[] = $tip_xml->__toString();
            }
        } catch (\Exception $e) {
            Log::error("A problem occurred loading tips from the tip server.");
            Log::error($e->getMessage());
            abort(500);
        }
        return view('tips')
            ->with('title', trans('tips.title'))
            ->with('tips', $tips);
    }
205
}