英文:
Shopware 6.5 - Cannot generate custom document type
问题
我理解你想要翻译的代码部分。以下是代码的中文翻译:
<?php declare(strict_types=1);
namespace Dima\OrderConfirmation\Core\Checkout\Document\Renderer;
use Shopware\Core\Checkout\Document\Renderer\AbstractDocumentRenderer;
use Shopware\Core\Checkout\Document\Renderer\DocumentRendererConfig;
use Shopware\Core\Checkout\Document\Renderer\RenderedDocument;
use Shopware\Core\Checkout\Document\Renderer\RendererResult;
use Shopware\Core\Checkout\Document\Service\DocumentConfigLoader;
use Shopware\Core\Checkout\Document\Struct\DocumentGenerateOperation;
use Shopware\Core\Checkout\Document\Twig\DocumentTemplateRenderer;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\Defaults;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\Plugin\Exception\DecorationPatternException;
use Shopware\Core\System\Locale\LocaleEntity;
use Shopware\Core\System\NumberRange\ValueGenerator\NumberRangeValueGeneratorInterface;
class OrderConfirmationRenderer extends AbstractDocumentRenderer
{
public const DEFAULT_TEMPLATE = '@DimaOrderConfirmation/documents/order_confirmation.html.twig';
final public const TYPE = 'order_confirmation';
/**
* @internal
*/
public function __construct(
private readonly EntityRepository $orderRepository,
private readonly DocumentConfigLoader $documentConfigLoader,
private readonly DocumentTemplateRenderer $documentTemplateRenderer,
private readonly NumberRangeValueGeneratorInterface $numberRangeValueGenerator,
private readonly string $rootDir,
) {
}
public function supports(): string
{
return self::TYPE;
}
/**
* @param array<DocumentGenerateOperation> $operations
*/
public function render(array $operations, Context $context, DocumentRendererConfig $rendererConfig): RendererResult
{
$ids = array_map(fn (DocumentGenerateOperation $operation) => $operation->getOrderId(), $operations);
if (empty($ids)) {
return new RendererResult();
}
$result = new RendererResult();
$template = self::DEFAULT_TEMPLATE;
$orders = $this->orderRepository->search(new Criteria($ids), $context)->getEntities();
foreach ($orders as $order) {
$orderId = $order->getId();
try {
$operation = $operations[$orderId] ?? null;
if ($operation === null) {
continue;
}
$config = clone $this->documentConfigLoader->load(self::TYPE, $order->getSalesChannelId(), $context);
$config->merge($operation->getConfig());
$number = $config->getDocumentNumber() ?: $this->getNumber($context, $order, $operation);
$now = (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT);
$config->merge([
'documentDate' => $operation->getConfig()['documentDate'] ?? $now,
'documentNumber' => $number,
'custom' => [
'invoiceNumber' => $number,
],
]);
// If document is uploaded manually
if ($operation->isStatic()) {
$doc = new RenderedDocument('', $number, $config->buildName(), $operation->getFileType(), $config->jsonSerialize());
$result->addSuccess($orderId, $doc);
continue;
}
/** @var LocaleEntity $locale */
$locale = $order->getLanguage()->getLocale();
$html = $this->documentTemplateRenderer->render(
$template,
[
'order' => $order,
'config' => $config,
'rootDir' => $this->rootDir,
'context' => $context,
],
$context,
$order->getSalesChannelId(),
$order->getLanguageId(),
$locale->getCode()
);
$doc = new RenderedDocument(
$html,
$number,
$config->buildName(),
$operation->getFileType(),
$config->jsonSerialize(),
);
$result->addSuccess($orderId, $doc);
} catch (\Throwable $exception) {
$result->addError($orderId, $exception);
}
}
return $result;
}
public function getDecorated(): AbstractDocumentRenderer
{
throw new DecorationPatternException(self::class);
}
private function getNumber(Context $context, OrderEntity $order, DocumentGenerateOperation $operation): string
{
return $this->numberRangeValueGenerator->getValue(
'document_' . self::TYPE,
$context,
$order->getSalesChannelId(),
$operation->isPreview()
);
}
}
希望这对你有所帮助。如果你有任何其他翻译需求,请随时告诉我。
英文:
I am currently trying to create a custom document type in Shopware 6.5.0.0 like described in the Shopware docs.
My custom document type gets recognized when i go to create a new document from an order in the admin, but when i try to generate the pdf - I get the error "Unable to find a document generator with type "order_confirmation"". As there is no example service created in the docs - i believe my error lies there. But i am not sure. I referenced the invoice service renderer registration for my services.xml
This is my services.xml:
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="Dima\OrderConfirmation\Core\Checkout\Document\Renderer\OrderConfirmationRenderer">
<argument type="service" id="order.repository"/>
<argument type="service" id="Shopware\Core\Checkout\Document\Service\DocumentConfigLoader"/>
<argument type="service" id="Shopware\Core\Checkout\Document\Twig\DocumentTemplateRenderer"/>
<argument type="service" id="Shopware\Core\System\NumberRange\ValueGenerator\NumberRangeValueGeneratorInterface"/>
<argument>%kernel.project_dir%</argument>
<tag name="document.renderer" />
</service>
</services>
</container>
And this is my document renderer:
<?php declare(strict_types=1);
namespace Dima\OrderConfirmation\Core\Checkout\Document\Renderer;
use Shopware\Core\Checkout\Document\Renderer\AbstractDocumentRenderer;
use Shopware\Core\Checkout\Document\Renderer\DocumentRendererConfig;
use Shopware\Core\Checkout\Document\Renderer\RenderedDocument;
use Shopware\Core\Checkout\Document\Renderer\RendererResult;
use Shopware\Core\Checkout\Document\Service\DocumentConfigLoader;
use Shopware\Core\Checkout\Document\Struct\DocumentGenerateOperation;
use Shopware\Core\Checkout\Document\Twig\DocumentTemplateRenderer;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\Defaults;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\Plugin\Exception\DecorationPatternException;
use Shopware\Core\System\Locale\LocaleEntity;
use Shopware\Core\System\NumberRange\ValueGenerator\NumberRangeValueGeneratorInterface;
class OrderConfirmationRenderer extends AbstractDocumentRenderer
{
public const DEFAULT_TEMPLATE = '@DimaOrderConfirmation/documents/order_confirmation.html.twig';
final public const TYPE = 'order_confirmation';
/**
* @internal
*/
public function __construct(
private readonly EntityRepository $orderRepository,
private readonly DocumentConfigLoader $documentConfigLoader,
private readonly DocumentTemplateRenderer $documentTemplateRenderer,
private readonly NumberRangeValueGeneratorInterface $numberRangeValueGenerator,
private readonly string $rootDir,
) {
}
public function supports(): string
{
return self::TYPE;
}
/**
* @param array<DocumentGenerateOperation> $operations
*/
public function render(array $operations, Context $context, DocumentRendererConfig $rendererConfig): RendererResult
{
$ids = \array_map(fn (DocumentGenerateOperation $operation) => $operation->getOrderId(), $operations);
if (empty($ids)) {
return new RendererResult();
}
$result = new RendererResult();
$template = self::DEFAULT_TEMPLATE;
$orders = $this->orderRepository->search(new Criteria($ids), $context)->getEntities();
foreach ($orders as $order) {
$orderId = $order->getId();
try {
$operation = $operations[$orderId] ?? null;
if ($operation === null) {
continue;
}
$config = clone $this->documentConfigLoader->load(self::TYPE, $order->getSalesChannelId(), $context);
$config->merge($operation->getConfig());
$number = $config->getDocumentNumber() ?: $this->getNumber($context, $order, $operation);
$now = (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT);
$config->merge([
'documentDate' => $operation->getConfig()['documentDate'] ?? $now,
'documentNumber' => $number,
'custom' => [
'invoiceNumber' => $number,
],
]);
// If document is uploaded manually
if ($operation->isStatic()) {
$doc = new RenderedDocument('', $number, $config->buildName(), $operation->getFileType(), $config->jsonSerialize());
$result->addSuccess($orderId, $doc);
continue;
}
/** @var LocaleEntity $locale */
$locale = $order->getLanguage()->getLocale();
$html = $this->documentTemplateRenderer->render(
$template,
[
'order' => $order,
'config' => $config,
'rootDir' => $this->rootDir,
'context' => $context,
],
$context,
$order->getSalesChannelId(),
$order->getLanguageId(),
$locale->getCode()
);
$doc = new RenderedDocument(
$html,
$number,
$config->buildName(),
$operation->getFileType(),
$config->jsonSerialize(),
);
$result->addSuccess($orderId, $doc);
} catch (\Throwable $exception) {
$result->addError($orderId, $exception);
}
}
return $result;
}
public function getDecorated(): AbstractDocumentRenderer
{
throw new DecorationPatternException(self::class);
}
private function getNumber(Context $context, OrderEntity $order, DocumentGenerateOperation $operation): string
{
return $this->numberRangeValueGenerator->getValue(
'document_' . self::TYPE,
$context,
$order->getSalesChannelId(),
$operation->isPreview()
);
}
}
I confirmed that the TYPE const matches with the document type i create in my migration, as i first thought that there maybe was a typo - but to no success.
What is it that i'm missing here?
答案1
得分: 0
这一切看起来都是正确的。你是否像这样实现了supports
方法?
public function supports(): string
{
return self::TYPE;
}
这是唯一会引发异常的行。而且只会在遍历所有标记为document.renderer
的服务并且没有评估支持该类型的服务时发生异常。
看起来你的服务如果没有匹配到的话根本就没有被注册。你是否有其他在services.xml
中注册的服务,以确认它们已经注册了,这样你就可以确定你没有错放文件之类的事情?
英文:
That all looks to be correct. Did you implement the supports
method like this?
public function supports(): string
{
return self::TYPE;
}
This is the only line where this exception is thrown. And it only happens if it iterates all the document.renderer
tagged services without evaluating one that supports the type.
It looks like your service is not being registered at all if it's not matching up. Do you have other services in your services.xml
that you can confirm being registered, so you can say for sure you didn't misplace the file or something like that?
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论