コード例 #1
1
 public function getAllProjects()
 {
     $key = "{$this->cachePrefix}-all-projects";
     if ($this->cache && ($projects = $this->cache->fetch($key))) {
         return $projects;
     }
     $first = json_decode($this->client->get('projects.json', ['query' => ['limit' => 100]])->getBody(), true);
     $projects = $first['projects'];
     if ($first['total_count'] > 100) {
         $requests = [];
         for ($i = 100; $i < $first['total_count']; $i += 100) {
             $requests[] = $this->client->getAsync('projects.json', ['query' => ['limit' => 100, 'offset' => $i]]);
         }
         /** @var Response[] $responses */
         $responses = Promise\unwrap($requests);
         $responseProjects = array_map(function (Response $response) {
             return json_decode($response->getBody(), true)['projects'];
         }, $responses);
         $responseProjects[] = $projects;
         $projects = call_user_func_array('array_merge', $responseProjects);
     }
     usort($projects, function ($projectA, $projectB) {
         return strcasecmp($projectA['name'], $projectB['name']);
     });
     $this->cache && $this->cache->save($key, $projects);
     return $projects;
 }
コード例 #2
0
 /**
  * __invoke.
  *
  * @param mixed $values
  *
  * @return $this
  */
 public function __invoke($values)
 {
     $response = json_decode((string) $values->getBody());
     // Return when empty response.
     if (empty($response)) {
         return $this;
     }
     // Process the response.
     $this->process($response);
     $promisses = [];
     // Loop over all artist and create promisses
     foreach ($this->getArtistsAlbumsList() as $artistEntity) {
         $artistEntity = $artistEntity[0];
         // Process offset value only one time.
         if (isset($this->processedArtistsList[$artistEntity->id]) && $this->processedArtistsList[$artistEntity->id] === true) {
             continue;
         } else {
             $getArtistRelatedArtists = 'artists/' . $artistEntity->id . '/related-artists';
             $promisses[] = $this->client->getAsync($getArtistRelatedArtists)->then($this);
             // <= re-use same object.
             $this->processedArtistsList[$artistEntity->id] = true;
         }
     }
     // Resolve promisses.
     Promise\unwrap($promisses);
     return $this;
 }
コード例 #3
0
 /**
  * @param string $uri
  * @param array  $query
  * @param array  $options
  *
  * @return Promise
  */
 public function getAsync($uri, array $query = [], array $options = [])
 {
     if (!empty($query)) {
         $options['query'] = $this->buildQuery($query);
     }
     return $this->guzzle->getAsync($uri, $options);
 }
コード例 #4
0
 /**
  * Returns a list of artist entities.
  *
  * @param array $artistIdList list of spotify id's.
  *
  * @return ArtistsAlbumsList
  */
 public function getArtistsAndAlbumsByIdList(array $artistIdList = [])
 {
     if (empty($artistIdList)) {
         throw new \InvalidArgumentException('Artist id list is empty.');
     }
     $getSeveralArtists = 'artists?ids=' . implode(',', $artistIdList);
     $rejectHandler = HandlerFactory::newRejectHandlerInstance();
     $promise = $this->client->getAsync($getSeveralArtists)->then(HandlerFactory::newArtistHandlerInstance($this->client), $rejectHandler)->then(HandlerFactory::newAlbumsHandlerInstance($this->client), $rejectHandler);
     $response = $promise->wait();
     return $response->getArtistsAlbumsList();
 }
