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

♻️ Cleanup

This commit is contained in:
2022-02-22 20:49:13 +01:00
parent e398f089af
commit ce498d3019
9 changed files with 205 additions and 242 deletions

View File

@ -153,10 +153,8 @@
C4DEB7D427A5D60B00834718 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4DEB7D327A5D60B00834718 /* Stats.swift */; };
C4E0F7ED27BEBDA9007475F2 /* NSWindowExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E0F7EC27BEBDA9007475F2 /* NSWindowExtension.swift */; };
C4E0F7EE27BEBDA9007475F2 /* NSWindowExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E0F7EC27BEBDA9007475F2 /* NSWindowExtension.swift */; };
C4E4404627C56F4700D225E1 /* Valet.Site.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E4404527C56F4700D225E1 /* Valet.Site.swift */; };
C4E4404727C56F4700D225E1 /* Valet.Site.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E4404527C56F4700D225E1 /* Valet.Site.swift */; };
C4E4404927C56F5F00D225E1 /* Valet.Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E4404827C56F5F00D225E1 /* Valet.Configuration.swift */; };
C4E4404A27C56F5F00D225E1 /* Valet.Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E4404827C56F5F00D225E1 /* Valet.Configuration.swift */; };
C4E4404627C56F4700D225E1 /* ValetSite.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E4404527C56F4700D225E1 /* ValetSite.swift */; };
C4E4404727C56F4700D225E1 /* ValetSite.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E4404527C56F4700D225E1 /* ValetSite.swift */; };
C4EC1E66279DE0380010F296 /* ServicesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C4EC1E65279DE0380010F296 /* ServicesView.xib */; };
C4EC1E68279DE0540010F296 /* ServicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EC1E67279DE0540010F296 /* ServicesView.swift */; };
C4EC1E73279DFCF40010F296 /* Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EC1E72279DFCF40010F296 /* Events.swift */; };
@ -307,8 +305,7 @@
C4D9ADC7277611A0007277F4 /* InternalSwitcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalSwitcher.swift; sourceTree = "<group>"; };
C4DEB7D327A5D60B00834718 /* Stats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stats.swift; sourceTree = "<group>"; };
C4E0F7EC27BEBDA9007475F2 /* NSWindowExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSWindowExtension.swift; sourceTree = "<group>"; };
C4E4404527C56F4700D225E1 /* Valet.Site.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Valet.Site.swift; sourceTree = "<group>"; };
C4E4404827C56F5F00D225E1 /* Valet.Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Valet.Configuration.swift; sourceTree = "<group>"; };
C4E4404527C56F4700D225E1 /* ValetSite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValetSite.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>"; };
C4EC1E65279DE0380010F296 /* ServicesView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ServicesView.xib; sourceTree = "<group>"; };
@ -578,8 +575,7 @@
isa = PBXGroup;
children = (
C4AF9F792754499000D44ED0 /* Valet.swift */,
C4E4404527C56F4700D225E1 /* Valet.Site.swift */,
C4E4404827C56F5F00D225E1 /* Valet.Configuration.swift */,
C4E4404527C56F4700D225E1 /* ValetSite.swift */,
);
path = Valet;
sourceTree = "<group>";
@ -856,7 +852,6 @@
C48D6C70279CD2AC00F26D7E /* PhpVersionNumber.swift in Sources */,
C4B585412770FE3900DA4FBE /* Shell.swift in Sources */,
C4998F0A2617633900B2526E /* PrefsWC.swift in Sources */,
C4E4404927C56F5F00D225E1 /* Valet.Configuration.swift in Sources */,
C4F8C0A422D4F12C002EFE61 /* DateExtension.swift in Sources */,
C4AF9F7A2754499000D44ED0 /* Valet.swift in Sources */,
5420395926135DC100FB00FA /* PrefsVC.swift in Sources */,
@ -868,7 +863,7 @@
C4EE55AD27708B9E001DF387 /* PMStatsView.swift in Sources */,
C4C8E818276F54D8003AC782 /* App+ConfigWatch.swift in Sources */,
54FCFD30276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */,
C4E4404627C56F4700D225E1 /* Valet.Site.swift in Sources */,
C4E4404627C56F4700D225E1 /* ValetSite.swift in Sources */,
C4EC1E68279DE0540010F296 /* ServicesView.swift in Sources */,
C4F2E43A2752F7D00020E974 /* PhpInstallation.swift in Sources */,
C41E871A2763D42300161EE0 /* SiteListVC+ContextMenu.swift in Sources */,
@ -1009,9 +1004,8 @@
C40B24F127A3106D0018C7D2 /* ServicesView.swift in Sources */,
C4F780C525D80B75000DBC97 /* MenuBarImageGenerator.swift in Sources */,
C4F780B725D80B5D000DBC97 /* App.swift in Sources */,
C4E4404A27C56F5F00D225E1 /* Valet.Configuration.swift in Sources */,
C4927F0C27B2DFC200C55AFD /* Errors.swift in Sources */,
C4E4404727C56F4700D225E1 /* Valet.Site.swift in Sources */,
C4E4404727C56F4700D225E1 /* ValetSite.swift in Sources */,
C44CCD4A27AFF3BC00CE40E5 /* MainMenu+Async.swift in Sources */,
C48D6C71279CD2AC00F26D7E /* PhpVersionNumber.swift in Sources */,
C4F780C925D80B75000DBC97 /* StringExtension.swift in Sources */,

