1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2025-08-07 03:50:08 +02:00

Allow toggling of PHP extensions in php.ini

This commit is contained in:
2021-01-31 22:50:39 +01:00
parent 1dc85a4d48
commit 5a50e7fdab
9 changed files with 115 additions and 48 deletions

View File

@ -26,6 +26,7 @@
C4811D2422D70A4700B5F6B3 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4811D2322D70A4700B5F6B3 /* App.swift */; };
C4811D2A22D70F9A00B5F6B3 /* MainMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4811D2922D70F9A00B5F6B3 /* MainMenu.swift */; };
C49EAB46259FC305007F6C3B /* Paths.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49EAB45259FC305007F6C3B /* Paths.swift */; };
C4ACA38F25C754C100060C66 /* PhpExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4ACA38E25C754C100060C66 /* PhpExtension.swift */; };
C4D8016622B1584700C6DA1B /* Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D8016522B1584700C6DA1B /* Startup.swift */; };
C4EE188422D3386B00E126E5 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EE188322D3386B00E126E5 /* Constants.swift */; };
C4F8C0A422D4F12C002EFE61 /* DateExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8C0A322D4F12C002EFE61 /* DateExtension.swift */; };
@ -54,6 +55,7 @@
C4811D2322D70A4700B5F6B3 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
C4811D2922D70F9A00B5F6B3 /* MainMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainMenu.swift; sourceTree = "<group>"; };
C49EAB45259FC305007F6C3B /* Paths.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Paths.swift; sourceTree = "<group>"; };
C4ACA38E25C754C100060C66 /* PhpExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpExtension.swift; sourceTree = "<group>"; };
C4D8016522B1584700C6DA1B /* Startup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Startup.swift; sourceTree = "<group>"; };
C4E713562570150F00007428 /* SECURITY.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = SECURITY.md; sourceTree = "<group>"; };
C4E713572570151400007428 /* docs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = docs; sourceTree = "<group>"; };
@ -182,6 +184,7 @@
children = (
C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */,
C41C1B4A22B019FF00E7CF16 /* PhpInstall.swift */,
C4ACA38E25C754C100060C66 /* PhpExtension.swift */,
);
path = Core;
sourceTree = "<group>";
@ -268,6 +271,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C4ACA38F25C754C100060C66 /* PhpExtension.swift in Sources */,
C4D8016622B1584700C6DA1B /* Startup.swift in Sources */,
C4F8C0A422D4F12C002EFE61 /* DateExtension.swift in Sources */,
C41C1B4722B009A400E7CF16 /* Shell.swift in Sources */,

View File

