File: EditConstraintRunner.php

package info (click to toggle)
mediawiki 1%3A1.43.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 417,464 kB
  • sloc: php: 1,062,949; javascript: 664,290; sql: 9,714; python: 5,458; xml: 3,489; sh: 1,131; makefile: 64
file content (145 lines) | stat: -rw-r--r-- 3,933 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<?php
/**
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 * http://www.gnu.org/copyleft/gpl.html
 *
 * @file
 */

namespace MediaWiki\EditPage\Constraint;

use MediaWiki\Logger\LoggerFactory;
use Psr\Log\LoggerInterface;
use Wikimedia\Assert\Assert;

/**
 * Back end to process the edit constraints
 *
 * Constraints reflect possible errors that need to be checked
 *
 * @since 1.36
 * @internal
 * @author DannyS712
 */
class EditConstraintRunner {

	private LoggerInterface $logger;

	/**
	 * @var IEditConstraint[]
	 *
	 * Constraints to check.
	 */
	private $constraints = [];

	/**
	 * @var IEditConstraint|false
	 *
	 * The constraint that failed, so that its status can be fetched, or false if none failed.
	 */
	private $failedConstraint = false;

	/**
	 * Create a new runner
	 */
	public function __construct() {
		// TODO allow passing an array here as the starting constraints?
		// TODO consider injecting this?
		$this->logger = LoggerFactory::getInstance( 'EditConstraintRunner' );
	}

	/**
	 * Add a constraint to check
	 *
	 * Not all constraints are applicable to the action api or other methods of submitting
	 * an edit
	 *
	 * For constraints that have dependencies, use the EditConstraintFactory.
	 *
	 * @param IEditConstraint $constraint
	 */
	public function addConstraint( IEditConstraint $constraint ) {
		$this->constraints[] = $constraint;
	}

	/**
	 * Run constraint checks
	 *
	 * Returns true if all constraints pass, false otherwise.
	 * Check getLegacyStatus for the reason
	 *
	 * @return bool
	 */
	public function checkConstraints(): bool {
		foreach ( $this->constraints as $constraint ) {
			$result = $constraint->checkConstraint();
			if ( $result !== IEditConstraint::CONSTRAINT_PASSED ) {
				// Use `info` instead of `debug` for the one constraint that failed
				$this->logger->info(
					'Checked {name}, got result: {result}',
					[
						'name' => $this->getConstraintName( $constraint ),
						'result' => $result
					]
				);

				$this->failedConstraint = $constraint;
				return false;
			}

			// Pass, log at `debug` level
			$this->logger->debug(
				'Checked {name}, got result: {result}',
				[
					'name' => $this->getConstraintName( $constraint ),
					'result' => $result
				]
			);
		}
		return true;
	}

	/**
	 * @param IEditConstraint $constraint
	 * @return string
	 */
	private function getConstraintName( IEditConstraint $constraint ): string {
		// Used for debug logging
		$fullClassName = explode( '\\', get_class( $constraint ) );
		$constraintName = end( $fullClassName );
		if ( $constraint instanceof PageSizeConstraint ) {
			// TODO "When you need to do this instanceof, it's a code smell"
			// Convert IEditConstraint to abstract class with a getName method
			// once the initial migration to edit constraints is complete
			// PageSizeConstraint is used twice, make sure they can be told apart
			$constraintName .= ' ' . $constraint->getType();
		}
		return $constraintName;
	}

	/**
	 * Get the constraint that failed
	 *
	 * @return IEditConstraint
	 */
	public function getFailedConstraint(): IEditConstraint {
		Assert::precondition(
			$this->failedConstraint !== false,
			'getFailedConstraint called with no failed constraint'
		);
		return $this->failedConstraint;
	}

}