diff --git a/PHP Monitor.xcodeproj/project.pbxproj b/PHP Monitor.xcodeproj/project.pbxproj index 43876ce..3f14729 100644 --- a/PHP Monitor.xcodeproj/project.pbxproj +++ b/PHP Monitor.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ C41C1B4922B00A9800E7CF16 /* MenuBarImageGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4822B00A9800E7CF16 /* MenuBarImageGenerator.swift */; }; C41C1B4B22B019FF00E7CF16 /* PhpVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4A22B019FF00E7CF16 /* PhpVersion.swift */; }; C41C1B4D22B0215A00E7CF16 /* Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4C22B0215A00E7CF16 /* Actions.swift */; }; + C42295DD2358D02000E263B2 /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42295DC2358D02000E263B2 /* Command.swift */; }; C476FF9822B0DD830098105B /* Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = C476FF9722B0DD830098105B /* Alert.swift */; }; C4811D2422D70A4700B5F6B3 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4811D2322D70A4700B5F6B3 /* App.swift */; }; C4811D2A22D70F9A00B5F6B3 /* MainMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4811D2922D70F9A00B5F6B3 /* MainMenu.swift */; }; @@ -35,6 +36,7 @@ C41C1B4822B00A9800E7CF16 /* MenuBarImageGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuBarImageGenerator.swift; sourceTree = ""; }; C41C1B4A22B019FF00E7CF16 /* PhpVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpVersion.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 = ""; }; C476FF9722B0DD830098105B /* Alert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Alert.swift; sourceTree = ""; }; C4811D2322D70A4700B5F6B3 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; C4811D2922D70F9A00B5F6B3 /* MainMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainMenu.swift; sourceTree = ""; }; @@ -112,6 +114,7 @@ C41C1B4622B009A400E7CF16 /* Shell.swift */, C4811D2322D70A4700B5F6B3 /* App.swift */, C4811D2922D70F9A00B5F6B3 /* MainMenu.swift */, + C42295DC2358D02000E263B2 /* Command.swift */, ); path = Singletons; sourceTree = ""; @@ -170,7 +173,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1020; - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1110; ORGANIZATIONNAME = "Nico Verbruggen"; TargetAttributes = { C41C1B3222B0097F00E7CF16 = { @@ -217,6 +220,7 @@ C4F8C0A422D4F12C002EFE61 /* DateExtension.swift in Sources */, C41C1B4722B009A400E7CF16 /* Shell.swift in Sources */, C41C1B4D22B0215A00E7CF16 /* Actions.swift in Sources */, + C42295DD2358D02000E263B2 /* Command.swift in Sources */, C4811D2422D70A4700B5F6B3 /* App.swift in Sources */, C41C1B4922B00A9800E7CF16 /* MenuBarImageGenerator.swift in Sources */, C4811D2A22D70F9A00B5F6B3 /* MainMenu.swift in Sources */, @@ -362,15 +366,17 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = phpmon/phpmon.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 12; + CURRENT_PROJECT_VERSION = 15; DEVELOPMENT_TEAM = 8M54J5J787; INFOPLIST_FILE = phpmon/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); + MARKETING_VERSION = 1.5; PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; @@ -382,15 +388,17 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = phpmon/phpmon.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 12; + CURRENT_PROJECT_VERSION = 15; DEVELOPMENT_TEAM = 8M54J5J787; INFOPLIST_FILE = phpmon/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); + MARKETING_VERSION = 1.5; PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; diff --git a/phpmon/Classes/Commands/Actions.swift b/phpmon/Classes/Commands/Actions.swift index bcc2a62..87e54b4 100644 --- a/phpmon/Classes/Commands/Actions.swift +++ b/phpmon/Classes/Commands/Actions.swift @@ -42,6 +42,35 @@ class Actions { public static func openPhpConfigFolder(version: String) { let files = [NSURL(fileURLWithPath: "/usr/local/etc/php/\(version)/php.ini")]; - NSWorkspace.shared.activateFileViewerSelecting(files as [URL]); + NSWorkspace.shared.activateFileViewerSelecting(files as [URL]) + } + + public static func XdebugFound(_ version: String) -> Bool { + let command = """ + grep -q 'zend_extension="xdebug.so"' /usr/local/etc/php/\(version)/php.ini; [ $? -eq 0 ] && echo "YES" || echo "NO" + """ + let output = Shell.user.pipe(command).trimmingCharacters(in: .whitespacesAndNewlines) + return (output == "YES") + } + + public static func XdebugEnabled(_ version: String) -> Bool { + let command = """ + grep -q '; zend_extension="xdebug.so"' /usr/local/etc/php/\(version)/php.ini; [ $? -eq 0 ] && echo "YES" || echo "NO" + """ + let output = Shell.user.pipe(command).trimmingCharacters(in: .whitespacesAndNewlines) + return (output == "NO") + } + + public static func toggleXdebug() { + let version = App.shared.currentVersion?.short + var command = """ + sed -i '' 's/; zend_extension="xdebug.so"/zend_extension="xdebug.so"/g' /usr/local/etc/php/\(version!)/php.ini + """ + if (self.XdebugEnabled(version!)) { + command = """ + sed -i '' 's/zend_extension="xdebug.so"/; zend_extension="xdebug.so"/g' /usr/local/etc/php/\(version!)/php.ini + """ + } + Shell.user.run(command) } } diff --git a/phpmon/Classes/Helpers/PhpVersion.swift b/phpmon/Classes/Helpers/PhpVersion.swift index 3ecda9c..bd42ca9 100644 --- a/phpmon/Classes/Helpers/PhpVersion.swift +++ b/phpmon/Classes/Helpers/PhpVersion.swift @@ -13,6 +13,9 @@ class PhpVersion { var short : String = "???" var long : String = "???" + var xdebugFound: Bool = false + var xdebugEnabled : Bool = false + init() { let version = Shell.user // Get the version directly from PHP @@ -23,7 +26,14 @@ class PhpVersion { // 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.XdebugFound(self.short) + if (self.xdebugFound) { + self.xdebugEnabled = Actions.XdebugEnabled(self.short) + } } } diff --git a/phpmon/Info.plist b/phpmon/Info.plist index e505c2a..556ab4e 100644 --- a/phpmon/Info.plist +++ b/phpmon/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.4 + $(MARKETING_VERSION) CFBundleVersion $(CURRENT_PROJECT_VERSION) LSApplicationCategoryType diff --git a/phpmon/Singletons/Command.swift b/phpmon/Singletons/Command.swift new file mode 100644 index 0000000..7c1e4d6 --- /dev/null +++ b/phpmon/Singletons/Command.swift @@ -0,0 +1,50 @@ +// +// Command.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 17/10/2019. +// Copyright © 2019 Nico Verbruggen. All rights reserved. +// + +import Cocoa + +class Command { + + public static func execute(path: String, arguments: [String]) -> String { + let task = Process() + task.launchPath = path + task.arguments = arguments + + let pipe = Pipe() + task.standardOutput = pipe + task.launch() + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + let output: String = String.init(data: data, encoding: String.Encoding.utf8)! + return output; + } + + public static func experiment() { + /* + print("Running '/usr/local/bin/php -v' directly...") + print("========================================") + var start = DispatchTime.now() + print(Command.execute(path: "/usr/local/bin/php", arguments: ["-v"])) + var end = DispatchTime.now() + var nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds + var timeInterval = Double(nanoTime) / 1_000_000_000 + print("Time to run command directly: \(timeInterval) seconds") + + print("") + print("Running 'bash -> php -v'...") + print("========================================") + start = DispatchTime.now() + print(Shell.user.pipe("php -v")) + end = DispatchTime.now() + nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds + timeInterval = Double(nanoTime) / 1_000_000_000 + print("Time to run command via bash: \(timeInterval) seconds") + */ + } + +} diff --git a/phpmon/Singletons/MainMenu.swift b/phpmon/Singletons/MainMenu.swift index c5f933b..631ef14 100644 --- a/phpmon/Singletons/MainMenu.swift +++ b/phpmon/Singletons/MainMenu.swift @@ -63,9 +63,29 @@ class MainMenu: NSObject, NSWindowDelegate { menu.addItem(NSMenuItem.separator()) } if (App.shared.currentVersion != nil) { - menu.addItem(NSMenuItem(title: "PHP configuration file (php.ini)", action: #selector(self.openActiveConfigFolder), keyEquivalent: "")) + menu.addItem(NSMenuItem(title: "PHP configuration file (php.ini)", action: #selector(self.openActiveConfigFolder), keyEquivalent: "c")) + let xdebugFound = App.shared.currentVersion!.xdebugFound + if (xdebugFound) { + let xdebugOn = App.shared.currentVersion!.xdebugEnabled + let xdebugToggleMenuItem = NSMenuItem( + title: "Xdebug", + action: #selector(self.toggleXdebug), keyEquivalent: "x" + ) + if (xdebugOn) { + xdebugToggleMenuItem.state = .on + } + menu.addItem(xdebugToggleMenuItem) + } else { + let disabledItem = NSMenuItem( + title: "xdebug.so missing", + action: nil, keyEquivalent: "x" + ) + disabledItem.isEnabled = false + menu.addItem(disabledItem) + } } - menu.addItem(NSMenuItem(title: "View shell output", action: #selector(self.openOutput), keyEquivalent: "")) + menu.addItem(NSMenuItem.separator()) + menu.addItem(NSMenuItem(title: "View shell output...", action: #selector(self.openOutput), keyEquivalent: "o")) menu.addItem(NSMenuItem.separator()) menu.addItem(NSMenuItem(title: "About PHP Monitor", action: #selector(self.openAbout), keyEquivalent: "")) menu.items.forEach({ (item) in @@ -147,6 +167,19 @@ class MainMenu: NSObject, NSWindowDelegate { } } + @objc public func toggleXdebug() { + DispatchQueue.global(qos: .userInitiated).async { [unowned self] in + DispatchQueue.main.async { + self.setStatusBar(image: NSImage(named: NSImage.Name("StatusBarIcon"))!) + } + Actions.toggleXdebug() + DispatchQueue.main.async { + self.updatePhpVersionInStatusBar() + self.update() + } + } + } + func windowWillClose(_ notification: Notification) { App.shared.windowController = nil Shell.user.delegate = nil diff --git a/phpmon/Singletons/Shell.swift b/phpmon/Singletons/Shell.swift index 204be91..5db6269 100644 --- a/phpmon/Singletons/Shell.swift +++ b/phpmon/Singletons/Shell.swift @@ -60,11 +60,15 @@ class Shell { ) as String let historyItem = ShellHistoryItem(command: command, output: output) - history.append(historyItem) - // Keep the last 100 items - history = history.suffix(100) - delegate?.didCompleteCommand(historyItem: historyItem) + DispatchQueue.global(qos: .userInitiated).async { [unowned self] in + self.history.append(historyItem) + // Keep the last 100 items + self.history = self.history.suffix(100) + } + + delegate?.didCompleteCommand(historyItem: historyItem) + return output } }