MediaWiki master
MetadataStorageHelper.php
Go to the documentation of this file.
1<?php
8
9use InvalidArgumentException;
14
23 private $repo;
24
25 public function __construct( LocalRepo $repo ) {
26 $this->repo = $repo;
27 }
28
37 public function getJsonMetadata( $file, $envelope ) {
38 // Try encoding
39 $s = $this->jsonEncode( $envelope );
40
41 // Decide whether to try splitting the metadata.
42 // Return early if it's not going to happen.
43 if ( !$this->repo->isSplitMetadataEnabled()
44 || !$file->getHandler()
45 || !$file->getHandler()->useSplitMetadata()
46 ) {
47 return [ $s, [] ];
48 }
49 $threshold = $this->repo->getSplitMetadataThreshold();
50 if ( !$threshold || strlen( $s ) <= $threshold ) {
51 return [ $s, [] ];
52 }
53 $blobStore = $this->repo->getBlobStore();
54 if ( !$blobStore ) {
55 return [ $s, [] ];
56 }
57
58 // The data as a whole is above the item threshold. Look for
59 // large items that can be split out.
60 $blobAddresses = [];
61 foreach ( $envelope['data'] as $name => $value ) {
62 $encoded = $this->jsonEncode( $value );
63 if ( strlen( $encoded ) > $threshold ) {
64 $blobAddresses[$name] = $blobStore->storeBlob(
65 $encoded,
66 [ BlobStore::IMAGE_HINT => $file->getName() ]
67 );
68 }
69 }
70 // Remove any items that were split out
71 $envelope['data'] = array_diff_key( $envelope['data'], $blobAddresses );
72 $envelope['blobs'] = $blobAddresses;
73 $s = $this->jsonEncode( $envelope );
74
75 return [ $s, $blobAddresses ];
76 }
77
84 public function jsonEncode( $data ): string {
85 $s = json_encode( $data,
86 JSON_INVALID_UTF8_IGNORE |
87 JSON_UNESCAPED_SLASHES |
88 JSON_UNESCAPED_UNICODE );
89 if ( $s === false ) {
90 throw new InvalidArgumentException( __METHOD__ . ': metadata is not JSON-serializable ' );
91 }
92 return $s;
93 }
94
95 public function getMetadataFromBlobStore( array $addresses ): array {
96 $result = [];
97 if ( $addresses ) {
98 $blobStore = $this->repo->getBlobStore();
99 if ( !$blobStore ) {
100 LoggerFactory::getInstance( 'LocalFile' )->warning(
101 "Unable to load metadata: repo has no blob store" );
102 return $result;
103 }
104 $status = $blobStore->getBlobBatch( $addresses );
105 if ( !$status->isGood() ) {
106 $msg = Status::wrap( $status )->getWikiText(
107 false, false, 'en' );
108 LoggerFactory::getInstance( 'LocalFile' )->warning(
109 "Error loading metadata from BlobStore: $msg" );
110 }
111 foreach ( $addresses as $itemName => $address ) {
112 $json = $status->getValue()[$address] ?? null;
113 if ( $json !== null ) {
114 $value = $this->jsonDecode( $json );
115 $result[$itemName] = $value;
116 }
117 }
118 }
119 return $result;
120 }
121
133 public function jsonDecode( string $s ) {
134 // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
135 return @json_decode( $s, true, 512, JSON_INVALID_UTF8_IGNORE );
136 }
137
138}
139
141class_alias( MetadataStorageHelper::class, 'MetadataStorageHelper' );
getJsonMetadata( $file, $envelope)
Get metadata in JSON format ready for DB insertion, optionally splitting items out to BlobStore.
jsonEncode( $data)
Do JSON encoding with local flags.
jsonDecode(string $s)
Do JSON decoding with local flags.
Local repository that stores files in the local filesystem and registers them in the wiki's own datab...
Definition LocalRepo.php:45
Create PSR-3 logger objects.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:44
Service for loading and storing data blobs.
Definition BlobStore.php:19
const IMAGE_HINT
Hint key for an image name.
Definition BlobStore.php:73