Skip to content
This repository has been archived by the owner on Aug 13, 2019. It is now read-only.

Commit

Permalink
III-2092 Merge branch 'master' into feature/III-2092
Browse files Browse the repository at this point in the history
* master: (22 commits)
  III-2081: Revert udb3-search dependency after merge
  III-2081: Rename OfferSearchParameters::withRegion() to withRegions()
  III-2081: Grab multiple region ids from search parameters
  III-2095 Update the cultuurnet/hydra dependency.
  III-2095 Use the settle method in combinatie with wait to execute the promises.
  III-2095 Remove unused variable.
  III-2095 Remove obsolete use statements.
  Revert dependencies after merge of III-2091
  III-2091 Rename CreatedBy to Creator to match JSON-LD naming.
  III-2091 Extract createdBy parameter from query parameters.
  III-2095: Add a paged collection factory that embeds json-ld based on @id
  III-2095: Remove conditional embed parameter from controller and factories
  III-2095: Update cultuurnet/hydra dependency
  III-2091 Update the cultuurnet/udb3-search dependency.
  III-2065 Update the cultuurnet/udb3-search dependency.
  Revert udb3-search dependency after merge of III-2073
  III-2073: Improve readability for toggle parameters
  III-2073: Improve the parsing of query parameters as boolean values
  III-2073 Extract uitpas toggle from query parameters.
  III-2073 Update the cultuurnet/udb3-search dependency.
  ...
  • Loading branch information
Luc Wollants committed May 17, 2017
2 parents b02d6f9 + ad24e5b commit be4eed0
Show file tree
Hide file tree
Showing 10 changed files with 677 additions and 282 deletions.
145 changes: 145 additions & 0 deletions src/JsonLdEmbeddingPagedCollectionFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?php

namespace CultuurNet\UDB3\Search\Http;

use CultuurNet\Hydra\PagedCollection;
use CultuurNet\UDB3\Search\PagedResultSet;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;

