From dd251936b929e8849bd2fd8a49dc1701f257704d Mon Sep 17 00:00:00 2001 From: Nico Verbruggen Date: Fri, 24 Dec 2021 16:09:51 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20PhpSwitcher=20i?= =?UTF-8?q?nto=20PhpEnv?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PHP Monitor.xcodeproj/project.pbxproj | 58 ++++++++-- phpmon-cli/main.swift | 10 +- phpmon-common/Core/Actions.swift | 104 +----------------- phpmon-common/Core/Helpers.swift | 55 +++++++++ phpmon-common/PHP/ActivePhpInstallation.swift | 2 +- .../PHP/{PhpSwitcher.swift => PhpEnv.swift} | 10 +- phpmon-common/PHP/PhpExtension.swift | 2 +- .../PHP/Switcher/InternalSwitcher.swift | 58 ++++++++++ phpmon-common/PHP/Switcher/PhpSwitcher.swift | 15 +++ phpmon/Domain/Core/App.swift | 4 +- phpmon/Domain/Core/AppDelegate.swift | 4 +- .../Homebrew/HomebrewDiagnostics.swift | 6 +- phpmon/Domain/Integrations/Valet/Valet.swift | 2 +- phpmon/Domain/Menu/MainMenu.swift | 50 +++------ phpmon/Domain/Menu/StatusMenu.swift | 32 +++--- .../PHP/ActivePhpInstallation+Checks.swift | 0 phpmon/Domain/Watcher/App+ConfigWatch.swift | 2 +- 17 files changed, 239 insertions(+), 175 deletions(-) create mode 100644 phpmon-common/Core/Helpers.swift rename phpmon-common/PHP/{PhpSwitcher.swift => PhpEnv.swift} (94%) create mode 100644 phpmon-common/PHP/Switcher/InternalSwitcher.swift create mode 100644 phpmon-common/PHP/Switcher/PhpSwitcher.swift rename {phpmon-common => phpmon/Domain}/PHP/ActivePhpInstallation+Checks.swift (100%) diff --git a/PHP Monitor.xcodeproj/project.pbxproj b/PHP Monitor.xcodeproj/project.pbxproj index c3e04e0..09cb6c2 100644 --- a/PHP Monitor.xcodeproj/project.pbxproj +++ b/PHP Monitor.xcodeproj/project.pbxproj @@ -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 = ""; }; C405A4CE24B9B9130062FAFA /* InternetAccessPolicy.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = InternetAccessPolicy.strings; sourceTree = ""; }; C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = InternetAccessPolicy.plist; sourceTree = ""; }; - C40C7F1D2772136000DDDCDC /* PhpSwitcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpSwitcher.swift; sourceTree = ""; }; + C40C7F1D2772136000DDDCDC /* PhpEnv.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpEnv.swift; sourceTree = ""; }; C40C7F2727721FF600DDDCDC /* ActivePhpInstallation+Checks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ActivePhpInstallation+Checks.swift"; sourceTree = ""; }; C40C7F2F27722E8D00DDDCDC /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = ""; }; C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomebrewPackage.swift; sourceTree = ""; }; @@ -201,6 +210,7 @@ C415D3DE2770F34D005EF286 /* AllowedArguments.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllowedArguments.swift; sourceTree = ""; }; C415D3E52770F540005EF286 /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; C415D3E72770F692005EF286 /* AppDelegate+InterApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+InterApp.swift"; sourceTree = ""; }; + C417DC73277614690015E6EE /* Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = ""; }; C4188988275FE8CB001EF227 /* Filesystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Filesystem.swift; sourceTree = ""; }; 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 = ""; }; @@ -254,6 +264,8 @@ C4C8E81A276F54E5003AC782 /* PhpConfigWatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhpConfigWatcher.swift; sourceTree = ""; }; C4CCBA6B275C567B008C7055 /* PMWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PMWindowController.swift; sourceTree = ""; }; C4D8016522B1584700C6DA1B /* Startup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Startup.swift; sourceTree = ""; }; + C4D9ADBE277610E1007277F4 /* PhpSwitcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpSwitcher.swift; sourceTree = ""; }; + C4D9ADC7277611A0007277F4 /* InternalSwitcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalSwitcher.swift; sourceTree = ""; }; C4E713562570150F00007428 /* SECURITY.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = SECURITY.md; sourceTree = ""; }; C4E713572570151400007428 /* docs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = docs; sourceTree = ""; }; C4EE188322D3386B00E126E5 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; @@ -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 = ""; @@ -429,6 +442,7 @@ children = ( C4AF9F6B275445D300D44ED0 /* Integrations */, C4B13B1D25C4915000548C3A /* Core */, + C4D9ADBD27761084007277F4 /* PHP */, C47331A0247093AC009A0597 /* Menu */, C464ADAA275A7A25003FCD53 /* SiteList */, 5420395726135DB800FB00FA /* Preferences */, @@ -556,6 +570,23 @@ name = Frameworks; sourceTree = ""; }; + C4D9ADBD27761084007277F4 /* PHP */ = { + isa = PBXGroup; + children = ( + C40C7F2727721FF600DDDCDC /* ActivePhpInstallation+Checks.swift */, + ); + path = PHP; + sourceTree = ""; + }; + C4D9ADC2277610E4007277F4 /* Switcher */ = { + isa = PBXGroup; + children = ( + C4D9ADBE277610E1007277F4 /* PhpSwitcher.swift */, + C4D9ADC7277611A0007277F4 /* InternalSwitcher.swift */, + ); + path = Switcher; + sourceTree = ""; + }; 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 */, diff --git a/phpmon-cli/main.swift b/phpmon-cli/main.swift index 27254d4..8b986a2 100644 --- a/phpmon-cli/main.swift +++ b/phpmon-cli/main.swift @@ -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) } diff --git a/phpmon-common/Core/Actions.swift b/phpmon-common/Core/Actions.swift index bbfc80d..bb5163a 100644 --- a/phpmon-common/Core/Actions.swift +++ b/phpmon-common/Core/Actions.swift @@ -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") - } - } diff --git a/phpmon-common/Core/Helpers.swift b/phpmon-common/Core/Helpers.swift new file mode 100644 index 0000000..369b605 --- /dev/null +++ b/phpmon-common/Core/Helpers.swift @@ -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") +} diff --git a/phpmon-common/PHP/ActivePhpInstallation.swift b/phpmon-common/PHP/ActivePhpInstallation.swift index 6111ffe..f4b124e 100644 --- a/phpmon-common/PHP/ActivePhpInstallation.swift +++ b/phpmon-common/PHP/ActivePhpInstallation.swift @@ -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 diff --git a/phpmon-common/PHP/PhpSwitcher.swift b/phpmon-common/PHP/PhpEnv.swift similarity index 94% rename from phpmon-common/PHP/PhpSwitcher.swift rename to phpmon-common/PHP/PhpEnv.swift index 8927d1e..c5dcb55 100644 --- a/phpmon-common/PHP/PhpSwitcher.swift +++ b/phpmon-common/PHP/PhpEnv.swift @@ -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() } diff --git a/phpmon-common/PHP/PhpExtension.swift b/phpmon-common/PHP/PhpExtension.swift index 0996691..05f1a06 100644 --- a/phpmon-common/PHP/PhpExtension.swift +++ b/phpmon-common/PHP/PhpExtension.swift @@ -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() } diff --git a/phpmon-common/PHP/Switcher/InternalSwitcher.swift b/phpmon-common/PHP/Switcher/InternalSwitcher.swift new file mode 100644 index 0000000..59fccbb --- /dev/null +++ b/phpmon-common/PHP/Switcher/InternalSwitcher.swift @@ -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() + } + } + +} diff --git a/phpmon-common/PHP/Switcher/PhpSwitcher.swift b/phpmon-common/PHP/Switcher/PhpSwitcher.swift new file mode 100644 index 0000000..e167e15 --- /dev/null +++ b/phpmon-common/PHP/Switcher/PhpSwitcher.swift @@ -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) + +} diff --git a/phpmon/Domain/Core/App.swift b/phpmon/Domain/Core/App.swift index 1743377..788b618 100644 --- a/phpmon/Domain/Core/App.swift +++ b/phpmon/Domain/Core/App.swift @@ -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() } } diff --git a/phpmon/Domain/Core/AppDelegate.swift b/phpmon/Domain/Core/AppDelegate.swift index 1e890d6..3183636 100644 --- a/phpmon/Domain/Core/AppDelegate.swift +++ b/phpmon/Domain/Core/AppDelegate.swift @@ -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 } diff --git a/phpmon/Domain/Integrations/Homebrew/HomebrewDiagnostics.swift b/phpmon/Domain/Integrations/Homebrew/HomebrewDiagnostics.swift index 29faf62..0f8dec2 100644 --- a/phpmon/Domain/Integrations/Homebrew/HomebrewDiagnostics.swift +++ b/phpmon/Domain/Integrations/Homebrew/HomebrewDiagnostics.swift @@ -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!") diff --git a/phpmon/Domain/Integrations/Valet/Valet.swift b/phpmon/Domain/Integrations/Valet/Valet.swift index a40295b..ce8ae55 100644 --- a/phpmon/Domain/Integrations/Valet/Valet.swift +++ b/phpmon/Domain/Integrations/Valet/Valet.swift @@ -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 diff --git a/phpmon/Domain/Menu/MainMenu.swift b/phpmon/Domain/Menu/MainMenu.swift index 121d86e..8cbb51f 100644 --- a/phpmon/Domain/Menu/MainMenu.swift +++ b/phpmon/Domain/Menu/MainMenu.swift @@ -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 + ) } } diff --git a/phpmon/Domain/Menu/StatusMenu.swift b/phpmon/Domain/Menu/StatusMenu.swift index 8c8a5a7..58facdd 100644 --- a/phpmon/Domain/Menu/StatusMenu.swift +++ b/phpmon/Domain/Menu/StatusMenu.swift @@ -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..