diff --git a/PHP Monitor.xcodeproj/project.pbxproj b/PHP Monitor.xcodeproj/project.pbxproj
index 71110ec..19a5b1e 100644
--- a/PHP Monitor.xcodeproj/project.pbxproj
+++ b/PHP Monitor.xcodeproj/project.pbxproj
@@ -3667,7 +3667,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 1455;
+ CURRENT_PROJECT_VERSION = 1460;
DEAD_CODE_STRIPPING = YES;
DEBUG = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
@@ -3680,7 +3680,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.4;
- MARKETING_VERSION = 7.0.2;
+ MARKETING_VERSION = 7.0.3;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
PRODUCT_MODULE_NAME = PHP_Monitor;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -3698,7 +3698,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 1455;
+ CURRENT_PROJECT_VERSION = 1460;
DEAD_CODE_STRIPPING = YES;
DEBUG = NO;
DEVELOPMENT_TEAM = 8M54J5J787;
@@ -3711,7 +3711,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.4;
- MARKETING_VERSION = 7.0.2;
+ MARKETING_VERSION = 7.0.3;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
PRODUCT_MODULE_NAME = PHP_Monitor;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -3939,7 +3939,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 1455;
+ CURRENT_PROJECT_VERSION = 1460;
DEAD_CODE_STRIPPING = YES;
DEBUG = NO;
DEVELOPMENT_TEAM = 8M54J5J787;
@@ -3952,7 +3952,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.4;
- MARKETING_VERSION = 7.0.2;
+ MARKETING_VERSION = 7.0.3;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon.dev;
PRODUCT_MODULE_NAME = PHP_Monitor;
PRODUCT_NAME = "$(TARGET_NAME) DEV";
@@ -4056,7 +4056,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 1455;
+ CURRENT_PROJECT_VERSION = 1460;
DEAD_CODE_STRIPPING = YES;
DEBUG = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
@@ -4069,7 +4069,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.4;
- MARKETING_VERSION = 7.0.2;
+ MARKETING_VERSION = 7.0.3;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon.dev;
PRODUCT_MODULE_NAME = PHP_Monitor;
PRODUCT_NAME = "$(TARGET_NAME) DEV";
@@ -4173,7 +4173,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 1455;
+ CURRENT_PROJECT_VERSION = 1460;
DEAD_CODE_STRIPPING = YES;
DEBUG = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
@@ -4186,7 +4186,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.4;
- MARKETING_VERSION = 7.0.2;
+ MARKETING_VERSION = 7.0.3;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon.eap;
PRODUCT_MODULE_NAME = PHP_Monitor;
PRODUCT_NAME = "$(TARGET_NAME) EAP";
@@ -4355,7 +4355,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 1455;
+ CURRENT_PROJECT_VERSION = 1460;
DEAD_CODE_STRIPPING = YES;
DEBUG = NO;
DEVELOPMENT_TEAM = 8M54J5J787;
@@ -4368,7 +4368,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.4;
- MARKETING_VERSION = 7.0.2;
+ MARKETING_VERSION = 7.0.3;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon.eap;
PRODUCT_MODULE_NAME = PHP_Monitor;
PRODUCT_NAME = "$(TARGET_NAME) EAP";
diff --git a/SECURITY.md b/SECURITY.md
index 4603aff..a8c53c8 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -4,19 +4,20 @@
Generally speaking, only the latest version of **PHP Monitor** is supported, except during transition periods (for example, when particular system requirements go up):
-| Version | Apple Silicon | Supported | Supported macOS | Deployment Target | Detected PHP Versions | Recommended Valet Version |
+| Version | Apple Silicon | Supported | Supported macOS | Minimum Deployment | Detected PHP Versions | Recommended Valet Version |
| ------- | ------------- | ------------------ | ----- | ----- | ----- | ----
-| 6.2 | ✅ Universal binary | ✅ Yes | Monterey (12.4+)
Ventura (13.0+)
Sonoma (14.0) | macOS 12.4 | PHP 5.6—PHP 8.2 (w/ Valet 2.x)
PHP 7.0—PHP 8.4 (w/ Valet 3.x)
PHP 7.1-PHP 8.4 (w/ Valet 4.x)| 3.0 or higher recommended
2.16.2 minimum |
+| 7.0 | ✅ Universal binary | ✅ Yes | Monterey (12.4+)
Ventura (13.0+)
Sonoma (14.0) | macOS 12.4+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)
PHP 7.0—PHP 8.4 (w/ Valet 3.x)
PHP 7.1-PHP 8.4 (w/ Valet 4.x)| 3.0 or higher recommended
2.16.2 minimum |
## Legacy versions
These versions of PHP Monitor are no longer supported, but if you’re using an older computer with an older version of Homebrew, Valet or macOS, you might want to use one of these versions.
-| Version | Apple Silicon | Supported | Supported macOS | Deployment Target | Detected PHP Versions | Minimum Required Valet Version |
+| Version | Apple Silicon | Supported | Supported macOS | Minimum Deployment | Detected PHP Versions | Minimum Required Valet Version |
| ------- | ------------- | ------------------ | ----- | ----- | ----- | ----
-| 6.1 | ✅ Universal binary | ❌ | Monterey (12.4+)
Ventura (13.0+)
Sonoma (14.0) | macOS 12.4 | PHP 5.6—PHP 8.2 (w/ Valet 2.x)
PHP 7.0—PHP 8.4 (w/ Valet 3.x)
PHP 7.1-PHP 8.4 (w/ Valet 4.x)| 3.0 or higher recommended
2.16.2 minimum |
-| 6.0 | ✅ Universal binary | ❌ | Monterey (12.4+)
Ventura (13.0+) | macOS 12.4 | PHP 5.6—PHP 8.2 (w/ Valet 2.x)
PHP 7.0—PHP 8.2 (w/ Valet 3.x)
PHP 7.1-PHP 8.2 (w/ Valet 4.x) | 3.0 or higher recommended
2.16.2 minimum |
-| 5.8 | ✅ Universal binary | ❌ | Monterey (12.4+)
Ventura (13.0+) | macOS 12.4 | PHP 5.6—PHP 8.2 (w/ Valet 2.x)
PHP 7.0—PHP 8.2 (w/ Valet 3.x)
PHP 7.1-PHP 8.2 (w/ Valet 4.x) | 3.0 or higher recommended
2.16.2 minimum |
+| 6.2 | ✅ Universal binary | ❌ | Monterey (12.4+)
Ventura (13.0+)
Sonoma (14.0) | macOS 12.4+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)
PHP 7.0—PHP 8.4 (w/ Valet 3.x)
PHP 7.1-PHP 8.4 (w/ Valet 4.x)| 3.0 or higher recommended
2.16.2 minimum |
+| 6.1 | ✅ Universal binary | ❌ | Monterey (12.4+)
Ventura (13.0+)
Sonoma (14.0) | macOS 12.4+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)
PHP 7.0—PHP 8.4 (w/ Valet 3.x)
PHP 7.1-PHP 8.4 (w/ Valet 4.x)| 3.0 or higher recommended
2.16.2 minimum |
+| 6.0 | ✅ Universal binary | ❌ | Monterey (12.4+)
Ventura (13.0+) | macOS 12.4+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)
PHP 7.0—PHP 8.2 (w/ Valet 3.x)
PHP 7.1-PHP 8.2 (w/ Valet 4.x) | 3.0 or higher recommended
2.16.2 minimum |
+| 5.8 | ✅ Universal binary | ❌ | Monterey (12.4+)
Ventura (13.0+) | macOS 12.4+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)
PHP 7.0—PHP 8.2 (w/ Valet 3.x)
PHP 7.1-PHP 8.2 (w/ Valet 4.x) | 3.0 or higher recommended
2.16.2 minimum |
| 5.7 | ✅ Universal binary | ❌ | Big Sur (11.0)
Monterey (12.0)
Ventura (13.0) | macOS 11+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)
PHP 7.0—PHP 8.2 (w/ Valet 3.x)
PHP 7.1-PHP 8.2 (w/ Valet 4.x) | 3.0 or higher recommended
2.16.2 minimum |
| 5.6 | ✅ Universal binary | ❌ | Big Sur (11.0)
Monterey (12.0)
Ventura (13.0) | macOS 11+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)
PHP 7.0—PHP 8.2 (w/ Valet 3.x) | 3.0 recommended
2.16.2 minimum |
| 4.1 | ✅ Universal binary | ❌ | Big Sur (11.0)
Monterey (12.0) | macOS 11+ | PHP 5.6—PHP 8.2 | 2.16.2 |
diff --git a/phpmon/Domain/App/AppDelegate.swift b/phpmon/Domain/App/AppDelegate.swift
index 5755588..e222c66 100644
--- a/phpmon/Domain/App/AppDelegate.swift
+++ b/phpmon/Domain/App/AppDelegate.swift
@@ -23,12 +23,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
*/
let state: App
- /**
- The MainMenu singleton is responsible for rendering the
- menu bar item and its menu, as well as its actions.
- */
- let menu: MainMenu
-
/**
The paths singleton that determines where Homebrew is installed,
and where to look for binaries.
@@ -96,7 +90,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
}
self.state = App.shared
- self.menu = MainMenu.shared
self.paths = Paths.shared
self.valet = Valet.shared
self.brew = Brew.shared
@@ -132,7 +125,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
setupNotifications()
Task { // Make sure the menu performs its initial checks
- await menu.startup()
+ await MainMenu.shared.startup()
}
}
diff --git a/phpmon/Domain/Menu/StatusMenu+Items.swift b/phpmon/Domain/Menu/StatusMenu+Items.swift
index c10267a..85b29b6 100644
--- a/phpmon/Domain/Menu/StatusMenu+Items.swift
+++ b/phpmon/Domain/Menu/StatusMenu+Items.swift
@@ -242,7 +242,7 @@ extension StatusMenu {
addLoadedPresets()
}
- private func addEmptyPresetHelp() {
+ @MainActor private func addEmptyPresetHelp() {
addItem(NSMenuItem(title: "mi_presets_title".localized, submenu: [
NSMenuItem(title: "mi_no_presets".localized),
NSMenuItem.separator(),
@@ -251,7 +251,7 @@ extension StatusMenu {
], target: MainMenu.shared))
}
- private func addLoadedPresets() {
+ @MainActor private func addLoadedPresets() {
addItem(NSMenuItem(title: "mi_presets_title".localized, submenu: [
NSMenuItem.separator(),
HeaderView.asMenuItem(text: "mi_apply_presets_title".localized)
@@ -266,7 +266,7 @@ extension StatusMenu {
// MARK: - Xdebug
- func addXdebugMenuItem() {
+ @MainActor func addXdebugMenuItem() {
if !Xdebug.enabled {
addItem(NSMenuItem.separator())
return
@@ -286,7 +286,7 @@ extension StatusMenu {
// MARK: - PHP Doctor
- func addPhpDoctorMenuItem() {
+ @MainActor func addPhpDoctorMenuItem() {
if !Preferences.isEnabled(.showPhpDoctorSuggestions) ||
!WarningManager.shared.hasWarnings() {
return
@@ -302,7 +302,7 @@ extension StatusMenu {
// MARK: - First Aid & Services
- func addFirstAidAndServicesMenuItems() {
+ @MainActor func addFirstAidAndServicesMenuItems() {
let services = NSMenuItem(title: "mi_other".localized)
var items: [NSMenuItem] = [
@@ -359,7 +359,7 @@ extension StatusMenu {
// MARK: - Other helper methods to generate menu items
- func addExtensionItem(_ phpExtension: PhpExtension, _ shortcutKey: Int) {
+ @MainActor func addExtensionItem(_ phpExtension: PhpExtension, _ shortcutKey: Int) {
let keyEquivalent = shortcutKey < 9 ? "\(shortcutKey)" : ""
let menuItem = ExtensionMenuItem(
diff --git a/phpmon/Domain/SwiftUI/Domains/VersionPopoverView.swift b/phpmon/Domain/SwiftUI/Domains/VersionPopoverView.swift
index f110f1c..726a7c4 100644
--- a/phpmon/Domain/SwiftUI/Domains/VersionPopoverView.swift
+++ b/phpmon/Domain/SwiftUI/Domains/VersionPopoverView.swift
@@ -14,8 +14,16 @@ struct VersionPopoverView: View {
@State var validPhpVersions: [VersionNumber]
+ @State var prefersIsolationSuggestions: Bool
+
@State var parent: NSPopover!
+ let rows = [
+ GridItem(.flexible()),
+ GridItem(.flexible()),
+ GridItem(.flexible())
+ ]
+
var body: some View {
VStack(alignment: .leading, spacing: 10) {
Text(getTitleText())
@@ -32,14 +40,29 @@ struct VersionPopoverView: View {
message: "alert.php_suggestions".localized,
color: Color("AppColor")
)
- HStack {
- ForEach(validPhpVersions, id: \.self) { version in
- Button("site_link.switch_to_php".localized(version.short), action: {
- MainMenu.shared.switchToPhpVersion(version.short)
- parent?.close()
- })
- }
- }.padding(EdgeInsets(top: 10, leading: 0, bottom: 0, trailing: 0))
+ if prefersIsolationSuggestions {
+ // SITE ISOLATION (preferred)
+ LazyVGrid(columns: self.rows, alignment: .leading, spacing: 5, content: {
+ ForEach(validPhpVersions, id: \.self) { version in
+ Button("site_link.isolate_php".localized(version.short), action: {
+ App.shared.domainListWindowController?.contentVC
+ .isolateSite(site: site, version: version.short)
+ parent?.close()
+ }).padding(EdgeInsets(top: 3, leading: 0, bottom: 3, trailing: 0))
+ }
+ }).padding(EdgeInsets(top: 5, leading: 0, bottom: 0, trailing: 0))
+ } else {
+ // GLOBAL SWITCHER
+ LazyVGrid(columns: self.rows, alignment: .leading, spacing: 5, content: {
+ ForEach(validPhpVersions, id: \.self) { version in
+ Button("site_link.switch_to_php".localized(version.short), action: {
+ MainMenu.shared.switchToPhpVersion(version.short)
+ parent?.close()
+ }).padding(EdgeInsets(top: 3, leading: 0, bottom: 3, trailing: 0))
+ }
+ }).padding(EdgeInsets(top: 5, leading: 0, bottom: 0, trailing: 0))
+ }
+
}
} else {
if site.preferredPhpVersionSource == .unknown {
@@ -137,6 +160,7 @@ struct DisclaimerView: View {
constraint: ""
),
validPhpVersions: [],
+ prefersIsolationSuggestions: false,
parent: nil
)
}
@@ -152,6 +176,7 @@ struct DisclaimerView: View {
constraint: "^8.1"
),
validPhpVersions: [],
+ prefersIsolationSuggestions: false,
parent: nil
)
}
@@ -168,6 +193,7 @@ struct DisclaimerView: View {
isolated: "8.0"
),
validPhpVersions: [],
+ prefersIsolationSuggestions: false,
parent: nil
)
}
@@ -184,6 +210,7 @@ struct DisclaimerView: View {
isolated: "7.4"
),
validPhpVersions: [],
+ prefersIsolationSuggestions: false,
parent: nil
)
}
@@ -200,8 +227,12 @@ struct DisclaimerView: View {
),
validPhpVersions: [
VersionNumber(major: 8, minor: 0, patch: 0),
- VersionNumber(major: 8, minor: 1, patch: 0)
+ VersionNumber(major: 8, minor: 1, patch: 0),
+ VersionNumber(major: 8, minor: 2, patch: 0),
+ VersionNumber(major: 8, minor: 3, patch: 0),
+ VersionNumber(major: 8, minor: 4, patch: 0)
],
+ prefersIsolationSuggestions: true,
parent: nil
)
}
diff --git a/phpmon/Modules/Domain List/UI/Cells/DomainListPhpCell.swift b/phpmon/Modules/Domain List/UI/Cells/DomainListPhpCell.swift
index 1e486b4..f22b84b 100644
--- a/phpmon/Modules/Domain List/UI/Cells/DomainListPhpCell.swift
+++ b/phpmon/Modules/Domain List/UI/Cells/DomainListPhpCell.swift
@@ -70,7 +70,12 @@ class DomainListPhpCell: NSTableCellView, DomainListCellProtocol {
let button = self.buttonPhpVersion!
let popover = NSPopover()
- let view = VersionPopoverView(site: site, validPhpVersions: validPhpSuggestions, parent: popover)
+ let view = VersionPopoverView(
+ site: site,
+ validPhpVersions: validPhpSuggestions,
+ prefersIsolationSuggestions: Valet.enabled(feature: .isolatedSites),
+ parent: popover
+ )
popover.contentViewController = NSHostingController(rootView: view)
popover.behavior = .transient
diff --git a/phpmon/Modules/Domain List/UI/DomainListVC+Actions.swift b/phpmon/Modules/Domain List/UI/DomainListVC+Actions.swift
index ba2dfb2..29807c1 100644
--- a/phpmon/Modules/Domain List/UI/DomainListVC+Actions.swift
+++ b/phpmon/Modules/Domain List/UI/DomainListVC+Actions.swift
@@ -126,17 +126,17 @@ extension DomainListVC {
}
}
- @objc func isolateSite(sender: PhpMenuItem) {
- guard let site = selectedSite else {
- return
- }
-
+ public func isolateSite(site: ValetSite, version: String) {
waitAndExecute {
do {
// Instruct Valet to isolate a given PHP version
- try await site.isolate(version: sender.version)
- // Reload the UI
- self.reloadSelectedRow()
+ try await site.isolate(version: version)
+ // Reload the UI if it's the same site
+ if self.selectedSite?.absolutePath == site.absolutePath {
+ self.reloadSelectedRow()
+ } else {
+ await self.reloadDomains()
+ }
} catch {
// Notify the user about a failed command
let error = error as! ValetInteractionError
@@ -145,7 +145,15 @@ extension DomainListVC {
}
}
- @objc func removeIsolatedSite() {
+ @objc func isolateSiteViaMenuItem(sender: PhpMenuItem) {
+ guard let site = selectedSite else {
+ return
+ }
+
+ self.isolateSite(site: site, version: sender.version)
+ }
+
+ @objc func removeIsolatedSiteViaMenuItem() {
guard let site = selectedSite else {
return
}
diff --git a/phpmon/Modules/Domain List/UI/DomainListVC+ContextMenu.swift b/phpmon/Modules/Domain List/UI/DomainListVC+ContextMenu.swift
index ba00710..cdd7677 100644
--- a/phpmon/Modules/Domain List/UI/DomainListVC+ContextMenu.swift
+++ b/phpmon/Modules/Domain List/UI/DomainListVC+ContextMenu.swift
@@ -121,7 +121,7 @@ extension DomainListVC {
for version in PhpEnvironments.shared.availablePhpVersions.reversed() {
let item = PhpMenuItem(
title: "domain_list.always_use_php".localized(version),
- action: #selector(self.isolateSite),
+ action: #selector(self.isolateSiteViaMenuItem),
keyEquivalent: ""
)
if site.servingPhpVersion == version && site.isolatedPhpVersion != nil {
@@ -137,7 +137,7 @@ extension DomainListVC {
items.append(NSMenuItem.separator())
items.append(NSMenuItem(
title: "domain_list.remove_isolation".localized,
- action: #selector(self.removeIsolatedSite)
+ action: #selector(self.removeIsolatedSiteViaMenuItem)
))
}
diff --git a/phpmon/en.lproj/Localizable.strings b/phpmon/en.lproj/Localizable.strings
index ec9aab8..7e25cb8 100644
--- a/phpmon/en.lproj/Localizable.strings
+++ b/phpmon/en.lproj/Localizable.strings
@@ -262,6 +262,7 @@ You may be asked for your password during the uninstallation process if file per
"domain_list.confirm_unlink_desc" = "No files will be removed. You can always link the folder again by clicking on the + button and selecting the original folder.";
"site_link.close" = "Close";
"site_link.switch_to_php" = "Switch to PHP %@";
+"site_link.isolate_php" = "Isolate PHP %@";
"domain_list.confirm_unproxy" = "Are you sure you want to remove the proxy '%@'?";
"domain_list.confirm_unproxy_desc" = "You can always recreate proxy the again by clicking on the + button.";