commit 747456f6f525b6e458047aa3f6876b9bb277dd4e Author: ionHaze Date: Thu Dec 26 17:47:33 2019 +0300 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..65fc6d3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/*.sublime* +/vendor \ No newline at end of file diff --git a/Command/StatusesCommand.php b/Command/StatusesCommand.php new file mode 100644 index 0000000..3168b18 --- /dev/null +++ b/Command/StatusesCommand.php @@ -0,0 +1,99 @@ +setName('statuses:update') + ->setDescription('Update statuses') + ->addArgument('accountId', InputArgument::OPTIONAL, 'Choose account, or make it for all'); + } + + public function __construct(ModuleManagerInterface $moduleManager, AccountManager $accountManager) + { + $this->moduleManager = $moduleManager; + $this->accountManager = $accountManager; + + parent::__construct(); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + if (!$this->lock()) { + $output->writeln('The command is already running in another process.'); + + return 0; + } + + $accountId = $input->getArgument('accountId') + ? (int) $input->getArgument('accountId') + : null; + + $paginator = []; + if (null !== $accountId) { + $paginator = [$this->accountManager - find($accountId)]; + } else { + $accountQuery = $this->accountManager->getRepository() + ->createQueryBuilder('account') + ->where('account.active = true') + ->andWhere('account.freeze != true') + ->addOrderBy('account.id') + ->getQuery() + ->setFirstResult(0) + ->setMaxResults(100); + $paginator = new Paginator($accountQuery); + } + + $count = 0; + foreach ($paginator as $account) { + try { + $count += $this->moduleManager + ->setAccount($account) + ->updateStatuses() + ; + } catch (AbstractModuleException $e) { + $output->writeln( + "Failed to update statuses for account {$account->getCrmUrl()}[{$account->getId()}]" + ); + $output->writeln("Error: {$e->getMessage()}"); + } + } + + $output->writeln("{$count} statuses updated."); + + $this->release(); + + return 0; + } +} diff --git a/Command/UpdateModuleCommand.php b/Command/UpdateModuleCommand.php new file mode 100644 index 0000000..a5e6632 --- /dev/null +++ b/Command/UpdateModuleCommand.php @@ -0,0 +1,99 @@ +setName('module:update') + ->setDescription('Update module') + ->addArgument('accountId', InputArgument::OPTIONAL, 'Choose account, or make it for all'); + } + + public function __construct(ModuleManagerInterface $moduleManager, AccountManager $accountManager) + { + $this->moduleManager = $moduleManager; + $this->accountManager = $accountManager; + + parent::__construct(); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + if (!$this->lock()) { + $output->writeln('The command is already running in another process.'); + + return 0; + } + + $accountId = $input->getArgument('accountId') + ? $input->getArgument('accountId') + : null; + + $paginator = []; + if (null !== $accountId) { + $paginator = [$this->accountManager->find($accountId)]; + } else { + $accountQuery = $this->accountManager->getRepository() + ->createQueryBuilder('account') + ->where('account.active = true') + ->andWhere('account.freeze != true') + ->addOrderBy('account.id') + ->getQuery() + ->setFirstResult(0) + ->setMaxResults(100); + $paginator = new Paginator($accountQuery); + } + + $count = 0; + foreach ($paginator as $account) { + try { + $this->moduleManager + ->setAccount($account) + ->updateModuleConfiguration() + ; + ++$count; + } catch (\Exception $e) { + $output->writeln( + "Failed to update configuration for account {$account->getCrmUrl()}[{$account->getId()}]" + ); + $output->writeln("Error: {$e->getMessage()}"); + } + } + + $output->writeln("{$count} modules updated."); + + $this->release(); + + return 0; + } +} diff --git a/Controller/AdminController.php b/Controller/AdminController.php new file mode 100644 index 0000000..395421e --- /dev/null +++ b/Controller/AdminController.php @@ -0,0 +1,394 @@ +entityManager = $entityManager; + $this->knpPaginator = $knpPaginator; + $this->openSsl = $openSsl; + $this->flashBag = $flashBag; + } + + /** + * @return string + */ + private function getShortBundle() + { + return strtr('Intaro\DeliveryModuleBundle', ['\\' => '']); + } + + /** + * @return string + */ + private function getNameService() + { + $bundle = explode('\\', 'Intaro\DeliveryModuleBundle'); + + return strtr(end($bundle), ['Bundle' => '']); + } + + /** + * @return Response + */ + public function listAction(Request $request) + { + $clientsQuery = $this->entityManager->createQuery(' + SELECT connection + FROM ' . $this->getConnectionClass() . ' connection + '); + + $pagination = $this->knpPaginator->paginate( + $clientsQuery, + $request->query->getInt('page', 1), + 20 + ); + + return $this->render( + $this->getShortBundle() . ':Connection:list.html.twig', + ['pagination' => $pagination, 'route' => $this->getRoute()] + ); + } + + /** + * @return Response + */ + public function newAction(Request $request) + { + $this->denyAccessUnlessGranted('ROLE_DEVELOPER'); + + $connectionClass = $this->getConnectionClass(); + $connection = new $connectionClass(); + $connection->setEncoder($this->openSsl); + $connectionTypeClass = 'Intaro\DeliveryModuleBundle\Form\ConnectionType'; + $form = $this->createForm($connectionTypeClass, $connection, [ + 'container' => $this->container, + 'is_admin' => true, + ]); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $connection->generateClientId(); + $this->actualizeWebhooks($connection); + $this->entityManager->persist($connection); + $this->entityManager->flush(); + + return $this->redirectToRoute($this->getRoute() . '_admin_edit', [ + 'connectionId' => $connection->getId(), + ]); + } + + return $this->render( + $this->getShortBundle() . ':Connection:edit.html.twig', + ['route' => $this->getRoute(), 'form' => $form->createView()] + ); + } + + /** + * @param string $connectionId + * + * @return Response + */ + public function editAction(Request $request, $connectionId) + { + $connection = $this->entityManager + ->getRepository($this->getConnectionClass()) + ->find($connectionId); + if (null === $connection) { + throw $this->createNotFoundException(); + } + + $connectionTypeClass = 'Intaro\DeliveryModuleBundle\Form\ConnectionType'; + $form = $this->createForm($connectionTypeClass, $connection, [ + 'container' => $this->container, + 'is_admin' => true, + ]); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $this->actualizeWebhooks($connection); + $this->entityManager->flush(); + + return $this->redirectToRoute($this->getRoute() . '_admin_edit', [ + 'connectionId' => $connection->getId(), + ]); + } + + return $this->render( + $this->getShortBundle() . ':Connection:edit.html.twig', + [ + 'route' => $this->getRoute(), + 'connection' => $connection, + 'form' => $form->createView(), + ] + ); + } + + /** + * @param string $connectionId + * + * @return Response + * + * @throws \Exception + */ + public function updateConfigurationAction(Request $request, $connectionId) + { + $this->denyAccessUnlessGranted('ROLE_DEVELOPER'); + + $api = $this->getDeliveryApi(); + + $connection = $this->entityManager + ->getRepository($this->getConnectionClass()) + ->find($connectionId); + + $api->setConnection($connection); + $result = $api->updateConfiguration(); + + if (isset($result['success']) && $result['success']) { + $this->flashBag->add('notice', 'ChangesWereSaved'); + } else { + $this->flashBag->add('error', 'ChangesWereNotSaved'); + } + + return $this->redirectToRoute($this->getRoute() . '_admin_edit', [ + 'connectionId' => $connection->getId(), + ]); + } + + /** + * @return Response + */ + public function parcelListAction(Request $request) + { + $parcelsQuery = $this->entityManager->createQuery(' + SELECT parcel + FROM ' . $this->getParcelClass() . ' parcel + '); + + $pagination = $this->knpPaginator->paginate( + $parcelsQuery, + $request->query->getInt('page', 1), + 20 + ); + + return $this->render( + $this->getShortBundle() . ':Parcel:list.html.twig', + ['route' => $this->getRoute(), 'pagination' => $pagination] + ); + } + + /** + * @return Response + */ + public function parcelNewAction(Request $request) + { + $this->denyAccessUnlessGranted('ROLE_DEVELOPER'); + + $parcelClass = $this->getParcelClass(); + $parcel = new $parcelClass(); + $parcelTypeClass = 'Intaro\DeliveryModuleBundle\Form\ParcelType'; + $form = $this->createForm($parcelTypeClass, $parcel, [ + 'connection_class' => $this->getConnectionClass(), + ]); + + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $this->entityManager->persist($parcel); + $this->entityManager->flush(); + + return $this->redirectToRoute($this->getRoute() . '_admin_parcel_list'); + } + + return $this->render( + $this->getShortBundle() . ':Parcel:edit.html.twig', + ['form' => $form->createView(), 'parcel' => $parcel] + ); + } + + /** + * @param string $parcelId + * + * @return Response + */ + public function parcelEditAction(Request $request, $parcelId) + { + $parcel = $this->entityManager + ->getRepository($this->getParcelClass()) + ->find(['id' => $parcelId]); + + $parcelTypeClass = 'Intaro\DeliveryModuleBundle\Form\ParcelType'; + $form = $this->createForm($parcelTypeClass, $parcel, [ + 'connection_class' => $this->getConnectionClass(), + ]); + + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $this->entityManager->flush(); + + return $this->redirectToRoute($this->getRoute() . '_admin_parcel_list'); + } + + return $this->render( + $this->getShortBundle() . ':Parcel:edit.html.twig', + ['form' => $form->createView(), 'parcel' => $parcel] + ); + } + + /** + * @return Response + * + * @throws \Exception + */ + public function connectAction(Request $request) + { + $api = $this->getDeliveryApi(); + + $referer = $request->headers->get('referer'); + $account = $request->query->get('account'); + $accountUrl = null; + if (!empty($account)) { + $accountUrl = null === parse_url($account, PHP_URL_HOST) + ? null : 'https://' . parse_url($account, PHP_URL_HOST); + } + + if ( + !empty($request->request->get('clientId')) + || !empty($request->attributes->get('clientId')) + ) { + if (!empty($request->request->get('clientId'))) { + $clientId = $request->request->get('clientId'); + } else { + $clientId = $request->attributes->get('clientId'); + } + + $connection = $this->entityManager + ->getRepository($this->getConnectionClass()) + ->findOneBy([ + 'clientId' => $clientId, + ]); + $accountUrl = $connection->getCrmUrl(); + } else { + $class = $this->getConnectionClass(); + $connection = new $class(); + $connection + ->setLanguage($request->getLocale()) + ->setEncoder($this->openSsl); + } + + $connectionTypeClass = 'Intaro\DeliveryModuleBundle\Form\ConnectionType'; + $form = $this->createForm($connectionTypeClass, $connection, [ + 'container' => $this->container, + 'is_admin' => false, + ]); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $connectionIsCreated = true; + if (empty($connection->getClientId())) { + $connection->generateClientId(); + $connectionIsCreated = false; + } + + $api->setConnection($connection); + $this->actualizeWebhooks($connection); + $result = $api->updateConfiguration(); + if (isset($result['success']) && $result['success']) { + if (!$connectionIsCreated) { + $this->entityManager->persist($connection); + } + $this->entityManager->flush(); + + return $this->redirect($connection->getCrmUrl() . '/admin/integration/list'); + } else { + $srcLogo = $request->getUriForPath( + '/bundles/delivery' + . strtolower($this->getNameService()) + . '/images/' + . strtolower($this->getNameService()) + . '.svg' + ); + + return $this->render( + 'DeliveryCoreBundle:Connection:configure_error.html.twig', + [ + 'referer' => $referer, + 'errors' => $result, + 'title_delivery' => $this->getNameService(), + 'src_logo_delivery' => $srcLogo, + ] + ); + } + } + + return $this->render( + $this->getShortBundle() . ':Connection:configure.html.twig', + [ + 'route' => $this->getRoute(), + 'form' => $form->createView(), + 'account' => $accountUrl, + ] + ); + } + + /** + * Actualize webhooks. + */ + protected function actualizeWebhooks(Connection $connection) + { + } +} diff --git a/Controller/ApiController.php b/Controller/ApiController.php new file mode 100644 index 0000000..86d6121 --- /dev/null +++ b/Controller/ApiController.php @@ -0,0 +1,462 @@ +jmsSerializer = $jmsSerializer; + $this->moduleManager = $moduleManager; + $this->accountManager = $accountManager; + $this->deliveryOrderManager = $deliveryOrderManager; + } + + public function activity(Request $request): JsonResponse + { + if (!is_string($request->request->get('activity'))) { + return $this->getInvalidResponse('Parameter "activity" must be json', 400); + } + $activity = $request->request->get('activity'); + + try { + $requestModel = $this->jmsSerializer->deserialize( + $activity, + IntegrationModule::class, + 'json', + DeserializationContext::create()->setGroups(['activity']) + ); + } catch (JmsException $e) { + return $this->getInvalidResponse($e->getMessage(), 400); + } + + $this->moduleManager->getAccount()->setActive($requestModel->active); + $this->moduleManager->getAccount()->setFreeze($requestModel->freeze); + + $systemUrl = $request->request->get('systemUrl'); + $this->moduleManager->getAccount()->setCrmUrl($systemUrl); + + $this->accountManager->flush(); + + return $this->getSucessfullResponse(); + } + + public function calculate(Request $request): JsonResponse + { + if (!is_string($request->request->get('calculate'))) { + return $this->getInvalidResponse('Parameter "calculate" must be json', 400); + } + $requestData = $request->request->get('calculate'); + try { + $requestModel = $this->jmsSerializer->deserialize( + $requestData, + RequestCalculate::class, + 'json', + DeserializationContext::create()->setGroups(['get', 'request']) + ); + } catch (JmsException $e) { + return $this->getInvalidResponse($e->getMessage(), 400); + } + + try { + $responseModel = $this->doCalculate($requestModel); + } catch (Exception\ServerUnreachableException $e) { + return $this->getInvalidResponse($e->getMessage(), 521); + } catch (Exception\AbstractModuleException $e) { + return $this->getInvalidResponse($e->getMessage(), 400); + } + + $response = new ResponseCalculateSuccessful($responseModel); + $response->result = $responseModel; + + return $this->getSucessfullResponse($response); + } + + public function save(Request $request): JsonResponse + { + if (!is_string($request->request->get('save'))) { + return $this->getInvalidResponse('Parameter "save" must be json', 400); + } + $requestData = $request->request->get('save'); + try { + $requestModel = $this->jmsSerializer->deserialize( + $requestData, + RequestSave::class, + 'json', + DeserializationContext::create()->setGroups(['get', 'request']) + ); + } catch (JmsException $e) { + return $this->getInvalidResponse($e->getMessage(), 400); + } + if (null === $requestModel->delivery) { + return $this->getInvalidResponse('Invalid request format', 400); + } + + $delivery = $this->deliveryOrderManager->findOneBy([ + 'account' => $this->moduleManager->getAccount(), + 'orderId' => $requestModel->order, + ]); + + // ищем доставки, созданные без заказа в запросе get + if (null === $delivery) { + $delivery = $this->deliveryOrderManager + ->findOneBy([ + 'account' => $this->moduleManager->getAccount(), + 'externalId' => $requestModel->deliveryId, + ]); + } + + try { + $responseModel = $this->doSave($requestModel, $delivery); + } catch (Exception\ServerUnreachableException $e) { + return $this->getInvalidResponse($e->getMessage(), 521); + } catch (Exception\AbstractModuleException $e) { + return $this->getInvalidResponse($e->getMessage(), 400); + } + + if (null === $delivery) { + $delivery = $this->deliveryOrderManager->create(); + } + + $delivery + ->setAccount($this->moduleManager->getAccount()) + ->setOrderId($requestModel->order) + ->setExternalId($responseModel->deliveryId) + ; + if ($responseModel->trackNumber) { + $delivery->setTrackNumber($responseModel->trackNumber); + } + + if (is_array($responseModel->additionalData)) { + foreach ($responseModel->additionalData as $key => $value) { + $setter = 'set' . ucfirst($key); + if (is_callable([$delivery, $setter])) { + $delivery->$setter($value); + } + } + } + + if (empty($delivery->getId())) { + $this->deliveryOrderManager->persist($delivery); + } + $this->deliveryOrderManager->flush(); + + return $this->getSucessfullResponse($responseModel); + } + + public function getDeliveryOrder(Request $request): JsonResponse + { + $externalId = $request->query->get('deliveryId'); + if (null === $externalId || empty($externalId)) { + return $this->getInvalidResponse('DeliveryId is required', 400); + } + + try { + $responseModel = $this->doGet($externalId); + } catch (Exception\ServerUnreachableException $e) { + return $this->getInvalidResponse($e->getMessage(), 521); + } catch (Exception\AbstractModuleException $e) { + return $this->getInvalidResponse($e->getMessage(), 400); + } + + return $this->getSucessfullResponse($responseModel); + } + + public function delete(Request $request): JsonResponse + { + if (!is_string($request->request->get('delete'))) { + return $this->getInvalidResponse('Parameter "delete" must be json', 400); + } + $requestData = $request->request->get('delete'); + try { + $requestModel = $this->jmsSerializer->deserialize( + $requestData, + RequestDelete::class, + 'json', + DeserializationContext::create()->setGroups(['get', 'request']) + ); + } catch (JmsException $e) { + return $this->getInvalidResponse($e->getMessage(), 400); + } + + $delivery = $this->deliveryOrderManager->findOneBy([ + 'account' => $this->moduleManager->getAccount(), + 'externalId' => $requestModel->deliveryId, + ]); + + if (null === $delivery) { + return $this->getInvalidResponse("Delivery '{$requestModel->deliveryId}' not found", 404); + } + + try { + $this->doDelete($requestModel, $delivery); + } catch (Exception\ServerUnreachableException $e) { + return $this->getInvalidResponse($e->getMessage(), 521); + } catch (Exception\AbstractModuleException $e) { + return $this->getInvalidResponse($e->getMessage(), 400); + } + + $this->deliveryOrderManager->remove($delivery); + $this->deliveryOrderManager->flush(); + + return $this->getSucessfullResponse(); + } + + public function shipmentPointList(Request $request): JsonResponse + { + $requestData = json_encode($request->query->all()); + try { + $requestModel = $this->jmsSerializer->deserialize( + $requestData, + RequestShipmentPointList::class, + 'json', + DeserializationContext::create()->setGroups(['get', 'request']) + ); + } catch (JmsException $e) { + return $this->getInvalidResponse($e->getMessage(), 400); + } + + try { + $responseModel = $this->doShipmentPointList($requestModel); + } catch (Exception\ServerUnreachableException $e) { + return $this->getInvalidResponse($e->getMessage(), 521); + } catch (Exception\AbstractModuleException $e) { + return $this->getInvalidResponse($e->getMessage(), 400); + } + + $response = new ResponseShipmentPointListSuccessful($responseModel); + $response->result = $responseModel; + + return $this->getSucessfullResponse($response); + } + + public function print(Request $request): Response + { + if (!is_string($request->request->get('print'))) { + return $this->getInvalidResponse('Parameter "print" must be json', 400); + } + $requestData = $request->request->get('print'); + try { + $requestModel = $this->jmsSerializer->deserialize( + $requestData, + RequestPrint::class, + 'json', + DeserializationContext::create()->setGroups(['get', 'request']) + ); + } catch (JmsException $e) { + return $this->getInvalidResponse($e->getMessage(), 400); + } + + try { + $plateData = $this->doPrint($requestModel); + } catch (Exception\ServerUnreachableException $e) { + return $this->getInvalidResponse($e->getMessage(), 521); + } catch (Exception\NotFoundException $e) { + return $this->getInvalidResponse($e->getMessage(), 404); + } catch (Exception\AbstractModuleException $e) { + return $this->getInvalidResponse($e->getMessage(), 400); + } + + if (count($plateData) > 1) { + $tmpFilename = tempnam(sys_get_temp_dir(), 'zip'); + $labelArchive = new \ZipArchive(); + $labelArchive->open($tmpFilename, \ZipArchive::CREATE); + foreach ($plateData as $fileName => $plate) { + $labelArchive->addFromString($fileName, $plate); + } + $labelArchive->close(); + $contents = file_get_contents($tmpFilename); + unlink($tmpFilename); + + $response = new Response($contents); + $response->headers->set('Content-Type', 'application/zip'); + } else { + $response = new Response(reset($plateData)); + $response->headers->set('Content-Type', 'application/pdf'); + } + + return $response; + } + + public function shipmentSave(Request $request): JsonResponse + { + if (!is_string($request->request->get('shipmentSave'))) { + return $this->getInvalidResponse('Parameter "shipmentSave" must be json', 400); + } + $requestData = $request->request->get('shipmentSave'); + try { + $requestModel = $this->jmsSerializer->deserialize( + $requestData, + RequestShipmentSave::class, + 'json', + DeserializationContext::create()->setGroups(['get', 'request']) + ); + } catch (JmsException $e) { + return $this->getInvalidResponse($e->getMessage(), 400); + } + + try { + $responseModel = $this->doShipmentSave($requestModel); + } catch (Exception\ServerUnreachableException $e) { + return $this->getInvalidResponse($e->getMessage(), 521); + } catch (Exception\AbstractModuleException $e) { + return $this->getInvalidResponse($e->getMessage(), 400); + } + + return $this->getSucessfullResponse($responseModel); + } + + public function shipmentDelete(Request $request): JsonResponse + { + if (!is_string($request->request->get('shipmentDelete'))) { + return $this->getInvalidResponse('Parameter "shipmentDelete" must be json', 400); + } + $requestData = $request->request->get('shipmentDelete'); + try { + $requestModel = $this->jmsSerializer->deserialize( + $requestData, + RequestShipmentDelete::class, + 'json', + DeserializationContext::create()->setGroups(['get', 'request']) + ); + } catch (JmsException $e) { + return $this->getInvalidResponse($e->getMessage(), 400); + } + + try { + $this->doShipmentDelete($requestModel); + } catch (Exception\ServerUnreachableException $e) { + return $this->getInvalidResponse($e->getMessage(), 521); + } catch (Exception\AbstractModuleException $e) { + return $this->getInvalidResponse($e->getMessage(), 400); + } + + return $this->getSucessfullResponse(); + } + + protected function getSucessfullResponse(object $responseResult = null): JsonResponse + { + if (!$responseResult instanceof AbstractResponseSuccessful) { + $response = new ResponseSuccessful(); + $response->result = $responseResult; + } else { + $response = $responseResult; + } + + $responseData = $this->jmsSerializer + ->serialize($response, 'json', SerializationContext::create()->setGroups(['response'])); + + return new JsonResponse(json_decode($responseData, true)); + } + + protected function getInvalidResponse(string $message, int $statusCode): JsonResponse + { + if ($statusCode >= 500) { + //корректно отдается в crm только в окружении prod + throw new SymfonyException\HttpException($statusCode, json_encode(['success' => false, 'errorMsg' => $message])); + } + + return new JsonResponse([ + 'success' => false, + 'errorMsg' => $message, + ], $statusCode); + } + + protected function doCalculate(RequestCalculate $requestModel): array + { + return $this->moduleManager->calculateDelivery($requestModel); + } + + protected function doGet(string $externalId): ResponseLoadDeliveryData + { + return $this->moduleManager->getDelivery($externalId); + } + + protected function doSave(RequestSave $requestModel, DeliveryOrder $delivery = null): ResponseSave + { + return $this->moduleManager->saveDelivery($requestModel, $delivery); + } + + protected function doDelete(RequestDelete $requestModel, DeliveryOrder $delivery): bool + { + return $this->moduleManager->deleteDelivery($requestModel, $delivery); + } + + protected function doShipmentPointList(RequestShipmentPointList $requestModel): array + { + return $this->moduleManager->shipmentPointList($requestModel); + } + + protected function doShipmentSave(RequestShipmentSave $requestModel): ResponseShipmentSave + { + return $this->moduleManager->saveShipment($requestModel); + } + + protected function doShipmentDelete(RequestShipmentDelete $requestModel): bool + { + return $this->moduleManager->deleteShipment($requestModel); + } + + protected function doPrint(RequestPrint $requestModel) + { + return $this->moduleManager->printDocument($requestModel); + } +} diff --git a/Controller/ClientIdSecuredControllerInterface.php b/Controller/ClientIdSecuredControllerInterface.php new file mode 100644 index 0000000..6f7b89d --- /dev/null +++ b/Controller/ClientIdSecuredControllerInterface.php @@ -0,0 +1,7 @@ +getRootNode(); + + $rootNode + ->children() + ->scalarNode('module_manager_class') + ->cannotBeEmpty() + ->end() + ->scalarNode('account_class') + ->isRequired() + ->cannotBeEmpty() + ->end() + ->scalarNode('delivery_order_class') + ->isRequired() + ->cannotBeEmpty() + ->end() + + ->arrayNode('configuration') + ->children() + ->scalarNode('integration_code') + ->cannotBeEmpty() + ->end() + + ->arrayNode('countries') + ->prototype('scalar')->end() + ->requiresAtLeastOneElement() + ->defaultValue(['ru']) + ->end() + + ->arrayNode('locales') + ->requiresAtLeastOneElement() + ->useAttributeAsKey('locale') + + ->arrayPrototype() + ->children() + ->scalarNode('name') + ->isRequired() + ->end() + ->scalarNode('logo') + ->isRequired() + ->end() + ->end() + ->end() + ->end() + + ->variableNode('parameters')->end() + ->end() + ->end() + ->end() + ; + + return $treeBuilder; + } +} diff --git a/DependencyInjection/RetailCrmDeliveryModuleExtension.php b/DependencyInjection/RetailCrmDeliveryModuleExtension.php new file mode 100644 index 0000000..f3a76a9 --- /dev/null +++ b/DependencyInjection/RetailCrmDeliveryModuleExtension.php @@ -0,0 +1,75 @@ +load('services.yaml'); + + $configuration = new Configuration(); + $config = $this->processConfiguration($configuration, $configs); + + $container->setParameter( + 'retailcrm.delivery_module.configuration', + $config['configuration'] + ); + + $moduleManagerClass = $config['module_manager_class']; + if (!class_exists($moduleManagerClass)) { + throw new \InvalidArgumentException("module_manager_class '{$moduleManagerClass}' does not exists"); + } + if (!is_subclass_of($moduleManagerClass, ModuleManagerInterface::class)) { + throw new \InvalidArgumentException("module_manager_class '{$moduleManagerClass}' must implement ModuleManagerInterace"); + } + $container->setParameter( + 'retailcrm.delivery_module.module_manager.class', + $moduleManagerClass + ); + + $accountClass = $config['account_class']; + if (!class_exists($accountClass)) { + throw new \InvalidArgumentException("account_class'] '{$accountClass}' does not exists"); + } + if (!is_subclass_of($accountClass, Account::class)) { + throw new \InvalidArgumentException("account_class '{$accountClass}' must extend " . Account::class); + } + $container->setParameter( + 'retailcrm.delivery_module.account.class', + $accountClass + ); + + $deliveryOrderClass = $config['delivery_order_class']; + if (!class_exists($deliveryOrderClass)) { + throw new \InvalidArgumentException("delivery_order_class'] '{$deliveryOrderClass}' does not exists"); + } + if (!is_subclass_of($deliveryOrderClass, DeliveryOrder::class)) { + throw new \InvalidArgumentException("delivery_order_class '{$deliveryOrderClass}' must extend " . DeliveryOrder::class); + } + $container->setParameter( + 'retailcrm.delivery_module.delivery_order.class', + $config['delivery_order_class'] + ); + } +} diff --git a/EventListener/SerializeListener.php b/EventListener/SerializeListener.php new file mode 100644 index 0000000..3b4b04a --- /dev/null +++ b/EventListener/SerializeListener.php @@ -0,0 +1,27 @@ + Events::PRE_SERIALIZE, 'method' => 'onPreSerialize', 'class' => ResponseResult::class], + ]; + } + + public function onPreSerialize(PreSerializeEvent $event) + { + if (is_object($event->getObject())) { + $event->setType(get_class($event->getObject())); + } else { + $event->setType('string'); + } + } +} diff --git a/EventSubscriber/ClientIdSubscriber.php b/EventSubscriber/ClientIdSubscriber.php new file mode 100644 index 0000000..f6e6439 --- /dev/null +++ b/EventSubscriber/ClientIdSubscriber.php @@ -0,0 +1,78 @@ +accountManager = $accountManager; + $this->moduleManager = $moduleManager; + } + + public static function getSubscribedEvents() + { + return [ + KernelEvents::CONTROLLER => 'onKernelController', + ]; + } + + public function onKernelController(ControllerEvent $event) + { + $controller = $event->getController(); + if (is_array($controller)) { + $controller = $controller[0]; + } + + if (!$controller instanceof ClientIdSecuredControllerInterface) { + return; + } + + $request = $event->getRequest(); + + if ($request->isMethod('post')) { + $clientId = $request->request->get('clientId'); + } else { + $clientId = $request->query->get('clientId'); + } + if (empty($clientId)) { + throw new AccessDeniedHttpException('ClientId required'); + } + + if (!Uuid::isValid($clientId)) { + throw new AccessDeniedHttpException('ClientId is not valid'); + } + + $account = $this->accountManager->findOneBy(['clientId' => $clientId]); + if (null === $account) { + throw new AccessDeniedHttpException('ClientId not found'); + } + if (!$account->isActive()) { + throw new AccessDeniedHttpException('Account is not active'); + } + if ($account->isFreeze()) { + throw new AccessDeniedHttpException('Account is freezed'); + } + + $this->moduleManager->setAccount($account); + } +} diff --git a/EventSubscriber/SerializeListener.php b/EventSubscriber/SerializeListener.php new file mode 100644 index 0000000..9473dfc --- /dev/null +++ b/EventSubscriber/SerializeListener.php @@ -0,0 +1,27 @@ + Events::PRE_SERIALIZE, 'method' => 'onPreSerialize', 'class' => ResponseResult::class], + ]; + } + + public function onPreSerialize(PreSerializeEvent $event) + { + if (is_object($event->getObject())) { + $event->setType(get_class($event->getObject())); + } else { + $event->setType('string'); + } + } +} diff --git a/Exception/AbstractModuleException.php b/Exception/AbstractModuleException.php new file mode 100644 index 0000000..6366946 --- /dev/null +++ b/Exception/AbstractModuleException.php @@ -0,0 +1,7 @@ +add('connectionId', null, [ + 'label' => 'label.connectionId', + 'required' => true, + 'attr' => [ + 'placeholder' => 'label.connectionId' + ] + ]) + ->add('crmKey', null, [ + 'label' => 'label.crmKey', + 'required' => true, + 'attr' => [ + 'placeholder' => 'label.crmKey' + ] + ]); + } +} diff --git a/Form/ConnectionType.php b/Form/ConnectionType.php new file mode 100644 index 0000000..cb38352 --- /dev/null +++ b/Form/ConnectionType.php @@ -0,0 +1,78 @@ +add('crmUrl', TextType::class, [ + 'label' => 'label.crmUrl', + 'required' => true, + 'attr' => [ + 'placeholder' => 'label.crmUrl', + 'pattern' => '^(https?:\/\/)?([\da-z0-9\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$', + ], + 'translation_domain' => 'messages' + ]) + ->add('crmKey', TextType::class, [ + 'label' => 'label.crmKey', + 'required' => true, + 'attr' => [ + 'placeholder' => 'label.crmKey' + ], + 'translation_domain' => 'messages' + ]) + ->add('isActive', CheckboxType::class, [ + 'label' => 'label.isActive', + 'required' => false, + 'translation_domain' => 'messages' + ]) + ->add('language', ChoiceType::class, [ + 'label' => 'label.language', + 'choices' => [ + 'RU' => 'ru', + 'EN' => 'en', + 'ES' => 'es' + ], + 'required' => true, + 'translation_domain' => 'messages' + ]) + ->add('isFreeze', CheckboxType::class, [ + 'label' => 'label.isFreeze', + 'required' => false, + 'translation_domain' => 'messages' + ]); + + if ($options['is_admin']) { + $builder + ->add('debug', CheckboxType::class, [ + 'label' => 'label.debug', + 'required' => false, + 'translation_domain' => 'messages' + ]); + } + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setRequired(['container', 'is_admin']); + } +} diff --git a/Form/ParcelType.php b/Form/ParcelType.php new file mode 100644 index 0000000..5861f7a --- /dev/null +++ b/Form/ParcelType.php @@ -0,0 +1,63 @@ +add( + 'connection', + EntityType::class, + [ + 'class' => $options['connection_class'], + 'label' => 'label.connection', + 'translation_domain' => 'messages' + ] + ) + ->add( + 'orderId', + TextType::class, + [ + 'label' => 'label.orderId', + 'translation_domain' => 'messages' + ] + ) + ->add( + 'trackId', + TextType::class, + [ + 'label' => 'label.trackId', + 'translation_domain' => 'messages' + ] + ) + ->add( + 'isClosed', + CheckboxType::class, + [ + 'required' => false, + 'label' => 'label.isClosed', + 'translation_domain' => 'messages' + ] + ); + } + + /** + * {@inheritDoc} + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setRequired(['connection_class']); + } +} diff --git a/Model/AbstractResponseSuccessful.php b/Model/AbstractResponseSuccessful.php new file mode 100644 index 0000000..ece888d --- /dev/null +++ b/Model/AbstractResponseSuccessful.php @@ -0,0 +1,17 @@ +") + */ + public $actions; + + /** + * Допустивые типы плательщиков за доставку. + * + * @var array + * + * @Serializer\Groups({"set", "get"}) + * @Serializer\SerializedName("payerType") + * @Serializer\Type("array") + */ + public $payerType; + + /** + * Максимальное количество заказов при печати документов. + * + * @var int + * + * @Serializer\Groups({"set", "get"}) + * @Serializer\SerializedName("platePrintLimit") + * @Serializer\Type("integer") + */ + public $platePrintLimit = 100; + + /** + * В методе calculate расчитывается стоимость доставки. + * + * @var bool + * + * @Serializer\Groups({"set", "get"}) + * @Serializer\SerializedName("rateDeliveryCost") + * @Serializer\Type("boolean") + */ + public $rateDeliveryCost = true; + + /** + * Разрешить использование упаковок. + * + * @var bool + * + * @Serializer\Groups({"set", "get"}) + * @Serializer\SerializedName("allowPackages") + * @Serializer\Type("boolean") + */ + public $allowPackages = false; + + /** + * Доставка наложенным платежом доступна/не доступна. + * + * @var bool + * + * @Serializer\Groups({"set", "get"}) + * @Serializer\SerializedName("codAvailable") + * @Serializer\Type("boolean") + */ + public $codAvailable = false; + + /** + * Возможен самопривоз на терминал. + * + * @var bool + * + * @Serializer\Groups({"set", "get"}) + * @Serializer\SerializedName("selfShipmentAvailable") + * @Serializer\Type("boolean") + */ + public $selfShipmentAvailable = false; + + /** + * Разрешить отдельно передавать трек номер + * + * @var string + * + * @Serializer\Groups({"set", "get"}) + * @Serializer\SerializedName("allowTrackNumber") + * @Serializer\Type("boolean") + */ + public $allowTrackNumber; + + /** + * Список стран откуда можно отправить посылку. Если массив пустой, то нет ограничения на страны. + * + * @var array + * + * @Serializer\Groups({"set", "get"}) + * @Serializer\SerializedName("availableCountries") + * @Serializer\Type("array") + */ + public $availableCountries; + + /** + * Список обязательных полей заказа. + * + * @var array + * + * @Serializer\Groups({"set", "get"}) + * @Serializer\SerializedName("requiredFields") + * @Serializer\Type("array") + */ + public $requiredFields; + + /** + * Список статусов службы доставки. + * + * @var Status[] + * + * @Serializer\Groups({"set", "get"}) + * @Serializer\SerializedName("statusList") + * @Serializer\Type("array") + */ + public $statusList; + + /** + * Список печатных форм, предоставляемых службой. + * + * @var Plate[] + * + * @Serializer\Groups({"set", "get"}) + * @Serializer\SerializedName("plateList") + * @Serializer\Type("array") + */ + public $plateList; + + /** + * Список дополнительных полей, необходимых для оформления доставки. + * + * @var DeliveryDataField[] + * + * @Serializer\Groups({"set", "get"}) + * @Serializer\SerializedName("deliveryDataFieldList") + * @Serializer\Type("array") + */ + public $deliveryDataFieldList; + + /** + * Список дополнительных полей, необходимых для заявки на отгрузку. + * + * @var DeliveryDataField[] + * + * @Serializer\Groups({"set", "get"}) + * @Serializer\SerializedName("shipmentDataFieldList") + * @Serializer\Type("array") + */ + public $shipmentDataFieldList; +} diff --git a/Model/Contragent.php b/Model/Contragent.php new file mode 100644 index 0000000..26a4e21 --- /dev/null +++ b/Model/Contragent.php @@ -0,0 +1,68 @@ +") + */ + public $phones; + + /** + * E-mail. + * + * @var string + * + * @Serializer\Groups({"get"}) + * @Serializer\SerializedName("email") + * @Serializer\Type("string") + */ + public $email; + + /** + * Данные контрагента. + * + * @var Contragent + * + * @Serializer\Groups({"get"}) + * @Serializer\SerializedName("contragent") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\Model\Contragent") + */ + public $contragent; + + public function getNickName(): ?string + { + $result = trim( + $this->lastName . ' ' . $this->firstName . ' ' . $this->patronymic + ); + + return $result; + } +} diff --git a/Model/DeliveryAddress.php b/Model/DeliveryAddress.php new file mode 100644 index 0000000..8006880 --- /dev/null +++ b/Model/DeliveryAddress.php @@ -0,0 +1,250 @@ +") + * @Serializer\Groups({"set", "get", "orderHistory", "history-reference", "calculate"}) + * @Serializer\Accessor(getter="getFrom", setter="setFrom") + * + * @var \DateTime|null + */ + protected $from; + + /** + * Время доставки "до" + * + * @Serializer\SerializedName("to") + * @Serializer\Type("DateTime<'H:i'>") + * @Serializer\Groups({"set", "get", "orderHistory", "history-reference", "calculate"}) + * @Serializer\Accessor(getter="getTo", setter="setTo") + * + * @var \DateTime|null + */ + protected $to; + + /** + * Время доставки (произвольный текст) + * + * @Serializer\SerializedName("custom") + * @Serializer\Type("string") + * @Serializer\Groups({"set", "get", "orderHistory", "history-reference", "calculate"}) + * + * @var string|null + */ + protected $custom; + + /** + * @param null|string|\DateTime $from + * @param null|string|\DateTime $to + * @param null|string $custom + * + * @return self + */ + public function __construct($from = null, $to = null, $custom = null) + { + $this->setFrom($from); + $this->setTo($to); + $this->setCustom($custom); + } + + /** + * Разбор строки со временем доставки + * + * @param string $time + * + * @return self + */ + public static function fromString($time) + { + $result = new self(); + $result->setString($time); + + return $result; + } + + /** + * @return \DateTime|null + */ + public function getFrom() + { + if ($this->from) { + $this->from->setDate(1970, 01, 01); + + if ('00:00:00' === $this->from->format('H:i:s')) { + return null; + } + } + + return $this->from; + } + + /** + * @param \DateTime|string|null $from + * + * @return $this + */ + public function setFrom($from) + { + $this->from = $this->ensureTime($from); + $this->ensureConsistency(); + + return $this; + } + + /** + * @return \DateTime|null + */ + public function getTo() + { + if ($this->to) { + $this->to->setDate(1970, 01, 01); + + if ('23:59:59' === $this->to->format('H:i:s')) { + return null; + } + } + + return $this->to; + } + + /** + * @param \DateTime|string|null $to + * + * @return $this + */ + public function setTo($to) + { + $this->to = $this->ensureTime($to); + $this->ensureConsistency(); + + return $this; + } + + /** + * @return string + */ + public function getCustom() + { + return $this->custom; + } + + /** + * @param string $custom + * + * @return $this + */ + public function setCustom($custom) + { + $this->custom = $custom; + + return $this; + } + + /** + * @param string $time + * + * @return $this + */ + public function setString($time) + { + // точное время: 12.30, 12:30 + $exactPattern = '/^в?\s*(\d{2}[:\.]\d{2})$/u'; + // диапазон времени: 12-13, c 12.00 по 13:00 + $rangePattern = '/^с?\s*(?P\d{2}[:\.]?\d{0,2})\s*(-|по|до)\s*(?P\d{2}[:\.]?\d{0,2})/u'; + // диапазон времени: c 12.00 + $rangeFromPattern = '/^с?\s*(?P\d{2}[:\.]?\d{0,2})/u'; + // диапазон времени: до 13:00 + $rangeToPattern = '/^(-|по|до)\s*(?P\d{2}[:\.]?\d{0,2})/u'; + + if (preg_match($exactPattern, $time, $matches)) { + $timeObj = new \DateTime($matches[1]); + $this->setFrom(clone $timeObj); + $this->setTo(clone $timeObj); + } elseif (preg_match($rangePattern, $time, $matches)) { + $from = $matches['from']; + $to = $matches['to']; + + $from = preg_match($exactPattern, $from) ? $from : $from . ':00'; + $to = preg_match($exactPattern, $to) ? $to : $to . ':00'; + + try { + $this->setFrom(new \DateTime($from)); + $this->setTo(new \DateTime($to)); + } catch (\Exception $e) { + $this->setFrom(null); + $this->setTo(null); + $this->setCustom($time); + } + } elseif (preg_match($rangeFromPattern, $time, $matches)) { + $from = $matches['from']; + $from = preg_match($exactPattern, $from) ? $from : $from . ':00'; + + try { + $this->setFrom(new \DateTime($from)); + $this->setTo(null); + } catch (\Exception $e) { + $this->setFrom(null); + $this->setTo(null); + $this->setCustom($time); + } + } elseif (preg_match($rangeToPattern, $time, $matches)) { + $to = $matches['to']; + $to = preg_match($exactPattern, $to) ? $to : $to . ':00'; + + try { + $this->setFrom(null); + $this->setTo(new \DateTime($to)); + } catch (\Exception $e) { + $this->setFrom(null); + $this->setTo(null); + $this->setCustom($time); + } + } else { + $this->setFrom(null); + $this->setTo(null); + $this->setCustom($time); + } + + return $this; + } + + /** + * @return string + */ + public function getString() + { + $from = $this->getFrom(); + $to = $this->getTo(); + $custom = $this->getCustom(); + + if (!($from || $to)) { + return (string) $custom; + } + + $fromPrint = $from ? $from->format('H:i') : null; + $toPrint = $to ? $to->format('H:i') : null; + + if ($fromPrint && $fromPrint === $toPrint) { + return 'в ' . $fromPrint; + } + + $str = ''; + if ($fromPrint) { + $str .= 'с ' . $fromPrint; + } + if ($toPrint) { + $str .= ' до ' . $toPrint; + } + + return trim($str); + } + + /** + * Проверяет, соответствует ли время доставки диапазону из настроек + * + * @param array $range + * @return bool + */ + public function equalsRange(array $range) + { + $fromEquals = false; + $toEquals = false; + + $from = $this->getFrom(); + $to = $this->getTo(); + + if ($from) { + if (isset($range['from'])) { + $fromEquals = $from->format('H:i') === $range['from']; + } + } else { + if (!isset($range['from']) || + !$range['from'] || + $range['from'] === '00:00' || + $range['from'] === '00:00:00' + ) { + $fromEquals = true; + } + } + + if ($to) { + if (isset($range['to'])) { + $toEquals = $to->format('H:i') === $range['to']; + } + } else { + if (!isset($range['to']) || + !$range['to'] || + $range['from'] === '23:59' || + $range['from'] === '23:59:59' + ) { + $toEquals = true; + } + } + + return $fromEquals && $toEquals; + } + + /** + * @return bool + */ + public function isEmpty() + { + return !($this->from || $this->to || $this->custom); + } + + /** + * @return string + */ + public function __toString() + { + return $this->getString(); + } + + protected function ensureTime($time) + { + if ($time) { + if (!$time instanceof \DateTime) { + $time = new \DateTime((string) $time); + } + $time->setDate(1970, 01, 01); + } + + return $time; + } + + /** + * Если для времени доставки указана только одна граница диапазона, то присвоим другой значение по умолчанию + */ + protected function ensureConsistency() + { + $from = $this->getFrom(); + $to = $this->getTo(); + + if ($from === null && $to !== null) { + $this->from = new \DateTime('1970-01-01T00:00:00'); + } elseif ($to === null && $from !== null) { + $this->to = new \DateTime('1970-01-01T23:59:59'); + } elseif ($to === null && $from === null) { + $this->to = null; + $this->from = null; + } + } +} diff --git a/Model/Entity/Account.php b/Model/Entity/Account.php new file mode 100644 index 0000000..c3d6e4d --- /dev/null +++ b/Model/Entity/Account.php @@ -0,0 +1,165 @@ +") + */ + protected $createdAt; + + /** + * @var string + * + * @Serializer\Groups({"get", "connect"}) + * @Serializer\Type("string") + */ + protected $crmUrl; + + /** + * @var string + * + * @Serializer\Groups({"get", "connect"}) + * @Serializer\Type("string") + */ + protected $crmApiKey; + + /** + * @var bool + */ + protected $active; + + /** + * @var bool + */ + protected $freeze; + + /** + * @var string + */ + protected $language; + + public function __construct() + { + $this->clientId = Uuid::uuid4(); + $this->createdAt = new \DateTime(); + $this->active = false; + $this->freeze = false; + } + + public function getId(): int + { + return $this->id; + } + + public function setClientId(UuidInterface $clientId): self + { + $this->clientId = $clientId; + + return $this; + } + + public function getClientId(): ?UuidInterface + { + return $this->clientId; + } + + public function getCreatedAt(): \DateTime + { + return $this->createdAt; + } + + public function setCreatedAt(\DateTime $createdAt): self + { + $this->createdAt = $createdAt; + + return $this; + } + + public function getCrmUrl(): ?string + { + return $this->crmUrl; + } + + public function setCrmUrl(?string $crmUrl): self + { + $this->crmUrl = rtrim($crmUrl, '/'); + + return $this; + } + + public function getCrmApiKey(): ?string + { + return $this->crmApiKey; + } + + public function setCrmApiKey(?string $crmApiKey): self + { + $this->crmApiKey = $crmApiKey; + + return $this; + } + + public function setActive(bool $active): self + { + $this->active = $active; + + return $this; + } + + public function isActive(): bool + { + return $this->active; + } + + public function setFreeze(bool $freeze): self + { + $this->freeze = $freeze; + + return $this; + } + + public function isFreeze(): bool + { + return $this->freeze; + } + + /** + * @Serializer\VirtualProperty + * @Serializer\Type("boolean") + * @Serializer\Groups({"get"}) + * @Serializer\SerializedName("isEnabled") + */ + public function isEnabled(): bool + { + return !$this->freeze && $this->active; + } + + public function setLanguage(string $language): self + { + $this->language = $language; + + return $this; + } + + public function getLanguage(): ?string + { + return $this->language; + } +} diff --git a/Model/Entity/DeliveryOrder.php b/Model/Entity/DeliveryOrder.php new file mode 100644 index 0000000..7d84c04 --- /dev/null +++ b/Model/Entity/DeliveryOrder.php @@ -0,0 +1,102 @@ +ended = false; + } + + /** + * @return int + */ + public function getId() + { + return $this->id; + } + + public function setAccount(Account $account): self + { + $this->account = $account; + + return $this; + } + + public function getAccount(): ?Account + { + return $this->account; + } + + public function setOrderId(int $orderId): self + { + $this->orderId = $orderId; + + return $this; + } + + public function getOrderId(): int + { + return $this->orderId; + } + + public function setExternalId(string $externalId): self + { + $this->externalId = $externalId; + + return $this; + } + + public function getExternalId(): string + { + return $this->externalId; + } + + public function setEnded(bool $ended): self + { + $this->ended = $ended; + + return $this; + } + + public function getTrackNumber(): string + { + return $this->externalId; + } + + public function setTrackNumber(string $trackNumber): self + { + return $this; + } + + public function getEnded(): bool + { + return $this->ended; + } +} diff --git a/Model/IntegrationModule.php b/Model/IntegrationModule.php new file mode 100644 index 0000000..0b514c5 --- /dev/null +++ b/Model/IntegrationModule.php @@ -0,0 +1,128 @@ +") + */ + public $actions; + + /** + * Список стран для которых доступен модуль + * @var array + * + * @Serializer\Groups({"set", "get"}) + * @Serializer\SerializedName("availableCountries") + * @Serializer\Type("array") + */ + public $availableCountries; + + /** + * URL настроек модуля + * @var string + * + * @Serializer\Groups({"set", "get"}) + * @Serializer\SerializedName("accountUrl") + * @Serializer\Type("string") + */ + public $accountUrl; + + /** + * Массив конфигураций интеграций + * @var array + * + * @Serializer\Groups({"set", "get"}) + * @Serializer\SerializedName("integrations") + * @Serializer\Type("array") + */ + public $integrations; +} diff --git a/Model/Manager.php b/Model/Manager.php new file mode 100644 index 0000000..e841dc1 --- /dev/null +++ b/Model/Manager.php @@ -0,0 +1,83 @@ +lastName . ' ' . $this->firstName . ' ' . $this->patronymic + ); + + return $result; + } +} diff --git a/Model/Package.php b/Model/Package.php new file mode 100644 index 0000000..2c71742 --- /dev/null +++ b/Model/Package.php @@ -0,0 +1,96 @@ +") + */ + public $items; + + public function __construct($weight = null, $width = null, $length = null, $height = null) + { + $this->weight = $weight; + $this->width = $width; + $this->length = $length; + $this->height = $height; + } + + public function getVolume() + { + if (!is_null($this->length) + && !is_null($this->width) + && !is_null($this->height) + ) { + return $this->length * $this->width * $this->height; + } else { + return false; + } + } + + public static function loadValidatorMetadata(ClassMetadata $metadata) + { + $metadata + ->addPropertyConstraint('weight', new Assert\NotBlank()); + } +} diff --git a/Model/PackageItem.php b/Model/PackageItem.php new file mode 100644 index 0000000..cb01deb --- /dev/null +++ b/Model/PackageItem.php @@ -0,0 +1,107 @@ +") + */ + public $properties; +} diff --git a/Model/PaymentType.php b/Model/PaymentType.php new file mode 100644 index 0000000..e98ebc6 --- /dev/null +++ b/Model/PaymentType.php @@ -0,0 +1,22 @@ +code = $code; + $this->label = $label; + } +} diff --git a/Model/Request/RequestCalculate.php b/Model/Request/RequestCalculate.php new file mode 100644 index 0000000..f0eb59e --- /dev/null +++ b/Model/Request/RequestCalculate.php @@ -0,0 +1,121 @@ +") + */ + public $packages; + + /** + * Объявленная стоимость. + * + * @var float + * + * @Serializer\Groups({"request", "calculate"}) + * @Serializer\SerializedName("declaredValue") + * @Serializer\Type("float") + */ + public $declaredValue; + + /** + * Наложенный платеж. + * + * @var float + * + * @Serializer\Groups({"request", "calculate"}) + * @Serializer\SerializedName("cod") + * @Serializer\Type("float") + */ + public $cod; + + /** + * Плательщик за доставку. + * + * @var string + * + * @Serializer\Groups({"request", "calculate"}) + * @Serializer\SerializedName("payerType") + * @Serializer\Type("string") + */ + public $payerType; + + /** + * Дата доставки. + * + * @var \DateTime + * + * @Serializer\Groups({"request", "calculate"}) + * @Serializer\SerializedName("deliveryDate") + * @Serializer\Type("DateTime<'Y-m-d'>") + */ + public $deliveryDate; + + /** + * Время доставки. + * + * @var DeliveryTime + * + * @Serializer\Groups({"request", "calculate"}) + * @Serializer\SerializedName("deliveryTime") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryTime") + */ + public $deliveryTime; + + /** + * Валюта. + * + * @var string + * + * @Serializer\Groups({"request", "calculate"}) + * @Serializer\SerializedName("currency") + * @Serializer\Type("string") + */ + public $currency; + + /** + * Дополнительные данные доставки. + * + * @var array + * + * @Serializer\Groups({"request", "calculate"}) + * @Serializer\SerializedName("extraData") + * @Serializer\Type("array") + */ + public $extraData; +} diff --git a/Model/Request/RequestDelete.php b/Model/Request/RequestDelete.php new file mode 100644 index 0000000..69f8031 --- /dev/null +++ b/Model/Request/RequestDelete.php @@ -0,0 +1,17 @@ +") + */ + public $packages; + + /** + * Данные доставки + * @var RetailCrm\DeliveryModuleBundle\Model\SaveDeliveryData + * + * @Serializer\Groups({"request"}) + * @Serializer\SerializedName("delivery") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\SaveDeliveryData") + */ + public $delivery; + + /** + * Валюта + * @var string $currency + * + * @Serializer\Groups({"request", "calculate"}) + * @Serializer\SerializedName("currency") + * @Serializer\Type("string") + */ + public $currency; + + public function getFullDeclaredValue() + { + $result = 0; + foreach ($this->packages as $package) { + foreach ($package->items as $item) { + $result += $item->declaredValue * $item->quantity; + } + } + + return $result; + } + + public function getFullItemsCodValue() + { + $result = 0; + foreach ($this->packages as $package) { + foreach ($package->items as $item) { + $result += $item->cod * $item->quantity; + } + } + + return $result; + } +} diff --git a/Model/Request/RequestShipmentDelete.php b/Model/Request/RequestShipmentDelete.php new file mode 100644 index 0000000..95392bd --- /dev/null +++ b/Model/Request/RequestShipmentDelete.php @@ -0,0 +1,28 @@ +") + */ + public $date; + + /** + * Время доставки ("custom" не ипользуется) + * @var RetailCrm\DeliveryModuleBundle\Model\DeliveryTime + * + * @Serializer\Groups({"get"}) + * @Serializer\SerializedName("time") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryTime") + */ + public $time; + + /** + * Адрес отгрузки + * @var string + * + * @Serializer\Groups({"get"}) + * @Serializer\SerializedName("address") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress") + */ + public $address; + + /** + * Массив идентификаторов оформленных доставок в службе доставки + * @var array + * + * @Serializer\Groups({"get"}) + * @Serializer\SerializedName("orders") + * @Serializer\Type("array") + */ + public $orders; + + /** + * @var string + * + * @Serializer\Groups({"get"}) + * @Serializer\SerializedName("comment") + * @Serializer\Type("string") + */ + public $comment; + + /** + * Дополнительные данные отгрузки + * @var array + * + * @Serializer\Groups({"get"}) + * @Serializer\SerializedName("extraData") + * @Serializer\Type("array") + */ + public $extraData; +} diff --git a/Model/Request/RequestStatusUpdateItem.php b/Model/Request/RequestStatusUpdateItem.php new file mode 100644 index 0000000..350a018 --- /dev/null +++ b/Model/Request/RequestStatusUpdateItem.php @@ -0,0 +1,53 @@ +") + */ + public $history; + + /** + * Массив дополнительных данных доставки + * @var array + * + * @Serializer\Groups({"request"}) + * @Serializer\SerializedName("extraData") + * @Serializer\Type("array") + */ + public $extraData; + + public function __construct() + { + $this->history = []; + } +} diff --git a/Model/RequestCalculate.php b/Model/RequestCalculate.php new file mode 100644 index 0000000..63acab0 --- /dev/null +++ b/Model/RequestCalculate.php @@ -0,0 +1,120 @@ +") + */ + public $packages; + + /** + * Объявленная стоимость. + * + * @var float + * + * @Serializer\Groups({"request", "calculate"}) + * @Serializer\SerializedName("declaredValue") + * @Serializer\Type("float") + */ + public $declaredValue; + + /** + * Наложенный платеж. + * + * @var float + * + * @Serializer\Groups({"request", "calculate"}) + * @Serializer\SerializedName("cod") + * @Serializer\Type("float") + */ + public $cod; + + /** + * Плательщик за доставку. + * + * @var string + * + * @Serializer\Groups({"request", "calculate"}) + * @Serializer\SerializedName("payerType") + * @Serializer\Type("string") + */ + public $payerType; + + /** + * Дата доставки. + * + * @var \DateTime + * + * @Serializer\Groups({"request", "calculate"}) + * @Serializer\SerializedName("deliveryDate") + * @Serializer\Type("DateTime<'Y-m-d'>") + */ + public $deliveryDate; + + /** + * Время доставки. + * + * @var DeliveryTime + * + * @Serializer\Groups({"request", "calculate"}) + * @Serializer\SerializedName("deliveryTime") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryTime") + */ + public $deliveryTime; + + /** + * Валюта. + * + * @var string + * + * @Serializer\Groups({"request", "calculate"}) + * @Serializer\SerializedName("currency") + * @Serializer\Type("string") + */ + public $currency; + + /** + * Дополнительные данные доставки. + * + * @var array + * + * @Serializer\Groups({"request", "calculate"}) + * @Serializer\SerializedName("extraData") + * @Serializer\Type("array") + */ + public $extraData; +} diff --git a/Model/RequestDelete.php b/Model/RequestDelete.php new file mode 100644 index 0000000..69f8031 --- /dev/null +++ b/Model/RequestDelete.php @@ -0,0 +1,17 @@ +") + */ + public $packages; + + /** + * Данные доставки. + * + * @var SaveDeliveryData + * + * @Serializer\Groups({"request"}) + * @Serializer\SerializedName("delivery") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\SaveDeliveryData") + */ + public $delivery; + + /** + * Валюта. + * + * @var string + * + * @Serializer\Groups({"request", "calculate"}) + * @Serializer\SerializedName("currency") + * @Serializer\Type("string") + */ + public $currency; + + public function getFullDeclaredValue() + { + $result = 0; + foreach ($this->packages as $package) { + foreach ($package->items as $item) { + $result += $item->declaredValue * $item->quantity; + } + } + + return $result; + } + + public function getFullItemsCodValue() + { + $result = 0; + foreach ($this->packages as $package) { + foreach ($package->items as $item) { + $result += $item->cod * $item->quantity; + } + } + + return $result; + } +} diff --git a/Model/RequestShipmentDelete.php b/Model/RequestShipmentDelete.php new file mode 100644 index 0000000..95392bd --- /dev/null +++ b/Model/RequestShipmentDelete.php @@ -0,0 +1,28 @@ +") + */ + public $date; + + /** + * Время доставки ("custom" не ипользуется) + * @var RetailCrm\DeliveryModuleBundle\Model\DeliveryTime + * + * @Serializer\Groups({"get"}) + * @Serializer\SerializedName("time") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryTime") + */ + public $time; + + /** + * Адрес отгрузки + * @var string + * + * @Serializer\Groups({"get"}) + * @Serializer\SerializedName("address") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress") + */ + public $address; + + /** + * Массив идентификаторов оформленных доставок в службе доставки + * @var array + * + * @Serializer\Groups({"get"}) + * @Serializer\SerializedName("orders") + * @Serializer\Type("array") + */ + public $orders; + + /** + * @var string + * + * @Serializer\Groups({"get"}) + * @Serializer\SerializedName("comment") + * @Serializer\Type("string") + */ + public $comment; + + /** + * Дополнительные данные отгрузки + * @var array + * + * @Serializer\Groups({"get"}) + * @Serializer\SerializedName("extraData") + * @Serializer\Type("array") + */ + public $extraData; +} diff --git a/Model/RequestStatusUpdateItem.php b/Model/RequestStatusUpdateItem.php new file mode 100644 index 0000000..350a018 --- /dev/null +++ b/Model/RequestStatusUpdateItem.php @@ -0,0 +1,53 @@ +") + */ + public $history; + + /** + * Массив дополнительных данных доставки + * @var array + * + * @Serializer\Groups({"request"}) + * @Serializer\SerializedName("extraData") + * @Serializer\Type("array") + */ + public $extraData; + + public function __construct() + { + $this->history = []; + } +} diff --git a/Model/Response/ResponseAutocompleteItem.php b/Model/Response/ResponseAutocompleteItem.php new file mode 100644 index 0000000..6aac639 --- /dev/null +++ b/Model/Response/ResponseAutocompleteItem.php @@ -0,0 +1,42 @@ +value = $value; + $this->label = $label; + $this->description = $description; + } +} diff --git a/Model/Response/ResponseAutocompleteSuccessful.php b/Model/Response/ResponseAutocompleteSuccessful.php new file mode 100644 index 0000000..b8c3e17 --- /dev/null +++ b/Model/Response/ResponseAutocompleteSuccessful.php @@ -0,0 +1,26 @@ +") + */ + public $result; +} diff --git a/Model/Response/ResponseCalculate.php b/Model/Response/ResponseCalculate.php new file mode 100644 index 0000000..c847adc --- /dev/null +++ b/Model/Response/ResponseCalculate.php @@ -0,0 +1,126 @@ +") + */ + public $pickuppointList; + + public function __construct() + { + $this->extraData = []; + } +} diff --git a/Model/Response/ResponseCalculateSuccessful.php b/Model/Response/ResponseCalculateSuccessful.php new file mode 100644 index 0000000..d87206b --- /dev/null +++ b/Model/Response/ResponseCalculateSuccessful.php @@ -0,0 +1,26 @@ +") + */ + public $result; +} diff --git a/Model/Response/ResponseLoadDeliveryData.php b/Model/Response/ResponseLoadDeliveryData.php new file mode 100644 index 0000000..ccca5f1 --- /dev/null +++ b/Model/Response/ResponseLoadDeliveryData.php @@ -0,0 +1,138 @@ +") + */ + public $shipmentDate; + + /** + * Дата доставки + * @var string + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("deliveryDate") + * @Serializer\Type("DateTime<'Y-m-d'>") + */ + public $deliveryDate; + + /** + * Время доставки + * @var RetailCrm\DeliveryModuleBundle\Model\DeliveryTime + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("deliveryTime") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryTime") + */ + public $deliveryTime; + + /** + * Код тарифа + * @var string + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("tariff") + * @Serializer\Type("string") + */ + public $tariff; + + /** + * Наименование тарифа + * @var string + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("tariffName") + * @Serializer\Type("string") + */ + public $tariffName; + + /** + * Плательщик за доставку + * @var string + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("payerType") + * @Serializer\Type("string") + */ + public $payerType; + + /** + * Текущий статус достаквки + * @var StatusInfo + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("status") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\StatusInfo") + */ + public $status; + + /** + * Дополнительные данные доставки + * @var string + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("extraData") + * @Serializer\Type("array") + */ + public $extraData; + + /** + * Адрес отгрузки + * @var DeliveryAddress + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("shipmentAddress") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress") + */ + public $shipmentAddress; + + /** + * Адрес доставки + * @var DeliveryAddress + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("deliveryAddress") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress") + */ + public $deliveryAddress; + + public $additionalData; + + public function __construct() + { + $this->extraData = []; + $this->additionalData = []; + } +} diff --git a/Model/Response/ResponseResult.php b/Model/Response/ResponseResult.php new file mode 100644 index 0000000..bb0f2c3 --- /dev/null +++ b/Model/Response/ResponseResult.php @@ -0,0 +1,7 @@ +extraData = []; + $this->additionalData = []; + } +} diff --git a/Model/Response/ResponseShipmentSave.php b/Model/Response/ResponseShipmentSave.php new file mode 100644 index 0000000..337c0c8 --- /dev/null +++ b/Model/Response/ResponseShipmentSave.php @@ -0,0 +1,36 @@ +") + */ + public $extraData; + + public static function loadValidatorMetadata(ClassMetadata $metadata) + { + $metadata + ->addPropertyConstraint('shipmentId', new Assert\NotBlank()); + } +} diff --git a/Model/Response/ResponseSuccessful.php b/Model/Response/ResponseSuccessful.php new file mode 100644 index 0000000..9d86cbf --- /dev/null +++ b/Model/Response/ResponseSuccessful.php @@ -0,0 +1,26 @@ +value = $value; + $this->label = $label; + $this->description = $description; + } +} diff --git a/Model/ResponseAutocompleteSuccessful.php b/Model/ResponseAutocompleteSuccessful.php new file mode 100644 index 0000000..b8c3e17 --- /dev/null +++ b/Model/ResponseAutocompleteSuccessful.php @@ -0,0 +1,26 @@ +") + */ + public $result; +} diff --git a/Model/ResponseCalculate.php b/Model/ResponseCalculate.php new file mode 100644 index 0000000..c847adc --- /dev/null +++ b/Model/ResponseCalculate.php @@ -0,0 +1,126 @@ +") + */ + public $pickuppointList; + + public function __construct() + { + $this->extraData = []; + } +} diff --git a/Model/ResponseCalculateSuccessful.php b/Model/ResponseCalculateSuccessful.php new file mode 100644 index 0000000..3247e35 --- /dev/null +++ b/Model/ResponseCalculateSuccessful.php @@ -0,0 +1,17 @@ +") + */ + public $result; +} diff --git a/Model/ResponseLoadDeliveryData.php b/Model/ResponseLoadDeliveryData.php new file mode 100644 index 0000000..ccca5f1 --- /dev/null +++ b/Model/ResponseLoadDeliveryData.php @@ -0,0 +1,138 @@ +") + */ + public $shipmentDate; + + /** + * Дата доставки + * @var string + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("deliveryDate") + * @Serializer\Type("DateTime<'Y-m-d'>") + */ + public $deliveryDate; + + /** + * Время доставки + * @var RetailCrm\DeliveryModuleBundle\Model\DeliveryTime + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("deliveryTime") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryTime") + */ + public $deliveryTime; + + /** + * Код тарифа + * @var string + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("tariff") + * @Serializer\Type("string") + */ + public $tariff; + + /** + * Наименование тарифа + * @var string + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("tariffName") + * @Serializer\Type("string") + */ + public $tariffName; + + /** + * Плательщик за доставку + * @var string + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("payerType") + * @Serializer\Type("string") + */ + public $payerType; + + /** + * Текущий статус достаквки + * @var StatusInfo + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("status") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\StatusInfo") + */ + public $status; + + /** + * Дополнительные данные доставки + * @var string + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("extraData") + * @Serializer\Type("array") + */ + public $extraData; + + /** + * Адрес отгрузки + * @var DeliveryAddress + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("shipmentAddress") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress") + */ + public $shipmentAddress; + + /** + * Адрес доставки + * @var DeliveryAddress + * + * @Serializer\Groups({"response"}) + * @Serializer\SerializedName("deliveryAddress") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryAddress") + */ + public $deliveryAddress; + + public $additionalData; + + public function __construct() + { + $this->extraData = []; + $this->additionalData = []; + } +} diff --git a/Model/ResponseResult.php b/Model/ResponseResult.php new file mode 100644 index 0000000..bb0f2c3 --- /dev/null +++ b/Model/ResponseResult.php @@ -0,0 +1,7 @@ +extraData = []; + $this->additionalData = []; + } +} diff --git a/Model/ResponseShipmentPointListSuccessful.php b/Model/ResponseShipmentPointListSuccessful.php new file mode 100644 index 0000000..2bd76c4 --- /dev/null +++ b/Model/ResponseShipmentPointListSuccessful.php @@ -0,0 +1,17 @@ +") + */ + public $result; +} diff --git a/Model/ResponseShipmentSave.php b/Model/ResponseShipmentSave.php new file mode 100644 index 0000000..337c0c8 --- /dev/null +++ b/Model/ResponseShipmentSave.php @@ -0,0 +1,36 @@ +") + */ + public $extraData; + + public static function loadValidatorMetadata(ClassMetadata $metadata) + { + $metadata + ->addPropertyConstraint('shipmentId', new Assert\NotBlank()); + } +} diff --git a/Model/ResponseSuccessful.php b/Model/ResponseSuccessful.php new file mode 100644 index 0000000..f00460a --- /dev/null +++ b/Model/ResponseSuccessful.php @@ -0,0 +1,17 @@ +") + */ + public $shipmentDate; + + /** + * Дата доставки. + * + * @var \DateTime + * + * @Serializer\Groups({"get"}) + * @Serializer\SerializedName("deliveryDate") + * @Serializer\Type("DateTime<'Y-m-d'>") + */ + public $deliveryDate; + + /** + * Время доставки ("custom" не ипользуется). + * + * @var \RetailCrm\DeliveryModuleBundle\Model\DeliveryTime + * + * @Serializer\Groups({"get"}) + * @Serializer\SerializedName("deliveryTime") + * @Serializer\Type("RetailCrm\DeliveryModuleBundle\Model\DeliveryTime") + */ + public $deliveryTime; + + /** + * Дополнительные данные доставки. + * + * @var array + * + * @Serializer\Groups({"get"}) + * @Serializer\SerializedName("extraData") + * @Serializer\Type("array") + */ + public $extraData; +} diff --git a/Model/ShipmentOrder.php b/Model/ShipmentOrder.php new file mode 100644 index 0000000..4666c88 --- /dev/null +++ b/Model/ShipmentOrder.php @@ -0,0 +1,30 @@ +") + */ + public $packages; +} diff --git a/Model/Status.php b/Model/Status.php new file mode 100644 index 0000000..9da23d9 --- /dev/null +++ b/Model/Status.php @@ -0,0 +1,45 @@ +code = $code; + $this->name = $name; + $this->isEditable = $isEditable; + } +} diff --git a/Model/StatusInfo.php b/Model/StatusInfo.php new file mode 100644 index 0000000..da2bc23 --- /dev/null +++ b/Model/StatusInfo.php @@ -0,0 +1,38 @@ +") + */ + public $updatedAt; + + /** + * Комментарий к статусу + * @var string + * + * @Serializer\Groups({"get", "response"}) + * @Serializer\SerializedName("comment") + * @Serializer\Type("string") + */ + public $comment; +} diff --git a/Model/Store.php b/Model/Store.php new file mode 100644 index 0000000..87c2e96 --- /dev/null +++ b/Model/Store.php @@ -0,0 +1,26 @@ +extraData[$fieldCode])) { + return null; + } else { + return $this->extraData[$fieldCode]; + } + } +} diff --git a/Model/Unit.php b/Model/Unit.php new file mode 100644 index 0000000..4f45d32 --- /dev/null +++ b/Model/Unit.php @@ -0,0 +1,33 @@ +
Re-enter data + unknown_country: Unknown country + unknown_shipping_country: Unknown shipping country + shipping_country_required: Shipping country must not be empty + shipper_postal_code_required: Shipper postal code required + delivery_postal_code_required: Delivery postal code required + manager_phone_required: Manager`s phone required + dhl: + ready_time_required: Ready time required + dury_payment_type_for_receiver: Duty Payment Type cant be sender for payer type receiver + receiver_account_number_required: Receiver account number required + +plate: + label: Label + +day_short: + monday: Mon + tuesday: Tue + wednesday: Wed + thursday: Thu + friday: Fri + saturday: Sat + sunday: Sun + +pagination.items.name: elements diff --git a/Resources/translations/messages.es.yml b/Resources/translations/messages.es.yml new file mode 100644 index 0000000..a66d5b5 --- /dev/null +++ b/Resources/translations/messages.es.yml @@ -0,0 +1,67 @@ +header: + configureConnection: Configuración de la conexión del sistema + additionalSettings: Configuración avanzada + adminParcelEdit: 'Editar seguimiento %trackId%' + adminParcelCreate: Crear seguimiento + listConnection: Conexiones actuales + listTracking: Seguimiento actual + serviceConnect: 'Conexión de Servicio %delivery%' + adminConnectionEdit: 'Editar datos del cliente: %uid%' + adminConnectionCreate: Nueva conexión + +button: + activate: Activar + save: Guardar + add: Añadir + listConnection: A la lista de conexiones + listTracking: Seguimiento de paquetes + addTracking: Añadir seguimiento + updateConfiguration: Actualizar configuración + +label: + crmUrl: Dirección del Sistema + crmKey: Clave API del sistema + debug: Modo de depuración + isActive: Conexión activa + isFreeze: Conexión congelada + language: Idioma + account_number: Número de cuenta + token: token API + isInProduction: Utilizar servidor normal + id: ID + connection: ID de conexión + orderId: ID de pedido + trackId: ID de seguimiento + isClosed: Seguimiento completado + connectionId: Id de conexión + +select_value: + sender: Remitente + receiver: Receptor + +error: + connect.failed: Datos para conectarse a %delivery% o la clave API del sistema son incorrectos, intente de nuevo.

Introducir datos de nuevo + unknown_country: País desconocido + unknown_shipping_country: Páis de envio desconocido + shipping_country_required: Debe especificar el país de envío + shipper_postal_code_required: Debe especificar el código Postal del remitente + delivery_postal_code_required: Debe especificar el código Postal del destinatario + manager_phone_required: Debe especificar el Teléfono del mánager + dhl: + ready_time_required: Debe especificar la fecha del envío + dury_payment_type_for_receiver: El remitente no puede pagar los cargos adicionales si el que paga es el destinatario + receiver_account_number_required: Debe especificar el número de cuenta del destinatario + +plate: + label: Etiqueta + +day_short: + monday: Lu + tuesday: Ma + wednesday: Mie + thursday: Ju + friday: Vi + saturday: Sa + sunday: Do + +pagination.items.name: elementos diff --git a/Resources/translations/messages.ru.yml b/Resources/translations/messages.ru.yml new file mode 100644 index 0000000..cfed3d8 --- /dev/null +++ b/Resources/translations/messages.ru.yml @@ -0,0 +1,67 @@ +header: + configureConnection: Настройка подключения к системе + additionalSettings: Дополнительные настройки + adminParcelEdit: 'Редактировать отслеживание %trackId%' + adminParcelCreate: Создать отслеживание + listConnection: Текущие подключения + listTracking: Текущие отслеживания + serviceConnect: 'Подключение сервиса %delivery%' + adminConnectionEdit: 'Редактировать данные клиента: %uid%' + adminConnectionCreate: Новое подключение + +button: + activate: Активировать + save: Сохранить + add: Добавить + listConnection: К списку подключений + listTracking: Отслеживание посылок + addTracking: Добавить отслеживание + updateConfiguration: Обновить конфигурацию + +label: + crmUrl: Адрес системы + crmKey: API ключ системы + debug: Режим отладки + isActive: Подключение активно + isFreeze: Подключение заморожено + language: Язык + account_number: Номер аккаунта + token: API токен + isInProduction: Использовать боевой сервер + id: ID + connection: ID подключения + orderId: ID заказа + trackId: ID отслеживания + isClosed: Отслеживание завершено + connectionId: Идентификатор подключения + +select_value: + sender: Отправитель + receiver: Получатель + +error: + connect.failed: Данные для подключения к %delivery% или API ключ системы введены неверно, попробуйте еще раз.

Ввести данные заново + unknown_country: Неизвестная страна + unknown_shipping_country: Неизвестная страна отправки + shipping_country_required: Необходимо указать страну отправки + shipper_postal_code_required: Необходимо указать почтовый индекс отправителя + delivery_postal_code_required: Необходимо указать почтовый индекс получателя + manager_phone_required: Необходимо указать телефон менеджера + dhl: + ready_time_required: Необходимо указать время отгрузки + dury_payment_type_for_receiver: Отправитель не может быть плательщиком за дополнительные сборы если тип плательщика получатель + receiver_account_number_required: Необходимо указать номер аккаунта получателя + +plate: + label: Наклейка + +day_short: + monday: Пн + tuesday: Вт + wednesday: Ср + thursday: Чт + friday: Пт + saturday: Сб + sunday: Вс + +pagination.items.name: элементов diff --git a/Resources/views/Connection/configure.html.twig b/Resources/views/Connection/configure.html.twig new file mode 100644 index 0000000..8d84911 --- /dev/null +++ b/Resources/views/Connection/configure.html.twig @@ -0,0 +1,68 @@ +{% form_theme form 'DeliveryCoreBundle:Form:configure.html.twig' %} + + + + + + + {% block title %}{% endblock %} + + + + + + +
+
+
+
+ {% block logo %}{% endblock %} +
+
+
+
+
+
+ {% block form %} +
+ {{ form_errors(form) }} +
+ +
+ {{ form_start(form) }} + + {% block form_delivery %} + {% endblock %} + +
+ {{ 'header.configureConnection'|trans }} + {{ form_widget(form.crmUrl, {'attr': {'value': account}}) }} + {{ form_errors(form.crmUrl) }} + + {{ form_widget(form.crmKey) }} + {{ form_errors(form.crmKey) }} + + {{ form_widget(form.language) }} + {{ form_errors(form.language) }} +
+ + {% block form_delivery_after %} + {% endblock %} + +
+ {{ form_rest(form) }} +
+ + + {{ form_end(form) }} + {% endblock %} + +
+
+ +
+ + + diff --git a/Resources/views/Connection/configure_error.html.twig b/Resources/views/Connection/configure_error.html.twig new file mode 100644 index 0000000..0440200 --- /dev/null +++ b/Resources/views/Connection/configure_error.html.twig @@ -0,0 +1,13 @@ +{% extends 'CoreAutomateBundle:Layout:connect.html.twig' %} + +{% block title %} + {{ 'header.serviceConnect'|trans({'%delivery%': title_delivery})|raw }} +{% endblock %} + +{% block logo %} + {{ title_delivery }} +{% endblock %} + +{% block form %} + {{ 'error.connect.failed'|trans({'%delivery%': title_delivery, '%href%': referer})|raw }} +{% endblock %} diff --git a/Resources/views/Connection/edit.html.twig b/Resources/views/Connection/edit.html.twig new file mode 100644 index 0000000..3b1889e --- /dev/null +++ b/Resources/views/Connection/edit.html.twig @@ -0,0 +1,60 @@ +{% extends 'CoreOmegaBundle:Layout:base.html.twig' %} +{% form_theme form 'DeliveryCoreBundle:Form:admin.html.twig' %} + +{% block content %} +
+

+ {% if connection is defined %} + {{ 'header.adminConnectionEdit'|trans({'%uid%': ''~connection.crmUrl~''})|raw }} + {% else %} + {{ 'header.adminConnectionCreate'|trans()|raw }} + {% endif %} +

+
+ +
+
+ {{ form_start(form) }} + {{ form_errors(form) }} + +
+ {{ form_row(form.crmUrl) }} + {{ form_row(form.crmKey) }} + + {{ form_row(form.isActive) }} + + {% if form.language is defined %} + {{ form_row(form.language) }} + {% endif %} + + {{ form_row(form.isFreeze) }} +
+ + {% block form_appendix %} + {% endblock %} + +
+ {{ form_row(form.debug) }} +
+ +
+
+ +
+ {% if is_granted('ROLE_DEVELOPER') %} + {% if connection is defined %} + + {% endif %} + {% endif %} +
+ + {{ form_end(form) }} +
+ +
+
+{% endblock %} diff --git a/Resources/views/Connection/list.html.twig b/Resources/views/Connection/list.html.twig new file mode 100644 index 0000000..dde22df --- /dev/null +++ b/Resources/views/Connection/list.html.twig @@ -0,0 +1,61 @@ +{% extends 'CoreOmegaBundle:Layout:base.html.twig' %} + +{% block content %} +
+

{{ 'header.listConnection'|trans()|raw }}

+
+ +
+
+ {% if is_granted('ROLE_DEVELOPER') %} + + {{ 'button.add'|trans()|raw }} + + {% endif %} + + {{ 'button.listTracking'|trans()|raw }} + +
+ + + + + + + + {% for client in pagination %} + + + + + + {% endfor %} +
{{ 'label.id'|trans()|raw }}{{ 'label.crmUrl'|trans()|raw }}{{ 'label.isActive'|trans()|raw }}
+ {{ client.clientId }} + + {% if client.crmUrl is not empty %} + + {{ client.crmUrl }} + + {% endif %} + + {% if client.isActive %} + + {% else %} + + {% endif %} +
+ +
+
+ + {{ pagination.getTotalItemCount }} {{ 'pagination.items.name'|trans()|raw }} + +
+
+ {{ knp_pagination_render(pagination) }} +
+
+
+
+{% endblock %} diff --git a/Resources/views/Form/admin.html.twig b/Resources/views/Form/admin.html.twig new file mode 100644 index 0000000..5e0b0f2 --- /dev/null +++ b/Resources/views/Form/admin.html.twig @@ -0,0 +1,18 @@ +{% extends "form_div_layout.html.twig" %} + +{% block form_row %} +{% spaceless %} +
+ {{ form_label(form, null, {'label_attr' : {'class': 'label-common'}}) }} + {{ form_errors(form) }} + + {% if not attr or not attr.class|default(null) %} + {% set attr = attr|default({})|merge({ + 'class': 'input-field', + 'style': 'max-width: 320px;' + }) %} + {% endif %} + {{ form_widget(form, { 'attr': attr }) }} +
+{% endspaceless %} +{% endblock form_row %} \ No newline at end of file diff --git a/Resources/views/Form/configure.html.twig b/Resources/views/Form/configure.html.twig new file mode 100644 index 0000000..60eb358 --- /dev/null +++ b/Resources/views/Form/configure.html.twig @@ -0,0 +1,13 @@ +{% extends "form_div_layout.html.twig" %} + +{% block form_errors %} + {% spaceless %} + {% if errors|length > 0 %} + {% for error in errors %} +
+ {{ error.message }} +
+ {% endfor %} + {% endif %} + {% endspaceless %} +{% endblock form_errors %} \ No newline at end of file diff --git a/Resources/views/Parcel/edit.html.twig b/Resources/views/Parcel/edit.html.twig new file mode 100644 index 0000000..00ef4cc --- /dev/null +++ b/Resources/views/Parcel/edit.html.twig @@ -0,0 +1,61 @@ +{% extends 'CoreOmegaBundle:Layout:base.html.twig' %} + +{% block content %} +
+

+ {% if parcel.id is not empty %} + {{ 'header.adminParcelEdit' |trans({'%trackId%': parcel.trackId})|raw }} + {% else %} + {{ 'header.adminParcelCreate' |trans()|raw }} + {% endif %} +

+
+ +
+
+ {{ form_start(form) }} + {{ form_errors(form) }} + +
+
+ {{ form_label(form.connection, null, {'label_attr' : {'class': 'label-common'}}) }} + {{ form_errors(form.connection) }} + {{ form_widget(form.connection, {'attr': {'class': 'input-field', 'style': 'width: 320px;'}}) }} +
+ +
+ {{ form_label(form.orderId, null, {'label_attr' : {'class': 'label-common'}}) }} + {{ form_errors(form.orderId) }} + {{ form_widget(form.orderId, {'attr': {'class': 'input-field', 'style': 'width: 320px;'}}) }} +
+
+ +
+
+ {{ form_label(form.trackId, null, {'label_attr' : {'class': 'label-common'}}) }} + {{ form_errors(form.trackId) }} + {{ form_widget(form.trackId, {'attr': {'class': 'input-field', 'style': 'width: 320px;'}}) }} +
+ +
+ {{ form_label(form.isClosed, null, {'label_attr' : {'class': 'label-common'}}) }} + {{ form_errors(form.isClosed) }} + {{ form_widget(form.isClosed) }} +
+
+ + {% block form_appendix %} + {% endblock %} + +
+
+ +
+
+ + {{ form_end(form) }} +
+ +
+
+{% endblock%} diff --git a/Resources/views/Parcel/list.html.twig b/Resources/views/Parcel/list.html.twig new file mode 100644 index 0000000..0eb062a --- /dev/null +++ b/Resources/views/Parcel/list.html.twig @@ -0,0 +1,60 @@ +{% extends 'CoreOmegaBundle:Layout:base.html.twig' %} + +{% block content %} +
+

{{ 'header.listConnection'|trans()|raw }}

+
+ +
+ + + + + + + + + {% for track in pagination %} + + + + + + + {% endfor %} +
{{ 'label.trackId'|trans()|raw }}{{ 'label.orderId'|trans()|raw }}{{ 'label.connection'|trans()|raw }}{{ 'label.isClosed'|trans()|raw }}
+ {{ track.trackId}} + + {{ track.orderId}} + + {{ track.clientId}} + + {% if track.isClosed %} + + {% else %} + + {% endif %} +
+ +
+
+ + {{ pagination.getTotalItemCount }} {{ 'pagination.items.name'|trans()|raw }} + +
+
+ {{ knp_pagination_render(pagination) }} +
+
+
+
+{% endblock%} diff --git a/RetailCrmDeliveryModuleBundle.php b/RetailCrmDeliveryModuleBundle.php new file mode 100644 index 0000000..f069420 --- /dev/null +++ b/RetailCrmDeliveryModuleBundle.php @@ -0,0 +1,9 @@ +class = $accountClass; + $this->entityManager = $entityManager; + } + + public function getClass(): string + { + return $this->getRepository()->getClassName(); + } + + public function create(): Account + { + $class = $this->getClass(); + + return new $class(); + } + + public function find(string $id): ?Account + { + return $this->getRepository()->find($id); + } + + public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null): array + { + return $this->getRepository()->findBy($criteria, $orderBy, $limit, $offset); + } + + public function findOneBy(array $criteria, array $orderBy = null): ?Account + { + return $this->getRepository()->findOneBy($criteria, $orderBy); + } + + public function flush(): void + { + $this->entityManager->flush(); + } + + public function getRepository(): ObjectRepository + { + return $this->entityManager->getRepository($this->class); + } +} diff --git a/Service/DeliveryOrderManager.php b/Service/DeliveryOrderManager.php new file mode 100644 index 0000000..e68390f --- /dev/null +++ b/Service/DeliveryOrderManager.php @@ -0,0 +1,65 @@ +class = $deliveryOrderClass; + $this->entityManager = $entityManager; + } + + public function getClass(): string + { + return $this->class; + } + + public function create(): DeliveryOrder + { + $class = $this->getClass(); + + return new $class(); + } + + public function find(int $id): ?DeliveryOrder + { + return $this->getRepository()->find($id); + } + + public function findBy(array $criteria): array + { + return $this->getRepository()->findBy($criteria); + } + + public function findOneBy(array $criteria): ?DeliveryOrder + { + return $this->getRepository()->findOneBy($criteria); + } + + public function persist(object $entity): void + { + $this->entityManager->persist($entity); + } + + public function remove(object $entity): void + { + $this->entityManager->remove($entity); + } + + public function flush(): void + { + $this->entityManager->flush(); + } + + public function getRepository(): ObjectRepository + { + return $this->entityManager->getRepository($this->class); + } +} diff --git a/Service/ModuleManager.php b/Service/ModuleManager.php new file mode 100644 index 0000000..289141e --- /dev/null +++ b/Service/ModuleManager.php @@ -0,0 +1,378 @@ +integrationCode = $moduleParameters['integration_code']; + $this->moduleParameters = $moduleParameters; + $this->retailCrmClientFactory = $retailCrmClientFactory; + $this->deliveryManager = $deliveryManager; + $this->jmsSerializer = $jmsSerializer; + $this->translator = $translator; + $this->router = $router; + $this->pinbaService = new PinbaService(); + } + + public function getAccountCode(): string + { + if (null === $this->account) { + throw new \LogicException('Account is not selected'); + } + + return sprintf('%s-%s', $this->integrationCode, $this->account->getId()); + } + + public function getAccount(): ?Account + { + return $this->account; + } + + public function setAccount(Account $account): ModuleManagerInterface + { + $this->account = $account; + + if ($this->account && $this->account->getLanguage() && $this->translator) { + $this->translator->setLocale($this->account->getLanguage()); + } + + $this->retailCrmClient = $this->retailCrmClientFactory->createRetailCrmClient($this->account, $this->logger); + + return $this; + } + + public function updateModuleConfiguration(): bool + { + if (null === $this->account) { + throw new \LogicException('Account is not selected'); + } + + $integrationModule = $this->buildIntegrationModule(); + $integrationModule = $this->jmsSerializer + ->serialize($integrationModule, 'json', SerializationContext::create()->setGroups(['get', 'request'])); + + $client = $this->retailCrmClient; + $response = $this->pinbaService->timerHandler( + [ + 'api' => 'retailCrm', + 'method' => 'integrationModulesEdit', + ], + static function () use ($client, $integrationModule) { + return $client->request->integrationModulesEdit( + json_decode($integrationModule, true) + ); + } + ); + + if ($response['success'] ?? false) { + return true; + } else { + return false; + } + } + + protected function buildIntegrationModule(): IntegrationModule + { + $integrationModule = new IntegrationModule(); + + $integrationModule->code = $this->getAccountCode(); + $integrationModule->integrationCode = $this->integrationCode; + $integrationModule->active = $this->account->isActive(); + $integrationModule->name = $this->moduleParameters['locales'][$this->translator->getLocale()]['name']; + $integrationModule->logo = $this->moduleParameters['locales'][$this->translator->getLocale()]['logo']; + $integrationModule->clientId = $this->account->getId(); + $integrationModule->availableCountries = $this->moduleParameters['countries']; + $integrationModule->actions = [ + 'activity' => 'activity', + ]; + + $integrationModule->baseUrl = $this->router->generate( + 'retailcrm_delivery_module_api_base', + [], + UrlGeneratorInterface::ABSOLUTE_URL + ); + $integrationModule->accountUrl = $this->router->generate( + 'retailcrm_delivery_module_connect', + ['_locale' => $this->account->getLanguage()], + UrlGeneratorInterface::ABSOLUTE_URL + ); + + $integrationModule->integrations = ['delivery' => $this->doBuildConfiguration()]; + + return $integrationModule; + } + + abstract protected function doBuildConfiguration(): Configuration; + + public function calculateDelivery(RequestCalculate $data): array + { + throw new \LogicException('Method should be implemented'); + } + + public function saveDelivery(RequestSave $data, DeliveryOrder $delivery = null): ResponseSave + { + throw new \LogicException('Method should be implemented'); + } + + public function getDelivery(string $externalId): ResponseLoadDeliveryData + { + throw new \LogicException('Method should be implemented'); + } + + public function deleteDelivery(RequestDelete $request, DeliveryOrder $delivery): bool + { + throw new \LogicException('Method should be implemented'); + } + + /** + * @return \RetailCrm\DeliveryModuleBundle\Model\Terminal[] + */ + public function shipmentPointList(RequestShipmentPointList $request): array + { + throw new \LogicException('Method should be implemented'); + } + + public function saveShipment(RequestShipmentSave $data): ResponseShipmentSave + { + throw new \LogicException('Method should be implemented'); + } + + public function deleteShipment(RequestShipmentDelete $request): bool + { + throw new \LogicException('Method should be implemented'); + } + + public function printDocument(RequestPrint $request) + { + $deliveries = $this->deliveryManager->findBy([ + 'account' => $this->account, + 'externalId' => $request->deliveryIds, + ]); + + if (empty($deliveries)) { + throw new NotFoundException('Deliveries not found'); + } + + return $this->doPrint($request->type, $deliveries); + } + + protected function doPrint(string $documentType, array $deliveries): array + { + throw new \LogicException('Method should be implemented'); + } + + public function updateStatuses(): int + { + if (null === $this->account) { + throw new \LogicException('Account is not selected'); + } + + $deliveryQuery = $this->deliveryManager->createQueryBuilder('delivery') + ->select('delivery') + ->andWhere('delivery.account = :account') + ->andWhere('delivery.id >= :lastId') + ->andWhere('delivery.ended = FALSE') + ->orderBy('delivery.id ASC') + ->createQuery() + ->setMaxResults(static::STATUS_UPDATE_LIMIT) + ->setAccount($this->account) + ; + + $count = 0; + $lastId = 0; + while (true) { + $deliveryQuery->setParameter('lastId', $lastId); + $deliveries = $deliveryQuery->getResult(); + if (empty($deliveries)) { + break; + } + + foreach ($deliveries as $delivery) { + if ($delivery->getId() > $lastId) { + $lastId = $delivery->getId(); + } + } + + $deliveriesHistory = $this->doUpdateStatuses($deliveries); + if (!empty($deliveriesHistory)) { + $this->updateRetailCrmOrderStatuses($deliveriesHistory); + } + $count += count($deliveriesHistory); + $this->deliveryManager->flush(); + } + + return $count; + } + + public function getRetailCrmClient(): ApiClient + { + if (null === $this->retailCrmClient) { + throw new \LogicException('Account is not selected'); + } + + return $this->retailCrmClient; + } + + /** + * Получение актуальных статусов доставки от службы доставки. + * + * @param \RetailCrm\DeliveryModuleBundle\Entity\Parcel[] $deliveries + * + * @return \RetailCrm\DeliveryModuleBundle\Model\RequestStatusUpdateItem[] + */ + protected function doUpdateStatuses(array $deliveries): array + { + throw new \LogicException('Method should be implemented'); + } + + /** + * Обновление статусов в CRM. + * + * @param \RetailCrm\DeliveryModuleBundle\Model\RequestStatusUpdateItem[] $deliveriesHistory + * + * @throws \Exception + */ + protected function updateRetailCrmOrderStatuses(array $deliveriesHistory): void + { + if (count($deliveriesHistory) > 100) { + $parts = array_chunk($deliveriesHistory, 100); + } else { + $parts = [$deliveriesHistory]; + } + + foreach ($parts as $part) { + $request = $this->jmsSerializer + ->serialize($part, 'json', SerializationContext::create()->setGroups(['get', 'request'])); + + $client = $this->retailCrmClient; + $moduleCode = $this->getAccountCode(); + $response = $this->pinbaService->timerHandler( + [ + 'api' => 'retailCrm', + 'method' => 'deliveryTracking', + ], + static function () use ($client, $moduleCode, $request) { + return $client->request->deliveryTracking( + $moduleCode, + json_decode($request, true) + ); + } + ); + } + } + + private function createRetailCrmClient(): void + { + if (null === $this->account) { + throw new \LogicException('Account is not selected'); + } + + if (empty($this->account->getCrmUrl())) { + throw new \LogicException('Crm url is empty'); + } + + if (empty($this->account->getCrmApiKey())) { + throw new \LogicException('Crm apiKey is empty'); + } + + $this->retailCrmClient = new ApiClient( + $this->account->getCrmUrl(), + $this->account->getCrmApiKey(), + ApiClient::V5 + ); + if ($this->logger) { + $this->retailCrmClient->setLogger($this->logger); + } + } +} diff --git a/Service/ModuleManagerInterface.php b/Service/ModuleManagerInterface.php new file mode 100644 index 0000000..0a40835 --- /dev/null +++ b/Service/ModuleManagerInterface.php @@ -0,0 +1,50 @@ +getCrmUrl())) { + throw new \LogicException('Crm url is empty'); + } + + if (empty($account->getCrmApiKey())) { + throw new \LogicException('Crm apiKey is empty'); + } + + $retailCrmClient = new ApiClient( + $account->getCrmUrl(), + $account->getCrmApiKey(), + ApiClient::V5 + ); + if ($logger) { + $retailCrmClient->setLogger($logger); + } + + return $retailCrmClient; + } +} diff --git a/Service/RetailCrmClientFactoryInterface.php b/Service/RetailCrmClientFactoryInterface.php new file mode 100644 index 0000000..c6cb0cd --- /dev/null +++ b/Service/RetailCrmClientFactoryInterface.php @@ -0,0 +1,12 @@ +2.2,<2.4" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "doctrine/coding-standard": "^6.0", + "mongodb/mongodb": "^1.1", + "phpunit/phpunit": "^7.0", + "predis/predis": "~1.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", + "homepage": "https://www.doctrine-project.org/projects/cache.html", + "keywords": [ + "abstraction", + "apcu", + "cache", + "caching", + "couchdb", + "memcached", + "php", + "redis", + "xcache" + ], + "time": "2019-11-29T15:36:20+00:00" + }, + { + "name": "doctrine/collections", + "version": "1.6.4", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7", + "reference": "6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan-shim": "^0.9.2", + "phpunit/phpunit": "^7.0", + "vimeo/psalm": "^3.2.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.", + "homepage": "https://www.doctrine-project.org/projects/collections.html", + "keywords": [ + "array", + "collections", + "iterators", + "php" + ], + "time": "2019-11-13T13:07:11+00:00" + }, + { + "name": "doctrine/common", + "version": "2.12.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/common.git", + "reference": "2053eafdf60c2172ee1373d1b9289ba1db7f1fc6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/common/zipball/2053eafdf60c2172ee1373d1b9289ba1db7f1fc6", + "reference": "2053eafdf60c2172ee1373d1b9289ba1db7f1fc6", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/inflector": "^1.0", + "doctrine/lexer": "^1.0", + "doctrine/persistence": "^1.1", + "doctrine/reflection": "^1.0", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^1.0", + "phpstan/phpstan": "^0.11", + "phpstan/phpstan-phpunit": "^0.11", + "phpunit/phpunit": "^7.0", + "squizlabs/php_codesniffer": "^3.0", + "symfony/phpunit-bridge": "^4.0.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.11.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, persistence interfaces, proxies, event system and much more.", + "homepage": "https://www.doctrine-project.org/projects/common.html", + "keywords": [ + "common", + "doctrine", + "php" + ], + "time": "2020-01-10T15:49:25+00:00" + }, + { + "name": "doctrine/dbal", + "version": "v2.10.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "c2b8e6e82732a64ecde1cddf9e1e06cb8556e3d8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/c2b8e6e82732a64ecde1cddf9e1e06cb8556e3d8", + "reference": "c2b8e6e82732a64ecde1cddf9e1e06cb8556e3d8", + "shasum": "" + }, + "require": { + "doctrine/cache": "^1.0", + "doctrine/event-manager": "^1.0", + "ext-pdo": "*", + "php": "^7.2" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "jetbrains/phpstorm-stubs": "^2019.1", + "phpstan/phpstan": "^0.11.3", + "phpunit/phpunit": "^8.4.1", + "symfony/console": "^2.0.5|^3.0|^4.0|^5.0" + }, + "suggest": { + "symfony/console": "For helpful console commands such as SQL execution and import of files." + }, + "bin": [ + "bin/doctrine-dbal" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.10.x-dev", + "dev-develop": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\DBAL\\": "lib/Doctrine/DBAL" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", + "homepage": "https://www.doctrine-project.org/projects/dbal.html", + "keywords": [ + "abstraction", + "database", + "db2", + "dbal", + "mariadb", + "mssql", + "mysql", + "oci8", + "oracle", + "pdo", + "pgsql", + "postgresql", + "queryobject", + "sasql", + "sql", + "sqlanywhere", + "sqlite", + "sqlserver", + "sqlsrv" + ], + "time": "2020-01-04T12:56:21+00:00" + }, + { + "name": "doctrine/event-manager", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "629572819973f13486371cb611386eb17851e85c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/629572819973f13486371cb611386eb17851e85c", + "reference": "629572819973f13486371cb611386eb17851e85c", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.9@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "event dispatcher", + "event manager", + "event system", + "events" + ], + "time": "2019-11-10T09:48:07+00:00" + }, + { + "name": "doctrine/inflector", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/ec3a55242203ffa6a4b27c58176da97ff0a7aec1", + "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string" + ], + "time": "2019-10-30T19:59:35+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2019-10-21T16:45:58+00:00" + }, + { + "name": "doctrine/lexer", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", + "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", + "shasum": "" + }, + "require": { + "php": "^7.2" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11.8", + "phpunit/phpunit": "^8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "time": "2019-10-30T14:39:59+00:00" + }, + { + "name": "doctrine/orm", + "version": "v2.7.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/orm.git", + "reference": "4d763ca4c925f647b248b9fa01b5f47aa3685d62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/orm/zipball/4d763ca4c925f647b248b9fa01b5f47aa3685d62", + "reference": "4d763ca4c925f647b248b9fa01b5f47aa3685d62", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.8", + "doctrine/cache": "^1.9.1", + "doctrine/collections": "^1.5", + "doctrine/common": "^2.11", + "doctrine/dbal": "^2.9.3", + "doctrine/event-manager": "^1.1", + "doctrine/instantiator": "^1.3", + "doctrine/persistence": "^1.2", + "ext-pdo": "*", + "php": "^7.1", + "symfony/console": "^3.0|^4.0|^5.0" + }, + "require-dev": { + "doctrine/coding-standard": "^5.0", + "phpunit/phpunit": "^7.5", + "symfony/yaml": "^3.4|^4.0|^5.0" + }, + "suggest": { + "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" + }, + "bin": [ + "bin/doctrine" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\ORM\\": "lib/Doctrine/ORM" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Object-Relational-Mapper for PHP", + "homepage": "https://www.doctrine-project.org/projects/orm.html", + "keywords": [ + "database", + "orm" + ], + "time": "2019-11-19T08:38:05+00:00" + }, + { + "name": "doctrine/persistence", + "version": "1.3.6", + "source": { + "type": "git", + "url": "https://github.com/doctrine/persistence.git", + "reference": "5dd3ac5eebef2d0b074daa4440bb18f93132dee4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/5dd3ac5eebef2d0b074daa4440bb18f93132dee4", + "reference": "5dd3ac5eebef2d0b074daa4440bb18f93132dee4", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/reflection": "^1.1", + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.10@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common", + "Doctrine\\Persistence\\": "lib/Doctrine/Persistence" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", + "homepage": "https://doctrine-project.org/projects/persistence.html", + "keywords": [ + "mapper", + "object", + "odm", + "orm", + "persistence" + ], + "time": "2020-01-16T22:06:23+00:00" + }, + { + "name": "doctrine/reflection", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/reflection.git", + "reference": "bc420ead87fdfe08c03ecc3549db603a45b06d4c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/reflection/zipball/bc420ead87fdfe08c03ecc3549db603a45b06d4c", + "reference": "bc420ead87fdfe08c03ecc3549db603a45b06d4c", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "ext-tokenizer": "*", + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.9" + }, + "require-dev": { + "doctrine/coding-standard": "^5.0", + "doctrine/common": "^2.10", + "phpstan/phpstan": "^0.11.0", + "phpstan/phpstan-phpunit": "^0.11.0", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Reflection project is a simple library used by the various Doctrine projects which adds some additional functionality on top of the reflection functionality that comes with PHP. It allows you to get the reflection information about classes, methods and properties statically.", + "homepage": "https://www.doctrine-project.org/projects/reflection.html", + "keywords": [ + "reflection", + "static" + ], + "time": "2020-01-08T19:53:19+00:00" + }, + { + "name": "hoa/compiler", + "version": "3.17.08.08", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Compiler.git", + "reference": "aa09caf0bf28adae6654ca6ee415ee2f522672de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Compiler/zipball/aa09caf0bf28adae6654ca6ee415ee2f522672de", + "reference": "aa09caf0bf28adae6654ca6ee415ee2f522672de", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0", + "hoa/file": "~1.0", + "hoa/iterator": "~2.0", + "hoa/math": "~1.0", + "hoa/protocol": "~1.0", + "hoa/regex": "~1.0", + "hoa/visitor": "~2.0" + }, + "require-dev": { + "hoa/json": "~2.0", + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Compiler\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Compiler library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "algebraic", + "ast", + "compiler", + "context-free", + "coverage", + "exhaustive", + "grammar", + "isotropic", + "language", + "lexer", + "library", + "ll1", + "llk", + "parser", + "pp", + "random", + "regular", + "rule", + "sampler", + "syntax", + "token", + "trace", + "uniform" + ], + "time": "2017-08-08T07:44:07+00:00" + }, + { + "name": "hoa/consistency", + "version": "1.17.05.02", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Consistency.git", + "reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Consistency/zipball/fd7d0adc82410507f332516faf655b6ed22e4c2f", + "reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f", + "shasum": "" + }, + "require": { + "hoa/exception": "~1.0", + "php": ">=5.5.0" + }, + "require-dev": { + "hoa/stream": "~1.0", + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Consistency\\": "." + }, + "files": [ + "Prelude.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Consistency library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "autoloader", + "callable", + "consistency", + "entity", + "flex", + "keyword", + "library" + ], + "time": "2017-05-02T12:18:12+00:00" + }, + { + "name": "hoa/event", + "version": "1.17.01.13", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Event.git", + "reference": "6c0060dced212ffa3af0e34bb46624f990b29c54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Event/zipball/6c0060dced212ffa3af0e34bb46624f990b29c54", + "reference": "6c0060dced212ffa3af0e34bb46624f990b29c54", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Event\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Event library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "event", + "library", + "listener", + "observer" + ], + "time": "2017-01-13T15:30:50+00:00" + }, + { + "name": "hoa/exception", + "version": "1.17.01.16", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Exception.git", + "reference": "091727d46420a3d7468ef0595651488bfc3a458f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Exception/zipball/091727d46420a3d7468ef0595651488bfc3a458f", + "reference": "091727d46420a3d7468ef0595651488bfc3a458f", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/event": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Exception\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Exception library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "exception", + "library" + ], + "time": "2017-01-16T07:53:27+00:00" + }, + { + "name": "hoa/file", + "version": "1.17.07.11", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/File.git", + "reference": "35cb979b779bc54918d2f9a4e02ed6c7a1fa67ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/File/zipball/35cb979b779bc54918d2f9a4e02ed6c7a1fa67ca", + "reference": "35cb979b779bc54918d2f9a4e02ed6c7a1fa67ca", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/event": "~1.0", + "hoa/exception": "~1.0", + "hoa/iterator": "~2.0", + "hoa/stream": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\File\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\File library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "Socket", + "directory", + "file", + "finder", + "library", + "link", + "temporary" + ], + "time": "2017-07-11T07:42:15+00:00" + }, + { + "name": "hoa/iterator", + "version": "2.17.01.10", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Iterator.git", + "reference": "d1120ba09cb4ccd049c86d10058ab94af245f0cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Iterator/zipball/d1120ba09cb4ccd049c86d10058ab94af245f0cc", + "reference": "d1120ba09cb4ccd049c86d10058ab94af245f0cc", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Iterator\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Iterator library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "iterator", + "library" + ], + "time": "2017-01-10T10:34:47+00:00" + }, + { + "name": "hoa/math", + "version": "1.17.05.16", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Math.git", + "reference": "7150785d30f5d565704912116a462e9f5bc83a0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Math/zipball/7150785d30f5d565704912116a462e9f5bc83a0c", + "reference": "7150785d30f5d565704912116a462e9f5bc83a0c", + "shasum": "" + }, + "require": { + "hoa/compiler": "~3.0", + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0", + "hoa/iterator": "~2.0", + "hoa/protocol": "~1.0", + "hoa/zformat": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Math\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Math library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "arrangement", + "combination", + "combinatorics", + "counting", + "library", + "math", + "permutation", + "sampler", + "set" + ], + "time": "2017-05-16T08:02:17+00:00" + }, + { + "name": "hoa/protocol", + "version": "1.17.01.14", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Protocol.git", + "reference": "5c2cf972151c45f373230da170ea015deecf19e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Protocol/zipball/5c2cf972151c45f373230da170ea015deecf19e2", + "reference": "5c2cf972151c45f373230da170ea015deecf19e2", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Protocol\\": "." + }, + "files": [ + "Wrapper.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Protocol library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "library", + "protocol", + "resource", + "stream", + "wrapper" + ], + "time": "2017-01-14T12:26:10+00:00" + }, + { + "name": "hoa/regex", + "version": "1.17.01.13", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Regex.git", + "reference": "7e263a61b6fb45c1d03d8e5ef77668518abd5bec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Regex/zipball/7e263a61b6fb45c1d03d8e5ef77668518abd5bec", + "reference": "7e263a61b6fb45c1d03d8e5ef77668518abd5bec", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0", + "hoa/math": "~1.0", + "hoa/protocol": "~1.0", + "hoa/ustring": "~4.0", + "hoa/visitor": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Regex\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Regex library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "compiler", + "library", + "regex" + ], + "time": "2017-01-13T16:10:24+00:00" + }, + { + "name": "hoa/stream", + "version": "1.17.02.21", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Stream.git", + "reference": "3293cfffca2de10525df51436adf88a559151d82" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Stream/zipball/3293cfffca2de10525df51436adf88a559151d82", + "reference": "3293cfffca2de10525df51436adf88a559151d82", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/event": "~1.0", + "hoa/exception": "~1.0", + "hoa/protocol": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Stream\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Stream library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "Context", + "bucket", + "composite", + "filter", + "in", + "library", + "out", + "protocol", + "stream", + "wrapper" + ], + "time": "2017-02-21T16:01:06+00:00" + }, + { + "name": "hoa/ustring", + "version": "4.17.01.16", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Ustring.git", + "reference": "e6326e2739178799b1fe3fdd92029f9517fa17a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Ustring/zipball/e6326e2739178799b1fe3fdd92029f9517fa17a0", + "reference": "e6326e2739178799b1fe3fdd92029f9517fa17a0", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "suggest": { + "ext-iconv": "ext/iconv must be present (or a third implementation) to use Hoa\\Ustring::transcode().", + "ext-intl": "To get a better Hoa\\Ustring::toAscii() and Hoa\\Ustring::compareTo()." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Ustring\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Ustring library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "library", + "search", + "string", + "unicode" + ], + "time": "2017-01-16T07:08:25+00:00" + }, + { + "name": "hoa/visitor", + "version": "2.17.01.16", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Visitor.git", + "reference": "c18fe1cbac98ae449e0d56e87469103ba08f224a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Visitor/zipball/c18fe1cbac98ae449e0d56e87469103ba08f224a", + "reference": "c18fe1cbac98ae449e0d56e87469103ba08f224a", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Visitor\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Visitor library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "library", + "structure", + "visit", + "visitor" + ], + "time": "2017-01-16T07:02:03+00:00" + }, + { + "name": "hoa/zformat", + "version": "1.17.01.10", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Zformat.git", + "reference": "522c381a2a075d4b9dbb42eb4592dd09520e4ac2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Zformat/zipball/522c381a2a075d4b9dbb42eb4592dd09520e4ac2", + "reference": "522c381a2a075d4b9dbb42eb4592dd09520e4ac2", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Zformat\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Zformat library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "library", + "parameter", + "zformat" + ], + "time": "2017-01-10T10:39:54+00:00" + }, + { + "name": "jms/metadata", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/metadata.git", + "reference": "8d8958103485c2cbdd9a9684c3869312ebdaf73a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/8d8958103485c2cbdd9a9684c3869312ebdaf73a", + "reference": "8d8958103485c2cbdd9a9684c3869312ebdaf73a", + "shasum": "" + }, + "require": { + "php": "^7.2" + }, + "require-dev": { + "doctrine/cache": "^1.0", + "doctrine/coding-standard": "^4.0", + "phpunit/phpunit": "^7.0", + "symfony/cache": "^3.1|^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Metadata\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "Class/method/property metadata management in PHP", + "keywords": [ + "annotations", + "metadata", + "xml", + "yaml" + ], + "time": "2019-09-17T15:30:40+00:00" + }, + { + "name": "jms/serializer", + "version": "3.4.0", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/serializer.git", + "reference": "e2d3c49d9322a08ee32221a5623c898160dada79" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/e2d3c49d9322a08ee32221a5623c898160dada79", + "reference": "e2d3c49d9322a08ee32221a5623c898160dada79", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/instantiator": "^1.0.3", + "hoa/compiler": "^3.17.08.08", + "jms/metadata": "^2.0", + "php": "^7.2" + }, + "conflict": { + "hoa/consistency": "<1.17.05.02", + "hoa/core": "*", + "hoa/iterator": "<2.16.03.15" + }, + "require-dev": { + "doctrine/coding-standard": "^5.0", + "doctrine/orm": "~2.1", + "doctrine/phpcr-odm": "^1.3|^2.0", + "ext-pdo_sqlite": "*", + "jackalope/jackalope-doctrine-dbal": "^1.1.5", + "ocramius/proxy-manager": "^1.0|^2.0", + "phpunit/phpunit": "^7.5||^8.0", + "psr/container": "^1.0", + "symfony/dependency-injection": "^3.0|^4.0|^5.0", + "symfony/expression-language": "^3.0|^4.0|^5.0", + "symfony/filesystem": "^3.0|^4.0|^5.0", + "symfony/form": "^3.0|^4.0|^5.0", + "symfony/translation": "^3.0|^4.0|^5.0", + "symfony/validator": "^3.1.9|^4.0|^5.0", + "symfony/yaml": "^3.3|^4.0|^5.0", + "twig/twig": "~1.34|~2.4" + }, + "suggest": { + "doctrine/cache": "Required if you like to use cache functionality.", + "doctrine/collections": "Required if you like to use doctrine collection types as ArrayCollection.", + "symfony/yaml": "Required if you'd like to use the YAML metadata format." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "JMS\\Serializer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "Library for (de-)serializing data of any complexity; supports XML, JSON, and YAML.", + "homepage": "http://jmsyst.com/libs/serializer", + "keywords": [ + "deserialization", + "jaxb", + "json", + "serialization", + "xml" + ], + "time": "2019-12-14T20:49:23+00:00" + }, + { + "name": "jms/serializer-bundle", + "version": "3.5.0", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/JMSSerializerBundle.git", + "reference": "5793ec59b2243365a625c0fd78415732097c11e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/JMSSerializerBundle/zipball/5793ec59b2243365a625c0fd78415732097c11e8", + "reference": "5793ec59b2243365a625c0fd78415732097c11e8", + "shasum": "" + }, + "require": { + "jms/serializer": "^2.3|^3.0", + "php": "^7.2", + "symfony/dependency-injection": "^3.3 || ^4.0 || ^5.0", + "symfony/framework-bundle": "^3.0 || ^4.0 || ^5.0" + }, + "require-dev": { + "doctrine/orm": "^2.4", + "phpunit/phpunit": "^6.0", + "symfony/expression-language": "^3.0 || ^4.0 || ^5.0", + "symfony/finder": "^3.0 || ^4.0 || ^5.0", + "symfony/form": "^3.0 || ^4.0 || ^5.0", + "symfony/stopwatch": "^3.0 || ^4.0 || ^5.0", + "symfony/twig-bundle": "*", + "symfony/validator": "^3.0 || ^4.0 || ^5.0", + "symfony/yaml": "^3.0 || ^4.0 || ^5.0" + }, + "suggest": { + "jms/di-extra-bundle": "Required to get lazy loading (de)serialization visitors, ^1.3", + "symfony/finder": "Required for cache warmup, supported versions ^3.0|^4.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "3.5-dev" + } + }, + "autoload": { + "psr-4": { + "JMS\\SerializerBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "Allows you to easily serialize, and deserialize data of any complexity", + "homepage": "http://jmsyst.com/bundles/JMSSerializerBundle", + "keywords": [ + "deserialization", + "json", + "serialization", + "xml" + ], + "time": "2019-11-29T13:03:07+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v9.99.99", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "shasum": "" + }, + "require": { + "php": "^7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "time": "2018-07-02T15:55:56+00:00" + }, + { + "name": "psr/cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "time": "2016-08-06T20:24:11+00:00" + }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/log", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2019-11-01T11:05:21+00:00" + }, + { + "name": "ramsey/uuid", + "version": "3.9.2", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "7779489a47d443f845271badbdcedfe4df8e06fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/7779489a47d443f845271badbdcedfe4df8e06fb", + "reference": "7779489a47d443f845271badbdcedfe4df8e06fb", + "shasum": "" + }, + "require": { + "ext-json": "*", + "paragonie/random_compat": "^1 | ^2 | 9.99.99", + "php": "^5.4 | ^7 | ^8", + "symfony/polyfill-ctype": "^1.8" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "codeception/aspect-mock": "^1 | ^2", + "doctrine/annotations": "^1.2", + "goaop/framework": "1.0.0-alpha.2 | ^1 | ^2.1", + "jakub-onderka/php-parallel-lint": "^1", + "mockery/mockery": "^0.9.11 | ^1", + "moontoast/math": "^1.1", + "paragonie/random-lib": "^2", + "php-mock/php-mock-phpunit": "^0.3 | ^1.1", + "phpunit/phpunit": "^4.8 | ^5.4 | ^6.5", + "squizlabs/php_codesniffer": "^3.5" + }, + "suggest": { + "ext-ctype": "Provides support for PHP Ctype functions", + "ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator", + "ext-openssl": "Provides the OpenSSL extension for use with the OpenSslGenerator", + "ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator", + "moontoast/math": "Provides support for converting UUID to 128-bit integer (in string form).", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-console": "A console application for generating UUIDs with ramsey/uuid", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Uuid\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + }, + { + "name": "Marijn Huizendveld", + "email": "marijn.huizendveld@gmail.com" + }, + { + "name": "Thibaud Fabre", + "email": "thibaud@aztech.io" + } + ], + "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", + "homepage": "https://github.com/ramsey/uuid", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "time": "2019-12-17T08:18:51+00:00" + }, + { + "name": "ramsey/uuid-doctrine", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid-doctrine.git", + "reference": "2a56db8e68bff487508244f5a2008075279d0255" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid-doctrine/zipball/2a56db8e68bff487508244f5a2008075279d0255", + "reference": "2a56db8e68bff487508244f5a2008075279d0255", + "shasum": "" + }, + "require": { + "doctrine/orm": "^2.5", + "php": "^5.4 || ^7.0", + "ramsey/uuid": "^3.0" + }, + "require-dev": { + "jakub-onderka/php-parallel-lint": "^1.0", + "mockery/mockery": "^0.9 || ^1.1", + "php-coveralls/php-coveralls": "^1.1 || ^2.1", + "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5", + "squizlabs/php_codesniffer": "^3.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Ramsey\\Uuid\\Doctrine\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marijn Huizendveld", + "email": "marijn.huizendveld@gmail.com" + }, + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "http://benramsey.com" + } + ], + "description": "Allow the use of a ramsey/uuid UUID as Doctrine field type.", + "homepage": "https://github.com/ramsey/uuid-doctrine", + "keywords": [ + "doctrine", + "guid", + "identifier", + "uuid" + ], + "time": "2018-08-11T21:01:22+00:00" + }, + { + "name": "retailcrm/api-client-php", + "version": "dev-add-logger", + "source": { + "type": "git", + "url": "https://github.com/raulleo/api-client-php.git", + "reference": "55c444e038c9741dee739f9b6c0acbe8f8247bd6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/raulleo/api-client-php/zipball/55c444e038c9741dee739f9b6c0acbe8f8247bd6", + "reference": "55c444e038c9741dee739f9b6c0acbe8f8247bd6", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "php": ">=5.4.0", + "psr/log": "^1.1" + }, + "require-dev": { + "apigen/apigen": "4.*", + "phpunit/phpunit": "4.*", + "squizlabs/php_codesniffer": "3.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-0": { + "RetailCrm\\": "lib/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "retailCRM", + "email": "support@retailcrm.ru" + } + ], + "description": "PHP client for retailCRM API", + "homepage": "http://www.retailcrm.ru/", + "keywords": [ + "API", + "REST", + "retailCRM" + ], + "support": { + "email": "support@retailcrm.ru", + "source": "https://github.com/raulleo/api-client-php/tree/add-logger" + }, + "time": "2019-08-29T15:00:10+00:00" + }, + { + "name": "symfony/cache", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "6e8d978878ae5de705ec9fabbb6011cc18776bc9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/6e8d978878ae5de705ec9fabbb6011cc18776bc9", + "reference": "6e8d978878ae5de705ec9fabbb6011cc18776bc9", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/cache": "~1.0", + "psr/log": "~1.0", + "symfony/cache-contracts": "^1.1.7|^2", + "symfony/service-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0" + }, + "conflict": { + "doctrine/dbal": "<2.5", + "symfony/dependency-injection": "<4.4", + "symfony/http-kernel": "<4.4", + "symfony/var-dumper": "<4.4" + }, + "provide": { + "psr/cache-implementation": "1.0", + "psr/simple-cache-implementation": "1.0", + "symfony/cache-implementation": "1.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/cache": "~1.6", + "doctrine/dbal": "~2.5", + "predis/predis": "~1.1", + "psr/simple-cache": "^1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Cache\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Cache component with PSR-6, PSR-16, and tags", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ], + "time": "2019-12-12T13:03:32+00:00" + }, + { + "name": "symfony/cache-contracts", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16", + "reference": "23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/cache": "^1.0" + }, + "suggest": { + "symfony/cache-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Cache\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to caching", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/config", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "7f930484966350906185ba0a604728f7898b7ba0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/7f930484966350906185ba0a604728f7898b7ba0", + "reference": "7f930484966350906185ba0a604728f7898b7ba0", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/filesystem": "^4.4|^5.0", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/finder": "<4.4" + }, + "require-dev": { + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Config Component", + "homepage": "https://symfony.com", + "time": "2019-12-18T13:50:31+00:00" + }, + { + "name": "symfony/console", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "fe6e3cd889ca64172d7a742a2eb058541404ef47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/fe6e3cd889ca64172d7a742a2eb058541404ef47", + "reference": "fe6e3cd889ca64172d7a742a2eb058541404ef47", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/service-contracts": "^1.1|^2" + }, + "conflict": { + "symfony/dependency-injection": "<4.4", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2019-12-17T13:20:22+00:00" + }, + { + "name": "symfony/dependency-injection", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "f9dbfbf487d08f60b1c83220edcd16559d1e40a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f9dbfbf487d08f60b1c83220edcd16559d1e40a2", + "reference": "f9dbfbf487d08f60b1c83220edcd16559d1e40a2", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/container": "^1.0", + "symfony/service-contracts": "^1.1.6|^2" + }, + "conflict": { + "symfony/config": "<5.0", + "symfony/finder": "<4.4", + "symfony/proxy-manager-bridge": "<4.4", + "symfony/yaml": "<4.4" + }, + "provide": { + "psr/container-implementation": "1.0", + "symfony/service-implementation": "1.0" + }, + "require-dev": { + "symfony/config": "^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DependencyInjection Component", + "homepage": "https://symfony.com", + "time": "2019-12-19T16:01:11+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "460863313bd3212d7c38e1b40602cbcfeeeea4a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/460863313bd3212d7c38e1b40602cbcfeeeea4a5", + "reference": "460863313bd3212d7c38e1b40602cbcfeeeea4a5", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/log": "^1.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "require-dev": { + "symfony/http-kernel": "^4.4|^5.0", + "symfony/serializer": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony ErrorHandler Component", + "homepage": "https://symfony.com", + "time": "2019-12-16T14:48:47+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "7b738a51645e10f864cc25c24d232fb03f37b475" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7b738a51645e10f864cc25c24d232fb03f37b475", + "reference": "7b738a51645e10f864cc25c24d232fb03f37b475", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/event-dispatcher-contracts": "^2" + }, + "conflict": { + "symfony/dependency-injection": "<4.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/stopwatch": "^4.4|^5.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "af23c2584d4577d54661c434446fb8fbed6025dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/af23c2584d4577d54661c434446fb8fbed6025dd", + "reference": "af23c2584d4577d54661c434446fb8fbed6025dd", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "1d71f670bc5a07b9ccc97dc44f932177a322d4e6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/1d71f670bc5a07b9ccc97dc44f932177a322d4e6", + "reference": "1d71f670bc5a07b9ccc97dc44f932177a322d4e6", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2019-11-26T23:25:11+00:00" + }, + { + "name": "symfony/finder", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "17874dd8ab9a19422028ad56172fb294287a701b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/17874dd8ab9a19422028ad56172fb294287a701b", + "reference": "17874dd8ab9a19422028ad56172fb294287a701b", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/framework-bundle", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/framework-bundle.git", + "reference": "36e51776b231d8e224da4ce4c60079540acd1c55" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/36e51776b231d8e224da4ce4c60079540acd1c55", + "reference": "36e51776b231d8e224da4ce4c60079540acd1c55", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": "^7.2.5", + "symfony/cache": "^4.4|^5.0", + "symfony/config": "^5.0", + "symfony/dependency-injection": "^5.0.1", + "symfony/error-handler": "^4.4.1|^5.0.1", + "symfony/filesystem": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/http-kernel": "^5.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/routing": "^5.0" + }, + "conflict": { + "doctrine/persistence": "<1.3", + "phpdocumentor/reflection-docblock": "<3.0", + "phpdocumentor/type-resolver": "<0.2.1", + "phpunit/phpunit": "<5.4.3", + "symfony/asset": "<4.4", + "symfony/browser-kit": "<4.4", + "symfony/console": "<4.4", + "symfony/dom-crawler": "<4.4", + "symfony/dotenv": "<4.4", + "symfony/form": "<4.4", + "symfony/http-client": "<4.4", + "symfony/lock": "<4.4", + "symfony/mailer": "<4.4", + "symfony/messenger": "<4.4", + "symfony/mime": "<4.4", + "symfony/property-info": "<4.4", + "symfony/serializer": "<4.4", + "symfony/stopwatch": "<4.4", + "symfony/translation": "<5.0", + "symfony/twig-bridge": "<4.4", + "symfony/twig-bundle": "<4.4", + "symfony/validator": "<4.4", + "symfony/web-profiler-bundle": "<4.4", + "symfony/workflow": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "~1.7", + "doctrine/cache": "~1.0", + "paragonie/sodium_compat": "^1.8", + "phpdocumentor/reflection-docblock": "^3.0|^4.0", + "symfony/asset": "^4.4|^5.0", + "symfony/browser-kit": "^4.4|^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/css-selector": "^4.4|^5.0", + "symfony/dom-crawler": "^4.4|^5.0", + "symfony/dotenv": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/form": "^4.4|^5.0", + "symfony/http-client": "^4.4|^5.0", + "symfony/lock": "^4.4|^5.0", + "symfony/mailer": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/mime": "^4.4|^5.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/process": "^4.4|^5.0", + "symfony/property-info": "^4.4|^5.0", + "symfony/security-csrf": "^4.4|^5.0", + "symfony/security-http": "^4.4|^5.0", + "symfony/serializer": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/string": "~5.0.0", + "symfony/translation": "^5.0", + "symfony/twig-bundle": "^4.4|^5.0", + "symfony/validator": "^4.4|^5.0", + "symfony/web-link": "^4.4|^5.0", + "symfony/workflow": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0", + "twig/twig": "^2.10|^3.0" + }, + "suggest": { + "ext-apcu": "For best performance of the system caches", + "symfony/console": "For using the console commands", + "symfony/form": "For using forms", + "symfony/property-info": "For using the property_info service", + "symfony/serializer": "For using the serializer service", + "symfony/validator": "For using validation", + "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering", + "symfony/yaml": "For using the debug:config and lint:yaml commands" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\FrameworkBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony FrameworkBundle", + "homepage": "https://symfony.com", + "time": "2019-12-17T10:33:13+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "5dd7f6be6e62d86ba6f3154cf40e78936367978b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/5dd7f6be6e62d86ba6f3154cf40e78936367978b", + "reference": "5dd7f6be6e62d86ba6f3154cf40e78936367978b", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/mime": "^4.4|^5.0", + "symfony/polyfill-mbstring": "~1.1" + }, + "require-dev": { + "predis/predis": "~1.0", + "symfony/expression-language": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "https://symfony.com", + "time": "2019-12-19T16:01:11+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "00ce30602f3f690e66a63c327743d7b26c723b2e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/00ce30602f3f690e66a63c327743d7b26c723b2e", + "reference": "00ce30602f3f690e66a63c327743d7b26c723b2e", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/log": "~1.0", + "symfony/error-handler": "^4.4|^5.0", + "symfony/event-dispatcher": "^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php73": "^1.9" + }, + "conflict": { + "symfony/browser-kit": "<4.4", + "symfony/cache": "<5.0", + "symfony/config": "<5.0", + "symfony/dependency-injection": "<4.4", + "symfony/doctrine-bridge": "<5.0", + "symfony/form": "<5.0", + "symfony/http-client": "<5.0", + "symfony/mailer": "<5.0", + "symfony/messenger": "<5.0", + "symfony/translation": "<5.0", + "symfony/twig-bridge": "<5.0", + "symfony/validator": "<5.0", + "twig/twig": "<2.4" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/cache": "~1.0", + "symfony/browser-kit": "^4.4|^5.0", + "symfony/config": "^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/css-selector": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/dom-crawler": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/routing": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", + "symfony/translation-contracts": "^1.1|^2", + "twig/twig": "^2.4|^3.0" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpKernel Component", + "homepage": "https://symfony.com", + "time": "2019-12-19T18:35:03+00:00" + }, + { + "name": "symfony/lock", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/lock.git", + "reference": "7ccaee23cc5b8884c9700eef4ccee03f85ff7821" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/lock/zipball/7ccaee23cc5b8884c9700eef4ccee03f85ff7821", + "reference": "7ccaee23cc5b8884c9700eef4ccee03f85ff7821", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/log": "~1.0" + }, + "conflict": { + "doctrine/dbal": "<2.5" + }, + "require-dev": { + "doctrine/dbal": "~2.5", + "mongodb/mongodb": "~1.1", + "predis/predis": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Lock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jérémy Derussé", + "email": "jeremy@derusse.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Lock Component", + "homepage": "https://symfony.com", + "keywords": [ + "cas", + "flock", + "locking", + "mutex", + "redlock", + "semaphore" + ], + "time": "2019-12-03T16:35:18+00:00" + }, + { + "name": "symfony/mime", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "0e6a4ced216e49d457eddcefb61132173a876d79" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/0e6a4ced216e49d457eddcefb61132173a876d79", + "reference": "0e6a4ced216e49d457eddcefb61132173a876d79", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "symfony/mailer": "<4.4" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10", + "symfony/dependency-injection": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A library to manipulate MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "time": "2019-11-30T14:12:50+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.13.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", + "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2019-11-27T13:56:44+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.13.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "6f9c239e61e1b0c9229a28ff89a812dc449c3d46" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/6f9c239e61e1b0c9229a28ff89a812dc449c3d46", + "reference": "6f9c239e61e1b0c9229a28ff89a812dc449c3d46", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php72": "^1.9" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "time": "2019-11-27T13:56:44+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.13.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7b4aab9743c30be783b73de055d24a39cf4b954f", + "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2019-11-27T14:18:11+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.13.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "66fea50f6cb37a35eea048d75a7d99a45b586038" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/66fea50f6cb37a35eea048d75a7d99a45b586038", + "reference": "66fea50f6cb37a35eea048d75a7d99a45b586038", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2019-11-27T13:56:44+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.13.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/4b0e2222c55a25b4541305a053013d5647d3a25f", + "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2019-11-27T16:25:15+00:00" + }, + { + "name": "symfony/routing", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "120c5fa4f4ef5466cbb510ece8126e0007285301" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/120c5fa4f4ef5466cbb510ece8126e0007285301", + "reference": "120c5fa4f4ef5466cbb510ece8126e0007285301", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "conflict": { + "symfony/config": "<5.0", + "symfony/dependency-injection": "<4.4", + "symfony/yaml": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "~1.2", + "psr/log": "~1.0", + "symfony/config": "^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation loader", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/expression-language": "For using expression matching", + "symfony/http-foundation": "For using a Symfony Request object", + "symfony/yaml": "For using the YAML loader" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Routing Component", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "time": "2019-12-12T13:03:32+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "144c5e51266b281231e947b51223ba14acf1a749" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/144c5e51266b281231e947b51223ba14acf1a749", + "reference": "144c5e51266b281231e947b51223ba14acf1a749", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/container": "^1.0" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/translation", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "3ae6fad7a3dc2d99a023f9360184628fc44acbb3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/3ae6fad7a3dc2d99a023f9360184628fc44acbb3", + "reference": "3ae6fad7a3dc2d99a023f9360184628fc44acbb3", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2" + }, + "conflict": { + "symfony/config": "<4.4", + "symfony/dependency-injection": "<5.0", + "symfony/http-kernel": "<5.0", + "symfony/twig-bundle": "<5.0", + "symfony/yaml": "<4.4" + }, + "provide": { + "symfony/translation-implementation": "2.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/dependency-injection": "^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/http-kernel": "^5.0", + "symfony/intl": "^4.4|^5.0", + "symfony/service-contracts": "^1.1.2|^2", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "psr/log-implementation": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Translation Component", + "homepage": "https://symfony.com", + "time": "2019-12-12T13:03:32+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "8cc682ac458d75557203b2f2f14b0b92e1c744ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/8cc682ac458d75557203b2f2f14b0b92e1c744ed", + "reference": "8cc682ac458d75557203b2f2f14b0b92e1c744ed", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "suggest": { + "symfony/translation-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a", + "reference": "d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/console": "<4.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "twig/twig": "^2.4|^3.0" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "time": "2019-12-18T13:50:31+00:00" + }, + { + "name": "symfony/var-exporter", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "1b9653e68d5b701bf6d9c91bdd3660078c9f4f28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/1b9653e68d5b701bf6d9c91bdd3660078c9f4f28", + "reference": "1b9653e68d5b701bf6d9c91bdd3660078c9f4f28", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "require-dev": { + "symfony/var-dumper": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A blend of var_export() + serialize() to turn any serializable data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "serialize" + ], + "time": "2019-12-01T08:48:26+00:00" + } + ], + "packages-dev": [ + { + "name": "doctrine/data-fixtures", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/data-fixtures.git", + "reference": "39e9777c9089351a468f780b01cffa3cb0a42907" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/39e9777c9089351a468f780b01cffa3cb0a42907", + "reference": "39e9777c9089351a468f780b01cffa3cb0a42907", + "shasum": "" + }, + "require": { + "doctrine/common": "^2.11", + "doctrine/persistence": "^1.3.3", + "php": "^7.2" + }, + "conflict": { + "doctrine/phpcr-odm": "<1.3.0" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "doctrine/coding-standard": "^6.0", + "doctrine/dbal": "^2.5.4", + "doctrine/mongodb-odm": "^1.3.0", + "doctrine/orm": "^2.7.0", + "phpunit/phpunit": "^7.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "For using MongoDB ODM with PHP 7", + "doctrine/mongodb-odm": "For loading MongoDB ODM fixtures", + "doctrine/orm": "For loading ORM fixtures", + "doctrine/phpcr-odm": "For loading PHPCR ODM fixtures" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\DataFixtures\\": "lib/Doctrine/Common/DataFixtures" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Data Fixtures for all Doctrine Object Managers", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database" + ], + "time": "2020-01-17T11:11:28+00:00" + }, + { + "name": "doctrine/doctrine-bundle", + "version": "2.0.6", + "source": { + "type": "git", + "url": "https://github.com/doctrine/DoctrineBundle.git", + "reference": "0ef972d3b730f975c80db9fffa4b2a0258c91442" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/0ef972d3b730f975c80db9fffa4b2a0258c91442", + "reference": "0ef972d3b730f975c80db9fffa4b2a0258c91442", + "shasum": "" + }, + "require": { + "doctrine/dbal": "^2.9.0", + "doctrine/persistence": "^1.3.3", + "jdorn/sql-formatter": "^1.2.16", + "php": "^7.1", + "symfony/cache": "^4.3.3|^5.0", + "symfony/config": "^4.3.3|^5.0", + "symfony/console": "^3.4.30|^4.3.3|^5.0", + "symfony/dependency-injection": "^4.3.3|^5.0", + "symfony/doctrine-bridge": "^4.3.7|^5.0", + "symfony/framework-bundle": "^3.4.30|^4.3.3|^5.0", + "symfony/service-contracts": "^1.1.1|^2.0" + }, + "conflict": { + "doctrine/orm": "<2.6", + "twig/twig": "<1.34|>=2.0,<2.4" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "doctrine/orm": "^2.6", + "ocramius/proxy-manager": "^2.1", + "phpunit/phpunit": "^7.5", + "symfony/phpunit-bridge": "^4.2", + "symfony/property-info": "^4.3.3|^5.0", + "symfony/twig-bridge": "^3.4.30|^4.3.3|^5.0", + "symfony/validator": "^3.4.30|^4.3.3|^5.0", + "symfony/web-profiler-bundle": "^3.4.30|^4.3.3|^5.0", + "symfony/yaml": "^3.4.30|^4.3.3|^5.0", + "twig/twig": "^1.34|^2.12" + }, + "suggest": { + "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", + "symfony/web-profiler-bundle": "To use the data collector." + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Bundle\\DoctrineBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Doctrine Project", + "homepage": "http://www.doctrine-project.org/" + } + ], + "description": "Symfony DoctrineBundle", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database", + "dbal", + "orm", + "persistence" + ], + "time": "2019-12-19T13:47:07+00:00" + }, + { + "name": "doctrine/doctrine-fixtures-bundle", + "version": "3.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/DoctrineFixturesBundle.git", + "reference": "8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/DoctrineFixturesBundle/zipball/8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70", + "reference": "8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70", + "shasum": "" + }, + "require": { + "doctrine/data-fixtures": "^1.3", + "doctrine/doctrine-bundle": "^1.11|^2.0", + "doctrine/orm": "^2.6.0", + "php": "^7.1", + "symfony/config": "^3.4|^4.3|^5.0", + "symfony/console": "^3.4|^4.3|^5.0", + "symfony/dependency-injection": "^3.4|^4.3|^5.0", + "symfony/doctrine-bridge": "^3.4|^4.1|^5.0", + "symfony/http-kernel": "^3.4|^4.3|^5.0" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpunit/phpunit": "^7.4", + "symfony/phpunit-bridge": "^4.1|^5.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "3.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Bundle\\FixturesBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Doctrine Project", + "homepage": "http://www.doctrine-project.org" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony DoctrineFixturesBundle", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "Fixture", + "persistence" + ], + "time": "2019-11-13T15:46:58+00:00" + }, + { + "name": "jdorn/sql-formatter", + "version": "v1.2.17", + "source": { + "type": "git", + "url": "https://github.com/jdorn/sql-formatter.git", + "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jdorn/sql-formatter/zipball/64990d96e0959dff8e059dfcdc1af130728d92bc", + "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc", + "shasum": "" + }, + "require": { + "php": ">=5.2.4" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "lib" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeremy Dorn", + "email": "jeremy@jeremydorn.com", + "homepage": "http://jeremydorn.com/" + } + ], + "description": "a PHP SQL highlighting library", + "homepage": "https://github.com/jdorn/sql-formatter/", + "keywords": [ + "highlight", + "sql" + ], + "time": "2014-01-12T16:20:24+00:00" + }, + { + "name": "symfony/doctrine-bridge", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/doctrine-bridge.git", + "reference": "0bdb2d31741cacacb95130d28fbac939c4d574f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/0bdb2d31741cacacb95130d28fbac939c4d574f2", + "reference": "0bdb2d31741cacacb95130d28fbac939c4d574f2", + "shasum": "" + }, + "require": { + "doctrine/event-manager": "~1.0", + "doctrine/persistence": "^1.3", + "php": "^7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2" + }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/dependency-injection": "<4.4", + "symfony/form": "<5", + "symfony/http-kernel": "<5", + "symfony/messenger": "<4.4", + "symfony/property-info": "<5", + "symfony/security-bundle": "<5", + "symfony/security-core": "<5", + "symfony/validator": "<5.0.2" + }, + "require-dev": { + "doctrine/annotations": "~1.7", + "doctrine/cache": "~1.6", + "doctrine/collections": "~1.0", + "doctrine/data-fixtures": "1.0.*", + "doctrine/dbal": "~2.4", + "doctrine/orm": "^2.6.3", + "doctrine/reflection": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/form": "^5.0", + "symfony/http-kernel": "^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/property-access": "^4.4|^5.0", + "symfony/property-info": "^5.0", + "symfony/proxy-manager-bridge": "^4.4|^5.0", + "symfony/security-core": "^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", + "symfony/validator": "^5.0.2", + "symfony/var-dumper": "^4.4|^5.0" + }, + "suggest": { + "doctrine/data-fixtures": "", + "doctrine/dbal": "", + "doctrine/orm": "", + "symfony/form": "", + "symfony/property-info": "", + "symfony/validator": "" + }, + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Doctrine\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Doctrine Bridge", + "homepage": "https://symfony.com", + "time": "2019-12-19T12:10:29+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "retailcrm/api-client-php": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^7.3" + }, + "platform-dev": [] +} diff --git a/docker-compose-test.yml b/docker-compose-test.yml new file mode 100644 index 0000000..7a2bf2a --- /dev/null +++ b/docker-compose-test.yml @@ -0,0 +1,28 @@ +version: '2.1' +services: + automate_app: + image: "gwinn/php:7.1" + working_dir: /automate + user: ${UID:-1000}:${GID:-1000} + volumes: + - ./:/automate + links: + - "automate_db:automate_db" + - "automate_cache:automate_cache" + - "automate_queue:automate_queue" + automate_db: + image: "postgres:9.5" + ports: + - ${POSTGRES_ADDRESS:-127.0.0.1:5432}:5432 + environment: + - POSTGRES_PASSWORD=automate + - POSTGRES_USER=automate + - POSTGRES_DB=automate + automate_cache: + image: "redis:alpine" + ports: + - "6379:6379" + automate_queue: + image: "schickling/beanstalkd:latest" + ports: + - "11300:11300" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..57478ac --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,46 @@ +version: '2.1' +services: + automate_app: + image: "gwinn/php:7.1" + ports: + - "80:8080" + working_dir: /automate + user: ${UID:-1000}:${GID:-1000} + volumes: + - ./:/automate + depends_on: + - automate_db + - automate_db_test + - automate_cache + - automate_queue + links: + - "automate_db:automate_db" + - "automate_db_test:automate_db_test" + - "automate_cache:automate_cache" + - "automate_queue:automate_queue" + command: make run + automate_db: + image: "postgres:9.5" + ports: + - ${POSTGRES_ADDRESS:-127.0.0.1:5432}:5432 + environment: + - POSTGRES_PASSWORD=automate + - POSTGRES_USER=automate + - POSTGRES_DB=automate + automate_db_test: + image: "postgres:9.5" + ports: + - ${POSTGRES_ADDRESS:-127.0.0.1:5434}:5434 + environment: + - PGPORT=5434 + - POSTGRES_PASSWORD=automate + - POSTGRES_USER=automate + - POSTGRES_DB=automate + automate_cache: + image: "redis:alpine" + ports: + - "6379:6379" + automate_queue: + image: "schickling/beanstalkd:latest" + ports: + - "11300:11300"