mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-08-07 03:50:08 +02:00
✨ Add marketing mode
This commit is contained in:
@ -62,6 +62,10 @@
|
||||
C417DC75277614690015E6EE /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = C417DC73277614690015E6EE /* Helpers.swift */; };
|
||||
C4188989275FE8CB001EF227 /* Filesystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4188988275FE8CB001EF227 /* Filesystem.swift */; };
|
||||
C418898A275FE8CB001EF227 /* Filesystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4188988275FE8CB001EF227 /* Filesystem.swift */; };
|
||||
C41C02A627E60D7A009F26CB /* SiteScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C02A527E60D7A009F26CB /* SiteScanner.swift */; };
|
||||
C41C02A927E61A65009F26CB /* ValetSite+Fake.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C02A827E61A65009F26CB /* ValetSite+Fake.swift */; };
|
||||
C41C02AA27E61CA3009F26CB /* SiteScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C02A527E60D7A009F26CB /* SiteScanner.swift */; };
|
||||
C41C02AB27E61CB3009F26CB /* ValetSite+Fake.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C02A827E61A65009F26CB /* ValetSite+Fake.swift */; };
|
||||
C41C1B3722B0097F00E7CF16 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B3622B0097F00E7CF16 /* AppDelegate.swift */; };
|
||||
C41C1B3B22B0098000E7CF16 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C41C1B3A22B0098000E7CF16 /* Assets.xcassets */; };
|
||||
C41C1B3E22B0098000E7CF16 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C41C1B3C22B0098000E7CF16 /* Main.storyboard */; };
|
||||
@ -267,6 +271,8 @@
|
||||
C4168F4427ADB4A3003B6C39 /* DEVELOPER.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = DEVELOPER.md; sourceTree = "<group>"; };
|
||||
C417DC73277614690015E6EE /* Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = "<group>"; };
|
||||
C4188988275FE8CB001EF227 /* Filesystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Filesystem.swift; sourceTree = "<group>"; };
|
||||
C41C02A527E60D7A009F26CB /* SiteScanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteScanner.swift; sourceTree = "<group>"; };
|
||||
C41C02A827E61A65009F26CB /* ValetSite+Fake.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ValetSite+Fake.swift"; sourceTree = "<group>"; };
|
||||
C41C1B3322B0097F00E7CF16 /* PHP Monitor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "PHP Monitor.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C41C1B3622B0097F00E7CF16 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
C41C1B3A22B0098000E7CF16 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
@ -656,6 +662,8 @@
|
||||
children = (
|
||||
C4AF9F792754499000D44ED0 /* Valet.swift */,
|
||||
C4E4404527C56F4700D225E1 /* ValetSite.swift */,
|
||||
C41C02A827E61A65009F26CB /* ValetSite+Fake.swift */,
|
||||
C41C02A527E60D7A009F26CB /* SiteScanner.swift */,
|
||||
C4D5CFC927E0F9CD00035329 /* NginxConfigParser.swift */,
|
||||
);
|
||||
path = Valet;
|
||||
@ -978,6 +986,7 @@
|
||||
C48D0CA325CC992000CC7490 /* StatsView.swift in Sources */,
|
||||
C40C7F2827721FF600DDDCDC /* ActivePhpInstallation+Checks.swift in Sources */,
|
||||
C4EE55A927708B9E001DF387 /* PMHeaderView.swift in Sources */,
|
||||
C41C02A927E61A65009F26CB /* ValetSite+Fake.swift in Sources */,
|
||||
C4F2E4372752F0870020E974 /* HomebrewDiagnostics.swift in Sources */,
|
||||
C4CCBA6C275C567B008C7055 /* PMWindowController.swift in Sources */,
|
||||
C4B585442770FE3900DA4FBE /* Command.swift in Sources */,
|
||||
@ -1043,6 +1052,7 @@
|
||||
C4D89BC62783C99400A02B68 /* ComposerJson.swift in Sources */,
|
||||
C46FA23F246C358E00944F05 /* StringExtension.swift in Sources */,
|
||||
C4B97B75275CF08C003F3378 /* AppDelegate+MenuOutlets.swift in Sources */,
|
||||
C41C02A627E60D7A009F26CB /* SiteScanner.swift in Sources */,
|
||||
C464ADAC275A7A3F003FCD53 /* SiteListWC.swift in Sources */,
|
||||
C464ADB2275A87CA003FCD53 /* SiteListCellProtocol.swift in Sources */,
|
||||
C4EE188422D3386B00E126E5 /* Constants.swift in Sources */,
|
||||
@ -1066,6 +1076,7 @@
|
||||
C4F780C825D80B75000DBC97 /* DateExtension.swift in Sources */,
|
||||
C493084B279F331F009C240B /* AddSiteVC.swift in Sources */,
|
||||
C4D9ADC0277610E1007277F4 /* PhpSwitcher.swift in Sources */,
|
||||
C41C02AA27E61CA3009F26CB /* SiteScanner.swift in Sources */,
|
||||
C4080FFB27BD956700BF2C6B /* BetterAlertVC.swift in Sources */,
|
||||
C4F780CC25D80B75000DBC97 /* ActivePhpInstallation.swift in Sources */,
|
||||
54D9E0BB27E4F51E003B9AD9 /* ModifierFlagsExtension.swift in Sources */,
|
||||
@ -1139,6 +1150,7 @@
|
||||
C4E4404727C56F4700D225E1 /* ValetSite.swift in Sources */,
|
||||
C44CCD4A27AFF3BC00CE40E5 /* MainMenu+Async.swift in Sources */,
|
||||
C48D6C71279CD2AC00F26D7E /* PhpVersionNumber.swift in Sources */,
|
||||
C41C02AB27E61CB3009F26CB /* ValetSite+Fake.swift in Sources */,
|
||||
C4F780C925D80B75000DBC97 /* StringExtension.swift in Sources */,
|
||||
C4B5853F2770FE3900DA4FBE /* Paths.swift in Sources */,
|
||||
C481F79A26164A7C004FBCFF /* Preferences.swift in Sources */,
|
||||
|
@ -62,6 +62,13 @@
|
||||
ReferencedContainer = "container:PHP Monitor.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariable
|
||||
key = "PHPMON_MARKETING_MODE"
|
||||
value = "YES"
|
||||
isEnabled = "YES">
|
||||
</EnvironmentVariable>
|
||||
</EnvironmentVariables>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
118
phpmon/Domain/Integrations/Valet/SiteScanner.swift
Normal file
118
phpmon/Domain/Integrations/Valet/SiteScanner.swift
Normal file
@ -0,0 +1,118 @@
|
||||
//
|
||||
// ValetSiteScanner.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 19/03/2022.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol SiteScanner
|
||||
{
|
||||
func resolveSiteCount(paths: [String]) -> Int
|
||||
|
||||
func resolveSitesFrom(paths: [String]) -> [ValetSite]
|
||||
}
|
||||
|
||||
class FakeSiteScanner: SiteScanner
|
||||
{
|
||||
let fakes = [
|
||||
ValetSite(fakeWithName: "laravel", tld: "test", secure: true, path: "~/Code/laravel/framework", linked: true),
|
||||
|
||||
ValetSite(fakeWithName: "tailwind", tld: "test", secure: true, path: "~/Code/tailwind/site", linked: true),
|
||||
|
||||
ValetSite(fakeWithName: "forge", tld: "test", secure: true, path: "~/Code/laravel/forge", linked: true),
|
||||
|
||||
ValetSite(fakeWithName: "wordpress", tld: "test", secure: false,
|
||||
path: "~/Code/wordpress", linked: false, driver: "Wordpress", constraint: "^7.4", isolated: "7.4")
|
||||
]
|
||||
|
||||
func resolveSiteCount(paths: [String]) -> Int {
|
||||
return fakes.count
|
||||
}
|
||||
|
||||
func resolveSitesFrom(paths: [String]) -> [ValetSite] {
|
||||
return fakes
|
||||
}
|
||||
}
|
||||
|
||||
class ValetSiteScanner: SiteScanner
|
||||
{
|
||||
func resolveSiteCount(paths: [String]) -> Int {
|
||||
return paths.map { path in
|
||||
|
||||
let entries = try! FileManager.default
|
||||
.contentsOfDirectory(atPath: path)
|
||||
|
||||
return entries
|
||||
.map { self.isSite($0, forPath: path) }
|
||||
.filter{ $0 == true}
|
||||
.count
|
||||
|
||||
}.reduce(0, +)
|
||||
}
|
||||
|
||||
func resolveSitesFrom(paths: [String]) -> [ValetSite] {
|
||||
var sites: [ValetSite] = []
|
||||
|
||||
paths.forEach { path in
|
||||
let entries = try! FileManager.default
|
||||
.contentsOfDirectory(atPath: path)
|
||||
|
||||
return entries.forEach {
|
||||
if let site = self.getSite($0, forPath: path, tld: Valet.shared.config.tld) {
|
||||
sites.append(site)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sites
|
||||
}
|
||||
|
||||
/**
|
||||
Determines whether the site can be resolved as a symbolic link or as a directory.
|
||||
Regular files are ignored. Returns true if the path can be parsed.
|
||||
*/
|
||||
private func isSite(_ entry: String, forPath path: String) -> Bool {
|
||||
let siteDir = path + "/" + entry
|
||||
|
||||
let attrs = try! FileManager.default.attributesOfItem(atPath: siteDir)
|
||||
|
||||
let type = attrs[FileAttributeKey.type] as! FileAttributeType
|
||||
|
||||
if type == FileAttributeType.typeSymbolicLink || type == FileAttributeType.typeDirectory {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
Determines whether the site can be resolved as a symbolic link or as a directory.
|
||||
Regular files are ignored, and the site is added to Valet's list of sites.
|
||||
*/
|
||||
private func getSite(_ entry: String, forPath path: String, tld: String) -> ValetSite? {
|
||||
let siteDir = path + "/" + entry
|
||||
|
||||
// See if the file is a symlink, if so, resolve it
|
||||
let attrs = try! FileManager.default.attributesOfItem(atPath: siteDir)
|
||||
|
||||
// We can also determine whether the thing at the path is a directory, too
|
||||
let type = attrs[FileAttributeKey.type] as! FileAttributeType
|
||||
|
||||
// We should also check that we can interpret the path correctly
|
||||
if URL(fileURLWithPath: siteDir).lastPathComponent == "" {
|
||||
Log.warn("Could not parse the site: \(siteDir), skipping!")
|
||||
return nil
|
||||
}
|
||||
|
||||
if type == FileAttributeType.typeSymbolicLink {
|
||||
return ValetSite(aliasPath: siteDir, tld: tld)
|
||||
} else if type == FileAttributeType.typeDirectory {
|
||||
return ValetSite(absolutePath: siteDir, tld: tld)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
@ -38,6 +38,19 @@ class Valet {
|
||||
self.sites = []
|
||||
}
|
||||
|
||||
/**
|
||||
If marketing mode is enabled, show a list of sites that are used for promotional screenshots.
|
||||
This can be done by swapping out the real Valet scanner with one that always returns a fixed
|
||||
list of fake sites. You should not interact with these sites!
|
||||
*/
|
||||
static var siteScanner: SiteScanner {
|
||||
if ProcessInfo.processInfo.environment["PHPMON_MARKETING_MODE"] != nil {
|
||||
return FakeSiteScanner()
|
||||
}
|
||||
|
||||
return ValetSiteScanner()
|
||||
}
|
||||
|
||||
/**
|
||||
Check if a particular feature is enabled.
|
||||
*/
|
||||
@ -89,7 +102,7 @@ class Valet {
|
||||
return
|
||||
}
|
||||
|
||||
resolvePaths(tld: config.tld)
|
||||
resolvePaths()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,82 +141,23 @@ class Valet {
|
||||
Returns a count of how many sites are linked and parked.
|
||||
*/
|
||||
private func countPaths() -> Int {
|
||||
var count = 0
|
||||
for path in config.paths {
|
||||
let entries = try! FileManager.default.contentsOfDirectory(atPath: path)
|
||||
for entry in entries {
|
||||
if resolveSite(entry, forPath: path) {
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
return count
|
||||
return Self.siteScanner
|
||||
.resolveSiteCount(paths: config.paths)
|
||||
}
|
||||
|
||||
/**
|
||||
Resolves all paths and creates linked or parked site instances that can be referenced later.
|
||||
*/
|
||||
private func resolvePaths(tld: String) {
|
||||
private func resolvePaths() {
|
||||
isBusy = true
|
||||
|
||||
sites = []
|
||||
|
||||
for path in config.paths {
|
||||
let entries = try! FileManager.default.contentsOfDirectory(atPath: path)
|
||||
for entry in entries {
|
||||
resolvePath(entry, forPath: path, tld: tld)
|
||||
}
|
||||
}
|
||||
|
||||
sites = sites.sorted { $0.absolutePath < $1.absolutePath }
|
||||
sites = Self.siteScanner
|
||||
.resolveSitesFrom(paths: config.paths)
|
||||
.sorted { $0.absolutePath < $1.absolutePath }
|
||||
|
||||
isBusy = false
|
||||
}
|
||||
|
||||
/**
|
||||
Determines whether the site can be resolved as a symbolic link or as a directory.
|
||||
Regular files are ignored. Returns true if the path can be parsed.
|
||||
*/
|
||||
private func resolveSite(_ entry: String, forPath path: String) -> Bool {
|
||||
let siteDir = path + "/" + entry
|
||||
|
||||
let attrs = try! FileManager.default.attributesOfItem(atPath: siteDir)
|
||||
|
||||
let type = attrs[FileAttributeKey.type] as! FileAttributeType
|
||||
|
||||
if type == FileAttributeType.typeSymbolicLink || type == FileAttributeType.typeDirectory {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
Determines whether the site can be resolved as a symbolic link or as a directory.
|
||||
Regular files are ignored, and the site is added to Valet's list of sites.
|
||||
*/
|
||||
private func resolvePath(_ entry: String, forPath path: String, tld: String) {
|
||||
let siteDir = path + "/" + entry
|
||||
|
||||
// See if the file is a symlink, if so, resolve it
|
||||
let attrs = try! FileManager.default.attributesOfItem(atPath: siteDir)
|
||||
|
||||
// We can also determine whether the thing at the path is a directory, too
|
||||
let type = attrs[FileAttributeKey.type] as! FileAttributeType
|
||||
|
||||
// We should also check that we can interpret the path correctly
|
||||
if URL(fileURLWithPath: siteDir).lastPathComponent == "" {
|
||||
Log.warn("Could not parse the site: \(siteDir), skipping!")
|
||||
return
|
||||
}
|
||||
|
||||
if type == FileAttributeType.typeSymbolicLink {
|
||||
sites.append(ValetSite(aliasPath: siteDir, tld: tld))
|
||||
} else if type == FileAttributeType.typeDirectory {
|
||||
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"!)
|
||||
|
37
phpmon/Domain/Integrations/Valet/ValetSite+Fake.swift
Normal file
37
phpmon/Domain/Integrations/Valet/ValetSite+Fake.swift
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// ValetSite+Fake.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 19/03/2022.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension ValetSite {
|
||||
|
||||
convenience init(
|
||||
fakeWithName name: String,
|
||||
tld: String,
|
||||
secure: Bool,
|
||||
path: String,
|
||||
linked: Bool,
|
||||
driver: String = "Laravel (^9.0)",
|
||||
constraint: String = "^8.1",
|
||||
isolated: String? = nil
|
||||
) {
|
||||
self.init(name: name, tld: tld, absolutePath: path, aliasPath: nil, makeDeterminations: false)
|
||||
self.secured = secure
|
||||
self.composerPhp = constraint
|
||||
|
||||
self.driver = driver
|
||||
self.driverDeterminedByComposer = true
|
||||
if linked {
|
||||
self.aliasPath = self.absolutePath
|
||||
}
|
||||
if let isolated = isolated {
|
||||
self.isolatedPhpVersion = PhpInstallation(isolated)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -60,16 +60,25 @@ class ValetSite {
|
||||
case valetphprc = "valetphprc"
|
||||
}
|
||||
|
||||
init(name: String, tld: String, absolutePath: String, aliasPath: String? = nil) {
|
||||
init(
|
||||
name: String,
|
||||
tld: String,
|
||||
absolutePath: String,
|
||||
aliasPath: String? = nil,
|
||||
makeDeterminations: Bool = true
|
||||
) {
|
||||
self.name = name
|
||||
self.tld = tld
|
||||
self.absolutePath = absolutePath
|
||||
self.aliasPath = aliasPath
|
||||
self.secured = false
|
||||
|
||||
determineSecured()
|
||||
determineComposerPhpVersion()
|
||||
determineDriver()
|
||||
determineIsolated()
|
||||
if makeDeterminations {
|
||||
determineSecured()
|
||||
determineComposerPhpVersion()
|
||||
determineDriver()
|
||||
determineIsolated()
|
||||
}
|
||||
}
|
||||
|
||||
convenience init(absolutePath: String, tld: String) {
|
||||
|
Reference in New Issue
Block a user