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

♻️ Refactor PhpSwitcher into PhpEnv

This commit is contained in:
2021-12-24 16:09:51 +01:00
parent c647aee8ea
commit dd251936b9
17 changed files with 239 additions and 175 deletions

View File

@ -24,9 +24,9 @@
54FCFD31276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54FCFD2F276C8DA4004CE748 /* HotkeyPreferenceView.swift */; };
C405A4D024B9B9140062FAFA /* InternetAccessPolicy.strings in Resources */ = {isa = PBXBuildFile; fileRef = C405A4CE24B9B9130062FAFA /* InternetAccessPolicy.strings */; };
C405A4D124B9B9140062FAFA /* InternetAccessPolicy.plist in Resources */ = {isa = PBXBuildFile; fileRef = C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */; };
C40C7F1E2772136000DDDCDC /* PhpSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F1D2772136000DDDCDC /* PhpSwitcher.swift */; };
C40C7F1F2772136000DDDCDC /* PhpSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F1D2772136000DDDCDC /* PhpSwitcher.swift */; };
C40C7F202772136000DDDCDC /* PhpSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F1D2772136000DDDCDC /* PhpSwitcher.swift */; };
C40C7F1E2772136000DDDCDC /* PhpEnv.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F1D2772136000DDDCDC /* PhpEnv.swift */; };
C40C7F1F2772136000DDDCDC /* PhpEnv.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F1D2772136000DDDCDC /* PhpEnv.swift */; };
C40C7F202772136000DDDCDC /* PhpEnv.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F1D2772136000DDDCDC /* PhpEnv.swift */; };
C40C7F2227721F8200DDDCDC /* PhpInstallation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F2E4392752F7D00020E974 /* PhpInstallation.swift */; };
C40C7F2327721F8200DDDCDC /* ActivePhpInstallation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4A22B019FF00E7CF16 /* ActivePhpInstallation.swift */; };
C40C7F2427721F8200DDDCDC /* PhpExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4ACA38E25C754C100060C66 /* PhpExtension.swift */; };
@ -45,6 +45,9 @@
C415D3E62770F540005EF286 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415D3E52770F540005EF286 /* main.swift */; };
C415D3E82770F692005EF286 /* AppDelegate+InterApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415D3E72770F692005EF286 /* AppDelegate+InterApp.swift */; };
C415D3E92770F692005EF286 /* AppDelegate+InterApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415D3E72770F692005EF286 /* AppDelegate+InterApp.swift */; };
C417DC74277614690015E6EE /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = C417DC73277614690015E6EE /* Helpers.swift */; };
C417DC75277614690015E6EE /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = C417DC73277614690015E6EE /* Helpers.swift */; };
C417DC76277614690015E6EE /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = C417DC73277614690015E6EE /* Helpers.swift */; };
C4188989275FE8CB001EF227 /* Filesystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4188988275FE8CB001EF227 /* Filesystem.swift */; };
C418898A275FE8CB001EF227 /* Filesystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4188988275FE8CB001EF227 /* Filesystem.swift */; };
C41C1B3722B0097F00E7CF16 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B3622B0097F00E7CF16 /* AppDelegate.swift */; };
@ -124,6 +127,12 @@
C4CCBA6C275C567B008C7055 /* PMWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CCBA6B275C567B008C7055 /* PMWindowController.swift */; };
C4CCBA6D275C567B008C7055 /* PMWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CCBA6B275C567B008C7055 /* PMWindowController.swift */; };
C4D8016622B1584700C6DA1B /* Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D8016522B1584700C6DA1B /* Startup.swift */; };
C4D9ADBF277610E1007277F4 /* PhpSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D9ADBE277610E1007277F4 /* PhpSwitcher.swift */; };
C4D9ADC0277610E1007277F4 /* PhpSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D9ADBE277610E1007277F4 /* PhpSwitcher.swift */; };
C4D9ADC1277610E1007277F4 /* PhpSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D9ADBE277610E1007277F4 /* PhpSwitcher.swift */; };
C4D9ADC8277611A0007277F4 /* InternalSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D9ADC7277611A0007277F4 /* InternalSwitcher.swift */; };
C4D9ADC9277611A0007277F4 /* InternalSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D9ADC7277611A0007277F4 /* InternalSwitcher.swift */; };
C4D9ADCA277611A0007277F4 /* InternalSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D9ADC7277611A0007277F4 /* InternalSwitcher.swift */; };
C4EE188422D3386B00E126E5 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EE188322D3386B00E126E5 /* Constants.swift */; };
C4EE55A927708B9E001DF387 /* PMHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EE55A627708B9E001DF387 /* PMHeaderView.swift */; };
C4EE55AA27708B9E001DF387 /* PMHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EE55A627708B9E001DF387 /* PMHeaderView.swift */; };
@ -192,7 +201,7 @@
54FCFD2F276C8DA4004CE748 /* HotkeyPreferenceView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HotkeyPreferenceView.swift; sourceTree = "<group>"; };
C405A4CE24B9B9130062FAFA /* InternetAccessPolicy.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = InternetAccessPolicy.strings; sourceTree = "<group>"; };
C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = InternetAccessPolicy.plist; sourceTree = "<group>"; };
C40C7F1D2772136000DDDCDC /* PhpSwitcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpSwitcher.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>"; };
C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomebrewPackage.swift; sourceTree = "<group>"; };
@ -201,6 +210,7 @@
C415D3DE2770F34D005EF286 /* AllowedArguments.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllowedArguments.swift; sourceTree = "<group>"; };
C415D3E52770F540005EF286 /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
C415D3E72770F692005EF286 /* AppDelegate+InterApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+InterApp.swift"; sourceTree = "<group>"; };
C417DC73277614690015E6EE /* Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = "<group>"; };
C4188988275FE8CB001EF227 /* Filesystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Filesystem.swift; sourceTree = "<group>"; };
C41C1B3322B0097F00E7CF16 /* PHP Monitor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "PHP Monitor.app"; sourceTree = BUILT_PRODUCTS_DIR; };
C41C1B3622B0097F00E7CF16 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@ -254,6 +264,8 @@
C4C8E81A276F54E5003AC782 /* PhpConfigWatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhpConfigWatcher.swift; sourceTree = "<group>"; };
C4CCBA6B275C567B008C7055 /* PMWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PMWindowController.swift; sourceTree = "<group>"; };
C4D8016522B1584700C6DA1B /* Startup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Startup.swift; sourceTree = "<group>"; };
C4D9ADBE277610E1007277F4 /* PhpSwitcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpSwitcher.swift; sourceTree = "<group>"; };
C4D9ADC7277611A0007277F4 /* InternalSwitcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalSwitcher.swift; sourceTree = "<group>"; };
C4E713562570150F00007428 /* SECURITY.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = SECURITY.md; sourceTree = "<group>"; };
C4E713572570151400007428 /* docs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = docs; sourceTree = "<group>"; };
C4EE188322D3386B00E126E5 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
@ -314,10 +326,10 @@
54B20EDF263AA22C00D3250E /* PHP */ = {
isa = PBXGroup;
children = (
C40C7F1D2772136000DDDCDC /* PhpEnv.swift */,
C4D9ADC2277610E4007277F4 /* Switcher */,
C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */,
C40C7F1D2772136000DDDCDC /* PhpSwitcher.swift */,
C41C1B4A22B019FF00E7CF16 /* ActivePhpInstallation.swift */,
C40C7F2727721FF600DDDCDC /* ActivePhpInstallation+Checks.swift */,
C4F2E4392752F7D00020E974 /* PhpInstallation.swift */,
C4ACA38E25C754C100060C66 /* PhpExtension.swift */,
);
@ -363,6 +375,7 @@
C4B5853B2770FE3900DA4FBE /* Paths.swift */,
C4B5853C2770FE3900DA4FBE /* Shell.swift */,
C40C7F2F27722E8D00DDDCDC /* Logger.swift */,
C417DC73277614690015E6EE /* Helpers.swift */,
);
path = Core;
sourceTree = "<group>";
@ -429,6 +442,7 @@
children = (
C4AF9F6B275445D300D44ED0 /* Integrations */,
C4B13B1D25C4915000548C3A /* Core */,
C4D9ADBD27761084007277F4 /* PHP */,
C47331A0247093AC009A0597 /* Menu */,
C464ADAA275A7A25003FCD53 /* SiteList */,
5420395726135DB800FB00FA /* Preferences */,
@ -556,6 +570,23 @@
name = Frameworks;
sourceTree = "<group>";
};
C4D9ADBD27761084007277F4 /* PHP */ = {
isa = PBXGroup;
children = (
C40C7F2727721FF600DDDCDC /* ActivePhpInstallation+Checks.swift */,
);
path = PHP;
sourceTree = "<group>";
};
C4D9ADC2277610E4007277F4 /* Switcher */ = {
isa = PBXGroup;
children = (
C4D9ADBE277610E1007277F4 /* PhpSwitcher.swift */,
C4D9ADC7277611A0007277F4 /* InternalSwitcher.swift */,
);
path = Switcher;
sourceTree = "<group>";
};
C4EE55B027708BB2001DF387 /* SwiftUI */ = {
isa = PBXGroup;
children = (
@ -743,13 +774,16 @@
C415D3E62770F540005EF286 /* main.swift in Sources */,
C40C7F2227721F8200DDDCDC /* PhpInstallation.swift in Sources */,
C4B585432770FE3900DA4FBE /* Shell.swift in Sources */,
C4D9ADC1277610E1007277F4 /* PhpSwitcher.swift in Sources */,
C40C7F2327721F8200DDDCDC /* ActivePhpInstallation.swift in Sources */,
C4B585462770FE3900DA4FBE /* Command.swift in Sources */,
C4D9ADCA277611A0007277F4 /* InternalSwitcher.swift in Sources */,
C40C7F2527721F9800DDDCDC /* HomebrewPackage.swift in Sources */,
C417DC76277614690015E6EE /* Helpers.swift in Sources */,
C40C7F3227722E8D00DDDCDC /* Logger.swift in Sources */,
C40C7F2B2772201C00DDDCDC /* Actions.swift in Sources */,
C415D3E12770F34D005EF286 /* AllowedArguments.swift in Sources */,
C40C7F202772136000DDDCDC /* PhpSwitcher.swift in Sources */,
C40C7F202772136000DDDCDC /* PhpEnv.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -791,8 +825,10 @@
C40C7F3027722E8D00DDDCDC /* Logger.swift in Sources */,
C41CA5ED2774F8EE00A2C80E /* SiteListVC+Actions.swift in Sources */,
C412E5FC25700D5300A1FB67 /* HomebrewPackage.swift in Sources */,
C4D9ADBF277610E1007277F4 /* PhpSwitcher.swift in Sources */,
54AB03262763858F00A29D5F /* Timer.swift in Sources */,
C4C8E81B276F54E5003AC782 /* PhpConfigWatcher.swift in Sources */,
C417DC74277614690015E6EE /* Helpers.swift in Sources */,
C415D3E82770F692005EF286 /* AppDelegate+InterApp.swift in Sources */,
C41C1B3722B0097F00E7CF16 /* AppDelegate.swift in Sources */,
C42759672627662800093CAE /* NSMenuExtension.swift in Sources */,
@ -801,10 +837,11 @@
C41C1B4B22B019FF00E7CF16 /* ActivePhpInstallation.swift in Sources */,
C4188989275FE8CB001EF227 /* Filesystem.swift in Sources */,
C4B97B7B275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */,
C40C7F1E2772136000DDDCDC /* PhpSwitcher.swift in Sources */,
C40C7F1E2772136000DDDCDC /* PhpEnv.swift in Sources */,
C476FF9822B0DD830098105B /* Alert.swift in Sources */,
C474B00624C0E98C00066A22 /* LocalNotification.swift in Sources */,
C48D0C9625CC80B100CC7490 /* HeaderView.swift in Sources */,
C4D9ADC8277611A0007277F4 /* InternalSwitcher.swift in Sources */,
C4B5635E276AB09000F12CCB /* VersionExtractor.swift in Sources */,
C47331A2247093B7009A0597 /* StatusMenu.swift in Sources */,
C46FA23F246C358E00944F05 /* StringExtension.swift in Sources */,
@ -829,6 +866,7 @@
C4EE55AC27708B9E001DF387 /* Preview.swift in Sources */,
54B48B60275F66AE006D90C5 /* Application.swift in Sources */,
C4F780C825D80B75000DBC97 /* DateExtension.swift in Sources */,
C4D9ADC0277610E1007277F4 /* PhpSwitcher.swift in Sources */,
C4F780CC25D80B75000DBC97 /* ActivePhpInstallation.swift in Sources */,
C4F780B125D80B4D000DBC97 /* PhpExtension.swift in Sources */,
C4F780CE25D80B75000DBC97 /* LocalNotification.swift in Sources */,
@ -855,6 +893,7 @@
C464ADB3275A87CA003FCD53 /* SiteListCell.swift in Sources */,
C415D3E92770F692005EF286 /* AppDelegate+InterApp.swift in Sources */,
C4AF9F78275447F100D44ED0 /* ValetConfigParserTest.swift in Sources */,
C417DC75277614690015E6EE /* Helpers.swift in Sources */,
C4B97B7C275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */,
C4B97B79275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */,
C4F7809C25D80344000DBC97 /* CommandTest.swift in Sources */,
@ -865,6 +904,7 @@
C4F780BD25D80B65000DBC97 /* Constants.swift in Sources */,
C4F780C325D80B75000DBC97 /* HeaderView.swift in Sources */,
C44C198E276E3A1C0072762D /* ProgressWindow.swift in Sources */,
C4D9ADC9277611A0007277F4 /* InternalSwitcher.swift in Sources */,
C4AF9F7D275454A900D44ED0 /* ValetTest.swift in Sources */,
C4B56362276AB0A500F12CCB /* VersionExtractorTest.swift in Sources */,
C4B585452770FE3900DA4FBE /* Command.swift in Sources */,
@ -875,7 +915,7 @@
C481F79A26164A7C004FBCFF /* Preferences.swift in Sources */,
C4B585422770FE3900DA4FBE /* Shell.swift in Sources */,
C464ADAD275A7A3F003FCD53 /* SiteListWC.swift in Sources */,
C40C7F1F2772136000DDDCDC /* PhpSwitcher.swift in Sources */,
C40C7F1F2772136000DDDCDC /* PhpEnv.swift in Sources */,
C4F780CB25D80B75000DBC97 /* StatsView.swift in Sources */,
C464ADB0275A7A6A003FCD53 /* SiteListVC.swift in Sources */,
C43A8A1A25D9CD1000591B77 /* Utility.swift in Sources */,

View File

@ -39,8 +39,8 @@ case .use, .performSwitch:
_ = Shell.user.executeSynchronously("brew link php", requiresPath: true)
}
let switcher = PhpSwitcher.shared
PhpSwitcher.detectPhpVersions()
let phpenv = PhpEnv.shared
PhpEnv.detectPhpVersions()
if CommandLine.arguments.count < 3 {
Log.err("You must enter at least two additional arguments when using this command.")
@ -48,11 +48,11 @@ case .use, .performSwitch:
}
let version = CommandLine.arguments[2].replacingOccurrences(of: "php@", with: "")
if switcher.availablePhpVersions.contains(version) {
if phpenv.availablePhpVersions.contains(version) {
Log.info("Switching to PHP \(version)...")
Actions.switchToPhpVersion(
version: version,
availableVersions: switcher.availablePhpVersions,
availableVersions: phpenv.availablePhpVersions,
completed: {
Log.info("The switch has been completed.")
exit(0)
@ -60,7 +60,7 @@ case .use, .performSwitch:
)
} else {
Log.err("A PHP installation with version \(version) is not installed.")
Log.err("The installed versions are: \(switcher.availablePhpVersions.joined(separator: ", ")).")
Log.err("The installed versions are: \(phpenv.availablePhpVersions.joined(separator: ", ")).")
Log.err("If this version is available, you may be able to install it by using `brew install php@\(version)`.")
exit(1)
}

View File

@ -14,7 +14,7 @@ class Actions {
public static func restartPhpFpm()
{
brew("services restart \(PhpSwitcher.phpInstall.formula)", sudo: true)
brew("services restart \(PhpEnv.phpInstall.formula)", sudo: true)
}
public static func restartNginx()
@ -29,7 +29,7 @@ class Actions {
public static func stopAllServices()
{
brew("services stop \(PhpSwitcher.phpInstall.formula)", sudo: true)
brew("services stop \(PhpEnv.phpInstall.formula)", sudo: true)
brew("services stop nginx", sudo: true)
brew("services stop dnsmasq", sudo: true)
}
@ -47,53 +47,6 @@ class Actions {
completed()
}
/**
Switching to a new PHP version involves:
- unlinking the current version
- stopping the active services
- linking the new desired version
Please note that depending on which version is installed,
the version that is switched to may or may not be identical to `php` (without @version).
*/
public static func switchToPhpVersion(
version: String,
availableVersions: [String],
completed: @escaping () -> Void
) {
Log.info("Switching to \(version), unlinking all versions...")
let group = DispatchGroup()
availableVersions.forEach { (available) in
group.enter()
DispatchQueue.global(qos: .userInitiated).async {
let formula = (available == PhpSwitcher.brewPhpVersion)
? "php" : "php@\(available)"
brew("unlink \(formula)")
brew("services stop \(formula)", sudo: true)
Log.perf("Unlinked and stopped services for \(formula)")
group.leave()
}
}
group.notify(queue: .global(qos: .userInitiated)) {
Log.info("All versions have been unlinked!")
Log.info("Linking the new version!")
let formula = (version == PhpSwitcher.brewPhpVersion) ? "php" : "php@\(version)"
brew("link \(formula) --overwrite --force")
brew("services start \(formula)", sudo: true)
Log.info("The new version has been linked!")
completed()
}
}
// MARK: - Finding Config Files
public static func openGenericPhpConfigFolder()
@ -138,8 +91,8 @@ class Actions {
{
brew("services restart dnsmasq", sudo: true)
PhpSwitcher.shared.detectPhpVersions().forEach { (version) in
let formula = (version == PhpSwitcher.brewPhpVersion) ? "php" : "php@\(version)"
PhpEnv.shared.detectPhpVersions().forEach { (version) in
let formula = (version == PhpEnv.brewPhpVersion) ? "php" : "php@\(version)"
brew("unlink php@\(version)")
brew("services stop \(formula)")
brew("services stop \(formula)", sudo: true)
@ -152,53 +105,4 @@ class Actions {
brew("services stop php", sudo: true)
brew("services stop nginx", sudo: true)
}
// MARK: Common Shell Commands
/**
Runs a `valet` command.
*/
public static func valet(_ command: String) -> String
{
return Shell.pipe("sudo \(Paths.valet) \(command)", requiresPath: true)
}
/**
Runs a `brew` command. Can run as superuser.
*/
public static func brew(_ command: String, sudo: Bool = false)
{
Shell.run("\(sudo ? "sudo " : "")" + "\(Paths.brew) \(command)")
}
/**
Runs `sed` in order to replace all occurrences of a string in a specific file with another.
*/
public static func sed(file: String, original: String, replacement: String)
{
// Escape slashes (or `sed` won't work)
let e_original = original.replacingOccurrences(of: "/", with: "\\/")
let e_replacement = replacement.replacingOccurrences(of: "/", with: "\\/")
// Check if gsed exists; it is able to follow symlinks,
// which we want to do to toggle the extension
if Shell.fileExists("\(Paths.binPath)/gsed") {
Shell.run("\(Paths.binPath)/gsed -i --follow-symlinks 's/\(e_original)/\(e_replacement)/g' \(file)")
} else {
Shell.run("sed -i '' 's/\(e_original)/\(e_replacement)/g' \(file)")
}
}
/**
Uses `grep` to determine whether a particular query string can be found in a particular file.
*/
public static func grepContains(file: String, query: String) -> Bool
{
return Shell.pipe("""
grep -q '\(query)' \(file); [ $? -eq 0 ] && echo "YES" || echo "NO"
""")
.trimmingCharacters(in: .whitespacesAndNewlines)
.contains("YES")
}
}

View File

@ -0,0 +1,55 @@
//
// Helpers.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 24/12/2021.
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//
// MARK: Common Shell Commands
/**
Runs a `valet` command.
*/
func valet(_ command: String) -> String
{
return Shell.pipe("sudo \(Paths.valet) \(command)", requiresPath: true)
}
/**
Runs a `brew` command. Can run as superuser.
*/
func brew(_ command: String, sudo: Bool = false)
{
Shell.run("\(sudo ? "sudo " : "")" + "\(Paths.brew) \(command)")
}
/**
Runs `sed` in order to replace all occurrences of a string in a specific file with another.
*/
func sed(file: String, original: String, replacement: String)
{
// Escape slashes (or `sed` won't work)
let e_original = original.replacingOccurrences(of: "/", with: "\\/")
let e_replacement = replacement.replacingOccurrences(of: "/", with: "\\/")
// Check if gsed exists; it is able to follow symlinks,
// which we want to do to toggle the extension
if Shell.fileExists("\(Paths.binPath)/gsed") {
Shell.run("\(Paths.binPath)/gsed -i --follow-symlinks 's/\(e_original)/\(e_replacement)/g' \(file)")
} else {
Shell.run("sed -i '' 's/\(e_original)/\(e_replacement)/g' \(file)")
}
}
/**
Uses `grep` to determine whether a particular query string can be found in a particular file.
*/
func grepContains(file: String, query: String) -> Bool
{
return Shell.pipe("""
grep -q '\(query)' \(file); [ $? -eq 0 ] && echo "YES" || echo "NO"
""")
.trimmingCharacters(in: .whitespacesAndNewlines)
.contains("YES")
}

View File

@ -25,7 +25,7 @@ class ActivePhpInstallation {
// MARK: - Computed
var formula: String {
return (version.short == PhpSwitcher.brewPhpVersion) ? "php" : "php@\(version.short)"
return (version.short == PhpEnv.brewPhpVersion) ? "php" : "php@\(version.short)"
}
// MARK: - Initializer

View File

@ -13,7 +13,7 @@ protocol PhpSwitcherDelegate: AnyObject {
func switcherDidCompleteSwitch()
}
class PhpSwitcher {
class PhpEnv {
// MARK: - Initializer
@ -36,7 +36,7 @@ class PhpSwitcher {
weak var delegate: PhpSwitcherDelegate?
/** The static app instance. Accessible at any time. */
static let shared = PhpSwitcher()
static let shared = PhpEnv()
/** Whether the switcher is busy performing any actions. */
var isBusy: Bool = false
@ -77,6 +77,12 @@ class PhpSwitcher {
// MARK: - Methods
public static var switcher: PhpSwitcher {
// Based on the setting, use a particular switcher
// For now, we'll hardcode the internal switcher though
return InternalSwitcher()
}
public static func detectPhpVersions() -> Void {
_ = Self.shared.detectPhpVersions()
}

View File

@ -78,7 +78,7 @@ class PhpExtension {
// ENABLED: Line where the comment delimiter (;) is removed
: line.replacingOccurrences(of: "; ", with: "")
Actions.sed(file: file, original: line, replacement: newLine)
sed(file: file, original: line, replacement: newLine)
enabled.toggle()
}

View File

@ -0,0 +1,58 @@
//
// InternalSwitcher.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 24/12/2021.
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//
import Foundation
class InternalSwitcher: PhpSwitcher {
/**
Switching to a new PHP version involves:
- unlinking the current version
- stopping the active services
- linking the new desired version
Please note that depending on which version is installed,
the version that is switched to may or may not be identical to `php`
(without @version).
*/
func performSwitch(to version: String, completion: @escaping () -> Void)
{
Log.info("Switching to \(version), unlinking all versions...")
let group = DispatchGroup()
PhpEnv.shared.availablePhpVersions.forEach { (available) in
group.enter()
DispatchQueue.global(qos: .userInitiated).async {
let formula = (available == PhpEnv.brewPhpVersion)
? "php" : "php@\(available)"
brew("unlink \(formula)")
brew("services stop \(formula)", sudo: true)
Log.perf("Unlinked and stopped services for \(formula)")
group.leave()
}
}
group.notify(queue: .global(qos: .userInitiated)) {
Log.info("All versions have been unlinked!")
Log.info("Linking the new version!")
let formula = (version == PhpEnv.brewPhpVersion) ? "php" : "php@\(version)"
brew("link \(formula) --overwrite --force")
brew("services start \(formula)", sudo: true)
Log.info("The new version has been linked!")
completion()
}
}
}

View File

@ -0,0 +1,15 @@
//
// PhpVersionSwitchContract.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 24/12/2021.
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//
import Foundation
protocol PhpSwitcher {
func performSwitch(to version: String, completion: @escaping () -> Void)
}

View File

@ -24,7 +24,7 @@ class App: PhpSwitcherDelegate {
/** Whether the app is busy doing something. Used to determine what UI to display. */
static var busy: Bool {
return PhpSwitcher.shared.isBusy
return PhpEnv.shared.isBusy
}
// MARK: Variables
@ -81,7 +81,7 @@ class App: PhpSwitcherDelegate {
}
func switcherDidCompleteSwitch() {
PhpSwitcher.shared.currentInstall = ActivePhpInstallation()
PhpEnv.shared.currentInstall = ActivePhpInstallation()
handlePhpConfigWatcher()
}
}

View File

@ -49,7 +49,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
detection, as well as switching. It is initialized
when the app is ready and passed all checks.
*/
var switcher: PhpSwitcher! = nil
var switcher: PhpEnv! = nil
var logger = Log.shared
@ -73,7 +73,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
}
func initializeSwitcher() {
self.switcher = PhpSwitcher.shared
self.switcher = PhpEnv.shared
self.switcher.delegate = self.state
}

View File

@ -46,12 +46,12 @@ class HomebrewDiagnostics {
from: tapAlias.data(using: .utf8)!
).first!
if tapPhp.version != PhpSwitcher.brewPhpVersion {
if tapPhp.version != PhpEnv.brewPhpVersion {
Log.warn("The `php` formula alias seems to be the different between the tap and core. This could be a problem!")
Log.info("Determining whether both of these versions are installed...")
let bothInstalled = PhpSwitcher.shared.availablePhpVersions.contains(tapPhp.version)
&& PhpSwitcher.shared.availablePhpVersions.contains(PhpSwitcher.brewPhpVersion)
let bothInstalled = PhpEnv.shared.availablePhpVersions.contains(tapPhp.version)
&& PhpEnv.shared.availablePhpVersions.contains(PhpEnv.brewPhpVersion)
if bothInstalled {
Log.warn("Both conflicting aliases seem to be installed, warning the user!")

View File

@ -22,7 +22,7 @@ class Valet {
var sites: [Site] = []
init() {
version = VersionExtractor.from(Actions.valet("--version"))
version = VersionExtractor.from(valet("--version"))
?? "UNKNOWN"
let file = FileManager.default.homeDirectoryForCurrentUser

View File

@ -41,7 +41,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
When the environment is all clear and the app can run, let's go.
*/
private func onEnvironmentPass() {
PhpSwitcher.detectPhpVersions()
PhpEnv.detectPhpVersions()
if HomebrewDiagnostics.shared.errors.contains(.aliasConflict) {
DispatchQueue.main.async {
@ -57,7 +57,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
Log.info("Determining broken PHP-FPM...")
// Attempt to find out if PHP-FPM is broken
let installation = PhpSwitcher.phpInstall
let installation = PhpEnv.phpInstall
installation.notifyAboutBrokenPhpFpm()
// Set up the config watchers on launch (these are automatically updated via delegate methods if the user switches)
@ -185,12 +185,12 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
*/
private func waitAndExecute(_ execute: @escaping () -> Void, completion: @escaping () -> Void = {})
{
PhpSwitcher.shared.isBusy = true
PhpEnv.shared.isBusy = true
setBusyImage()
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
update()
execute()
PhpSwitcher.shared.isBusy = false
PhpEnv.shared.isBusy = false
DispatchQueue.main.async { [self] in
updatePhpVersionInStatusBar()
@ -203,7 +203,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
// MARK: - User Interface
@objc func refreshActiveInstallation() {
PhpSwitcher.shared.currentInstall = ActivePhpInstallation()
PhpEnv.shared.currentInstall = ActivePhpInstallation()
updatePhpVersionInStatusBar()
}
@ -223,7 +223,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
} else {
// The dynamic icon has been requested
let long = Preferences.preferences[.fullPhpVersionDynamicIcon] as! Bool
setStatusBarImage(version: long ? PhpSwitcher.phpInstall.version.long : PhpSwitcher.phpInstall.version.short)
setStatusBarImage(version: long ? PhpEnv.phpInstall.version.long : PhpEnv.phpInstall.version.short)
}
}
}
@ -343,12 +343,12 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
}
func updateGlobalDependencies(notify: Bool, completion: @escaping (Bool) -> Void) {
PhpSwitcher.shared.isBusy = true
PhpEnv.shared.isBusy = true
setBusyImage()
self.update()
let noLongerBusy = {
PhpSwitcher.shared.isBusy = false
PhpEnv.shared.isBusy = false
DispatchQueue.main.async { [self] in
self.updatePhpVersionInStatusBar()
self.update()
@ -419,14 +419,14 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
}
@objc func openActiveConfigFolder() {
if (PhpSwitcher.phpInstall.version.error) {
if (PhpEnv.phpInstall.version.error) {
// php version was not identified
Actions.openGenericPhpConfigFolder()
return
}
// php version was identified
Actions.openPhpConfigFolder(version: PhpSwitcher.phpInstall.version.short)
Actions.openPhpConfigFolder(version: PhpEnv.phpInstall.version.short)
}
@objc func openGlobalComposerFolder() {
@ -439,7 +439,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
@objc func switchToPhpVersion(sender: PhpMenuItem) {
setBusyImage()
PhpSwitcher.shared.isBusy = true
PhpEnv.shared.isBusy = true
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
// Update the PHP version in the status bar
@ -449,10 +449,10 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
update()
let completion = {
PhpSwitcher.shared.delegate?.switcherDidCompleteSwitch()
PhpEnv.shared.delegate?.switcherDidCompleteSwitch()
// Mark as no longer busy
PhpSwitcher.shared.isBusy = false
PhpEnv.shared.isBusy = false
// Perform UI updates on main thread
DispatchQueue.main.async { [self] in
@ -464,7 +464,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
title: String(format: "notification.version_changed_title".localized, sender.version),
subtitle: String(format: "notification.version_changed_desc".localized, sender.version)
)
PhpSwitcher.phpInstall.notifyAboutBrokenPhpFpm()
PhpEnv.phpInstall.notifyAboutBrokenPhpFpm()
}
// Run composer updates
@ -478,24 +478,10 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
}
}
/* DISABLED UNTIL VALET SWITCHING IS OK (see #34)
if Preferences.preferences[.useInternalSwitcher] as! Bool == false {
// 1. Default switcher using Valet
// Will cause less issues, but is slower
Actions.switchToPhpVersionUsingValet(
version: sender.version,
availableVersions: App.shared.availablePhpVersions,
completed: completion
)
} else { */
// 2. Custom switcher (internal)
// Will cause more issues with Homebrew and is faster
Actions.switchToPhpVersion(
version: sender.version,
availableVersions: PhpSwitcher.shared.availablePhpVersions,
completed: completion
)
/* } */
PhpEnv.switcher.performSwitch(
to: sender.version,
completion: completion
)
}
}

View File

@ -9,14 +9,14 @@ import Cocoa
class StatusMenu : NSMenu {
func addPhpVersionMenuItems() {
if PhpSwitcher.phpInstall.version.error {
if PhpEnv.phpInstall.version.error {
for message in ["mi_php_broken_1", "mi_php_broken_2", "mi_php_broken_3", "mi_php_broken_4"] {
addItem(NSMenuItem(title: message.localized, action: nil, keyEquivalent: ""))
}
return
}
let phpVersionText = "\("mi_php_version".localized) \(PhpSwitcher.phpInstall.version.long)"
let phpVersionText = "\("mi_php_version".localized) \(PhpEnv.phpInstall.version.long)"
addItem(HeaderView.asMenuItem(text: phpVersionText))
}
@ -26,7 +26,7 @@ class StatusMenu : NSMenu {
return
}
if PhpSwitcher.shared.availablePhpVersions.count == 0 {
if PhpEnv.shared.availablePhpVersions.count == 0 {
return
}
@ -40,14 +40,14 @@ class StatusMenu : NSMenu {
servicesMenu.addItem(NSMenuItem(title: "mi_help".localized, action: nil, keyEquivalent: ""))
if !PhpSwitcher.shared.availablePhpVersions.contains(PhpSwitcher.brewPhpVersion) {
if !PhpEnv.shared.availablePhpVersions.contains(PhpEnv.brewPhpVersion) {
servicesMenu.addItem(NSMenuItem(
title: "mi_force_load_latest_unavailable".localized(PhpSwitcher.brewPhpVersion),
title: "mi_force_load_latest_unavailable".localized(PhpEnv.brewPhpVersion),
action: nil, keyEquivalent: "f"
))
} else {
servicesMenu.addItem(NSMenuItem(
title: "mi_force_load_latest".localized(PhpSwitcher.brewPhpVersion),
title: "mi_force_load_latest".localized(PhpEnv.brewPhpVersion),
action: #selector(MainMenu.forceRestartLatestPhp), keyEquivalent: "f"))
}
@ -92,13 +92,13 @@ class StatusMenu : NSMenu {
self.addItem(NSMenuItem.separator())
self.addItem(HeaderView.asMenuItem(text: "mi_composer".localized))
self.addItem(NSMenuItem(title: "mi_global_composer".localized, action: #selector(MainMenu.openGlobalComposerFolder), keyEquivalent: "g"))
self.addItem(NSMenuItem(title: "mi_update_global_composer".localized, action: PhpSwitcher.shared.isBusy ? nil : #selector(MainMenu.updateComposerDependencies), keyEquivalent: ""))
self.addItem(NSMenuItem(title: "mi_update_global_composer".localized, action: PhpEnv.shared.isBusy ? nil : #selector(MainMenu.updateComposerDependencies), keyEquivalent: ""))
if (PhpSwitcher.shared.isBusy) {
if (PhpEnv.shared.isBusy) {
return
}
let stats = PhpSwitcher.phpInstall.limits
let stats = PhpEnv.phpInstall.limits
// Stats
self.addItem(NSMenuItem.separator())
@ -112,12 +112,12 @@ class StatusMenu : NSMenu {
self.addItem(NSMenuItem.separator())
self.addItem(HeaderView.asMenuItem(text: "mi_detected_extensions".localized))
if (PhpSwitcher.phpInstall.extensions.count == 0) {
if (PhpEnv.phpInstall.extensions.count == 0) {
self.addItem(NSMenuItem(title: "mi_no_extensions_detected".localized, action: nil, keyEquivalent: ""))
}
var shortcutKey = 1
for phpExtension in PhpSwitcher.phpInstall.extensions {
for phpExtension in PhpEnv.phpInstall.extensions {
self.addExtensionItem(phpExtension, shortcutKey)
shortcutKey += 1
}
@ -130,20 +130,20 @@ class StatusMenu : NSMenu {
private func addSwitchToPhpMenuItems() {
var shortcutKey = 1
for index in (0..<PhpSwitcher.shared.availablePhpVersions.count).reversed() {
for index in (0..<PhpEnv.shared.availablePhpVersions.count).reversed() {
// Get the short and long version
let shortVersion = PhpSwitcher.shared.availablePhpVersions[index]
let longVersion = PhpSwitcher.shared.cachedPhpInstallations[shortVersion]!.longVersion
let shortVersion = PhpEnv.shared.availablePhpVersions[index]
let longVersion = PhpEnv.shared.cachedPhpInstallations[shortVersion]!.longVersion
let long = Preferences.preferences[.fullPhpVersionDynamicIcon] as! Bool
let versionString = long ? longVersion : shortVersion
let action = #selector(MainMenu.switchToPhpVersion(sender:))
let brew = (shortVersion == PhpSwitcher.brewPhpVersion) ? "php" : "php@\(shortVersion)"
let brew = (shortVersion == PhpEnv.brewPhpVersion) ? "php" : "php@\(shortVersion)"
let menuItem = PhpMenuItem(
title: "\("mi_php_switch".localized) \(versionString) (\(brew))",
action: (shortVersion == PhpSwitcher.phpInstall.version.short) ? nil : action, keyEquivalent: "\(shortcutKey)"
action: (shortVersion == PhpEnv.phpInstall.version.short) ? nil : action, keyEquivalent: "\(shortcutKey)"
)
menuItem.version = shortVersion

View File

@ -28,7 +28,7 @@ extension App {
}
func handlePhpConfigWatcher(forceReload: Bool = false) {
let url = URL(fileURLWithPath: "\(Paths.etcPath)/php/\(PhpSwitcher.phpInstall.version.short)")
let url = URL(fileURLWithPath: "\(Paths.etcPath)/php/\(PhpEnv.phpInstall.version.short)")
// Watcher needs to be created
if self.watcher == nil {