Page MenuHomeWickedGov Phorge

LogStore.php
No OneTemporary

Size
3 KB
Referenced Files
None
Subscribers
None

LogStore.php

<?php
namespace MediaWiki\Extension\Thanks\Storage;
use InvalidArgumentException;
use MediaWiki\CheckUser\Hooks;
use MediaWiki\Config\ServiceOptions;
use MediaWiki\Extension\Thanks\Storage\Exceptions\InvalidLogType;
use MediaWiki\Extension\Thanks\Storage\Exceptions\LogDeleted;
use MediaWiki\Logging\DatabaseLogEntry;
use MediaWiki\Logging\ManualLogEntry;
use MediaWiki\Registration\ExtensionRegistry;
use MediaWiki\User\ActorNormalization;
use MediaWiki\User\User;
use Wikimedia\Rdbms\IConnectionProvider;
/**
* Manages the storage for Thank events.
* Thanks are stored as logs with relations between users.
* Each thank action should have an unique ID generated by callers.
*/
class LogStore {
public const CONSTRUCTOR_OPTIONS = [ 'ThanksLogging', 'ThanksAllowedLogTypes' ];
public function __construct(
protected readonly IConnectionProvider $conn,
protected readonly ActorNormalization $actorNormalization,
protected readonly ServiceOptions $serviceOptions,
) {
$serviceOptions->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
}
/**
* @param User $user The user performing the thanks (and the log entry).
* @param User $recipient The target of the thanks (and the log entry).
* @param string $uniqueId A unique Id to identify the event being thanked for, to use
* when checking for duplicate thanks
*/
public function thank( User $user, User $recipient, string $uniqueId ): void {
if ( $user->isTemp() ) {
throw new InvalidArgumentException(
'Temporary accounts may not thank other users.'
);
}
if ( !$this->serviceOptions->get( 'ThanksLogging' ) ) {
return;
}
$logEntry = new ManualLogEntry( 'thanks', 'thank' );
$logEntry->setPerformer( $user );
$logEntry->setRelations( [ 'thankid' => $uniqueId ] );
$target = $recipient->getUserPage();
$logEntry->setTarget( $target );
$logId = $logEntry->insert();
$logEntry->publish( $logId, 'udp' );
if ( ExtensionRegistry::getInstance()->isLoaded( 'CheckUser' ) ) {
$recentChange = $logEntry->getRecentChange();
// TODO: This should be done in a separate hook handler
Hooks::updateCheckUserData( $recentChange );
}
}
/**
* This checks the log_search data.
*
* @param User $thanker The user sending the thanks.
* @param string $uniqueId The identifier for the thanks.
* @return bool Whether thanks has already been sent
*/
public function haveThanked( User $thanker, string $uniqueId ): bool {
// TODO: Figure out why it's not getting the data from a replica
$dbw = $this->conn->getPrimaryDatabase();
$thankerActor = $this->actorNormalization->acquireActorId( $thanker, $dbw );
return (bool)$dbw->newSelectQueryBuilder()
->select( 'ls_value' )
->from( 'log_search' )
->join( 'logging', null, [ 'ls_log_id=log_id' ] )
->where(
[
'log_actor' => $thankerActor,
'ls_field' => 'thankid',
'ls_value' => $uniqueId,
]
)
->caller( __METHOD__ )
->fetchRow();
}
/**
* @throws InvalidLogType
* @throws LogDeleted
*/
public function getLogEntryFromId( int $logId ): ?DatabaseLogEntry {
$logEntry = DatabaseLogEntry::newFromId( $logId, $this->conn->getPrimaryDatabase() );
if ( !$logEntry ) {
return null;
}
// Make sure this log type is allowed.
$allowedLogTypes = $this->serviceOptions->get( 'ThanksAllowedLogTypes' );
if ( !in_array( $logEntry->getType(), $allowedLogTypes )
&& !in_array( $logEntry->getType() . '/' . $logEntry->getSubtype(), $allowedLogTypes ) ) {
throw new InvalidLogType( $logEntry->getType() );
}
// Don't permit thanks if any part of the log entry is deleted.
if ( $logEntry->getDeleted() ) {
throw new LogDeleted();
}
return $logEntry;
}
}

File Metadata

Mime Type
text/x-php
Expires
Aug 19 2026, 20:10 (7 w, 1 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
e3/8a/2c1ba3ddb1a1b24f0fdb106480e0
Default Alt Text
LogStore.php (3 KB)

Event Timeline