コード例 #5
0
ファイル: Timer.php プロジェクト: pwlap/loater
 /**
  * Get loading time information for two websites
  * Info: Requests are concurrent - http://docs.guzzlephp.org/en/latest/quickstart.html#concurrent-requests
  *
  * @param $comparingUri
  * @param $competitorUri
  *
  * @return array
  */
 public function watchConcurrent($comparingUri, $competitorUri)
 {
     $comparingStats = null;
     $comparingRequest = $this->client->getAsync($comparingUri, [RequestOptions::TIMEOUT => $this->timeout, RequestOptions::ON_STATS => function (TransferStats $stats) use(&$comparingStats) {
         $comparingStats = $stats;
     }]);
     $competitorStats = null;
     $competitorRequest = $this->client->getAsync($competitorUri, [RequestOptions::TIMEOUT => $this->timeout, RequestOptions::ON_STATS => function (TransferStats $stats) use(&$competitorStats) {
         $competitorStats = $stats;
     }]);
     Promise\settle([$comparingRequest, $competitorRequest])->wait();
     return [$comparingStats, $competitorStats];
 }
コード例 #6
0
 /**
  * __invoke.
  *
  * @param mixed $values
  *
  * @return $this
  */
 public function __invoke($values)
 {
     // Get from previous handler the artists albums list.
     $this->artistsAlbumsList = $values->getArtistsAlbumsList();
     $promisses = [];
     // Loop over the artists albums list creating promisses for each artist.
     foreach ($this->artistsAlbumsList as $artistId => $artistAlbum) {
         $artistsTopTracks = 'artists/' . $artistId . '/top-tracks?country=US';
         $promisses[$artistId] = $this->client->getAsync($artistsTopTracks);
     }
     // Resolve all promisses.
     $artistAlbums = Promise\unwrap($promisses);
     // Process the result.
     $this->process($artistAlbums);
     return $this;
 }
コード例 #7
0
ファイル: snitches.php プロジェクト: kcmerrill/snitchin
 static function http()
 {
     return function ($log_entry, $options) {
         $client = new Client();
         $url = $options;
         $method = 'put';
         if (is_array($options)) {
             if (!isset($options['url'])) {
                 throw new \LogicException('HTTP requires either a string(url) or an array of options with the key url to be set to CURL');
             }
             $url = $options['url'];
             if (isset($options['method'])) {
                 $method = $options['method'];
             }
         }
         if (!is_string($url)) {
             throw new \LogicException('HTTP requires either a string(url) or an array of options with the key url to be set to CURL');
         }
         if ($method == 'get') {
             $client->getAsync($url);
         } else {
             $client->postAsync($url, array('body' => json_encode($log_entry)));
         }
     };
 }
コード例 #8
0
 public function handle()
 {
     $this->totalPageCount = count($this->users);
     $client = new Client();
     $requests = function ($total) use($client) {
         foreach ($this->users as $key => $user) {
             $uri = 'https://api.github.com/users/' . $user;
             (yield function () use($client, $uri) {
                 return $client->getAsync($uri);
             });
         }
     };
     $pool = new Pool($client, $requests($this->totalPageCount), ['concurrency' => $this->concurrency, 'fulfilled' => function ($response, $index) {
         $res = json_decode($response->getBody()->getContents());
         $this->info("请求第 {$index} 个请求,用户 " . $this->users[$index] . " 的 Github ID 为:" . $res->id);
         $this->countedAndCheckEnded();
     }, 'rejected' => function ($reason, $index) {
         $this->error("rejected");
         $this->error("rejected reason: " . $reason);
         $this->countedAndCheckEnded();
     }]);
     // 开始发送请求
     $promise = $pool->promise();
     $promise->wait();
 }
