mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-08-09 04:42:59 +02:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
9a175e7291 | |||
d53e92ce94 | |||
3344fdb1dc | |||
020a0260f1 | |||
3ce7e8f48b | |||
ae7e13de9b | |||
c82ea1fac1 | |||
d6258f54a9 |
@@ -2799,7 +2799,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 1020;
|
CURRENT_PROJECT_VERSION = 1025;
|
||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEBUG = YES;
|
DEBUG = YES;
|
||||||
DEVELOPMENT_TEAM = 8M54J5J787;
|
DEVELOPMENT_TEAM = 8M54J5J787;
|
||||||
@@ -2828,7 +2828,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 1020;
|
CURRENT_PROJECT_VERSION = 1025;
|
||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEBUG = NO;
|
DEBUG = NO;
|
||||||
DEVELOPMENT_TEAM = 8M54J5J787;
|
DEVELOPMENT_TEAM = 8M54J5J787;
|
||||||
@@ -3056,7 +3056,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 1020;
|
CURRENT_PROJECT_VERSION = 1025;
|
||||||
DEBUG = NO;
|
DEBUG = NO;
|
||||||
DEVELOPMENT_TEAM = 8M54J5J787;
|
DEVELOPMENT_TEAM = 8M54J5J787;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
@@ -3166,7 +3166,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 1020;
|
CURRENT_PROJECT_VERSION = 1025;
|
||||||
DEBUG = YES;
|
DEBUG = YES;
|
||||||
DEVELOPMENT_TEAM = 8M54J5J787;
|
DEVELOPMENT_TEAM = 8M54J5J787;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
@@ -20,9 +20,18 @@ struct Constants {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The PHP versions supported by this application.
|
* The PHP versions supported by this application.
|
||||||
* Depends on what version of Valet is installed.
|
* Any other PHP versions are considered invalid.
|
||||||
*/
|
*/
|
||||||
static let ValetSupportedPhpVersionMatrix = [
|
static let DetectedPhpVersions: Set = [
|
||||||
|
"5.6",
|
||||||
|
"7.0", "7.1", "7.2", "7.3", "7.4",
|
||||||
|
"8.0", "8.1", "8.2", "8.3"
|
||||||
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
The PHP versions supported by each version of Valet.
|
||||||
|
*/
|
||||||
|
static let ValetSupportedPhpVersionMatrix: [Int: Set] = [
|
||||||
2: // Valet v2 has the broadest legacy support
|
2: // Valet v2 has the broadest legacy support
|
||||||
[
|
[
|
||||||
"5.6",
|
"5.6",
|
||||||
@@ -32,12 +41,14 @@ struct Constants {
|
|||||||
3: // Valet v3 dropped support for v5.6
|
3: // Valet v3 dropped support for v5.6
|
||||||
[
|
[
|
||||||
"7.0", "7.1", "7.2", "7.3", "7.4",
|
"7.0", "7.1", "7.2", "7.3", "7.4",
|
||||||
"8.0", "8.1", "8.2", "8.3"
|
"8.0", "8.1", "8.2",
|
||||||
|
"8.3" // dev
|
||||||
],
|
],
|
||||||
4: // Valet v4 dropped support for <v7.4
|
4: // Valet v4 dropped support for v7.0-v7.3
|
||||||
[
|
[
|
||||||
"7.4",
|
"7.4",
|
||||||
"8.0", "8.1", "8.2", "8.3"
|
"8.0", "8.1", "8.2",
|
||||||
|
"8.3" // dev
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@@ -33,8 +33,8 @@ class Application {
|
|||||||
Attempt to open a specific directory in the app of choice.
|
Attempt to open a specific directory in the app of choice.
|
||||||
(This will open the app if it isn't open yet.)
|
(This will open the app if it isn't open yet.)
|
||||||
*/
|
*/
|
||||||
@objc public func openDirectory(file: String) async {
|
@objc public func openDirectory(file: String) {
|
||||||
return await Shell.quiet("/usr/bin/open -a \"\(name)\" \"\(file)\"")
|
Task { await Shell.quiet("/usr/bin/open -a \"\(name)\" \"\(file)\"") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Checks if the app is installed. */
|
/** Checks if the app is installed. */
|
||||||
|
@@ -38,9 +38,12 @@ class PhpEnv {
|
|||||||
/** Whether the switcher is busy performing any actions. */
|
/** Whether the switcher is busy performing any actions. */
|
||||||
var isBusy: Bool = false
|
var isBusy: Bool = false
|
||||||
|
|
||||||
/** All available versions of PHP. */
|
/** All versions of PHP that are currently supported. */
|
||||||
var availablePhpVersions: [String] = []
|
var availablePhpVersions: [String] = []
|
||||||
|
|
||||||
|
/** All versions of PHP that are currently installed but not compatible. */
|
||||||
|
var incompatiblePhpVersions: [String] = []
|
||||||
|
|
||||||
/** Cached information about the PHP installations. */
|
/** Cached information about the PHP installations. */
|
||||||
var cachedPhpInstallations: [String: PhpInstallation] = [:]
|
var cachedPhpInstallations: [String: PhpInstallation] = [:]
|
||||||
|
|
||||||
@@ -87,13 +90,14 @@ class PhpEnv {
|
|||||||
/**
|
/**
|
||||||
Detects which versions of PHP are installed.
|
Detects which versions of PHP are installed.
|
||||||
*/
|
*/
|
||||||
public func detectPhpVersions() async -> [String] {
|
public func detectPhpVersions() async -> Set<String> {
|
||||||
let files = await Shell.pipe("ls \(Paths.optPath) | grep php@").out
|
let files = await Shell.pipe("ls \(Paths.optPath) | grep php@").out
|
||||||
|
|
||||||
var versionsOnly = await extractPhpVersions(
|
let versions = await extractPhpVersions(from: files.components(separatedBy: "\n"))
|
||||||
from: files.components(separatedBy: "\n"),
|
|
||||||
supported: Constants.ValetSupportedPhpVersionMatrix[Valet.shared.version.major] ?? []
|
let supportedByValet = Constants.ValetSupportedPhpVersionMatrix[Valet.shared.version.major] ?? []
|
||||||
)
|
|
||||||
|
var supportedVersions = versions.intersection(supportedByValet)
|
||||||
|
|
||||||
// Make sure the aliased version is detected
|
// Make sure the aliased version is detected
|
||||||
// The user may have `php` installed, but not e.g. `php@8.0`
|
// The user may have `php` installed, but not e.g. `php@8.0`
|
||||||
@@ -101,13 +105,18 @@ class PhpEnv {
|
|||||||
let phpAlias = homebrewPackage.version
|
let phpAlias = homebrewPackage.version
|
||||||
|
|
||||||
// Avoid inserting a duplicate
|
// Avoid inserting a duplicate
|
||||||
if !versionsOnly.contains(phpAlias) && FileSystem.fileExists("\(Paths.optPath)/php/bin/php") {
|
if !supportedVersions.contains(phpAlias) && FileSystem.fileExists("\(Paths.optPath)/php/bin/php") {
|
||||||
versionsOnly.append(phpAlias)
|
supportedVersions.insert(phpAlias)
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.info("The PHP versions that were detected are: \(versionsOnly)")
|
availablePhpVersions = Array(supportedVersions)
|
||||||
|
.sorted(by: { $0.versionCompare($1) == .orderedDescending })
|
||||||
|
|
||||||
availablePhpVersions = versionsOnly
|
incompatiblePhpVersions = Array(versions.subtracting(supportedByValet))
|
||||||
|
.sorted(by: { $0.versionCompare($1) == .orderedDescending })
|
||||||
|
|
||||||
|
Log.info("The PHP versions that were detected are: \(availablePhpVersions)")
|
||||||
|
Log.info("The PHP versions that were unsupported are: \(incompatiblePhpVersions)")
|
||||||
|
|
||||||
var mappedVersions: [String: PhpInstallation] = [:]
|
var mappedVersions: [String: PhpInstallation] = [:]
|
||||||
|
|
||||||
@@ -117,7 +126,7 @@ class PhpEnv {
|
|||||||
|
|
||||||
cachedPhpInstallations = mappedVersions
|
cachedPhpInstallations = mappedVersions
|
||||||
|
|
||||||
return versionsOnly
|
return supportedVersions
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -129,11 +138,11 @@ class PhpEnv {
|
|||||||
*/
|
*/
|
||||||
public func extractPhpVersions(
|
public func extractPhpVersions(
|
||||||
from versions: [String],
|
from versions: [String],
|
||||||
supported: [String],
|
|
||||||
checkBinaries: Bool = true,
|
checkBinaries: Bool = true,
|
||||||
generateHelpers: Bool = true
|
generateHelpers: Bool = true
|
||||||
) async -> [String] {
|
) async -> Set<String> {
|
||||||
var output: [String] = []
|
let supported = Constants.DetectedPhpVersions
|
||||||
|
var output: Set<String> = []
|
||||||
versions.filter { (version) -> Bool in
|
versions.filter { (version) -> Bool in
|
||||||
// Omit everything that doesn't start with php@
|
// Omit everything that doesn't start with php@
|
||||||
// (e.g. something-php@8.0 won't be detected)
|
// (e.g. something-php@8.0 won't be detected)
|
||||||
@@ -145,7 +154,7 @@ class PhpEnv {
|
|||||||
if !output.contains(version)
|
if !output.contains(version)
|
||||||
&& supported.contains(version)
|
&& supported.contains(version)
|
||||||
&& (checkBinaries ? FileSystem.fileExists("\(Paths.optPath)/php@\(version)/bin/php") : true) {
|
&& (checkBinaries ? FileSystem.fileExists("\(Paths.optPath)/php@\(version)/bin/php") : true) {
|
||||||
output.append(version)
|
output.insert(version)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -261,7 +261,7 @@ class Startup {
|
|||||||
},
|
},
|
||||||
name: "valet version is supported",
|
name: "valet version is supported",
|
||||||
titleText: "startup.errors.valet_version_not_supported.title".localized,
|
titleText: "startup.errors.valet_version_not_supported.title".localized,
|
||||||
subtitleText: "startup.errors.valet_version_not_supported.subtitle".localized(Valet.shared.version.text),
|
subtitleText: "startup.errors.valet_version_not_supported.subtitle".localized,
|
||||||
descriptionText: "startup.errors.valet_version_not_supported.desc".localized
|
descriptionText: "startup.errors.valet_version_not_supported.desc".localized
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
@@ -30,17 +30,17 @@ extension DomainListVC {
|
|||||||
NSWorkspace.shared.open(url)
|
NSWorkspace.shared.open(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func openInFinder() async {
|
@objc func openInFinder() {
|
||||||
await Shell.quiet("open '\(selectedSite!.absolutePath)'")
|
Task { return await Shell.quiet("open '\(selectedSite!.absolutePath)'") }
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func openInTerminal() async {
|
@objc func openInTerminal() {
|
||||||
await Shell.quiet("open -b com.apple.terminal '\(selectedSite!.absolutePath)'")
|
Task { await Shell.quiet("open -b com.apple.terminal '\(selectedSite!.absolutePath)'") }
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func openWithEditor(sender: EditorMenuItem) async {
|
@objc func openWithEditor(sender: EditorMenuItem) {
|
||||||
guard let editor = sender.editor else { return }
|
guard let editor = sender.editor else { return }
|
||||||
await editor.openDirectory(file: selectedSite!.absolutePath)
|
editor.openDirectory(file: selectedSite!.absolutePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - UI interaction
|
// MARK: - UI interaction
|
||||||
|
@@ -109,6 +109,24 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate, PhpSwitcherDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func showIncompatiblePhpVersionsAlert() {
|
||||||
|
Task { @MainActor in
|
||||||
|
BetterAlert().withInformation(
|
||||||
|
title: "startup.unsupported_versions_explanation.title".localized,
|
||||||
|
subtitle: "startup.unsupported_versions_explanation.subtitle".localized(
|
||||||
|
PhpEnv.shared.incompatiblePhpVersions
|
||||||
|
.map({ version in
|
||||||
|
return "• PHP \(version)"
|
||||||
|
})
|
||||||
|
.joined(separator: "\n")
|
||||||
|
),
|
||||||
|
description: "startup.unsupported_versions_explanation.desc".localized
|
||||||
|
)
|
||||||
|
.withPrimary(text: "generic.ok".localized)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Reloads the menu in the background, using `asyncExecution`. */
|
/** Reloads the menu in the background, using `asyncExecution`. */
|
||||||
@objc func reloadPhpMonitorMenuInBackground() {
|
@objc func reloadPhpMonitorMenuInBackground() {
|
||||||
asyncExecution({
|
asyncExecution({
|
||||||
|
@@ -30,7 +30,7 @@ extension StatusMenu {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if PhpEnv.shared.availablePhpVersions.isEmpty { return }
|
if PhpEnv.shared.availablePhpVersions.isEmpty && PhpEnv.shared.incompatiblePhpVersions.isEmpty { return }
|
||||||
|
|
||||||
addSwitchToPhpMenuItems()
|
addSwitchToPhpMenuItems()
|
||||||
self.addItem(NSMenuItem.separator())
|
self.addItem(NSMenuItem.separator())
|
||||||
@@ -49,8 +49,7 @@ extension StatusMenu {
|
|||||||
|
|
||||||
func addSwitchToPhpMenuItems() {
|
func addSwitchToPhpMenuItems() {
|
||||||
var shortcutKey = 1
|
var shortcutKey = 1
|
||||||
for index in (0..<PhpEnv.shared.availablePhpVersions.count).reversed() {
|
for index in (0..<PhpEnv.shared.availablePhpVersions.count) {
|
||||||
|
|
||||||
// Get the short and long version
|
// Get the short and long version
|
||||||
let shortVersion = PhpEnv.shared.availablePhpVersions[index]
|
let shortVersion = PhpEnv.shared.availablePhpVersions[index]
|
||||||
let longVersion = PhpEnv.shared.cachedPhpInstallations[shortVersion]!.versionNumber
|
let longVersion = PhpEnv.shared.cachedPhpInstallations[shortVersion]!.versionNumber
|
||||||
@@ -72,6 +71,16 @@ extension StatusMenu {
|
|||||||
|
|
||||||
addItem(menuItem)
|
addItem(menuItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !PhpEnv.shared.incompatiblePhpVersions.isEmpty {
|
||||||
|
addItem(NSMenuItem.separator())
|
||||||
|
addItem(NSMenuItem(
|
||||||
|
title: "⚠️ " + "mi_php_unsupported".localized(
|
||||||
|
"\(PhpEnv.shared.incompatiblePhpVersions.count)"
|
||||||
|
),
|
||||||
|
action: #selector(MainMenu.showIncompatiblePhpVersionsAlert)
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addCoreMenuItems() {
|
func addCoreMenuItems() {
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
"mi_unsure" = "We are not sure what version of PHP you are running.";
|
"mi_unsure" = "We are not sure what version of PHP you are running.";
|
||||||
"mi_php_version" = "Global PHP version: PHP";
|
"mi_php_version" = "Global PHP version: PHP";
|
||||||
"mi_php_switch" = "Switch to PHP";
|
"mi_php_switch" = "Switch to PHP";
|
||||||
|
"mi_php_unsupported" = "Some installed PHP versions are not displayed.";
|
||||||
"mi_php_broken_1" = "Oof! It appears your PHP installation is broken...";
|
"mi_php_broken_1" = "Oof! It appears your PHP installation is broken...";
|
||||||
"mi_php_broken_2" = "Try running `php -v` in your terminal.";
|
"mi_php_broken_2" = "Try running `php -v` in your terminal.";
|
||||||
"mi_php_broken_3" = "You could also try switching to another version.";
|
"mi_php_broken_3" = "You could also try switching to another version.";
|
||||||
@@ -525,7 +526,7 @@ If you are seeing this message but are confused why this folder has gone missing
|
|||||||
|
|
||||||
// Valet version too new or old
|
// Valet version too new or old
|
||||||
"startup.errors.valet_version_not_supported.title" = "This version of Valet is not supported";
|
"startup.errors.valet_version_not_supported.title" = "This version of Valet is not supported";
|
||||||
"startup.errors.valet_version_not_supported.subtitle" = "You are running a version of Valet that is currently not supported (%@). PHP Monitor currently works with Valet v2, v3 and v4. In order to avoid causing issues on your system, PHP Monitor cannot start.";
|
"startup.errors.valet_version_not_supported.subtitle" = "You are running a version of Valet that is currently not supported. PHP Monitor currently works with Valet v2, v3 and v4. In order to avoid causing issues on your system, PHP Monitor cannot start.";
|
||||||
"startup.errors.valet_version_not_supported.desc" = "You must install a version of Valet that is compatible with PHP Monitor, or you may need to upgrade to a newer version of PHP Monitor which may include compatibility for this version of Valet (consult the latest release notes for more info).";
|
"startup.errors.valet_version_not_supported.desc" = "You must install a version of Valet that is compatible with PHP Monitor, or you may need to upgrade to a newer version of PHP Monitor which may include compatibility for this version of Valet (consult the latest release notes for more info).";
|
||||||
|
|
||||||
/// Brew & sudoers
|
/// Brew & sudoers
|
||||||
@@ -560,8 +561,16 @@ If you are seeing this message but are confused why this folder has gone missing
|
|||||||
"startup.version_mismatch.button_switch_back" = "Switch back to PHP %@";
|
"startup.version_mismatch.button_switch_back" = "Switch back to PHP %@";
|
||||||
"startup.version_mismatch.button_stay" = "Keep using PHP %@";
|
"startup.version_mismatch.button_stay" = "Keep using PHP %@";
|
||||||
|
|
||||||
// SPONSOR ENCOURAGEMENT
|
// Warning about unsupported PHP versions
|
||||||
|
"startup.unsupported_versions_explanation.title" = "One or more PHP installed versions are not supported.";
|
||||||
|
"startup.unsupported_versions_explanation.subtitle" = "The following versions of PHP are installed on your system but are not supported by this version of Valet.
|
||||||
|
|
||||||
|
%@
|
||||||
|
|
||||||
|
Valet might break if you link these PHP versions so PHP Monitor won't let you switch to them.";
|
||||||
|
"startup.unsupported_versions_explanation.desc" = "If you need support for older versions of PHP, you may need to downgrade to an older versions of Valet. Otherwise, it might be a good idea to uninstall any outdated versions that are not in use. This message will only be removed after restarting PHP Monitor.";
|
||||||
|
|
||||||
|
// Sponsor encouragement
|
||||||
"startup.sponsor_encouragement.title" = "If PHP Monitor has been useful to you or your company, please consider leaving a tip.";
|
"startup.sponsor_encouragement.title" = "If PHP Monitor has been useful to you or your company, please consider leaving a tip.";
|
||||||
"startup.sponsor_encouragement.subtitle" = "To be 100% transparent: I plan to keep PHP Monitor open source and free. Your support makes this decision very easy.\n\n(You will only see this prompt once.)";
|
"startup.sponsor_encouragement.subtitle" = "To be 100% transparent: I plan to keep PHP Monitor open source and free. Your support makes this decision very easy.\n\n(You will only see this prompt once.)";
|
||||||
"startup.sponsor_encouragement.desc" = "If you have already donated, then YOU are the reason why the app was able to get all these updates. In that case, this is a THANK YOU message to you. I appreciate the support.";
|
"startup.sponsor_encouragement.desc" = "If you have already donated, then YOU are the reason why the app was able to get all these updates. In that case, this is a THANK YOU message to you. I appreciate the support.";
|
||||||
|
@@ -24,11 +24,10 @@ class PhpVersionDetectionTest: XCTestCase {
|
|||||||
"php@5.6", // should be omitted, not supported
|
"php@5.6", // should be omitted, not supported
|
||||||
"php@5.4" // should be omitted, not supported
|
"php@5.4" // should be omitted, not supported
|
||||||
],
|
],
|
||||||
supported: ["7.0", "8.0", "8.1", "8.2"],
|
|
||||||
checkBinaries: false,
|
checkBinaries: false,
|
||||||
generateHelpers: false
|
generateHelpers: false
|
||||||
)
|
)
|
||||||
|
|
||||||
XCTAssertEqual(outcome, ["8.0", "7.0"])
|
XCTAssertEqual(outcome, ["8.0", "7.0", "5.6"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user