Skip to content

Commit 199babb

Browse files
authored
fix(embed): run extension-less scripts of the embedded app with php-cli (#2765)
`php-cli` only resolved scripts ending in `.php` against the embedded app, so `./my-app php-cli bin/console`, documented in `docs/embed.md`, fails. Any relative script missing from the working directory is now resolved against the embedded app, when it exists there. Scripts in the working directory still take precedence; flags and absolute paths are left untouched.
1 parent d50aecb commit 199babb

2 files changed

Lines changed: 56 additions & 4 deletions

File tree

‎caddy/php-cli.go‎

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,8 @@ func cmdPHPCLI(fs caddycmd.Flags) (int, error) {
3232
// php's cli sapi expects the 0th arg to be the program itself, only filter out 'php-cli' arg
3333
args := append([]string{os.Args[0]}, os.Args[2:]...)
3434

35-
if frankenphp.EmbeddedAppPath != "" && len(args) > 1 && !strings.HasPrefix(args[1], "-") && strings.HasSuffix(args[1], ".php") {
36-
if _, err := os.Stat(args[1]); err != nil {
37-
args[1] = filepath.Join(frankenphp.EmbeddedAppPath, args[1])
38-
}
35+
if len(args) > 1 {
36+
args[1] = resolveEmbeddedScript(args[1])
3937
}
4038

4139
logger := slog.New(zapslog.NewHandler(caddy.Log().Core(), zapslog.WithName("frankenphp")))
@@ -45,3 +43,21 @@ func cmdPHPCLI(fs caddycmd.Flags) (int, error) {
4543

4644
return status, nil
4745
}
46+
47+
// resolveEmbeddedScript resolves relative scripts missing from the working directory,
48+
// including extension-less ones such as bin/console, against the embedded app.
49+
func resolveEmbeddedScript(script string) string {
50+
if frankenphp.EmbeddedAppPath == "" || strings.HasPrefix(script, "-") || !filepath.IsLocal(script) {
51+
return script
52+
}
53+
if _, err := os.Stat(script); err == nil {
54+
return script
55+
}
56+
57+
embedded := filepath.Join(frankenphp.EmbeddedAppPath, script)
58+
if _, err := os.Stat(embedded); err != nil {
59+
return script
60+
}
61+
62+
return embedded
63+
}

‎caddy/php-cli_test.go‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package caddy
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"testing"
7+
8+
"github.com/dunglas/frankenphp"
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
func TestResolveEmbeddedScript(t *testing.T) {
14+
app := t.TempDir()
15+
require.NoError(t, os.MkdirAll(filepath.Join(app, "bin"), 0o755))
16+
require.NoError(t, os.WriteFile(filepath.Join(app, "bin", "console"), []byte("#!/usr/bin/env php\n<?php\n"), 0o644))
17+
require.NoError(t, os.WriteFile(filepath.Join(app, "index.php"), []byte("<?php\n"), 0o644))
18+
19+
cwd := t.TempDir()
20+
require.NoError(t, os.WriteFile(filepath.Join(cwd, "local.php"), []byte("<?php\n"), 0o644))
21+
t.Chdir(cwd)
22+
23+
orig := frankenphp.EmbeddedAppPath
24+
t.Cleanup(func() { frankenphp.EmbeddedAppPath = orig })
25+
26+
frankenphp.EmbeddedAppPath = ""
27+
assert.Equal(t, "bin/console", resolveEmbeddedScript("bin/console"))
28+
29+
frankenphp.EmbeddedAppPath = app
30+
assert.Equal(t, filepath.Join(app, "bin", "console"), resolveEmbeddedScript("bin/console"))
31+
assert.Equal(t, filepath.Join(app, "index.php"), resolveEmbeddedScript("index.php"))
32+
assert.Equal(t, "local.php", resolveEmbeddedScript("local.php"), "files of the working directory take precedence")
33+
assert.Equal(t, "missing.php", resolveEmbeddedScript("missing.php"))
34+
assert.Equal(t, "-r", resolveEmbeddedScript("-r"))
35+
assert.Equal(t, "/bin/console", resolveEmbeddedScript("/bin/console"))
36+
}

0 commit comments

Comments
 (0)