コード例 #9
0
ファイル: Storage.php プロジェクト: melfa/air-telegram-bot
 /**
  * @return \GuzzleHttp\Promise\PromiseInterface
  */
 public function getCo2Ppm()
 {
     return $this->http->getAsync('query', [RequestOptions::AUTH => [$this->influxConfig->user, $this->influxConfig->password], RequestOptions::QUERY => ['db' => 'air', 'q' => 'select last(ppm) from co2']])->then(function (ResponseInterface $response) {
         $influxResponse = json_decode($response->getBody(), true);
         /*
            {
                "results": [
                    {
                        "series": [
                            {
                                "name": "cpu_load_short",
                                "columns": [
                                    "time",
                                    "ppm"
                                ],
                                "values": [
                                    [
                                        "2015-01-29T21:55:43.702900257Z",
                                        0.55
                                    ],
                                    [
                                        "2015-01-29T21:55:43.702900257Z",
                                        23422
                                    ],
                                    [
                                        "2015-06-11T20:46:02Z",
                                        0.64
                                    ]
                                ]
                            }
                        ]
                    }
                ]
            }
         */
         if (!$influxResponse || !is_array($influxResponse)) {
             return null;
         }
         return $influxResponse['results'][0]['series'][0]['values'][0][1];
     }, function ($e) {
         // todo logging
         var_dump($e->getMessage());
         //                echo $e->getMessage() . "\n";
         //                echo $e->getRequest()->getMethod();
     });
 }
コード例 #10
0
ファイル: VulnDB.php プロジェクト: Zae/wp-vulnerabilities
 /**
  * @param $entities
  *
  * @return mixed
  */
 private function findVulnerabilities(array $entities)
 {
     $requests = Collection::make($entities)->map(function (Entity $entity) {
         return function () use($entity) {
             return $this->vulnDBApi->getAsync($this->getAPIPath($entity));
         };
     })->getIterator();
     (new Pool($this->vulnDBApi, $requests, ['concurrency' => $this->config->get('http.concurrency'), 'fulfilled' => function ($response, $index) use(&$entities) {
         if ($response->getStatusCode() === 200) {
             $response_object = json_decode((string) $response->getBody());
             if ($this->isVulnerable($response_object, $entities[$index], $vulnerabilities)) {
                 $entities[$index]->vulnerable(Collection::make($vulnerabilities)->implode('title', ','));
             }
         }
     }]))->promise()->wait();
     return $entities;
 }
コード例 #11
0
ファイル: Http.php プロジェクト: legalthings/data-enricher
 /**
  * Do async request for node
  * 
  * @param Node $node
  */
 public function applyToNode(Node $node)
 {
     $url = $this->getUrl($node);
     if (!isset($url)) {
         return;
     }
     $client = new Client(['http_errors' => false]);
     $promise = $client->getAsync($url)->then(function (Response $response) use($node) {
         $this->applyResult($node, $response);
     });
     $node->setResult($promise);
 }
コード例 #12
0
 public function testCanSendMagicAsyncRequests()
 {
     $client = new Client();
     Server::flush();
     Server::enqueue([new Response(200, ['Content-Length' => 2], 'hi')]);
     $p = $client->getAsync(Server::$url, ['query' => ['test' => 'foo']]);
     $this->assertInstanceOf(PromiseInterface::class, $p);
     $this->assertEquals(200, $p->wait()->getStatusCode());
     $received = Server::received(true);
     $this->assertCount(1, $received);
     $this->assertEquals('test=foo', $received[0]->getUri()->getQuery());
 }
コード例 #13
0
 /**
  * @return array
  */
 private function flushPromises()
 {
     foreach ($this->queries as $key => $query) {
         $cacheKey = $query->getCacheKey();
         // checks if cache exists for the requests. if not pass it to promise.
         if (!($cacheKey && ($cacheItem = $this->getCachePool()->getItem($cacheKey)) && $cacheItem->isHit())) {
             ++$this->debug['executedqueries'];
             $this->promises[$key] = $this->client->getAsync((string) $query);
         } elseif ($cacheKey) {
             $this->cacheData[$key] = $cacheItem->get();
         }
         unset($this->queries[$key]);
     }
     return $this->promises;
 }
コード例 #14
0
ファイル: Client.php プロジェクト: GMSteuart/PandaLove
 public function fetchAccountsPresence($accounts)
 {
     $client = new GuzzleClient(['base_uri' => XboxConstants::$getBaseXboxAPI]);
     // Set up getCommands
     $requests = array();
     foreach ($accounts as $account) {
         if ($account->xuid == null) {
             $destiny = new DestinyClient();
             $account = $destiny->fetchAccountData($account);
         }
         $url = sprintf(XboxConstants::$getPresenceUrl, $account->xuid);
         $requests[$account->seo] = $client->getAsync($url, ['headers' => ['X-AUTH' => env('XBOXAPI_KEY')]]);
     }
     $results = GuzzlePromise\Unwrap($requests);
     return $results;
 }
