diff --git a/README.md b/README.md
index b5bcef9..222e1a0 100644
--- a/README.md
+++ b/README.md
@@ -79,16 +79,28 @@ If you're still having issues, here's a few common questions & answers, as well
Which versions of PHP are supported?
+The following versions of PHP are officially supported:
+
+
+- PHP 7.4
+- PHP 8.0
+- PHP 8.1
+- PHP 8.2
+
+
+The following versions have some support via backport and/or dev version:
+
+
+- PHP 5.6 (Valet 2 only)
+- PHP 7.0 (Valet 2 and 3 only)
+- PHP 7.1 (Valet 2 and 3 only)
+- PHP 7.2 (Valet 2 and 3 only)
+- PHP 7.3 (Valet 2 and 3 only)
+
+
+Additionally, the following dev version is also available:
+
-- PHP 5.6 (backport + only if you are running Valet 2)
-- PHP 7.0 (backport)
-- PHP 7.1 (backport)
-- PHP 7.2 (backport)
-- PHP 7.3 (backport)
-- PHP 7.4 (backport)
-- PHP 8.0 (official support)
-- PHP 8.1 (official support)
-- PHP 8.2 (latest version)
- PHP 8.3-dev (experimental)
@@ -96,6 +108,8 @@ For more details, consult the [constants file](https://github.com/nicoverbruggen
Backports are available via [this tap](https://github.com/shivammathur/homebrew-php). For more information about those backports, please see the next FAQ entry.
+For maximum compatibility with older PHP versions, you may wish to keep using Valet 2 or 3.
+
diff --git a/SECURITY.md b/SECURITY.md
index e9a4382..4543d3e 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -6,7 +6,7 @@ Generally speaking, only the latest version of **PHP Monitor** is supported, exc
| Version | Apple Silicon | Supported | Supported macOS | Deployment Target | Detected PHP Versions | Recommended Valet Version |
| ------- | ------------- | ------------------ | ----- | ----- | ----- | ----
-| 6.x | ✅ Universal binary | ✅ Yes | 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 |
+| 6.x | ✅ Universal binary | ✅ Yes | 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.4-PHP 8.2 (w/ Valet 4.x) | 3.0 or higher recommended
2.16.2 minimum |
## Legacy versions
diff --git a/phpmon/Common/Core/Actions.swift b/phpmon/Common/Core/Actions.swift
index 4851993..072463c 100644
--- a/phpmon/Common/Core/Actions.swift
+++ b/phpmon/Common/Core/Actions.swift
@@ -71,7 +71,7 @@ class Actions {
"services stop \(name)",
sudo: ServicesManager.shared[name]?.formula.elevated ?? false
)
- await ServicesManager.shared.updateServices()
+ await ServicesManager.shared.reloadServicesStatus()
}
public static func startService(name: String) async {
@@ -79,7 +79,7 @@ class Actions {
"services start \(name)",
sudo: ServicesManager.shared[name]?.formula.elevated ?? false
)
- await ServicesManager.shared.updateServices()
+ await ServicesManager.shared.reloadServicesStatus()
}
// MARK: - Finding Config Files
diff --git a/phpmon/Domain/App/Services/FakeServicesManager.swift b/phpmon/Domain/App/Services/FakeServicesManager.swift
index 0601028..0c4b9dc 100644
--- a/phpmon/Domain/App/Services/FakeServicesManager.swift
+++ b/phpmon/Domain/App/Services/FakeServicesManager.swift
@@ -40,7 +40,7 @@ class FakeServicesManager: ServicesManager {
}
}
- override func updateServices() async {
+ override func reloadServicesStatus() async {
await delay(seconds: 0.3)
for formula in self.serviceWrappers {
@@ -48,7 +48,29 @@ class FakeServicesManager: ServicesManager {
formula.isBusy = false
}
- print("Sending the update!")
broadcastServicesUpdated()
}
+
+ override func toggleService(named: String) async {
+ guard let wrapper = self[named] else {
+ return Log.err("The wrapper for service \(named) does not exist.")
+ }
+
+ wrapper.isBusy = true
+ Task { @MainActor in
+ wrapper.objectWillChange.send()
+ }
+
+ guard let service = wrapper.service else {
+ return Log.err("The actual service for wrapper \(named) is nil.")
+ }
+
+ await delay(seconds: 2)
+ service.running = !service.running
+ wrapper.isBusy = false
+ Task { @MainActor in
+ wrapper.objectWillChange.send()
+ self.objectWillChange.send()
+ }
+ }
}
diff --git a/phpmon/Domain/App/Services/ServicesManager.swift b/phpmon/Domain/App/Services/ServicesManager.swift
index b8d124b..0cd58ca 100644
--- a/phpmon/Domain/App/Services/ServicesManager.swift
+++ b/phpmon/Domain/App/Services/ServicesManager.swift
@@ -17,7 +17,7 @@ class ServicesManager: ObservableObject {
public static func useFake() {
ServicesManager.shared = FakeServicesManager.init(
- formulae: ["php", "nginx", "dnsmasq"],
+ formulae: ["php", "nginx", "dnsmasq", "mysql"],
status: .loading
)
}
@@ -38,6 +38,7 @@ class ServicesManager: ObservableObject {
}
let statuses = self.serviceWrappers[0...2].map { $0.status }
+
if statuses.contains(.loading) {
return "Determining Valet status..."
}
@@ -70,16 +71,25 @@ class ServicesManager: ObservableObject {
return .green
}
- @available(*, deprecated, message: "Use a more specific method instead")
- static func loadHomebrewServices() {
- // print(self.shared)
- print("This method must be updated")
+ /**
+ This method is called when the system configuration has changed
+ and all the status of one or more services may need to be determined.
+ */
+ public func reloadServicesStatus() async {
+ fatalError("This method `\(#function)` has not been implemented")
}
- public func updateServices() async {
- fatalError("Must be implemented in child class")
+ /**
+ This method is called when a service needs to be toggled (on/off).
+ */
+ public func toggleService(named: String) async {
+ fatalError("This method `\(#function)` has not been implemented")
}
+ /**
+ This method will notify all publishers that subscribe to notifiable objects.
+ The notified objects include this very ServicesManager as well as any individual service instances.
+ */
public func broadcastServicesUpdated() {
Task { @MainActor in
self.serviceWrappers.forEach { wrapper in
diff --git a/phpmon/Domain/App/Services/ValetServicesManager.swift b/phpmon/Domain/App/Services/ValetServicesManager.swift
index 9ffff96..be5531c 100644
--- a/phpmon/Domain/App/Services/ValetServicesManager.swift
+++ b/phpmon/Domain/App/Services/ValetServicesManager.swift
@@ -13,10 +13,10 @@ class ValetServicesManager: ServicesManager {
super.init()
// Load the initial services state
- Task { await self.updateServices() }
+ Task { await self.reloadServicesStatus() }
}
- override func updateServices() async {
+ override func reloadServicesStatus() async {
// TODO
}
}
diff --git a/phpmon/Domain/Menu/MainMenu+Async.swift b/phpmon/Domain/Menu/MainMenu+Async.swift
index ca9b766..013913a 100644
--- a/phpmon/Domain/Menu/MainMenu+Async.swift
+++ b/phpmon/Domain/Menu/MainMenu+Async.swift
@@ -74,7 +74,7 @@ extension MainMenu {
}
if behaviours.contains(.broadcastServicesUpdate) {
- Task { await ServicesManager.shared.updateServices() }
+ Task { await ServicesManager.shared.reloadServicesStatus() }
}
if error != nil {
diff --git a/phpmon/Domain/Menu/MainMenu.swift b/phpmon/Domain/Menu/MainMenu.swift
index 727e54a..b411efc 100644
--- a/phpmon/Domain/Menu/MainMenu.swift
+++ b/phpmon/Domain/Menu/MainMenu.swift
@@ -94,7 +94,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate, PhpSwitcherDelegate
self.refreshActiveInstallation()
self.refreshIcon()
self.rebuild()
- await ServicesManager.shared.updateServices()
+ await ServicesManager.shared.reloadServicesStatus()
Log.perf("The menu has been reloaded!")
}
}
@@ -184,7 +184,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate, PhpSwitcherDelegate
// Make sure the shortcut key does not trigger this when the menu is open
App.shared.shortcutHotkey?.isPaused = true
Task { // Reload Homebrew services information asynchronously
- await ServicesManager.shared.updateServices()
+ await ServicesManager.shared.reloadServicesStatus()
}
}
diff --git a/phpmon/Domain/SwiftUI/Menu/ServicesView.swift b/phpmon/Domain/SwiftUI/Menu/ServicesView.swift
index 606c894..566dffc 100644
--- a/phpmon/Domain/SwiftUI/Menu/ServicesView.swift
+++ b/phpmon/Domain/SwiftUI/Menu/ServicesView.swift
@@ -119,27 +119,19 @@ struct ServiceView: View {
// .buttonStyle(BlueButton())
.frame(minWidth: 70, alignment: .center)
}
- if service.status == .active {
+ if service.status == .active || service.status == .inactive {
Button {
- // TODO
- print("you pressed the button")
+ Task { await ServicesManager.shared.toggleService(named: service.name) }
} label: {
- Image(systemName: "checkmark")
- .resizable()
- .frame(width: 12.0, height: 12.0)
- .foregroundColor(Color("IconColorGreen"))
- }
- .frame(width: 25, height: 25)
- }
- if service.status == .inactive {
- Button {
- // TODO
- } label: {
- Image(systemName: "xmark")
- .resizable()
- .frame(width: 12.0, height: 12.0)
- .foregroundColor(Color("IconColorRed"))
- }
+ Image(
+ systemName: service.status == .active ? "checkmark" : "xmark"
+ )
+ .resizable()
+ .frame(width: 12.0, height: 12.0)
+ .foregroundColor(
+ service.status == .active ? Color("IconColorGreen") : Color("IconColorRed")
+ )
+ }.frame(width: 25, height: 25)
}
}.frame(minWidth: 70)
}