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

♻️ Rework various common classes

This commit is contained in:
2021-12-21 16:00:27 +01:00
parent a6387e96e7
commit ceb168c6cf
21 changed files with 272 additions and 216 deletions

View File

@ -27,6 +27,14 @@
C40C7F1E2772136000DDDCDC /* PhpSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F1D2772136000DDDCDC /* PhpSwitcher.swift */; };
C40C7F1F2772136000DDDCDC /* PhpSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F1D2772136000DDDCDC /* PhpSwitcher.swift */; };
C40C7F202772136000DDDCDC /* PhpSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F1D2772136000DDDCDC /* PhpSwitcher.swift */; };
C40C7F2227721F8200DDDCDC /* PhpInstallation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F2E4392752F7D00020E974 /* PhpInstallation.swift */; };
C40C7F2327721F8200DDDCDC /* ActivePhpInstallation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4A22B019FF00E7CF16 /* ActivePhpInstallation.swift */; };
C40C7F2427721F8200DDDCDC /* PhpExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4ACA38E25C754C100060C66 /* PhpExtension.swift */; };
C40C7F2527721F9800DDDCDC /* HomebrewPackage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */; };
C40C7F2627721FA200DDDCDC /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EE188322D3386B00E126E5 /* Constants.swift */; };
C40C7F2827721FF600DDDCDC /* ActivePhpInstallation+Checks.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F2727721FF600DDDCDC /* ActivePhpInstallation+Checks.swift */; };
C40C7F2927721FF600DDDCDC /* ActivePhpInstallation+Checks.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F2727721FF600DDDCDC /* ActivePhpInstallation+Checks.swift */; };
C40C7F2B2772201C00DDDCDC /* Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415D3B62770F294005EF286 /* Actions.swift */; };
C412E5FC25700D5300A1FB67 /* HomebrewPackage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */; };
C415D3B72770F294005EF286 /* Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415D3B62770F294005EF286 /* Actions.swift */; };
C415D3B82770F294005EF286 /* Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415D3B62770F294005EF286 /* Actions.swift */; };
@ -180,6 +188,7 @@
C405A4CE24B9B9130062FAFA /* InternetAccessPolicy.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = InternetAccessPolicy.strings; sourceTree = "<group>"; };
C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = InternetAccessPolicy.plist; sourceTree = "<group>"; };
C40C7F1D2772136000DDDCDC /* PhpSwitcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpSwitcher.swift; sourceTree = "<group>"; };
C40C7F2727721FF600DDDCDC /* ActivePhpInstallation+Checks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ActivePhpInstallation+Checks.swift"; sourceTree = "<group>"; };
C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomebrewPackage.swift; sourceTree = "<group>"; };
C415D3B62770F294005EF286 /* Actions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Actions.swift; sourceTree = "<group>"; };
C415D3D62770F341005EF286 /* phpmon-cli */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "phpmon-cli"; sourceTree = BUILT_PRODUCTS_DIR; };
@ -298,6 +307,8 @@
54B20EDF263AA22C00D3250E /* PHP */ = {
isa = PBXGroup;
children = (
C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */,
C40C7F1D2772136000DDDCDC /* PhpSwitcher.swift */,
C41C1B4A22B019FF00E7CF16 /* ActivePhpInstallation.swift */,
C4F2E4392752F7D00020E974 /* PhpInstallation.swift */,
C4ACA38E25C754C100060C66 /* PhpExtension.swift */,
@ -335,6 +346,26 @@
path = "Test Files";
sourceTree = "<group>";
};
C40C7F2127721F7300DDDCDC /* Core */ = {
isa = PBXGroup;
children = (
C415D3B62770F294005EF286 /* Actions.swift */,
C4EE188322D3386B00E126E5 /* Constants.swift */,
C4B5853D2770FE3900DA4FBE /* Command.swift */,
C4B5853B2770FE3900DA4FBE /* Paths.swift */,
C4B5853C2770FE3900DA4FBE /* Shell.swift */,
);
path = Core;
sourceTree = "<group>";
};
C40C7F2C2772204700DDDCDC /* PHP */ = {
isa = PBXGroup;
children = (
C40C7F2727721FF600DDDCDC /* ActivePhpInstallation+Checks.swift */,
);
path = PHP;
sourceTree = "<group>";
};
C415D3D72770F341005EF286 /* phpmon-cli */ = {
isa = PBXGroup;
children = (
@ -373,7 +404,6 @@
C41C1B3522B0097F00E7CF16 /* phpmon */ = {
isa = PBXGroup;
children = (
C4EE188322D3386B00E126E5 /* Constants.swift */,
C41E181722CB61EB0072CF09 /* Domain */,
C41C1B3F22B0098000E7CF16 /* Info.plist */,
C4232EE42612526500158FC6 /* Credits.html */,
@ -398,7 +428,7 @@
children = (
C4AF9F6B275445D300D44ED0 /* Integrations */,
C4B13B1D25C4915000548C3A /* Core */,
54B20EDF263AA22C00D3250E /* PHP */,
C40C7F2C2772204700DDDCDC /* PHP */,
C47331A0247093AC009A0597 /* Menu */,
C464ADAA275A7A25003FCD53 /* SiteList */,
5420395726135DB800FB00FA /* Preferences */,
@ -480,7 +510,6 @@
isa = PBXGroup;
children = (
C4F2E4362752F0870020E974 /* HomebrewDiagnostics.swift */,
C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */,
);
path = Homebrew;
sourceTree = "<group>";
@ -497,7 +526,6 @@
C4B97B77275CF1B5003F3378 /* App+ActivationPolicy.swift */,
C4B97B7A275CF20A003F3378 /* App+GlobalHotkey.swift */,
C4D8016522B1584700C6DA1B /* Startup.swift */,
C415D3B62770F294005EF286 /* Actions.swift */,
);
path = Core;
sourceTree = "<group>";
@ -505,10 +533,8 @@
C4B5853A2770FE2500DA4FBE /* phpmon-common */ = {
isa = PBXGroup;
children = (
C4B5853D2770FE3900DA4FBE /* Command.swift */,
C4B5853B2770FE3900DA4FBE /* Paths.swift */,
C4B5853C2770FE3900DA4FBE /* Shell.swift */,
C40C7F1D2772136000DDDCDC /* PhpSwitcher.swift */,
C40C7F2127721F7300DDDCDC /* Core */,
54B20EDF263AA22C00D3250E /* PHP */,
);
path = "phpmon-common";
sourceTree = "<group>";
@ -710,10 +736,16 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C40C7F2427721F8200DDDCDC /* PhpExtension.swift in Sources */,
C40C7F2627721FA200DDDCDC /* Constants.swift in Sources */,
C4B585402770FE3900DA4FBE /* Paths.swift in Sources */,
C415D3E62770F540005EF286 /* main.swift in Sources */,
C40C7F2227721F8200DDDCDC /* PhpInstallation.swift in Sources */,
C4B585432770FE3900DA4FBE /* Shell.swift in Sources */,
C40C7F2327721F8200DDDCDC /* ActivePhpInstallation.swift in Sources */,
C4B585462770FE3900DA4FBE /* Command.swift in Sources */,
C40C7F2527721F9800DDDCDC /* HomebrewPackage.swift in Sources */,
C40C7F2B2772201C00DDDCDC /* Actions.swift in Sources */,
C415D3E12770F34D005EF286 /* AllowedArguments.swift in Sources */,
C40C7F202772136000DDDCDC /* PhpSwitcher.swift in Sources */,
);
@ -737,6 +769,7 @@
C4F2E43A2752F7D00020E974 /* PhpInstallation.swift in Sources */,
C41E871A2763D42300161EE0 /* SiteListVC+ContextMenu.swift in Sources */,
C48D0CA325CC992000CC7490 /* StatsView.swift in Sources */,
C40C7F2827721FF600DDDCDC /* ActivePhpInstallation+Checks.swift in Sources */,
C4EE55A927708B9E001DF387 /* PMHeaderView.swift in Sources */,
C4F2E4372752F0870020E974 /* HomebrewDiagnostics.swift in Sources */,
C4CCBA6C275C567B008C7055 /* PMWindowController.swift in Sources */,
@ -794,6 +827,7 @@
C4F780CC25D80B75000DBC97 /* ActivePhpInstallation.swift in Sources */,
C4F780B125D80B4D000DBC97 /* PhpExtension.swift in Sources */,
C4F780CE25D80B75000DBC97 /* LocalNotification.swift in Sources */,
C40C7F2927721FF600DDDCDC /* ActivePhpInstallation+Checks.swift in Sources */,
C4FBFC532616485F00CDB8E1 /* PhpVersionDetectionTest.swift in Sources */,
C43A8A2425D9D20D00591B77 /* BrewJsonParserTest.swift in Sources */,
C4F780CA25D80B75000DBC97 /* HomebrewPackage.swift in Sources */,
@ -1020,7 +1054,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 200;
CURRENT_PROJECT_VERSION = 220;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = phpmon/Info.plist;
@ -1045,7 +1079,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 200;
CURRENT_PROJECT_VERSION = 220;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = phpmon/Info.plist;

View File

@ -301,9 +301,7 @@ The switcher will disable all PHP-FPM services not belonging to the version you
### Want to know more?
If you want to know more about how this works, I recommend you check out the source code.
This app isn't very complicated after all. In the end, this just (conveniently) executes some shell commands.
If you want to know more about how this works, I recommend you check out the source code.
## 🔧 Build instructions

View File

@ -31,9 +31,11 @@ if !AllowedArguments.has(argument) {
let action = AllowedArguments.init(rawValue: argument)
let switcher = PhpSwitcher.shared
PhpSwitcher.detectPhpVersions()
switch action {
case .use:
// Read the PHP value
let version = CommandLine.arguments[2]
print("Switching to PHP \(version)...")
break

View File

@ -10,74 +10,6 @@ import AppKit
class Actions {
// MARK: - Detect PHP Versions
public static func detectPhpVersions() -> [String]
{
let files = Shell.pipe("ls \(Paths.optPath) | grep php@")
var versionsOnly = Self.extractPhpVersions(from: files.components(separatedBy: "\n"))
// Make sure the aliased version is detected
// The user may have `php` installed, but not e.g. `php@8.0`
// We should also detect that as a version that is installed
let phpAlias = PhpSwitcher.shared.brewPhpVersion
// Avoid inserting a duplicate
if (!versionsOnly.contains(phpAlias) && Shell.fileExists("\(Paths.optPath)/php/bin/php")) {
versionsOnly.append(phpAlias);
}
print("The PHP versions that were detected are: \(versionsOnly)")
PhpSwitcher.shared.availablePhpVersions = versionsOnly
Actions.extractPhpLongVersions()
return versionsOnly
}
/**
This method extracts the PHP full version number after finding the php installation folders.
To be refactored at some later point, I'd like to cache the `PhpInstallation` objects instead of just the version number at some point.
*/
public static func extractPhpLongVersions()
{
var mappedVersions: [String: PhpInstallation] = [:]
PhpSwitcher.shared.availablePhpVersions.forEach { version in
mappedVersions[version] = PhpInstallation(version)
}
PhpSwitcher.shared.cachedPhpInstallations = mappedVersions
}
/**
Extracts valid PHP versions from an array of strings.
This array of strings is usually retrieved from `grep`.
*/
public static func extractPhpVersions(
from versions: [String],
checkBinaries: Bool = true
) -> [String] {
var output : [String] = []
versions.filter { (version) -> Bool in
// Omit everything that doesn't start with php@
// (e.g. something-php@8.0 won't be detected)
return version.starts(with: "php@")
}.forEach { (string) in
let version = string.components(separatedBy: "php@")[1]
// Only append the version if it doesn't already exist (avoid dupes),
// is supported and where the binary exists (avoids broken installs)
if !output.contains(version)
&& Constants.SupportedPhpVersions.contains(version)
&& (checkBinaries ? Shell.fileExists("\(Paths.optPath)/php@\(version)/bin/php") : true)
{
output.append(version)
}
}
return output
}
// MARK: - Services
public static func restartPhpFpm()
@ -137,7 +69,7 @@ class Actions {
group.enter()
DispatchQueue.global(qos: .userInitiated).async {
let formula = (available == PhpSwitcher.shared.brewPhpVersion)
let formula = (available == PhpSwitcher.brewPhpVersion)
? "php" : "php@\(available)"
brew("unlink \(formula)")
@ -151,7 +83,7 @@ class Actions {
print("All versions have been unlinked!")
print("Linking the new version!")
let formula = (version == PhpSwitcher.shared.brewPhpVersion) ? "php" : "php@\(version)"
let formula = (version == PhpSwitcher.brewPhpVersion) ? "php" : "php@\(version)"
brew("link \(formula) --overwrite --force")
brew("services start \(formula)", sudo: true)
@ -204,8 +136,8 @@ class Actions {
{
brew("services restart dnsmasq", sudo: true)
detectPhpVersions().forEach { (version) in
let formula = (version == PhpSwitcher.shared.brewPhpVersion) ? "php" : "php@\(version)"
PhpSwitcher.shared.detectPhpVersions().forEach { (version) in
let formula = (version == PhpSwitcher.brewPhpVersion) ? "php" : "php@\(version)"
brew("unlink php@\(version)")
brew("services stop \(formula)")
brew("services stop \(formula)", sudo: true)

View File

@ -1,6 +1,6 @@
//
// Command.swift
// phpmon-common
// PHP Monitor
//
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//

View File

@ -1,6 +1,6 @@
//
// Paths.swift
// phpmon-common
// PHP Monitor
//
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//

View File

@ -1,6 +1,6 @@
//
// Shell.swift
// phpmon-common
// PHP Monitor
//
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//

View File

@ -25,7 +25,7 @@ class ActivePhpInstallation {
// MARK: - Computed
var formula: String {
return (version.short == PhpSwitcher.shared.brewPhpVersion) ? "php" : "php@\(version.short)"
return (version.short == PhpSwitcher.brewPhpVersion) ? "php" : "php@\(version.short)"
}
// MARK: - Initializer
@ -122,26 +122,6 @@ class ActivePhpInstallation {
return (match == nil) ? "⚠️" : "\(value)B"
}
/**
It is always possible that the system configuration for PHP-FPM has not been set up for Valet.
This can occur when a user manually installs a new PHP version, but does not run `valet install`.
In that case, we should alert the user!
- Important: The underlying check is `checkPhpFpmStatus`, which can be run multiple times.
This method actively presents a modal if said checks fails, so don't call this method too many times.
*/
public func notifyAboutBrokenPhpFpm() {
if !self.checkPhpFpmStatus() {
DispatchQueue.main.async {
Alert.notify(
message: "alert.php_fpm_broken.title".localized,
info: "alert.php_fpm_broken.info".localized,
style: .critical
)
}
}
}
/**
Determine if PHP-FPM is configured correctly.
@ -149,7 +129,7 @@ class ActivePhpInstallation {
versions of PHP, we can just check for the existence of the `valet-fpm.conf` file. If the check here fails,
that means that Valet won't work properly.
*/
private func checkPhpFpmStatus() -> Bool {
func checkPhpFpmStatus() -> Bool {
if self.version.short == "5.6" {
// The main PHP config file should contain `valet.sock` and then we're probably fine?
let fileName = "\(Paths.etcPath)/php/5.6/php-fpm.conf"

View File

@ -0,0 +1,146 @@
//
// PhpSwitcher.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 21/12/2021.
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//
import Foundation
protocol PhpSwitcherDelegate: AnyObject {
func switcherDidStartSwitching()
func switcherDidCompleteSwitch()
}
class PhpSwitcher {
// MARK: - Initializer
init() {
self.currentInstall = ActivePhpInstallation()
let brewPhpAlias = Shell.pipe("\(Paths.brew) info php --json");
self.homebrewPackage = try! JSONDecoder().decode(
[HomebrewPackage].self,
from: brewPhpAlias.data(using: .utf8)!
).first!
print("When on your system, the `php` formula means version \(homebrewPackage.version)!")
}
// MARK: - Properties
/** The delegate that is informed of updates. */
weak var delegate: PhpSwitcherDelegate?
/** The static app instance. Accessible at any time. */
static let shared = PhpSwitcher()
/** Whether the switcher is busy performing any actions. */
var isBusy: Bool = false
/** All available versions of PHP. */
var availablePhpVersions: [String] = []
/** Cached information about the PHP installations. */
var cachedPhpInstallations: [String: PhpInstallation] = [:]
/** Information about the currently linked PHP installation. */
var currentInstall: ActivePhpInstallation
/**
The version that the `php` formula via Brew is aliased to on the current system.
If you're up to date, `php` will be aliased to the latest version,
but that might not be the case since not everyone keeps their
software up-to-date.
As such, we take that information from Homebrew.
*/
static var brewPhpVersion: String {
return Self.shared.homebrewPackage.version
}
/**
The currently linked and active PHP installation.
*/
static var phpInstall: ActivePhpInstallation {
return Self.shared.currentInstall
}
/**
Information we were able to discern from the Homebrew info command.
*/
var homebrewPackage: HomebrewPackage! = nil
// MARK: - Methods
public static func detectPhpVersions() -> Void {
_ = Self.shared.detectPhpVersions()
}
/**
Detects which versions of PHP are installed.
*/
public func detectPhpVersions() -> [String]
{
let files = Shell.pipe("ls \(Paths.optPath) | grep php@")
var versionsOnly = extractPhpVersions(from: files.components(separatedBy: "\n"))
// Make sure the aliased version is detected
// The user may have `php` installed, but not e.g. `php@8.0`
// We should also detect that as a version that is installed
let phpAlias = homebrewPackage.version
// Avoid inserting a duplicate
if (!versionsOnly.contains(phpAlias) && Shell.fileExists("\(Paths.optPath)/php/bin/php")) {
versionsOnly.append(phpAlias)
}
print("The PHP versions that were detected are: \(versionsOnly)")
availablePhpVersions = versionsOnly
var mappedVersions: [String: PhpInstallation] = [:]
availablePhpVersions.forEach { version in
mappedVersions[version] = PhpInstallation(version)
}
cachedPhpInstallations = mappedVersions
return versionsOnly
}
/**
Extracts valid PHP versions from an array of strings.
This array of strings is usually retrieved from `grep`.
*/
public func extractPhpVersions(
from versions: [String],
checkBinaries: Bool = true
) -> [String] {
var output : [String] = []
versions.filter { (version) -> Bool in
// Omit everything that doesn't start with php@
// (e.g. something-php@8.0 won't be detected)
return version.starts(with: "php@")
}.forEach { (string) in
let version = string.components(separatedBy: "php@")[1]
// Only append the version if it doesn't already exist (avoid dupes),
// is supported and where the binary exists (avoids broken installs)
if !output.contains(version)
&& Constants.SupportedPhpVersions.contains(version)
&& (checkBinaries ? Shell.fileExists("\(Paths.optPath)/php@\(version)/bin/php") : true)
{
output.append(version)
}
}
return output
}
}

View File

@ -1,60 +0,0 @@
//
// PhpSwitcher.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 21/12/2021.
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//
import Foundation
protocol PhpSwitcherDelegate: AnyObject {
func switcherDidStartSwitching()
func switcherDidCompleteSwitch()
}
class PhpSwitcher {
init() {
self.currentInstall = ActivePhpInstallation()
}
/** The delegate that is informed of updates. */
weak var delegate: PhpSwitcherDelegate?
/** The static app instance. Accessible at any time. */
static let shared = PhpSwitcher()
/** Whether the switcher is busy performing any actions. */
var isBusy: Bool = false
/** All available versions of PHP. */
var availablePhpVersions: [String] = []
/** Cached information about the PHP installations. */
var cachedPhpInstallations: [String: PhpInstallation] = [:]
/** Static accessor for `PhpSwitcher.shared.currentInstall`. */
static var phpInstall: ActivePhpInstallation {
return Self.shared.currentInstall
}
/** Information about the currently linked PHP installation. */
var currentInstall: ActivePhpInstallation
/**
The version that the `php` formula via Brew is aliased to on the current system.
If you're up to date, `php` will be aliased to the latest version,
but that might not be the case.
*/
var brewPhpVersion: String {
return homebrewPackage.version
}
/**
Information we were able to discern from the Homebrew info command.
*/
var homebrewPackage: HomebrewPackage! = nil
}

View File

@ -15,10 +15,6 @@ class App: PhpSwitcherDelegate {
/** The static app instance. Accessible at any time. */
static let shared = App()
init() {
PhpSwitcher.shared.delegate = self
}
/** Retrieve the version number from the main info dictionary, Info.plist. */
static var version: String {
let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String

View File

@ -20,16 +20,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
*/
let sharedShell: Shell
/**
The PhpSwitcher singleton that handles PHP version
detection, as well as switching.
- Note: It is important to initialize the switcher
before the `App` singleton, so that the delegate
is set correctly.
*/
let switcher: PhpSwitcher
/**
The App singleton contains information about the state of
the application and global variables.
@ -54,6 +44,13 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
*/
let valet: Valet
/**
The PhpSwitcher singleton that handles PHP version
detection, as well as switching. It is initialized
when the app is ready and passed all checks.
*/
var switcher: PhpSwitcher! = nil
// MARK: - Initializer
/**
@ -65,7 +62,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
print("Version \(App.version)")
print("==================================")
self.sharedShell = Shell.user
self.switcher = PhpSwitcher.shared
self.state = App.shared
self.menu = MainMenu.shared
self.paths = Paths.shared
@ -73,6 +69,11 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
super.init()
}
func initializeSwitcher() {
self.switcher = PhpSwitcher.shared
self.switcher.delegate = self.state
}
// MARK: - Lifecycle
/**

View File

@ -6,6 +6,7 @@
//
import Foundation
import AppKit
class Startup {
@ -75,37 +76,30 @@ class Startup {
)
if (!failed) {
determineBrewAliasVersion()
initializeSwitcher()
print("PHP Monitor has determined the application has successfully passed all checks.")
success()
}
}
/**
* In order to avoid having to hard-code which version of PHP is aliased to what specific subversion,
* PHP Monitor now determines the alias by checking the user's system.
Because the Switcher requires various environment guarantees, the switcher is only
initialized when it is done working.
*/
private func determineBrewAliasVersion()
{
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.pipe("\(Paths.brew) info php --json");
PhpSwitcher.shared.homebrewPackage = try! JSONDecoder().decode(
[HomebrewPackage].self,
from: brewPhpAlias.data(using: .utf8)!
).first!
print("When on your system, the `php` formula means version \(PhpSwitcher.shared.brewPhpVersion)!")
private func initializeSwitcher() {
DispatchQueue.main.async {
let appDelegate = NSApplication.shared.delegate as! AppDelegate
appDelegate.initializeSwitcher()
}
}
/**
* Perform an environment check. Will cause the application to terminate, if `breaking` is set to true.
*
* - Parameter condition: Fail condition to check for; if this returns `true`, the alert will be shown
* - Parameter messageText: Short description of what is wrong
* - Parameter informativeText: Expanded description of the environment check that failed
* - Parameter breaking: If the application should terminate afterwards
Perform an environment check. Will cause the application to terminate, if `breaking` is set to true.
- Parameter condition: Fail condition to check for; if this returns `true`, the alert will be shown
- Parameter messageText: Short description of what is wrong
- Parameter informativeText: Expanded description of the environment check that failed
- Parameter breaking: If the application should terminate afterwards
*/
private func performEnvironmentCheck(
_ condition: Bool,

View File

@ -46,12 +46,12 @@ class HomebrewDiagnostics {
from: tapAlias.data(using: .utf8)!
).first!
if tapPhp.version != PhpSwitcher.shared.brewPhpVersion {
if tapPhp.version != PhpSwitcher.brewPhpVersion {
print("The `php` formula alias seems to be the different between the tap and core. This could be a problem!")
print("Determining whether both of these versions are installed...")
let bothInstalled = PhpSwitcher.shared.availablePhpVersions.contains(tapPhp.version)
&& PhpSwitcher.shared.availablePhpVersions.contains(PhpSwitcher.shared.brewPhpVersion)
&& PhpSwitcher.shared.availablePhpVersions.contains(PhpSwitcher.brewPhpVersion)
if bothInstalled {
print("Both conflicting aliases seem to be installed, warning the user!")

View File

@ -41,7 +41,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
When the environment is all clear and the app can run, let's go.
*/
private func onEnvironmentPass() {
_ = Actions.detectPhpVersions()
PhpSwitcher.detectPhpVersions()
if HomebrewDiagnostics.shared.errors.contains(.aliasConflict) {
DispatchQueue.main.async {

View File

@ -40,14 +40,14 @@ class StatusMenu : NSMenu {
servicesMenu.addItem(NSMenuItem(title: "mi_help".localized, action: nil, keyEquivalent: ""))
if !PhpSwitcher.shared.availablePhpVersions.contains(PhpSwitcher.shared.brewPhpVersion) {
if !PhpSwitcher.shared.availablePhpVersions.contains(PhpSwitcher.brewPhpVersion) {
servicesMenu.addItem(NSMenuItem(
title: "mi_force_load_latest_unavailable".localized(PhpSwitcher.shared.brewPhpVersion),
title: "mi_force_load_latest_unavailable".localized(PhpSwitcher.brewPhpVersion),
action: nil, keyEquivalent: "f"
))
} else {
servicesMenu.addItem(NSMenuItem(
title: "mi_force_load_latest".localized(PhpSwitcher.shared.brewPhpVersion),
title: "mi_force_load_latest".localized(PhpSwitcher.brewPhpVersion),
action: #selector(MainMenu.forceRestartLatestPhp), keyEquivalent: "f"))
}
@ -140,7 +140,7 @@ class StatusMenu : NSMenu {
let versionString = long ? longVersion : shortVersion
let action = #selector(MainMenu.switchToPhpVersion(sender:))
let brew = (shortVersion == PhpSwitcher.shared.brewPhpVersion) ? "php" : "php@\(shortVersion)"
let brew = (shortVersion == PhpSwitcher.brewPhpVersion) ? "php" : "php@\(shortVersion)"
let menuItem = PhpMenuItem(
title: "\("mi_php_switch".localized) \(versionString) (\(brew))",
action: (shortVersion == PhpSwitcher.phpInstall.version.short) ? nil : action, keyEquivalent: "\(shortcutKey)"

View File

@ -0,0 +1,33 @@
//
// ActivePhpInstallation.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 21/12/2021.
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//
import Foundation
extension ActivePhpInstallation {
/**
It is always possible that the system configuration for PHP-FPM has not been set up for Valet.
This can occur when a user manually installs a new PHP version, but does not run `valet install`.
In that case, we should alert the user!
- Important: The underlying check is `checkPhpFpmStatus`, which can be run multiple times.
This method actively presents a modal if said checks fails, so don't call this method too many times.
*/
public func notifyAboutBrokenPhpFpm() {
if !self.checkPhpFpmStatus() {
DispatchQueue.main.async {
Alert.notify(
message: "alert.php_fpm_broken.title".localized,
info: "alert.php_fpm_broken.info".localized,
style: .critical
)
}
}
}
}