mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-08-07 03:50:08 +02:00
♻️ Refactor Valet structure, add #143
This commit is contained in:
@ -153,6 +153,10 @@
|
|||||||
C4DEB7D427A5D60B00834718 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4DEB7D327A5D60B00834718 /* Stats.swift */; };
|
C4DEB7D427A5D60B00834718 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4DEB7D327A5D60B00834718 /* Stats.swift */; };
|
||||||
C4E0F7ED27BEBDA9007475F2 /* NSWindowExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E0F7EC27BEBDA9007475F2 /* NSWindowExtension.swift */; };
|
C4E0F7ED27BEBDA9007475F2 /* NSWindowExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E0F7EC27BEBDA9007475F2 /* NSWindowExtension.swift */; };
|
||||||
C4E0F7EE27BEBDA9007475F2 /* 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 */; };
|
||||||
C4EC1E66279DE0380010F296 /* ServicesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C4EC1E65279DE0380010F296 /* ServicesView.xib */; };
|
C4EC1E66279DE0380010F296 /* ServicesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C4EC1E65279DE0380010F296 /* ServicesView.xib */; };
|
||||||
C4EC1E68279DE0540010F296 /* ServicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EC1E67279DE0540010F296 /* ServicesView.swift */; };
|
C4EC1E68279DE0540010F296 /* ServicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EC1E67279DE0540010F296 /* ServicesView.swift */; };
|
||||||
C4EC1E73279DFCF40010F296 /* Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EC1E72279DFCF40010F296 /* Events.swift */; };
|
C4EC1E73279DFCF40010F296 /* Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EC1E72279DFCF40010F296 /* Events.swift */; };
|
||||||
@ -303,6 +307,8 @@
|
|||||||
C4D9ADC7277611A0007277F4 /* InternalSwitcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalSwitcher.swift; sourceTree = "<group>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
||||||
C4E713562570150F00007428 /* SECURITY.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = SECURITY.md; 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>"; };
|
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>"; };
|
C4EC1E65279DE0380010F296 /* ServicesView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ServicesView.xib; sourceTree = "<group>"; };
|
||||||
@ -572,6 +578,8 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
C4AF9F792754499000D44ED0 /* Valet.swift */,
|
C4AF9F792754499000D44ED0 /* Valet.swift */,
|
||||||
|
C4E4404527C56F4700D225E1 /* Valet.Site.swift */,
|
||||||
|
C4E4404827C56F5F00D225E1 /* Valet.Configuration.swift */,
|
||||||
);
|
);
|
||||||
path = Valet;
|
path = Valet;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -848,6 +856,7 @@
|
|||||||
C48D6C70279CD2AC00F26D7E /* PhpVersionNumber.swift in Sources */,
|
C48D6C70279CD2AC00F26D7E /* PhpVersionNumber.swift in Sources */,
|
||||||
C4B585412770FE3900DA4FBE /* Shell.swift in Sources */,
|
C4B585412770FE3900DA4FBE /* Shell.swift in Sources */,
|
||||||
C4998F0A2617633900B2526E /* PrefsWC.swift in Sources */,
|
C4998F0A2617633900B2526E /* PrefsWC.swift in Sources */,
|
||||||
|
C4E4404927C56F5F00D225E1 /* Valet.Configuration.swift in Sources */,
|
||||||
C4F8C0A422D4F12C002EFE61 /* DateExtension.swift in Sources */,
|
C4F8C0A422D4F12C002EFE61 /* DateExtension.swift in Sources */,
|
||||||
C4AF9F7A2754499000D44ED0 /* Valet.swift in Sources */,
|
C4AF9F7A2754499000D44ED0 /* Valet.swift in Sources */,
|
||||||
5420395926135DC100FB00FA /* PrefsVC.swift in Sources */,
|
5420395926135DC100FB00FA /* PrefsVC.swift in Sources */,
|
||||||
@ -859,6 +868,7 @@
|
|||||||
C4EE55AD27708B9E001DF387 /* PMStatsView.swift in Sources */,
|
C4EE55AD27708B9E001DF387 /* PMStatsView.swift in Sources */,
|
||||||
C4C8E818276F54D8003AC782 /* App+ConfigWatch.swift in Sources */,
|
C4C8E818276F54D8003AC782 /* App+ConfigWatch.swift in Sources */,
|
||||||
54FCFD30276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */,
|
54FCFD30276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */,
|
||||||
|
C4E4404627C56F4700D225E1 /* Valet.Site.swift in Sources */,
|
||||||
C4EC1E68279DE0540010F296 /* ServicesView.swift in Sources */,
|
C4EC1E68279DE0540010F296 /* ServicesView.swift in Sources */,
|
||||||
C4F2E43A2752F7D00020E974 /* PhpInstallation.swift in Sources */,
|
C4F2E43A2752F7D00020E974 /* PhpInstallation.swift in Sources */,
|
||||||
C41E871A2763D42300161EE0 /* SiteListVC+ContextMenu.swift in Sources */,
|
C41E871A2763D42300161EE0 /* SiteListVC+ContextMenu.swift in Sources */,
|
||||||
@ -999,7 +1009,9 @@
|
|||||||
C40B24F127A3106D0018C7D2 /* ServicesView.swift in Sources */,
|
C40B24F127A3106D0018C7D2 /* ServicesView.swift in Sources */,
|
||||||
C4F780C525D80B75000DBC97 /* MenuBarImageGenerator.swift in Sources */,
|
C4F780C525D80B75000DBC97 /* MenuBarImageGenerator.swift in Sources */,
|
||||||
C4F780B725D80B5D000DBC97 /* App.swift in Sources */,
|
C4F780B725D80B5D000DBC97 /* App.swift in Sources */,
|
||||||
|
C4E4404A27C56F5F00D225E1 /* Valet.Configuration.swift in Sources */,
|
||||||
C4927F0C27B2DFC200C55AFD /* Errors.swift in Sources */,
|
C4927F0C27B2DFC200C55AFD /* Errors.swift in Sources */,
|
||||||
|
C4E4404727C56F4700D225E1 /* Valet.Site.swift in Sources */,
|
||||||
C44CCD4A27AFF3BC00CE40E5 /* MainMenu+Async.swift in Sources */,
|
C44CCD4A27AFF3BC00CE40E5 /* MainMenu+Async.swift in Sources */,
|
||||||
C48D6C71279CD2AC00F26D7E /* PhpVersionNumber.swift in Sources */,
|
C48D6C71279CD2AC00F26D7E /* PhpVersionNumber.swift in Sources */,
|
||||||
C4F780C925D80B75000DBC97 /* StringExtension.swift in Sources */,
|
C4F780C925D80B75000DBC97 /* StringExtension.swift in Sources */,
|
||||||
|
Binary file not shown.
@ -39,19 +39,20 @@ struct ComposerJson: Decodable {
|
|||||||
Checks what the PHP version constraint is.
|
Checks what the PHP version constraint is.
|
||||||
Returns a tuple (constraint, location of constraint).
|
Returns a tuple (constraint, location of constraint).
|
||||||
*/
|
*/
|
||||||
public func getPhpVersion() -> (String, String) {
|
public func getPhpVersion() -> (String, Valet.Site.VersionSource)
|
||||||
|
{
|
||||||
// Check if in platform
|
// Check if in platform
|
||||||
if configuration?.platform?.php != nil {
|
if configuration?.platform?.php != nil {
|
||||||
return (configuration!.platform!.php!, "platform")
|
return (configuration!.platform!.php!, .platform)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if in dependencies
|
// Check if in dependencies
|
||||||
if dependencies?["php"] != nil {
|
if dependencies?["php"] != nil {
|
||||||
return (dependencies!["php"]!, "require")
|
return (dependencies!["php"]!, .require)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unknown!
|
// Unknown!
|
||||||
return ("???", "unknown")
|
return ("???", .unknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
32
phpmon/Domain/Integrations/Valet/Valet.Configuration.swift
Normal file
32
phpmon/Domain/Integrations/Valet/Valet.Configuration.swift
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
188
phpmon/Domain/Integrations/Valet/Valet.Site.swift
Normal file
188
phpmon/Domain/Integrations/Valet/Valet.Site.swift
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -180,176 +180,4 @@ class Valet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Structs
|
|
||||||
|
|
||||||
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`.
|
|
||||||
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: String = "unknown"
|
|
||||||
|
|
||||||
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`)
|
|
||||||
- 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() {
|
|
||||||
let path = "\(absolutePath!)/composer.json"
|
|
||||||
|
|
||||||
do {
|
|
||||||
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.")
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -80,8 +80,8 @@ class SiteListCell: NSTableCellView
|
|||||||
|
|
||||||
alert.messageText = "alert.composer_php_requirement.title"
|
alert.messageText = "alert.composer_php_requirement.title"
|
||||||
.localized("\(site.name!).\(Valet.shared.config.tld)", site.composerPhp)
|
.localized("\(site.name!).\(Valet.shared.config.tld)", site.composerPhp)
|
||||||
alert.informativeText = "alert.composer_php_requirement.info"
|
alert.informativeText = "alert.composer_php_requirement.type.\(site.composerPhpSource.rawValue)"
|
||||||
.localized(site.composerPhpSource)
|
.localized
|
||||||
|
|
||||||
alert.addButton(withTitle: "site_link.close".localized)
|
alert.addButton(withTitle: "site_link.close".localized)
|
||||||
|
|
||||||
|
@ -196,8 +196,11 @@ problem manually, using your own Terminal app (this just shows you the output)."
|
|||||||
"alert.composer_success.info" = "Your global Composer dependencies have been successfully updated.";
|
"alert.composer_success.info" = "Your global Composer dependencies have been successfully updated.";
|
||||||
|
|
||||||
// Composer Version
|
// Composer Version
|
||||||
"alert.composer_php_requirement.title" = "`%@` has the following PHP requirement: \"php\":\n\"%@\".";
|
"alert.composer_php_requirement.title" = "`%@` has the following PHP requirement: %@.";
|
||||||
"alert.composer_php_requirement.info" = "This required PHP version was determined by checking the `%@` field in the `composer.json` file when the site list was last refreshed.";
|
"alert.composer_php_requirement.type.unknown" = "The required PHP version was determined by an unknown factor.";
|
||||||
|
"alert.composer_php_requirement.type.require" = "This required PHP version was determined by checking the `require` field in the `composer.json` file when the site list was last refreshed.";
|
||||||
|
"alert.composer_php_requirement.type.platform" = "This required PHP version was determined by checking the `platform` field in the `composer.json` file when the site list was last refreshed.";
|
||||||
|
"alert.composer_php_requirement.type.valetphprc" = "This required PHP version was determined by checking the .valetphprc file in your project's directory.";
|
||||||
|
|
||||||
// Suggest Fix My Valet
|
// Suggest Fix My Valet
|
||||||
"alert.php_switch_failed.title" = "Switching to PHP %@ seems to have failed.";
|
"alert.php_switch_failed.title" = "Switching to PHP %@ seems to have failed.";
|
||||||
|
Reference in New Issue
Block a user