Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
PersistentDatabaseCache.php
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\Cache;
5
6use Iterator;
7use MediaWiki\Json\JsonCodec;
8use Wikimedia\Rdbms\ILoadBalancer;
9
17 private const TABLE_NAME = 'translate_cache';
18 private ILoadBalancer $loadBalancer;
19 private JsonCodec $jsonCodec;
20
21 public function __construct( ILoadBalancer $loadBalancer, JsonCodec $jsonCodec ) {
22 $this->loadBalancer = $loadBalancer;
23 $this->jsonCodec = $jsonCodec;
24 }
25
27 public function get( string ...$keynames ): array {
28 $dbr = $this->loadBalancer->getConnection( DB_REPLICA );
29 $rows = $dbr->newSelectQueryBuilder()
30 ->select( [ 'tc_key', 'tc_value', 'tc_exptime', 'tc_tag' ] )
31 ->from( self::TABLE_NAME )
32 ->where( [ 'tc_key' => $keynames ] )
33 ->caller( __METHOD__ )
34 ->fetchResultSet();
35
36 return $this->buildEntries( $rows );
37 }
38
40 public function getByTag( string $tag ): array {
41 $dbr = $this->loadBalancer->getConnection( DB_REPLICA );
42 $rows = $dbr->newSelectQueryBuilder()
43 ->select( [ 'tc_key', 'tc_value', 'tc_exptime', 'tc_tag' ] )
44 ->from( self::TABLE_NAME )
45 ->where( [ 'tc_tag' => $tag ] )
46 ->caller( __METHOD__ )
47 ->fetchResultSet();
48
49 return $this->buildEntries( $rows );
50 }
51
52 public function has( string $keyname ): bool {
53 $dbr = $this->loadBalancer->getConnection( DB_REPLICA );
54 $hasRow = $dbr->newSelectQueryBuilder()
55 ->select( 'tc_key' )
56 ->from( self::TABLE_NAME )
57 ->where( [ 'tc_key' => $keyname ] )
58 ->caller( __METHOD__ )
59 ->fetchRow();
60
61 return (bool)$hasRow;
62 }
63
64 public function hasEntryWithTag( string $tag ): bool {
65 $dbr = $this->loadBalancer->getConnection( DB_REPLICA );
66 $hasRow = $dbr->newSelectQueryBuilder()
67 ->select( 'tc_key' )
68 ->from( self::TABLE_NAME )
69 ->where( [ 'tc_tag' => $tag ] )
70 ->caller( __METHOD__ )
71 ->fetchRow();
72
73 return (bool)$hasRow;
74 }
75
76 public function set( PersistentCacheEntry ...$entries ): void {
77 $dbw = $this->loadBalancer->getConnection( DB_PRIMARY );
78
79 foreach ( $entries as $entry ) {
80 $value = $this->jsonCodec->serialize( $entry->value() );
81 $rowsToInsert = [
82 'tc_key' => $entry->key(),
83 'tc_value' => $value,
84 'tc_exptime' => $dbw->timestampOrNull( $entry->exptime() ),
85 'tc_tag' => $entry->tag()
86 ];
87
88 $rowsToUpdate = [
89 'tc_value' => $value,
90 'tc_exptime' => $dbw->timestampOrNull( $entry->exptime() ),
91 'tc_tag' => $entry->tag()
92 ];
93
94 $dbw->upsert(
95 self::TABLE_NAME,
96 $rowsToInsert,
97 'tc_key',
98 $rowsToUpdate,
99 __METHOD__
100 );
101 }
102 }
103
104 public function setExpiry( string $keyname, int $expiryTime ): void {
105 $dbw = $this->loadBalancer->getConnection( DB_PRIMARY );
106 $dbw->update(
107 self::TABLE_NAME,
108 [ 'tc_exptime' => $dbw->timestamp( $expiryTime ) ],
109 [ 'tc_key' => $keyname ],
110 __METHOD__
111 );
112 }
113
114 public function delete( string ...$keynames ): void {
115 $dbw = $this->loadBalancer->getConnection( DB_PRIMARY );
116 $dbw->delete(
117 self::TABLE_NAME,
118 [ 'tc_key' => $keynames ],
119 __METHOD__
120 );
121 }
122
123 public function deleteEntriesWithTag( string $tag ): void {
124 $dbw = $this->loadBalancer->getConnection( DB_PRIMARY );
125 $dbw->delete(
126 self::TABLE_NAME,
127 [ 'tc_tag' => $tag ],
128 __METHOD__
129 );
130 }
131
132 public function clear(): void {
133 $dbw = $this->loadBalancer->getConnection( DB_PRIMARY );
134 $dbw->delete(
135 self::TABLE_NAME,
136 '*',
137 __METHOD__
138 );
139 }
140
142 private function buildEntries( Iterator $rows ): array {
143 $entries = [];
144 foreach ( $rows as $row ) {
145 $entries[] = new PersistentCacheEntry(
146 $row->tc_key,
147 $this->jsonCodec->unserialize( $row->tc_value ),
148 $row->tc_exptime ? (int)wfTimestamp( TS_UNIX, $row->tc_exptime ) : null,
149 $row->tc_tag
150 );
151 }
152
153 return $entries;
154 }
155}
A persistent cache implementation using the database.
Defines what method should be provided by a class implementing a persistent cache.