mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-11-08 05:30:05 +01:00
✨ Extension loading improvements (#31) and more
* The README has been updated with additional information * The acknowledgements section has been added to the README * The php@X.X/opt/bin/php-config binary is now used (#39) * Extensions are now loaded from all possible .ini files * PHP Monitor's preferences window can now be triggered via hotkey * The first nine extensions can be triggered via hotkey
This commit is contained in:
@@ -29,6 +29,11 @@ class PhpExtension {
|
||||
/// Whether the extension has been enabled.
|
||||
var enabled: Bool
|
||||
|
||||
/// The file where this extension was located, but only the filename, not the full path to the .ini file.
|
||||
var fileNameOnly: String {
|
||||
return String(file.split(separator: "/").last ?? "php.ini")
|
||||
}
|
||||
|
||||
/**
|
||||
This regular expression will allow us to identify lines which activate an extension.
|
||||
|
||||
@@ -41,7 +46,7 @@ class PhpExtension {
|
||||
|
||||
- Note: Extensions that are disabled in a different way will not be detected. This is intentional.
|
||||
*/
|
||||
static let extensionRegex = #"^(extension=|zend_extension=|; extension=|; zend_extension=)"(?<name>[a-zA-Z]*).so"$"#
|
||||
static let extensionRegex = #"^(extension=|zend_extension=|; extension=|; zend_extension=)(?<name>["]?(?:\/?.\/?)+(?:\.so)"?)$"#
|
||||
|
||||
/**
|
||||
When registering an extension, we do that based on the line found inside the .ini file.
|
||||
@@ -52,7 +57,12 @@ class PhpExtension {
|
||||
let range = Range(match!.range(withName: "name"), in: line)!
|
||||
|
||||
self.line = line
|
||||
self.name = line[range]
|
||||
|
||||
let fullPath = String(line[range])
|
||||
.replacingOccurrences(of: "\"", with: "") // replace excess "
|
||||
.replacingOccurrences(of: ".so", with: "") // replace excess .so
|
||||
self.name = String(fullPath.split(separator: "/").last!) // take last segment
|
||||
|
||||
self.enabled = !line.contains(";")
|
||||
self.file = file
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ class PhpInstallation {
|
||||
|
||||
// Load extension information
|
||||
let path = URL(fileURLWithPath: "\(Paths.etcPath)/php/\(version.short)/php.ini")
|
||||
|
||||
extensions = PhpExtension.load(from: path)
|
||||
|
||||
// Get configuration values
|
||||
@@ -43,6 +42,20 @@ class PhpInstallation {
|
||||
upload_max_filesize: Self.getByteCount(key: "upload_max_filesize"),
|
||||
post_max_size: Self.getByteCount(key: "post_max_size")
|
||||
)
|
||||
|
||||
// Determine which folder(s) to scan for additional files
|
||||
let iniFolder = Command.execute(path: Paths.phpConfig, arguments: ["--ini-dir"], trimNewlines: true)
|
||||
|
||||
// Check the contents of the ini dir
|
||||
let enumerator = FileManager.default.enumerator(atPath: URL(fileURLWithPath: iniFolder).path)
|
||||
let filePaths = enumerator?.allObjects as! [String]
|
||||
|
||||
filePaths.filter { $0.contains(".ini") }.forEach { (iniFileName) in
|
||||
let extensions = PhpExtension.load(from: URL(fileURLWithPath: "\(iniFolder)/\(iniFileName)"))
|
||||
if extensions.count > 0 {
|
||||
self.extensions.append(contentsOf: extensions)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,7 +64,7 @@ class PhpInstallation {
|
||||
*/
|
||||
private static func getVersion() -> Version {
|
||||
var versionStruct = Version()
|
||||
let version = Command.execute(path: Paths.php, arguments: ["-r", "print phpversion();"])
|
||||
let version = Command.execute(path: Paths.phpConfig, arguments: ["--version"], trimNewlines: true)
|
||||
|
||||
if (version == "" || version.contains("Warning") || version.contains("Error")) {
|
||||
versionStruct.short = "💩 BROKEN"
|
||||
|
||||
@@ -98,7 +98,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
|
||||
// Add about & quit menu items
|
||||
menu.addItem(NSMenuItem(title: "mi_preferences".localized, action: #selector(openPrefs), keyEquivalent: ""))
|
||||
menu.addItem(NSMenuItem(title: "mi_preferences".localized, action: #selector(openPrefs), keyEquivalent: ","))
|
||||
menu.addItem(NSMenuItem(title: "mi_about".localized, action: #selector(openAbout), keyEquivalent: ""))
|
||||
menu.addItem(NSMenuItem(title: "mi_quit".localized, action: #selector(terminateApp), keyEquivalent: "q"))
|
||||
|
||||
|
||||
@@ -106,8 +106,10 @@ class StatusMenu : NSMenu {
|
||||
self.addItem(NSMenuItem(title: "mi_no_extensions_detected".localized, action: nil, keyEquivalent: ""))
|
||||
}
|
||||
|
||||
var shortcutKey = 1
|
||||
for phpExtension in App.phpInstall!.extensions {
|
||||
self.addExtensionItem(phpExtension)
|
||||
self.addExtensionItem(phpExtension, shortcutKey)
|
||||
shortcutKey += 1
|
||||
}
|
||||
|
||||
self.addItem(NSMenuItem.separator())
|
||||
@@ -115,11 +117,19 @@ class StatusMenu : NSMenu {
|
||||
self.addItem(NSMenuItem(title: "mi_php_refresh".localized, action: #selector(MainMenu.reloadPhpMonitorMenu), keyEquivalent: "r"))
|
||||
}
|
||||
|
||||
private func addExtensionItem(_ phpExtension: PhpExtension) {
|
||||
private func addExtensionItem(_ phpExtension: PhpExtension, _ shortcutKey: Int) {
|
||||
let keyEquivalent = shortcutKey < 9 ? "\(shortcutKey)" : ""
|
||||
|
||||
let menuItem = ExtensionMenuItem(
|
||||
title: "\(phpExtension.name.capitalized) (php.ini)",
|
||||
action: #selector(MainMenu.toggleExtension), keyEquivalent: ""
|
||||
title: "\(phpExtension.name) (\(phpExtension.fileNameOnly))",
|
||||
action: #selector(MainMenu.toggleExtension),
|
||||
keyEquivalent: keyEquivalent
|
||||
)
|
||||
|
||||
if menuItem.keyEquivalent != "" {
|
||||
menuItem.keyEquivalentModifierMask = [.option]
|
||||
}
|
||||
|
||||
menuItem.state = phpExtension.enabled ? .on : .off
|
||||
menuItem.phpExtension = phpExtension
|
||||
|
||||
|
||||
@@ -162,7 +162,11 @@ class Actions {
|
||||
*/
|
||||
public static func sed(file: String, original: String, replacement: String)
|
||||
{
|
||||
Shell.run("sed -i '' 's/\(original)/\(replacement)/g' \(file)")
|
||||
// Escape slashes (or `sed` won't work)
|
||||
let e_original = original.replacingOccurrences(of: "/", with: "\\/")
|
||||
let e_replacment = replacement.replacingOccurrences(of: "/", with: "\\/")
|
||||
|
||||
Shell.run("sed -i '' 's/\(e_original)/\(e_replacment)/g' \(file)")
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,8 +14,9 @@ class Command {
|
||||
|
||||
- Parameter path: The path of the command or program to invoke.
|
||||
- Parameter arguments: A list of arguments that are passed on.
|
||||
- Parameter trimNewlines: Removes empty new line output.
|
||||
*/
|
||||
public static func execute(path: String, arguments: [String]) -> String {
|
||||
public static func execute(path: String, arguments: [String], trimNewlines: Bool = false) -> String {
|
||||
let task = Process()
|
||||
task.launchPath = path
|
||||
task.arguments = arguments
|
||||
@@ -26,6 +27,13 @@ class Command {
|
||||
|
||||
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||
let output: String = String.init(data: data, encoding: String.Encoding.utf8)!
|
||||
|
||||
if (trimNewlines) {
|
||||
return output.components(separatedBy: .newlines)
|
||||
.filter({ !$0.isEmpty })
|
||||
.joined(separator: "\n")
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,10 @@ class Paths {
|
||||
return "\(binPath)/php"
|
||||
}
|
||||
|
||||
public static var phpConfig: String {
|
||||
return "\(binPath)/php-config"
|
||||
}
|
||||
|
||||
// - MARK: Paths
|
||||
|
||||
public static var binPath: String {
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
// PREFERENCES
|
||||
|
||||
"prefs.title" = "Preferences";
|
||||
"prefs.title" = "PHP Monitor: Preferences";
|
||||
"prefs.close" = "Close";
|
||||
"prefs.dynamic_icon_title" = "Show a dynamic icon in the menu bar";
|
||||
"prefs.dynamic_icon_desc" = "If you uncheck this box, the truck icon will always be visible.\nIf checked, it will display the major version number of the currently linked PHP version.";
|
||||
|
||||
Reference in New Issue
Block a user