diff --git a/PHP Monitor.xcodeproj/project.pbxproj b/PHP Monitor.xcodeproj/project.pbxproj index 4afdae5..33e21a8 100644 --- a/PHP Monitor.xcodeproj/project.pbxproj +++ b/PHP Monitor.xcodeproj/project.pbxproj @@ -147,6 +147,13 @@ C4F2E4382752F08D0020E974 /* HomebrewDiagnostics.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F2E4362752F0870020E974 /* HomebrewDiagnostics.swift */; }; C4F2E43A2752F7D00020E974 /* PhpInstallation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F2E4392752F7D00020E974 /* PhpInstallation.swift */; }; C4F2E43B27530F750020E974 /* PhpInstallation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F2E4392752F7D00020E974 /* PhpInstallation.swift */; }; + C4F30B03278E16BA00755FCE /* HomebrewService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F30B02278E16BA00755FCE /* HomebrewService.swift */; }; + C4F30B04278E16BA00755FCE /* HomebrewService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F30B02278E16BA00755FCE /* HomebrewService.swift */; }; + C4F30B05278E16BA00755FCE /* HomebrewService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F30B02278E16BA00755FCE /* HomebrewService.swift */; }; + C4F30B07278E195800755FCE /* brew-services.json in Resources */ = {isa = PBXBuildFile; fileRef = C4F30B06278E195800755FCE /* brew-services.json */; }; + C4F30B08278E195800755FCE /* brew-services.json in Resources */ = {isa = PBXBuildFile; fileRef = C4F30B06278E195800755FCE /* brew-services.json */; }; + C4F30B09278E1A0E00755FCE /* CustomPrefs.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C3ED4227834C5200AB15D8 /* CustomPrefs.swift */; }; + C4F30B0A278E1A1A00755FCE /* ComposerJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D89BC52783C99400A02B68 /* ComposerJson.swift */; }; C4F7809C25D80344000DBC97 /* CommandTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F7809B25D80344000DBC97 /* CommandTest.swift */; }; C4F780A825D80AE8000DBC97 /* php.ini in Resources */ = {isa = PBXBuildFile; fileRef = C4F780A725D80AE8000DBC97 /* php.ini */; }; C4F780AE25D80B37000DBC97 /* ExtensionParserTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F780AD25D80B37000DBC97 /* ExtensionParserTest.swift */; }; @@ -280,6 +287,8 @@ C4EE55A827708B9E001DF387 /* PMStatsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PMStatsView.swift; sourceTree = ""; }; C4F2E4362752F0870020E974 /* HomebrewDiagnostics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomebrewDiagnostics.swift; sourceTree = ""; }; C4F2E4392752F7D00020E974 /* PhpInstallation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpInstallation.swift; sourceTree = ""; }; + C4F30B02278E16BA00755FCE /* HomebrewService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomebrewService.swift; sourceTree = ""; }; + C4F30B06278E195800755FCE /* brew-services.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "brew-services.json"; sourceTree = ""; }; C4F7807425D7F7E5000DBC97 /* RELEASE.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = RELEASE.md; sourceTree = ""; }; C4F7807925D7F84B000DBC97 /* phpmon-tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "phpmon-tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; C4F7807D25D7F84B000DBC97 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -333,9 +342,9 @@ 54B20EDF263AA22C00D3250E /* PHP */ = { isa = PBXGroup; children = ( - C40C7F1D2772136000DDDCDC /* PhpEnv.swift */, C4D9ADC2277610E4007277F4 /* Switcher */, - C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */, + C4F30B01278E169B00755FCE /* Homebrew */, + C40C7F1D2772136000DDDCDC /* PhpEnv.swift */, C41C1B4A22B019FF00E7CF16 /* ActivePhpInstallation.swift */, C4F2E4392752F7D00020E974 /* PhpInstallation.swift */, C4ACA38E25C754C100060C66 /* PhpExtension.swift */, @@ -368,6 +377,7 @@ children = ( C4AF9F70275445FF00D44ED0 /* valet-config.json */, C43A8A1F25D9D1D700591B77 /* brew.json */, + C4F30B06278E195800755FCE /* brew-services.json */, C4F780A725D80AE8000DBC97 /* php.ini */, ); path = "Test Files"; @@ -614,6 +624,15 @@ path = SwiftUI; sourceTree = ""; }; + C4F30B01278E169B00755FCE /* Homebrew */ = { + isa = PBXGroup; + children = ( + C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */, + C4F30B02278E16BA00755FCE /* HomebrewService.swift */, + ); + path = Homebrew; + sourceTree = ""; + }; C4F7807A25D7F84B000DBC97 /* phpmon-tests */ = { isa = PBXGroup; children = ( @@ -759,6 +778,7 @@ C4232EE52612526500158FC6 /* Credits.html in Resources */, 54FCFD26276C883F004CE748 /* CheckboxPreferenceView.xib in Resources */, C473319F2470923A009A0597 /* Localizable.strings in Resources */, + C4F30B07278E195800755FCE /* brew-services.json in Resources */, 54FCFD2D276C8D67004CE748 /* HotkeyPreferenceView.xib in Resources */, C405A4D024B9B9140062FAFA /* InternetAccessPolicy.strings in Resources */, C48D0C9A25CC888B00CC7490 /* HeaderView.xib in Resources */, @@ -775,6 +795,7 @@ C43A8A2025D9D1D700591B77 /* brew.json in Resources */, C4AF9F72275445FF00D44ED0 /* valet-config.json in Resources */, C44C1992276E44CB0072762D /* ProgressWindow.storyboard in Resources */, + C4F30B08278E195800755FCE /* brew-services.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -792,6 +813,7 @@ C40C7F2227721F8200DDDCDC /* PhpInstallation.swift in Sources */, C4B585432770FE3900DA4FBE /* Shell.swift in Sources */, C4D9ADC1277610E1007277F4 /* PhpSwitcher.swift in Sources */, + C4F30B05278E16BA00755FCE /* HomebrewService.swift in Sources */, C40C7F2327721F8200DDDCDC /* ActivePhpInstallation.swift in Sources */, C4B585462770FE3900DA4FBE /* Command.swift in Sources */, C4D9ADCA277611A0007277F4 /* InternalSwitcher.swift in Sources */, @@ -836,6 +858,7 @@ C4B97B78275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */, C4811D2422D70A4700B5F6B3 /* App.swift in Sources */, C41C1B4922B00A9800E7CF16 /* MenuBarImageGenerator.swift in Sources */, + C4F30B03278E16BA00755FCE /* HomebrewService.swift in Sources */, 5420395F2613607600FB00FA /* Preferences.swift in Sources */, C48D0C9325CC804200CC7490 /* XibLoadable.swift in Sources */, 54FCFD2A276C8AA4004CE748 /* CheckboxPreferenceView.swift in Sources */, @@ -895,6 +918,7 @@ C43A8A2425D9D20D00591B77 /* BrewJsonParserTest.swift in Sources */, C4F780CA25D80B75000DBC97 /* HomebrewPackage.swift in Sources */, C4C8E81C276F54E5003AC782 /* PhpConfigWatcher.swift in Sources */, + C4F30B04278E16BA00755FCE /* HomebrewService.swift in Sources */, C4AF9F7B2754499000D44ED0 /* Valet.swift in Sources */, C4F780C025D80B6E000DBC97 /* Startup.swift in Sources */, C4CCBA6D275C567B008C7055 /* PMWindowController.swift in Sources */, @@ -910,6 +934,7 @@ C481F79726164A78004FBCFF /* PrefsVC.swift in Sources */, C41E871B2763D42300161EE0 /* SiteListVC+ContextMenu.swift in Sources */, C40C7F3127722E8D00DDDCDC /* Logger.swift in Sources */, + C4F30B09278E1A0E00755FCE /* CustomPrefs.swift in Sources */, C464ADB3275A87CA003FCD53 /* SiteListCell.swift in Sources */, C415D3E92770F692005EF286 /* AppDelegate+InterApp.swift in Sources */, C4AF9F78275447F100D44ED0 /* ValetConfigParserTest.swift in Sources */, @@ -925,6 +950,7 @@ C4F780C325D80B75000DBC97 /* HeaderView.swift in Sources */, C44C198E276E3A1C0072762D /* ProgressWindow.swift in Sources */, C4D9ADC9277611A0007277F4 /* InternalSwitcher.swift in Sources */, + C4F30B0A278E1A1A00755FCE /* ComposerJson.swift in Sources */, C4AF9F7D275454A900D44ED0 /* ValetTest.swift in Sources */, C4B56362276AB0A500F12CCB /* VersionExtractorTest.swift in Sources */, C4B585452770FE3900DA4FBE /* Command.swift in Sources */, @@ -1120,7 +1146,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 220; + CURRENT_PROJECT_VERSION = 230; DEVELOPMENT_TEAM = 8M54J5J787; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = phpmon/Info.plist; @@ -1145,7 +1171,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 220; + CURRENT_PROJECT_VERSION = 230; DEVELOPMENT_TEAM = 8M54J5J787; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = phpmon/Info.plist; diff --git a/phpmon-common/PHP/HomebrewPackage.swift b/phpmon-common/PHP/Homebrew/HomebrewPackage.swift similarity index 100% rename from phpmon-common/PHP/HomebrewPackage.swift rename to phpmon-common/PHP/Homebrew/HomebrewPackage.swift diff --git a/phpmon-common/PHP/Homebrew/HomebrewService.swift b/phpmon-common/PHP/Homebrew/HomebrewService.swift new file mode 100644 index 0000000..1d92861 --- /dev/null +++ b/phpmon-common/PHP/Homebrew/HomebrewService.swift @@ -0,0 +1,21 @@ +// +// HomebrewService.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 11/01/2022. +// Copyright © 2022 Nico Verbruggen. All rights reserved. +// + +import Foundation + +struct HomebrewService: Decodable { + let name: String + let service_name: String + let running: Bool + let loaded: Bool + let pid: Int? + let user: String? + let status: String? + let log_path: String? + let error_log_path: String? +} diff --git a/phpmon-tests/BrewJsonParserTest.swift b/phpmon-tests/BrewJsonParserTest.swift index a91cbee..7db5889 100644 --- a/phpmon-tests/BrewJsonParserTest.swift +++ b/phpmon-tests/BrewJsonParserTest.swift @@ -15,9 +15,9 @@ class BrewJsonParserTest: XCTestCase { } func testCanLoadExtension() throws { - let json = try? String(contentsOf: Self.jsonBrewFile, encoding: .utf8) + let json = try! String(contentsOf: Self.jsonBrewFile, encoding: .utf8) let package = try! JSONDecoder().decode( - [HomebrewPackage].self, from: json!.data(using: .utf8)! + [HomebrewPackage].self, from: json.data(using: .utf8)! ).first! XCTAssertEqual(package.name, "php") @@ -27,5 +27,20 @@ class BrewJsonParserTest: XCTestCase { installed.version.starts(with: "8.0") }), true) } + + static var jsonBrewServicesFile: URL { + return Bundle(for: Self.self).url(forResource: "brew-services", withExtension: "json")! + } + + func testCanParseServicesJson() throws { + let json = try! String(contentsOf: Self.jsonBrewServicesFile, encoding: .utf8) + let services = try! JSONDecoder().decode( + [HomebrewService].self, from: json.data(using: .utf8)! + ) + + XCTAssertGreaterThan(services.count, 0) + XCTAssertEqual(services.first?.name, "dnsmasq") + XCTAssertEqual(services.first?.service_name, "homebrew.mxcl.dnsmasq") + } } diff --git a/phpmon-tests/PhpVersionDetectionTest.swift b/phpmon-tests/PhpVersionDetectionTest.swift index 660e128..8585680 100644 --- a/phpmon-tests/PhpVersionDetectionTest.swift +++ b/phpmon-tests/PhpVersionDetectionTest.swift @@ -11,7 +11,7 @@ import XCTest class PhpVersionDetectionTest: XCTestCase { func testCanDetectValidPhpVersions() throws { - let outcome = Actions.extractPhpVersions(from: [ + let outcome = PhpEnv.shared.extractPhpVersions(from: [ "", // empty lines should be omitted "php@8.0", "php@8.0", // should only be detected once diff --git a/phpmon-tests/Test Files/brew-services.json b/phpmon-tests/Test Files/brew-services.json new file mode 100644 index 0000000..52dc263 --- /dev/null +++ b/phpmon-tests/Test Files/brew-services.json @@ -0,0 +1,135 @@ +[ + { + "name": "dnsmasq", + "service_name": "homebrew.mxcl.dnsmasq", + "running": true, + "loaded": true, + "schedulable": false, + "pid": 106, + "exit_code": 0, + "user": "root", + "status": "started", + "file": "/Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist", + "command": "/opt/homebrew/opt/dnsmasq/sbin/dnsmasq --keep-in-foreground -C /opt/homebrew/etc/dnsmasq.conf -7 /opt/homebrew/etc/dnsmasq.d,*.conf", + "working_dir": null, + "root_dir": null, + "log_path": null, + "error_log_path": null, + "interval": null, + "cron": null + }, + { + "name": "httpd", + "service_name": "homebrew.mxcl.httpd", + "running": false, + "loaded": false, + "schedulable": false, + "pid": null, + "exit_code": null, + "user": null, + "status": "none", + "file": "/opt/homebrew/opt/httpd/homebrew.mxcl.httpd.plist", + "command": "/opt/homebrew/opt/httpd/bin/httpd -D FOREGROUND", + "working_dir": null, + "root_dir": null, + "log_path": null, + "error_log_path": null, + "interval": null, + "cron": null + }, + { + "name": "mailhog", + "service_name": "homebrew.mxcl.mailhog", + "running": false, + "loaded": false, + "schedulable": false, + "pid": null, + "exit_code": null, + "user": null, + "status": "none", + "file": "/opt/homebrew/opt/mailhog/homebrew.mxcl.mailhog.plist", + "command": "/opt/homebrew/opt/mailhog/bin/MailHog", + "working_dir": null, + "root_dir": null, + "log_path": "/opt/homebrew/var/log/mailhog.log", + "error_log_path": "/opt/homebrew/var/log/mailhog.log", + "interval": null, + "cron": null + }, + { + "name": "nginx", + "service_name": "homebrew.mxcl.nginx", + "running": true, + "loaded": true, + "schedulable": false, + "pid": 116, + "exit_code": 0, + "user": "root", + "status": "started", + "file": "/Library/LaunchDaemons/homebrew.mxcl.nginx.plist", + "command": "/opt/homebrew/opt/nginx/bin/nginx -g daemon off;", + "working_dir": "/opt/homebrew", + "root_dir": null, + "log_path": null, + "error_log_path": null, + "interval": null, + "cron": null + }, + { + "name": "php", + "service_name": "homebrew.mxcl.php", + "running": true, + "loaded": true, + "schedulable": false, + "pid": 142, + "exit_code": 0, + "user": "root", + "status": "started", + "file": "/Library/LaunchDaemons/homebrew.mxcl.php.plist", + "command": "/opt/homebrew/opt/php/sbin/php-fpm --nodaemonize", + "working_dir": "/opt/homebrew/var", + "root_dir": null, + "log_path": null, + "error_log_path": "/opt/homebrew/var/log/php-fpm.log", + "interval": null, + "cron": null + }, + { + "name": "php@8.0", + "service_name": "homebrew.mxcl.php@8.0", + "running": false, + "loaded": false, + "schedulable": false, + "pid": null, + "exit_code": null, + "user": null, + "status": "none", + "file": "/opt/homebrew/opt/php@8.0/homebrew.mxcl.php@8.0.plist", + "command": "/opt/homebrew/opt/php@8.0/sbin/php-fpm --nodaemonize", + "working_dir": "/opt/homebrew/var", + "root_dir": null, + "log_path": null, + "error_log_path": "/opt/homebrew/var/log/php-fpm.log", + "interval": null, + "cron": null + }, + { + "name": "unbound", + "service_name": "homebrew.mxcl.unbound", + "running": false, + "loaded": false, + "schedulable": false, + "pid": null, + "exit_code": null, + "user": null, + "status": "none", + "file": "/opt/homebrew/opt/unbound/homebrew.mxcl.unbound.plist", + "command": "/opt/homebrew/opt/unbound/sbin/unbound -d -c /opt/homebrew/etc/unbound/unbound.conf", + "working_dir": null, + "root_dir": null, + "log_path": null, + "error_log_path": null, + "interval": null, + "cron": null + } +] diff --git a/phpmon-tests/ValetTest.swift b/phpmon-tests/ValetTest.swift index 6d5b31d..b7713c4 100644 --- a/phpmon-tests/ValetTest.swift +++ b/phpmon-tests/ValetTest.swift @@ -11,7 +11,7 @@ import XCTest class ValetTest: XCTestCase { func testDetermineValetVersion() { - let version = Actions.valet("--version") + let version = valet("--version") XCTAssert(version.contains("Laravel Valet 2.")) } diff --git a/phpmon/Domain/Core/AppDelegate.swift b/phpmon/Domain/Core/AppDelegate.swift index 3183636..a8e3c2e 100644 --- a/phpmon/Domain/Core/AppDelegate.swift +++ b/phpmon/Domain/Core/AppDelegate.swift @@ -88,7 +88,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele // Make sure notifications will work setupNotifications() // Make sure the menu performs its initial checks - menu.startup() + menu.rebuild() } }