Passed
Push — 6.5.0.0 ( 85bd4e...fe6596 )
by Christian
24:46 queued 09:10
created

PhpBinaryFinder::find()   B

Complexity

Conditions 7
Paths 8

Size

Total Lines 30
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 14
c 1
b 0
f 0
nc 8
nop 0
dl 0
loc 30
rs 8.8333
1
<?php
2
declare(strict_types=1);
3
4
namespace App\Services;
5
6
use Shopware\Core\Framework\Log\Package;
7
use Symfony\Component\Process\ExecutableFinder;
8
use Symfony\Component\Process\Process;
9
10
/**
11
 * @internal
12
 *
13
 * @codeCoverageIgnore
14
 */
15
#[Package('core')]
16
class PhpBinaryFinder
17
{
18
    private const PHP_BINARY_NAMES = ['php8.2', 'php8.1', 'php'];
19
20
    private const PHP_KNOWN_LOCATIONS = [
21
        '/opt/plesk/php/{major}.{minor}/bin/php',
22
        '/bin/php{major}{minor}',
23
        '/opt/RZphp{major}{minor}/bin/php-cli',
24
        '/opt/alt/php{major}{minor}/usr/bin/php',
25
        '/opt/php-{major}.{minor}.{release}/bin/php',
26
        '/opt/php-{major}.{minor}/bin/php',
27
        '/opt/php{major}.{minor}/bin/php',
28
        '/opt/php{major}{minor}/bin/php',
29
        '/opt/php{major}/bin/php',
30
        '/usr/bin/php{major}.{minor}-cli',
31
        '/usr/bin/php{major}.{minor}',
32
        '/usr/bin/php{major}{minor}',
33
        '/usr/bin/php{major}{minor}/php{major}',
34
        '/usr/bin/php{major}',
35
        '/usr/bin/php',
36
        '/usr/iports/php{major}{minor}/bin/php',
37
        '/usr/lib/cgi-bin/php{major}.{minor}',
38
        '/usr/lib64/php{major}.{minor}/bin/php',
39
        '/usr/local/bin/edis-php-cli-{major}{minor}-stable-openssl',
40
        '/usr/local/bin/edis-php-cli-{major}{minor}',
41
        '/usr/local/bin/php_cli',
42
        '/usr/local/bin/php',
43
        '/usr/local/bin/php{major}-{major}{minor}LATEST-CLI',
44
        '/usr/local/bin/php{major}.{minor}.{release}-cli',
45
        '/usr/local/php-{major}.{minor}/bin/php',
46
        '/usr/local/php{major}{minor}/bin/php',
47
        '/usr/local/phpfarm/inst/php-{major}.{minor}/bin/php',
48
        '/usr/local/php{major}{minor}/bin/php',
49
        '/opt/phpbrew/php/php-{major}.{minor}/bin/php',
50
        '/opt/phpfarm/inst/php-{major}.{minor}/bin/php-cgi',
51
        '/vrmd/webserver/php{major}{minor}/bin/php',
52
        '/package/host/localhost/php-{major}.{minor}/bin/php',
53
        '/Applications/MAMP/bin/php/php{major}.{minor}.{release}/bin/php',
54
    ];
55
56
    public function find(): string
57
    {
58
        // Look for specific PHP binaries by hosters
59
        if ($hosterSpecificBinary = $this->findHostedSpecificBinary()) {
60
            return $hosterSpecificBinary;
61
        }
62
63
        // Look for PHP binaries in same place as our fpm/cgi binary
64
        if (\defined('PHP_BINARY')) {
65
            $phpPath = \dirname(\PHP_BINARY);
66
            $fileName = explode('-', basename(\PHP_BINARY), 2);
67
            $expectedPath = $phpPath . \DIRECTORY_SEPARATOR . $fileName[0];
68
69
            if (file_exists($expectedPath) && $this->isPHPRunning($expectedPath)) {
70
                return $expectedPath;
71
            }
72
        }
73
74
        // Look into PHP path
75
        $finder = new ExecutableFinder();
76
77
        foreach (self::PHP_BINARY_NAMES as $name) {
78
            $binary = $finder->find($name);
79
80
            if ($binary !== null) {
81
                return $binary;
82
            }
83
        }
84
85
        return '';
86
    }
87
88
    private function findHostedSpecificBinary(): ?string
89
    {
90
        foreach (self::PHP_KNOWN_LOCATIONS as $knownLocation) {
91
            $path = $this->getPhpVersionPath($knownLocation);
92
93
            if (file_exists($path) && $this->isPHPRunning($path)) {
94
                return $path;
95
            }
96
        }
97
98
        return null;
99
    }
100
101
    private function getPhpVersionPath(string $path): string
102
    {
103
        return str_replace(
104
            [
105
                '{major}',
106
                '{minor}',
107
                '{release}',
108
                '{extra}',
109
            ],
110
            [
111
                \PHP_MAJOR_VERSION,
112
                \PHP_MINOR_VERSION,
113
                \PHP_RELEASE_VERSION,
114
                \PHP_EXTRA_VERSION,
115
            ],
116
            $path
117
        );
118
    }
119
120
    private function isPHPRunning(string $path): bool
121
    {
122
        $process = new Process([$path, '-v']);
123
        $process->run();
124
125
        return $process->isSuccessful();
126
    }
127
}
128