vendor/boldr/cloudprnt-receipt-printer/src/Controller/CloudPrntController.php line 33

Open in your IDE?
  1. <?php
  2. namespace Boldr\Shop\CloudPrntReceiptPrinterBundle\Controller;
  3. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  4. use Symfony\Component\Routing\Annotation\Route;
  5. use Symfony\Component\HttpFoundation\{ RequestResponseBinaryFileResponse };
  6. use Boldr\Shop\ReceiptPrinterBundle\Printer\PrintJobManager;
  7. use Boldr\Shop\CloudPrntReceiptPrinterBundle\Entity\CloudPrntPrinterConfiguration;
  8. use Boldr\Shop\ReceiptPrinterBundle\Entity\{ Receipt };
  9. use mikehaertl\wkhtmlto\Image;
  10. use Boldr\Shop\CpUtilBinLocator\CpUtilBinLocator;
  11. use Imagick;
  12. use ImagickException;
  13. use Boldr\Shop\ShopBundle\Presenter\Order\OrderPresenter;
  14. use Symfony\Component\HttpKernel\Config\FileLocator;
  15. use Psr\Log\LoggerInterface;
  16. class CloudPrntController extends AbstractController
  17. {
  18.     public static function getSubscribedServices()
  19.     {
  20.         return array_merge(parent::getSubscribedServices(), [
  21.             'print_job_manager' => PrintJobManager::class,
  22.             'order_presenter' => OrderPresenter::class,
  23.             'file_locator' => FileLocator::class,
  24.             'logger' => LoggerInterface::class,
  25.         ]);
  26.     }
  27.     /** @Route("/boldr-api/cloudprnt/{secret}", name="cloudprnt_receipt_printer_print") */
  28.     public function cloudprnt(Request $requeststring $secret)
  29.     {
  30.         $printerConfigurations $this->getDoctrine()->getRepository(CloudPrntPrinterConfiguration::class)->findBySecret($secret);
  31.         if (count($printerConfigurations) === 0)
  32.             throw $this->createNotFoundException();
  33.         $printers array_map(fn($printerConfiguration) => $printerConfiguration->getPrinter(), $printerConfigurations);
  34.         if ($request->getMethod() == 'POST')
  35.         {
  36.             return $this->poll($request$printers);
  37.         }
  38.         elseif ($request->getMethod() == 'GET')
  39.         {
  40.             return $this->print($request$printers);
  41.         }
  42.         elseif ($request->getMethod() == 'DELETE')
  43.         {
  44.             return $this->completed($request$printers);
  45.         }
  46.     }
  47.     private function poll(Request $request, array $printers): Response
  48.     {
  49.         $printJobManager $this->get('print_job_manager');
  50.         $printJobs $printJobManager->getPrintJobs($printers, ['unknown''queued']);
  51.         $data = [];
  52.         // Ignore jobs if printingInProgress
  53.         if (!$request->request->get('printingInProgress'false))
  54.         {
  55.             if (count($printJobs) == 0)
  56.             {
  57.                 $data['jobReady'] = false;
  58.             }
  59.             else
  60.             {
  61.                 $receipt $printJobs[0];
  62.                 $data = [
  63.                     'jobReady' => true,
  64.                     'jobToken' => (string) $receipt->getId(),
  65.                     'mediaTypes' => ['application/vnd.star.raster''application/vnd.star.line''application/vnd.star.starprnt''image/png''image/jpeg''application/vnd.star.starprntcore']
  66.                 ];
  67.             }
  68.         }
  69.         return $this->json($data);
  70.     }
  71.     private function getPrintJobByToken(array $printersstring $jobToken)
  72.     {
  73.         $printJobManager $this->get('print_job_manager');
  74.         $receipt $printJobManager->getPrintJob($printers$jobToken);
  75.         if ($receipt === null)
  76.          // || $receipt->getState() == 'printed')
  77.             return null;
  78.         return $receipt;
  79.     }
  80.     private function print(Request $request, array $printers): Response
  81.     {
  82.         $token $request->query->get('token');
  83.         if ($token === null)
  84.         {
  85.             return $this->json(['error' => 'missing_token_parameter']);
  86.         }
  87.         $printJob $this->getPrintJobByToken($printers$token);
  88.         if ($printJob === null)
  89.             throw $this->createNotFoundException();
  90.         $printer $printJob->getPrinter();
  91.         $mediaType $request->query->get('type');
  92.         $printJob->setState(Receipt::STATE_PRINTING);
  93.         $this->getDoctrine()->getManager()->flush();
  94.         $template $printer->getConfiguration()->getTemplate();
  95.         $orders $printJob->getOrders();
  96.         $customer $orders[0]->getCustomer();
  97.         $state $orders[0]->getState();
  98.         $currency $orders[0]->getCurrency();
  99.         $megaOrder = clone $orders[0];
  100.         $invoiceItems $megaOrder->getInvoiceItems();
  101.         $orderItems $megaOrder->getItems();
  102.         foreach ($orders as $i => $order)
  103.         {
  104.             if ($i !== 0)
  105.             {
  106.                 foreach ($order->getItems() as $orderItem)
  107.                 {
  108.                     $orderItems->add($orderItem);
  109.                     $invoiceItem $orderItem->getInvoiceItem();
  110.                     $invoiceItems->add($invoiceItem);
  111.                 }
  112.                 foreach ($order->getInvoiceItems() as $invoiceItem)
  113.                 {
  114.                     if (!$invoiceItems->contains($invoiceItem))
  115.                     {
  116.                         $invoiceItems->add($invoiceItem);
  117.                     }
  118.                 }
  119.             }
  120.         }
  121.         $orderView $this->get('order_presenter')->createOrderView($megaOrder$printer->getLocale());
  122.         // Separate items by category
  123.         $orderItemViewsByCategoryId = [];
  124.         if ($printer->getSeparateItemsByCategory())
  125.         {
  126.             $printerCategoryIds array_map(fn($category) => $category->getId(), $printer->getCategories());
  127.             foreach ($orderView->getItems() as $orderItemView)
  128.             {
  129.                 $orderItemViewCategoryIds array_map(fn($categoryView) => $categoryView->getId(), $orderItemView->getProduct()->getCategories());
  130.                 $inAny false;
  131.                 foreach ($printerCategoryIds as $id)
  132.                 {
  133.                     if (in_array($id$orderItemViewCategoryIds))
  134.                     {
  135.                         $orderItemViewsByCategoryId[$id][] = $orderItemView;
  136.                         $inAny true;
  137.                         break;
  138.                     }
  139.                 }
  140.                 if (!$inAny && !$printer->getRestrictItemsByCategory())
  141.                 {
  142.                     $orderItemViewsByCategoryId[null][] = $orderItemView;
  143.                 }
  144.             }
  145.         }
  146.         // Generate receipt view
  147.         $templateData $this->getParameter('boldr_cloudprnt_receipt_printer.receipt_templates')[$template];
  148.         $html $this->renderView($templateData['template'], [
  149.             'order' => $orderView,
  150.             'logoUrl' => null,
  151.             'separateItemsByCategory' => $printer->getSeparateItemsByCategory(),
  152.             'categoryTranslations' => array_map(fn($category) => $category->getTranslations()->get($printer->getLocale()), $printer->getCategories()),
  153.             'orderItemsByCategoryId' => $orderItemViewsByCategoryId,
  154.         ]);
  155.         // Render to image
  156.         $stylesheet substr($templateData['stylesheet'], 01) == '@'
  157.             $this->get('file_locator')->locate($templateData['stylesheet'])
  158.             : $this->getParameter('kernel.project_dir') .'/'$templateData['stylesheet'];
  159.         $wkhtmltoimage = new Image([
  160.             'user-style-sheet' => $stylesheet,
  161.             'width' => '518',
  162.             'encoding' => 'utf-8'
  163.         ]);
  164.         $wkhtmltoimage->setPage($html);
  165.         try
  166.         {
  167.             $imagick = new Imagick;
  168.             // $imagick->readImageBlob('');
  169.             $imagick->readImageBlob($wkhtmltoimage->toString());
  170.             $imagick->setImageType(Imagick::IMGTYPE_GRAYSCALE);
  171.             $imagick->setImageFormat('png8');
  172.             $imagick->stripImage();
  173.             $bytes = (string) $imagick;
  174.         }
  175.         catch (ImagickException $ex)
  176.         {
  177.             $this->container->get('logger')->critical('printing failed for receipt token '$token .', requeued: '$ex);
  178.             // If image generation failed for some reason, e.g. empty image string passed,
  179.             // re-queue the receipt to be printed another time.
  180.             $printJob->setState(Receipt::STATE_QUEUED);
  181.             $this->getDoctrine()->getManager()->flush();
  182.             return new Response(''500);
  183.         }
  184.         if (!in_array($mediaType$request->getAcceptableContentTypes()))
  185.         {
  186.             $response = new Response($bytes);
  187.             $response->headers->set('Content-Type''image/png');
  188.             return $response;
  189.         }
  190.         $tmpInput tempnam(sys_get_temp_dir(), 'bcpi');
  191.         rename($tmpInput$tmpInput.'.png');
  192.         $tmpInput .= '.png';
  193.         file_put_contents($tmpInput$bytes);
  194.         // Capture cputil output
  195.         $tmpOutput tempnam(sys_get_temp_dir(), 'bcpo');
  196.         $this->runCpUtilCommand('thermal3 dither buzzer-start 1 scale-to-fit decode '.$mediaType.' '.$tmpInput.' '.$tmpOutput);
  197.         $response = new BinaryFileResponse($tmpOutput);
  198.         $response->headers->set('Content-Type'$mediaType);
  199.         $response->headers->set('X-Star-Buzzerstartpattern''1');
  200.         return $response;
  201.     }
  202.     private function runCpUtilCommand(string $command)
  203.     {
  204.         $cpUtilPath CpUtilBinLocator::getCpUtilBin();
  205.         system($cpUtilPath .' '$command);
  206.     }
  207.     private function completed(Request $request, array $printers): Response
  208.     {
  209.         $printJob $this->getPrintJobByToken($printers$request->query->get('token'));
  210.         if ($printJob === null)
  211.             return $this->createNotFoundException();
  212.         $code $request->query->get('code');
  213.         if ($code)
  214.         {
  215.             if ($code >= 400 && $code 600)
  216.             {
  217.                 $orderNumbers $printJob->getOrders()->map(fn($order) => $order->getNumber() ?? ('ID#'$order->getId()))->toArray();
  218.                 //$this->get('logger')->critical('Print job "'.$printJob->getId().'" (order(s) '. join(', ', $orderNumbers) .') return status '. $code .', retrying.');
  219.                 return $this->json([]);
  220.             }
  221.         }
  222.         $printJob->setState(Receipt::STATE_PRINTED);
  223.         $this->getDoctrine()->getManager()->flush();
  224.         return $this->json([]);
  225.     }
  226.     public function handleClientAction(Request $request)
  227.     {
  228.         $clientActions $request->request->get('clientAction');
  229.         foreach ($clientActions as $clientAction)
  230.         {
  231.             switch ($clientAction['request'])
  232.             {
  233.             }
  234.         }
  235.     }
  236. }