Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 60
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiInvalidatePersonalizedPraiseSuggestion
0.00% covered (danger)
0.00%
0 / 60
0.00% covered (danger)
0.00%
0 / 6
156
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 1
56
 needsToken
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isWriteMode
0.00% covered (danger)
0.00%
0 / 1
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
 getAllowedParams
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace GrowthExperiments\Api;
4
5use ApiBase;
6use ApiMain;
7use GrowthExperiments\EventLogging\PersonalizedPraiseLogger;
8use GrowthExperiments\MentorDashboard\PersonalizedPraise\PraiseworthyMenteeSuggester;
9use GrowthExperiments\Mentorship\Provider\MentorProvider;
10use GrowthExperiments\Mentorship\Store\MentorStore;
11use MediaWiki\Logger\LoggerFactory;
12use MediaWiki\ParamValidator\TypeDef\UserDef;
13use MediaWiki\User\UserIdentity;
14use Wikimedia\ParamValidator\ParamValidator;
15
16class ApiInvalidatePersonalizedPraiseSuggestion extends ApiBase {
17
18    private MentorProvider $mentorProvider;
19    private MentorStore $mentorStore;
20    private PraiseworthyMenteeSuggester $praiseworthyMenteeSuggester;
21
22    private PersonalizedPraiseLogger $personalizedPraiseLogger;
23
24    /**
25     * @param ApiMain $mainModule
26     * @param string $moduleName
27     * @param MentorProvider $mentorProvider
28     * @param MentorStore $mentorStore
29     * @param PraiseworthyMenteeSuggester $praiseworthyMenteeSuggester
30     * @param PersonalizedPraiseLogger $personalizedPraiseLogger
31     */
32    public function __construct(
33        ApiMain $mainModule,
34        $moduleName,
35        MentorProvider $mentorProvider,
36        MentorStore $mentorStore,
37        PraiseworthyMenteeSuggester $praiseworthyMenteeSuggester,
38        PersonalizedPraiseLogger $personalizedPraiseLogger
39    ) {
40        parent::__construct( $mainModule, $moduleName );
41
42        $this->mentorProvider = $mentorProvider;
43        $this->mentorStore = $mentorStore;
44        $this->praiseworthyMenteeSuggester = $praiseworthyMenteeSuggester;
45        $this->personalizedPraiseLogger = $personalizedPraiseLogger;
46    }
47
48    /** @inheritDoc */
49    public function execute() {
50        if ( !$this->mentorProvider->isMentor( $this->getUser() ) ) {
51            $this->dieWithError( [ 'apierror-permissiondenied-generic' ] );
52        }
53
54        $params = $this->extractRequestParams();
55        /** @var UserIdentity $mentee */
56        $mentee = $params['mentee'];
57
58        if ( $params['reason'] === PersonalizedPraiseLogger::ACTION_PRAISED ) {
59            $this->praiseworthyMenteeSuggester->markMenteeAsPraised( $mentee );
60        } elseif ( $params['reason'] === PersonalizedPraiseLogger::ACTION_SKIPPED ) {
61            $this->praiseworthyMenteeSuggester->markMenteeAsSkipped( $mentee );
62        }
63
64        $this->getResult()->addValue( null, $this->getModuleName(), [
65            'status' => 'ok',
66            'mentee' => $mentee->getName(),
67        ] );
68
69        $mentor = $this->mentorStore->loadMentorUser( $mentee, MentorStore::ROLE_PRIMARY );
70        if ( !$mentor ) {
71            LoggerFactory::getInstance( 'GrowthExperiments' )->warning(
72                'ApiInvalidatePersonalizedPraiseSuggestion failed to load mentor for {mentee}',
73                [ 'mentee' => $mentee->getName() ]
74            );
75            return;
76        }
77
78        if ( $params['reason'] === PersonalizedPraiseLogger::ACTION_PRAISED ) {
79            $this->personalizedPraiseLogger->logPraised(
80                $mentor,
81                $mentee
82            );
83        } elseif ( $params['reason'] === PersonalizedPraiseLogger::ACTION_SKIPPED ) {
84            $this->personalizedPraiseLogger->logSkipped(
85                $mentor,
86                $mentee,
87                $params['skipreason']
88            );
89        }
90    }
91
92    public function needsToken() {
93        return 'csrf';
94    }
95
96    /** @inheritDoc */
97    public function isWriteMode() {
98        return true;
99    }
100
101    /** @inheritDoc */
102    public function isInternal() {
103        return true;
104    }
105
106    /** @inheritDoc */
107    protected function getAllowedParams() {
108        return [
109            'mentee' => [
110                ParamValidator::PARAM_REQUIRED => true,
111                ParamValidator::PARAM_TYPE => 'user',
112                UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name', 'id' ],
113                UserDef::PARAM_RETURN_OBJECT => true,
114            ],
115            'reason' => [
116                ParamValidator::PARAM_TYPE => [
117                    'skipped',
118                    'praised'
119                ],
120            ],
121            'skipreason' => [
122                // NOTE: Keep in sync with SkipMenteeDialog.vue's reasonItems
123                ParamValidator::PARAM_TYPE => [
124                    'already-praised',
125                    'not-praiseworthy',
126                    'not-now',
127                    'other'
128                ],
129            ],
130        ];
131    }
132}