Issues (224)

src/StubGenerator.php (1 issue)

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the box project.
7
 *
8
 * (c) Kevin Herrera <[email protected]>
9
 *     Théo Fidry <[email protected]>
10
 *
11
 * This source file is subject to the MIT license that is bundled
12
 * with this source code in the file LICENSE.
13
 */
14
15
namespace KevinGH\Box;
16
17
use function addcslashes;
18
use function implode;
19
use function str_replace;
20
21
/**
22
 * Generates a new PHP bootstrap loader stub for a PHAR.
23
 *
24
 * @private
25
 */
26
final class StubGenerator
27
{
28
    use NotInstantiable;
29
30
    private const CHECK_FILE_NAME = 'bin/check-requirements.php';
31
32
    private const STUB_TEMPLATE = <<<'STUB'
33
        __BOX_SHEBANG__
34
        <?php
35
        __BOX_BANNER__
36
37
        __BOX_PHAR_CONFIG__
38
39
        __HALT_COMPILER(); ?>
40
41
        STUB;
42
43
    /**
44
     * @param null|string           $alias     The alias to be used in "phar://" URLs
45
     * @param null|string           $banner    The top header comment banner text
46
     * @param null|string           $index     The location within the PHAR of index script
47
     * @param bool                  $intercept Use the Phar::interceptFileFuncs() method?
48
     * @param null|non-empty-string $shebang   The shebang line
0 ignored issues
show
Documentation Bug introduced by
The doc comment null|non-empty-string at position 2 could not be parsed: Unknown type name 'non-empty-string' at position 2 in null|non-empty-string.
Loading history...
49
     */
50
    public static function generateStub(
51
        ?string $alias = null,
52
        ?string $banner = null,
53
        ?string $index = null,
54
        bool $intercept = false,
55
        ?string $shebang = null,
56
        bool $checkRequirements = true,
57
    ): string {
58
        $stub = self::STUB_TEMPLATE;
59
60
        $stub = str_replace(
61
            "__BOX_SHEBANG__\n",
62
            null === $shebang ? '' : $shebang."\n",
63
            $stub,
64
        );
65
66
        $stub = str_replace(
67
            "__BOX_BANNER__\n",
68
            self::generateBannerStmt($banner),
69
            $stub,
70
        );
71
72
        return str_replace(
73
            "__BOX_PHAR_CONFIG__\n",
74
            self::generatePharConfigStmt(
75
                $alias,
76
                $index,
77
                $intercept,
78
                $checkRequirements,
79
            ),
80
            $stub,
81
        );
82
    }
83
84
    private static function generateBannerStmt(?string $banner): string
85
    {
86
        if (null === $banner) {
87
            return '';
88
        }
89
90
        $generatedBanner = "/*\n * ";
91
92
        $generatedBanner .= str_replace(
93
            " \n",
94
            "\n",
95
            str_replace("\n", "\n * ", $banner),
96
        );
97
98
        $generatedBanner .= "\n */";
99
100
        return "\n".$generatedBanner."\n";
101
    }
102
103
    private static function getAliasStmt(?string $alias): ?string
104
    {
105
        return null !== $alias ? 'Phar::mapPhar('.self::arg($alias).');' : null;
106
    }
107
108
    /**
109
     * Escapes an argument so it can be written as a string in a call.
110
     *
111
     * @return string The escaped argument
112
     */
113
    private static function arg(string $arg, string $quote = "'"): string
114
    {
115
        return $quote.addcslashes($arg, $quote).$quote;
116
    }
117
118
    private static function generatePharConfigStmt(
119
        ?string $alias = null,
120
        ?string $index = null,
121
        bool $intercept = false,
122
        bool $checkRequirements = true,
123
    ): string {
124
        $previous = false;
125
        $stub = [];
126
        $aliasStmt = self::getAliasStmt($alias);
127
128
        if (null !== $aliasStmt) {
129
            $stub[] = $aliasStmt;
130
131
            $previous = true;
132
        }
133
134
        if ($intercept) {
135
            $stub[] = 'Phar::interceptFileFuncs();';
136
137
            $previous = true;
138
        }
139
140
        if (false !== $checkRequirements) {
141
            if ($previous) {
142
                $stub[] = '';
143
            }
144
145
            $checkRequirementsFile = self::CHECK_FILE_NAME;
146
147
            $stub[] = null === $alias
148
                ? "require 'phar://' . __FILE__ . '/.box/{$checkRequirementsFile}';"
149
                : "require 'phar://{$alias}/.box/{$checkRequirementsFile}';";
150
151
            $previous = true;
152
        }
153
154
        if (null !== $index) {
155
            if ($previous) {
156
                $stub[] = '';
157
            }
158
159
            $indexPath = null === $alias
160
                ? "'phar://' . __FILE__ . '/{$index}';"
161
                : "'phar://{$alias}/{$index}';";
162
163
            $stub[] = "\$_SERVER['SCRIPT_FILENAME'] = {$indexPath}";
164
            $stub[] = "require {$indexPath}";
165
        }
166
167
        if ([] === $stub) {
168
            return "// No PHAR config\n";
169
        }
170
171
        return implode("\n", $stub)."\n";
172
    }
173
}
174