Completed
Pull Request — master (#86)
by Jan Philipp
01:53
created

BashScriptParser::shouldWarnAboutBestPractice()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Psh\ScriptRuntime\ScriptLoader;
4
5
use Shopware\Psh\Listing\Script;
6
use Shopware\Psh\ScriptRuntime\BashCommand;
7
8
class BashScriptParser implements ScriptParser
9
{
10
    const TYPE_DIRECT_EXECUTE = '<PSH_EXECUTE_THROUGH_CMD>';
11
12
    const SHOULD_BE_PRESENT = "set -euo pipefail";
13
14
    /**
15
     * {@inheritdoc}
16
     */
17
    public function parseContent(string $content, Script $script, ScriptLoader $loader): array
18
    {
19
        $this->testContentContainsMarker($content);
20
        $this->testScriptFileFitsRequirements($script);
21
22
        $shouldWarn = $this->shouldWarnAboutBestPractice($content);
23
        $warning = null;
24
25
        if ($shouldWarn) {
26
            $warning = 'Execution of this script is not secure, please consider adding <bold>set -euo pipefail</bold> in the beginning';
27
        }
28
29
        return [new BashCommand($script, $warning)];
30
    }
31
32
    /**
33
     * @param Script $script
34
     */
35
    private function testScriptFileFitsRequirements(Script $script)
36
    {
37
        if (!is_executable($script->getPath())) {
38
            throw new \RuntimeException('Bash scripts can only be executed if they are executable please execute <bold>chmod +x ' . $script->getPath() . '</bold>');
39
        }
40
41
        if (!is_writable($script->getDirectory())) {
42
            throw new \RuntimeException('Bash scripts can only be executed if they are in a writable directory please execute <bold>chmod +w ' . $script->getDirectory() . '</bold>');
43
        }
44
    }
45
46
    /**
47
     * @param string $content
48
     */
49
    private function testContentContainsMarker(string $content)
50
    {
51
        if (strpos($content, self::TYPE_DIRECT_EXECUTE) === false) {
52
            throw new ScriptNotSupportedByParser('Marker for execution missing');
53
        }
54
    }
55
56
    /**
57
     * @param string $content
58
     * @return bool
59
     */
60
    private function shouldWarnAboutBestPractice(string $content): bool
61
    {
62
        $firstLines = explode("\n", $content, 5);
63
        foreach ($firstLines as $line) {
64
            if ($line === self::SHOULD_BE_PRESENT) {
65
                return false;
66
            }
67
        }
68
69
        return true;
70
    }
71
}
72