1<?php declare(strict_types=1);
2
3/*
4 * This file is part of the Monolog package.
5 *
6 * (c) Jordi Boggiano <j.boggiano@seld.be>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Monolog\Processor;
13
14use Monolog\Logger;
15use Psr\Log\LogLevel;
16
17/**
18 * Injects Hg branch and Hg revision number in all records
19 *
20 * @author Jonathan A. Schweder <jonathanschweder@gmail.com>
21 *
22 * @phpstan-import-type LevelName from \Monolog\Logger
23 * @phpstan-import-type Level from \Monolog\Logger
24 */
25class MercurialProcessor implements ProcessorInterface
26{
27    /** @var Level */
28    private $level;
29    /** @var array{branch: string, revision: string}|array<never>|null */
30    private static $cache = null;
31
32    /**
33     * @param int|string $level The minimum logging level at which this Processor will be triggered
34     *
35     * @phpstan-param Level|LevelName|LogLevel::* $level
36     */
37    public function __construct($level = Logger::DEBUG)
38    {
39        $this->level = Logger::toMonologLevel($level);
40    }
41
42    /**
43     * {@inheritDoc}
44     */
45    public function __invoke(array $record): array
46    {
47        // return if the level is not high enough
48        if ($record['level'] < $this->level) {
49            return $record;
50        }
51
52        $record['extra']['hg'] = self::getMercurialInfo();
53
54        return $record;
55    }
56
57    /**
58     * @return array{branch: string, revision: string}|array<never>
59     */
60    private static function getMercurialInfo(): array
61    {
62        if (self::$cache) {
63            return self::$cache;
64        }
65
66        $result = explode(' ', trim(`hg id -nb`));
67
68        if (count($result) >= 3) {
69            return self::$cache = [
70                'branch' => $result[1],
71                'revision' => $result[2],
72            ];
73        }
74
75        return self::$cache = [];
76    }
77}
78