answear / luigis-box-bundle
Luigi's Box integration for Symfony.
Installs: 23 723
Dependents: 0
Suggesters: 0
Security: 0
Stars: 6
Watchers: 5
Forks: 2
Open Issues: 0
Type:symfony-bundle
Requires
- php: ^8.2
- ext-json: *
- guzzlehttp/guzzle: ^6.0|^7.0
- symfony/http-kernel: ^6.0|^7.0
- symfony/property-access: ^6.0|^7.0
- symfony/serializer: ^6.0|^7.0
- symfony/validator: ^6.0|^7.0
- webmozart/assert: ^1.11
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.64
- matthiasnoback/symfony-config-test: ^5.2
- phpro/grumphp: ^2.8
- phpstan/phpstan: ^1.12
- phpstan/phpstan-webmozart-assert: ^1.2
- phpunit/phpunit: ^10.5
- roave/security-advisories: dev-master
- symfony/phpunit-bridge: ^6.1|^7.0
README
Luigi's Box integration for Symfony. Luigi's Box documentation can be found here: https://live.luigisbox.com/.
Installation
- install with Composer
composer require answear/luigis-box-bundle
Setup
- provide required config data:
publicKey
andprivateKey
searchCacheTtl
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();
Dynamic configurations
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(...));
Usage
Content requests
- Full content update document
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);
- Change availability
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,ServiceUnavailableException
Consider 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 }
Content response
\Answear\LuigisBoxBundle\Response\ApiResponse
:
- (bool)
$success
-true
if all documents will be passed successfully, - (int)
$okCount
- number of successfully passed documents, - (int)
$errorsCount
- number of failed documents, - (array)
$errors
- array of\Answear\LuigisBoxBundle\Response\ApiResponseError
objects, - (array)
$rawResponse
- decoded response from api.
ApiResponseError
:
- (string)
$url
- url of document - (string)
$type
- type of error (ex.malformed_input
) - (string)
$reason
- failure text (ex.incorrect object format
) - (array|null)
$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.
Searching (documentation here)
- Request
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.
- Response
SearchRequest::search()
will return a SearchResponse
object with following fields:
- (string) $searchUrl
- (string) $query
- (string|null) $correctedQuery
- (array) $filters
- (Hit[]) $hits.
Hit
:- (string) $url;
- (array) $attributes;
- (array) $nested;
- (string) $type;
- (array) $highlight;
- (bool) $exact;
- (bool) $alternative;
- (Hit[]) $quickSearchHits
- like above
- (Facet[]) $facets.
Facet
:- (string) $name;
- (string) $type;
- (array) $values;
- (int) $totalHits
- (int) $currentSize
Update by query (documentation here)
- Update
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();
- Retrieve job status
use Answear\LuigisBoxBundle\ValueObject\UpdateByQuery; $jobId = 1; /** @var \Answear\LuigisBoxBundle\Service\UpdateByQueryRequest $request **/ $response = $request->getStatus($jobId);
getStatus
will return UpdateByQueryStatusResponse
with following fields:
- (array) $rawResponse
- (string) $trackerId
- (bool) $completed
- (int|null) $okCount - null if not completed
- (int|null) $errorsCount - null if not completed
- (ApiResponseError[]|null) $errors - null if not completed
Final notes
Feel free to make pull requests with new features, improvements or bug fixes. The Answear team will be grateful for any comments.
Have fun!