[], self::MEDIUM => [], self::LOW => [], self::NONE => [], ]; /** * @var bool[] * @phan-var array */ private $hasNameParam = []; /** * @var bool[] * @phan-var array */ private $hasNoParams = []; /** * @var bool[] * @phan-var array */ private $isEnabled = []; /** * Do not instantiate directly: use MediaWikiServices to fetch. * @param array $linterCategories */ public function __construct( array $linterCategories ) { foreach ( $linterCategories as $name => $info ) { $this->isEnabled[$name] = $info['enabled']; if ( $info['enabled'] ) { $this->categories[$info['priority']][] = $name; } if ( $info['has-name'] ?? false ) { $this->hasNameParam[$name] = true; } if ( $info['no-params'] ?? false ) { $this->hasNoParams[$name] = true; } if ( isset( $info['dbid'] ) ) { if ( isset( $this->categoryIds[$name] ) ) { throw new InvalidArgumentException( "duplicate ID: $name" ); } $this->categoryIds[$name] = $info['dbid']; } } sort( $this->categories[self::HIGH] ); sort( $this->categories[self::MEDIUM] ); sort( $this->categories[self::LOW] ); sort( $this->categories[self::NONE] ); } /** * @param string $name * @return bool */ public function hasNameParam( $name ) { return isset( $this->hasNameParam[$name] ); } /** * @param string $name * @return bool */ public function hasNoParams( $name ) { return isset( $this->hasNoParams[$name] ); } public function isEnabled( string $name ): bool { // Default to true so !isKnownCategory aren't dropped return $this->isEnabled[$name] ?? true; } /** * @return string[] */ public function getHighPriority() { return $this->categories[self::HIGH]; } /** * @return string[] */ public function getMediumPriority() { return $this->categories[self::MEDIUM]; } /** * @return string[] */ public function getLowPriority() { return $this->categories[self::LOW]; } /** * @return string[] */ public function getNonePriority() { return $this->categories[self::NONE]; } /** * Categories that are configured to be displayed to users * * @return string[] */ public function getVisibleCategories() { return array_merge( $this->categories[self::HIGH], $this->categories[self::MEDIUM], $this->categories[self::LOW] ); } /** * Categories that are configured to not be displayed to users * * @return string[] */ public function getInvisibleCategories() { return $this->categories[self::NONE]; } /** * Whether this category has a hardcoded id and can be * inserted into the database * * @param string $name * @return bool */ public function isKnownCategory( $name ) { return isset( $this->categoryIds[$name] ); } /** * @param int $id * @return string * @throws MissingCategoryException if we can't find the name for the id */ public function getCategoryName( $id ) { $flip = array_flip( $this->categoryIds ); if ( isset( $flip[$id] ) ) { return $flip[$id]; } throw new MissingCategoryException( "Could not find name for id $id" ); } /** * @param string[] $names * @return int[] */ public function getCategoryIds( array $names ) { $result = []; foreach ( $names as $name ) { $result[$name] = $this->getCategoryId( $name ); } return $result; } /** * Get the int id for the category in lint_categories table * * @param string $name * @param int|null $hint An optional hint, passed along from Parsoid. * If the hint contains a suggested category ID but the Linter * extension doesn't (yet) have one, use the ID from Parsoid's hint. * This allows decoupling the Parsoid deploy of a new category * from the corresponding Linter extension deploy. * @return int * @throws MissingCategoryException if we can't find the id for the name * and there is no hint from Parsoid */ public function getCategoryId( $name, $hint = null ) { if ( isset( $this->categoryIds[$name] ) ) { return $this->categoryIds[$name]; } // Use hint from Parsoid, if available. if ( $hint !== null ) { return $hint; } throw new MissingCategoryException( "Cannot find id for '$name'" ); } }