1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2025-08-07 12:00:09 +02:00

Enable version switching in presets

* Moved Preset to dedicated file
* Added async friendly PHP version switch
* Added conditional PHP switch based on Preset
This commit is contained in:
2022-05-31 21:43:24 +02:00
parent bbebe78997
commit da8659adba
5 changed files with 169 additions and 83 deletions

View File

@ -48,6 +48,8 @@
C40B24F127A3106D0018C7D2 /* ServicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EC1E67279DE0540010F296 /* ServicesView.swift */; };
C40B24F227A310770018C7D2 /* Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EC1E72279DFCF40010F296 /* Events.swift */; };
C40B24F427A310830018C7D2 /* StatusMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = C47331A1247093B7009A0597 /* StatusMenu.swift */; };
C40C5C9C2846A40600E28255 /* Preset.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C5C9B2846A40600E28255 /* Preset.swift */; };
C40C5C9D2846A40600E28255 /* Preset.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C5C9B2846A40600E28255 /* Preset.swift */; };
C40C7F1E2772136000DDDCDC /* PhpEnv.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F1D2772136000DDDCDC /* PhpEnv.swift */; };
C40C7F1F2772136000DDDCDC /* PhpEnv.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F1D2772136000DDDCDC /* PhpEnv.swift */; };
C40C7F2827721FF600DDDCDC /* ActivePhpInstallation+Checks.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F2727721FF600DDDCDC /* ActivePhpInstallation+Checks.swift */; };
@ -307,6 +309,7 @@
C4068CA927B0890D00544CD5 /* MenuBarIcons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuBarIcons.swift; sourceTree = "<group>"; };
C4080FF527BD8C6400BF2C6B /* BetterAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BetterAlert.swift; sourceTree = "<group>"; };
C4080FF927BD956700BF2C6B /* BetterAlertVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BetterAlertVC.swift; sourceTree = "<group>"; };
C40C5C9B2846A40600E28255 /* Preset.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preset.swift; sourceTree = "<group>"; };
C40C7F1D2772136000DDDCDC /* PhpEnv.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpEnv.swift; sourceTree = "<group>"; };
C40C7F2727721FF600DDDCDC /* ActivePhpInstallation+Checks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ActivePhpInstallation+Checks.swift"; sourceTree = "<group>"; };
C40C7F2F27722E8D00DDDCDC /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
@ -554,6 +557,14 @@
path = Notice;
sourceTree = "<group>";
};
C40C5C9E2846A42D00E28255 /* Presets */ = {
isa = PBXGroup;
children = (
C40C5C9B2846A40600E28255 /* Preset.swift */,
);
path = Presets;
sourceTree = "<group>";
};
C40C7F1C27720E1400DDDCDC /* Test Files */ = {
isa = PBXGroup;
children = (
@ -643,6 +654,7 @@
5420395726135DB800FB00FA /* Preferences */,
C44C198F276E3A380072762D /* Progress */,
C4C8E81D276F5686003AC782 /* Watcher */,
C40C5C9E2846A42D00E28255 /* Presets */,
C4EE55B027708BB2001DF387 /* SwiftUI */,
);
path = Domain;
@ -1212,6 +1224,7 @@
C4CCBA6C275C567B008C7055 /* PMWindowController.swift in Sources */,
C4B585442770FE3900DA4FBE /* Command.swift in Sources */,
C44067F527E2582B0045BD4E /* DomainListNameCell.swift in Sources */,
C40C5C9C2846A40600E28255 /* Preset.swift in Sources */,
C41CD0292628D8EE0065BBED /* GlobalKeybindPreference.swift in Sources */,
C4EE55AB27708B9E001DF387 /* Preview.swift in Sources */,
C44067F727E258410045BD4E /* DomainListPhpCell.swift in Sources */,
@ -1353,6 +1366,7 @@
C41E871B2763D42300161EE0 /* DomainListVC+ContextMenu.swift in Sources */,
C40C7F3127722E8D00DDDCDC /* Logger.swift in Sources */,
C4068CAB27B0890D00544CD5 /* MenuBarIcons.swift in Sources */,
C40C5C9D2846A40600E28255 /* Preset.swift in Sources */,
C4F30B09278E1A0E00755FCE /* CustomPrefs.swift in Sources */,
C42800AB28452AA50099C999 /* StatusMenu+Items.swift in Sources */,
C40FE738282ABA4F00A302C2 /* AppVersion.swift in Sources */,

View File

@ -201,10 +201,48 @@ extension MainMenu {
PhpEnv.switcher.performSwitch(
to: version,
completion: {
PhpEnv.shared.currentInstall = ActivePhpInstallation()
App.shared.handlePhpConfigWatcher()
PhpEnv.shared.delegate?.switcherDidCompleteSwitch(to: version)
}
)
}
}
// MARK: - Async
/**
This async-friendly version of the switcher can be invoked elsewhere in the app:
```
Task {
await MainMenu.shared.switchToPhp("8.1")
// thing to do after the switch
}
```
Since this async function uses `withCheckedContinuation`
any code after will run only after the switcher is done.
*/
func switchToPhp(_ version: String) async {
DispatchQueue.main.async { [self] in
setBusyImage()
PhpEnv.shared.isBusy = true
PhpEnv.shared.delegate = self
PhpEnv.shared.delegate?.switcherDidStartSwitching(to: version)
}
return await withCheckedContinuation({ continuation in
updatePhpVersionInStatusBar()
rebuild()
PhpEnv.switcher.performSwitch(
to: version,
completion: {
PhpEnv.shared.currentInstall = ActivePhpInstallation()
App.shared.handlePhpConfigWatcher()
PhpEnv.shared.delegate?.switcherDidCompleteSwitch(to: version)
continuation.resume()
}
)
})
}
}

