From 77f4de8ca9529726779dcc7919f8321f2df32ecd Mon Sep 17 00:00:00 2001 From: Nico Verbruggen Date: Tue, 26 Jan 2021 18:42:26 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Cleanup=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PHP Monitor.xcodeproj/project.pbxproj | 18 ++- phpmon/Classes/Commands/Actions.swift | 97 +++++++------ phpmon/Classes/Commands/Startup.swift | 26 ++-- .../{Helpers => Core}/HomebrewPackage.swift | 0 phpmon/Classes/Core/PhpInstall.swift | 64 +++++++++ phpmon/Classes/Helpers/Alert.swift | 4 + phpmon/Classes/Helpers/PhpVersion.swift | 51 ------- phpmon/Classes/Menu/StatusMenu.swift | 128 +++++++++--------- phpmon/Singletons/App.swift | 12 +- phpmon/Singletons/MainMenu.swift | 63 +++++---- 10 files changed, 258 insertions(+), 205 deletions(-) rename phpmon/Classes/{Helpers => Core}/HomebrewPackage.swift (100%) create mode 100644 phpmon/Classes/Core/PhpInstall.swift delete mode 100644 phpmon/Classes/Helpers/PhpVersion.swift diff --git a/PHP Monitor.xcodeproj/project.pbxproj b/PHP Monitor.xcodeproj/project.pbxproj index 74a089f..88f8f8b 100644 --- a/PHP Monitor.xcodeproj/project.pbxproj +++ b/PHP Monitor.xcodeproj/project.pbxproj @@ -15,7 +15,7 @@ C41C1B3E22B0098000E7CF16 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C41C1B3C22B0098000E7CF16 /* Main.storyboard */; }; C41C1B4722B009A400E7CF16 /* Shell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4622B009A400E7CF16 /* Shell.swift */; }; C41C1B4922B00A9800E7CF16 /* MenuBarImageGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4822B00A9800E7CF16 /* MenuBarImageGenerator.swift */; }; - C41C1B4B22B019FF00E7CF16 /* PhpVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4A22B019FF00E7CF16 /* PhpVersion.swift */; }; + C41C1B4B22B019FF00E7CF16 /* PhpInstall.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4A22B019FF00E7CF16 /* PhpInstall.swift */; }; C41C1B4D22B0215A00E7CF16 /* Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4C22B0215A00E7CF16 /* Actions.swift */; }; C42295DD2358D02000E263B2 /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42295DC2358D02000E263B2 /* Command.swift */; }; C46FA23F246C358E00944F05 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46FA23E246C358E00944F05 /* StringExtension.swift */; }; @@ -44,7 +44,7 @@ C41C1B4022B0098000E7CF16 /* phpmon.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = phpmon.entitlements; sourceTree = ""; }; C41C1B4622B009A400E7CF16 /* Shell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shell.swift; sourceTree = ""; }; C41C1B4822B00A9800E7CF16 /* MenuBarImageGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuBarImageGenerator.swift; sourceTree = ""; }; - C41C1B4A22B019FF00E7CF16 /* PhpVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpVersion.swift; sourceTree = ""; }; + C41C1B4A22B019FF00E7CF16 /* PhpInstall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpInstall.swift; sourceTree = ""; }; C41C1B4C22B0215A00E7CF16 /* Actions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Actions.swift; sourceTree = ""; }; C42295DC2358D02000E263B2 /* Command.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = ""; }; C46FA23E246C358E00944F05 /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; }; @@ -124,6 +124,7 @@ C41E181722CB61EB0072CF09 /* Classes */ = { isa = PBXGroup; children = ( + C4B13B1D25C4915000548C3A /* Core */, C47331A0247093AC009A0597 /* Menu */, C4811D2722D70D8E00B5F6B3 /* Commands */, C4811D2822D70D9C00B5F6B3 /* Helpers */, @@ -173,14 +174,21 @@ isa = PBXGroup; children = ( C476FF9722B0DD830098105B /* Alert.swift */, - C41C1B4A22B019FF00E7CF16 /* PhpVersion.swift */, C41C1B4822B00A9800E7CF16 /* MenuBarImageGenerator.swift */, C474B00524C0E98C00066A22 /* LocalNotification.swift */, - C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */, ); path = Helpers; sourceTree = ""; }; + C4B13B1D25C4915000548C3A /* Core */ = { + isa = PBXGroup; + children = ( + C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */, + C41C1B4A22B019FF00E7CF16 /* PhpInstall.swift */, + ); + path = Core; + sourceTree = ""; + }; C4F8C0A222D4F100002EFE61 /* Extensions */ = { isa = PBXGroup; children = ( @@ -273,7 +281,7 @@ C4811D2A22D70F9A00B5F6B3 /* MainMenu.swift in Sources */, C412E5FC25700D5300A1FB67 /* HomebrewPackage.swift in Sources */, C41C1B3722B0097F00E7CF16 /* AppDelegate.swift in Sources */, - C41C1B4B22B019FF00E7CF16 /* PhpVersion.swift in Sources */, + C41C1B4B22B019FF00E7CF16 /* PhpInstall.swift in Sources */, C486EFFC2586931100A02B2C /* PhpMenuItem.swift in Sources */, C49EAB46259FC305007F6C3B /* Paths.swift in Sources */, C476FF9822B0DD830098105B /* Alert.swift in Sources */, diff --git a/phpmon/Classes/Commands/Actions.swift b/phpmon/Classes/Commands/Actions.swift index f072246..821b574 100644 --- a/phpmon/Classes/Commands/Actions.swift +++ b/phpmon/Classes/Commands/Actions.swift @@ -11,7 +11,10 @@ import AppKit class Actions { - public static func detectPhpVersions() -> [String] { + // MARK: - Detect PHP Versions + + public static func detectPhpVersions() -> [String] + { let files = Shell.user.pipe("ls \(Paths.optPath()) | grep php@") var versions = files.components(separatedBy: "\n") @@ -30,6 +33,7 @@ class Actions { // The user may have `php` installed, but not e.g. `php@8.0` // We should also detect that as a version that is installed let phpAlias = App.shared.brewPhpVersion + if (!versionsOnly.contains(phpAlias)) { versionsOnly.append(phpAlias); } @@ -37,23 +41,21 @@ class Actions { return versionsOnly } - public static func restartPhpFpm() { - let version = App.shared.currentVersion!.short - if (version == App.shared.brewPhpVersion) { - Shell.user.run("sudo \(Paths.brew()) services restart php") - } else { - Shell.user.run("sudo \(Paths.brew()) services restart php@\(version)") - } + // MARK: - Services + + public static func restartPhpFpm() + { + brew("services restart \(App.phpInstall!.formula)", sudo: true) } public static func restartNginx() { - Shell.user.run("sudo \(Paths.brew()) services restart nginx") + brew("services restart nginx", sudo: true) } public static func restartDnsMasq() { - Shell.user.run("sudo \(Paths.brew()) services restart dnsmasq") + brew("services restart dnsmasq", sudo: true) } /** @@ -65,7 +67,8 @@ class Actions { 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]) { + public static func switchToPhpVersion(version: String, availableVersions: [String]) + { availableVersions.forEach { (available) in let formula = (available == App.shared.brewPhpVersion) ? "php" : "php@\(available)" Shell.user.run("\(Paths.brew()) unlink \(formula)") @@ -77,22 +80,30 @@ class Actions { Shell.user.run("sudo \(Paths.brew()) services start \(formula)") } - public static func openGenericPhpConfigFolder() { + // MARK: - Finding Config Files + + public static func openGenericPhpConfigFolder() + { let files = [NSURL(fileURLWithPath: "\(Paths.etcPath())/php")]; NSWorkspace.shared.activateFileViewerSelecting(files as [URL]) } - public static func openPhpConfigFolder(version: String) { + public static func openPhpConfigFolder(version: String) + { let files = [NSURL(fileURLWithPath: "\(Paths.etcPath())/php/\(version)/php.ini")]; NSWorkspace.shared.activateFileViewerSelecting(files as [URL]) } - public static func openValetConfigFolder() { + public static func openValetConfigFolder() + { let files = [NSURL(fileURLWithPath: NSString(string: "~/.config/valet").expandingTildeInPath)]; NSWorkspace.shared.activateFileViewerSelecting(files as [URL]) } - public static func didFindXdebug(_ version: String) -> Bool { + // MARK: - Xdebug Actions + + public static func didFindXdebug(_ version: String) -> Bool + { let command = """ grep -q 'zend_extension="xdebug.so"' \(Paths.etcPath())/php/\(version)/php.ini; [ $? -eq 0 ] && echo "YES" || echo "NO" """ @@ -100,7 +111,8 @@ class Actions { return (output == "YES") } - public static func didEnableXdebug(_ version: String) -> Bool { + public static func didEnableXdebug(_ version: String) -> Bool + { let command = """ grep -q '; zend_extension="xdebug.so"' \(Paths.etcPath())/php/\(version)/php.ini; [ $? -eq 0 ] && echo "YES" || echo "NO" """ @@ -108,43 +120,48 @@ class Actions { return (output == "NO") } - public static func toggleXdebug() { - let version = App.shared.currentVersion?.short + public static func toggleXdebug() + { + let version = App.phpInstall!.version.short var command = """ - sed -i '' 's/; zend_extension="xdebug.so"/zend_extension="xdebug.so"/g' \(Paths.etcPath())/php/\(version!)/php.ini + sed -i '' 's/; zend_extension="xdebug.so"/zend_extension="xdebug.so"/g' \(Paths.etcPath())/php/\(version)/php.ini """ - if (self.didEnableXdebug(version!)) { + if (self.didEnableXdebug(version)) { command = """ - sed -i '' 's/zend_extension="xdebug.so"/; zend_extension="xdebug.so"/g' \(Paths.etcPath())/php/\(version!)/php.ini + sed -i '' 's/zend_extension="xdebug.so"/; zend_extension="xdebug.so"/g' \(Paths.etcPath())/php/\(version)/php.ini """ } Shell.user.run(command) } + // MARK: - Quick Fix + /** Detects all currently available PHP versions, and unlinks each and every one of them. After this, the brew services are also stopped, the latest PHP version is linked, and php + nginx are restarted. If this does not solve the issue, the user may need to install additional extensions and/or run `composer global update`. */ - public static func fixMyPhp() { - Shell.user.run("sudo \(Paths.brew()) services stop dnsmasq") - Shell.user.run("sudo \(Paths.brew()) services start dnsmasq") - let versions = self.detectPhpVersions() - versions.forEach { (version) in - Shell.user.run("\(Paths.brew()) unlink php@\(version)") - if (version == App.shared.brewPhpVersion) { - Shell.user.run("\(Paths.brew()) services stop php") - Shell.user.run("sudo \(Paths.brew()) services stop php") - } else { - Shell.user.run("\(Paths.brew()) services stop php@\(version)") - Shell.user.run("sudo \(Paths.brew()) services stop php@\(version)") - } + public static func fixMyPhp() + { + brew("services restart dnsmasq", sudo: true) + + self.detectPhpVersions().forEach { (version) in + let formula = (version == App.shared.brewPhpVersion) ? "php" : "php@\(version)" + brew("unlink php@\(version)") + brew("services stop \(formula)") + brew("services stop \(formula)", sudo: true) } - Shell.user.run("\(Paths.brew()) services stop php") - Shell.user.run("\(Paths.brew()) services stop nginx") - Shell.user.run("\(Paths.brew()) link php") - Shell.user.run("sudo \(Paths.brew()) services restart dnsmasq") - Shell.user.run("sudo \(Paths.brew()) services restart php") - Shell.user.run("sudo \(Paths.brew()) services restart nginx") + + brew("services stop php") + brew("services stop nginx") + brew("link php") + brew("services restart dnsmasq", sudo: true) + brew("services stop php", sudo: true) + brew("services stop nginx", sudo: true) + } + + private static func brew(_ command: String, sudo: Bool = false) + { + Shell.user.run("\(sudo ? "sudo " : "")" + "\(Paths.brew()) \(command)") } } diff --git a/phpmon/Classes/Commands/Startup.swift b/phpmon/Classes/Commands/Startup.swift index d458471..96fa922 100644 --- a/phpmon/Classes/Commands/Startup.swift +++ b/phpmon/Classes/Commands/Startup.swift @@ -105,23 +105,17 @@ class Startup { messageText: String, informativeText: String, breaking: Bool - ) - { - if (condition) { - // Only breaking issues will cause the notification + ) { + if (!condition) { return } + + self.failed = breaking + + DispatchQueue.main.async { + // Present the information to the user + Alert.notify(message: messageText, info: informativeText) + // Only breaking issues will throw the extra retry modal if (breaking) { - self.failed = true - } - DispatchQueue.main.async { - // Present the information to the user - _ = Alert.present( - messageText: messageText, - informativeText: informativeText - ) - // Only breaking issues will throw the extra retry modal - if (breaking) { - self.failureCallback() - } + self.failureCallback() } } } diff --git a/phpmon/Classes/Helpers/HomebrewPackage.swift b/phpmon/Classes/Core/HomebrewPackage.swift similarity index 100% rename from phpmon/Classes/Helpers/HomebrewPackage.swift rename to phpmon/Classes/Core/HomebrewPackage.swift diff --git a/phpmon/Classes/Core/PhpInstall.swift b/phpmon/Classes/Core/PhpInstall.swift new file mode 100644 index 0000000..87ee525 --- /dev/null +++ b/phpmon/Classes/Core/PhpInstall.swift @@ -0,0 +1,64 @@ +// +// PhpVersionExtractor.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 11/06/2019. +// Copyright © 2019 Nico Verbruggen. All rights reserved. +// + +import Foundation + +class PhpInstall { + + var version: Version = Version() + var xdebug: Xdebug = Xdebug() + + // MARK: - Computed + + var formula: String { + return (self.version.short == App.shared.brewPhpVersion) ? "php" : "php@\(self.version.short)" + } + + // MARK: - Initializer + + init() { + let version = Command.execute(path: Paths.php(), arguments: ["-r", "print phpversion();"]) + + if (version == "" || version.contains("Warning")) { + self.version.short = "💩 BROKEN" + self.version.long = ""; + self.version.error = true + return; + } + + // That's the long version + self.version.long = version + + // Next up, let's strip away the minor version number + let segments = self.version.long.components(separatedBy: ".") + + // Get the first two elements + self.version.short = segments[0...1].joined(separator: ".") + + // Determine the Xdebug status + self.xdebug = Xdebug( + found: Actions.didFindXdebug(self.version.short), + enabled: Actions.didEnableXdebug(self.version.short) + ) + + self.version.error = false + } + + // MARK: - Structs + + struct Version { + var short = "???" + var long = "???" + var error = false + } + + struct Xdebug { + var found: Bool = false + var enabled: Bool = false + } +} diff --git a/phpmon/Classes/Helpers/Alert.swift b/phpmon/Classes/Helpers/Alert.swift index 1162223..5725961 100644 --- a/phpmon/Classes/Helpers/Alert.swift +++ b/phpmon/Classes/Helpers/Alert.swift @@ -24,4 +24,8 @@ class Alert { } return alert.runModal() == .alertFirstButtonReturn } + + public static func notify(message: String, info: String) { + _ = self.present(messageText: message, informativeText: info, buttonTitle: "OK", secondButtonTitle: "") + } } diff --git a/phpmon/Classes/Helpers/PhpVersion.swift b/phpmon/Classes/Helpers/PhpVersion.swift deleted file mode 100644 index b2f4c36..0000000 --- a/phpmon/Classes/Helpers/PhpVersion.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// PhpVersionExtractor.swift -// PHP Monitor -// -// Created by Nico Verbruggen on 11/06/2019. -// Copyright © 2019 Nico Verbruggen. All rights reserved. -// - -import Foundation - -class PhpVersion { - - var short : String = "???" - var long : String = "???" - - var xdebugFound: Bool = false - var xdebugEnabled : Bool = false - - var error : Bool = false - - init() { - let version = Command.execute( - path: Paths.php(), - arguments: ["-r", "print phpversion();"] - ) - - if (version == "" || version.contains("Warning")) { - self.short = "💩 BROKEN" - self.long = ""; - self.error = true - return; - } - - // That's the long version - self.long = version - - // Next up, let's strip away the minor version number - let segments = long.components(separatedBy: ".") - - // Get the first two elements - self.short = segments[0...1].joined(separator: ".") - - // Load xdebug support - self.xdebugFound = Actions.didFindXdebug(self.short) - if (self.xdebugFound) { - self.xdebugEnabled = Actions.didEnableXdebug(self.short) - } - - self.error = false; - } -} diff --git a/phpmon/Classes/Menu/StatusMenu.swift b/phpmon/Classes/Menu/StatusMenu.swift index dafa84f..329fc63 100644 --- a/phpmon/Classes/Menu/StatusMenu.swift +++ b/phpmon/Classes/Menu/StatusMenu.swift @@ -12,86 +12,92 @@ class StatusMenu : NSMenu { public func addPhpVersionMenuItems() { - var string = "mi_unsure".localized - if (App.shared.currentVersion != nil) { - if (!App.shared.currentVersion!.error) { - // in case the php version loaded without issue - string = "\("mi_php_version".localized) \(App.shared.currentVersion!.long)" - self.addItem(NSMenuItem(title: string, action: nil, keyEquivalent: "")) - } else { - // in case of an error show the error message - ["mi_php_broken_1", "mi_php_broken_2", - "mi_php_broken_3", "mi_php_broken_4"].forEach { (message) in - self.addItem(NSMenuItem(title: message.localized, action: nil, keyEquivalent: "")) - } + if (App.shared.currentInstall == nil) { + return + } + + if (!App.phpInstall!.version.error) { + // in case the php version loaded without issue + let string = "\("mi_php_version".localized) \(App.phpInstall!.version.long)" + self.addItem(NSMenuItem(title: string, action: nil, keyEquivalent: "")) + } else { + // in case of an error show the error message + ["mi_php_broken_1", "mi_php_broken_2", + "mi_php_broken_3", "mi_php_broken_4"].forEach { (message) in + self.addItem(NSMenuItem(title: message.localized, action: nil, keyEquivalent: "")) } } } public func addPhpActionMenuItems() { - if (App.shared.availablePhpVersions.count > 0 && !App.shared.busy) { - var shortcutKey = 1 - for index in (0.. Void, _ completion: @escaping () -> Void = {}) @@ -159,16 +158,16 @@ class MainMenu: NSObject, NSWindowDelegate { // MARK: - User Interface @objc func updatePhpVersionInStatusBar() { - App.shared.currentVersion = PhpVersion() - if (App.shared.busy) { - DispatchQueue.main.async { + App.shared.currentInstall = PhpInstall() + + DispatchQueue.main.async { + if (App.shared.busy) { self.setStatusBar(image: NSImage(named: NSImage.Name("StatusBarIcon"))!) - } - } else { - DispatchQueue.main.async { - self.setStatusBarImage(version: App.shared.currentVersion!.short) + } else { + self.setStatusBarImage(version: App.phpInstall!.version.short) } } + self.update() } @@ -223,28 +222,26 @@ class MainMenu: NSObject, NSWindowDelegate { @objc public func forceRestartLatestPhp() { // Tell the user the switch is about to occur - _ = Alert.present( - messageText: "alert.force_reload.title".localized, - informativeText: "alert.force_reload.info".localized - ) + Alert.notify(message: "alert.force_reload.title".localized, info: "alert.force_reload.info".localized) // Start switching - self.waitAndExecute({ Actions.fixMyPhp() }, { - _ = Alert.present( - messageText: "alert.force_reload_done.title".localized, - informativeText: "alert.force_reload_done.info".localized - ) - }) + self.waitAndExecute( + { Actions.fixMyPhp() }, + { Alert.notify( + message: "alert.force_reload_done.title".localized, + info: "alert.force_reload_done.info".localized + ) } + ) } @objc public func openActiveConfigFolder() { - if (App.shared.currentVersion!.error) { + if (App.phpInstall!.version.error) { // php version was not identified Actions.openGenericPhpConfigFolder() - } else { - // php version was identified - Actions.openPhpConfigFolder(version: App.shared.currentVersion!.short) + return } + // php version was identified + Actions.openPhpConfigFolder(version: App.phpInstall!.version.short) } @objc public func openValetConfigFolder() { @@ -253,20 +250,26 @@ class MainMenu: NSObject, NSWindowDelegate { @objc public func switchToPhpVersion(sender: PhpMenuItem) { print("Switching to: PHP \(sender.version)") + self.setBusyImage() App.shared.busy = true + DispatchQueue.global(qos: .userInitiated).async { [unowned self] in // Update the PHP version in the status bar self.updatePhpVersionInStatusBar() + // Update the menu self.update() + // Switch the PHP version Actions.switchToPhpVersion( version: sender.version, availableVersions: App.shared.availablePhpVersions ) + // Mark as no longer busy App.shared.busy = false + // Perform UI updates on main thread DispatchQueue.main.async { self.updatePhpVersionInStatusBar()