class JsonLdEmbeddingPagedCollectionFactory implements PagedCollectionFactoryInterface
{
/**
* @var PagedCollectionFactoryInterface
*/
private $pagedCollectionFactory;

/**
* @var ClientInterface
*/
private $httpClient;

/**
* @var LoggerInterface
*/
private $logger;

/**
* @param PagedCollectionFactoryInterface $pagedCollectionFactory
* @param ClientInterface $httpClient
* @param LoggerInterface $logger
*/
public function __construct(
PagedCollectionFactoryInterface $pagedCollectionFactory,
ClientInterface $httpClient,
LoggerInterface $logger
) {
$this->pagedCollectionFactory = $pagedCollectionFactory;
$this->httpClient = $httpClient;
$this->logger = $logger;
}

/**
* @param PagedResultSet $pagedResultSet
* @param int $start
* @param int $limit
* @return PagedCollection
*/
public function fromPagedResultSet(
PagedResultSet $pagedResultSet,
$start,
$limit
) {
$pagedCollection = $this->pagedCollectionFactory->fromPagedResultSet($pagedResultSet, $start, $limit);
$members = $pagedCollection->getMembers();

$promises = $this->getJsonLdRequestPromises($members);

$jsonLdBodies = [];

$results = \GuzzleHttp\Promise\settle($promises)->wait();

foreach ($results as $key => $result) {
switch ($result['state']) {
case Promise::FULFILLED:
/** @var ResponseInterface $response */
$response = $result['value'];
$jsonLdBodies[] = json_decode($response->getBody());
break;

default:
$this->logClientException($result['reason']);
break;
}
}

$merged = $this->mergeResults($members, $jsonLdBodies);

return $pagedCollection->withMembers($merged);
}

/**
* @param \stdClass[] $members
* @return PromiseInterface[]
*/
private function getJsonLdRequestPromises(array $members)
{
$promises = [];

foreach ($members as $body) {
if (isset($body->{'@id'})) {
$promises[$body->{'@id'}] = $this->httpClient->requestAsync(
'GET',
$body->{'@id'}
);
}
}

return $promises;
}

/**
* @param array $originalResults
* @param array $jsonLdResults
* @return array
*/
private function mergeResults(array $originalResults, array $jsonLdResults)
{
$mergedResults = $originalResults;

foreach ($jsonLdResults as $jsonLd) {
if (!isset($jsonLd->{'@id'})) {
continue;
}

$mergedResults = array_map(
function ($result) use ($jsonLd) {
if (isset($result->{'@id'}) && $result->{'@id'} == $jsonLd->{'@id'}) {
return $jsonLd;
} else {
return $result;
}
},
$mergedResults
);
}

return $mergedResults;
}

/**
* @param ClientException $exception
*/
private function logClientException(ClientException $exception)
{
$url = (string) $exception->getRequest()->getUri();
$code = (string) $exception->getResponse()->getStatusCode();
$message = "Could not embed document from url {$url}, received error code {$code}.";

$this->logger->error($message);
}
}
114 changes: 94 additions & 20 deletions src/OfferSearchController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use CultuurNet\UDB3\Label\ValueObjects\LabelName;
use CultuurNet\UDB3\Language;
use CultuurNet\UDB3\PriceInfo\Price;
use CultuurNet\UDB3\Search\Creator;
use CultuurNet\UDB3\Search\DistanceFactoryInterface;
use CultuurNet\UDB3\Search\GeoDistanceParameters;
use CultuurNet\UDB3\Search\Offer\AudienceType;
Expand All @@ -15,11 +16,14 @@
use CultuurNet\UDB3\Search\Offer\FacetName;
use CultuurNet\UDB3\Search\Offer\OfferSearchParameters;
use CultuurNet\UDB3\Search\Offer\OfferSearchServiceInterface;
use CultuurNet\UDB3\Search\Offer\SortBy;
use CultuurNet\UDB3\Search\Offer\Sorting;
use CultuurNet\UDB3\Search\Offer\WorkflowStatus;
use CultuurNet\UDB3\Search\Offer\TermId;
use CultuurNet\UDB3\Search\Offer\TermLabel;
use CultuurNet\UDB3\Search\QueryStringFactoryInterface;
use CultuurNet\UDB3\Search\Region\RegionId;
use CultuurNet\UDB3\Search\SortOrder;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
Expand Down Expand Up @@ -91,7 +95,7 @@ public function __construct(
PagedCollectionFactoryInterface $pagedCollectionFactory = null
) {
if (is_null($pagedCollectionFactory)) {
$pagedCollectionFactory = new PagedCollectionFactory();
$pagedCollectionFactory = new ResultSetMappingPagedCollectionFactory();
}

$this->searchService = $searchService;
Expand All @@ -112,11 +116,6 @@ public function search(Request $request)
$start = (int) $request->query->get('start', 0);
$limit = (int) $request->query->get('limit', 30);

// The embed option is returned as a string, and casting "false" to a
// boolean returns true, so we have to do some extra conversion.
$embedParameter = $request->query->get('embed', false);
$embed = $this->getStringAsBoolean($embedParameter);

if ($limit == 0) {
$limit = 30;
}
Expand Down Expand Up @@ -177,11 +176,12 @@ public function search(Request $request)
);
}

if (!empty($request->query->get('regionId'))) {
$parameters = $parameters->withRegion(
new RegionId($request->query->get('regionId')),
$regionIds = $this->getRegionIdsFromQuery($request, 'regions');
if (!empty($regionIds)) {
$parameters = $parameters->withRegions(
$this->regionIndexName,
$this->regionDocumentType
$this->regionDocumentType,
...$regionIds
);
}

Expand Down Expand Up @@ -264,11 +264,14 @@ public function search(Request $request)
);
}

$mediaObjectsToggle = $request->query->get('hasMediaObjects', null);
$mediaObjectsToggle = $this->castMixedToBool($request->query->get('hasMediaObjects', null));
if (!is_null($mediaObjectsToggle)) {
$parameters = $parameters->withMediaObjectsToggle(
$this->getStringAsBoolean($mediaObjectsToggle)
);
$parameters = $parameters->withMediaObjectsToggle($mediaObjectsToggle);
}

