تخطَّ إلى المحتوى

العقود / الاستخراج

يُعرّف مجال الاستخراج العقود التي تستخدمها لقراءة ملفات تنسيق المستندات المحمولة (⁨PDF⁩)، والتحقق منها، وتحويل محتواها إلى بيانات مُهيكلة. ويشمل الفاحص، ومدققات الامتثال، ومدير ⁨PDF/A⁩، وعقود الكائنات المستوردة، وعقود التضمين وفهرس المتجهات، والنطاق الفرعي للتحقق من الفواتير الإلكترونية.

Terminal window
composer require nextpdf/core:^3

يقرأ InspectorInterface بايتات ⁨PDF⁩ الخام ويُعيد InspectResult مُهيكلًا. وتُدرج النتيجة الكائنات الموجودة في الملف. استخدم هذا العقد مع أي أداة تقرأ ملف ⁨PDF⁩ لم يكتبه المحرك.

يربط ExternalComplianceValidatorInterface المحرك بمدقق خارجي مثل ⁨veraPDF.⁩ ويختبر المدقق ⁨PDF/A⁩ وإمكانية الوصول الشاملة لتنسيق المستندات المحمولة (⁨PDF/UA⁩). عند عدم تهيئة أي مدقق، تُعيد التطبيقة الفارغة نتيجة “غير متوفر”. ويظل الموقع الذي لا يتوفر فيه ⁨veraPDF⁩ قيد التشغيل. يتحقق ProfileValidatorInterface من بيئة التشغيل مقابل ملف نشر، بما في ذلك الامتدادات المطلوبة والموصى بها. ويُعيد حُكمًا مُحدد النوع.

يُبقي PdfAManagerInterface ملف ⁨PDF/A⁩ مطابقًا للمواصفة أثناء بنائه بواسطة الكاتب. ويحظر ⁨JavaScript⁩، وإجراءات النماذج المعتمدة على ⁨JavaScript⁩، والتشفير المُضمَّن. ويمنع ⁨PDF/A⁩ العناصر الثلاثة كلها. كما يتحقق من تضمين كل خط، ويضبط بيانات تعريف مطابقة للمواصفة، ويكتب الكائنات اللازمة قبل الفهرس. تُشحَن الفئة الفعلية في إصدار ⁨Pro.⁩ يعثر عليها ⁨Core⁩ عبر class_exists() ويربطها بالعقد. ولا يحمل المحرك مفتوح المصدر أي تبعية مدفوعة.

يغطي الكائنات المستوردة عقدان: ImportedFormObjectInterface وEmbeddedPdfObjectInterface. ويوفران وصولًا مُحدد النوع إلى الكائنات المقروءة من ملف ⁨PDF⁩ قائم كي يتمكن المحرك من إعادة تضمينها. يحتفظ المسار غير الفاقد ببايتات القاموس الخام. ويوفر المسار الاحتياطي مصفوفة قاموس مُحلَّلة للكائنات المأخوذة من دفوق الكائنات. كل كائن مُعاد تضمينه هو كائن ⁨PDF⁩ غير مباشر. ويُعرِّفه رقم كائن ورقم جيل، كما هو محدد في ⁨ISO 32000-2⁩ §7.3.10.

تدعم عقود التضمين البحث. ويحوّل EmbeddingServiceInterface النص إلى متجه كثيف، ويُبلّغ عن حجم النموذج واسمه كي يتمكن المستدعون من التكيف أثناء التشغيل. يُشغّل إصدار ⁨Pro⁩ نموذجًا يعمل على وحدة المعالجة المركزية (⁨CPU⁩). ويُشغّل إصدار ⁨Enterprise⁩ نموذجًا يعمل على وحدة معالجة الرسوميات (⁨GPU⁩). يبني VectorIndexInterface فهرس أقرب الجيران ويبحث فيه. وهو الفهرس الصغير داخل العملية للاستخدام في ⁨Core.⁩ أما البحث الأوسع نطاقًا فيبقى ضمن عقد خاص بإصدار ⁨Enterprise.⁩

تضم مجموعة EInvoice مدقق الفواتير الإلكترونية العابر للمستويات. ويُجري ValidatorInterface فحوصًا تمهيدية على حمولة فاتورة الصناعة المتقاطعة (⁨CII⁩) أو لغة الأعمال الشاملة (⁨UBL⁩). ويُجري SchematronRunnerInterface تمريرة قواعد العمل. ويجمع ValidationResult النتائج وانتهاكات القواعد. يجب أن يرفض المدقق المُدخل السيئ بنتيجة، لا باستثناء. كما يجب أن يحمي من الحمولات التي تحتوي على إعلان نوع المستند (⁨DOCTYPE⁩) ومن الحمولات المفرطة الحجم.

