Перейти к содержимому

Support: общие утилиты + Clock + Sleeper

Модуль Support содержит общие утилиты, которые движок использует внутри. У него также есть небольшая публичная часть: системные часы PHP Standards Recommendation 20 (PSR-20), конвейер сбора предупреждений и примитивы сериализации Portable Document Format (PDF). Большая часть пространства имён — внутренняя инфраструктура. На этой странице описаны компоненты, на которые можно полагаться, и отмечены компоненты, предназначенные только для внутреннего использования.

Окно терминала
composer require nextpdf/core:^3

Часы (PSR-20). SystemClock реализует Psr\Clock\ClockInterface. Его метод now() возвращает текущее время в виде DateTimeImmutable. Модель PSR-20 определяет интерфейс часов с одной операцией чтения, возвращающей текущее время в виде неизменяемого значения даты-времени (PSR-20 psr_20_clock#2.1). SystemClock используется по умолчанию: движок использует его, когда вы не внедряете часы. Чтобы зафиксировать время в тестах, внедрите замороженные часы, которые реализуют тот же интерфейс. Используйте часы вместе с Config::deterministic, когда нужен побайтово идентичный вывод.

Конвейер предупреждений. WarningCollector — основной транспорт предупреждений в памяти для нефатальных проблем отрисовки. Движок добавляет Warning при каждом детерминированном ухудшении: например, для сжатого столбца таблицы, неразрешённого шрифта или отсутствующего глифа. После генерации вы читаете предупреждения через Document::getWarnings(). Warning — это неизменяемый объект-значение. Он содержит WarningCode, WarningSeverity (warning или degraded), страницу, тип элемента, идентификатор функции, флаг паритета при ухудшении, сообщение, DegradationImpact и необязательный идентификатор возможности. WarningCode — это перечисление со строковыми значениями, состоящими из стабильных идентификаторов. Идентификаторы используют префикс NEXTPDF_W_, например NEXTPDF_W_FONT_UNRESOLVED, поэтому вы можете безопасно сопоставлять их в тестах. addWithPolicy() применяет активную DegradationPolicy. При строгой политике риск для соответствия, потеря семантики или блокирующее воздействие приводят к выбросу DegradedException. При сбалансированной политике к исключению приводит только блокирующее воздействие. Разрешающая политика никогда не выбрасывает исключение.

Примитивы PDF. PdfStringEscaper — единственный источник истины для экранирования строк и имён PDF. escapeLiteral() экранирует символы, которые требуют экранирования в литеральной строке PDF: обратную косую черту, скобки, возврат каретки (CR), перевод строки (LF), горизонтальную табуляцию (HT), забой (BS) и перевод страницы (FF). Он также удаляет байт NUL. escapeName() кодирует в шестнадцатеричный вид байты за пределами печатаемого диапазона American Standard Code for Information Interchange (ASCII) и байты из набора разделителей PDF в объекте-имени. BinaryBuffer — это оптимизированный для записи двоичный накопитель для объектов и потоков PDF. В потоковом режиме для больших документов он выгружает данные в дескриптор php://temp. Он также поддерживает операции с диапазонами байтов, необходимые для встраивания подписи. PdfOperators содержит строки формата для операторов потока контента: контуров, текста, состояния графики и шрифтов. Слои рисования и разбора совместно используют эти строки.

BinaryBuffer, PdfOperators и большинство остальных элементов NextPDF\Support\ — это внутренняя инфраструктура. Их используют слои записи и рисования. Эта страница описывает их для полноты и аудита. Они не входят в поддерживаемый публичный API. Вместо этого опирайтесь на фасад Document и пространство имён Contracts. SystemClock, WarningCollector, Warning, WarningCode, WarningSeverity и DegradationImpact — это публичные элементы.

СимволВидВидимостьОсновные члены
NextPDF\Support\SystemClockfinal classpublicnow(): DateTimeImmutable (PSR-20 ClockInterface)
NextPDF\Support\WarningCollectorfinal classpublicadd(), emit(), addWithPolicy(), getWarnings(), hasWarnings(), hasDegradedParity(), clear()
NextPDF\Support\Warningfinal readonly classpublic$code, $severity, $page, $elementType, $featureId, $degradedParity, $message, $impact, $capabilityId
NextPDF\Support\WarningCodestring enumpublicстабильные идентификаторы NEXTPDF_W_*
NextPDF\Support\WarningSeveritystring enumpublicWarning, Degraded
NextPDF\Support\DegradationImpactstring enumpublicCosmetic, LayoutRisk, SemanticLoss, ComplianceRisk, Blocking
NextPDF\Support\PdfStringEscaperfinal readonly classвнутреннийescapeLiteral(), escapeName() (статические)
NextPDF\Support\BinaryBufferfinal classвнутреннийwrite(), writeStream(), replaceAt(), extract(), enableStreaming(), getContents()
NextPDF\Support\PdfOperatorsfinal classвнутреннийконстанты строк формата для операторов потока контента

После генерации прочитайте собранные предупреждения.

<?php
declare(strict_types=1);
use NextPDF\Support\WarningCollector;
$collector = new WarningCollector();
// The engine appends warnings during rendering. After generation:
if ($collector->hasWarnings()) {
foreach ($collector->getWarnings() as $warning) {
\printf(
"[%s] page %d: %s\n",
$warning->code->value,
$warning->page,
$warning->message,
);
}
}

Внедрите часы, чтобы сделать время детерминированным, а предупреждение о паритете при ухудшении считайте сбоем сборки.

<?php
declare(strict_types=1);
use NextPDF\Support\SystemClock;
use NextPDF\Support\WarningCollector;
use Psr\Clock\ClockInterface;
// Production uses the real system clock.
$clock = new SystemClock();
$now = $clock->now(); // DateTimeImmutable
$epoch = $now->getTimestamp(); // int
// In tests, swap in any ClockInterface that returns a fixed instant
// (the parameter is typed to the PSR-20 interface, not SystemClock).
function buildReport(ClockInterface $clock): \DateTimeImmutable
{
return $clock->now();
}
$collector = new WarningCollector();
// ... run generation ...
if ($collector->hasDegradedParity()) {
throw new \RuntimeException('Output parity degraded; failing the build.');
}
  • SystemClock::now() при каждом вызове возвращает новый DateTimeImmutable. Не рассчитывайте, что два вызова вернут один и тот же момент времени. Чтобы зафиксировать время, внедрите замороженные часы.
  • WarningCollector работает в памяти и существует для каждого экземпляра отдельно. Это основной канал предупреждений. Дополнительный файл JavaScript Object Notation (JSON) и вывод стандартной ошибки (STDERR) интерфейса командной строки (CLI) формируются на границе вывода, а не самим сборщиком.
  • addWithPolicy() может выбросить DegradedException в середине отрисовки при строгой политике. Перехватывайте его на границе генерации, если нужен частичный вывод.
  • WarningCode содержит стабильные строковые значения. Сопоставляйте по варианту перечисления, а не по тексту сообщения: этот текст предназначен для чтения человеком и может измениться.
  • BinaryBuffer::getLength() — это намеренный псевдоним getOffset() для паритета с потоковым интерфейсом. Оба возвращают одинаковое количество байтов.
  • Рассматривайте PdfStringEscaper, BinaryBuffer и PdfOperators как внутреннюю инфраструктуру. На них не распространяется гарантия стабильности публичного API.

SystemClock::now() создаёт один объект и работает за O(1). Добавление в WarningCollector — вставка в список с амортизированной сложностью O(1). getWarnings() возвращает базовый список. В потоковом режиме BinaryBuffer удерживает данные в памяти до порога maxmemory (по умолчанию 2 MB), прежде чем выгрузить их на диск; это сохраняет постоянным пиковое потребление памяти для больших документов. Бюджет performance_budget по умолчанию для этой справочной страницы — wall_ms: 1500, peak_mb: 64.

Используйте интерфейс часов, чтобы устранить недетерминизм реального времени в подписанном выводе и выводе с меткой времени: внедрите фиксированные часы вместе с Config::deterministic. PdfStringEscaper — это единая аудируемая точка экранирования для вывода строк и имён PDF. Направляйте через него весь вывод строк, чтобы предотвратить внедрение контента через неэкранированные скобки или разделители в тексте, предоставленном пользователем. Предупреждения могут содержать сведения из документа, например типы элементов и идентификаторы функций. Очищайте вывод предупреждений, прежде чем направлять его в журнал с низким уровнем доверия.

СпецификацияПунктТема
PSR-20 (PHP-FIG)psr_20_clock#2.1Операция чтения часов возвращает неизменяемое значение даты-времени
ISO 32000-2:2020§7.3.4.2 / §7.3.5Экранирование литеральных строк и объектов-имён (пересказано; текст ISO не цитируется, фрагменты не закреплены)

SystemClock реализует ClockInterface из PSR-20. Экранировщик следует правилам PDF для символов литеральных строк и объектов-имён. Текст ISO пересказан согласно политике цитирования сайта; дословные фрагменты не закреплены.

  • /modules/core/exception/ — исключение DegradedException, выбрасываемое addWithPolicy()
  • /modules/core/contracts/DegradationPolicy, Capability
  • /modules/core/observability/ — пересылка предупреждений и метрики
  • /modules/core/config/Config::deterministic сочетается с часами
  • /modules/core/writer/ — внутренний потребитель BinaryBuffer и PdfOperators

Глоссарий: PSR-20 · политика ухудшения · объект-значение