diff --git a/package.json b/package.json index 3948a51d..2d6f9f02 100644 --- a/package.json +++ b/package.json @@ -232,6 +232,7 @@ "sail", "lando", "ddev", + "docker", "local" ], "enumItemLabels": [ @@ -241,6 +242,7 @@ "Sail", "Lando", "DDEV", + "Docker", "Local" ], "markdownEnumDescriptions": [ @@ -250,6 +252,7 @@ "Sail", "Lando", "DDEV", + "Docker", "Use PHP installed on the local machine." ], "default": "auto", @@ -259,6 +262,16 @@ "type": "string", "description": "Template for running PHP code. Use {code} as an optional placeholder for the php file to run. e.g. `php \"{code}\"`.\n\nIf no {code} is present, code filepath will be appended to the command." }, + "Laravel.dockerService": { + "type": "string", + "default": "php", + "description": "Name of the Docker service container holding PHP executable and Laravel app source code." + }, + "Laravel.dockerBase": { + "type": "string", + "default": "/app", + "description": "Base path of the Laravel app source code inside Docker container." + }, "Laravel.basePath": { "type": "string", "default": "", @@ -674,4 +687,4 @@ "vscode-languageserver-textdocument": "^1.0.11", "vscode-languageserver-types": "^3.17.5" } -} +} \ No newline at end of file diff --git a/src/commands/pint.ts b/src/commands/pint.ts index d36f40a0..142afa08 100644 --- a/src/commands/pint.ts +++ b/src/commands/pint.ts @@ -1,4 +1,4 @@ -import { fixFilePath } from "@src/support/php"; +import { fixFilePath, getDefaultPhpCommand, getPhpEnv } from "@src/support/php"; import { statusBarError, statusBarSuccess, @@ -12,8 +12,10 @@ import { showErrorPopup } from "../support/popup"; import { getWorkspaceFolders, projectPath, + pathForPhpEnv, projectPathExists, } from "../support/project"; +import os from "os"; export const pintCommands = { all: commandName("laravel.pint.run"), @@ -27,7 +29,8 @@ const runPintCommand = ( ): Promise => { return new Promise((resolve, reject) => { // Check if pint exists in vendor/bin - const pintPath = projectPath("vendor/bin/pint"); + const pintBin = "vendor/bin/pint"; + const pintPath = projectPath(pintBin); if (!projectPathExists("vendor/bin/pint")) { const errorMessage = @@ -37,7 +40,14 @@ const runPintCommand = ( return; } - const command = `"${pintPath}" ${args}`.trim(); + let command = `"${pintPath}" ${args}`.trim(); + + if (getPhpEnv() !== "local") { + const pintInEnv = pathForPhpEnv("vendor/bin/pint"); + command = `${getDefaultPhpCommand()} "${pintInEnv}" ${args}`.trim(); + } else if (os.platform() === "win32") { + command = `${getDefaultPhpCommand()} "${pintPath}" ${args}`.trim(); + } cp.exec( command, diff --git a/src/support/config.ts b/src/support/config.ts index 1b2dc3e3..3b796812 100644 --- a/src/support/config.ts +++ b/src/support/config.ts @@ -6,6 +6,8 @@ type ConfigKey = | "basePath" | "phpEnvironment" | "phpCommand" + | "dockerService" + | "dockerBase" | "tests.docker.enabled" | "tests.ssh.enabled" | "tests.suiteSuffix" diff --git a/src/support/php.ts b/src/support/php.ts index 72002dca..1f3ee13c 100644 --- a/src/support/php.ts +++ b/src/support/php.ts @@ -1,6 +1,7 @@ import { getTemplate, TemplateName } from "@src/templates"; import * as cp from "child_process"; import * as fs from "fs"; +import { sep as pathsep } from "path"; import * as vscode from "vscode"; import { BoundedFileCache } from "./cache"; import { config } from "./config"; @@ -91,7 +92,7 @@ export const initVendorWatchers = () => { registerWatcher(autoloadWatcher); }; -const getPhpCommand = (): string => { +export const getPhpCommand = (): string => { const phpEnv = config("phpEnvironment", "auto"); for (const [key, option] of Object.entries(phpEnvironments)) { @@ -110,6 +111,15 @@ const getPhpCommand = (): string => { let check = checks.shift(); let result = ""; + if (key === "docker") { + const dockerService = config("dockerService", "php"); + check = check?.replace("{dockerService}", dockerService); + option.command = option.command.replace( + "{dockerService}", + dockerService, + ); + } + while (check) { info(`Checking ${key} PHP installation: ${check}`); @@ -161,7 +171,7 @@ export const clearPhpFileCache = () => { discoverFiles.clear(); }; -const getDefaultPhpCommand = (): string => { +export const getDefaultPhpCommand = (): string => { defaultPhpCommand ??= getPhpCommand(); return defaultPhpCommand; @@ -251,7 +261,7 @@ export const runInLaravel = ( export const fixFilePath = (path: string) => { if (phpEnvironmentsThatUseRelativePaths.includes(phpEnvKey!)) { - return relativePath(path); + return relativePath(path).replaceAll(pathsep, "/"); } return path; diff --git a/src/support/phpEnvironments.ts b/src/support/phpEnvironments.ts index f88fb7d1..57ac4cd3 100644 --- a/src/support/phpEnvironments.ts +++ b/src/support/phpEnvironments.ts @@ -14,6 +14,7 @@ export type PhpEnvironment = | "sail" | "lando" | "ddev" + | "docker" | "local"; export const phpEnvironments: Record = { @@ -52,10 +53,16 @@ export const phpEnvironments: Record = { command: "ddev php", relativePath: true, }, + docker: { + label: "Docker", + check: "docker compose exec {dockerService} which php", + command: 'docker compose exec {dockerService} "{binaryPath}"', + relativePath: true, + }, local: { label: "Local", description: "Use PHP installed on the local machine.", - check: "php -r 'echo PHP_BINARY;'", + check: 'php -r "echo PHP_BINARY;"', command: '"{binaryPath}"', }, }; diff --git a/src/support/project.ts b/src/support/project.ts index 8ff0e30a..30f76163 100644 --- a/src/support/project.ts +++ b/src/support/project.ts @@ -2,7 +2,7 @@ import * as fs from "fs"; import * as path from "path"; import * as vscode from "vscode"; import { config } from "./config"; -import { isPhpEnv } from "./php"; +import { getPhpEnv, isPhpEnv } from "./php"; let internalVendorExists: boolean | null = null; @@ -35,6 +35,14 @@ export const pathForPhpEnv = (srcPath: string): string => { return srcPath.replace(new RegExp("^/var/www/html/"), ""); } + if (srcPath.match(/^\//) && getPhpEnv() === "docker") { + const dockerBase = config("dockerBase", "/app").replace( + /\/$/, + "", + ); + return projectPath(srcPath.replace(new RegExp(`^${dockerBase}/?`), "")); + } + return srcPath; };