コード例 #15
0
 private function search()
 {
     // https://oeis.org/search?q=1010&sort=&language=english&go=Search
     $client = new Client(['base_uri' => 'https://oeis.org', 'cookies' => true]);
     for ($i = 0; $i < 1000000; $i++) {
         $a = function ($number) use($client) {
             return $client->getAsync('/search', ['query' => ['q' => $number, 'language' => 'english', 'go' => 'Search']])->then(function (Response $response) use($number) {
                 $content = $response->getBody()->getContents();
                 preg_match('/of (\\d+) results|Found (\\d+) results/', $content, $matches);
                 $found = $matches[1] ? $matches[1] : ($matches[2] ? $matches[2] : 0);
                 return [$number, $found];
             });
         };
         (yield $a($i));
     }
 }
コード例 #16
0
ファイル: helpers.php プロジェクト: takashiki/image-force
 function are_available($urls, $timeout = 10)
 {
     $client = new Client(['timeout' => $timeout, 'connect_timeout' => $timeout]);
     $promises = array_map(function ($url) use($client) {
         return $client->getAsync($url);
     }, $urls);
     try {
         $results = Promise\settle($promises)->wait();
         return array_map(function ($result) {
             return $result['value']->getStatusCode() === 200;
         }, $results);
     } catch (Exception $e) {
         return array_map(function ($url) {
             return false;
         }, $urls);
     }
 }
コード例 #17
0
 /**
  * Make a HTTP Request
  *
  * @param            $url
  * @param array      $options
  * @param bool|false $isAsyncRequest
  *
  * @return mixed
  */
 private function httpRequest($url, array $options = [], $isAsyncRequest = false)
 {
     if ($url == null || trim($url) == '') {
         return 'URL was invalid.';
     }
     $options = $this->getOptions($this->defaultHeaders(), $options, $isAsyncRequest);
     try {
         $response = $this->client->getAsync($url, $options);
         if ($isAsyncRequest) {
             self::$promises[] = $response;
         } else {
             $response = $response->wait();
         }
     } catch (RequestException $e) {
         return 'There was an error while processing the request';
     }
     return $response;
 }
コード例 #18
0
ファイル: Reviewer.php プロジェクト: nirouch/reviewer
 /**
  * Get reviews from country App Store
  *
  * @param  integer $appId
  * @param  string  $countryCode
  * @param  string  $countryName
  * @return array   list of reviews
  */
 public function getReviewsByCountry($appId, $countryCode, $countryName)
 {
     $reviews = [];
     $promises = [];
     for ($i = 1; $i <= $this->maxPages; $i++) {
         $promises['page' . $i] = $this->client->getAsync("https://itunes.apple.com/{$countryCode}/rss/customerreviews/page={$i}/id={$appId}/sortBy=mostRecent/json");
     }
     try {
         $responses = Promise\unwrap($promises);
         for ($page = 1; $page <= $this->maxPages; $page++) {
             $reviewsData = json_decode((string) $responses['page' . $page]->getBody(), true);
             if (!isset($reviewsData['feed']) || !isset($reviewsData['feed']['entry']) || count($reviewsData['feed']['entry']) == 0) {
                 // Received empty page
                 if ($this->logger) {
                     $this->logger->debug("#{$appId}: Received 0 entries for page {$page} in {$countryName}");
                 }
             } else {
                 if ($this->logger) {
                     $countEntries = count($reviewsData['feed']['entry']) - 1;
                     $this->logger->debug("#{$appId}: Received {$countEntries} entries for page {$page} in {$countryName}");
                 }
                 $applicationData = [];
                 foreach ($reviewsData['feed']['entry'] as $reviewEntry) {
                     if (isset($reviewEntry['im:name']) && isset($reviewEntry['im:image']) && isset($reviewEntry['link'])) {
                         // First element is always an app metadata
                         $applicationData = ['name' => $reviewEntry['im:name']['label'], 'image' => end($reviewEntry['im:image'])['label'], 'link' => $reviewEntry['link']['attributes']['href']];
                         continue;
                     }
                     $reviewId = intval($reviewEntry['id']['label']);
                     if ($this->storage->get("r{$reviewId}")) {
                         continue;
                     }
                     $review = ['id' => $reviewId, 'author' => ['uri' => $reviewEntry['author']['uri']['label'], 'name' => $reviewEntry['author']['name']['label']], 'title' => $reviewEntry['title']['label'], 'content' => $reviewEntry['content']['label'], 'rating' => intval($reviewEntry['im:rating']['label']), 'country' => $countryName, 'application' => array_merge($applicationData, ['version' => $reviewEntry['im:version']['label']])];
                     array_push($reviews, $review);
                 }
             }
         }
     } catch (Exception $e) {
         if ($this->logger) {
             $this->logger->error('Reviewer: exception while getting reviews', ['exception' => $e]);
         }
     }
     return $reviews;
 }
