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