wikimedia/mediawiki-extensions-Translate

View on GitHub
src/Synchronization/ManageGroupSynchronizationCacheActionApi.php

Summary

Maintainability
A
3 hrs
Test Coverage
<?php
declare( strict_types = 1 );

namespace MediaWiki\Extension\Translate\Synchronization;

use ApiBase;
use ApiMain;
use Exception;
use FormatJson;
use MediaWiki\Extension\Translate\MessageGroupProcessing\MessageGroups;
use MediaWiki\Logger\LoggerFactory;
use Psr\Log\LoggerInterface;
use Wikimedia\ParamValidator\ParamValidator;

/**
 * Api module for managing group synchronization cache
 * @ingroup API TranslateAPI
 * @since 2021.03
 * @author Abijeet Patro
 * @license GPL-2.0-or-later
 */
class ManageGroupSynchronizationCacheActionApi extends ApiBase {
    private const RIGHT = 'translate-manage';
    private const VALID_OPS = [ 'resolveMessage', 'resolveGroup' ];
    private GroupSynchronizationCache $groupSyncCache;
    private LoggerInterface $groupSyncLog;

    public function __construct(
        ApiMain $mainModule,
        string $moduleName,
        GroupSynchronizationCache $groupSyncCache
    ) {
        parent::__construct( $mainModule, $moduleName );
        $this->groupSyncCache = $groupSyncCache;
        $this->groupSyncLog = LoggerFactory::getInstance( 'Translate.GroupSynchronization' );
    }

    public function execute() {
        $this->checkUserRightsAny( self::RIGHT );
        $block = $this->getUser()->getBlock();
        if ( $block && $block->isSitewide() ) {
            $this->dieBlocked( $block );
        }

        $params = $this->extractRequestParams();
        $operation = $params['operation'];
        $groupId = $params['group'];
        $titleStr = $params['title'] ?? null;

        $group = MessageGroups::getGroup( $groupId );
        if ( $group === null ) {
            $this->dieWithError( 'apierror-translate-invalidgroup', 'invalidgroup' );
        }

        try {
            if ( $operation === 'resolveMessage' ) {
                if ( $titleStr === null ) {
                    $this->dieWithError( [ 'apierror-missingparam', 'title' ] );
                }
                $this->markAsResolved( $groupId, $titleStr );
            } elseif ( $operation === 'resolveGroup' ) {
                $this->markAsResolved( $groupId );
            }
        } catch ( Exception $e ) {
            $data = [
                'requestParams' => $params,
                'exceptionMessage' => $e->getMessage()
            ];

            $this->groupSyncLog->error(
                "Error while running: ManageGroupSynchronizationCacheActionApi::execute. Details: \n" .
                FormatJson::encode( $data, true )
            );

            $this->dieWithError(
                [
                    'apierror-translate-operation-error',
                    wfEscapeWikiText( $e->getMessage() )
                ]
            );
        }
    }

    private function markAsResolved( string $groupId, ?string $messageTitle = null ): void {
        if ( $messageTitle === null ) {
            $currentGroupStatus = $this->groupSyncCache->markGroupAsResolved( $groupId );
            $this->groupSyncLog->info(
                '{user} resolved group {groupId}.',
                [
                    'user' => $this->getUser()->getName(),
                    'groupId' => $groupId
                ]
            );
        } else {
            $this->groupSyncCache->markMessageAsResolved( $groupId, $messageTitle );
            $currentGroupStatus = $this->groupSyncCache->syncGroupErrors( $groupId );
            $this->groupSyncLog->info(
                '{user} resolved message {messageTitle} in group {groupId}.',
                [
                    'user' => $this->getUser()->getName(),
                    'groupId' => $groupId,
                    'messageTitle' => $messageTitle
                ]
            );
        }

        $this->getResult()->addValue( null, $this->getModuleName(), [
            'success' => 1,
            'data' => [
                'groupRemainingMessageCount' => count( $currentGroupStatus->getRemainingMessages() )
            ]
        ] );
    }

    protected function getAllowedParams() {
        return [
            'operation' => [
                ParamValidator::PARAM_TYPE => self::VALID_OPS,
                ParamValidator::PARAM_ISMULTI => false,
                ParamValidator::PARAM_REQUIRED => true,
            ],
            'title' => [
                ParamValidator::PARAM_TYPE => 'string',
                ParamValidator::PARAM_REQUIRED => false
            ],
            'group' => [
                ParamValidator::PARAM_TYPE => 'string',
                ParamValidator::PARAM_REQUIRED => true
            ]
        ];
    }

    public function isInternal() {
        return true;
    }

    public function needsToken() {
        return 'csrf';
    }
}