コード例 #19
0
ファイル: Sitemap.php プロジェクト: vedebel/sitemap
 /**
  * @param string $url
  * @param bool $async
  * @return bool|PromiseInterface
  */
 private function loadPage($url, $async = false)
 {
     /** @var Url $pageUrl */
     $pageUrl = $this->config->get('url');
     if (false === strpos($url, $pageUrl->getHost())) {
         $url = $pageUrl->getProtocol() . '://' . $pageUrl->getHost() . '/' . ltrim($url, '/');
     }
     if ($sleepTimeout = $this->config->get('timeouts.sleep')) {
         sleep($sleepTimeout);
     }
     try {
         $options = ['timeout' => $this->config->get('timeouts.request'), 'allow_redirects' => true, 'headers' => ['User-Agent' => $this->config->get('userAgent')]];
         if ($async) {
             $promise = $this->client->getAsync($url, $options);
             return $promise;
         }
         $response = $this->client->get($url, $options);
         if ($lastModified = $response->getHeaderLine("Last-Modified")) {
             $lastModified = \DateTime::createFromFormat("D, d M Y H:i:s O", $lastModified);
             $lastModified = $lastModified ? $lastModified->format('Y-m-d\\TH:i:sP') : null;
         } else {
             $lastModified = null;
         }
         $this->lastUrlData = ["status" => $response->getStatusCode(), "lastModified" => $lastModified];
         if (200 !== (int) $response->getStatusCode()) {
             $this->log('Error! Url: ' . $url . ' Status: ' . $response->getStatusCode());
             return false;
         }
         $this->parser->load($response->getBody());
     } catch (TooManyRedirectsException $e) {
         $this->log('Error! Url: ' . $url . '. ' . $e->getMessage());
         return false;
     } catch (RequestException $e) {
         if (429 === (int) $e->getCode()) {
             $sleepTimeout = $this->config->get('timeout.sleep');
             $this->config->set('limits.sleep', $sleepTimeout + 0.5);
         }
         $this->log('Error! Url: ' . $url . '. ' . $e->getMessage());
         return false;
     }
     return true;
 }