النوعالصنفالأعضاء الرئيسيونالاستقرارمنذ
InspectorInterfaceواجهةinspect(string, InspectConfig): InspectResultتجريبي2.2.0
ExternalComplianceValidatorInterfaceواجهةvalidate(string, ComplianceFlavour)، isAvailable()تجريبي2.4.0
ProfileValidatorInterfaceواجهةvalidate(DeploymentProfile): DeploymentProfileResultتجريبي2.4.0
PdfAManagerInterfaceواجهةvalidateNoJavaScript()، validateFont()، validateNoEncryption()، applyOutputProfile()، writeRequiredObjects()مستقر1.10.0
ImportedFormObjectInterfaceواجهةgetWidth()، getHeight()، getEmbeddedObjects()، getResourcesDict()، getMediaBox()، getContentStream()مستقر1.8.0
EmbeddedPdfObjectInterfaceواجهةgetRawDictionaryBytes()، getRawStreamData()، getDictionary()مستقر1.8.0
EmbeddingServiceInterfaceواجهةembed()، batchEmbed()، getDimension()، getModelName()تجريبي2.1.0
VectorIndexInterfaceواجهةbuild()، search()، delete()، count()تجريبي2.1.0
EInvoice\ValidatorInterfaceواجهةvalidate(string, ValidatorContext): ValidationResultتجريبي5.1.0
EInvoice\ValidationResultفئة نهائية للقراءة فقط$isValid، getErrors()، getWarnings()، fail()تجريبي5.1.0

كما يُصدر نطاق EInvoice أيضًا SchematronRunnerInterface، وProfileInterface، وValidationFinding، وRuleViolation، والتعدادات ProfileType، وRuleSeverity، وValidationFindingLevel.

examples/contracts/extraction-quickstart.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\InspectorInterface;
use NextPDF\Inspect\InspectConfig;
/**
* Inspect a PDF and report its object count.
*
* @param InspectorInterface $inspector A configured inspector.
* @param string $pdfData Raw PDF bytes.
*/
function describe(InspectorInterface $inspector, string $pdfData): \NextPDF\Inspect\InspectResult
{
return $inspector->inspect($pdfData, new InspectConfig());
}

تعتمد الدالة على العقد. ويمكن لأي تطبيقة فاحص أن تفي به.

examples/contracts/extraction-production.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\EInvoice\ValidatorInterface;
use NextPDF\Contracts\EInvoice\ValidatorContext;
use NextPDF\Contracts\ExternalComplianceValidatorInterface;
use NextPDF\ValueObjects\ComplianceFlavour;
use Psr\Log\LoggerInterface;
final readonly class InvoiceConformanceService
{
public function __construct(
private ValidatorInterface $invoiceValidator,
private ExternalComplianceValidatorInterface $pdfaValidator,
private LoggerInterface $logger,
) {}
/**
* Validate the invoice XML, then the PDF/A-3 carrier.
*
* @param string $xml The CII or UBL invoice payload.
* @param string $pdfPath Absolute path to the PDF/A-3 carrier.
*/
public function validate(string $xml, string $pdfPath, ValidatorContext $ctx): bool
{
$result = $this->invoiceValidator->validate($xml, $ctx);
if (!$result->isValid) {
$this->logger->warning('Invoice XML invalid', [
'errors' => \count($result->getErrors()),
]);
return false;
}
if (!$this->pdfaValidator->isAvailable()) {
$this->logger->info('PDF/A validator unavailable; skipping carrier check.');
return true;
}
$carrier = $this->pdfaValidator->validate($pdfPath, ComplianceFlavour::PdfA3b);
return $carrier->isConformant();
}
}

تتعامل الخدمة صراحةً مع حالة عدم توفر المدقق بدلًا من افتراض وجوده.

  • EInvoice\ValidatorInterface::validate() يُعيد ValidationResult فاشلًا للمُدخل المُشوَّه. ولا يطرح استثناءً لانتهاكات حُسن التكوين. تحقق من $isValid؛ لا تُغلِّف الاستدعاء بكتلة ⁨try/catch⁩ في تلك الحالة.
  • يجب التحقق من ExternalComplianceValidatorInterface::isAvailable() قبل الاعتماد على حُكم. تُعيد التطبيقة الفارغة “غير متوفر”. ومعاملة ذلك على أنه “غير مطابق” تُنتج نتائج سلبية خاطئة.
  • EmbeddedPdfObjectInterface::getRawDictionaryBytes() يُعيد null للكائنات المأخوذة من دفق كائنات. ارجع إلى getDictionary() كحل احتياطي. لا تفترض وجود بايتات خام.
  • EmbeddingServiceInterface::getDimension() يختلف باختلاف المستوى. يجب أن تقرأ الشيفرة التي تُخصص متجهًا ثابت العرض البُعدَ أثناء التشغيل، لا أن تُضمّنه بقيمة صريحة.
  • VectorIndexInterface::build() يتطلب قائمتي متجهات ومعرّفات متساويتي الطول ومتسقتي الأبعاد. يُثير عدم التطابق InvalidArgumentException. تحقق من القائمتين قبل بناء الفهرس.

