diff --git a/PHP Monitor.xcodeproj/project.pbxproj b/PHP Monitor.xcodeproj/project.pbxproj index 824f5e43..d5f1c211 100644 --- a/PHP Monitor.xcodeproj/project.pbxproj +++ b/PHP Monitor.xcodeproj/project.pbxproj @@ -117,6 +117,7 @@ C44CCD4127AFE2FC00CE40E5 /* AlertableError.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44CCD3F27AFE2FC00CE40E5 /* AlertableError.swift */; }; C44CCD4927AFF3B700CE40E5 /* MainMenu+Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44CCD4827AFF3B700CE40E5 /* MainMenu+Async.swift */; }; C44CCD4A27AFF3BC00CE40E5 /* MainMenu+Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44CCD4827AFF3B700CE40E5 /* MainMenu+Async.swift */; }; + C44F868E2835BD8D005C353A /* phpmon-config.json in Resources */ = {isa = PBXBuildFile; fileRef = C44F868D2835BD8D005C353A /* phpmon-config.json */; }; C459B4BD27F6093700E9B4B4 /* nginx-proxy.test in Resources */ = {isa = PBXBuildFile; fileRef = C459B4BC27F6093700E9B4B4 /* nginx-proxy.test */; }; C464ADAC275A7A3F003FCD53 /* DomainListWC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C464ADAB275A7A3F003FCD53 /* DomainListWC.swift */; }; C464ADAD275A7A3F003FCD53 /* DomainListWC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C464ADAB275A7A3F003FCD53 /* DomainListWC.swift */; }; @@ -265,6 +266,7 @@ C4F780CE25D80B75000DBC97 /* LocalNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = C474B00524C0E98C00066A22 /* LocalNotification.swift */; }; C4F8C0A422D4F12C002EFE61 /* DateExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8C0A322D4F12C002EFE61 /* DateExtension.swift */; }; C4FBFC532616485F00CDB8E1 /* PhpVersionDetectionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4FBFC512616485F00CDB8E1 /* PhpVersionDetectionTest.swift */; }; + C4FC21B128391F8E00D368BB /* MainMenu+Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F361602836BFD9003598CC /* MainMenu+Actions.swift */; }; C4FE011128084FC200D1DE6D /* SelectionVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4FE011028084FC200D1DE6D /* SelectionVC.swift */; }; C4FE011228084FC200D1DE6D /* SelectionVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4FE011028084FC200D1DE6D /* SelectionVC.swift */; }; /* End PBXBuildFile section */ @@ -350,6 +352,7 @@ C44C1990276E44CB0072762D /* ProgressWindow.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = ProgressWindow.storyboard; sourceTree = ""; }; C44CCD3F27AFE2FC00CE40E5 /* AlertableError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertableError.swift; sourceTree = ""; }; C44CCD4827AFF3B700CE40E5 /* MainMenu+Async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainMenu+Async.swift"; sourceTree = ""; }; + C44F868D2835BD8D005C353A /* phpmon-config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "phpmon-config.json"; sourceTree = ""; }; C459B4BC27F6093700E9B4B4 /* nginx-proxy.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-proxy.test"; sourceTree = ""; }; C464ADAB275A7A3F003FCD53 /* DomainListWC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainListWC.swift; sourceTree = ""; }; C464ADAE275A7A69003FCD53 /* DomainListVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainListVC.swift; sourceTree = ""; }; @@ -551,6 +554,7 @@ C40C7F1C27720E1400DDDCDC /* Test Files */ = { isa = PBXGroup; children = ( + C44F868C2835BD60005C353A /* phpmon */, C459B4C127F6097E00E9B4B4 /* php */, C459B4C027F6096300E9B4B4 /* valet */, C459B4BF27F6094100E9B4B4 /* brew */, @@ -680,6 +684,14 @@ path = Errors; sourceTree = ""; }; + C44F868C2835BD60005C353A /* phpmon */ = { + isa = PBXGroup; + children = ( + C44F868D2835BD8D005C353A /* phpmon-config.json */, + ); + path = phpmon; + sourceTree = ""; + }; C459B4BE27F6093A00E9B4B4 /* nginx */ = { isa = PBXGroup; children = ( @@ -1120,6 +1132,7 @@ C42CFB1827DFDFDC00862737 /* nginx-site-isolated.test in Resources */, C4F780A825D80AE8000DBC97 /* php.ini in Resources */, C4068CA527B0780A00544CD5 /* CheckboxPreferenceView.xib in Resources */, + C44F868E2835BD8D005C353A /* phpmon-config.json in Resources */, C43A8A2025D9D1D700591B77 /* brew-formula.json in Resources */, C4AF9F72275445FF00D44ED0 /* valet-config.json in Resources */, C44C1992276E44CB0072762D /* ProgressWindow.storyboard in Resources */, @@ -1322,6 +1335,7 @@ C4F2E4382752F08D0020E974 /* HomebrewDiagnostics.swift in Sources */, C4F780AE25D80B37000DBC97 /* PhpExtensionTest.swift in Sources */, C4C8E819276F54D8003AC782 /* App+ConfigWatch.swift in Sources */, + C4FC21B128391F8E00D368BB /* MainMenu+Actions.swift in Sources */, 54D9E0B927E4F51E003B9AD9 /* KeyCombo.swift in Sources */, C4EED88A27A48778006D7272 /* InterAppHandler.swift in Sources */, C48D6C75279CD3E400F26D7E /* PhpVersionNumberTest.swift in Sources */, @@ -1548,7 +1562,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 795; + CURRENT_PROJECT_VERSION = 800; DEBUG = YES; DEVELOPMENT_TEAM = 8M54J5J787; ENABLE_HARDENED_RUNTIME = YES; @@ -1574,7 +1588,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 795; + CURRENT_PROJECT_VERSION = 800; DEBUG = NO; DEVELOPMENT_TEAM = 8M54J5J787; ENABLE_HARDENED_RUNTIME = YES; diff --git a/phpmon-tests/Test Files/phpmon/phpmon-config.json b/phpmon-tests/Test Files/phpmon/phpmon-config.json new file mode 100644 index 00000000..628d85ee --- /dev/null +++ b/phpmon-tests/Test Files/phpmon/phpmon-config.json @@ -0,0 +1,34 @@ +{ + "scan_apps": [], + "presets": [ + { + "name": "Default PHP", + "extensions": { + "xdebug": false + }, + "configuration": { + "memory_limit": "128M" + } + }, + { + "name": "Personal Site", + "extensions": { + "xdebug": true + }, + "configuration": { + "xdebug.mode": "coverage", + "memory_limit": "512M" + } + }, + { + "name": "PHP Monitor", + "extensions": { + "xdebug": true + }, + "configuration": { + "xdebug.mode": "coverage", + "memory_limit": "512M" + } + } + ] +} diff --git a/phpmon/Common/Extensions/NSMenuExtension.swift b/phpmon/Common/Extensions/NSMenuExtension.swift index eeed88d2..93b90c69 100644 --- a/phpmon/Common/Extensions/NSMenuExtension.swift +++ b/phpmon/Common/Extensions/NSMenuExtension.swift @@ -27,3 +27,25 @@ extension NSMenu { } } + +// MARK: - NSMenuItem subclasses + +class PhpMenuItem: NSMenuItem { + var version: String = "" +} + +class XdebugMenuItem: NSMenuItem { + var mode: String = "" +} + +class ExtensionMenuItem: NSMenuItem { + var phpExtension: PhpExtension? +} + +class EditorMenuItem: NSMenuItem { + var editor: Application? +} + +class PresetMenuItem: NSMenuItem { + var preset: CustomPrefs.Preset? +} diff --git a/phpmon/Domain/Menu/MainMenu+Actions.swift b/phpmon/Domain/Menu/MainMenu+Actions.swift index e64cc7ed..390c1c94 100644 --- a/phpmon/Domain/Menu/MainMenu+Actions.swift +++ b/phpmon/Domain/Menu/MainMenu+Actions.swift @@ -145,6 +145,12 @@ extension MainMenu { } } + @objc func togglePreset(sender: PresetMenuItem) { + asyncExecution { + dump(sender.preset) + } + } + @objc func openPhpInfo() { var url: URL? diff --git a/phpmon/Domain/Menu/StatusMenu.swift b/phpmon/Domain/Menu/StatusMenu.swift index 333b14f3..9880b6c3 100644 --- a/phpmon/Domain/Menu/StatusMenu.swift +++ b/phpmon/Domain/Menu/StatusMenu.swift @@ -69,6 +69,7 @@ class StatusMenu: NSMenu { self.addItem(NSMenuItem.separator()) self.addXdebugMenuItem() + self.addPresetsMenuItem() self.addFirstAidAndServicesMenuItems() } @@ -140,6 +141,43 @@ class StatusMenu: NSMenu { } } + func addPresetsMenuItem() { + if Preferences.custom.presets.isEmpty { + return + } + + let presets = NSMenuItem(title: "Configuration Presets", action: nil, keyEquivalent: "") + let presetsMenu = NSMenu() + presetsMenu.addItem(NSMenuItem.separator()) + presetsMenu.addItem(HeaderView.asMenuItem(text: "Apply Configuration Presets")) + + for preset in Preferences.custom.presets { + let presetMenuItem = PresetMenuItem( + title: "\(preset.name) (\(preset.extensions.count) extension, \(preset.configuration.count) prefs)", + action: #selector(MainMenu.togglePreset(sender:)), + keyEquivalent: "" + ) + presetMenuItem.preset = preset + presetsMenu.addItem(presetMenuItem) + } + + presetsMenu.addItem(NSMenuItem.separator()) + presetsMenu.addItem(NSMenuItem( + title: "Revert to Previous Configuration...", + action: #selector(MainMenu.restartDnsMasq), keyEquivalent: "") + ) + presetsMenu.addItem(NSMenuItem.separator()) + presetsMenu.addItem(NSMenuItem( + title: "\(Preferences.custom.presets.count) profiles loaded from configuration file", + action: nil, keyEquivalent: "") + ) + for item in presetsMenu.items { + item.target = MainMenu.shared + } + self.setSubmenu(presetsMenu, for: presets) + self.addItem(presets) + } + func addXdebugMenuItem() { if !Xdebug.enabled { return @@ -289,21 +327,3 @@ class StatusMenu: NSMenu { self.addItem(menuItem) } } - -// MARK: - NSMenuItem subclasses - -class PhpMenuItem: NSMenuItem { - var version: String = "" -} - -class XdebugMenuItem: NSMenuItem { - var mode: String = "" -} - -class ExtensionMenuItem: NSMenuItem { - var phpExtension: PhpExtension? -} - -class EditorMenuItem: NSMenuItem { - var editor: Application? -} diff --git a/phpmon/Domain/Preferences/CustomPrefs.swift b/phpmon/Domain/Preferences/CustomPrefs.swift index e095ad43..4a5f47c1 100644 --- a/phpmon/Domain/Preferences/CustomPrefs.swift +++ b/phpmon/Domain/Preferences/CustomPrefs.swift @@ -10,8 +10,16 @@ import Foundation struct CustomPrefs: Decodable { let scanApps: [String] + let presets: [Preset] private enum CodingKeys: String, CodingKey { case scanApps = "scan_apps" + case presets = "presets" + } + + struct Preset: Decodable { + let name: String + let extensions: [String: Bool] + let configuration: [String: String?] } } diff --git a/phpmon/Domain/Preferences/Preferences.swift b/phpmon/Domain/Preferences/Preferences.swift index 96b7937b..196b062c 100644 --- a/phpmon/Domain/Preferences/Preferences.swift +++ b/phpmon/Domain/Preferences/Preferences.swift @@ -52,7 +52,7 @@ class Preferences { public init() { Preferences.handleFirstTimeLaunch() cachedPreferences = Self.cache() - customPreferences = CustomPrefs(scanApps: []) + customPreferences = CustomPrefs(scanApps: [], presets: []) loadCustomPreferences() } @@ -188,7 +188,9 @@ class Preferences { CustomPrefs.self, from: try! String(contentsOf: url, encoding: .utf8).data(using: .utf8)! ) + Log.info("The .phpmon.conf.json file was successfully parsed.") + Log.info("There are \(customPreferences.presets.count) custom presets.") } catch { Log.warn("The .phpmon.conf.json file seems to be missing or malformed.") }