コード例 #20
0
ファイル: Client.php プロジェクト: Briareos/Undine
 /**
  * @param UriInterface $url
  * @param Session      $session
  *
  * @return Promise
  *
  * @resolves bool True if the module was just disconnected, false if it was already disconnected.
  *
  * @rejects  RequestException
  * @rejects  OxygenPageNotFoundException
  */
 public function disconnectOxygenAsync(UriInterface $url, Session $session)
 {
     return $this->client->getAsync($url->withQuery(\GuzzleHttp\Psr7\build_query(['q' => 'admin/config/oxygen/disconnect'])), [RequestOptions::COOKIES => $session->getCookieJar(), RequestOptions::AUTH => $session->getAuthData()])->then(function (ResponseInterface $response) use($url, $session) {
         $crawler = new Crawler((string) $response->getBody(), (string) $url);
         try {
             $form = $crawler->filter('form#oxygen-admin-disconnect')->form();
             if ($form->get('oxygen_connected')->getValue() === 'yes') {
                 return $this->client->requestAsync($form->getMethod(), $form->getUri(), [RequestOptions::COOKIES => $session->getCookieJar(), RequestOptions::AUTH => $session->getAuthData(), RequestOptions::HEADERS => ['referer' => $form->getUri()], RequestOptions::FORM_PARAMS => $form->getPhpValues()]);
             }
             return false;
         } catch (\Exception $e) {
             throw new OxygenPageNotFoundException();
         }
     })->then(function ($result) {
         if (!$result instanceof ResponseInterface) {
             // Module was already disconnected.
             return false;
         }
         // Module was successfully disconnected.
         return true;
     });
 }
コード例 #21
0
ファイル: Api2Gis.php プロジェクト: akeinhell/2gis-api
 /**
  * Выполнение ассинхронных запросов
  * @param $requests
  * @return GisResponse[]
  * @throws GisRequestException
  */
 public function getAsync($requests)
 {
     $result = [];
     $index = 0;
     // разбиваем по 10 запросов
     foreach (array_chunk($requests, 10) as $chunk) {
         $promises = [];
         foreach ($chunk as $request) {
             /** @var $params BaseParams */
             $params = $request['params'];
             $params->setKey($this->apiKey);
             $promises[$index] = $this->client->getAsync($request['url'], ['query' => $params->toArray()]);
             $index++;
         }
         foreach (Promise\unwrap($promises) as $i => $response) {
             $result[$i] = $this->formatResponse($response);
         }
         //Пауза нужна, иначе блочат ключ
         // @todo продумать задержки :-(
         sleep(1);
     }
     return $result;
 }
コード例 #22
0
    /**
     * @test
     */
    public function histogramsShouldIncrementAtomically()
    {
        $start = microtime(true);
        $promises = [$this->client->getAsync('/examples/some_histogram.php?c=0&adapter=' . $this->adapter), $this->client->getAsync('/examples/some_histogram.php?c=1&adapter=' . $this->adapter), $this->client->getAsync('/examples/some_histogram.php?c=2&adapter=' . $this->adapter), $this->client->getAsync('/examples/some_histogram.php?c=3&adapter=' . $this->adapter), $this->client->getAsync('/examples/some_histogram.php?c=4&adapter=' . $this->adapter), $this->client->getAsync('/examples/some_histogram.php?c=5&adapter=' . $this->adapter), $this->client->getAsync('/examples/some_histogram.php?c=6&adapter=' . $this->adapter), $this->client->getAsync('/examples/some_histogram.php?c=7&adapter=' . $this->adapter), $this->client->getAsync('/examples/some_histogram.php?c=8&adapter=' . $this->adapter), $this->client->getAsync('/examples/some_histogram.php?c=9&adapter=' . $this->adapter)];
        Promise\settle($promises)->wait();
        $end = microtime(true);
        echo "\ntime: " . ($end - $start) . "\n";
        $metricsResult = $this->client->get('/examples/metrics.php?adapter=' . $this->adapter);
        $body = (string) $metricsResult->getBody();
        $this->assertThat($body, $this->stringContains(<<<EOF
test_some_histogram_bucket{type="blue",le="0.1"} 1
test_some_histogram_bucket{type="blue",le="1"} 2
test_some_histogram_bucket{type="blue",le="2"} 3
test_some_histogram_bucket{type="blue",le="3.5"} 4
test_some_histogram_bucket{type="blue",le="4"} 5
test_some_histogram_bucket{type="blue",le="5"} 6
test_some_histogram_bucket{type="blue",le="6"} 7
test_some_histogram_bucket{type="blue",le="7"} 8
test_some_histogram_bucket{type="blue",le="8"} 9
test_some_histogram_bucket{type="blue",le="9"} 10
test_some_histogram_bucket{type="blue",le="+Inf"} 10
test_some_histogram_count{type="blue"} 10
test_some_histogram_sum{type="blue"} 45
EOF
));
    }
