MediaWiki master
ChangesListFilterFactory.php
Go to the documentation of this file.
1<?php
2
4
5use InvalidArgumentException;
6use UnexpectedValueException;
7
13 private ?string $showHidePrefix;
14
15 public function __construct( private array $config ) {
16 $this->showHidePrefix = $config['showHidePrefix'] ?? null;
17 }
18
56 array $definitions
57 ) {
58 foreach ( $definitions as $groupDefinition ) {
59 if ( !$this->isConfigSatisfied( $groupDefinition ) ) {
60 continue;
61 }
62 $this->transformGroupDefinition( $container, $groupDefinition );
63 $group = $this->createGroup( $groupDefinition );
64 $this->registerSupersets( $group, $groupDefinition );
65 $container->registerGroup( $group );
66 $this->registerConflicts( $container, $group, $groupDefinition );
67 $this->handlePendingConflicts( $container, $group );
68 }
69 }
70
79 private function isConfigSatisfied( array $def ) {
80 foreach ( $def['requireConfig'] ?? [] as $name => $value ) {
81 if ( !array_key_exists( $name, $this->config ) || $this->config[$name] !== $value ) {
82 return false;
83 }
84 }
85 return true;
86 }
87
88 private function transformGroupDefinition(
89 ChangesListFilterGroupContainer $container,
90 array &$groupDefinition
91 ) {
92 $groupDefinition['priority'] =
93 $container->fillPriority( $groupDefinition['priority'] ?? null );
94
95 $filterDefs = [];
96 foreach ( $groupDefinition['filters'] as $def ) {
97 if ( !$this->isConfigSatisfied( $def ) ) {
98 continue;
99 }
100 $def = $this->transformFilterDefinition( $def );
101 $filterDefs[] = $def;
102 }
103 $groupDefinition['filters'] = $filterDefs;
104 }
105
115 private function transformFilterDefinition( array $filterDefinition ) {
116 if ( $this->showHidePrefix !== null && isset( $filterDefinition['showHideSuffix'] ) ) {
117 $filterDefinition['showHide'] = $this->showHidePrefix . $filterDefinition['showHideSuffix'];
118 }
119
120 return $filterDefinition;
121 }
122
123 private function createGroup( array $groupDefinition ): ChangesListFilterGroup {
124 $className = $groupDefinition['class'];
125 unset( $groupDefinition['class'] );
126
127 $group = new $className( $groupDefinition );
128 if ( !( $group instanceof ChangesListFilterGroup ) ) {
129 throw new UnexpectedValueException(
130 "$className was expected to be an instance of ChangesListFilterGroup" );
131 }
132 return $group;
133 }
134
142 private function registerSupersets( ChangesListFilterGroup $group, array $groupDefinition ) {
143 foreach ( $groupDefinition['filters'] as $def ) {
144 foreach ( $def['subsets'] ?? [] as $subsetName ) {
145 $filter = $group->getFilter( $def['name'] );
146 $subset = $group->getFilter( $subsetName );
147 if ( $filter && $subset ) {
148 $filter->setAsSupersetOf( $subset );
149 }
150 }
151 }
152 }
153
163 private function registerConflicts(
164 ChangesListFilterGroupContainer $container,
165 ChangesListFilterGroup $group,
166 array $groupDefinition
167 ) {
168 foreach ( $groupDefinition['filters'] as $def ) {
169 $filter = $group->getFilter( $def['name'] );
170 foreach ( $def['conflictsWith'] ?? [] as $conflictingGroupName => $conflictingFilters ) {
171 foreach ( $conflictingFilters as $conflictingFilterName => $opts ) {
172 '@phan-var array $opts';
173 $opts += $def['conflictOptions'] ?? [];
174 $missing = array_diff(
175 [ 'globalKey', 'forwardKey', 'backwardKey' ],
176 array_keys( $opts )
177 );
178 if ( $missing ) {
179 throw new InvalidArgumentException(
180 "The conflict option(s) " . implode( ', ', $missing ) .
181 " must be present in either conflictsWith or conflictOptions in " .
182 "the definition of filter {$group->getName()}/{$def['name']}"
183 );
184 }
185 $conflictingGroup = $container->getGroup( $conflictingGroupName );
186 $conflictingFilter = $conflictingGroup?->getFilter( $conflictingFilterName );
187 if ( $conflictingFilter ) {
188 $filter->conflictsWith(
189 $conflictingFilter,
190 $opts['globalKey'],
191 $opts['forwardKey'],
192 $opts['backwardKey']
193 );
194 } else {
195 $container->addPendingConflict(
196 $filter,
197 $conflictingGroupName,
198 $conflictingFilterName,
199 $opts
200 );
201 }
202 }
203 }
204 }
205 }
206
215 private function handlePendingConflicts(
216 ChangesListFilterGroupContainer $container,
217 ChangesListFilterGroup $group
218 ) {
219 foreach ( $group->getFilters() as $filter ) {
220 $conflicts = $container->popPendingConflicts( $group, $filter );
221 foreach ( $conflicts as [ $sourceFilter, $opts ] ) {
222 $sourceFilter->conflictsWith(
223 $filter,
224 $opts['globalKey'],
225 $opts['forwardKey'],
226 $opts['backwardKey']
227 );
228 }
229 }
230 }
231}
registerFiltersFromDefinitions(ChangesListFilterGroupContainer $container, array $definitions)
Register filters from an array of group definitions.
registerGroup(ChangesListFilterGroup $group)
Register a structured changes list filter group.