Pro รุ่น
AST — การอ้างอิงเชิงลึก
ภาพรวมโดยสังเขป
หัวข้อที่มีชื่อว่า “ภาพรวมโดยสังเขป”หน้านี้เป็นการอ้างอิงเชิงลึกของโมดูล AST ของ Pro ครอบคลุมพื้นผิวสาธารณะสำหรับการสร้าง แคช การ mutate การเขียน และการปล่อย (emit) สัญญาพฤติกรรมของพื้นผิวเหล่านั้น และโหมดความล้มเหลว โมดูลนี้แจง PDF ที่โหลดแล้วเป็นต้นไม้ AstDocument แบบ immutable ใช้ mutation ในหน่วยความจำที่บันทึกไว้ และเขียนการอัปเดตเชิงเพิ่มแบบใช้ overlay AstDocument และ AstNode เป็นชนิดค่าของ Core ในเนมสเปซ NextPDF\Ast โมดูลนี้ผลิตและใช้งานมัน
ความพร้อมใช้งานและการอนุญาตสิทธิ์
หัวข้อที่มีชื่อว่า “ความพร้อมใช้งานและการอนุญาตสิทธิ์”ความสามารถนี้มาพร้อมกับ NextPDF Pro (nextpdf/pro) และเปิดใช้งานด้วย license envelope ระดับ Pro การติดตั้งที่ไม่มีสิทธิ์ดังกล่าวจะไม่โหลดคลาสของความสามารถนี้ เปรียบเทียบรุ่นและขอรับสิทธิ์ใช้งาน
ไม่มีแฟล็กสิทธิ์ใช้งานรายฟีเจอร์ นี่เป็นความสามารถของรุ่น Pro พฤติกรรมการสร้างถูกควบคุมโดย AstBuildOptions ทั้งหมด
พื้นผิว public API
หัวข้อที่มีชื่อว่า “พื้นผิว public API”| สัญลักษณ์ | พารามิเตอร์ | พฤติกรรมเริ่มต้น | คืนค่า | ยกข้อยกเว้นหรือล้มเหลวด้วย | หมายเหตุ |
|---|---|---|---|---|---|
AstBuilder::__construct | PdfReader $reader, AstBuildOptions $options, ?AstCache $cache = null | ผูกตัวอ่านที่โหลดแล้วเข้ากับอ็อพชันการสร้าง การแคชเป็นทางเลือก | AstBuilder | — | แคชที่เป็น null หมายความว่าทุกการเรียก build() จะสร้างใหม่ |
AstBuilder::build | string $sourceHash (SHA-256 hex แบบเต็มของไบต์ PDF) | การค้นหาแคช การปฏิเสธการเข้ารหัส เส้นทาง structure-tree ทางเลือกสำรองแบบ untagged การแนบ bounding-box การจัดเก็บแคช | AstDocument | AstUnsupportedEncryptionException, AstBuildLimitException, AstBuildTimeoutException | การชนแคชจะคืนค่าโดยไม่แจงซ้ำ |
AstBuildOptions::__construct | ?int $pageRangeStart = null, ?int $pageRangeEnd = null, int $maxNodes = 100_000, int $maxDepth = 200, ?int $estimatedTokenBudget = null, int $maxMemoryBytes = 268435456, float $timeoutSeconds = 30.0, bool $useHeuristic = false | อ็อพเจกต์ค่าคอนฟิกแบบ immutable | AstBuildOptions | — | estimatedTokenBudget เป็นคำใบ้เชิงข้อมูล ไม่มีการบังคับใช้ |
AstBuildOptions::pageRangeContains | int $pageIndex | เป็นจริงเมื่อดัชนีฐาน 0 อยู่ภายในช่วงที่กำหนดค่าไว้ | bool | — | ขอบเขตที่เป็น null เปิดปลาย ทั้งคู่เป็น null หมายถึงทุกหน้า |
AstBuildOptions::hash | — | SHA-256 ที่เสถียรบนค่าอ็อพชันทั้งหมด | string | — | ค่าที่เท่ากันให้ hash ที่เท่ากันข้ามอินสแตนซ์ ใช้เป็นส่วนของคีย์แคช |
AstCache::__construct | CacheInterface $backend | ห่อหุ้ม backend PSR-16 ใด ๆ | AstCache | — | — |
AstCache::buildKey | string $sourceHash, AstBuildOptions $options | คีย์ = nextpdf_ast_v1_ + hex 32 ตัวแรกของ source hash + _ + hex 16 ตัวแรกของ options hash | string | — | การเปลี่ยนอ็อพชันจะทำให้ผลลัพธ์ที่แคชไว้ใช้ไม่ได้โดยอัตโนมัติ |
AstCache::get | string $cacheKey | ถอดรหัส payload JSON ผ่านการตรวจสอบรายฟิลด์อย่างเข้มงวด | ?AstDocument | ไม่ยกข้อยกเว้น ความล้มเหลวคืนค่า null | payload ที่ผิดรูปแบบหรือถูกดัดแปลงจะล้มเหลวแบบปิด (fail closed) เป็นการพลาดแคช |
AstCache::set | string $cacheKey, AstDocument $document | จัดเก็บ JSON ด้วย TTL 24 ชั่วโมง แล้วตรวจสอบด้วยการอ่านกลับทันที | void | AstWriteVerificationException (Exception namespace) | ความล้มเหลวในการเขียน backend หรือการวนรอบที่ล้มเหลวจะยกข้อยกเว้น |
AstCache::delete | string $cacheKey | การลบแบบพยายามอย่างดีที่สุด | void | ไม่ยกข้อยกเว้น | ความล้มเหลวในการลบ backend จะถูกกลืน |
AstCache::has | string $cacheKey | การตรวจสอบการมีอยู่แบบพยายามอย่างดีที่สุด | bool | ไม่ยกข้อยกเว้น ความล้มเหลวคืนค่า false | — |
AstMutator::updateNode | AstDocument $document, string $nodeId, array $updates | แทนที่ text_content บันทึกรายการ Updated | AstDocument (อินสแตนซ์ใหม่) | InvalidArgumentException | ใช้เฉพาะคีย์ text_content คีย์ที่ไม่รู้จักจะถูกละเว้น |
AstMutator::deleteNode | AstDocument $document, string $nodeId | ลบโหนดออกจากต้นไม้ในหน่วยความจำ บันทึกรายการ Deleted | AstDocument (อินสแตนซ์ใหม่) | InvalidArgumentException | ลบในหน่วยความจำเท่านั้น ดูข้อควรระวังเรื่อง redaction ด้านล่าง |
AstMutator::getMutationLog | — | คืนอินสแตนซ์ log ที่ใช้ร่วมกัน | MutationLog | — | ส่ง log เดียวกันไปยัง AstWriter |
AstMutator::resetLog | — | ทิ้ง mutation ที่บันทึกไว้ทั้งหมด | void | — | เริ่ม log ใหม่ |
MutationLog | record, all, isEmpty, count, forNode, mutatedNodeIds | log ในหน่วยความจำแบบเพิ่มต่อท้ายอย่างเดียว รักษาลำดับการแทรกไว้ | ตามแต่ละเมทอด | — | forNode คืนรายการล่าสุดสำหรับโหนด รายการสุดท้ายชนะ |
MutationEntry::__construct | string $nodeId, MutationType $type, ?AstNode $originalNode, ?AstNode $mutatedNode, DateTimeImmutable $timestamp | ระเบียนแบบ immutable ของ mutation หนึ่งครั้ง | MutationEntry | — | originalNode เป็น null สำหรับ Inserted mutatedNode เป็น null สำหรับ Deleted |
MutationType | enum case Updated, Inserted, Deleted | การจำแนกที่หนุนด้วยสตริง | — | — | Deleted ภายใต้ OVERLAY จะซ่อนเนื้อหา ไม่ได้ลบไบต์ |
AstWriter::write | string $originalPdfBytes, MutationLog $log | เพิ่มต่อท้ายการอัปเดตเชิงเพิ่มซึ่ง overlay stream ครอบคลุม bounding box ที่ถูก mutate | string (ไบต์ PDF ที่แก้ไขแล้ว) | AstWriteException | log ว่างจะคืนอินพุตโดยไม่เปลี่ยนแปลง รายการ Inserted และรายการที่ไม่มี bounding box จะถูกข้าม |
AstWriter::writeAndVerify | string $originalPdfBytes, MutationLog $log | รัน write() แล้วตรวจสอบผลลัพธ์เชิงโครงสร้าง | string (ไบต์ PDF ที่ตรวจสอบแล้ว) | AstWriteException, AstWriteVerificationException (Writer namespace) | การตรวจสอบเป็นเชิงโครงสร้าง ไม่ใช่เชิงความหมาย |
AstPdfEmitter::emit | AstNode $root, BinaryBuffer $buffer, ObjectRegistry $registry, array $pageObjects | เขียน StructTreeRoot เชน StructElem และ ParentTree สำหรับต้นไม้ที่จัดหาให้ | EmitResult | AstEmitException | root ต้องเป็นโหนด Document ที่มีลูก ตัว emitter แบบ round-trip สำหรับการตรวจสอบ structure-tree |
EmitResult::__construct | int $structTreeRootObject, int $rootElementObject, int $parentTreeObject, int $elementObjectCount, int $parentTreeNextKey | ระเบียนแบบ immutable ของตัวระบุอ็อพเจกต์ที่ปล่อยออกมา | EmitResult | — | — |
public function build(string $sourceHash): AstDocumentpublic function updateNode(AstDocument $document, string $nodeId, array $updates): AstDocumentpublic function deleteNode(AstDocument $document, string $nodeId): AstDocumentpublic function write(string $originalPdfBytes, MutationLog $log): stringpublic function writeAndVerify(string $originalPdfBytes, MutationLog $log): stringลำดับชั้นข้อยกเว้น
หัวข้อที่มีชื่อว่า “ลำดับชั้นข้อยกเว้น”NextPDF\Pro\Ast\Exception\AstExceptionขยายRuntimeException— ฐานของลำดับชั้นการสร้างAstBuildLimitExceptionขยายAstException— เกินเพดานโหนด ความลึก หรือหน่วยความจำAstBuildTimeoutExceptionขยายAstBuildLimitException— หมดเวลาการสร้างแบบ wall-clockAstNoStructTreeExceptionขยายAstException— ไม่มี structure tree อยู่AstBuilder::build()ดักจับภายในและใช้ทางเลือกสำรอง ผู้เรียกbuild()จะไม่พบเห็นมันAstUnsupportedEncryptionExceptionขยายAstException— PDF อินพุตถูกเข้ารหัสNextPDF\Pro\Ast\Exception\AstWriteVerificationExceptionขยายAstException— การตรวจสอบการเขียนแคชล้มเหลวNextPDF\Pro\Ast\Writer\AstWriteExceptionขยายRuntimeException— ความล้มเหลวของอินพุตหรือโครงสร้างของตัวเขียนNextPDF\Pro\Ast\Writer\AstWriteVerificationExceptionขยายAstWriteException— การตรวจสอบเชิงโครงสร้างหลังการเขียนล้มเหลว
มีคลาส AstWriteVerificationException ที่แตกต่างกันสองคลาสในเนมสเปซที่ต่างกัน AstCache::set() ยกคลาสในเนมสเปซ Exception ส่วน AstWriter::writeAndVerify() ยกคลาสในเนมสเปซ Writer จับคู่เนมสเปซในประโยค catch
สัญญาพฤติกรรม
หัวข้อที่มีชื่อว่า “สัญญาพฤติกรรม”AstBuilder::build($sourceHash) ต้องการ SHA-256 hex แบบเต็มของไบต์ต้นทาง ไปป์ไลน์คือ การค้นหาแคชที่เลือกได้ การปฏิเสธการเข้ารหัส เส้นทาง structure-tree ทางเลือกสำรองแบบ untagged การแนบ bounding-box และการจัดเก็บแคชที่เลือกได้
คีย์แคชรวม source hash เข้ากับ hash ของ AstBuildOptions hash ของอ็อพชันเสถียรข้ามอินสแตนซ์ที่มีค่าเหมือนกัน อินพุตและอ็อพชันที่เหมือนกันจึงคืนต้นไม้เดียวกัน เมื่อไม่ได้จัดหาแคช ทุกการเรียกจะสร้างใหม่ payload ที่แคชไว้เป็น JSON ไม่เคยเป็น native PHP serialization เส้นทางการอ่านตรวจสอบแต่ละฟิลด์และสร้างเฉพาะชนิดค่า AST เท่านั้น รายการแคชที่ถูกวางยาจึงไม่สามารถกระตุ้น object injection และลดระดับเป็นการพลาดแคช
เส้นทาง structure-tree รันเมื่อมี structure tree อยู่ เพดานทรัพยากร — จำนวนโหนด ความลึก เดลตาหน่วยความจำ และเวลา wall-clock — ถูกบังคับใช้ระหว่างการอ่าน structure-tree และยก AstBuildLimitException หรือ AstBuildTimeoutException หากตัวอ่านรายงานว่าไม่มี structure tree ตัวสร้างจะสลับไปยังเส้นทาง untagged คือตัวสร้างแบบฮิวริสติกเมื่อ useHeuristic เป็นจริง มิฉะนั้นเป็นตัวสร้างทางเลือกสำรองแบบเปล่า Bounding box ถูกแนบโดยการวิเคราะห์ content stream ของแต่ละหน้าที่อยู่ในช่วง หน้าที่ content stream ไม่สามารถแจงได้จะถูกข้ามและคงส่วนที่เหลือของต้นไม้ไว้สมบูรณ์
AstNode เป็นแบบ immutable การอัปเดตต้นไม้สร้างโหนดที่ได้รับผลกระทบใหม่จากล่างขึ้นบน ส่วนต้นไม้ย่อยที่ไม่เปลี่ยนแปลงถูกคืนค่าโดยเอกลักษณ์ AstMutator ปฏิบัติตามสัญญาเดียวกัน แต่ละ mutation คืน AstDocument ใหม่ สร้างใหม่เฉพาะเส้นทางจาก root ไปยังเป้าหมาย และบันทึก MutationEntry ใน MutationLog ที่ใช้ร่วมกัน
AstWriter ใช้ MutationLog ในโหมด OVERLAY เป็นการอัปเดตเชิงเพิ่มแบบเพิ่มต่อท้ายอย่างเดียว ได้แก่ content stream overlay ใหม่ อ็อพเจกต์หน้าที่อัปเดตแล้ว ส่วน cross-reference ที่ครอบคลุมเฉพาะอ็อพเจกต์ใหม่ และ trailer ที่ /Prev ชี้ไปยัง startxref ก่อนหน้า ไบต์ต้นฉบับถูกคงไว้สมบูรณ์ ตามแบบจำลองการอัปเดตเชิงเพิ่มของ ISO 32000-2:2020, 7.5.6 ข้อความแทนที่ที่วาดสำหรับรายการ Updated จะ escape \, ( และ ) ในสตริงลิเทอรัล ตาม ISO 32000-2:2020, 7.3.4.2
AstPdfEmitter::emit() เป็นส่วนกลับเชิงสมมาตรของการอ่าน structure-tree ต้นไม้ที่ผลิตโดยตัวอ่านจะ round-trip เป็นต้นไม้ที่เทียบเท่ากันเชิงโครงสร้าง ยกเว้นการเปลี่ยนหมายเลข node-id และคลาส canonicalisation ที่จัดทำเอกสารไว้ MCID ที่มีอยู่บนโหนดจะถูกปล่อยซ้ำแบบเดิมทุกตัวอักษร ไม่มีการจัดสรรใหม่
กรณีขอบและโหมดความล้มเหลว
หัวข้อที่มีชื่อว่า “กรณีขอบและโหมดความล้มเหลว”- อินพุตที่เข้ารหัสถูกปฏิเสธก่อนงานต้นไม้ใด ๆ ไม่มีผลลัพธ์ต้นไม้บางส่วนสำหรับ PDF ที่เข้ารหัส ถอดรหัสก่อน
- เพดานทรัพยากร: จำนวนโหนดสูงสุด (ค่าเริ่มต้น 100,000) ความลึกสูงสุด (ค่าเริ่มต้น 200) หน่วยความจำสูงสุด (ค่าเริ่มต้น 256 MiB) การหมดเวลา wall-clock (ค่าเริ่มต้น 30 s) การเกินเพดานจะยก
AstBuildLimitExceptionการหมดเวลาจะยกAstBuildTimeoutExceptionซึ่งเป็นคลาสย่อย - ช่วงหน้าเริ่มนับจาก 0 และเป็นแบบรวม ขอบเขตที่เป็น null หมายถึงทุกหน้า
- หน้าที่ content stream ไม่สามารถแจงได้จะถูกข้ามระหว่างการแนบ bounding-box ส่วนที่เหลือของต้นไม้ไม่ได้รับผลกระทบ
AstCache::get()ไม่ยกข้อยกเว้น: payload ที่ผิดรูปแบบ ถูกดัดแปลง หรือไม่ใช่สตริงจะคืนค่า null และบังคับให้สร้างใหม่AstCache::set()ล้มเหลวแบบส่งเสียงดังเมื่อการเขียน backend หรือการอ่านกลับทันทีล้มเหลวAstMutatorยกInvalidArgumentExceptionเมื่อไม่พบ node id คีย์อัปเดตที่ไม่รู้จักจะถูกละเว้นอย่างเงียบ ๆ ใช้เฉพาะtext_contentAstWriter::write()ยกAstWriteExceptionเมื่ออินพุตขาดส่วนหัว%PDF-หรือstartxrefที่ระบุตำแหน่งได้ รายการที่ไม่มี bounding box จะถูกข้ามอย่างเงียบ ๆ หน้าที่ไม่สามารถระบุตำแหน่งได้ด้วยการสแกนอ็อพเจกต์ — ตัวอย่างเช่นภายใต้ compressed cross-reference stream — จะถูกข้าม หากไม่สามารถใช้ overlay ได้ ไบต์อินพุตจะถูกคืนโดยไม่เปลี่ยนแปลง- เอาต์พุต OVERLAY ไม่ใช่ redaction สี่เหลี่ยมสีขาวและข้อความที่วาดใหม่ถูกเพิ่มต่อท้าย ไบต์เนื้อหาต้นฉบับยังคงอยู่ในไฟล์และกู้คืนได้ด้วยการแยกดิบ อย่าใช้สำหรับการลบตาม GDPR Art. 17 หรือ redaction ทางกฎหมาย ตัวเขียนโหมด reconstruct มีอยู่ในซอร์สทรีแต่ถูกทำเครื่องหมายว่าเป็นภายใน ยังไม่พร้อมใช้งานจริง และอยู่นอกพื้นผิว API ที่รองรับ
- เรขาคณิตของ overlay สมมติเป็น A4 แนวตั้ง (595 x 842 pt) เพราะตัวเขียนไม่อ่าน MediaBox ของหน้า บนหน้าที่ไม่ใช่ A4 overlay อาจเยื้องเล็กน้อย เอาต์พุตยังคงถูกต้องเชิงโครงสร้าง
writeAndVerify()ตรวจสอบเฉพาะโครงสร้าง: ส่วนหัว%%EOFท้ายไฟล์ และการเติบโตของเอาต์พุต ไม่ได้แจงเอกสารที่ mutate ซ้ำเชิงความหมายAstPdfEmitter::emit()ยกAstEmitExceptionเมื่อ root ไม่ใช่โหนด Document หรือไม่มีลูก รายการคู่ OBJR (annotation) จะไม่ถูกปล่อยในรุ่นนี้- โมดูลนี้ไม่ดำเนินการเข้ารหัสลับและไม่กำหนดพฤติกรรมเฉพาะ FIPS SHA-256 ปรากฏเฉพาะเป็นการกำหนดที่อยู่ตามเนื้อหาสำหรับคีย์แคช
การเป็นไปตามข้อกำหนด
หัวข้อที่มีชื่อว่า “การเป็นไปตามข้อกำหนด”เส้นทาง structure-tree อ่านสิ่งอำนวยความสะดวกโครงสร้างเชิงตรรกะของ tagged-PDF ที่กำหนดโดย ISO 32000-2 คลังข้อมูล RAG ที่พร้อมใช้งานในเวลาเขียนไม่รวมข้อว่าด้วยโครงสร้างเชิงตรรกะ คำกล่าวนั้นจึงอิงผลิตภัณฑ์จากคำอธิบายประกอบของซอร์ส เลย์เอาต์การอัปเดตเชิงเพิ่มของตัวเขียนเป็นไปตาม ISO 32000-2:2020, 7.5.6 (อ้างอิงด้านล่าง) และการ escape สตริงลิเทอรัลเป็นไปตาม ISO 32000-2:2020, 7.3.4.2 (อ้างอิงด้านล่าง)
คำกล่าวเหล่านี้อธิบายความสามารถเทียบกับข้อที่อ้างอิง NextPDF ไม่ถือใบรับรองการเป็นไปตามข้อกำหนด และการรองรับข้อหนึ่งไม่ใช่การอ้างการรับรอง
บันทึกการพัฒนา
หัวข้อที่มีชื่อว่า “บันทึกการพัฒนา”- ประกอบ
AstBuilderหนึ่งตัวต่อPdfReaderที่โหลดหนึ่งตัว ใช้AstCacheซ้ำข้ามการสร้างเพื่อเฉลี่ยต้นทุนการแจง การออกแบบคีย์ทำให้การเปลี่ยนอ็อพชันทำให้ตัวเองใช้ไม่ได้ - ใช้
MutationLogหนึ่งตัวร่วมกันระหว่างAstMutatorและAstWriterเพื่อให้ตัวเขียนใช้เซสชันที่บันทึกไว้อย่างแม่นยำ เรียกresetLog()ระหว่างเซสชันการแก้ไขที่เป็นอิสระต่อกัน - ตั้ง
useHeuristicเป็นจริงสำหรับเอกสาร untagged เมื่อการจัดกลุ่มที่ได้จากเลย์เอาต์เป็นที่ต้องการมากกว่าต้นไม้ทางเลือกสำรองแบบเปล่า - การสร้างเป็นแบบกำหนดได้แน่นอนสำหรับไบต์และอ็อพชันที่เหมือนกัน พึ่งพาสิ่งนี้สำหรับการทดสอบแบบ snapshot
- จับความล้มเหลวการสร้างผ่านลำดับชั้น
NextPDF\Pro\Ast\Exceptionและความล้มเหลวการเขียนผ่านลำดับชั้นNextPDF\Pro\Ast\Writerทั้งสองไม่ใช้ฐานร่วมกันต่ำกว่าRuntimeException
ขอบเขตการเผยแพร่
หัวข้อที่มีชื่อว่า “ขอบเขตการเผยแพร่”หน้านี้จัดทำเอกสารเฉพาะพฤติกรรมที่สังเกตได้จากภายนอกและพื้นผิว public API ที่รองรับเท่านั้น เส้นทางเนมสเปซภายใน คลาสตัวช่วย ตารางกลไก ชื่อไฟล์ runbook และคำนำหน้า ticket อยู่นอกขอบเขต