Context
Surfaced while reviewing the mailer 1.0.0-beta.4 domain-command refactor (branch chore/mago-burndown-2-mechanical). Not a regression from that work — the pre-refactor SendVerificationEmailListener and ProcessResendVerificationMiddleware used the same call. Deferred so it does not block the current merge.
Data
CommandHandler\SendVerificationEmailHandler and CommandHandler\ResendVerificationEmailHandler escape with the global function and explicit flags:
htmlspecialchars($command->firstName, flags: ENT_QUOTES, encoding: 'UTF-8')
htmlspecialchars($command->verificationUrl, flags: ENT_QUOTES, encoding: 'UTF-8')
- Explicit
flags: overrides the PHP 8.1+ default of ENT_QUOTES | ENT_SUBSTITUTE. Without ENT_SUBSTITUTE, htmlspecialchars() returns an empty string for input containing an invalid code sequence, so the value renders blank rather than as U+FFFD.
$verificationUrl is interpolated into href="..." — an attribute context, not a text-node context.
- Both handlers escape the same two values, and both pass the raw
$command->firstName / $command->verificationUrl to withAltBody(), which is plain text.
laminas/laminas-escaper 2.18.0 is installed but is not a direct dependency of this package: it arrives transitively via laminas/laminas-view 3.1.0 (^2.17.0) and laminas/laminas-stratigility 4.3.1 (^2.10.0).
- Relevant
laminas-escaper semantics: escapeHtml() is htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, $encoding); escapeHtmlAttr() additionally hex-encodes every character outside [a-zA-Z0-9,.\-_]; escapeUrl() is rawurlencode() and is documented for URL subcomponents only, not for an entire URI.
Convention
Filter and escaper components are used wherever they meet requirements. Any webware component that provides templates can safely depend on laminas/laminas-escaper, as it is a hard requirement of laminas-view.
Context
Surfaced while reviewing the mailer
1.0.0-beta.4domain-command refactor (branchchore/mago-burndown-2-mechanical). Not a regression from that work — the pre-refactorSendVerificationEmailListenerandProcessResendVerificationMiddlewareused the same call. Deferred so it does not block the current merge.Data
CommandHandler\SendVerificationEmailHandlerandCommandHandler\ResendVerificationEmailHandlerescape with the global function and explicit flags:flags:overrides the PHP 8.1+ default ofENT_QUOTES | ENT_SUBSTITUTE. WithoutENT_SUBSTITUTE,htmlspecialchars()returns an empty string for input containing an invalid code sequence, so the value renders blank rather than asU+FFFD.$verificationUrlis interpolated intohref="..."— an attribute context, not a text-node context.$command->firstName/$command->verificationUrltowithAltBody(), which is plain text.laminas/laminas-escaper2.18.0 is installed but is not a direct dependency of this package: it arrives transitively vialaminas/laminas-view3.1.0 (^2.17.0) andlaminas/laminas-stratigility4.3.1 (^2.10.0).laminas-escapersemantics:escapeHtml()ishtmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, $encoding);escapeHtmlAttr()additionally hex-encodes every character outside[a-zA-Z0-9,.\-_];escapeUrl()israwurlencode()and is documented for URL subcomponents only, not for an entire URI.Convention
Filter and escaper components are used wherever they meet requirements. Any webware component that provides templates can safely depend on
laminas/laminas-escaper, as it is a hard requirement of laminas-view.