1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2025-12-21 03:10:06 +01:00

♻️ Get rid of ContainerMacro

This commit is contained in:
2025-10-28 13:16:30 +01:00
parent 8eca1a55b5
commit 16522ddc60
39 changed files with 263 additions and 471 deletions

View File

@@ -3,11 +3,10 @@
archiveVersion = 1;
classes = {
};
objectVersion = 60;
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
0303412A2E92C3560031BE17 /* ContainerMacro in Frameworks */ = {isa = PBXBuildFile; productRef = 030341292E92C3560031BE17 /* ContainerMacro */; };
0309E6672B0D4B2F002AC007 /* BrewExtensionsObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0309E6662B0D4B2F002AC007 /* BrewExtensionsObservable.swift */; };
031E2B692B1525A7007C29E1 /* BrewPhpExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031E2B682B1525A7007C29E1 /* BrewPhpExtension.swift */; };
031E2B6A2B1525A7007C29E1 /* BrewPhpExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031E2B682B1525A7007C29E1 /* BrewPhpExtension.swift */; };
@@ -1295,7 +1294,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0303412A2E92C3560031BE17 /* ContainerMacro in Frameworks */,
C47014FF2C46D57C0069AAE7 /* NVAlert in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -2432,7 +2430,6 @@
name = "PHP Monitor";
packageProductDependencies = (
C47014FE2C46D57C0069AAE7 /* NVAlert */,
030341292E92C3560031BE17 /* ContainerMacro */,
);
productName = phpmon;
productReference = C41C1B3322B0097F00E7CF16 /* PHP Monitor.app */;
@@ -2550,7 +2547,6 @@
packageReferences = (
C47014FA2C46D31B0069AAE7 /* XCRemoteSwiftPackageReference "NVAppUpdater" */,
C47014FD2C46D57C0069AAE7 /* XCRemoteSwiftPackageReference "NVAlert" */,
030341282E92C3560031BE17 /* XCLocalSwiftPackageReference "packages/container-macro" */,
);
productRefGroup = C41C1B3422B0097F00E7CF16 /* Products */;
projectDirPath = "";
@@ -4505,13 +4501,6 @@
};
/* End XCConfigurationList section */
/* Begin XCLocalSwiftPackageReference section */
030341282E92C3560031BE17 /* XCLocalSwiftPackageReference "packages/container-macro" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = "packages/container-macro";
};
/* End XCLocalSwiftPackageReference section */
/* Begin XCRemoteSwiftPackageReference section */
C47014FA2C46D31B0069AAE7 /* XCRemoteSwiftPackageReference "NVAppUpdater" */ = {
isa = XCRemoteSwiftPackageReference;
@@ -4532,10 +4521,6 @@
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
030341292E92C3560031BE17 /* ContainerMacro */ = {
isa = XCSwiftPackageProductDependency;
productName = ContainerMacro;
};
C47014FB2C46D31B0069AAE7 /* NVAppUpdater */ = {
isa = XCSwiftPackageProductDependency;
package = C47014FA2C46D31B0069AAE7 /* XCRemoteSwiftPackageReference "NVAppUpdater" */;

View File

@@ -1,67 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "2600"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ContainerMacro"
BuildableName = "ContainerMacro"
BlueprintName = "ContainerMacro"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ContainerMacro"
BuildableName = "ContainerMacro"
BlueprintName = "ContainerMacro"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>ContainerMacro.xcscheme_^#shared#^_</key>
<dict>
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>4</integer>
</dict>
<key>NVContainer.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>4</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>ContainerMacro</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>

View File

@@ -1,38 +0,0 @@
// swift-tools-version: 5.9
import PackageDescription
import CompilerPluginSupport
let package = Package(
name: "ContainerMacro",
platforms: [.macOS(.v13)],
products: [
.library(
name: "ContainerMacro",
targets: ["ContainerMacro"]
),
],
dependencies: [
.package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0"),
],
targets: [
.macro(
name: "ContainerMacroPlugin",
dependencies: [
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
.product(name: "SwiftCompilerPlugin", package: "swift-syntax")
]
),
.target(
name: "ContainerMacro",
dependencies: ["ContainerMacroPlugin"]
),
.testTarget(
name: "ContainerMacroTests",
dependencies: [
"ContainerMacroPlugin",
.product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"),
]
),
]
)

View File

@@ -1,52 +0,0 @@
# ContainerMacro
A Swift macro for automatic container dependency injection in PHP Monitor.
## Usage
```swift
import ContainerMacro
@ContainerAccess
class MyClass {
func doSomething() {
container.shell.run("command")
container.favorites.add(site)
}
}
```
## What it generates
The `@ContainerAccess` macro automatically adds:
- A private `container: Container` property
- An `init(_ container:)` initializer
- Computed properties for each Container service you want to access
## Maintenance
When you add new services to `Container`, you must update the service list in:
**`Sources/ContainerMacroPlugin/ContainerAccessMacro.swift`** (lines 14-18):
```swift
let allContainerServices: [(name: String, type: String)] = [
("shell", "ShellProtocol"),
// Add your new service here:
// ("myNewService", "MyServiceType"),
]
```
## Testing
Run tests with:
```bash
cd packages/container-macro
swift test
```
## Integration
The package is added as a local Swift Package in Xcode:
- File → Add Package Dependencies → Add Local...
- Select `packages/container-macro`

View File

@@ -1,24 +0,0 @@
/// Automatically adds container dependency injection to a class.
///
/// This macro generates:
/// - A public `container` property
/// - An `init(_ container:)` initializer
/// - Computed properties for all Container services
///
/// Usage:
/// ```swift
/// import ContainerMacro
///
/// @ContainerAccess
/// class MyClass {
/// func doSomething() {
/// container.shell.run("command")
/// container.favorites.add(site)
/// }
/// }
/// ```
@attached(member, names: named(container), named(init(container:)), arbitrary)
public macro ContainerAccess() = #externalMacro(
module: "ContainerMacroPlugin",
type: "ContainerAccessMacro"
)

View File

@@ -1,61 +0,0 @@
import SwiftCompilerPlugin
import SwiftSyntax
import SwiftSyntaxBuilder
import SwiftSyntaxMacros
public struct ContainerAccessMacro: MemberMacro {
public static func expansion(
of node: AttributeSyntax,
providingMembersOf declaration: some DeclGroupSyntax,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
// Map of ALL Container properties to their types
// This should be kept in sync with the Container class
let allContainerServices: [(name: String, type: String)] = [
("shell", "ShellProtocol"),
("filesystem", "FileSystemProtocol"),
("command", "CommandProtocol"),
("paths", "Paths"),
("phpEnvs", "PhpEnvironments"),
("favorites", "Favorites"),
("warningManager", "WarningManager")
]
// Check if the class already has an initializer
let hasExistingInit = declaration.memberBlock.members.contains { member in
if let initDecl = member.decl.as(InitializerDeclSyntax.self) {
return true
}
return false
}
var members: [DeclSyntax] = []
// Add the container property
members.append(
"""
public let container: Container
"""
)
// Only add the initializer if one doesn't already exist
if !hasExistingInit {
members.append(
"""
init(_ container: Container) {
self.container = container
}
"""
)
}
return members
}
}
@main
struct ContainerMacroPlugin: CompilerPlugin {
let providingMacros: [Macro.Type] = [
ContainerAccessMacro.self,
]
}

View File

@@ -1,106 +0,0 @@
import SwiftSyntaxMacros
import SwiftSyntaxMacrosTestSupport
import XCTest
#if canImport(ContainerMacroPlugin)
import ContainerMacroPlugin
final class ContainerAccessMacroTests: XCTestCase {
let testMacros: [String: Macro.Type] = [
"ContainerAccess": ContainerAccessMacro.self,
]
func testContainerAccessWithSpecificServices() throws {
assertMacroExpansion(
"""
@ContainerAccess(["shell"])
class InternalSwitcher {
func doSomething() {
print("Hello")
}
}
""",
expandedSource: """
class InternalSwitcher {
func doSomething() {
print("Hello")
}
private let container: Container
init(container: Container = App.shared.container) {
self.container = container
}
private var shell: ShellProtocol {
return container.shell
}
}
""",
macros: testMacros
)
}
func testContainerAccessWithMultipleServices() throws {
assertMacroExpansion(
"""
@ContainerAccess(["shell", "favorites"])
class MyClass {
}
""",
expandedSource: """
class MyClass {
private let container: Container
init(container: Container = App.shared.container) {
self.container = container
}
private var shell: ShellProtocol {
return container.shell
}
private var favorites: Favorites {
return container.favorites
}
}
""",
macros: testMacros
)
}
func testContainerAccessWithAllServices() throws {
assertMacroExpansion(
"""
@ContainerAccess
class MyClass {
}
""",
expandedSource: """
class MyClass {
private let container: Container
init(container: Container = App.shared.container) {
self.container = container
}
private var shell: ShellProtocol {
return container.shell
}
private var favorites: Favorites {
return container.favorites
}
private var warningManager: WarningManager {
return container.warningManager
}
}
""",
macros: testMacros
)
}
}
#endif

View File

@@ -7,10 +7,19 @@
import Foundation
import AppKit
import ContainerMacro
@ContainerAccess
class Actions {
// MARK: - Container
var container: Container
init(_ container: Container) {
self.container = container
}
// MARK: - Variables
var formulae: HomebrewFormulae {
return HomebrewFormulae(App.shared.container)
}

View File

@@ -7,10 +7,19 @@
//
import Foundation
import ContainerMacro
@ContainerAccess
struct HomebrewFormulae {
// MARK: - Container
var container: Container
init(_ container: Container) {
self.container = container
}
// MARK: - Variables
var php: HomebrewFormula {
if container.phpEnvs.homebrewPackage == nil {
return HomebrewFormula("php", elevated: true)

View File

@@ -21,6 +21,9 @@ extension String {
}
class RealFileSystem: FileSystemProtocol {
// MARK: - Container
var container: Container
init(container: Container) {

View File

@@ -7,17 +7,22 @@
//
import Foundation
import ContainerMacro
/// An application that is capable of opening a particular directory (usually of a PHP project).
/// In most cases this is going to be a code editor, but it could also be another application
/// that supports opening those directories, like a visual Git client or a terminal app.
@ContainerAccess
class Application {
enum AppType {
case editor, browser, git_gui, terminal, user_supplied
}
// MARK: - Container
var container: Container
// MARK: - Variables
/// Name of the app. Used for display purposes and to determine `name.app` exists.
let name: String

View File

@@ -6,7 +6,6 @@
//
import Foundation
import ContainerMacro
/**
An installed version of PHP, that was detected by scanning the `/opt/php@version/bin` directory.
@@ -18,22 +17,27 @@ import ContainerMacro
Using `version.short` is advisable if you want to interact with Homebrew.
*/
@ContainerAccess
class ActivePhpInstallation {
// MARK: - Container
var container: Container
// MARK: - Variables
var version: VersionNumber!
var limits: Limits!
var iniFiles: [PhpConfigurationFile] = []
var hasErrorState: Bool = false
// MARK: - Computed
var extensions: [PhpExtension] {
return iniFiles.flatMap { initFile in
return initFile.extensions
}
}
// MARK: - Computed
var formula: String {
return (version.short == PhpEnvironments.brewPhpAlias) ? "php" : "php@\(version.short)"
}

View File

@@ -8,10 +8,19 @@
import Foundation
import Cocoa
import ContainerMacro
@ContainerAccess
class Xdebug {
// MARK: - Container
var container: Container
init(_ container: Container) {
self.container = container
}
// MARK: - Variables
public var enabled: Bool {
return container.phpEnvs.getConfigFile(forKey: "xdebug.mode") != nil
}
@@ -28,6 +37,19 @@ class Xdebug {
return value.components(separatedBy: ",").filter { self.availableModes.contains($0) }
}
public var availableModes: [String] {
return [
"develop",
"coverage",
"debug",
"gcstats",
"profile",
"trace"
]
}
// MARK: - Methods
public func asMenuItems() -> [NSMenuItem] {
var items: [NSMenuItem] = []
@@ -46,15 +68,4 @@ class Xdebug {
return items
}
public var availableModes: [String] {
return [
"develop",
"coverage",
"debug",
"gcstats",
"profile",
"trace"
]
}
}

View File

@@ -7,7 +7,6 @@
//
import Foundation
import ContainerMacro
/**
A PHP extension that was detected in the php.ini file.
@@ -16,8 +15,14 @@ import ContainerMacro
- Note: You need to know more about regular expressions to be able to deal with these NSRegularExpression
instances. You can find more information here: https://nshipster.com/swift-regular-expressions/
*/
@ContainerAccess
class PhpExtension {
// MARK: - Container
var container: Container
// MARK: - Variables
/// The file where this extension was located.
var file: String

View File

@@ -7,10 +7,15 @@
//
import Foundation
import ContainerMacro
@ContainerAccess
class PhpInstallation {
// MARK: - Container
var container: Container
// MARK: - Variables
var versionNumber: VersionNumber
var iniFiles: [PhpConfigurationFile] = []
@@ -35,6 +40,8 @@ class PhpInstallation {
return "php@\(self.versionNumber.short)"
}
// MARK: - Methods
/**
In order to determine details about a PHP installation,
well simply run `php-config --version` in the relevant directory.

View File

@@ -7,10 +7,19 @@
//
import Foundation
import ContainerMacro
@ContainerAccess
class InternalSwitcher: PhpSwitcher {
// MARK: - Container
var container: Container
init(_ container: Container) {
self.container = container
}
// MARK: - Switcher
/**
Switching to a new PHP version involves:
- unlinking the current version

View File

@@ -8,10 +8,11 @@
import Foundation
import SwiftUI
import ContainerMacro
@ContainerAccess
class ServicesManager: ObservableObject {
var container: Container
@ObservedObject static var shared: ServicesManager = ValetServicesManager(App.shared.container)
@Published var services = [Service]()

View File

@@ -9,9 +9,9 @@
import Foundation
import Cocoa
import NVAlert
import ContainerMacro
class ValetServicesManager: ServicesManager {
override init(_ container: Container) {
super.init(container)

View File

@@ -8,14 +8,25 @@
import Foundation
import NVAlert
import ContainerMacro
@ContainerAccess
@MainActor class ComposerWindow {
// MARK: - Container
var container: Container
init(_ container: Container) {
self.container = container
}
// MARK: - Variables
private var shouldNotify: Bool! = nil
private var completion: ((Bool) -> Void)! = nil
private var window: TerminalProgressWindowController?
// MARK: - Methods
/**
Updates the global dependencies and runs the completion callback when done.
*/

View File

@@ -7,10 +7,19 @@
//
import Foundation
import ContainerMacro
@ContainerAccess
class BrewPermissionFixer {
// MARK: - Container
var container: Container
init(_ container: Container) {
self.container = container
}
// MARK: - Variables
var broken: [DueOwnershipFormula] = []
/**

View File

@@ -7,10 +7,19 @@
//
import Foundation
import ContainerMacro
@ContainerAccess
class Brew {
// MARK: - Container
var container: Container
init(_ container: Container) {
self.container = container
}
// MARK: - Variables
static let shared = Brew(App.shared.container)
/// Formulae that can be observed.

View File

@@ -8,12 +8,23 @@
import Foundation
import NVAlert
import ContainerMacro
@ContainerAccess
class BrewDiagnostics {
// MARK: - Container
var container: Container
init(_ container: Container) {
self.container = container
}
// MARK: - Static Instance
public static let shared = BrewDiagnostics(App.shared.container)
// MARK: - Variables
var filesystem: FileSystemProtocol {
return container.filesystem
}
@@ -23,6 +34,8 @@ class BrewDiagnostics {
*/
public var installedTaps: [String] = []
// MARK: - Methods
/**
Load which taps are installed.
*/

View File

@@ -7,9 +7,9 @@
//
import Foundation
import ContainerMacro
struct BrewPhpFormula: Equatable {
/// The dependency container.
let container: Container

View File

@@ -7,7 +7,6 @@
//
import Foundation
import ContainerMacro
protocol HandlesBrewPhpFormulae {
func loadPhpVersions(loadOutdated: Bool) async -> [BrewPhpFormula]
@@ -24,8 +23,17 @@ extension HandlesBrewPhpFormulae {
}
}
@ContainerAccess
class BrewPhpFormulaeHandler: HandlesBrewPhpFormulae {
// MARK: - Container
var container: Container
init(_ container: Container) {
self.container = container
}
// MARK: - Methods
public func loadPhpVersions(loadOutdated: Bool) async -> [BrewPhpFormula] {
var outdated: [OutdatedFormula]?

View File

@@ -7,10 +7,15 @@
//
import Foundation
import ContainerMacro
@ContainerAccess
class InstallPhpExtensionCommand: BrewCommand {
// MARK: - Container
var container: Container
// MARK: - Variables
let installing: [BrewPhpExtension]
func getExtensionNames() -> String {
@@ -21,6 +26,8 @@ class InstallPhpExtensionCommand: BrewCommand {
return "phpman.steps.installing".localized(getExtensionNames())
}
// MARK: - Methods
public init(_ container: Container,
install extensions: [BrewPhpExtension]) {
self.container = container

View File

@@ -7,12 +7,19 @@
//
import Foundation
import ContainerMacro
@ContainerAccess
class RemovePhpExtensionCommand: BrewCommand {
// MARK: - Container
var container: Container
// MARK: - Variables
public let phpExtension: BrewPhpExtension
// MARK: - Methods
public init(_ container: Container,
remove formula: BrewPhpExtension) {
self.container = container

View File

@@ -7,15 +7,22 @@
//
import Foundation
import ContainerMacro
@ContainerAccess
class ModifyPhpVersionCommand: BrewCommand {
// MARK: - Container
var container: Container
// MARK: - Variables
let title: String
let installing: [BrewPhpFormula]
let upgrading: [BrewPhpFormula]
let phpGuard: PhpGuard
// MARK: - Methods
func getCommandTitle() -> String {
return title
}

View File

@@ -7,14 +7,21 @@
//
import Foundation
import ContainerMacro
@ContainerAccess
class RemovePhpVersionCommand: BrewCommand {
// MARK: - Container
var container: Container
// MARK: - Variables
let formula: String
let version: String
let phpGuard: PhpGuard
// MARK: - Methods
init(
_ container: Container,
formula: String

View File

@@ -7,15 +7,24 @@
//
import Foundation
import ContainerMacro
struct ValetInteractionError: Error {
/// The command the user should try (and failed).
var command: String
}
@ContainerAccess
class ValetInteractor {
// MARK: - Container
var container: Container
init(_ container: Container) {
self.container = container
}
// MARK: - Shared Instance
static var shared = ValetInteractor(App.shared.container)
public static func useFake() {

View File

@@ -7,11 +7,17 @@
//
import Foundation
import ContainerMacro
@ContainerAccess
class ValetDomainScanner: DomainScanner {
// MARK: - Container
var container: Container
init(_ container: Container) {
self.container = container
}
// MARK: - Sites
func resolveSiteCount(paths: [String]) -> Int {

View File

@@ -7,10 +7,12 @@
//
import Foundation
import ContainerMacro
@ContainerAccess
class ValetSite: ValetListable {
/// Dependency container.
var container: Container
/// Name of the site. Does not include the TLD.
var name: String

View File

@@ -7,14 +7,12 @@
//
import Foundation
import ContainerMacro
/**
This class is responsible for handling the state of Valet throughout PHP Monitor. A singleton instance is created
and accessible throughout the lifecycle of the app, unless the user has decided to not use Valet. In that case,
only a restricted subset of functionality is available in the app.
*/
@ContainerAccess
class Valet {
enum FeatureFlag {
@@ -23,6 +21,9 @@ class Valet {
static let shared = Valet()
/// The dependency container.
var container: Container
/// The version of Valet that was detected.
var version: VersionNumber?

View File

@@ -6,10 +6,21 @@
// Copyright © 2025 Nico Verbruggen. All rights reserved.
//
import ContainerMacro
@ContainerAccess
///
/// This class is still WIP and pending for a future release of PHP Monitor.
///
class InstallHomebrew {
// MARK: - Container
var container: Container
init(_ container: Container) {
self.container = container
}
// MARK: - Methods
public func run() async throws {
let script = """
NONINTERACTIVE=1 /bin/bash -c \

View File

@@ -6,10 +6,18 @@
// Copyright © 2025 Nico Verbruggen. All rights reserved.
//
import ContainerMacro
@ContainerAccess
class ZshRunCommand {
// MARK: - Container
var container: Container
init(_ container: Container) {
self.container = container
}
// MARK: - Methods
/**
Adds a given line to .zshrc, which may be needed to adjust the PATH.
*/

View File

@@ -7,9 +7,9 @@
//
import Foundation
import ContainerMacro
class BytePhpPreference: PhpPreference {
enum UnitOption: String, CaseIterable {
case kilobyte = "K"
case megabyte = "M"

View File

@@ -8,10 +8,11 @@
import Foundation
import SwiftUI
import ContainerMacro
@ContainerAccess
class PhpPreference {
var container: Container
let key: String
init(_ container: Container, key: String) {

View File

@@ -7,19 +7,18 @@
//
import Foundation
import ContainerMacro
struct FileExistenceCheck {
let condition: (() -> Bool)?
let path: String
}
@ContainerAccess
class PhpConfigChecker {
public static var shared = PhpConfigChecker(App.shared.container)
var missing: [String] = []
var container: Container
init(_ container: Container) {
self.container = container
}
public func check() {
missing = []
@@ -49,3 +48,8 @@ class PhpConfigChecker {
}
}
}
struct FileExistenceCheck {
let condition: (() -> Bool)?
let path: String
}

View File

@@ -8,10 +8,11 @@
import Foundation
import Cocoa
import ContainerMacro
@ContainerAccess
class WarningManager: ObservableObject {
var container: Container
init(
container: Container,
fake: Bool = false