Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
48.44% covered (danger)
48.44%
31 / 64
50.00% covered (danger)
50.00%
4 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
TemplateBasedTaskTypeHandler
48.44% covered (danger)
48.44%
31 / 64
50.00% covered (danger)
50.00%
4 / 8
110.68
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 validateTaskTypeConfiguration
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
3
 createTaskType
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
2
 getSearchTerm
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getSubmissionHandler
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getChangeTags
10.53% covered (danger)
10.53%
2 / 19
0.00% covered (danger)
0.00%
0 / 1
53.84
 getTaskTypeIdByChangeTagName
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
56
1<?php
2
3namespace GrowthExperiments\NewcomerTasks\TaskType;
4
5use GrowthExperiments\Config\Validation\GrowthConfigValidation;
6use GrowthExperiments\NewcomerTasks\ConfigurationLoader\ConfigurationValidator;
7use GrowthExperiments\NewcomerTasks\SubmissionHandler;
8use GrowthExperiments\NewcomerTasks\TemplateBasedTaskSubmissionHandler;
9use InvalidArgumentException;
10use MediaWiki\Title\TitleParser;
11use StatusValue;
12
13/**
14 * A handler for task types that represent an article with a certain maintenance template on it.
15 */
16class TemplateBasedTaskTypeHandler extends TaskTypeHandler {
17
18    public const ID = 'template-based';
19
20    public const NEWCOMER_TASK_COPYEDIT_TAG = 'newcomer task copyedit';
21    public const NEWCOMER_TASK_REFERENCES_TAG = 'newcomer task references';
22    public const NEWCOMER_TASK_UPDATE_TAG = 'newcomer task update';
23    public const NEWCOMER_TASK_EXPAND_TAG = 'newcomer task expand';
24    public const NEWCOMER_TASK_LINKS_TAG = 'newcomer task links';
25
26    public const NEWCOMER_TASK_TEMPLATE_BASED_ALL_CHANGE_TAGS = [
27        self::NEWCOMER_TASK_COPYEDIT_TAG,
28        self::NEWCOMER_TASK_REFERENCES_TAG,
29        self::NEWCOMER_TASK_UPDATE_TAG,
30        self::NEWCOMER_TASK_EXPAND_TAG,
31        self::NEWCOMER_TASK_LINKS_TAG,
32    ];
33
34    /** @var TitleParser */
35    private $titleParser;
36
37    /** @var TemplateBasedTaskSubmissionHandler */
38    private $submissionHandler;
39
40    /**
41     * @param ConfigurationValidator $configurationValidator
42     * @param TemplateBasedTaskSubmissionHandler $submissionHandler
43     * @param TitleParser $titleParser
44     */
45    public function __construct(
46        ConfigurationValidator $configurationValidator,
47        TemplateBasedTaskSubmissionHandler $submissionHandler,
48        TitleParser $titleParser
49    ) {
50        parent::__construct( $configurationValidator, $titleParser );
51        $this->titleParser = $titleParser;
52        $this->submissionHandler = $submissionHandler;
53    }
54
55    /** @inheritDoc */
56    public function getId(): string {
57        return self::ID;
58    }
59
60    /** @inheritDoc */
61    public function validateTaskTypeConfiguration( string $taskTypeId, array $config ): StatusValue {
62        $status = parent::validateTaskTypeConfiguration( $taskTypeId, $config );
63        $templateFieldStatus = $this->configurationValidator->validateRequiredField( 'templates',
64            $config, $taskTypeId );
65        $status->merge( $templateFieldStatus );
66        $status->merge( $this->configurationValidator->validateFieldIsArray( 'templates', $config, $taskTypeId ) );
67        if ( $status->isOK() ) {
68            $status->merge( $this->configurationValidator->validateArrayMaxSize(
69                GrowthConfigValidation::MAX_TEMPLATES_IN_COLLECTION, $config['templates'],
70                $taskTypeId, 'templates' ) );
71            foreach ( $config['templates'] as $template ) {
72                $this->validateTemplate( $template, $taskTypeId, $status );
73            }
74        }
75        return $status;
76    }
77
78    /** @inheritDoc */
79    public function createTaskType( string $taskTypeId, array $config ): TaskType {
80        '@phan-var array{group:string,templates:string[]} $config';
81        $templates = [];
82        foreach ( $config['templates'] as $template ) {
83            $templates[] = $this->titleParser->parseTitle( $template, NS_TEMPLATE );
84        }
85        $taskType = new TemplateBasedTaskType(
86            $taskTypeId,
87            $config['group'],
88            [ 'learnMoreLink' => $config['learnmore'] ?? null ],
89            $templates,
90            $this->parseExcludedTemplates( $config ),
91            $this->parseExcludedCategories( $config )
92        );
93        $taskType->setHandlerId( $this->getId() );
94        return $taskType;
95    }
96
97    /** @inheritDoc */
98    public function getSearchTerm( TaskType $taskType ): string {
99        if ( !$taskType instanceof TemplateBasedTaskType ) {
100            throw new InvalidArgumentException( '$taskType must be a TemplateBasedTaskType' );
101        }
102        return parent::getSearchTerm( $taskType ) .
103            'hastemplate:' . Util::escapeSearchTitleList( $taskType->getTemplates() );
104    }
105
106    /**
107     * @return TemplateBasedTaskSubmissionHandler
108     */
109    public function getSubmissionHandler(): SubmissionHandler {
110        return $this->submissionHandler;
111    }
112
113    /** @inheritDoc */
114    public function getChangeTags( ?string $taskType = null ): array {
115        if ( !$taskType ) {
116            return self::NEWCOMER_TASK_TEMPLATE_BASED_ALL_CHANGE_TAGS;
117        }
118        switch ( $taskType ) {
119            case 'copyedit':
120                $taskTypeSpecificTag = self::NEWCOMER_TASK_COPYEDIT_TAG;
121                break;
122            case 'references':
123                $taskTypeSpecificTag = self::NEWCOMER_TASK_REFERENCES_TAG;
124                break;
125            case 'update':
126                $taskTypeSpecificTag = self::NEWCOMER_TASK_UPDATE_TAG;
127                break;
128            case 'expand':
129                $taskTypeSpecificTag = self::NEWCOMER_TASK_EXPAND_TAG;
130                break;
131            case 'links':
132                $taskTypeSpecificTag = self::NEWCOMER_TASK_LINKS_TAG;
133                break;
134            default:
135                throw new InvalidArgumentException( "$taskType is not valid." );
136        }
137        return array_merge( parent::getChangeTags(), [ $taskTypeSpecificTag ] );
138    }
139
140    /** @inheritDoc */
141    public function getTaskTypeIdByChangeTagName( string $changeTagName ): ?string {
142        switch ( $changeTagName ) {
143            case self::NEWCOMER_TASK_COPYEDIT_TAG:
144                return 'copyedit';
145            case self::NEWCOMER_TASK_REFERENCES_TAG:
146                return 'references';
147            case self::NEWCOMER_TASK_UPDATE_TAG:
148                return 'update';
149            case self::NEWCOMER_TASK_EXPAND_TAG:
150                return 'expand';
151            case self::NEWCOMER_TASK_LINKS_TAG:
152                return 'links';
153            default:
154                throw new InvalidArgumentException( "$changeTagName is not valid" );
155        }
156    }
157
158}