answear/luigis-box-bundle
Symfony bundle for integrating Luigi's Box search and content updates. Configure public/private keys, hosts, timeouts, cache TTL, multiple or dynamic configs and custom headers, then send content updates and search requests through simple services.
Luigi's Box integration for Symfony. Luigi's Box documentation can be found here: https://live.luigisbox.com/.
composer require answear/luigis-box-bundle
publicKey and privateKeysearchCacheTtl is time to live for Luigi cache request in seconds (max 300 seconds - this is Luigi's Box limit)# config/packages/answear_luigis_box.yaml
answear_luigis_box:
default_config: second_config_name
configs:
your_config_name:
host: 'https://live.luigisbox.com' #default
publicKey: 'your_public_key'
privateKey: 'your_private_key'
connectionTimeout: 4.0 #default
requestTimeout: 10.0 #default
searchTimeout: 6.0 #default
searchCacheTtl: 0 #default
second_config_name:
publicKey: 'your_public_key'
privateKey: 'your_private_key'
If you have only one config you can omit default_config node.
Configs will be passed to \Answear\LuigisBoxBundle\Service\ConfigProvider class.
If you have more configurations you can change them as follows
use Answear\LuigisBoxBundle\Service\ConfigProvider;
/** @var ConfigProvider $configProvider **/
$configProvider->setConfig('your_config_name');
and use application as before.
If you need to pass custom headers to search request do it as follows
use Answear\LuigisBoxBundle\Service\ConfigProvider;
/** @var ConfigProvider $configProvider **/
$configProvider->setHeader('header-name', 'header-value');
/* reset all headers */
$configProvider->resetHeaders();
You can pass additional configuration.
use Answear\LuigisBoxBundle\DTO\ConfigDTO;
use Answear\LuigisBoxBundle\Service\ConfigProvider;
/** @var ConfigProvider $configProvider **/
$configProvider->addConfig('your_config_name', new ConfigDTO(...));
use Answear\LuigisBoxBundle\ValueObject\ContentUpdate;
use Answear\LuigisBoxBundle\ValueObject\ContentUpdateCollection;
// ...
$collection = new ContentUpdateCollection([new ContentUpdate('product title', 'product/url', 'object type', ['field' => 'field 1'])]);
/** @var \Answear\LuigisBoxBundle\Service\RequestInterface $request **/
$apiResponse = $request->contentUpdate($collection);
First argument ($title) will be used as product's title in Luigi's Box unless a title field is present in the $fields argument.
use Answear\LuigisBoxBundle\ValueObject\ContentUpdateCollection;
use Answear\LuigisBoxBundle\ValueObject\PartialContentUpdate;
// ...
$collection = new ContentUpdateCollection([new PartialContentUpdate('product/url', 'object type', ['title' => 'product title'])]);
/** @var \Answear\LuigisBoxBundle\Service\RequestInterface $request **/
$apiResponse = $request->partialContentUpdate($collection);
use Answear\LuigisBoxBundle\ValueObject\ContentRemoval;
use Answear\LuigisBoxBundle\ValueObject\ContentRemovalCollection;
// ...
$collection = new ContentRemovalCollection([new ContentRemoval('product/url', 'product')]);
/** @var \Answear\LuigisBoxBundle\Service\RequestInterface $request **/
$apiResponse = $request->contentRemoval($collection);
Additional method to simply enable/disable objects - partial update will be used.
use Answear\LuigisBoxBundle\ValueObject\ContentAvailability;
use Answear\LuigisBoxBundle\ValueObject\ContentAvailabilityCollection;
// ...
$isAvailable = true;
$collection = new ContentAvailabilityCollection([new ContentAvailability('product/url', $isAvailable)]);
/** @var \Answear\LuigisBoxBundle\Service\RequestInterface $request **/
$apiResponse = $request->changeAvailability($collection);
// ... or pass one object
$isAvailable = true;
/** @var \Answear\LuigisBoxBundle\Service\RequestInterface $request **/
$apiResponse = $request->changeAvailability(new ContentAvailability('product/url', $isAvailable));
In all request you can catch some exceptions:
BadRequestException - bad request,TooManyItemsException - make request with fewer items,MalformedResponseException - something went wrong with Luigi's Box api response,TooManyRequestsException - delay request rate,ServiceUnavailableExceptionConsider catching them separately:
use Answear\LuigisBoxBundle\Exception\BadRequestException;
use Answear\LuigisBoxBundle\Exception\TooManyItemsException;
use Answear\LuigisBoxBundle\Exception\MalformedResponseException;
use Answear\LuigisBoxBundle\Exception\TooManyRequestsException;
use Answear\LuigisBoxBundle\Exception\ServiceUnavailableException;
try {
// ... request
} catch (BadRequestException $exception){
//bad request
$request = $exception->request;
$response = $exception->response;
} catch (TooManyItemsException $exception){
//items limit reached
$limit = $exception->limit;
} catch (MalformedResponseException $exception){
//bad response
$response = $exception->response;
} catch (TooManyRequestsException $exception){
//repeat request after $retryAfter seconds
$retryAfter = $exception->retryAfterSeconds;
} catch (ServiceUnavailableException $exception){
//delay request
}
\Answear\LuigisBoxBundle\Response\ApiResponse:
$success - true if all documents will be passed successfully,$okCount - number of successfully passed documents,$errorsCount - number of failed documents,$errors - array of \Answear\LuigisBoxBundle\Response\ApiResponseError objects,$rawResponse - decoded response from api.ApiResponseError:
$url - url of document$type - type of error (ex. malformed_input)$reason - failure text (ex. incorrect object format)$causedBy - specific reason of error (ex. ["url": ["is missing"]])Note!
ApiResponse::$success will be set to false if any of passed documents fails. Check $okCount if you want to know how many documents were updated and $errors to check exactly which documents failed.
use Answear\LuigisBoxBundle\ValueObject\SearchUrlBuilder;
// ...
$page = 3;
$urlBuilder = new SearchUrlBuilder($page);
$urlBuilder
->setQuery('nice top')
->addFilter('type', 'product')
->addFilter('category', 'top')
->addFilter('brand', 'Medicine')
->addFilter('brand', 'Answear')
->addPrefer('brand', 'Answear')
->setSort('size', 'asc');
//the above code produces a url query like `size=10&page=3&q=nice+top&f%5B0%5D=type%3Aproduct&f%5B1%5D=category%3Atop&f%5B2%5D=brand%3AMedicine&f%5B3%5D=brand%3AAnswear&sort=size%3Aasc&prefer%5B0%5D=brand%3AAnswear`
/** @var \Answear\LuigisBoxBundle\Service\SearchRequestInterface $request **/
$searchResponse = $request->search($urlBuilder);
Check the Luigi's Box documentation to find out exact purpose of each field SearchUrlBuilder is exposing.
SearchRequest::search() will return a SearchResponse object with following fields:
Hit:
Facet:
use Answear\LuigisBoxBundle\ValueObject\UpdateByQuery;
// ...
$types = ['product'];
$fields = ['color' => 'green'];
$search = new UpdateByQuery\Search($types, $fields);
$updateFields = ['color' => ['olive', 'emerald']];
$update = new UpdateByQuery\Update($updateFields);
$updateByQuery = new UpdateByQuery($search, $update);
/** @var \Answear\LuigisBoxBundle\Service\UpdateByQueryRequest $request **/
$response = $request->update($updateByQuery);
$jobId = $response->getJobId();
use Answear\LuigisBoxBundle\ValueObject\UpdateByQuery;
$jobId = 1;
/** @var \Answear\LuigisBoxBundle\Service\UpdateByQueryRequest $request **/
$response = $request->getStatus($jobId);
getStatus will return UpdateByQueryStatusResponse with following fields:
Feel free to make pull requests with new features, improvements or bug fixes. The Answear team will be grateful for any comments.
Have fun!
How can I help you explore Laravel packages today?