View File

@ -39,7 +39,7 @@ struct ComposerJson: Decodable {
Checks what the PHP version constraint is.
Returns a tuple (constraint, location of constraint).
*/
public func getPhpVersion() -> (String, Valet.Site.VersionSource)
public func getPhpVersion() -> (String, ValetSite.VersionSource)
{
// Check if in platform
if configuration?.platform?.php != nil {

View File

@ -1,32 +0,0 @@
//
// Valet.Configuration.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 22/02/2022.
// Copyright © 2022 Nico Verbruggen. All rights reserved.
//
import Foundation
extension Valet {
struct Configuration: Decodable {
/// Top level domain suffix. Usually "test" but can be set to something else.
/// - Important: Does not include the actual dot. ("test", not ".test"!)
let tld: String
/// The paths that need to be checked.
let paths: [String]
/// The loopback address. Optional.
let loopback: String?
/// The default site that is served if the domain is not found. Optional.
let defaultSite: String?
private enum CodingKeys: String, CodingKey {
case tld, paths, loopback, defaultSite = "default"
}
}
}

View File

@ -1,188 +0,0 @@
//
// Valet+Subclasses.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 22/02/2022.
// Copyright © 2022 Nico Verbruggen. All rights reserved.
//
import Foundation
extension Valet {
class Site {
/// Name of the site. Does not include the TLD.
var name: String!
/// The absolute path to the directory that is served.
var absolutePath: String!
/// The absolute path to the directory that is served,
/// replacing the user's home folder with ~.
lazy var absolutePathRelative: String = {
return self.absolutePath
.replacingOccurrences(of: "/Users/\(Paths.whoami)", with: "~")
}()
/// Location of the alias. If set, this is a linked domain.
var aliasPath: String?
/// Whether the site has been secured.
var secured: Bool!
/// What driver is currently in use. If not detected, defaults to nil.
var driver: String? = nil
/// Whether the driver was determined by checking the Composer file.
var driverDeterminedByComposer: Bool = false
/// A list of notable Composer dependencies.
var notableComposerDependencies: [String: String] = [:]
/// The PHP version as discovered in `composer.json` or in .valetphprc.
var composerPhp: String = "???"
/// Check whether the PHP version is valid for the currently linked version.
var composerPhpCompatibleWithLinked: Bool = false
/// How the PHP version was determined.
var composerPhpSource: VersionSource = .unknown
enum VersionSource: String {
case unknown = "unknown"
case require = "require"
case platform = "platform"
case valetphprc = "valetphprc"
}
init() {}
convenience init(absolutePath: String, tld: String) {
self.init()
self.absolutePath = absolutePath
self.name = URL(fileURLWithPath: absolutePath).lastPathComponent
self.aliasPath = nil
determineSecured(tld)
determineComposerPhpVersion()
determineDriver()
}
convenience init(aliasPath: String, tld: String) {
self.init()
self.absolutePath = try! FileManager.default.destinationOfSymbolicLink(atPath: aliasPath)
self.name = URL(fileURLWithPath: aliasPath).lastPathComponent
self.aliasPath = aliasPath
determineSecured(tld)
determineComposerPhpVersion()
determineDriver()
}
/**
Checks if a certificate file can be found in the `valet/Certificates` directory.
- Note: The file is not validated, only its presence is checked.
*/
public func determineSecured(_ tld: String) {
secured = Filesystem.fileExists("~/.config/valet/Certificates/\(self.name!).\(tld).key")
}
/**
Checks if `composer.json` exists in the folder, and extracts notable information:
- The PHP version required (the constraint, so it could be `^8.0`, for example)
- Where the PHP version was found (`require` or `platform` or via .valetphprc)
- Notable PHP dependencies (determined via `PhpFrameworks.DependencyList`)
The method then also checks if the determined constraint (if found) is compatible
with the currently linked version of PHP (see `composerPhpMatchesSystem`).
*/
public func determineComposerPhpVersion() {
do {
let path = "\(absolutePath!)/composer.json"
if Filesystem.fileExists(path) {
let decoded = try JSONDecoder().decode(
ComposerJson.self,
from: String(contentsOf: URL(fileURLWithPath: path), encoding: .utf8).data(using: .utf8)!
)
(self.composerPhp, self.composerPhpSource) = decoded.getPhpVersion()
self.notableComposerDependencies = decoded.getNotableDependencies()
}
} catch {
Log.err("Something went wrong reading the Composer JSON file.")
}
do {
let path = "\(absolutePath!)/.valetphprc"
if Filesystem.fileExists(path) {
let contents = try String(contentsOf: URL(fileURLWithPath: path), encoding: .utf8)
if let version = VersionExtractor.from(contents) {
self.composerPhp = version
self.composerPhpSource = .valetphprc
}
}
} catch {
Log.err("Something went wrong parsing the .valetphprc file")
}
// TODO: Check if .valetphprc exists and if it contains a valid version number
if self.composerPhp == "???" {
return
}
// Split the composer list (on "|") to evaluate multiple constraints
// For example, for Laravel 8 projects the value is "^7.3|^8.0"
self.composerPhpCompatibleWithLinked =
self.composerPhp.split(separator: "|").map { string in
return PhpVersionNumberCollection.make(from: [PhpEnv.phpInstall.version.long])
.matching(constraint: string.trimmingCharacters(in: .whitespacesAndNewlines))
.count > 0
}.contains(true)
}
/**
Determine the driver to be displayed in the list of sites. In v5.0, this has been changed
to load the "framework" or "project type" instead.
*/
public func determineDriver() {
self.determineDriverViaComposer()
if self.driver == nil {
self.driver = PhpFrameworks.detectFallbackDependency(self.absolutePath)
}
}
/**
Check the dependency list and see if a particular dependency can't be found.
We'll revert the dependency list so that Laravel and Symfony are detected last.
(Some other frameworks might use Laravel, so if we found it first the detection would be incorrect:
this would happen with Statamic, for example.)
*/
private func determineDriverViaComposer() {
self.driverDeterminedByComposer = true
PhpFrameworks.DependencyList.reversed().forEach { (key: String, value: String) in
if self.notableComposerDependencies.keys.contains(key) {
self.driver = value
}
}
}
@available(*, deprecated, renamed: "determineDriver")
private func determineDriverViaValet() {
let driver = Shell.pipe("cd '\(absolutePath!)' && valet which", requiresPath: true)
if driver.contains("This site is served by") {
self.driver = driver
.replacingOccurrences(of: "This site is served by [", with: "")
.replacingOccurrences(of: "ValetDriver].\n", with: "")
} else {
self.driver = nil
}
}
}
}

View File

@ -19,7 +19,7 @@ class Valet {
var config: Valet.Configuration!
/// A cached list of sites that were detected after analyzing the paths set up for Valet.
var sites: [Site] = []
var sites: [ValetSite] = []
/// Whether we're busy with some blocking operation.
var isBusy: Bool = false
@ -174,9 +174,28 @@ class Valet {
}
if type == FileAttributeType.typeSymbolicLink {
sites.append(Site(aliasPath: siteDir, tld: tld))
sites.append(ValetSite(aliasPath: siteDir, tld: tld))
} else if type == FileAttributeType.typeDirectory {
sites.append(Site(absolutePath: siteDir, tld: tld))
sites.append(ValetSite(absolutePath: siteDir, tld: tld))
}
}
struct Configuration: Decodable {
/// Top level domain suffix. Usually "test" but can be set to something else.
/// - Important: Does not include the actual dot. ("test", not ".test"!)
let tld: String
/// The paths that need to be checked.
let paths: [String]
/// The loopback address. Optional.
let loopback: String?
/// The default site that is served if the domain is not found. Optional.
let defaultSite: String?
private enum CodingKeys: String, CodingKey {
case tld, paths, loopback, defaultSite = "default"
}
}

View File

@ -0,0 +1,170 @@
//
// Valet+Subclasses.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 22/02/2022.
// Copyright © 2022 Nico Verbruggen. All rights reserved.
//
import Foundation
class ValetSite {
/// Name of the site. Does not include the TLD.
var name: String!
/// The absolute path to the directory that is served.
var absolutePath: String!
/// The absolute path to the directory that is served,
/// replacing the user's home folder with ~.
lazy var absolutePathRelative: String = {
return self.absolutePath
.replacingOccurrences(of: "/Users/\(Paths.whoami)", with: "~")
}()
/// Location of the alias. If set, this is a linked domain.
var aliasPath: String?
/// Whether the site has been secured.
var secured: Bool!
/// What driver is currently in use. If not detected, defaults to nil.
var driver: String? = nil
/// Whether the driver was determined by checking the Composer file.
var driverDeterminedByComposer: Bool = false
/// A list of notable Composer dependencies.
var notableComposerDependencies: [String: String] = [:]
/// The PHP version as discovered in `composer.json` or in .valetphprc.
var composerPhp: String = "???"
/// Check whether the PHP version is valid for the currently linked version.
var composerPhpCompatibleWithLinked: Bool = false
/// How the PHP version was determined.
var composerPhpSource: VersionSource = .unknown
enum VersionSource: String {
case unknown = "unknown"
case require = "require"
case platform = "platform"
case valetphprc = "valetphprc"
}
init() {}
convenience init(absolutePath: String, tld: String) {
self.init()
self.absolutePath = absolutePath
self.name = URL(fileURLWithPath: absolutePath).lastPathComponent
self.aliasPath = nil
determineSecured(tld)
determineComposerPhpVersion()
determineDriver()
}
convenience init(aliasPath: String, tld: String) {
self.init()
self.absolutePath = try! FileManager.default.destinationOfSymbolicLink(atPath: aliasPath)
self.name = URL(fileURLWithPath: aliasPath).lastPathComponent
self.aliasPath = aliasPath
determineSecured(tld)
determineComposerPhpVersion()
determineDriver()
}
/**
Checks if a certificate file can be found in the `valet/Certificates` directory.
- Note: The file is not validated, only its presence is checked.
*/
public func determineSecured(_ tld: String) {
secured = Filesystem.fileExists("~/.config/valet/Certificates/\(self.name!).\(tld).key")
}
/**
Checks if `composer.json` exists in the folder, and extracts notable information:
- The PHP version required (the constraint, so it could be `^8.0`, for example)
- Where the PHP version was found (`require` or `platform` or via .valetphprc)
- Notable PHP dependencies (determined via `PhpFrameworks.DependencyList`)
The method then also checks if the determined constraint (if found) is compatible
with the currently linked version of PHP (see `composerPhpMatchesSystem`).
*/
public func determineComposerPhpVersion() {
do {
let path = "\(absolutePath!)/composer.json"
if Filesystem.fileExists(path) {
let decoded = try JSONDecoder().decode(
ComposerJson.self,
from: String(contentsOf: URL(fileURLWithPath: path), encoding: .utf8).data(using: .utf8)!
)
(self.composerPhp, self.composerPhpSource) = decoded.getPhpVersion()
self.notableComposerDependencies = decoded.getNotableDependencies()
}
} catch {
Log.err("Something went wrong reading the Composer JSON file.")
}
do {
let path = "\(absolutePath!)/.valetphprc"
if Filesystem.fileExists(path) {
let contents = try String(contentsOf: URL(fileURLWithPath: path), encoding: .utf8)
if let version = VersionExtractor.from(contents) {
self.composerPhp = version
self.composerPhpSource = .valetphprc
}
}
} catch {
Log.err("Something went wrong parsing the .valetphprc file")
}
if self.composerPhp == "???" {
return
}
// Split the composer list (on "|") to evaluate multiple constraints
// For example, for Laravel 8 projects the value is "^7.3|^8.0"
self.composerPhpCompatibleWithLinked = self.composerPhp.split(separator: "|")
.map { string in
return PhpVersionNumberCollection.make(from: [PhpEnv.phpInstall.version.long])
.matching(constraint: string.trimmingCharacters(in: .whitespacesAndNewlines))
.count > 0
}.contains(true)
}
/**
Determine the driver to be displayed in the list of sites. In v5.0, this has been changed
to load the "framework" or "project type" instead.
*/
public func determineDriver() {
self.determineDriverViaComposer()
if self.driver == nil {
self.driver = PhpFrameworks.detectFallbackDependency(self.absolutePath)
}
}
/**
Check the dependency list and see if a particular dependency can't be found.
We'll revert the dependency list so that Laravel and Symfony are detected last.
(Some other frameworks might use Laravel, so if we found it first the detection would be incorrect:
this would happen with Statamic, for example.)
*/
private func determineDriverViaComposer() {
self.driverDeterminedByComposer = true
PhpFrameworks.DependencyList.reversed().forEach { (key: String, value: String) in
if self.notableComposerDependencies.keys.contains(key) {
self.driver = value
}
}
}
}

View File

@ -11,7 +11,7 @@ import AppKit
class SiteListCell: NSTableCellView
{
var site: Valet.Site? = nil
var site: ValetSite? = nil
@IBOutlet weak var labelSiteName: NSTextField!
@IBOutlet weak var labelPathName: NSTextField!
@ -29,7 +29,7 @@ class SiteListCell: NSTableCellView
super.draw(dirtyRect)
}
func populateCell(with site: Valet.Site) {
func populateCell(with site: ValetSite) {
self.site = site
// Make sure to show the TLD

View File

@ -65,7 +65,7 @@ extension SiteListVC {
}
}
private func addUnlink(to menu: NSMenu, with site: Valet.Site) {
private func addUnlink(to menu: NSMenu, with site: ValetSite) {
if (site.aliasPath != nil) {
menu.addItem(
withTitle: "site_list.unlink".localized,
@ -76,7 +76,7 @@ extension SiteListVC {
}
}
private func addToggleSecure(to menu: NSMenu, with site: Valet.Site) {
private func addToggleSecure(to menu: NSMenu, with site: ValetSite) {
menu.addItem(
withTitle: site.secured
? "site_list.unsecure".localized

View File

@ -20,7 +20,7 @@ class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
// MARK: - Variables
/// List of sites that will be displayed in this view. Originates from the `Valet` object.
var sites: [Valet.Site] = []
var sites: [ValetSite] = []
/// Array that contains various apps that might open a particular site directory.
var applications: [Application] {
@ -32,7 +32,7 @@ class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
// MARK: - Helper Variables
var selectedSite: Valet.Site? {
var selectedSite: ValetSite? {
if tableView.selectedRow == -1 {
return nil
}