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

Compare commits

..

8 Commits

Author SHA1 Message Date
a6c3f0ceba 🍱 Use classic DEV channel icon 2023-02-27 19:16:15 +01:00
f274e9e004 👌 Updated IAP for accessing formulae.brew.sh 2023-02-27 19:08:04 +01:00
a07881a987 👌 Fix copy of missing config check 2023-02-27 19:04:50 +01:00
715b674929 Fix tests 2023-02-26 15:02:43 +01:00
cb504cc3f0 🔧 Bump build 2023-02-24 19:37:41 +01:00
7c08a2fdfe 👌 Improve PHP Doctor w/ async code
- This fixes an issue with PHP Doctor's "Scan Again" button not working.
- This also adds a new check which verifies if "php.ini", "php-fpm.conf"
  and "php-fpm.d/valet-fpm.conf" exist (all required files).
2023-02-24 19:36:12 +01:00
2f47610c85 🔧 Use macOS 12.4 deployment target 2023-02-21 02:27:03 +01:00
cc6324b692 ♻️ PHP Guard changes 2023-02-20 18:15:12 +01:00
27 changed files with 213 additions and 153 deletions

View File

@ -112,6 +112,7 @@
C43A8A1A25D9CD1000591B77 /* Utility.swift in Sources */ = {isa = PBXBuildFile; fileRef = C43A8A1925D9CD1000591B77 /* Utility.swift */; };
C43A8A2025D9D1D700591B77 /* brew-formula.json in Resources */ = {isa = PBXBuildFile; fileRef = C43A8A1F25D9D1D700591B77 /* brew-formula.json */; };
C43A8A2425D9D20D00591B77 /* HomebrewPackageTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C43A8A2325D9D20D00591B77 /* HomebrewPackageTest.swift */; };
C43FDBE929A932B0003D85EC /* PhpConfigChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = C43FDBE829A932B0003D85EC /* PhpConfigChecker.swift */; };
C44067F527E2582B0045BD4E /* DomainListNameCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44067F427E2582B0045BD4E /* DomainListNameCell.swift */; };
C44067F727E258410045BD4E /* DomainListPhpCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44067F627E258410045BD4E /* DomainListPhpCell.swift */; };
C44067F927E2585E0045BD4E /* DomainListTypeCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44067F827E2585E0045BD4E /* DomainListTypeCell.swift */; };
@ -709,6 +710,9 @@
C4FACE83288F1F9700FC478F /* OnboardingWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4FACE82288F1F9700FC478F /* OnboardingWindowController.swift */; };
C4FBFC532616485F00CDB8E1 /* PhpVersionDetectionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4FBFC512616485F00CDB8E1 /* PhpVersionDetectionTest.swift */; };
C4FC21B128391F8E00D368BB /* MainMenu+Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F361602836BFD9003598CC /* MainMenu+Actions.swift */; };
C4FD87A529AB98720002D701 /* PhpConfigChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = C43FDBE829A932B0003D85EC /* PhpConfigChecker.swift */; };
C4FD87A629AB98730002D701 /* PhpConfigChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = C43FDBE829A932B0003D85EC /* PhpConfigChecker.swift */; };
C4FD87A729AB98730002D701 /* PhpConfigChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = C43FDBE829A932B0003D85EC /* PhpConfigChecker.swift */; };
C4FE011128084FC200D1DE6D /* SelectionVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4FE011028084FC200D1DE6D /* SelectionVC.swift */; };
C4FE011228084FC200D1DE6D /* SelectionVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4FE011028084FC200D1DE6D /* SelectionVC.swift */; };
/* End PBXBuildFile section */
@ -811,6 +815,7 @@
C43A8A1925D9CD1000591B77 /* Utility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utility.swift; sourceTree = "<group>"; };
C43A8A1F25D9D1D700591B77 /* brew-formula.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "brew-formula.json"; sourceTree = "<group>"; };
C43A8A2325D9D20D00591B77 /* HomebrewPackageTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomebrewPackageTest.swift; sourceTree = "<group>"; };
C43FDBE829A932B0003D85EC /* PhpConfigChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpConfigChecker.swift; sourceTree = "<group>"; };
C44067F427E2582B0045BD4E /* DomainListNameCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainListNameCell.swift; sourceTree = "<group>"; };
C44067F627E258410045BD4E /* DomainListPhpCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainListPhpCell.swift; sourceTree = "<group>"; };
C44067F827E2585E0045BD4E /* DomainListTypeCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DomainListTypeCell.swift; sourceTree = "<group>"; };
@ -1219,6 +1224,7 @@
C422DDAB28A2DAA100CEAC97 /* Warnings */ = {
isa = PBXGroup;
children = (
C43FDBE729A9329A003D85EC /* Services */,
C47699F028A2F3150060FEB8 /* Warning.swift */,
C47699EE28A2F2A30060FEB8 /* WarningManager.swift */,
C422DDAC28A2DAC600CEAC97 /* WarningsWindowController.swift */,
@ -1244,6 +1250,14 @@
path = Warning;
sourceTree = "<group>";
};
C43FDBE729A9329A003D85EC /* Services */ = {
isa = PBXGroup;
children = (
C43FDBE829A932B0003D85EC /* PhpConfigChecker.swift */,
);
path = Services;
sourceTree = "<group>";
};
C44067F327E256560045BD4E /* Cells */ = {
isa = PBXGroup;
children = (
@ -2155,6 +2169,7 @@
C4D9ADC8277611A0007277F4 /* InternalSwitcher.swift in Sources */,
C4FACE83288F1F9700FC478F /* OnboardingWindowController.swift in Sources */,
C4080FFA27BD956700BF2C6B /* BetterAlertVC.swift in Sources */,
C43FDBE929A932B0003D85EC /* PhpConfigChecker.swift in Sources */,
C4BF56AB2949381100379603 /* FakeValetInteractor.swift in Sources */,
C4B5635E276AB09000F12CCB /* VersionExtractor.swift in Sources */,
C451AFF62969E40F0078E617 /* HelpButton.swift in Sources */,
@ -2209,6 +2224,7 @@
C471E84328F9BB650021E251 /* App.swift in Sources */,
C4E2E85E28FC282B003B070C /* TestableConfiguration.swift in Sources */,
C491997D29901DF7001F3A21 /* CaskFile.swift in Sources */,
C4FD87A629AB98730002D701 /* PhpConfigChecker.swift in Sources */,
C45E2A7529199248005C7CFD /* InternalSwitcherTest.swift in Sources */,
C471E84428F9BB650021E251 /* App+ActivationPolicy.swift in Sources */,
C471E84528F9BB650021E251 /* App+GlobalHotkey.swift in Sources */,
@ -2358,6 +2374,7 @@
C471E89028F9BB8F0021E251 /* AlertableError.swift in Sources */,
C471E89128F9BB8F0021E251 /* Errors.swift in Sources */,
C471E89228F9BB8F0021E251 /* Alert.swift in Sources */,
C4FD87A529AB98720002D701 /* PhpConfigChecker.swift in Sources */,
C471E89328F9BB8F0021E251 /* Application.swift in Sources */,
C471E89428F9BB8F0021E251 /* LocalNotification.swift in Sources */,
C471E89528F9BB8F0021E251 /* MenuBarImageGenerator.swift in Sources */,
@ -2606,6 +2623,7 @@
C4D936CB27E3EE4A00BD69FE /* DomainListCellProtocol.swift in Sources */,
C4B97B76275CF08C003F3378 /* AppDelegate+MenuOutlets.swift in Sources */,
C4F780CD25D80B75000DBC97 /* Alert.swift in Sources */,
C4FD87A729AB98730002D701 /* PhpConfigChecker.swift in Sources */,
C485706D28BF450900539B36 /* NSMenuItemExtension.swift in Sources */,
C481F79726164A78004FBCFF /* PrefsVC.swift in Sources */,
C495F5B028A42E080087F70A /* EnvironmentCheck.swift in Sources */,
@ -2792,7 +2810,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 11.0;
MACOSX_DEPLOYMENT_TARGET = 12.4;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
@ -2849,7 +2867,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 11.0;
MACOSX_DEPLOYMENT_TARGET = 12.4;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
@ -2867,7 +2885,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1071;
CURRENT_PROJECT_VERSION = 1075;
DEAD_CODE_STRIPPING = YES;
DEBUG = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
@ -2879,7 +2897,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MACOSX_DEPLOYMENT_TARGET = 12.4;
MARKETING_VERSION = 5.8;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -2897,7 +2915,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1071;
CURRENT_PROJECT_VERSION = 1075;
DEAD_CODE_STRIPPING = YES;
DEBUG = NO;
DEVELOPMENT_TEAM = 8M54J5J787;
@ -2909,7 +2927,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MACOSX_DEPLOYMENT_TARGET = 12.4;
MARKETING_VERSION = 5.8;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -3108,7 +3126,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 11.0;
MACOSX_DEPLOYMENT_TARGET = 12.4;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
@ -3120,13 +3138,13 @@
C4975D0828CD190C00FFB4E8 /* Release.Dev */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconEA;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconDev;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppColor;
CODE_SIGN_ENTITLEMENTS = phpmon/phpmon.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1071;
CURRENT_PROJECT_VERSION = 1075;
DEBUG = NO;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
@ -3137,7 +3155,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MACOSX_DEPLOYMENT_TARGET = 12.4;
MARKETING_VERSION = 5.8;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon.dev;
PRODUCT_NAME = "$(TARGET_NAME) DEV";
@ -3218,7 +3236,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 11.0;
MACOSX_DEPLOYMENT_TARGET = 12.4;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
@ -3231,13 +3249,13 @@
C4975D0B28CD193A00FFB4E8 /* Debug.Dev */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconEA;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconDev;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppColor;
CODE_SIGN_ENTITLEMENTS = phpmon/phpmon.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1071;
CURRENT_PROJECT_VERSION = 1075;
DEBUG = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
@ -3248,7 +3266,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MACOSX_DEPLOYMENT_TARGET = 12.4;
MARKETING_VERSION = 5.8;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon.dev;
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@ -24,7 +24,7 @@ You can also add new domains as links, isolate sites, manage various services, a
PHP Monitor is a universal application that runs natively on Apple Silicon **and** Intel-based Macs.
* Your user account can administer your computer (required for some functionality, e.g. certificate generation)
* macOS 11 Big Sur or later
* macOS 12.4 or later (Monterey and Ventura are supported)
* Homebrew is installed in `/usr/local/homebrew` or `/opt/homebrew`
* Homebrew `php` formula is installed
* Laravel Valet (works with Valet v2, v3 and v4)
@ -275,6 +275,8 @@ This problem is usually resolved by upgrading Valet and running `valet install`
composer global update
valet install
If you are seeing a 502 (Bad Gateway) error after about 30 seconds or so, your request is likely timing out. You may need to solve a performance issue with your own code.
</details>

View File

@ -6,7 +6,7 @@ Generally speaking, only the latest version of **PHP Monitor** is supported, exc
| Version | Apple Silicon | Supported | Supported macOS | Deployment Target | Detected PHP Versions | Recommended Valet Version |
| ------- | ------------- | ------------------ | ----- | ----- | ----- | ----
| 5.7 | ✅ Universal binary | ✅ Yes | Big Sur (11.0)<br/>Monterey (12.0)<br/>Ventura (13.0) | macOS 11+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)<br/>PHP 7.0—PHP 8.2 (w/ Valet 3.x)<br/>PHP 7.1-PHP 8.2 (w/ Valet 4.x*) | 3.0 or higher recommended<br/> 2.16.2 minimum |
| 5.8 | ✅ Universal binary | ✅ Yes | Monterey (12.4+)<br/>Ventura (13.0+) | macOS 12.4 | PHP 5.6—PHP 8.2 (w/ Valet 2.x)<br/>PHP 7.0—PHP 8.2 (w/ Valet 3.x)<br/>PHP 7.1-PHP 8.2 (w/ Valet 4.x*) | 3.0 or higher recommended<br/> 2.16.2 minimum |
(*) Preliminary listing. Valet 4 hasn't been released yet and the versions of PHP Valet can work with might still change.
@ -16,6 +16,7 @@ These versions of PHP Monitor are no longer supported, but if youre using an
| Version | Apple Silicon | Supported | Supported macOS | Deployment Target | Detected PHP Versions | Minimum Required Valet Version |
| ------- | ------------- | ------------------ | ----- | ----- | ----- | ----
| 5.7 | ✅ Universal binary | ❌ | Big Sur (11.0)<br/>Monterey (12.0)<br/>Ventura (13.0)* | macOS 11+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)<br/>PHP 7.0—PHP 8.2 (w/ Valet 3.x) | 3.0 recommended<br/> 2.16.2 minimum |
| 5.6 | ✅ Universal binary | ❌ | Big Sur (11.0)<br/>Monterey (12.0)<br/>Ventura (13.0)* | macOS 11+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)<br/>PHP 7.0—PHP 8.2 (w/ Valet 3.x) | 3.0 recommended<br/> 2.16.2 minimum |
| 4.1 | ✅ Universal binary | ❌ | Big Sur (11.0)<br/>Monterey (12.0) | macOS 11+ | PHP 5.6—PHP 8.2 | 2.16.2 |
| 4.0 | ✅ Universal binary | ❌ | Big Sur (11.0)<br/>Monterey (12.0) | macOS 10.14+ | PHP 5.6—PHP 8.2 | 2.13 |

