| 1 |
<?php |
| 2 |
|
| 3 |
if (!defined('ABSPATH')) { |
| 4 |
exit; |
| 5 |
} |
| 6 |
|
| 7 |
/** |
| 8 |
* A body-byte count somebody actually measured, and the name of who measured |
| 9 |
* it. |
| 10 |
* |
| 11 |
* Both halves of the emitted-against-delivered comparison are byte counts, and |
| 12 |
* both have to agree on one question before they can be compared at all: which |
| 13 |
* reported values are real measurements and which are a refusal to answer. The |
| 14 |
* rule and the vocabulary lived in two classes before this one existed -- |
| 15 |
* ABJ_404_Solution_ResponseBodyDeliveryEvidence for the emitted half and |
| 16 |
* ABJ_404_Solution_DeliveredTableResponseSize for the delivered half -- as |
| 17 |
* byte-identical copies, down to the same explanatory sentence. Two copies of |
| 18 |
* the rule that decides whether a comparison is possible is one copy too many: |
| 19 |
* if either had ever been "fixed" alone, the pair would have started comparing |
| 20 |
* a measurement against a refusal and reporting the difference as a rewritten |
| 21 |
* body, which is the exact false finding the comparison exists to avoid. |
| 22 |
* |
| 23 |
* Pure vocabulary and one pure rule. No I/O, no journal knowledge, no |
| 24 |
* formatting. |
| 25 |
*/ |
| 26 |
final class ABJ_404_Solution_MeasuredBodyBytes { |
| 27 |
|
| 28 |
/** Nobody produced a usable count for this half of the comparison. */ |
| 29 |
const SOURCE_UNAVAILABLE = 'unavailable'; |
| 30 |
|
| 31 |
/** |
| 32 |
* Delivered = Resource Timing `decodedBodySize`, the only octet count the |
| 33 |
* browser measures on the wire rather than through the JSON parser. |
| 34 |
*/ |
| 35 |
const SOURCE_RESOURCE_TIMING = 'resource_timing_decoded_body'; |
| 36 |
|
| 37 |
/** Emitted = the encoded JSON only. */ |
| 38 |
const SOURCE_ENCODE = 'json_encode'; |
| 39 |
|
| 40 |
/** |
| 41 |
* Emitted = the encoded JSON plus the `stream` step's leading whitespace |
| 42 |
* block, which is echoed outside json_encode() and so is absent from the |
| 43 |
* encoded count. |
| 44 |
*/ |
| 45 |
const SOURCE_ENCODE_PLUS_STREAM = 'json_encode_plus_stream_whitespace'; |
| 46 |
|
| 47 |
/** |
| 48 |
* The count as a positive integer, or null when the reporter declined to |
| 49 |
* give one. |
| 50 |
* |
| 51 |
* Zero and the client's own -1 sentinel are both unknown, not empty. |
| 52 |
* Resource Timing reports 0 for an entry it will not disclose (an opaque |
| 53 |
* or timing-restricted response) exactly as it would for a genuinely empty |
| 54 |
* body, and nothing downstream can tell those apart. Calling either one |
| 55 |
* "0 bytes" would invent a measurement out of a browser's refusal to |
| 56 |
* answer, and a fabricated zero on either half of the comparison reads as |
| 57 |
* the largest possible discrepancy. |
| 58 |
* |
| 59 |
* @param mixed $value Whatever the journal record carried. |
| 60 |
*/ |
| 61 |
public static function disclosed($value): ?int { |
| 62 |
return is_numeric($value) && (int)$value > 0 ? (int)$value : null; |
| 63 |
} |
| 64 |
} |
| 65 |
|