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

♻️ Rework how the user's PATH is loaded

This commit is contained in:
2022-08-15 01:47:55 +02:00
parent bbbdce6b44
commit a9f9c38e0d
12 changed files with 154 additions and 102 deletions

View File

@ -98,6 +98,8 @@
C42CFB1627DFDE7900862737 /* nginx-site.test in Resources */ = {isa = PBXBuildFile; fileRef = C42CFB1527DFDE7900862737 /* nginx-site.test */; };
C42CFB1827DFDFDC00862737 /* nginx-site-isolated.test in Resources */ = {isa = PBXBuildFile; fileRef = C42CFB1727DFDFDC00862737 /* nginx-site-isolated.test */; };
C42CFB1A27DFE8BD00862737 /* NginxConfigurationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42CFB1927DFE8BD00862737 /* NginxConfigurationTest.swift */; };
C42E3BF428A9BF5100AFECFC /* Shell+PATH.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42E3BF328A9BF5100AFECFC /* Shell+PATH.swift */; };
C42E3BF528A9BF5100AFECFC /* Shell+PATH.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42E3BF328A9BF5100AFECFC /* Shell+PATH.swift */; };
C42F26732805B4B400938AC7 /* DomainListable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42F26722805B4B400938AC7 /* DomainListable.swift */; };
C42F26742805B4B400938AC7 /* DomainListable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42F26722805B4B400938AC7 /* DomainListable.swift */; };
C42F26762805FEE200938AC7 /* nginx-secure-proxy.test in Resources */ = {isa = PBXBuildFile; fileRef = C42F26752805FEE200938AC7 /* nginx-secure-proxy.test */; };
@ -356,6 +358,7 @@
C42CFB1527DFDE7900862737 /* nginx-site.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-site.test"; sourceTree = "<group>"; };
C42CFB1727DFDFDC00862737 /* nginx-site-isolated.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-site-isolated.test"; sourceTree = "<group>"; };
C42CFB1927DFE8BD00862737 /* NginxConfigurationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NginxConfigurationTest.swift; sourceTree = "<group>"; };
C42E3BF328A9BF5100AFECFC /* Shell+PATH.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Shell+PATH.swift"; sourceTree = "<group>"; };
C42F26722805B4B400938AC7 /* DomainListable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainListable.swift; sourceTree = "<group>"; };
C42F26752805FEE200938AC7 /* nginx-secure-proxy.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-secure-proxy.test"; sourceTree = "<group>"; };
C436039F275E67610028EFC6 /* AppDelegate+Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Notifications.swift"; sourceTree = "<group>"; };
@ -608,6 +611,7 @@
C4B5853D2770FE3900DA4FBE /* Command.swift */,
C4B5853B2770FE3900DA4FBE /* Paths.swift */,
C4B5853C2770FE3900DA4FBE /* Shell.swift */,
C42E3BF328A9BF5100AFECFC /* Shell+PATH.swift */,
C4C1019A27C65C6F001FACC2 /* Process.swift */,
C40C7F2F27722E8D00DDDCDC /* Logger.swift */,
C417DC73277614690015E6EE /* Helpers.swift */,
@ -1386,6 +1390,7 @@
C4C3ED412783497000AB15D8 /* MainMenu+Startup.swift in Sources */,
C4D89BC62783C99400A02B68 /* ComposerJson.swift in Sources */,
C46FA23F246C358E00944F05 /* StringExtension.swift in Sources */,
C42E3BF428A9BF5100AFECFC /* Shell+PATH.swift in Sources */,
C42337A3281F19F000459A48 /* Xdebug.swift in Sources */,
C4B97B75275CF08C003F3378 /* AppDelegate+MenuOutlets.swift in Sources */,
C41C02A627E60D7A009F26CB /* SiteScanner.swift in Sources */,
@ -1430,6 +1435,7 @@
C449B4F027EE7FB800C47E8A /* DomainListTLSCell.swift in Sources */,
C4FBFC532616485F00CDB8E1 /* PhpVersionDetectionTest.swift in Sources */,
C43A8A2425D9D20D00591B77 /* HomebrewPackageTest.swift in Sources */,
C42E3BF528A9BF5100AFECFC /* Shell+PATH.swift in Sources */,
C4F780CA25D80B75000DBC97 /* HomebrewPackage.swift in Sources */,
C4C8E81C276F54E5003AC782 /* PhpConfigWatcher.swift in Sources */,
C4F319C927B034A500AFF46F /* Stats.swift in Sources */,

