MediaWiki master
LocalUserOptionsStore.php
Go to the documentation of this file.
1<?php
2
4
10
13 private array $optionsFromDb;
14
15 public function __construct(
16 private readonly IConnectionProvider $dbProvider,
17 private readonly HookRunner $hookRunner,
18 ) {
19 }
20
21 public function fetch(
22 UserIdentity $user,
23 int $recency
24 ): array {
25 // In core, only users with local accounts may have preferences
26 if ( !$user->getId() ) {
27 return [];
28 }
29
30 $dbr = DBAccessObjectUtils::getDBFromRecency( $this->dbProvider, $recency );
31 $res = $dbr->newSelectQueryBuilder()
32 ->select( [ 'up_property', 'up_value' ] )
33 ->from( 'user_properties' )
34 ->where( [ 'up_user' => $user->getId() ] )
35 ->recency( $recency )
36 ->caller( __METHOD__ )->fetchResultSet();
37
38 $options = [];
39 foreach ( $res as $row ) {
40 $options[$row->up_property] = (string)$row->up_value;
41 }
42
43 $this->optionsFromDb[$user->getId()] = $options;
44 return $options;
45 }
46
48 public function fetchBatchForUserNames( array $keys, array $userNames ) {
49 if ( !$keys || !$userNames ) {
50 return [];
51 }
52
53 $options = [];
54 $res = $this->dbProvider->getReplicaDatabase()
55 ->newSelectQueryBuilder()
56 ->select( [ 'user_name', 'up_property', 'up_value' ] )
57 ->from( 'user_properties' )
58 ->join( 'user', null, 'user_id=up_user' )
59 ->where( [
60 'up_property' => $keys,
61 'user_name' => $userNames
62 ] )
63 ->caller( __METHOD__ )
64 ->fetchResultSet();
65 foreach ( $res as $row ) {
66 $options[$row->up_property][$row->user_name] = (string)$row->up_value;
67 }
68 return $options;
69 }
70
72 public function store( UserIdentity $user, array $updates ) {
73 // In core, only users with local accounts may have preferences
74 if ( !$user->getId() ) {
75 return false;
76 }
77
78 $oldOptions = $this->optionsFromDb[ $user->getId() ]
79 ?? $this->fetch( $user, IDBAccessObject::READ_LATEST );
80 $newOptions = $oldOptions;
81 $keysToDelete = [];
82 $rowsToInsert = [];
83 foreach ( $updates as $key => $value ) {
85 $value, $oldOptions[$key] ?? null )
86 ) {
87 // Update by deleting and reinserting
88 if ( array_key_exists( $key, $oldOptions ) ) {
89 $keysToDelete[] = $key;
90 unset( $newOptions[$key] );
91 }
92 if ( $value !== null ) {
93 $truncValue = mb_strcut( $value, 0,
95 $rowsToInsert[] = [
96 'up_user' => $user->getId(),
97 'up_property' => $key,
98 'up_value' => $truncValue,
99 ];
100 $newOptions[$key] = $truncValue;
101 }
102 }
103 }
104 if ( !count( $keysToDelete ) && !count( $rowsToInsert ) ) {
105 // Nothing to do
106 return false;
107 }
108
109 // Do the DELETE
110 $dbw = $this->dbProvider->getPrimaryDatabase();
111 if ( $keysToDelete ) {
112 $dbw->newDeleteQueryBuilder()
113 ->deleteFrom( 'user_properties' )
114 ->where( [ 'up_user' => $user->getId() ] )
115 ->andWhere( [ 'up_property' => $keysToDelete ] )
116 ->caller( __METHOD__ )->execute();
117 }
118 if ( $rowsToInsert ) {
119 // Insert the new preference rows
120 $dbw->newInsertQueryBuilder()
121 ->insertInto( 'user_properties' )
122 ->ignore()
123 ->rows( $rowsToInsert )
124 ->caller( __METHOD__ )->execute();
125 }
126
127 // Update cache
128 $this->optionsFromDb[$user->getId()] = $newOptions;
129
130 $this->hookRunner->onLocalUserOptionsStoreSave( $user, $oldOptions, $newOptions );
131
132 return true;
133 }
134
135}
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:69
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
__construct(private readonly IConnectionProvider $dbProvider, private readonly HookRunner $hookRunner,)
fetchBatchForUserNames(array $keys, array $userNames)
Fetch specific options for multiple users from the store.Return an array indexed first by option key,...
store(UserIdentity $user, array $updates)
Process a batch of option updates.The store may assume that fetch() was previously called with a rece...
fetch(UserIdentity $user, int $recency)
Fetch all options for a given user from the store.
static isValueEqual( $a, $b)
Determines whether two values are sufficiently similar that the database does not need to be updated ...
Get or change options for a given user in a given backend store.
Interface for objects representing user identity.
getId( $wikiId=self::LOCAL)
Provide primary and replica IDatabase connections.
Interface for database access objects.