تتناسب تكلفة الفحص والتحقق مع حجم المستند وعدد الكائنات. ويغطي performance_budget البالغ 1500 ⁨ms⁩ زمنًا فعليًا و64 ⁨MB⁩ ذروةً لمستند واحد متوسط. يضيف استدعاء ⁨veraPDF⁩ خارجي زمن معالجته الخاص. وهذا الزمن خارج ميزانية المحرك، وينبغي تشغيله خارج مسار الطلب. تتناسب تكلفة التضمين مع طول النص، وتكون أقل بكثير عند تنفيذها في دفعة بدلًا من حلقة، خصوصًا على نموذج ⁨GPU.⁩ فضِّل batchEmbed(). البحث في المتجهات دون خطي في حجم الفهرس بالنسبة إلى الفهرس داخل العملية. ملف إعادة الإنتاج هو structural. يُسجِّل تقرير التحقق طابعًا زمنيًا وبصمة بيئة. وقد تختلف تشغيلتان في تلك الحقول، بينما يظل حُكم المطابقة متطابقًا.

يقرأ الاستخراج مستندات لم يُنشئها المحرك، لذلك يكون كل مُدخل غير موثوق. يُحلِّل كل من الفاحص ومدقق الفواتير الإلكترونية بايتات مُورَّدة خارجيًا. يجب أن يحجب مدقق الفواتير الإلكترونية الحمولات التي تحتوي على إعلان نوع المستند (⁨DOCTYPE⁩)، والحمولات المفرطة الحجم، والحمولات ذات أحرف التحكم المحظورة قبل التحليل، لمنع هجمات الكيان الخارجي وهجمات مليار الضحكات في لغة الترميز القابلة للامتداد (⁨XML⁩). تنسخ إعادة تضمين الكائنات المستوردة بايتات من ملف ⁨PDF⁩ أجنبي. وقد يحمل كائن مصدري خبيث محتوى عدائيًا، لذلك تحفظ إعادة التضمين البايتات دون تنفيذها. يُزيل فرض ⁨PDF/A⁩ لغة ⁨JavaScript⁩ والإجراءات. يرفض مدير ⁨PDF/A⁩ لغة ⁨JavaScript⁩ والتشفير لأن كليهما محظوران في الملف، وكلاهما متجها إساءة استخدام في مستند أرشيفي طويل العمر. عامِل المحتوى المفحوص والكائنات المستوردة و⁨XML⁩ الفاتورة على أنها مُدخلات عدائية في كل المراحل.

الادعاءالمعيارالبندالدليل
يحظر ⁨PDF/A-4⁩ لغة ⁨JavaScript⁩ وإجراءات النماذج المعتمدة على ⁨JavaScript⁩؛ ويرفض مدير ⁨PDF/A⁩ كليهما.⁨ISO 19005-4⁩§6.7.1مُستشهَد به بالبند (ليس في المجموعة)
كل كائن مُعاد تضمينه هو كائن ⁨PDF⁩ غير مباشر يُعرَّف برقم كائن وجيل.⁨ISO 32000-2⁩§7.3.10

⁨ISO 19005-4⁩ مُستشهَد به بالبند. وهو غير موجود في مجموعة الاستشهادات القابلة للتحقق، لذلك لا يُسجَّل أي reference_id. ادعاء الكائن غير المباشر في ⁨ISO 32000-2⁩ مُثبَّت في المسرد. كلا الادعاءين مُعاد صياغته. ولا يُعيد المحرك إنتاج أي نص معياري.

يُعرّف ⁨Core⁩ عقود الاستخراج ويُجمّدها. وتُشحَن الشيفرة الإنتاجية الكامنة وراء PdfAManagerInterface وEmbeddingServiceInterface وVectorIndexInterface في إصداري ⁨Pro⁩ و⁨Enterprise⁩، بما في ذلك نماذج التضمين على ⁨CPU⁩ و⁨GPU⁩ ومسار فرض ⁨PDF/A⁩ الكامل. يحلّ ⁨Core⁩ هذه العقود أثناء التشغيل عبر class_exists(). لذلك لا يحمل المحرك مفتوح المصدر أي تبعية تجارية، ولا تتغير واجهة برمجة التطبيقات (⁨API⁩) عند الترقية.