Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
97.37% |
37 / 38 |
|
0.00% |
0 / 1 |
CRAP | |
0.00% |
0 / 1 |
| MultiListBuilder | |
97.37% |
37 / 38 |
|
0.00% |
0 / 1 |
5 | |
0.00% |
0 / 1 |
| buildWeightedTags | |
97.37% |
37 / 38 |
|
0.00% |
0 / 1 |
5 | |||
| 1 | <?php |
| 2 | |
| 3 | namespace CirrusSearch\Extra\MultiList; |
| 4 | |
| 5 | use Wikimedia\Assert\Assert; |
| 6 | |
| 7 | /** |
| 8 | * Utility class for encoding weighted tags. |
| 9 | * |
| 10 | * @see https://wikitech.wikimedia.org/wiki/Search/WeightedTags |
| 11 | */ |
| 12 | class MultiListBuilder { |
| 13 | |
| 14 | private const WEIGHTED_TAG_DEFAULT_NAME = 'exists'; |
| 15 | |
| 16 | /** |
| 17 | * @param string $tagPrefix A prefix shared by all `$tagNames` |
| 18 | * @param null|null[]|int[] $tagWeightsByName Optional tag weights. A map of optional weights, keyed by tag name. |
| 19 | * Omit for tags which are fully defined by their prefix. |
| 20 | * A single weight ranges between 1-1000. |
| 21 | * |
| 22 | * @return MultiListWeightedTag[] |
| 23 | */ |
| 24 | public static function buildWeightedTags( |
| 25 | string $tagPrefix, |
| 26 | ?array $tagWeightsByName = null |
| 27 | ): array { |
| 28 | Assert::precondition( |
| 29 | trim( $tagPrefix ) !== '', |
| 30 | "invalid tag prefix [$tagPrefix]: cannot be empty" |
| 31 | ); |
| 32 | Assert::precondition( |
| 33 | strpos( $tagPrefix, MultiListItem::DELIMITER ) === false, |
| 34 | "invalid tag prefix $tagPrefix: must not contain " . MultiListItem::DELIMITER |
| 35 | ); |
| 36 | |
| 37 | Assert::parameterType( |
| 38 | [ |
| 39 | 'array', |
| 40 | 'null' |
| 41 | ], |
| 42 | $tagWeightsByName, |
| 43 | '$tagWeightsByName' |
| 44 | ); |
| 45 | |
| 46 | if ( $tagWeightsByName === null ) { |
| 47 | $tagWeightsByName = [ self::WEIGHTED_TAG_DEFAULT_NAME => null ]; |
| 48 | } |
| 49 | |
| 50 | foreach ( $tagWeightsByName as $tagName => $tagWeight ) { |
| 51 | Assert::precondition( |
| 52 | strpos( $tagName, MultiListWeightedTag::WEIGHT_DELIMITER ) === false, |
| 53 | "invalid tag name $tagName: must not contain " . MultiListWeightedTag::WEIGHT_DELIMITER |
| 54 | ); |
| 55 | if ( $tagWeight !== null ) { |
| 56 | Assert::precondition( |
| 57 | is_int( $tagWeight ), |
| 58 | "weights must be integers but $tagWeight is " . get_debug_type( $tagWeight ) |
| 59 | ); |
| 60 | Assert::precondition( |
| 61 | $tagWeight >= 1 && $tagWeight <= 1000, |
| 62 | "weights must be between 1 and 1000 (found: $tagWeight)" |
| 63 | ); |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | return array_map( |
| 68 | static fn ( $tagName ) => new MultiListWeightedTag( |
| 69 | $tagPrefix, $tagName, $tagWeightsByName[$tagName] |
| 70 | ), |
| 71 | array_keys( $tagWeightsByName ) |
| 72 | ); |
| 73 | } |
| 74 | } |