Passed
Pull Request — main (#277)
by Sebastian
07:10 queued 03:45
created

Shorthand::getClass()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 9
nc 4
nop 2
dl 0
loc 14
ccs 10
cts 10
cp 1
crap 4
rs 9.9666
c 1
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of CaptainHook.
5
 *
6
 * (c) Sebastian Feldmann <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace CaptainHook\App\Runner;
13
14
use CaptainHook\App\Hook;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, CaptainHook\App\Runner\Hook. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
15
use RuntimeException;
16
17
/**
18
 * Class Shorthand
19
 *
20
 * Defines some shorthands that can be used in the configuration file to not
21
 * clutter the configuration with the full classnames.
22
 *
23
 * @package CaptainHook
24
 * @author  Sebastian Feldmann <[email protected]>
25
 * @link    https://github.com/captainhook-git/captainhook
26
 * @since   Class available since Release 5.26.0
27
 */
28
class Shorthand
29
{
30
    /**
31
     * Shorthand to action mapping
32
     *
33
     * @var array<string, array<string, array<string, string>>>
34
     */
35
    private static array $map = [
36
        'action'    => [
37
            'branch'  => [
38
                'ensurenaming'                       => Hook\Branch\Action\EnsureNaming::class,
39
                'preventpushoffixupandsquashcommits' => Hook\Branch\Action\BlockFixupAndSquashCommits::class,
40
            ],
41
            'debug'   => [
42
                'fail' => Hook\Debug\Failure::class,
43
                'ok'   => Hook\Debug\Success::class,
44
            ],
45
            'file'    => [
46
                'blocksecrets'        => Hook\Diff\Action\BlockSecrets::class,
47
                'doesnotcontainregex' => Hook\File\Action\DoesNotContainRegex::class,
48
                'isnotempty'          => Hook\File\Action\IsNotEmpty::class,
49
                'maxsize'             => Hook\File\Action\MaxSize::class,
50
            ],
51
            'message' => [
52
                'injectissuekeyfrombranch' => Hook\Message\Action\InjectIssueKeyFromBranch::class,
53
                'cacheonfail    '          => Hook\Message\Action\CacheOnFail::class,
54
                'mustfollowbeamsrules'     => Hook\Message\Action\Beams::class,
55
                'mustcontainsregex'        => Hook\Message\Action\Regex::class,
56
                'preparefromfile'          => Hook\Message\Action\PrepareFromFile::class,
57
                'prepare'                  => Hook\Message\Action\Prepare::class,
58
            ],
59
            'notify'  => [
60
                'gitnotify' => Hook\Notify\Action\Notify::class,
61
            ],
62
        ],
63
        'condition' => [
64
            'inconfig'    => [
65
                'customvalueistruthy' => Hook\Condition\Config\CustomValueIsTruthy::class,
66
                'customvalueisfalsy'  => Hook\Condition\Config\CustomValueIsFalsy::class,
67
            ],
68
            'filechanged' => [
69
                'any' => Hook\Condition\FileChanged\Any::class,
70
                'all' => Hook\Condition\FileChanged\All::class,
71
            ],
72
            'filestaged'  => [
73
                'all'    => Hook\Condition\FileStaged\All::class,
74
                'any'    => Hook\Condition\FileStaged\Any::class,
75
                'thatis' => Hook\Condition\FileStaged\ThatIs::class,
76
            ],
77
            'status'      => [
78
                'onbranch' => Hook\Condition\Branch\On::class,
79
            ]
80
        ]
81
    ];
82
83
    /**
84
     * Check if a configured action value is actually shorthand for an internal action
85
     *
86
     * @param  string $action
87
     * @return bool
88
     */
89 40
    public static function isShorthand(string $action): bool
90
    {
91 40
        return (bool) preg_match('#^captainhook\.[a-z]+#i', $action);
92
    }
93
94
    /**
95
     * Return the matching action class for given action shorthand
96
     *
97
     * @param  string $shorthand
98
     * @return string
99
     */
100 5
    public static function getActionClass(string $shorthand): string
101
    {
102 5
        return Shorthand::getClass('action', $shorthand);
103
    }
104
105
    /**
106
     * Return the matching condition class for given condition shorthand
107
     *
108
     * @param  string $shorthand
109
     * @return string
110
     */
111 2
    public static function getConditionClass(string $shorthand): string
112
    {
113 2
        return Shorthand::getClass('condition', $shorthand);
114
    }
115
116
    /**
117
     * Returns the matching class for shorthand
118
     *
119
     * @param  string $type
120
     * @param  string $shorthand
121
     * @return string
122
     */
123 7
    private static function getClass(string $type, string $shorthand): string
124
    {
125 7
        $path = explode('.', strtolower($shorthand));
126 7
        if (count($path) !== 3) {
127 1
            throw new RuntimeException('Invalid ' . $type . ' shorthand: ' . $shorthand);
128
        }
129 6
        [$trigger, $group, $name] = $path;
130 6
        if (!isset(self::$map[$type][$group])) {
131 1
            throw new RuntimeException('Invalid ' . $type . ' group: ' . $group);
132
        }
133 5
        if (!isset(self::$map[$type][$group][$name])) {
134 2
            throw new RuntimeException('Invalid ' . $type . ' => ' . $name);
135
        }
136 3
        return self::$map[$type][$group][$name];
137
    }
138
}
139