$uitpasToggle = $this->castMixedToBool($request->query->get('uitpas', null));
if (!is_null($uitpasToggle)) {
$parameters = $parameters->withUitpasToggle($uitpasToggle);
}

if ($request->query->get('calendarType')) {
Expand Down Expand Up @@ -347,13 +350,23 @@ public function search(Request $request)
$parameters = $parameters->withFacets(...$facets);
}

if ($request->query->get('creator')) {
$parameters = $parameters->withCreator(
new Creator($request->query->get('creator'))
);
}

$sorting = $this->getSortingFromQuery($request, 'sort');
if (!empty($sorting)) {
$parameters = $parameters->withSorting(...$sorting);
}

$resultSet = $this->searchService->search($parameters);

$pagedCollection = $this->pagedCollectionFactory->fromPagedResultSet(
$resultSet,
$start,
$limit,
$embed
$limit
);

$jsonArray = $pagedCollection->jsonSerialize();
Expand All @@ -371,12 +384,16 @@ public function search(Request $request)
}

/**
* @param string $string
* @return bool
* @param mixed $mixed
* @return bool|null
*/
private function getStringAsBoolean($string)
private function castMixedToBool($mixed)
{
return filter_var($string, FILTER_VALIDATE_BOOLEAN);
if (is_null($mixed) || (is_string($mixed) && empty($mixed))) {
return null;
}

return filter_var($mixed, FILTER_VALIDATE_BOOLEAN);
}

/**
Expand Down Expand Up @@ -513,6 +530,63 @@ function ($value) {
);
}

/**
* @param Request $request
* @param string $queryParameter
* @return RegionIds[]
*/
private function getRegionIdsFromQuery(Request $request, $queryParameter)
{
return $this->getArrayFromQueryParameters(
$request,
$queryParameter,
function ($value) {
return new RegionId($value);
}
);
}

/**
* @param Request $request
* @param string $queryParameter
* @return Sorting[]
* @throws \InvalidArgumentException
*/
private function getSortingFromQuery(Request $request, $queryParameter)
{
$sorting = $request->query->get($queryParameter, []);

if (!is_array($sorting)) {
throw new \InvalidArgumentException('Invalid sorting syntax given.');
}

foreach ($sorting as $field => $order) {
if (is_int($field)) {
throw new \InvalidArgumentException('Sort field missing.');
}

if (empty($order)) {
throw new \InvalidArgumentException('Sort order missing.');
}

try {
$sortBy = SortBy::get($field);
} catch (\InvalidArgumentException $e) {
throw new \InvalidArgumentException("Invalid sort field '{$field}' given.");
}

try {
$sortOrder = SortOrder::get($order);
} catch (\InvalidArgumentException $e) {
throw new \InvalidArgumentException("Invalid sort order '{$order}' given.");
}

$sorting[$field] = new Sorting($sortBy, $sortOrder);
}

return array_values($sorting);
}

/**
* @param Request $request
* @param string $queryParameter
Expand Down
5 changes: 2 additions & 3 deletions src/OrganizerSearchController.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function __construct(
PagedCollectionFactoryInterface $pagedCollectionFactory = null
) {
if (is_null($pagedCollectionFactory)) {
$pagedCollectionFactory = new PagedCollectionFactory();
$pagedCollectionFactory = new ResultSetMappingPagedCollectionFactory();
}

$this->searchService = $searchService;
Expand Down Expand Up @@ -78,8 +78,7 @@ public function search(Request $request)
$pagedCollection = $this->pagedCollectionFactory->fromPagedResultSet(
$resultSet,
$start,
$limit,
$embed
$limit
);

return (new JsonResponse($pagedCollection, 200, ['Content-Type' => 'application/ld+json']))
Expand Down
Loading

0 comments on commit be4eed0

Please sign in to comment.