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

Add support for Homebrew in /opt/homebrew (#20)

This commit is contained in:
2021-01-01 22:54:03 +01:00
parent e73474e30c
commit 94f086881a
9 changed files with 124 additions and 34 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 */; };
C486EFFC2586931100A02B2C /* PhpMenuItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C486EFFB2586931100A02B2C /* PhpMenuItem.swift */; };
C49EAB46259FC305007F6C3B /* Paths.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49EAB45259FC305007F6C3B /* Paths.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>"; };
C486EFFB2586931100A02B2C /* PhpMenuItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpMenuItem.swift; sourceTree = "<group>"; };
C49EAB45259FC305007F6C3B /* Paths.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Paths.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>"; };
@ -149,6 +151,7 @@
C4811D2622D70CEF00B5F6B3 /* Singletons */ = {
isa = PBXGroup;
children = (
C49EAB45259FC305007F6C3B /* Paths.swift */,
C41C1B4622B009A400E7CF16 /* Shell.swift */,
C42295DC2358D02000E263B2 /* Command.swift */,
C4811D2322D70A4700B5F6B3 /* App.swift */,
@ -272,6 +275,7 @@
C41C1B3722B0097F00E7CF16 /* AppDelegate.swift in Sources */,
C41C1B4B22B019FF00E7CF16 /* PhpVersion.swift in Sources */,
C486EFFC2586931100A02B2C /* PhpMenuItem.swift in Sources */,
C49EAB46259FC305007F6C3B /* Paths.swift in Sources */,
C476FF9822B0DD830098105B /* Alert.swift in Sources */,
C474B00624C0E98C00066A22 /* LocalNotification.swift in Sources */,
C47331A2247093B7009A0597 /* StatusMenu.swift in Sources */,

View File

@ -33,6 +33,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
*/
let menu : MainMenu
/**
The paths singleton that determines where Homebrew is installed,
and where to look for binaries.
*/
let paths : Paths
// MARK: - Initializer
/**
@ -42,6 +48,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
self.sharedShell = Shell.user
self.state = App.shared
self.menu = MainMenu.shared
self.paths = Paths.shared
super.init()
}

View File

@ -12,7 +12,7 @@ import AppKit
class Actions {
public static func detectPhpVersions() -> [String] {
let files = Shell.user.pipe("ls /usr/local/opt | grep php@")
let files = Shell.user.pipe("ls \(Paths.optPath()) | grep php@")
var versions = files.components(separatedBy: "\n")
// Remove all empty strings
@ -40,15 +40,15 @@ class Actions {
public static func restartPhpFpm() {
let version = App.shared.currentVersion!.short
if (version == App.shared.brewPhpVersion) {
Shell.user.run("sudo brew services restart php")
Shell.user.run("sudo \(Paths.brew()) services restart php")
} else {
Shell.user.run("sudo brew services restart php@\(version)")
Shell.user.run("sudo \(Paths.brew()) services restart php@\(version)")
}
}
public static func restartNginx()
{
Shell.user.run("sudo brew services restart nginx")
Shell.user.run("sudo \(Paths.brew()) services restart nginx")
}
/**
@ -63,22 +63,22 @@ class Actions {
public static func switchToPhpVersion(version: String, availableVersions: [String]) {
availableVersions.forEach { (available) in
let formula = (available == App.shared.brewPhpVersion) ? "php" : "php@\(available)"
Shell.user.run("brew unlink \(formula)")
Shell.user.run("sudo brew services stop \(formula)")
Shell.user.run("\(Paths.brew()) unlink \(formula)")
Shell.user.run("sudo \(Paths.brew()) services stop \(formula)")
}
let formula = (version == App.shared.brewPhpVersion) ? "php" : "php@\(version)"
Shell.user.run("brew link \(formula) --overwrite --force")
Shell.user.run("sudo brew services start \(formula)")
Shell.user.run("\(Paths.brew()) link \(formula) --overwrite --force")
Shell.user.run("sudo \(Paths.brew()) services start \(formula)")
}
public static func openGenericPhpConfigFolder() {
let files = [NSURL(fileURLWithPath: "/usr/local/etc/php")];
let files = [NSURL(fileURLWithPath: "\(Paths.etcPath())/php")];
NSWorkspace.shared.activateFileViewerSelecting(files as [URL])
}
public static func openPhpConfigFolder(version: String) {
let files = [NSURL(fileURLWithPath: "/usr/local/etc/php/\(version)/php.ini")];
let files = [NSURL(fileURLWithPath: "\(Paths.etcPath())/php/\(version)/php.ini")];
NSWorkspace.shared.activateFileViewerSelecting(files as [URL])
}
@ -89,7 +89,7 @@ class Actions {
public static func didFindXdebug(_ version: String) -> Bool {
let command = """
grep -q 'zend_extension="xdebug.so"' /usr/local/etc/php/\(version)/php.ini; [ $? -eq 0 ] && echo "YES" || echo "NO"
grep -q 'zend_extension="xdebug.so"' \(Paths.etcPath())/php/\(version)/php.ini; [ $? -eq 0 ] && echo "YES" || echo "NO"
"""
let output = Shell.user.pipe(command).trimmingCharacters(in: .whitespacesAndNewlines)
return (output == "YES")
@ -97,7 +97,7 @@ class Actions {
public static func didEnableXdebug(_ version: String) -> Bool {
let command = """
grep -q '; zend_extension="xdebug.so"' /usr/local/etc/php/\(version)/php.ini; [ $? -eq 0 ] && echo "YES" || echo "NO"
grep -q '; zend_extension="xdebug.so"' \(Paths.etcPath())/php/\(version)/php.ini; [ $? -eq 0 ] && echo "YES" || echo "NO"
"""
let output = Shell.user.pipe(command).trimmingCharacters(in: .whitespacesAndNewlines)
return (output == "NO")
@ -106,11 +106,11 @@ class Actions {
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
sed -i '' 's/; zend_extension="xdebug.so"/zend_extension="xdebug.so"/g' \(Paths.etcPath())/php/\(version!)/php.ini
"""
if (self.didEnableXdebug(version!)) {
command = """
sed -i '' 's/zend_extension="xdebug.so"/; zend_extension="xdebug.so"/g' /usr/local/etc/php/\(version!)/php.ini
sed -i '' 's/zend_extension="xdebug.so"/; zend_extension="xdebug.so"/g' \(Paths.etcPath())/php/\(version!)/php.ini
"""
}
Shell.user.run(command)
@ -124,19 +124,19 @@ class Actions {
public static func fixMyPhp() {
let versions = self.detectPhpVersions()
versions.forEach { (version) in
Shell.user.run("brew unlink php@\(version)")
Shell.user.run("\(Paths.brew()) unlink php@\(version)")
if (version == App.shared.brewPhpVersion) {
Shell.user.run("brew services stop php")
Shell.user.run("sudo brew services stop php")
Shell.user.run("\(Paths.brew()) services stop php")
Shell.user.run("sudo \(Paths.brew()) services stop php")
} else {
Shell.user.run("brew services stop php@\(version)")
Shell.user.run("sudo brew services stop php@\(version)")
Shell.user.run("\(Paths.brew()) services stop php@\(version)")
Shell.user.run("sudo \(Paths.brew()) services stop php@\(version)")
}
}
Shell.user.run("brew services stop php")
Shell.user.run("brew services stop nginx")
Shell.user.run("brew link php")
Shell.user.run("sudo brew services restart php")
Shell.user.run("sudo brew services restart nginx")
Shell.user.run("\(Paths.brew()) services stop php")
Shell.user.run("\(Paths.brew()) services stop nginx")
Shell.user.run("\(Paths.brew()) link php")
Shell.user.run("sudo \(Paths.brew()) services restart php")
Shell.user.run("sudo \(Paths.brew()) services restart nginx")
}
}

View File

@ -25,14 +25,14 @@ class Startup {
self.failureCallback = failure
self.performEnvironmentCheck(
!Shell.user.pipe("which php").contains("/usr/local/bin/php"),
!Shell.fileExists("\(Paths.binPath())/php"),
messageText: "startup.errors.php_binary.title".localized,
informativeText: "startup.errors.php_binary_desc".localized,
breaking: true
)
self.performEnvironmentCheck(
!Shell.user.pipe("ls /usr/local/opt | grep php").contains("php"),
!Shell.user.pipe("ls \(Paths.optPath()) | grep php").contains("php"),
messageText: "startup.errors.php_opt.title".localized,
informativeText: "startup.errors.php_opt.desc".localized,
breaking: true
@ -46,7 +46,7 @@ class Startup {
)
self.performEnvironmentCheck(
!Shell.user.pipe("cat /private/etc/sudoers.d/brew").contains("/usr/local/bin/brew"),
!Shell.user.pipe("cat /private/etc/sudoers.d/brew").contains("\(Paths.binPath())/brew"),
messageText: "startup.errors.sudoers_brew.title".localized,
informativeText: "startup.errors.sudoers_brew.desc".localized,
breaking: true
@ -59,7 +59,7 @@ class Startup {
breaking: true
)
let services = Shell.user.pipe("brew services list | grep php")
let services = Shell.user.pipe("\(Paths.brew()) services list | grep php")
self.performEnvironmentCheck(
(services.countInstances(of: "started") > 1),
messageText: "startup.errors.services.title".localized,
@ -82,7 +82,7 @@ class Startup {
print("PHP Monitor has determined the application has successfully passed all checks.")
print("Determining which version of PHP is aliased to `php` via Homebrew...")
let brewPhpAlias = Shell.user.pipe("brew info php --json");
let brewPhpAlias = Shell.user.pipe("\(Paths.brew()) info php --json");
App.shared.brewPhpPackage = try! JSONDecoder().decode(
[HomebrewPackage].self,

View File

@ -19,7 +19,10 @@ class PhpVersion {
var error : Bool = false
init() {
let version = Command.execute(path: "/usr/local/bin/php", arguments: ["-r", "print phpversion();"])
let version = Command.execute(
path: Paths.php(),
arguments: ["-r", "print phpversion();"]
)
if (version == "" || version.contains("Warning")) {
self.short = "💩 BROKEN"

View File

@ -59,11 +59,11 @@
/// 1. PHP binary not found
"startup.errors.php_binary.title" = "PHP is not correctly installed";
"startup.errors.php_binary_desc" = "You must install PHP via brew. Try running `which php` in Terminal, it should return `/usr/local/bin/php`. The app will not work correctly until you resolve this issue. (Usually `brew link php` resolves this issue.)";
"startup.errors.php_binary_desc" = "You must install PHP via brew. Try running `which php` in Terminal, it should return `/usr/local/bin/php` (or `/opt/homebrew/bin/php`). The app will not work correctly until you resolve this issue. (Usually `brew link php` resolves this issue.)";
/// 2. PHP not found in /usr/local/opt
/// 2. PHP not found in /usr/local/opt or /opt/homebrew/opt
"startup.errors.php_opt.title" = "PHP is not correctly installed";
"startup.errors.php_opt.desc" = "PHP alias was not found in `/usr/local/opt`. The app will not work correctly until you resolve this issue. If you already have the `php` formula installed, you may need to run `brew install php` in order for PHP Monitor to detect this installation.";
"startup.errors.php_opt.desc" = "PHP alias was not found in `/usr/local/opt` (or `/opt/homebrew/opt`). The app will not work correctly until you resolve this issue. If you already have the `php` formula installed, you may need to run `brew install php` in order for PHP Monitor to detect this installation.";
/// 3. Valet not installed
"startup.errors.valet_executable.title" = "Laravel Valet is not correctly installed";

View File

@ -201,7 +201,7 @@ class MainMenu: NSObject, NSWindowDelegate {
@objc public func openPhpInfo() {
self.waitAndExecute({
try! "<?php phpinfo();".write(toFile: "/tmp/phpmon_phpinfo.php", atomically: true, encoding: .utf8)
Shell.user.run("/usr/local/bin/php-cgi -q /tmp/phpmon_phpinfo.php > /tmp/phpmon_phpinfo.html")
Shell.user.run("\(Paths.binPath())/php-cgi -q /tmp/phpmon_phpinfo.php > /tmp/phpmon_phpinfo.html")
}, {
NSWorkspace.shared.open(URL(string: "file:///private/tmp/phpmon_phpinfo.html")!)
})

View File

@ -0,0 +1,70 @@
//
// Paths.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 01/01/2021.
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//
import Foundation
enum HomebrewDirectory: String {
case opt = "/opt/homebrew/bin"
case usr = "/usr/local/bin"
}
class Paths {
static let shared = Paths()
var baseDirectory : HomebrewDirectory
init() {
let optBrewFound = Shell.fileExists("\(HomebrewDirectory.opt.rawValue)/brew")
let usrBrewFound = Shell.fileExists("\(HomebrewDirectory.usr.rawValue)/brew")
if (optBrewFound) {
self.baseDirectory = .opt
} else if (usrBrewFound) {
self.baseDirectory = .usr
} else {
// Falling back to Intel
print("Seems like we couldn't determine the architecture.")
print("This usually means we're in trouble... (no Homebrew?)")
self.baseDirectory = .usr
}
print("Homebrew directory: \(self.baseDirectory)")
}
public static func brew() -> String {
return "\(self.binPath())/brew"
}
public static func php() -> String {
return "\(self.binPath())/php"
}
public static func binPath() -> String {
return self.shared.baseDirectory.rawValue
}
public static func optPath() -> String {
switch self.shared.baseDirectory {
case .opt:
return "/opt/homebrew/opt"
case .usr:
return "/usr/local/opt"
}
}
public static func etcPath() -> String {
switch self.shared.baseDirectory {
case .opt:
return "/opt/homebrew/etc"
case .usr:
return "/usr/local/etc"
}
}
}

View File

@ -46,4 +46,10 @@ class Shell {
encoding: .utf8
)!
}
public static func fileExists(_ filePath: String) -> Bool {
return Shell.user.pipe(
"if [ -f \(filePath) ]; then echo \"Y\"; fi"
).contains("Y")
}
}