コード例 #23
0
ファイル: Api.php プロジェクト: TorbenKoehn/gw2-php
 public function download($uri, $bodyAsString = false)
 {
     $key = 'gw2php-' . sha1($uri) . '-dl.cache';
     $path = $this->_options['cacheDirectory'] . '/' . $key;
     if (!file_exists($path) || time() - filemtime($path) > $this->_options['cacheLifeTime']) {
         $client = new Client();
         $fp = fopen($path, 'w+');
         $response = $client->getAsync($uri, ['verify' => false, 'save_to' => $fp])->wait();
         $body = $response->getBody();
         fclose($fp);
     }
     return $bodyAsString ? file_get_contents($path) : fopen($path, 'r');
 }
コード例 #24
0
ファイル: index.php プロジェクト: shinji62/php-guzzle
<?php

require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
$client = new Client();
// Initiate each request but do not block
$promises = ['yahoo' => $client->getAsync('http://www.yahoo.co.jp/'), 'passmarket' => $client->getAsync('http://passmarket.yahoo.co.jp/')];
// Wait on all of the requests to complete.
$results = Promise\unwrap($promises);
echo $results['yahoo']->getBody();
echo $results['passmarket']->getBody();
コード例 #25
0
 /**
  * @Rest\Get(
  *     "/{country}/multi",
  *     name="search_multi"
  * )
  *
  * @Rest\QueryParam(
  *   name="search-string",
  *   nullable=false,
  *   description="Search string"
  * )
  *
  * @Rest\QueryParam(
  *   name="lon",
  *   nullable=true,
  *   description="Longitude"
  * )
  *
  * @Rest\QueryParam(
  *   name="lat",
  *   nullable=true,
  *   description="Latitude"
  * )
  *
  * @ApiDoc(
  *   section="Search",
  *   description="Search all",
  *   statusCodes = {
  *     200 = "Search results"
  *   },
  *   requirements={
  *     {
  *       "name"="country",
  *       "dataType"="string",
  *       "description"="ISO Code of country"
  *     }
  *   },
  *   tags={
  *       "stable" = "green"
  *   }
  * )
  *
  * @param $country
  * @param ParamFetcherInterface $paramFetcher
  *
  * @return array
  *
  * @throws NoSearchStringProvidedException
  */
 public function multiSearchAction($country, ParamFetcherInterface $paramFetcher) : array
 {
     $keywords = KeywordsParser::parse($paramFetcher->get('search-string'));
     if (empty($keywords)) {
         throw new NoSearchStringProvidedException();
     }
     $request = $this->get('request_stack')->getCurrentRequest();
     $client = new Client(['base_uri' => $request->getSchemeAndHttpHost()]);
     $params = ['country' => $country, 'search-string' => $paramFetcher->get('search-string')];
     if ($paramFetcher->get('lat') && $paramFetcher->get('lon')) {
         $params = array_merge($params, ['lon' => $paramFetcher->get('lon'), 'lat' => $paramFetcher->get('lat')]);
     }
     $promises = ['elects' => $client->getAsync($this->generateUrl('search_elect', $params), ['decode_content' => 'gzip']), 'zones' => $client->getAsync($this->generateUrl('search_zone', $params), ['decode_content' => 'gzip'])];
     /** @var Response[] $results */
     $results = Promise\unwrap($promises);
     return ['elects' => json_decode($results['elects']->getBody()->getContents(), true), 'zones' => json_decode($results['zones']->getBody()->getContents(), true)];
 }