View File

@ -15,12 +15,6 @@ extension MainMenu {
func switcherDidStartSwitching(to version: String) {}
func switcherDidCompleteSwitch(to version: String) {
// Update the PHP version
PhpEnv.shared.currentInstall = ActivePhpInstallation()
// Ensure the config watcher gets reloaded
App.shared.handlePhpConfigWatcher()
// Mark as no longer busy
PhpEnv.shared.isBusy = false
@ -56,7 +50,7 @@ extension MainMenu {
}
}
@MainActor private func suggestFixMyValet(failed version: String) {
private func suggestFixMyValet(failed version: String) {
let outcome = BetterAlert()
.withInformation(
title: "alert.php_switch_failed.title".localized(version),

View File

@ -17,79 +17,3 @@ struct CustomPrefs: Decodable {
case presets = "presets"
}
}
struct Preset: Decodable {
let name: String
let version: String?
let extensions: [String: Bool]
let configuration: [String: String?]
public enum CodingKeys: String, CodingKey {
case version = "php",
name = "name",
extensions = "extensions",
configuration = "configuration"
}
public func getMenuItemText() -> String {
var info = extensions.count == 1
? "preset.extension".localized(extensions.count)
: "preset.extensions".localized(extensions.count)
info += ", "
info += configuration.count == 1
? "preset.preference".localized(configuration.count)
: "preset.preferences".localized(configuration.count)
if self.version == nil || !PhpEnv.shared.availablePhpVersions.contains(self.version!) {
return "<span style=\"font-family: '-apple-system'; font-size: 12px;\">"
+ "<b>\(name.stripped)</b><br/>"
+ "<i style=\"font-size: 11px;\">"
+ info + "</i>"
+ "</span>"
}
return "<span style=\"font-family: '-apple-system'; font-size: 12px;\">"
+ "<b>\(name.stripped)</b><br/>"
+ "<i style=\"font-size: 11px;\">"
+ "Switches to PHP \(version!)<br/>"
+ info + "</i>"
+ "</span>"
}
public func apply() {
// Apply the PHP version if is considered a valid version
// TODO
// Apply the configuration changes first
for conf in configuration {
applyConfigurationValue(key: conf.key, value: conf.value ?? "")
}
// Apply the extension changes in-place afterward
for ext in extensions {
for foundExt in PhpEnv.phpInstall.extensions
where foundExt.name == ext.key && foundExt.enabled != ext.value {
Log.info("Toggling extension \(foundExt.name) in \(foundExt.file)")
foundExt.toggle()
break
}
}
Actions.restartPhpFpm()
}
private func applyConfigurationValue(key: String, value: String) {
guard let file = PhpEnv.shared.getConfigFile(forKey: key) else {
return
}
do {
if file.has(key: key) {
Log.info("Setting config value \(key) in \(file.filePath)")
try file.replace(key: key, value: value)
}
} catch {
Log.err("Setting \(key) to \(value) failed.")
}
}
}

View File

@ -0,0 +1,116 @@
//
// Preset.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 31/05/2022.
// Copyright © 2022 Nico Verbruggen. All rights reserved.
//
import Foundation
struct Preset: Decodable {
let name: String
let version: String?
let extensions: [String: Bool]
let configuration: [String: String?]
public enum CodingKeys: String, CodingKey {
case version = "php",
name = "name",
extensions = "extensions",
configuration = "configuration"
}
public func getMenuItemText() -> String {
var info = extensions.count == 1
? "preset.extension".localized(extensions.count)
: "preset.extensions".localized(extensions.count)
info += ", "
info += configuration.count == 1
? "preset.preference".localized(configuration.count)
: "preset.preferences".localized(configuration.count)
if self.version == nil {
return "<span style=\"font-family: '-apple-system'; font-size: 12px;\">"
+ "<b>\(name.stripped)</b><br/>"
+ "<i style=\"font-size: 11px;\">"
+ info + "</i>"
+ "</span>"
}
return "<span style=\"font-family: '-apple-system'; font-size: 12px;\">"
+ "<b>\(name.stripped)</b><br/>"
+ "<i style=\"font-size: 11px;\">"
+ "Switches to PHP \(version!)<br/>"
+ info + "</i>"
+ "</span>"
}
public func apply() {
Task {
// Apply the PHP version if is considered a valid version
if self.version != nil {
await switchToPhpVersionIfValid()
}
// Apply the configuration changes first
for conf in configuration {
applyConfigurationValue(key: conf.key, value: conf.value ?? "")
}
// Apply the extension changes in-place afterward
for ext in extensions {
for foundExt in PhpEnv.phpInstall.extensions
where foundExt.name == ext.key && foundExt.enabled != ext.value {
Log.info("Toggling extension \(foundExt.name) in \(foundExt.file)")
foundExt.toggle()
break
}
}
Actions.restartPhpFpm()
}
}
private func switchToPhpVersionIfValid() async {
if PhpEnv.shared.currentInstall.version.short == self.version! {
Log.info("The version we are supposed to switch to is already active.")
return
}
if PhpEnv.shared.availablePhpVersions.first(where: { $0 == self.version }) != nil {
await MainMenu.shared.switchToPhp(self.version!)
return
} else {
DispatchQueue.main.async {
BetterAlert()
.withInformation(
title: "PHP version unavailable",
subtitle: "You have specified a PHP version (\(version!)) that is unavailable.",
description: "Please make sure this version of PHP is installed "
+ "and you can switch to it in the dropdown. "
+ "Currently supported versions include: "
+ "\(PhpEnv.shared.availablePhpVersions.joined(separator: ", "))."
)
.withPrimary(text: "OK")
.show()
}
return
}
}
private func applyConfigurationValue(key: String, value: String) {
guard let file = PhpEnv.shared.getConfigFile(forKey: key) else {
return
}
do {
if file.has(key: key) {
Log.info("Setting config value \(key) in \(file.filePath)")
try file.replace(key: key, value: value)
}
} catch {
Log.err("Setting \(key) to \(value) failed.")
}
}
}