View File

@ -1,68 +0,0 @@
{
"images" : [
{
"filename" : "icon_16x16.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"filename" : "icon_16x16@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"filename" : "icon_32x32.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"filename" : "icon_32x32@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"filename" : "icon_128x128.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"filename" : "icon_128x128@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"filename" : "icon_256x256.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"filename" : "icon_256x256@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"filename" : "icon_512x512.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"filename" : "icon_512x512@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 575 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

View File

@ -15,7 +15,7 @@ class AppVersion: Comparable {
init(version: String, build: String?, suffix: String? = nil) {
self.version = version
self.build = Int(build ?? "0")
self.build = build == nil ? nil : Int(build!)
self.suffix = suffix
}

View File

@ -40,6 +40,9 @@ struct CaskFile {
let lines = string.split(separator: "\n")
.filter { $0 != "" }
.map { line in
return line.trimmingCharacters(in: .whitespacesAndNewlines)
}
if lines.count < 4 {
Log.err("The CaskFile is <4 lines long, which is too short")

View File

@ -9,6 +9,7 @@
import Foundation
import Cocoa
@MainActor
class BetterAlert {
var windowController: NSWindowController!

View File

@ -142,42 +142,50 @@ class Stats {
}
public static func evaluateLastLinkedPhpVersion() {
let currentVersion = PhpEnv.phpInstall.version.short
let currentVersion = PhpEnv.phpInstall.version?.short ?? ""
let previousVersion = Stats.lastGlobalPhpVersion
// Save the PHP version that is currently in use (only if unknown)
if Stats.lastGlobalPhpVersion == "" {
if currentVersion == "" {
return Log.warn("<PG> PHP Guard is unable to determine the current PHP version!")
}
Log.info("<PG> The currently linked version of PHP is: \(currentVersion).")
if previousVersion == "" {
Stats.persistCurrentGlobalPhpVersion(version: currentVersion)
Log.info("Persisting the currently linked PHP version (first time only).")
} else {
Log.info("Previously, the globally linked PHP version was: \(previousVersion).")
if previousVersion != currentVersion {
Log.info("Currently, that version is: \(currentVersion). This is a mismatch.")
Task { @MainActor in
BetterAlert()
.withInformation(
title: "startup.version_mismatch.title".localized,
subtitle: "startup.version_mismatch.subtitle".localized(
currentVersion,
previousVersion
),
description: "startup.version_mismatch.desc".localized()
)
.withPrimary(text: "startup.version_mismatch.button_switch_back".localized(
previousVersion
), action: { alert in
alert.close(with: .OK)
Task { MainMenu.shared.switchToAnyPhpVersion(previousVersion) }
})
.withTertiary(text: "startup.version_mismatch.button_stay".localized(
currentVersion
), action: { alert in
Stats.persistCurrentGlobalPhpVersion(version: currentVersion)
alert.close(with: .OK)
})
.show()
}
}
return Log.warn("<PG> PHP Guard is saving the currently linked PHP version (first time only).")
}
Log.info("<PG> Previously, the globally linked PHP version was: \(previousVersion).")
if previousVersion == currentVersion {
return Log.info("<PG> PHP Guard did not notice any changes in the linked PHP version.")
}
// At this point, the version is *not* a match
Log.info("<PG> PHP Guard noticed a different PHP version. An alert will be displayed!")
Task { @MainActor in
BetterAlert()
.withInformation(
title: "startup.version_mismatch.title".localized,
subtitle: "startup.version_mismatch.subtitle".localized(
currentVersion,
previousVersion
),
description: "startup.version_mismatch.desc".localized()
)
.withPrimary(text: "startup.version_mismatch.button_switch_back".localized(
previousVersion
), action: { alert in
alert.close(with: .OK)
Task { MainMenu.shared.switchToAnyPhpVersion(previousVersion) }
})
.withTertiary(text: "startup.version_mismatch.button_stay".localized(
currentVersion
), action: { alert in
Stats.persistCurrentGlobalPhpVersion(version: currentVersion)
alert.close(with: .OK)
})
.show()
}
}
}

View File

@ -9,10 +9,14 @@
import SwiftUI
struct WarningListView: View {
@State var warnings: [Warning]
@ObservedObject var warningManager: WarningManager
init(empty: Bool = false) {
self.warnings = empty ? [] : WarningManager.shared.warnings
if empty {
WarningManager.shared.warnings = []
}
warningManager = WarningManager.shared
}
var body: some View {
@ -40,7 +44,6 @@ struct WarningListView: View {
Button("warnings.refresh.button".localizedForSwiftUI) {
Task { // Reload warnings
await WarningManager.shared.checkEnvironment()
self.warnings = WarningManager.shared.warnings
}
}
Text("warnings.refresh.button.description".localizedForSwiftUI)
@ -51,14 +54,14 @@ struct WarningListView: View {
List {
VStack(alignment: .leading, spacing: 0) {
if warnings.isEmpty {
if warningManager.warnings.isEmpty {
NoWarningsView()
} else {
ForEach(warnings) { warning in
ForEach(warningManager.warnings) { warning in
Group {
WarningView(
title: warning.title,
paragraphs: warning.paragraphs,
paragraphs: warning.paragraphs(),
documentationUrl: warning.url
)
.fixedSize(horizontal: false, vertical: true)
@ -67,7 +70,8 @@ struct WarningListView: View {
}.padding(5)
}
}
}.frame(minHeight: 0, maxHeight: .infinity).padding(5)
}
.frame(minHeight: 0, maxHeight: .infinity).padding(5)
}
.listRowInsets(EdgeInsets())
.listStyle(.plain)

View File

@ -26,7 +26,7 @@ struct WarningView: View {
Text(title.localizedForSwiftUI)
.fontWeight(.bold)
ForEach(paragraphs, id: \.self) { paragraph in
Text(paragraph.localizedForSwiftUI)
Text(paragraph)
.font(.system(size: 13))
}
}

View File

@ -0,0 +1,39 @@
//
// PhpConfigChecker.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 24/02/2023.
// Copyright © 2023 Nico Verbruggen. All rights reserved.
//
import Foundation
class PhpConfigChecker {
public static var shared = PhpConfigChecker()
var missing: [String] = []
public func check() {
missing = []
let shouldExist = [
"php.ini",
"php-fpm.conf",
"php-fpm.d/valet-fpm.conf"
]
for version in PhpEnv.shared.availablePhpVersions {
for file in shouldExist {
let fullFilePath = Paths.etcPath.appending("/php/\(version)/\(file)")
if !FileSystem.fileExists(fullFilePath) {
missing.append(fullFilePath)
}
}
}
if !missing.isEmpty {
Log.warn("The following config file(s) were missing: \(missing)")
}
}
}

View File

@ -8,19 +8,27 @@
import Foundation
struct Warning: Identifiable {
struct Warning: Identifiable, Hashable {
var id = UUID()
let command: () async -> Bool
let name: String
let title: String
let paragraphs: [String]
let paragraphs: () -> [String]
let url: String?
/**
- Parameters:
- command: The command that, if it returns true, means that a warning applies
- name: The internal name or description for this warning
- title: The title displayed for the user
- paragraphs: The main body of text displayed for the user
- url: The URL that one can navigate to for more information (if applicable)
*/
init(
command: @escaping () async -> Bool,
name: String,
title: String,
paragraphs: [String],
paragraphs: @escaping () -> [String],
url: String?
) {
self.command = command
@ -33,4 +41,12 @@ struct Warning: Identifiable {
public func applies() async -> Bool {
return await self.command()
}
public static func == (lhs: Warning, rhs: Warning) -> Bool {
return lhs.hashValue == rhs.hashValue
}
public func hash(into hasher: inout Hasher) {
hasher.combine(self.id)
}
}

View File

@ -9,9 +9,9 @@
import Foundation
import Cocoa
class WarningManager {
class WarningManager: ObservableObject {
static var shared = WarningManager()
static var shared: WarningManager = WarningManager()
init() {
if isRunningSwiftUIPreview {
@ -26,8 +26,8 @@ class WarningManager {
.trimmingCharacters(in: .whitespacesAndNewlines) == "1"
},
name: "Running PHP Monitor with Rosetta on M1",
title: "warnings.arm_compatibility.title",
paragraphs: ["warnings.arm_compatibility.description"],
title: "warnings.arm_compatibility.title".localized,
paragraphs: { return ["warnings.arm_compatibility.description".localized] },
url: "https://github.com/nicoverbruggen/phpmon/wiki/PHP-Monitor-and-Apple-Silicon"
),
Warning(
@ -36,13 +36,27 @@ class WarningManager {
!FileSystem.isWriteableFile("/usr/local/bin/")
},
name: "Helpers cannot be symlinked and not in PATH",
title: "warnings.helper_permissions.title",
paragraphs: [
"warnings.helper_permissions.description",
"warnings.helper_permissions.unavailable",
"warnings.helper_permissions.symlink"
],
title: "warnings.helper_permissions.title".localized,
paragraphs: { return [
"warnings.helper_permissions.description".localized,
"warnings.helper_permissions.unavailable".localized,
"warnings.helper_permissions.symlink".localized
] },
url: "https://github.com/nicoverbruggen/phpmon/wiki/PHP-Monitor-helper-binaries"
),
Warning(
command: {
PhpConfigChecker.shared.check()
return !PhpConfigChecker.shared.missing.isEmpty
},
name: "Your PHP installation is missing configuration files",
title: "warnings.files_missing.title".localized,
paragraphs: { return [
"warnings.files_missing.description".localized(
PhpConfigChecker.shared.missing.joined(separator: "\n")
)
] },
url: nil
)
]
@ -60,11 +74,11 @@ class WarningManager {
Checks the user's environment and checks if any special warnings apply.
*/
func checkEnvironment() async {
self.warnings = []
if ProcessInfo.processInfo.environment["EXTREME_DOCTOR_MODE"] != nil {
// For debugging purposes, we may wish to see all possible evaluations listed
self.warnings = self.evaluations
Task { @MainActor in
self.warnings = self.evaluations
}
} else {
// Otherwise, loop over the actual evaluations and list the warnings
await loopOverEvaluations()
@ -74,9 +88,14 @@ class WarningManager {
}
private func loopOverEvaluations() async {
Task { @MainActor in
self.warnings = []
}
for check in self.evaluations where await check.applies() {
Log.info("[DOCTOR] \(check.name) (!)")
self.warnings.append(check)
Task { @MainActor in
self.warnings.append(check)
}
continue
}
}

View File

@ -10,6 +10,22 @@
<string>https://github.com/nicoverbruggen/phpmon</string>
<key>Connections</key>
<array>
<dict>
<key>IsIncoming</key>
<false/>
<key>Host</key>
<string>github.com, api.github.com</string>
<key>NetworkProtocol</key>
<string>TCP</string>
<key>Port</key>
<string>443</string>
<key>Relevance</key>
<string>Essential</string>
<key>Purpose</key>
<string>PHP Monitor directly invokes Homebrew which contacts GitHub. This happens when PHP Monitor asks for more information about the PHP formula to determine which version of PHP you&apos;ve got running.</string>
<key>DenyConsequences</key>
<string>If you deny these connections, PHP Monitor might not be able to complete its preset set of instructions, causing version switching to fail.</string>
</dict>
<dict>
<key>IsIncoming</key>
<false/>
@ -46,15 +62,15 @@
<key>IsIncoming</key>
<false/>
<key>Host</key>
<string>github.com, api.github.com</string>
<string>formulae.brew.sh</string>
<key>NetworkProtocol</key>
<string>TCP</string>
<key>Port</key>
<string>443</string>
<string>80, 443</string>
<key>Relevance</key>
<string>Essential</string>
<key>Purpose</key>
<string>PHP Monitor directly invokes Homebrew which contacts GitHub. This happens when PHP Monitor asks for more information about the PHP formula to determine which version of PHP you&apos;ve got running.</string>
<string>PHP Monitor directly invokes Homebrew which contacts the Homebrew API. This happens when PHP Monitor asks for more information about the PHP formula to determine which version of PHP you&apos;ve got running.</string>
<key>DenyConsequences</key>
<string>If you deny these connections, PHP Monitor might not be able to complete its preset set of instructions, causing version switching to fail.</string>
</dict>

View File

@ -661,6 +661,13 @@ COMMON TROUBLESHOOTING TIPS
"warnings.arm_compatibility.title" = "You are running PHP Monitor using Rosetta on Apple Silicon, which means your PHP environment is also running via Rosetta.";
"warnings.arm_compatibility.description" = "You appear to be running an ARM-compatible version of macOS, but you are currently running PHP Monitor using Rosetta. While this will work correctly, it is recommended that you use the native version of Homebrew.";
"warnings.files_missing.title" = "Your PHP installation is missing important required configuration files.";
"warnings.files_missing.description" = "The following key configuration files should exist after installing PHP:
• %@
When files like these are missing, it's recommended to reinstall the appropriate PHP version(s) via Homebrew again, which should restore the configuration files that are missing. Missing configuration files can be the reason why you get '502 Bad Gateway' errors, even after running Fix My Valet.";
"warnings.none" = "There are no recommendations available for you right now. You're all good!";
// ONBOARDING

View File

@ -138,7 +138,7 @@ class TestableConfigurations {
: .instant(ShellStrings.shared.brewServicesAsRoot),
"/opt/homebrew/bin/brew services info --all --json"
: .instant(ShellStrings.shared.brewServicesAsUser),
"curl -s --max-time 5 '\(Constants.Urls.StableBuildCaskFile.absoluteString)' | grep version"
"curl -s --max-time 10 '\(Constants.Urls.DevBuildCaskFile.absoluteString)'"
: .instant("version '5.6.2_976'"),
"/opt/homebrew/bin/brew unlink php"
: .delayed(0.2, "OK"),

View File

@ -37,10 +37,4 @@ class ValetVersionExtractorTest: XCTestCase {
XCTAssertEqual(version.major, 3)
}
func test_can_determine_valet_version() async {
let version = await valet("--version", sudo: false)
XCTAssert(version.contains("Laravel Valet 2") || version.contains("Laravel Valet 3"))
}
}