@ -165,7 +165,7 @@ class Actions {
/**
Runs a `brew` command. Can run as superuser.
*/
private static func brew(_ command: String, sudo: Bool = false)
public static func brew(_ command: String, sudo: Bool = false)
{
Shell.run("\(sudo ? "sudo " : "")" + "\(Paths.brew) \(command)")
}
@ -173,17 +173,15 @@ class Actions {
/**
Runs `sed` in order to replace all occurrences of a string in a specific file with another.
*/
private static func sed(file: String, original: String, replacement: String)
public static func sed(file: String, original: String, replacement: String)
{
Shell.run("""
sed -i '' 's/\(original)/\(replacement)/g' \(file)
""")
Shell.run("sed -i '' 's/\(original)/\(replacement)/g' \(file)")
}
/**
Uses `grep` to determine whether a particular query string can be found in a particular file.
*/
private static func grepContains(file: String, query: String) -> Bool
public static func grepContains(file: String, query: String) -> Bool
{
return Shell.pipe("""
grep -q '\(query)' \(file); [ $? -eq 0 ] && echo "YES" || echo "NO"

View File

@ -113,9 +113,7 @@ class Startup {
// Present the information to the user
Alert.notify(message: messageText, info: informativeText)
// Only breaking issues will throw the extra retry modal
if (breaking) {
self.failureCallback()
}
breaking ? self.failureCallback() : ()
}
}
}

View File

@ -0,0 +1,58 @@
//
// PhpExtension.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 31/01/2021.
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//
import Foundation
/**
A PHP extension that was detected in the php.ini file.
Please note that the extension may be disabled.
- Note: You need to know more about regular expressions to be able to deal with these NSRegularExpression
instances. You can find more information here: https://nshipster.com/swift-regular-expressions/
*/
class PhpExtension {
var file: String
var line: String
var name: String
var enabled: Bool
init(_ line: String, file: String) {
let regex = try! NSRegularExpression(pattern: #"^(extension=|zend_extension=|; extension=|; zend_extension=)"(?<name>[a-zA-Z]*).so"$"#, options: [])
let match = regex.matches(in: line, options: [], range: NSMakeRange(0, line.count)).first
let range = Range(match!.range(withName: "name"), in: line)!
self.line = line
self.name = line[range]
self.enabled = !line.contains(";")
self.file = file
}
public func toggle() {
Actions.sed(
file: self.file,
original: self.line,
replacement: self.enabled ? "; \(self.line)" : self.line.replacingOccurrences(of: "; ", with: "")
)
self.enabled = !self.enabled
}
static func load(from path: URL) -> [PhpExtension] {
let file = try! String(contentsOf: path, encoding: .utf8)
return file.components(separatedBy: "\n")
.filter({ (line) -> Bool in
return line.range(
of: #"^(extension=|zend_extension=|; extension=|; zend_extension=)"[a-zA-Z]*.so"$"#,
options: .regularExpression
) != nil
})
.map { (line) -> PhpExtension in
return PhpExtension(line, file: path.path)
}
}
}

View File

@ -9,8 +9,8 @@ import Foundation
class PhpInstall {
var version: Version = Version()
var xdebug: Xdebug = Xdebug()
var version: Version!
var extensions: [PhpExtension]!
// MARK: - Computed
@ -23,6 +23,8 @@ class PhpInstall {
init() {
let version = Command.execute(path: Paths.php, arguments: ["-r", "print phpversion();"])
self.version = Version()
if (version == "" || version.contains("Warning")) {
self.version.short = "💩 BROKEN"
self.version.long = "";
@ -39,13 +41,9 @@ class PhpInstall {
// 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
// Load extension information
let path = URL(fileURLWithPath: "\(Paths.etcPath)/php/\(self.version.short)/php.ini")
self.extensions = PhpExtension.load(from: path)
}
// MARK: - Structs
@ -55,9 +53,4 @@ class PhpInstall {
var long = "???"
var error = false
}
struct Xdebug {
var found: Bool = false
var enabled: Bool = false
}
}

View File

@ -7,10 +7,6 @@
import Cocoa
class PhpMenuItem: NSMenuItem {
var version: String = ""
}
class StatusMenu : NSMenu {
public func addPhpVersionMenuItems()
{
@ -79,26 +75,34 @@ class StatusMenu : NSMenu {
self.addItem(NSMenuItem(title: "mi_phpinfo".localized, action: #selector(MainMenu.openPhpInfo), keyEquivalent: "i"))
self.addItem(NSMenuItem.separator())
self.addItem(NSMenuItem(title: "mi_enabled_extensions".localized, action: nil, keyEquivalent: ""))
self.addXdebugMenuItem()
}
private func addXdebugMenuItem()
{
let xdebugFound = App.phpInstall!.xdebug.found
let xdebugOn = App.phpInstall!.xdebug.enabled
self.addItem(NSMenuItem(title: "mi_detected_extensions".localized, action: nil, keyEquivalent: ""))
let menuItem = NSMenuItem(
title: xdebugFound ? "mi_xdebug".localized : "mi_xdebug_missing".localized,
action: #selector(MainMenu.toggleXdebug), keyEquivalent: "x"
)
if (!xdebugFound) {
menuItem.isEnabled = false
} else {
menuItem.state = xdebugOn ? .on : .off
for phpExtension in App.phpInstall!.extensions {
self.addExtensionItem(phpExtension)
}
if (App.phpInstall!.extensions.count == 0) {
self.addItem(NSMenuItem(title: "mi_no_extensions_detected".localized, action: nil, keyEquivalent: ""))
}
}
private func addExtensionItem(_ phpExtension: PhpExtension) {
let menuItem = ExtensionMenuItem(
title: "\(phpExtension.name.capitalized) (php.ini)",
action: #selector(MainMenu.toggleExtension), keyEquivalent: ""
)
menuItem.state = phpExtension.enabled ? .on : .off
menuItem.phpExtension = phpExtension
self.addItem(menuItem)
}
}
// MARK: - In order to store extra data in each item, NSMenuItem is subclassed
class PhpMenuItem: NSMenuItem {
var version: String = ""
}
class ExtensionMenuItem: NSMenuItem {
var phpExtension: PhpExtension? = nil
}

View File

@ -27,4 +27,10 @@ extension String {
return count
}
subscript (r: Range<String.Index>) -> String {
let start = r.lowerBound
let end = r.upperBound
return String(self[start ..< end])
}
}

View File

@ -29,10 +29,8 @@
"mi_valet_config" = "Locate Valet folder (.config/valet)";
"mi_php_config" = "Locate PHP configuration file (php.ini)";
"mi_phpinfo" = "Show current configuration (phpinfo)";
"mi_enabled_extensions" = "Enabled Extensions";
"mi_xdebug" = "Xdebug";
"mi_xdebug_missing" = "xdebug.so missing";
"mi_detected_extensions" = "Detected Extensions";
"mi_no_extensions_detected" = "No additional extensions detected.";
"mi_quit" = "Quit PHP Monitor";
"mi_about" = "About PHP Monitor";

View File

@ -210,6 +210,14 @@ class MainMenu: NSObject, NSWindowDelegate {
})
}
@objc public func toggleExtension(sender: ExtensionMenuItem) {
self.waitAndExecute({
// Toggle that extension
print("Toggling extension '\(sender.phpExtension!.name)'")
sender.phpExtension?.toggle()
})
}
@objc public func openPhpInfo() {
self.waitAndExecute({
try! "<?php phpinfo();".write(toFile: "/tmp/phpmon_phpinfo.php", atomically: true, encoding: .utf8)