Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 46
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiQueryDeletedTranslations
0.00% covered (danger)
0.00%
0 / 46
0.00% covered (danger)
0.00%
0 / 5
72
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 31
0.00% covered (danger)
0.00%
0 / 1
20
 getAllowedParams
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 getExamplesMessages
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 isInternal
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * A query module to get total number of deleted translations
4 * published by the user, during some period.
5 *
6 * @copyright See AUTHORS.txt
7 * @license GPL-2.0-or-later
8 */
9
10namespace ContentTranslation\ActionApi;
11
12use ApiQuery;
13use ApiQueryBase;
14use MediaWiki\MediaWikiServices;
15use MediaWiki\Storage\NameTableAccessException;
16use Wikimedia\ParamValidator\ParamValidator;
17
18class ApiQueryDeletedTranslations extends ApiQueryBase {
19    public function __construct( ApiQuery $query, $moduleName ) {
20        parent::__construct( $query, $moduleName, 'dt' );
21    }
22
23    public function execute() {
24        $user = $this->getUser();
25        if ( !$user->isRegistered() ) {
26            $this->dieWithError( 'apierror-mustbeloggedin-generic', 'mustbeloggedin' );
27        }
28
29        $params = $this->extractRequestParams();
30        $after = $params[ 'after' ];
31
32        $this->addTables( [ 'change_tag', 'archive' ] );
33        $this->addFields( [ 'deleted_count' => 'COUNT(*)' ] );
34        $this->addJoinConds( [ 'change_tag' => [ 'LEFT JOIN', 'ar_rev_id = ct_rev_id' ] ] );
35
36        $changeTagDefStore = MediaWikiServices::getInstance()->getChangeTagDefStore();
37        try {
38            $this->addWhereFld( 'ct_tag_id', $changeTagDefStore->getId( 'contenttranslation' ) );
39        } catch ( NameTableAccessException $exception ) {
40            // Return zero deleted articles if we cannot find contenttranslation tag definition ID
41            $this->getResult()->addValue( [ 'query', $this->getModuleName() ], 'deleted', 0 );
42            return;
43        }
44
45        $this->addWhereFld(
46            'ar_actor',
47            $this->getDB()->newSelectQueryBuilder()
48                ->select( 'actor_id' )
49                ->from( 'actor' )
50                ->where( [ 'actor_user' => $user->getId() ] )
51                ->caller( __METHOD__ )
52                ->fetchField()
53        );
54        $this->addWhereFld( 'ar_namespace', $params[ 'namespace' ] ?? NS_MAIN );
55        if ( $after !== null ) {
56            $this->addTimestampWhereRange( 'ar_timestamp', 'newer', $after, null, false );
57        }
58
59        /*
60         * Generated SQL query example
61         *
62         * SELECT COUNT(*) AS deleted_count FROM `archive`
63         * LEFT JOIN `change_tag` ON ((ar_rev_id = ct_rev_id))
64         * WHERE ct_tag_id = '2' AND ar_actor = '217' AND
65         * ar_namespace = '0' AND (ar_timestamp>='20190407162444')
66         */
67        $row = $this->select( __METHOD__ )->current();
68
69        $this->getResult()->addValue(
70            [ 'query', $this->getModuleName() ],
71            'deleted',
72            (int)$row->deleted_count
73        );
74    }
75
76    public function getAllowedParams() {
77        return [
78            'after' => [
79                ParamValidator::PARAM_TYPE => 'timestamp',
80            ],
81            'namespace' => [
82                ParamValidator::PARAM_TYPE => 'namespace',
83            ],
84        ];
85    }
86
87    protected function getExamplesMessages() {
88        $url = 'action=query&meta=cxdeletedtranslations' .
89            '&dtafter=2019-04-07T16%3A24%3A44.000Z&dtnamespace=0';
90
91        return [
92            $url => 'apihelp-query+cxdeletedtranslations-example-1',
93        ];
94    }
95
96    public function isInternal() {
97        return true;
98    }
99}