packages/requirements/src/Config/Markdown/StaticBadge.php

1<?php
2
3declare(strict_types=1);
4
5namespace Requirements\Config\Markdown;
6
7use Requirements\Input\InvalidInputException;
8
9/**
10 * Checks that a static shields.io badge image shows the value and role its alt text and
11 * title declare, so the rendered card cannot mislead.
12 */
13final class StaticBadge
14{
15    /**
16     * Checks a badge image; images from other hosts or paths are not checked.
17     *
18     * @param string $url The image URL
19     * @param string $field The field the badge sets
20     * @param string $value The value in its alt text
21     *
22     * @throws InvalidInputException When the static image shows another role or value
23     */
24    public static function validate(string $url, string $field, string $value): void
25    {
26        $path = rawurldecode((string) parse_url($url, PHP_URL_PATH));
27        if (parse_url($url, PHP_URL_HOST) !== 'img.shields.io' || preg_match('~^/badge/(kind|status|origin|category|label)-(.*)$~', $path, $match) !== 1) {
28            return;
29        }
30        $parts = explode('-', str_replace('--', "\0", $match[2]));
31        $message = str_replace(["\0", '_'], ['-', ' '], str_replace('__', "\1", $parts[0]));
32        $message = str_replace("\1", '_', $message);
33        if (count($parts) !== 2 || $match[1] !== $field || $message !== $value) {
34            throw new InvalidInputException('Static badge image text and role must agree with its alt text and title.');
35        }
36    }
37}
38