View File

@ -19,12 +19,9 @@ public class Paths {
private var userName: String
private var PATH: String
init() {
baseDir = App.architecture != "x86_64" ? .opt : .usr
userName = String(Shell.pipe("whoami").split(separator: "\n")[0])
PATH = String(Shell.pipe("echo $PATH")).trimmingCharacters(in: .whitespacesAndNewlines)
}
public func detectBinaryPaths() {
@ -60,10 +57,6 @@ public class Paths {
return shared.userName
}
public static var PATH: String {
return shared.PATH
}
public static var cellarPath: String {
return "\(shared.baseDir.rawValue)/Cellar"
}

View File

@ -0,0 +1,27 @@
//
// Shell+PATH.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 15/08/2022.
// Copyright © 2022 Nico Verbruggen. All rights reserved.
//
import Foundation
extension Shell {
var PATH: String {
let task = Process()
task.launchPath = "/bin/zsh"
// We need an interactive shell so the user's PATH is loaded in correctly
task.arguments = ["--login", "-ilc", "echo $PATH"]
let pipe = Pipe()
task.standardOutput = pipe
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
return String(data: data, encoding: String.Encoding.utf8) ?? ""
}
}

View File

@ -20,7 +20,7 @@ class PhpHelper {
let destination = "/Users/\(Paths.whoami)/.config/phpmon/bin/pm\(dotless)"
// Check if the ~/.config/phpmon/bin directory is in the PATH
let inPath = Paths.PATH.contains("/Users/\(Paths.whoami)/.config/phpmon/bin")
let inPath = Shell.user.PATH.contains("/Users/\(Paths.whoami)/.config/phpmon/bin")
// Check if we can create symlinks (`/usr/local/bin` must be writable)
let canWriteSymlinks = FileManager.default.isWritableFile(atPath: "/usr/local/bin/")

View File

@ -13,9 +13,9 @@
</head>
<body>
<br>
<p><b>Want to spread the love?</b> Leave a <a href="https://github.com/nicoverbruggen/phpmon">star on GitHub</a>!</p>
<p><b>Having issues?</b> Consult the <a href="https://github.com/nicoverbruggen/phpmon#%EF%B8%8F-faq--troubleshooting">FAQ & Troubleshooting</a> section.</p>
<p><b>Want to support me?</b> You can <a href="https://nicoverbruggen.be/sponsor">financially support</a> the continued development of this app.</p>
<p><b>Do you enjoy using the app?</b> Leave a <a href="https://github.com/nicoverbruggen/phpmon">star on GitHub</a>!</p>
<p><b>Having issues?</b> Consult the <a href="https://github.com/nicoverbruggen/phpmon#%EF%B8%8F-faq--troubleshooting">FAQ</a> section, I did my best to ensure everything is documented.</p>
<p><b>Want to support further development of PHP Monitor?</b> You can <a href="https://nicoverbruggen.be/sponsor">financially support</a> the continued development of this app.</p>
<p><b>Get the latest on Twitter</b> Give me a <a href="https://twitter.com/nicoverbruggen">follow on Twitter</a> to learn about the latest and greatest updates of this app.</p>
<br>
</body>

View File

@ -64,7 +64,6 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate, PhpSwitcherDelegate
menu.addRemainingMenuItems()
menu.addItem(NSMenuItem.separator())
menu.addWarningsMenuItem()
menu.addCoreMenuItems()
menu.items.forEach({ (item) in

View File

@ -157,6 +157,7 @@ extension StatusMenu {
return
}
self.addItem(NSMenuItem.separator())
let xdebugSwitch = NSMenuItem(
title: "mi_xdebug_mode".localized,
action: nil,

View File

@ -66,25 +66,34 @@ class StatusMenu: NSMenu {
self.addExtensionsMenuItems()
self.addXdebugMenuItem()
self.addPhpDoctorMenuItem()
self.addItem(NSMenuItem.separator())
self.addXdebugMenuItem()
self.addPresetsMenuItem()
self.addFirstAidAndServicesMenuItems()
}
func addWarningsMenuItem() {
func addPhpDoctorMenuItem() {
if !Preferences.isEnabled(.showPhpDoctorSuggestions) ||
!WarningManager.shared.hasWarnings() {
return
}
self.addItem(NSMenuItem.separator())
let count = WarningManager.shared.warnings.count
self.addItem(NSMenuItem(title: "mi_warnings".localized(count),
action: #selector(MainMenu.openWarnings), keyEquivalent: ""))
self.addItem(HeaderView.asMenuItem(text: "mi_php_doctor".localized))
self.addItem(NSMenuItem(
title: "mi_recommendations_count".localized(WarningManager.shared.warnings.count),
action: nil,
keyEquivalent: ""
))
self.addItem(NSMenuItem(
title: "mi_view_recommendations".localized,
action: #selector(MainMenu.openWarnings),
keyEquivalent: ""
))
}
func addCoreMenuItems() {

View File

@ -28,9 +28,9 @@ struct OnboardingTextItem: View {
Text(description.localizedForSwiftUI)
.foregroundColor(Color.secondary)
.font(.system(size: 13))
.lineLimit(6)
.lineLimit(4)
.fixedSize(horizontal: false, vertical: true)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.frame(minWidth: 0, maxWidth: 800, alignment: .leading)
}
}
.padding()
@ -41,8 +41,7 @@ struct OnboardingTextItem: View {
struct OnboardingView: View {
var body: some View {
VStack(spacing: 10) {
VStack(alignment: .center) {
VStack(alignment: .center, spacing: 5) {
HStack {
Image(nsImage: NSApp.applicationIconImage)
.resizable()
@ -111,10 +110,10 @@ struct OnboardingView: View {
App.shared.onboardingWindowController?.close()
}
}
}.padding()
}
.padding(.leading)
.padding(.trailing)
}
.padding(.top, 8)
}
}

View File

@ -11,23 +11,35 @@ import SwiftUI
struct WarningListView: View {
var body: some View {
VStack {
HStack(spacing: 15) {
HStack(alignment: .center, spacing: 15) {
Image(systemName: "stethoscope.circle.fill")
.resizable()
.frame(width: 40, height: 40)
.foregroundColor(Color.red)
.padding(12)
VStack(alignment: .trailing, spacing: 5) {
VStack(alignment: .leading, spacing: 5) {
Text("warnings.description".localizedForSwiftUI)
.font(.system(size: 12))
.frame(maxWidth: .infinity, alignment: .leading)
Text("warnings.disclaimer".localizedForSwiftUI)
.font(.system(size: 12))
.foregroundColor(.gray)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
.padding(10)
Divider()
HStack(alignment: .center, spacing: 15) {
Button("warnings.refresh.button".localizedForSwiftUI) {
WarningManager.shared.evaluateWarnings()
}
Text("warnings.refresh.button.description".localizedForSwiftUI)
.foregroundColor(.gray)
.font(.system(size: 11))
}
.padding(10)
List {
VStack(alignment: .leading, spacing: 0) {
ForEach(WarningManager.shared.warnings) { warning in

View File

@ -32,7 +32,7 @@ class WarningManager {
),
Warning(
command: {
!Paths.PATH.contains("/Users/\(Paths.whoami)/.config/phpmon/bin") &&
return !Shell.user.PATH.contains("/Users/\(Paths.whoami)/.config/phpmon/bin") &&
!FileManager.default.isWritableFile(atPath: "/usr/local/bin/")
},
name: "Helpers cannot be symlinked and not in PATH",
@ -74,6 +74,8 @@ class WarningManager {
if ProcessInfo.processInfo.environment["EXTREME_DOCTOR_MODE"] != nil {
self.warnings = self.evaluations
}
MainMenu.shared.rebuild()
}
}

View File

@ -55,7 +55,9 @@
"mi_detected_extensions" = "Detected Extensions";
"mi_no_extensions_detected" = "No additional extensions detected.";
"mi_warnings" = "(%i) PHP Doctor...";
"mi_php_doctor" = "PHP Doctor";
"mi_recommendations_count" = "%i Issue(s) Detected!";
"mi_view_recommendations" = "View Recommendations...";
"mi_valet" = "Laravel Valet";
"mi_domain_list" = "View Domains List...";
@ -517,6 +519,8 @@ If you are seeing this message but are confused why this folder has gone missing
"warnings.title" = "PHP Doctor";
"warnings.description" = "**PHP Doctor** will suggest improvements to your active system configuration.";
"warnings.disclaimer" = "You may choose to hide all recommendations from the PHP Monitor menu in Preferences, but it is recommended that you deal with all actionable items.";
"warnings.refresh.button" = "Scan Again";
"warnings.refresh.button.description" = "Press this button once you've fixed an issue. This will cause PHP Monitor to re-evaluate your environment. If it's really fixed, the recommendation should disappear.";
"warnings.helper_permissions.title" = "PHP Monitors helpers are currently unavailable.";
"warnings.helper_permissions.description" = "PHP Monitor comes with various helper binaries. Using these binaries allows you to easily invoke a specific version of PHP without switching the linked PHP version.";
@ -531,14 +535,14 @@ If you are seeing this message but are confused why this folder has gone missing
"onboarding.title" = "Welcome Tour";
"onboarding.welcome" = "Welcome to PHP Monitor!";
"onboarding.explore" = "Learn more about some of the features that PHP Monitor has to offer. You can find a more comprehensive list of features on GitHub.";
"onboarding.tour.menu_bar.title" = "Get Started";
"onboarding.tour.menu_bar" = "PHP Monitor lives in your menu bar. From here, you can switch the globally linked PHP version, start or stop services, locate config files, and more.";
"onboarding.tour.menu_bar.title" = "Power In Your Menu Bar";
"onboarding.tour.menu_bar" = "PHP Monitor lives in your menu bar. From this menu, you can access most of PHP Monitor's key functionality, including switching the globally linked PHP version, locating config files, and much more.";
"onboarding.tour.faq_hint" = "I recommend that you check out the [README](https://github.com/nicoverbruggen/phpmon/blob/main/README.md) on GitHub: it contains a comprehensive FAQ with various tips and common questions and answers.";
"onboarding.tour.services.title" = "Manage Services";
"onboarding.tour.services" = "Once you click on the menu bar item, you can see at a glance based on the checkmarks or crosses if all of the Homebrew services are up and running. You can also click on a service to quickly toggle it. You can also add your own!";
"onboarding.tour.services.title" = "Manage Homebrew Services";
"onboarding.tour.services" = "Once you click on the menu bar item, you can see at a glance based on the checkmarks or crosses if all of the Homebrew services are up and running. You can also click on a service to quickly toggle it.";
"onboarding.tour.domains.title" = "Manage Domains";
"onboarding.tour.domains" = "By opening the Domains window via the menu bar item, you can view which domains are linked and parked, as well as active nginx proxies.";
"onboarding.tour.isolation.title" = "Isolate Domains";
"onboarding.tour.isolation" = "If you have Valet 3 installed, you can even use domain isolation by right-clicking on a given domain in the Domains window. This allows you to pick a specific version of PHP to use for that domain, and that domain only!";
"onboarding.tour.isolation" = "If you have Valet 3 installed, you can even use domain isolation by right-clicking on a given domain in the Domains window. This allows you to pick a specific version of PHP to use for that domain, and that domain only.";
"onboarding.tour.once" = "You will only see the Welcome Tour once. You can re-open the Welcome Tour later via the menu bar icon (under First Aid & Services).";
"onboarding.tour.close" = "Close Tour";