mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-08-06 19:40:08 +02:00
✅ Added linting
This commit is contained in:
15
.swiftlint.yml
Normal file
15
.swiftlint.yml
Normal file
@ -0,0 +1,15 @@
|
||||
disabled_rules:
|
||||
- todo
|
||||
- identifier_name
|
||||
- force_try
|
||||
- force_cast
|
||||
|
||||
opt_in_rules:
|
||||
- empty_count
|
||||
|
||||
included:
|
||||
- phpmon
|
||||
- phpmon-tests
|
||||
|
||||
excluded:
|
||||
- phpmon/Vendor
|
@ -230,6 +230,7 @@
|
||||
C4F30B0A278E1A1A00755FCE /* ComposerJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D89BC52783C99400A02B68 /* ComposerJson.swift */; };
|
||||
C4F30B0B278E203C00755FCE /* MainMenu+Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C3ED402783497000AB15D8 /* MainMenu+Startup.swift */; };
|
||||
C4F319C927B034A500AFF46F /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4DEB7D327A5D60B00834718 /* Stats.swift */; };
|
||||
C4F5FBCD28218CB8001065C5 /* Xdebug.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42337A2281F19F000459A48 /* Xdebug.swift */; };
|
||||
C4F7809C25D80344000DBC97 /* CommandTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F7809B25D80344000DBC97 /* CommandTest.swift */; };
|
||||
C4F780A825D80AE8000DBC97 /* php.ini in Resources */ = {isa = PBXBuildFile; fileRef = C4F780A725D80AE8000DBC97 /* php.ini */; };
|
||||
C4F780AE25D80B37000DBC97 /* PhpExtensionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F780AD25D80B37000DBC97 /* PhpExtensionTest.swift */; };
|
||||
@ -405,6 +406,7 @@
|
||||
C4F2E4392752F7D00020E974 /* PhpInstallation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpInstallation.swift; sourceTree = "<group>"; };
|
||||
C4F30B02278E16BA00755FCE /* HomebrewService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomebrewService.swift; sourceTree = "<group>"; };
|
||||
C4F30B06278E195800755FCE /* brew-services.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "brew-services.json"; sourceTree = "<group>"; };
|
||||
C4F5FBCC28218C93001065C5 /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .swiftlint.yml; sourceTree = "<group>"; };
|
||||
C4F7807925D7F84B000DBC97 /* phpmon-tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "phpmon-tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C4F7807D25D7F84B000DBC97 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
C4F7809B25D80344000DBC97 /* CommandTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandTest.swift; sourceTree = "<group>"; };
|
||||
@ -549,6 +551,7 @@
|
||||
C4E713562570150F00007428 /* SECURITY.md */,
|
||||
C4168F4427ADB4A3003B6C39 /* DEVELOPER.md */,
|
||||
54D9E0C027E4F5E9003B9AD9 /* LICENSE */,
|
||||
C4F5FBCC28218C93001065C5 /* .swiftlint.yml */,
|
||||
C4E713572570151400007428 /* docs */,
|
||||
C41C1B3522B0097F00E7CF16 /* phpmon */,
|
||||
C4F7807A25D7F84B000DBC97 /* phpmon-tests */,
|
||||
@ -974,6 +977,7 @@
|
||||
C41C1B2F22B0097F00E7CF16 /* Sources */,
|
||||
C41C1B3022B0097F00E7CF16 /* Frameworks */,
|
||||
C41C1B3122B0097F00E7CF16 /* Resources */,
|
||||
C4F5FBCB28216985001065C5 /* Run `swiftlint` */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@ -1089,6 +1093,27 @@
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
C4F5FBCB28216985001065C5 /* Run `swiftlint` */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run `swiftlint`";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\n\nif which swiftlint > /dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
C41C1B2F22B0097F00E7CF16 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
@ -1291,6 +1316,7 @@
|
||||
C449B4F227EE7FC400C47E8A /* DomainListPhpCell.swift in Sources */,
|
||||
C42CFB1A27DFE8BD00862737 /* NginxConfigurationTest.swift in Sources */,
|
||||
C4F30B0B278E203C00755FCE /* MainMenu+Startup.swift in Sources */,
|
||||
C4F5FBCD28218CB8001065C5 /* Xdebug.swift in Sources */,
|
||||
C40B24F227A310770018C7D2 /* Events.swift in Sources */,
|
||||
C4F30B0A278E1A1A00755FCE /* ComposerJson.swift in Sources */,
|
||||
C4C0E8E027F88AEB002D32A9 /* FakeSiteScanner.swift in Sources */,
|
||||
|
@ -64,9 +64,9 @@ class HomebrewPackageTest: XCTestCase {
|
||||
return ["php", "nginx", "dnsmasq"].contains(service.name)
|
||||
})
|
||||
|
||||
XCTAssertTrue(services.contains(where: {$0.name == "php"} ))
|
||||
XCTAssertTrue(services.contains(where: {$0.name == "nginx"} ))
|
||||
XCTAssertTrue(services.contains(where: {$0.name == "dnsmasq"} ))
|
||||
XCTAssertTrue(services.contains(where: {$0.name == "php"}))
|
||||
XCTAssertTrue(services.contains(where: {$0.name == "nginx"}))
|
||||
XCTAssertTrue(services.contains(where: {$0.name == "dnsmasq"}))
|
||||
XCTAssertEqual(services.count, 3)
|
||||
}
|
||||
|
||||
|
@ -12,33 +12,28 @@ class Actions {
|
||||
|
||||
// MARK: - Services
|
||||
|
||||
public static func restartPhpFpm()
|
||||
{
|
||||
public static func restartPhpFpm() {
|
||||
brew("services restart \(PhpEnv.phpInstall.formula)", sudo: true)
|
||||
}
|
||||
|
||||
public static func restartNginx()
|
||||
{
|
||||
public static func restartNginx() {
|
||||
brew("services restart nginx", sudo: true)
|
||||
}
|
||||
|
||||
public static func restartDnsMasq()
|
||||
{
|
||||
public static func restartDnsMasq() {
|
||||
brew("services restart dnsmasq", sudo: true)
|
||||
}
|
||||
|
||||
public static func stopAllServices()
|
||||
{
|
||||
public static func stopAllServices() {
|
||||
brew("services stop \(PhpEnv.phpInstall.formula)", sudo: true)
|
||||
brew("services stop nginx", sudo: true)
|
||||
brew("services stop dnsmasq", sudo: true)
|
||||
}
|
||||
|
||||
public static func fixHomebrewPermissions() throws
|
||||
{
|
||||
public static func fixHomebrewPermissions() throws {
|
||||
var servicesCommands = [
|
||||
"\(Paths.brew) services stop nginx",
|
||||
"\(Paths.brew) services stop dnsmasq",
|
||||
"\(Paths.brew) services stop dnsmasq"
|
||||
]
|
||||
var cellarCommands = [
|
||||
"chown -R \(Paths.whoami):admin \(Paths.cellarPath)/nginx",
|
||||
@ -64,34 +59,30 @@ class Actions {
|
||||
|
||||
let eventResult: NSAppleEventDescriptor? = appleScript?.executeAndReturnError(nil)
|
||||
|
||||
if (eventResult == nil) {
|
||||
if eventResult == nil {
|
||||
throw HomebrewPermissionError(kind: .applescriptNilError)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Finding Config Files
|
||||
|
||||
public static func openGenericPhpConfigFolder()
|
||||
{
|
||||
let files = [NSURL(fileURLWithPath: "\(Paths.etcPath)/php")];
|
||||
public static func openGenericPhpConfigFolder() {
|
||||
let files = [NSURL(fileURLWithPath: "\(Paths.etcPath)/php")]
|
||||
NSWorkspace.shared.activateFileViewerSelecting(files as [URL])
|
||||
}
|
||||
|
||||
public static func openGlobalComposerFolder()
|
||||
{
|
||||
public static func openGlobalComposerFolder() {
|
||||
let file = FileManager.default.homeDirectoryForCurrentUser
|
||||
.appendingPathComponent(".composer/composer.json")
|
||||
NSWorkspace.shared.activateFileViewerSelecting([file] as [URL])
|
||||
}
|
||||
|
||||
public static func openPhpConfigFolder(version: String)
|
||||
{
|
||||
let files = [NSURL(fileURLWithPath: "\(Paths.etcPath)/php/\(version)/php.ini")];
|
||||
public static func openPhpConfigFolder(version: String) {
|
||||
let files = [NSURL(fileURLWithPath: "\(Paths.etcPath)/php/\(version)/php.ini")]
|
||||
NSWorkspace.shared.activateFileViewerSelecting(files as [URL])
|
||||
}
|
||||
|
||||
public static func openValetConfigFolder()
|
||||
{
|
||||
public static func openValetConfigFolder() {
|
||||
let file = FileManager.default.homeDirectoryForCurrentUser
|
||||
.appendingPathComponent(".config/valet")
|
||||
NSWorkspace.shared.activateFileViewerSelecting([file] as [URL])
|
||||
@ -99,8 +90,7 @@ class Actions {
|
||||
|
||||
// MARK: - Other Actions
|
||||
|
||||
public static func createTempPhpInfoFile() -> URL
|
||||
{
|
||||
public static func createTempPhpInfoFile() -> URL {
|
||||
// Write a file called `phpmon_phpinfo.php` to /tmp
|
||||
try! "<?php phpinfo();".write(toFile: "/tmp/phpmon_phpinfo.php", atomically: true, encoding: .utf8)
|
||||
|
||||
@ -124,8 +114,7 @@ class Actions {
|
||||
If this does not solve the issue, the user may need to install additional
|
||||
extensions and/or run `composer global update`.
|
||||
*/
|
||||
public static func fixMyValet(completed: @escaping () -> Void)
|
||||
{
|
||||
public static func fixMyValet(completed: @escaping () -> Void) {
|
||||
InternalSwitcher().performSwitch(to: PhpEnv.brewPhpVersion, completion: {
|
||||
brew("services restart dnsmasq", sudo: true)
|
||||
brew("services restart php", sudo: true)
|
||||
|
@ -28,7 +28,7 @@ public class Command {
|
||||
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||
let output: String = String.init(data: data, encoding: String.Encoding.utf8)!
|
||||
|
||||
if (trimNewlines) {
|
||||
if trimNewlines {
|
||||
return output.components(separatedBy: .newlines)
|
||||
.filter({ !$0.isEmpty })
|
||||
.joined(separator: "\n")
|
||||
|
@ -11,24 +11,21 @@
|
||||
/**
|
||||
Runs a `valet` command. Defaults to running as superuser.
|
||||
*/
|
||||
func valet(_ command: String, sudo: Bool = true) -> String
|
||||
{
|
||||
func valet(_ command: String, sudo: Bool = true) -> String {
|
||||
return Shell.pipe("\(sudo ? "sudo " : "")" + "\(Paths.valet) \(command)", requiresPath: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Runs a `brew` command. Can run as superuser.
|
||||
*/
|
||||
func brew(_ command: String, sudo: Bool = false)
|
||||
{
|
||||
func brew(_ command: String, sudo: Bool = false) {
|
||||
Shell.run("\(sudo ? "sudo " : "")" + "\(Paths.brew) \(command)")
|
||||
}
|
||||
|
||||
/**
|
||||
Runs `sed` in order to replace all occurrences of a string in a specific file with another.
|
||||
*/
|
||||
func sed(file: String, original: String, replacement: String)
|
||||
{
|
||||
func sed(file: String, original: String, replacement: String) {
|
||||
// Escape slashes (or `sed` won't work)
|
||||
let e_original = original.replacingOccurrences(of: "/", with: "\\/")
|
||||
let e_replacement = replacement.replacingOccurrences(of: "/", with: "\\/")
|
||||
@ -45,8 +42,7 @@ func sed(file: String, original: String, replacement: String)
|
||||
/**
|
||||
Uses `grep` to determine whether a particular query string can be found in a particular file.
|
||||
*/
|
||||
func grepContains(file: String, query: String) -> Bool
|
||||
{
|
||||
func grepContains(file: String, query: String) -> Bool {
|
||||
return Shell.pipe("""
|
||||
grep -q '\(query)' \(file); [ $? -eq 0 ] && echo "YES" || echo "NO"
|
||||
""")
|
||||
|
@ -49,7 +49,7 @@ public class Paths {
|
||||
// - MARK: Detected Binaries
|
||||
|
||||
/** The path to the Composer binary. Can be in multiple locations, so is detected instead. */
|
||||
public static var composer: String? = nil
|
||||
public static var composer: String?
|
||||
|
||||
// - MARK: Paths
|
||||
|
||||
|
@ -35,8 +35,11 @@ extension Process {
|
||||
forName: NSNotification.Name.NSFileHandleDataAvailable,
|
||||
object: pipe.fileHandleForReading,
|
||||
queue: nil
|
||||
) { notification in
|
||||
if let outputString = String(data: pipe.fileHandleForReading.availableData, encoding: String.Encoding.utf8) {
|
||||
) { _ in
|
||||
if let outputString = String(
|
||||
data: pipe.fileHandleForReading.availableData,
|
||||
encoding: String.Encoding.utf8
|
||||
) {
|
||||
callback(outputString)
|
||||
}
|
||||
pipe.fileHandleForReading.waitForDataInBackgroundAndNotify()
|
||||
|
@ -14,25 +14,25 @@ extension NSWindow {
|
||||
/**
|
||||
Shakes a window. Inspired by: http://blog.ericd.net/2016/09/30/shaking-a-macos-window/
|
||||
*/
|
||||
func shake(){
|
||||
func shake() {
|
||||
let numberOfShakes = 3, durationOfShake = 0.2, vigourOfShake: CGFloat = 0.03
|
||||
|
||||
let frame: CGRect = self.frame
|
||||
let shakeAnimation :CAKeyframeAnimation = CAKeyframeAnimation()
|
||||
let shakeAnimation: CAKeyframeAnimation = CAKeyframeAnimation()
|
||||
|
||||
let shakePath = CGMutablePath()
|
||||
shakePath.move( to: CGPoint(x:NSMinX(frame), y:NSMinY(frame)))
|
||||
shakePath.move( to: CGPoint(x: frame.minX, y: frame.minY))
|
||||
|
||||
for _ in 0...numberOfShakes-1 {
|
||||
shakePath.addLine(to: CGPoint(x:NSMinX(frame) - frame.size.width * vigourOfShake, y:NSMinY(frame)))
|
||||
shakePath.addLine(to: CGPoint(x:NSMinX(frame) + frame.size.width * vigourOfShake, y:NSMinY(frame)))
|
||||
shakePath.addLine(to: CGPoint(x: frame.minX - frame.size.width * vigourOfShake, y: frame.minY))
|
||||
shakePath.addLine(to: CGPoint(x: frame.minX + frame.size.width * vigourOfShake, y: frame.minY))
|
||||
}
|
||||
|
||||
shakePath.closeSubpath()
|
||||
shakeAnimation.path = shakePath
|
||||
shakeAnimation.duration = durationOfShake
|
||||
|
||||
self.animations = ["frameOrigin":shakeAnimation]
|
||||
self.animations = ["frameOrigin": shakeAnimation]
|
||||
self.animator().setFrameOrigin(self.frame.origin)
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ extension String {
|
||||
}
|
||||
|
||||
func countInstances(of stringToFind: String) -> Int {
|
||||
if (stringToFind.isEmpty) {
|
||||
if stringToFind.isEmpty {
|
||||
return 0
|
||||
}
|
||||
|
||||
|
@ -26,10 +26,10 @@ extension XibLoadable where Self: NSView {
|
||||
|
||||
static func createFromXib(in bundle: Bundle = Bundle.main) -> Self? {
|
||||
guard let xibName = xibName else { return nil }
|
||||
var topLevelArray: NSArray? = nil
|
||||
var topLevelArray: NSArray?
|
||||
bundle.loadNibNamed(NSNib.Name(xibName), owner: self, topLevelObjects: &topLevelArray)
|
||||
guard let results = topLevelArray else { return nil }
|
||||
let views = Array<Any>(results).filter { $0 is Self }
|
||||
let views = [Any](results).filter { $0 is Self }
|
||||
return views.last as? Self
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ class Alert {
|
||||
alert.messageText = messageText
|
||||
alert.informativeText = informativeText
|
||||
alert.addButton(withTitle: buttonTitle)
|
||||
if (!secondButtonTitle.isEmpty) {
|
||||
if !secondButtonTitle.isEmpty {
|
||||
alert.addButton(withTitle: secondButtonTitle)
|
||||
}
|
||||
alert.beginSheetModal(for: window) { response in
|
||||
|
@ -24,7 +24,7 @@ class MenuBarImageGenerator {
|
||||
NSAttributedString.Key.paragraphStyle: textStyle
|
||||
]
|
||||
|
||||
let padding : CGFloat = 2.0;
|
||||
let padding: CGFloat = 2.0
|
||||
|
||||
// Create an attributed string so we'll know how wide the item will need to be
|
||||
let attributedString = NSAttributedString(string: text, attributes: textFontAttributes)
|
||||
|
@ -23,7 +23,7 @@ class VersionExtractor {
|
||||
let match = regex.matches(
|
||||
in: string,
|
||||
options: [],
|
||||
range: NSMakeRange(0, string.count)
|
||||
range: NSRange(location: 0, length: string.count)
|
||||
).first
|
||||
|
||||
guard let match = match else {
|
||||
|
@ -35,7 +35,7 @@ class ActivePhpInstallation {
|
||||
getVersion()
|
||||
|
||||
// If an error occurred, exit early
|
||||
if (version.error) {
|
||||
if version.error {
|
||||
limits = Limits()
|
||||
extensions = []
|
||||
return
|
||||
@ -60,9 +60,9 @@ class ActivePhpInstallation {
|
||||
|
||||
// See if any extensions are present in said .ini files
|
||||
paths.forEach { (iniFilePath) in
|
||||
let exts = PhpExtension.load(from: URL(fileURLWithPath: iniFilePath))
|
||||
if exts.count > 0 {
|
||||
extensions.append(contentsOf: exts)
|
||||
let loadedExtensions = PhpExtension.load(from: URL(fileURLWithPath: iniFilePath))
|
||||
if loadedExtensions.isEmpty {
|
||||
extensions.append(contentsOf: loadedExtensions)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -71,12 +71,12 @@ class ActivePhpInstallation {
|
||||
When the app tries to retrieve the version, the installation is considered broken if the output is nothing,
|
||||
_or_ if the output contains the word "Warning" or "Error". In normal situations this should not be the case.
|
||||
*/
|
||||
private func getVersion() -> Void {
|
||||
private func getVersion() {
|
||||
self.version = Version()
|
||||
|
||||
let version = Command.execute(path: Paths.phpConfig, arguments: ["--version"], trimNewlines: true)
|
||||
|
||||
if (version == "" || version.contains("Warning") || version.contains("Error")) {
|
||||
if version == "" || version.contains("Warning") || version.contains("Error") {
|
||||
self.version.short = "💩 BROKEN"
|
||||
self.version.long = ""
|
||||
self.version.error = true
|
||||
@ -112,13 +112,13 @@ class ActivePhpInstallation {
|
||||
let value = Command.execute(path: Paths.php, arguments: ["-r", "echo ini_get('\(key)');"])
|
||||
|
||||
// Check if the value is unlimited
|
||||
if (value == "-1") {
|
||||
if value == "-1" {
|
||||
return "∞"
|
||||
}
|
||||
|
||||
// Check if the syntax is valid otherwise
|
||||
let regex = try! NSRegularExpression(pattern: #"^([0-9]*)(K|M|G|)$"#, options: [])
|
||||
let match = regex.matches(in: value, options: [], range: NSMakeRange(0, value.count)).first
|
||||
let match = regex.matches(in: value, options: [], range: NSRange(location: 0, length: value.count)).first
|
||||
return (match == nil) ? "⚠️" : "\(value)B"
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ class Xdebug {
|
||||
"debug",
|
||||
"gcstats",
|
||||
"profile",
|
||||
"trace",
|
||||
"trace"
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ class PhpEnv {
|
||||
init() {
|
||||
self.currentInstall = ActivePhpInstallation()
|
||||
|
||||
let brewPhpAlias = Shell.pipe("\(Paths.brew) info php --json");
|
||||
let brewPhpAlias = Shell.pipe("\(Paths.brew) info php --json")
|
||||
|
||||
self.homebrewPackage = try! JSONDecoder().decode(
|
||||
[HomebrewPackage].self,
|
||||
@ -76,15 +76,14 @@ class PhpEnv {
|
||||
return InternalSwitcher()
|
||||
}
|
||||
|
||||
public static func detectPhpVersions() -> Void {
|
||||
public static func detectPhpVersions() {
|
||||
_ = Self.shared.detectPhpVersions()
|
||||
}
|
||||
|
||||
/**
|
||||
Detects which versions of PHP are installed.
|
||||
*/
|
||||
public func detectPhpVersions() -> [String]
|
||||
{
|
||||
public func detectPhpVersions() -> [String] {
|
||||
let files = Shell.pipe("ls \(Paths.optPath) | grep php@")
|
||||
|
||||
var versionsOnly = extractPhpVersions(from: files.components(separatedBy: "\n"))
|
||||
@ -95,7 +94,7 @@ class PhpEnv {
|
||||
let phpAlias = homebrewPackage.version
|
||||
|
||||
// Avoid inserting a duplicate
|
||||
if (!versionsOnly.contains(phpAlias) && Filesystem.fileExists("\(Paths.optPath)/php/bin/php")) {
|
||||
if !versionsOnly.contains(phpAlias) && Filesystem.fileExists("\(Paths.optPath)/php/bin/php") {
|
||||
versionsOnly.append(phpAlias)
|
||||
}
|
||||
|
||||
@ -126,7 +125,7 @@ class PhpEnv {
|
||||
checkBinaries: Bool = true,
|
||||
generateHelpers: Bool = true
|
||||
) -> [String] {
|
||||
var output : [String] = []
|
||||
var output: [String] = []
|
||||
|
||||
var supported = Constants.SupportedPhpVersions
|
||||
|
||||
@ -144,8 +143,7 @@ class PhpEnv {
|
||||
// is supported and where the binary exists (avoids broken installs)
|
||||
if !output.contains(version)
|
||||
&& supported.contains(version)
|
||||
&& (checkBinaries ? Filesystem.fileExists("\(Paths.optPath)/php@\(version)/bin/php") : true)
|
||||
{
|
||||
&& (checkBinaries ? Filesystem.fileExists("\(Paths.optPath)/php@\(version)/bin/php") : true) {
|
||||
output.append(version)
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,8 @@ class PhpHelper {
|
||||
if FileManager.default.fileExists(atPath: destination) {
|
||||
let contents = try String(contentsOfFile: destination)
|
||||
if !contents.contains(keyPhrase) {
|
||||
Log.info("The file at '\(destination)' already exists and was not generated by PHP Monitor (or is unreadable). Not updating this file.")
|
||||
Log.info("The file at '\(destination)' already exists and was not generated by PHP Monitor "
|
||||
+ "(or is unreadable). Not updating this file.")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +134,12 @@ public struct PhpVersionNumber: Equatable {
|
||||
|
||||
public static func make(from versionString: String, type: MatchType = .versionOnly) -> Self? {
|
||||
let regex = try! NSRegularExpression(pattern: type.rawValue, options: [])
|
||||
let match = regex.matches(in: versionString, options: [], range: NSMakeRange(0, versionString.count)).first
|
||||
|
||||
let match = regex.matches(
|
||||
in: versionString,
|
||||
options: [],
|
||||
range: NSRange(location: 0, length: versionString.count)
|
||||
).first
|
||||
|
||||
if match != nil {
|
||||
let major = Int(
|
||||
@ -143,7 +148,7 @@ public struct PhpVersionNumber: Equatable {
|
||||
let minor = Int(
|
||||
versionString[Range(match!.range(withName: "minor"), in: versionString)!]
|
||||
)!
|
||||
var patch: Int? = nil
|
||||
var patch: Int?
|
||||
if let minorRange = Range(match!.range(withName: "patch"), in: versionString) {
|
||||
patch = Int(versionString[minorRange])
|
||||
}
|
||||
|
@ -23,7 +23,8 @@ class PhpExtension {
|
||||
/// The original string that was used to determine this extension is active.
|
||||
var line: String
|
||||
|
||||
/// The name of the extension. This is always identical to the name found in the original string. If you want to display this name, capitalize this.
|
||||
/// The name of the extension. This is always identical to the name found in the original string.
|
||||
/// If you want to display this name, capitalize this.
|
||||
var name: String
|
||||
|
||||
/// Whether the extension has been enabled.
|
||||
@ -34,6 +35,7 @@ class PhpExtension {
|
||||
return String(file.split(separator: "/").last ?? "php.ini")
|
||||
}
|
||||
|
||||
// swiftlint:disable line_length
|
||||
/**
|
||||
This regular expression will allow us to identify lines which activate an extension.
|
||||
|
||||
@ -47,13 +49,14 @@ class PhpExtension {
|
||||
- Note: Extensions that are disabled in a different way will not be detected. This is intentional.
|
||||
*/
|
||||
static let extensionRegex = #"^(extension|zend_extension|;(\s?)extension|;(\s?)zend_extension)(\s?)(=)(\s?)(?<name>["]?(?:\/?.\/?)+(?:\.so)"?)$"#
|
||||
// swiftlint:enable line_length
|
||||
|
||||
/**
|
||||
When registering an extension, we do that based on the line found inside the .ini file.
|
||||
*/
|
||||
init(_ line: String, file: String) {
|
||||
let regex = try! NSRegularExpression(pattern: Self.extensionRegex, options: [])
|
||||
let match = regex.matches(in: line, options: [], range: NSMakeRange(0, line.count)).first
|
||||
let match = regex.matches(in: line, options: [], range: NSRange(location: 0, length: line.count)).first
|
||||
let range = Range(match!.range(withName: "name"), in: line)!
|
||||
|
||||
self.line = line
|
||||
@ -69,7 +72,8 @@ class PhpExtension {
|
||||
}
|
||||
|
||||
/**
|
||||
This simply toggles the extension in the .ini file. You may need to restart the other services in order for this change to apply.
|
||||
This simply toggles the extension in the .ini file.
|
||||
You may need to restart the other services in order for this change to apply.
|
||||
*/
|
||||
func toggle() {
|
||||
let newLine = enabled
|
||||
@ -91,7 +95,7 @@ class PhpExtension {
|
||||
static func load(from path: URL) -> [PhpExtension] {
|
||||
let file = try? String(contentsOf: path, encoding: .utf8)
|
||||
|
||||
if (file == nil) {
|
||||
if file == nil {
|
||||
Log.err("There was an issue reading the file. Assuming no extensions were found.")
|
||||
return []
|
||||
}
|
||||
|
@ -20,8 +20,7 @@ class InternalSwitcher: PhpSwitcher {
|
||||
the version that is switched to may or may not be identical to `php`
|
||||
(without @version).
|
||||
*/
|
||||
func performSwitch(to version: String, completion: @escaping () -> Void)
|
||||
{
|
||||
func performSwitch(to version: String, completion: @escaping () -> Void) {
|
||||
Log.info("Switching to \(version), unlinking all versions...")
|
||||
|
||||
let isolated = Valet.shared.sites.filter { site in
|
||||
@ -32,7 +31,7 @@ class InternalSwitcher: PhpSwitcher {
|
||||
|
||||
var versions: Set<String> = [version]
|
||||
|
||||
if (Valet.enabled(feature: .isolatedSites)) {
|
||||
if Valet.enabled(feature: .isolatedSites) {
|
||||
versions = versions.union(isolated)
|
||||
}
|
||||
|
||||
@ -71,8 +70,9 @@ class InternalSwitcher: PhpSwitcher {
|
||||
let existing = URL(string: "file://\(Paths.etcPath)/php/\(version)/php-fpm.d/www.conf")!
|
||||
let new = URL(string: "file://\(Paths.etcPath)/php/\(version)/php-fpm.d/www.conf.disabled-by-phpmon")!
|
||||
do {
|
||||
if (FileManager.default.fileExists(atPath: new.path)) {
|
||||
Log.info("A moved `www.conf.disabled-by-phpmon` file was found for PHP \(version), cleaning up so the newer `www.conf` can be moved again.")
|
||||
if FileManager.default.fileExists(atPath: new.path) {
|
||||
Log.info("A moved `www.conf.disabled-by-phpmon` file was found for PHP \(version), "
|
||||
+ "cleaning up so the newer `www.conf` can be moved again.")
|
||||
try FileManager.default.removeItem(at: new)
|
||||
}
|
||||
try FileManager.default.moveItem(at: existing, to: new)
|
||||
@ -93,7 +93,7 @@ class InternalSwitcher: PhpSwitcher {
|
||||
private func startPhpVersion(_ version: String, primary: Bool) {
|
||||
let formula = (version == PhpEnv.brewPhpVersion) ? "php" : "php@\(version)"
|
||||
|
||||
if (primary) {
|
||||
if primary {
|
||||
Log.info("\(formula) is the primary formula, linking and starting services...")
|
||||
brew("link \(formula) --overwrite --force")
|
||||
} else {
|
||||
|
@ -38,7 +38,7 @@ extension App {
|
||||
If there are no windows open, the app will be an accessory (toolbar) app.
|
||||
*/
|
||||
public func updateActivationPolicy() {
|
||||
NSApp.setActivationPolicy(openWindows.count > 0 ? .regular : .accessory)
|
||||
NSApp.setActivationPolicy(!openWindows.isEmpty ? .regular : .accessory)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -41,10 +41,10 @@ class App {
|
||||
var preferences: [PreferenceName: Bool]!
|
||||
|
||||
/** The window controller of the currently active preferences window. */
|
||||
var preferencesWindowController: PrefsWC? = nil
|
||||
var preferencesWindowController: PrefsWC?
|
||||
|
||||
/** The window controller of the currently active site list window. */
|
||||
var domainListWindowController: DomainListWC? = nil
|
||||
var domainListWindowController: DomainListWC?
|
||||
|
||||
/** List of detected (installed) applications that PHP Monitor can work with. */
|
||||
var detectedApplications: [Application] = []
|
||||
@ -57,7 +57,7 @@ class App {
|
||||
/**
|
||||
The shortcut the user has requested.
|
||||
*/
|
||||
var shortcutHotkey: HotKey? = nil {
|
||||
var shortcutHotkey: HotKey? {
|
||||
didSet {
|
||||
setupGlobalHotkeyListener()
|
||||
}
|
||||
|
@ -44,4 +44,3 @@ extension AppDelegate {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ class InterApp {
|
||||
subtitle: "PHP Monitor can't switch to PHP \(version), as it may not be installed or available."
|
||||
).withPrimary(text: "OK").show()
|
||||
}
|
||||
}),
|
||||
})
|
||||
]}
|
||||
|
||||
}
|
||||
|
@ -17,8 +17,7 @@ class Startup {
|
||||
If this method returns false, there was a failed check and an alert was displayed.
|
||||
If this method returns true, then all checks succeeded and the app can continue.
|
||||
*/
|
||||
func checkEnvironment() async -> Bool
|
||||
{
|
||||
func checkEnvironment() async -> Bool {
|
||||
// Do the important system setup checks
|
||||
Log.info("[ARCH] The user is running PHP Monitor with the architecture: \(App.architecture)")
|
||||
|
||||
|
@ -145,7 +145,7 @@ class AddProxyVC: NSViewController, NSTextFieldDelegate {
|
||||
Valet.shared.config.tld
|
||||
)
|
||||
|
||||
if (inputProxySubject.stringValue.isEmpty || inputDomainName.stringValue.isEmpty) {
|
||||
if inputProxySubject.stringValue.isEmpty || inputDomainName.stringValue.isEmpty {
|
||||
previewText.stringValue = "domain_list.add.empty_fields".localized
|
||||
return
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ class AddSiteVC: NSViewController, NSTextFieldDelegate {
|
||||
Valet.shared.config.tld
|
||||
)
|
||||
|
||||
if (inputDomainName.stringValue.isEmpty) {
|
||||
if inputDomainName.stringValue.isEmpty {
|
||||
previewText.stringValue = "domain_list.add.empty_fields".localized
|
||||
return
|
||||
}
|
||||
|
@ -9,8 +9,7 @@
|
||||
import Cocoa
|
||||
import AppKit
|
||||
|
||||
class DomainListKindCell: NSTableCellView, DomainListCellProtocol
|
||||
{
|
||||
class DomainListKindCell: NSTableCellView, DomainListCellProtocol {
|
||||
static let reusableName = "domainListKindCell"
|
||||
|
||||
@IBOutlet weak var imageViewType: NSImageView!
|
||||
|
@ -9,8 +9,7 @@
|
||||
import Cocoa
|
||||
import AppKit
|
||||
|
||||
class DomainListNameCell: NSTableCellView, DomainListCellProtocol
|
||||
{
|
||||
class DomainListNameCell: NSTableCellView, DomainListCellProtocol {
|
||||
static let reusableName = "domainListNameCell"
|
||||
|
||||
@IBOutlet weak var labelSiteName: NSTextField!
|
||||
|
@ -9,11 +9,10 @@
|
||||
import Cocoa
|
||||
import AppKit
|
||||
|
||||
class DomainListPhpCell: NSTableCellView, DomainListCellProtocol
|
||||
{
|
||||
class DomainListPhpCell: NSTableCellView, DomainListCellProtocol {
|
||||
static let reusableName = "domainListPhpCell"
|
||||
|
||||
var site: ValetSite? = nil
|
||||
var site: ValetSite?
|
||||
|
||||
@IBOutlet weak var buttonPhpVersion: NSButton!
|
||||
@IBOutlet weak var imageViewPhpVersionOK: NSImageView!
|
||||
@ -53,7 +52,7 @@ class DomainListPhpCell: NSTableCellView, DomainListCellProtocol
|
||||
|
||||
var information = ""
|
||||
|
||||
if (self.site?.isolatedPhpVersion != nil) {
|
||||
if self.site?.isolatedPhpVersion != nil {
|
||||
information += "alert.composer_php_isolated.desc".localized(
|
||||
self.site!.isolatedPhpVersion!.versionNumber.homebrewVersion,
|
||||
PhpEnv.phpInstall.version.short
|
||||
|
@ -9,8 +9,7 @@
|
||||
import Cocoa
|
||||
import AppKit
|
||||
|
||||
class DomainListTLSCell: NSTableCellView, DomainListCellProtocol
|
||||
{
|
||||
class DomainListTLSCell: NSTableCellView, DomainListCellProtocol {
|
||||
static let reusableName = "domainListTLSCell"
|
||||
|
||||
@IBOutlet weak var imageViewLock: NSImageView!
|
||||
|
@ -9,8 +9,7 @@
|
||||
import Cocoa
|
||||
import AppKit
|
||||
|
||||
class DomainListTypeCell: NSTableCellView, DomainListCellProtocol
|
||||
{
|
||||
class DomainListTypeCell: NSTableCellView, DomainListCellProtocol {
|
||||
static let reusableName = "domainListTypeCell"
|
||||
|
||||
@IBOutlet weak var labelDriver: NSTextField!
|
||||
|
@ -68,11 +68,11 @@ extension DomainListVC {
|
||||
}
|
||||
|
||||
private func addDetectedApps(to menu: NSMenu) {
|
||||
if (applications.count > 0) {
|
||||
if !applications.isEmpty {
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
menu.addItem(withTitle: "domain_list.detected_apps".localized, action: nil, keyEquivalent: "")
|
||||
|
||||
for (_, editor) in applications.enumerated() {
|
||||
for editor in applications {
|
||||
let editorMenuItem = EditorMenuItem(
|
||||
title: "Open with \(editor.name)",
|
||||
action: #selector(self.openWithEditor(sender:)),
|
||||
@ -85,7 +85,7 @@ extension DomainListVC {
|
||||
}
|
||||
|
||||
private func addUnlink(to menu: NSMenu, with site: ValetSite) {
|
||||
if (site.aliasPath != nil) {
|
||||
if site.aliasPath != nil {
|
||||
menu.addItem(
|
||||
withTitle: "domain_list.unlink".localized,
|
||||
action: #selector(self.unlinkSite),
|
||||
@ -103,11 +103,15 @@ extension DomainListVC {
|
||||
private func addIsolate(to menu: NSMenu, with site: ValetSite) {
|
||||
if site.isolatedPhpVersion == nil {
|
||||
// ISOLATION POSSIBLE
|
||||
let isolationMenuItem = NSMenuItem(title:"domain_list.isolate".localized, action: nil, keyEquivalent: "")
|
||||
let isolationMenuItem = NSMenuItem(title: "domain_list.isolate".localized, action: nil, keyEquivalent: "")
|
||||
let submenu = NSMenu()
|
||||
submenu.addItem(withTitle: "Choose a PHP version", action: nil, keyEquivalent: "")
|
||||
for version in PhpEnv.shared.availablePhpVersions.reversed() {
|
||||
let item = PhpMenuItem(title: "Always use PHP \(version)", action: #selector(self.isolateSite), keyEquivalent: "")
|
||||
let item = PhpMenuItem(
|
||||
title: "Always use PHP \(version)",
|
||||
action: #selector(self.isolateSite),
|
||||
keyEquivalent: ""
|
||||
)
|
||||
item.version = version
|
||||
submenu.addItem(item)
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ class DomainListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource
|
||||
}
|
||||
|
||||
/// The last sort descriptor used.
|
||||
var sortDescriptor: NSSortDescriptor? = nil
|
||||
var sortDescriptor: NSSortDescriptor?
|
||||
|
||||
/// String that was last searched for. Empty by default.
|
||||
var lastSearchedFor = ""
|
||||
@ -55,12 +55,12 @@ class DomainListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource
|
||||
return domains[tableView.selectedRow]
|
||||
}
|
||||
|
||||
var timer: Timer? = nil
|
||||
var timer: Timer?
|
||||
|
||||
// MARK: - Display
|
||||
|
||||
public static func create(delegate: NSWindowDelegate?) {
|
||||
let storyboard = NSStoryboard(name: "Main" , bundle : nil)
|
||||
let storyboard = NSStoryboard(name: "Main", bundle: nil)
|
||||
|
||||
let windowController = storyboard.instantiateController(
|
||||
withIdentifier: "domainListWindow"
|
||||
@ -80,7 +80,7 @@ class DomainListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource
|
||||
}
|
||||
|
||||
public static func show(delegate: NSWindowDelegate? = nil) {
|
||||
if (App.shared.domainListWindowController == nil) {
|
||||
if App.shared.domainListWindowController == nil {
|
||||
Self.create(delegate: delegate)
|
||||
}
|
||||
|
||||
@ -137,8 +137,7 @@ class DomainListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource
|
||||
- Parameter execute: Callback of the work that needs to happen.
|
||||
- Parameter completion: Callback that is fired when the work is done.
|
||||
*/
|
||||
internal func waitAndExecute(_ execute: @escaping () -> Void, completion: @escaping () -> Void = {})
|
||||
{
|
||||
internal func waitAndExecute(_ execute: @escaping () -> Void, completion: @escaping () -> Void = {}) {
|
||||
setUIBusy()
|
||||
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
|
||||
execute()
|
||||
@ -168,17 +167,12 @@ class DomainListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource
|
||||
var sorted = self.domains
|
||||
|
||||
switch descriptor.key {
|
||||
case "Secure":
|
||||
sorted = self.domains.sorted { $0.getListableSecured() && !$1.getListableSecured() }; break
|
||||
case "Domain":
|
||||
sorted = self.domains.sorted { $0.getListableAbsolutePath() < $1.getListableAbsolutePath() }; break
|
||||
case "PHP":
|
||||
sorted = self.domains.sorted { $0.getListablePhpVersion() < $1.getListablePhpVersion() }; break
|
||||
case "Kind":
|
||||
sorted = self.domains.sorted { $0.getListableKind() < $1.getListableKind() }; break
|
||||
case "Type":
|
||||
sorted = self.domains.sorted { $0.getListableType() < $1.getListableType() }; break
|
||||
default: break;
|
||||
case "Secure": sorted = self.domains.sorted { $0.getListableSecured() && !$1.getListableSecured() }
|
||||
case "Domain": sorted = self.domains.sorted { $0.getListableAbsolutePath() < $1.getListableAbsolutePath() }
|
||||
case "PHP": sorted = self.domains.sorted { $0.getListablePhpVersion() < $1.getListablePhpVersion() }
|
||||
case "Kind": sorted = self.domains.sorted { $0.getListableKind() < $1.getListableKind() }
|
||||
case "Type": sorted = self.domains.sorted { $0.getListableType() < $1.getListableType() }
|
||||
default: break
|
||||
}
|
||||
|
||||
self.domains = descriptor.ascending ? sorted.reversed() : sorted
|
||||
@ -199,7 +193,7 @@ class DomainListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource
|
||||
DispatchQueue.main.async {
|
||||
self.tableView.selectRowIndexes([site.offset], byExtendingSelection: false)
|
||||
self.tableView.scrollRowToVisible(site.offset)
|
||||
if (secure && !site.element.getListableSecured()) {
|
||||
if secure && !site.element.getListableSecured() {
|
||||
self.toggleSecure()
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ class DomainListWC: PMWindowController, NSSearchFieldDelegate, NSToolbarDelegate
|
||||
// MARK: - Add a new site
|
||||
|
||||
func showSelectionWindow() {
|
||||
let storyboard = NSStoryboard(name: "Main", bundle : nil)
|
||||
let storyboard = NSStoryboard(name: "Main", bundle: nil)
|
||||
|
||||
let windowController = storyboard.instantiateController(
|
||||
withIdentifier: "showSelectionWindow"
|
||||
@ -95,7 +95,7 @@ class DomainListWC: PMWindowController, NSSearchFieldDelegate, NSToolbarDelegate
|
||||
dialog.canChooseFiles = false
|
||||
dialog.beginSheetModal(for: self.window!) { response in
|
||||
let result = dialog.url
|
||||
if (result != nil && response == .OK) {
|
||||
if result != nil && response == .OK {
|
||||
let path: String = result!.path
|
||||
self.showLinkPopup(path)
|
||||
}
|
||||
@ -103,7 +103,7 @@ class DomainListWC: PMWindowController, NSSearchFieldDelegate, NSToolbarDelegate
|
||||
}
|
||||
|
||||
private func showLinkPopup(_ folder: String) {
|
||||
let storyboard = NSStoryboard(name: "Main", bundle : nil)
|
||||
let storyboard = NSStoryboard(name: "Main", bundle: nil)
|
||||
|
||||
let windowController = storyboard.instantiateController(
|
||||
withIdentifier: "addSiteWindow"
|
||||
@ -118,7 +118,7 @@ class DomainListWC: PMWindowController, NSSearchFieldDelegate, NSToolbarDelegate
|
||||
}
|
||||
|
||||
private func showProxyPopup() {
|
||||
let storyboard = NSStoryboard(name: "Main", bundle : nil)
|
||||
let storyboard = NSStoryboard(name: "Main", bundle: nil)
|
||||
|
||||
let windowController = storyboard.instantiateController(
|
||||
withIdentifier: "addProxyWindow"
|
||||
|
@ -16,8 +16,8 @@ struct ComposerJson: Decodable {
|
||||
|
||||
// MARK: - JSON structure
|
||||
|
||||
let dependencies: Dictionary<String, String>?
|
||||
let devDependencies: Dictionary<String, String>?
|
||||
let dependencies: [String: String]?
|
||||
let devDependencies: [String: String]?
|
||||
let configuration: Config?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
@ -40,8 +40,7 @@ struct ComposerJson: Decodable {
|
||||
Checks what the PHP version constraint is.
|
||||
Returns a tuple (constraint, location of constraint).
|
||||
*/
|
||||
public func getPhpVersion() -> (String, ValetSite.VersionSource)
|
||||
{
|
||||
public func getPhpVersion() -> (String, ValetSite.VersionSource) {
|
||||
// Check if in platform
|
||||
if configuration?.platform?.php != nil {
|
||||
return (configuration!.platform!.php!, .platform)
|
||||
@ -76,5 +75,3 @@ struct ComposerJson: Decodable {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,10 +10,10 @@ import Foundation
|
||||
|
||||
class ComposerWindow {
|
||||
|
||||
private var menu: MainMenu? = nil
|
||||
private var menu: MainMenu?
|
||||
private var shouldNotify: Bool! = nil
|
||||
private var completion: ((Bool) -> Void)! = nil
|
||||
private var window: ProgressWindowController? = nil
|
||||
private var window: ProgressWindowController?
|
||||
|
||||
/**
|
||||
Updates the global dependencies and runs the completion callback when done.
|
||||
@ -80,7 +80,7 @@ class ComposerWindow {
|
||||
// Closing the window should happen after a slight delay
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [self] in
|
||||
window?.close()
|
||||
if (shouldNotify) {
|
||||
if shouldNotify {
|
||||
LocalNotification.send(
|
||||
title: "alert.composer_success.title".localized,
|
||||
subtitle: "alert.composer_success.info".localized
|
||||
|
@ -17,7 +17,7 @@ struct PhpFrameworks {
|
||||
public static let DependencyList = [
|
||||
|
||||
// COMMON FRAMEWORKS
|
||||
"laravel/framework" : "Laravel",
|
||||
"laravel/framework": "Laravel",
|
||||
"symfony/symfony": "Symfony",
|
||||
"laravel/lumen": "Lumen",
|
||||
|
||||
@ -37,7 +37,7 @@ struct PhpFrameworks {
|
||||
"johnpbloch/wordpress-core": "WordPress",
|
||||
"zendframework/zendframework": "Zend",
|
||||
"zendframework/zend-mvc": "Zend",
|
||||
"typo3/cms-core": "Typo3",
|
||||
"typo3/cms-core": "Typo3"
|
||||
|
||||
// TODO (6.0): Handle these in v6.0
|
||||
// "magento/*": "Magento",
|
||||
@ -61,7 +61,7 @@ struct PhpFrameworks {
|
||||
],
|
||||
"Typo3": [
|
||||
"/typo3",
|
||||
"/public/typo3",
|
||||
"/public/typo3"
|
||||
]
|
||||
]
|
||||
|
||||
|
@ -17,8 +17,7 @@ class HomebrewDiagnostics {
|
||||
|
||||
This check only needs to be performed if the `shivammathur/php` tap is active.
|
||||
*/
|
||||
public static func hasAliasConflict() -> Bool
|
||||
{
|
||||
public static func hasAliasConflict() -> Bool {
|
||||
let tapAlias = Shell.pipe("\(Paths.brew) info shivammathur/php/php --json")
|
||||
|
||||
if tapAlias.contains("brew tap shivammathur/php") || tapAlias.contains("Error") {
|
||||
@ -34,7 +33,8 @@ class HomebrewDiagnostics {
|
||||
).first!
|
||||
|
||||
if tapPhp.version != PhpEnv.brewPhpVersion {
|
||||
Log.warn("The `php` formula alias seems to be the different between the tap and core. This could be a problem!")
|
||||
Log.warn("The `php` formula alias seems to be the different between the tap and core. "
|
||||
+ "This could be a problem!")
|
||||
Log.info("Determining whether both of these versions are installed...")
|
||||
|
||||
let bothInstalled = PhpEnv.shared.availablePhpVersions.contains(tapPhp.version)
|
||||
@ -55,12 +55,23 @@ class HomebrewDiagnostics {
|
||||
}
|
||||
}
|
||||
|
||||
public static func presentAlertAboutConflict() {
|
||||
DispatchQueue.main.async {
|
||||
BetterAlert()
|
||||
.withInformation(
|
||||
title: "alert.php_alias_conflict.title".localized,
|
||||
subtitle: "alert.php_alias_conflict.info".localized
|
||||
)
|
||||
.withPrimary(text: "OK")
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
In order to see if we support the --json syntax, we'll query nginx.
|
||||
If the JSON response cannot be parsed, Homebrew is probably out of date.
|
||||
*/
|
||||
public static func cannotLoadService(_ name: String = "nginx") -> Bool
|
||||
{
|
||||
public static func cannotLoadService(_ name: String = "nginx") -> Bool {
|
||||
let serviceInfo = try? JSONDecoder().decode(
|
||||
[HomebrewService].self,
|
||||
from: Shell.pipe(
|
||||
|
@ -44,7 +44,7 @@ class NginxConfiguration {
|
||||
options: []
|
||||
)
|
||||
|
||||
guard let match = regex.firstMatch(in: contents, range: NSMakeRange(0, contents.count))
|
||||
guard let match = regex.firstMatch(in: contents, range: NSRange(location: 0, length: contents.count))
|
||||
else { return nil }
|
||||
|
||||
return contents[Range(match.range(withName: "proxy"), in: contents)!]
|
||||
@ -60,7 +60,7 @@ class NginxConfiguration {
|
||||
options: []
|
||||
)
|
||||
|
||||
guard let match = regex.firstMatch(in: contents, range: NSMakeRange(0, contents.count))
|
||||
guard let match = regex.firstMatch(in: contents, range: NSRange(location: 0, length: contents.count))
|
||||
else { return nil }
|
||||
|
||||
let major: String = contents[Range(match.range(withName: "major"), in: contents)!],
|
||||
|
@ -8,10 +8,8 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
class ValetProxyScanner: ProxyScanner
|
||||
{
|
||||
func resolveProxies(directoryPath: String) -> [ValetProxy]
|
||||
{
|
||||
class ValetProxyScanner: ProxyScanner {
|
||||
func resolveProxies(directoryPath: String) -> [ValetProxy] {
|
||||
return try! FileManager
|
||||
.default
|
||||
.contentsOfDirectory(atPath: directoryPath)
|
||||
|
@ -8,8 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
class ValetProxy: DomainListable
|
||||
{
|
||||
class ValetProxy: DomainListable {
|
||||
var domain: String
|
||||
var tld: String
|
||||
var target: String
|
||||
|
@ -6,14 +6,16 @@
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
class FakeSiteScanner: SiteScanner
|
||||
{
|
||||
class FakeSiteScanner: SiteScanner {
|
||||
let fakes = [
|
||||
ValetSite(fakeWithName: "laravel", tld: "test", secure: true, path: "~/Code/laravel/framework", linked: true),
|
||||
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, constraint: "8.0"),
|
||||
ValetSite(fakeWithName: "tailwind", tld: "test", secure: true,
|
||||
path: "~/Code/tailwind/site", linked: true, constraint: "8.0"),
|
||||
|
||||
ValetSite(fakeWithName: "forge", tld: "test", secure: true, path: "~/Code/laravel/forge", linked: true),
|
||||
ValetSite(fakeWithName: "forge", tld: "test", secure: true,
|
||||
path: "~/Code/laravel/forge", linked: true),
|
||||
|
||||
ValetSite(fakeWithName: "concord", tld: "test", secure: false,
|
||||
path: "~/Code/concord", linked: true, driver: "Laravel (^8.0)", constraint: "^7.4", isolated: "7.4"),
|
||||
|
@ -8,8 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol SiteScanner
|
||||
{
|
||||
protocol SiteScanner {
|
||||
func resolveSiteCount(paths: [String]) -> Int
|
||||
|
||||
func resolveSitesFrom(paths: [String]) -> [ValetSite]
|
||||
|
@ -8,8 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
class ValetSiteScanner: SiteScanner
|
||||
{
|
||||
class ValetSiteScanner: SiteScanner {
|
||||
func resolveSiteCount(paths: [String]) -> Int {
|
||||
return paths.map { path in
|
||||
|
||||
@ -18,7 +17,7 @@ class ValetSiteScanner: SiteScanner
|
||||
|
||||
return entries
|
||||
.map { self.isSite($0, forPath: path) }
|
||||
.filter{ $0 == true}
|
||||
.filter { $0 == true}
|
||||
.count
|
||||
|
||||
}.reduce(0, +)
|
||||
|
@ -26,9 +26,9 @@ extension ValetSite {
|
||||
|
||||
self.composerPhpCompatibleWithLinked = self.composerPhp.split(separator: "|")
|
||||
.map { string in
|
||||
return PhpVersionNumberCollection.make(from: [PhpEnv.phpInstall.version.long])
|
||||
return !PhpVersionNumberCollection.make(from: [PhpEnv.phpInstall.version.long])
|
||||
.matching(constraint: string.trimmingCharacters(in: .whitespacesAndNewlines))
|
||||
.count > 0
|
||||
.isEmpty
|
||||
}.contains(true)
|
||||
|
||||
self.driver = driver
|
||||
|
@ -36,7 +36,7 @@ class ValetSite: DomainListable {
|
||||
var secured: Bool!
|
||||
|
||||
/// What driver is currently in use. If not detected, defaults to nil.
|
||||
var driver: String? = nil
|
||||
var driver: String?
|
||||
|
||||
/// Whether the driver was determined by checking the Composer file.
|
||||
var driverDeterminedByComposer: Bool = false
|
||||
@ -60,10 +60,10 @@ class ValetSite: DomainListable {
|
||||
}
|
||||
|
||||
enum VersionSource: String {
|
||||
case unknown = "unknown"
|
||||
case require = "require"
|
||||
case platform = "platform"
|
||||
case valetphprc = "valetphprc"
|
||||
case unknown
|
||||
case require
|
||||
case platform
|
||||
case valetphprc
|
||||
}
|
||||
|
||||
init(
|
||||
@ -103,8 +103,9 @@ class ValetSite: DomainListable {
|
||||
*/
|
||||
public func determineIsolated() {
|
||||
if let version = ValetSite.isolatedVersion("~/.config/valet/Nginx/\(self.name).\(self.tld)") {
|
||||
if (!PhpEnv.shared.cachedPhpInstallations.keys.contains(version)) {
|
||||
Log.err("The PHP version \(version) is isolated for the site \(self.name) but that PHP version is unavailable.")
|
||||
if !PhpEnv.shared.cachedPhpInstallations.keys.contains(version) {
|
||||
Log.err("The PHP version \(version) is isolated for the site \(self.name) "
|
||||
+ "but that PHP version is unavailable.")
|
||||
return
|
||||
}
|
||||
self.isolatedPhpVersion = PhpEnv.shared.cachedPhpInstallations[version]
|
||||
@ -144,9 +145,9 @@ class ValetSite: DomainListable {
|
||||
// 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])
|
||||
return !PhpVersionNumberCollection.make(from: [PhpEnv.phpInstall.version.long])
|
||||
.matching(constraint: string.trimmingCharacters(in: .whitespacesAndNewlines))
|
||||
.count > 0
|
||||
.isEmpty
|
||||
}.contains(true)
|
||||
}
|
||||
|
||||
|
@ -67,10 +67,28 @@ class Valet {
|
||||
return self.shared.features.contains(feature)
|
||||
}
|
||||
|
||||
/**
|
||||
Retrieve a list of all domains, including sites & proxies.
|
||||
*/
|
||||
public static func getDomainListable() -> [DomainListable] {
|
||||
return self.shared.sites + self.shared.proxies
|
||||
}
|
||||
|
||||
/**
|
||||
Notify the user about a non-default TLD being set.
|
||||
*/
|
||||
public static func notifyAboutUnsupportedTLD() {
|
||||
if Valet.shared.config.tld != "test" {
|
||||
DispatchQueue.main.async {
|
||||
BetterAlert().withInformation(
|
||||
title: "alert.warnings.tld_issue.title".localized,
|
||||
subtitle: "alert.warnings.tld_issue.subtitle".localized,
|
||||
description: "alert.warnings.tld_issue.description".localized
|
||||
).withPrimary(text: "OK").show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
We don't want to load the initial config.json file as soon as the class is initialised.
|
||||
|
||||
@ -118,7 +136,7 @@ class Valet {
|
||||
public func reloadSites() {
|
||||
loadConfiguration()
|
||||
|
||||
if (isBusy) {
|
||||
if isBusy {
|
||||
return
|
||||
}
|
||||
|
||||
@ -132,7 +150,7 @@ class Valet {
|
||||
`enabled(feature)`, which contains information about the feature set of the version of Valet that is currently
|
||||
in use. This allows PHP Monitor to do different things when Valet 3.0 is enabled.
|
||||
*/
|
||||
public func evaluateFeatureSupport() -> Void {
|
||||
public func evaluateFeatureSupport() {
|
||||
let isOlderThanVersionThree = version.versionCompare("3.0") == .orderedAscending
|
||||
|
||||
if isOlderThanVersionThree {
|
||||
@ -148,7 +166,7 @@ class Valet {
|
||||
Should this procedure fail, the user will get an alert notifying them that the version of Valet they have
|
||||
installed is not recent enough.
|
||||
*/
|
||||
public func validateVersion() -> Void {
|
||||
public func validateVersion() {
|
||||
// 1. Evaluate feature support
|
||||
Valet.shared.evaluateFeatureSupport()
|
||||
|
||||
@ -160,13 +178,17 @@ class Valet {
|
||||
BetterAlert()
|
||||
.withInformation(
|
||||
title: "alert.min_valet_version.title".localized,
|
||||
subtitle:"alert.min_valet_version.info".localized(version!, Constants.MinimumRecommendedValetVersion)
|
||||
subtitle: "alert.min_valet_version.info".localized(
|
||||
version!,
|
||||
Constants.MinimumRecommendedValetVersion
|
||||
)
|
||||
)
|
||||
.withPrimary(text: "OK")
|
||||
.show()
|
||||
}
|
||||
} else {
|
||||
Log.info("Valet version \(version!) is recent enough, OK (recommended: \(Constants.MinimumRecommendedValetVersion))")
|
||||
Log.info("Valet version \(version!) is recent enough, OK " +
|
||||
"(recommended: \(Constants.MinimumRecommendedValetVersion))")
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,9 +242,11 @@ class Valet {
|
||||
/// The default site that is served if the domain is not found. Optional.
|
||||
let defaultSite: String?
|
||||
|
||||
// swiftlint:disable nesting
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case tld, paths, loopback, defaultSite = "default"
|
||||
}
|
||||
// swiftlint:enable nesting
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ extension MainMenu {
|
||||
}
|
||||
|
||||
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
|
||||
var error: Error? = nil
|
||||
var error: Error?
|
||||
|
||||
do { try execute() } catch let e { error = e }
|
||||
|
||||
@ -69,7 +69,7 @@ extension MainMenu {
|
||||
|
||||
if behaviours.contains(.updatesMenuBarContents) {
|
||||
updatePhpVersionInStatusBar()
|
||||
} else if behaviours.contains(.setsBusyUI) {
|
||||
} else if behaviours.contains(.setsBusyUI) {
|
||||
refreshIcon()
|
||||
}
|
||||
|
||||
|
@ -26,8 +26,7 @@ extension MainMenu {
|
||||
)
|
||||
.withPrimary(text: "alert.fix_my_valet.ok".localized)
|
||||
.withSecondary(text: "alert.fix_my_valet.cancel".localized)
|
||||
.didSelectPrimary()
|
||||
{
|
||||
.didSelectPrimary() {
|
||||
Log.info("The user has chosen to abort Fix My Valet")
|
||||
return
|
||||
}
|
||||
@ -76,7 +75,7 @@ extension MainMenu {
|
||||
MainMenu.shared.switchToPhpVersion(version)
|
||||
})
|
||||
.withSecondary(text: "alert.fix_my_valet_done.stay".localized(PhpEnv.brewPhpVersion))
|
||||
.withTertiary(text: "", action: { alert in
|
||||
.withTertiary(text: "", action: { _ in
|
||||
NSWorkspace.shared.open(Constants.Urls.FrequentlyAskedQuestions)
|
||||
})
|
||||
.show()
|
||||
|
@ -42,15 +42,7 @@ extension MainMenu {
|
||||
|
||||
// Check for an alias conflict
|
||||
if HomebrewDiagnostics.hasAliasConflict() {
|
||||
DispatchQueue.main.async {
|
||||
BetterAlert()
|
||||
.withInformation(
|
||||
title: "alert.php_alias_conflict.title".localized,
|
||||
subtitle: "alert.php_alias_conflict.info".localized
|
||||
)
|
||||
.withPrimary(text: "OK")
|
||||
.show()
|
||||
}
|
||||
HomebrewDiagnostics.presentAlertAboutConflict()
|
||||
}
|
||||
|
||||
updatePhpVersionInStatusBar()
|
||||
@ -60,22 +52,27 @@ extension MainMenu {
|
||||
let installation = PhpEnv.phpInstall
|
||||
installation.notifyAboutBrokenPhpFpm()
|
||||
|
||||
// Set up the config watchers on launch (these are automatically updated via delegate methods if the user switches)
|
||||
// Set up the config watchers on launch
|
||||
// (these are automatically updated via delegate methods if the user switches)
|
||||
Log.info("Setting up watchers...")
|
||||
App.shared.handlePhpConfigWatcher()
|
||||
|
||||
// Detect applications (preset + custom)
|
||||
Log.info("Detecting applications...")
|
||||
App.shared.detectedApplications = Application.detectPresetApplications()
|
||||
|
||||
let customApps = Preferences.custom.scanApps.map { appName in
|
||||
return Application(appName, .user_supplied)
|
||||
}.filter { app in
|
||||
return app.isInstalled()
|
||||
}
|
||||
|
||||
App.shared.detectedApplications.append(contentsOf: customApps)
|
||||
|
||||
let appNames = App.shared.detectedApplications.map { app in
|
||||
return app.name
|
||||
}
|
||||
|
||||
Log.info("Detected applications: \(appNames)")
|
||||
|
||||
// Load the global hotkey
|
||||
@ -85,15 +82,7 @@ extension MainMenu {
|
||||
Valet.shared.startPreloadingSites()
|
||||
|
||||
// A non-default TLD is not officially supported since Valet 3.2.x
|
||||
if (Valet.shared.config.tld != "test") {
|
||||
DispatchQueue.main.async {
|
||||
BetterAlert().withInformation(
|
||||
title: "alert.warnings.tld_issue.title".localized,
|
||||
subtitle: "alert.warnings.tld_issue.subtitle".localized,
|
||||
description: "alert.warnings.tld_issue.description".localized
|
||||
).withPrimary(text: "OK").show()
|
||||
}
|
||||
}
|
||||
Valet.notifyAboutUnsupportedTLD()
|
||||
|
||||
NotificationCenter.default.post(name: Events.ServicesUpdated, object: nil)
|
||||
|
||||
|
@ -11,7 +11,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate, PhpSwitcherDelegate
|
||||
|
||||
static let shared = MainMenu()
|
||||
|
||||
weak var menuDelegate: NSMenuDelegate? = nil
|
||||
weak var menuDelegate: NSMenuDelegate?
|
||||
|
||||
/**
|
||||
The status bar item with variable length.
|
||||
@ -143,7 +143,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate, PhpSwitcherDelegate
|
||||
/** Refreshes the icon with the PHP version. */
|
||||
@objc func refreshIcon() {
|
||||
DispatchQueue.main.async { [self] in
|
||||
if (PhpEnv.shared.isBusy) {
|
||||
if PhpEnv.shared.isBusy {
|
||||
setStatusBar(image: NSImage(named: NSImage.Name("StatusBarIcon"))!)
|
||||
} else {
|
||||
if Preferences.preferences[.shouldDisplayDynamicIcon] as! Bool == false {
|
||||
@ -257,7 +257,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate, PhpSwitcherDelegate
|
||||
}
|
||||
|
||||
@objc func openPhpInfo() {
|
||||
var url: URL? = nil
|
||||
var url: URL?
|
||||
|
||||
asyncWithBusyUI {
|
||||
url = Actions.createTempPhpInfoFile()
|
||||
@ -274,7 +274,7 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate, PhpSwitcherDelegate
|
||||
}
|
||||
|
||||
@objc func openActiveConfigFolder() {
|
||||
if (PhpEnv.phpInstall.version.error) {
|
||||
if PhpEnv.phpInstall.version.error {
|
||||
// php version was not identified
|
||||
Actions.openGenericPhpConfigFolder()
|
||||
return
|
||||
|
@ -52,7 +52,7 @@ class ServicesView: NSView, XibLoadable {
|
||||
func loadData() {
|
||||
self.applyAllInfoFieldsFromCachedValue()
|
||||
HomebrewService.loadAll { services in
|
||||
ServicesView.services = Dictionary(uniqueKeysWithValues: services.map{ ($0.name, $0) })
|
||||
ServicesView.services = Dictionary(uniqueKeysWithValues: services.map { ($0.name, $0) })
|
||||
self.applyAllInfoFieldsFromCachedValue()
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
class StatusMenu : NSMenu {
|
||||
class StatusMenu: NSMenu {
|
||||
|
||||
func addPhpVersionMenuItems() {
|
||||
if PhpEnv.phpInstall.version.error {
|
||||
@ -27,7 +27,7 @@ class StatusMenu : NSMenu {
|
||||
return
|
||||
}
|
||||
|
||||
if PhpEnv.shared.availablePhpVersions.count == 0 {
|
||||
if PhpEnv.shared.availablePhpVersions.isEmpty {
|
||||
return
|
||||
}
|
||||
|
||||
@ -40,8 +40,10 @@ class StatusMenu : NSMenu {
|
||||
|
||||
func addValetMenuItems() {
|
||||
self.addItem(HeaderView.asMenuItem(text: "mi_valet".localized))
|
||||
self.addItem(NSMenuItem(title: "mi_valet_config".localized, action: #selector(MainMenu.openValetConfigFolder), keyEquivalent: "v"))
|
||||
self.addItem(NSMenuItem(title: "mi_domain_list".localized, action: #selector(MainMenu.openDomainList), keyEquivalent: "l"))
|
||||
self.addItem(NSMenuItem(
|
||||
title: "mi_valet_config".localized, action: #selector(MainMenu.openValetConfigFolder), keyEquivalent: "v"))
|
||||
self.addItem(NSMenuItem(
|
||||
title: "mi_domain_list".localized, action: #selector(MainMenu.openDomainList), keyEquivalent: "l"))
|
||||
self.addItem(NSMenuItem.separator())
|
||||
}
|
||||
|
||||
@ -52,7 +54,7 @@ class StatusMenu : NSMenu {
|
||||
|
||||
self.addComposerMenuItems()
|
||||
|
||||
if (PhpEnv.shared.isBusy) {
|
||||
if PhpEnv.shared.isBusy {
|
||||
return
|
||||
}
|
||||
|
||||
@ -72,24 +74,42 @@ class StatusMenu : NSMenu {
|
||||
}
|
||||
|
||||
func addCoreMenuItems() {
|
||||
self.addItem(NSMenuItem(title: "mi_preferences".localized, action: #selector(MainMenu.openPrefs), keyEquivalent: ","))
|
||||
self.addItem(NSMenuItem(title: "mi_about".localized, action: #selector(MainMenu.openAbout), keyEquivalent: ""))
|
||||
self.addItem(NSMenuItem(title: "mi_quit".localized, action: #selector(MainMenu.terminateApp), keyEquivalent: "q"))
|
||||
self.addItem(
|
||||
NSMenuItem(title: "mi_preferences".localized, action: #selector(MainMenu.openPrefs), keyEquivalent: ",")
|
||||
)
|
||||
self.addItem(
|
||||
NSMenuItem(title: "mi_about".localized, action: #selector(MainMenu.openAbout), keyEquivalent: "")
|
||||
)
|
||||
self.addItem(
|
||||
NSMenuItem(title: "mi_quit".localized, action: #selector(MainMenu.terminateApp), keyEquivalent: "q")
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: Remaining Menu Items
|
||||
|
||||
func addConfigurationMenuItems() {
|
||||
self.addItem(HeaderView.asMenuItem(text: "mi_configuration".localized))
|
||||
self.addItem(NSMenuItem(title: "mi_php_config".localized, action: #selector(MainMenu.openActiveConfigFolder), keyEquivalent: "c"))
|
||||
self.addItem(NSMenuItem(title: "mi_phpinfo".localized, action: #selector(MainMenu.openPhpInfo), keyEquivalent: "i"))
|
||||
self.addItem(
|
||||
NSMenuItem(title: "mi_php_config".localized,
|
||||
action: #selector(MainMenu.openActiveConfigFolder), keyEquivalent: "c")
|
||||
)
|
||||
self.addItem(
|
||||
NSMenuItem(title: "mi_phpinfo".localized, action: #selector(MainMenu.openPhpInfo), keyEquivalent: "i")
|
||||
)
|
||||
}
|
||||
|
||||
func addComposerMenuItems() {
|
||||
self.addItem(HeaderView.asMenuItem(text: "mi_composer".localized))
|
||||
self.addItem(NSMenuItem(title: "mi_global_composer".localized, action: #selector(MainMenu.openGlobalComposerFolder), keyEquivalent: "g"))
|
||||
self.addItem(
|
||||
NSMenuItem(title: "mi_global_composer".localized,
|
||||
action: #selector(MainMenu.openGlobalComposerFolder), keyEquivalent: "g")
|
||||
)
|
||||
|
||||
let composerMenuItem = NSMenuItem(title: "mi_update_global_composer".localized, action: PhpEnv.shared.isBusy ? nil : #selector(MainMenu.updateGlobalComposerDependencies), keyEquivalent: "g")
|
||||
let composerMenuItem = NSMenuItem(
|
||||
title: "mi_update_global_composer".localized,
|
||||
action: PhpEnv.shared.isBusy ? nil : #selector(MainMenu.updateGlobalComposerDependencies),
|
||||
keyEquivalent: "g"
|
||||
)
|
||||
composerMenuItem.keyEquivalentModifierMask = .shift
|
||||
|
||||
self.addItem(composerMenuItem)
|
||||
@ -108,7 +128,7 @@ class StatusMenu : NSMenu {
|
||||
func addExtensionsMenuItems() {
|
||||
self.addItem(HeaderView.asMenuItem(text: "mi_detected_extensions".localized))
|
||||
|
||||
if (PhpEnv.phpInstall.extensions.count == 0) {
|
||||
if PhpEnv.phpInstall.extensions.isEmpty {
|
||||
self.addItem(NSMenuItem(title: "mi_no_extensions_detected".localized, action: nil, keyEquivalent: ""))
|
||||
}
|
||||
|
||||
@ -172,18 +192,35 @@ class StatusMenu : NSMenu {
|
||||
servicesMenu.addItem(NSMenuItem.separator())
|
||||
servicesMenu.addItem(HeaderView.asMenuItem(text: "mi_services".localized))
|
||||
|
||||
servicesMenu.addItem(NSMenuItem(title: "mi_restart_dnsmasq".localized, action: #selector(MainMenu.restartDnsMasq), keyEquivalent: "d"))
|
||||
servicesMenu.addItem(NSMenuItem(title: "mi_restart_php_fpm".localized, action: #selector(MainMenu.restartPhpFpm), keyEquivalent: "p"))
|
||||
servicesMenu.addItem(NSMenuItem(title: "mi_restart_nginx".localized, action: #selector(MainMenu.restartNginx), keyEquivalent: "n"))
|
||||
servicesMenu.addItem(NSMenuItem(title: "mi_restart_all_services".localized, action: #selector(MainMenu.restartAllServices), keyEquivalent: "s"))
|
||||
servicesMenu.addItem(
|
||||
NSMenuItem(title: "mi_stop_all_services".localized, action: #selector(MainMenu.stopAllServices), keyEquivalent: "s"),
|
||||
withKeyModifier: [.command, .shift])
|
||||
NSMenuItem(title: "mi_restart_dnsmasq".localized,
|
||||
action: #selector(MainMenu.restartDnsMasq), keyEquivalent: "d")
|
||||
)
|
||||
servicesMenu.addItem(
|
||||
NSMenuItem(title: "mi_restart_php_fpm".localized,
|
||||
action: #selector(MainMenu.restartPhpFpm), keyEquivalent: "p")
|
||||
)
|
||||
servicesMenu.addItem(
|
||||
NSMenuItem(title: "mi_restart_nginx".localized,
|
||||
action: #selector(MainMenu.restartNginx), keyEquivalent: "n")
|
||||
)
|
||||
servicesMenu.addItem(
|
||||
NSMenuItem(title: "mi_restart_all_services".localized,
|
||||
action: #selector(MainMenu.restartAllServices), keyEquivalent: "s")
|
||||
)
|
||||
servicesMenu.addItem(
|
||||
NSMenuItem(title: "mi_stop_all_services".localized,
|
||||
action: #selector(MainMenu.stopAllServices), keyEquivalent: "s"),
|
||||
withKeyModifier: [.command, .shift]
|
||||
)
|
||||
|
||||
servicesMenu.addItem(NSMenuItem.separator())
|
||||
servicesMenu.addItem(HeaderView.asMenuItem(text: "mi_manual_actions".localized))
|
||||
|
||||
servicesMenu.addItem(NSMenuItem(title: "mi_php_refresh".localized, action: #selector(MainMenu.reloadPhpMonitorMenuInForeground), keyEquivalent: "r"))
|
||||
servicesMenu.addItem(
|
||||
NSMenuItem(title: "mi_php_refresh".localized,
|
||||
action: #selector(MainMenu.reloadPhpMonitorMenuInForeground), keyEquivalent: "r")
|
||||
)
|
||||
|
||||
for item in servicesMenu.items {
|
||||
item.target = MainMenu.shared
|
||||
@ -210,11 +247,13 @@ class StatusMenu : NSMenu {
|
||||
let brew = (shortVersion == PhpEnv.brewPhpVersion) ? "php" : "php@\(shortVersion)"
|
||||
let menuItem = PhpMenuItem(
|
||||
title: "\("mi_php_switch".localized) \(versionString) (\(brew))",
|
||||
action: (shortVersion == PhpEnv.phpInstall.version.short) ? nil : action, keyEquivalent: "\(shortcutKey)"
|
||||
action: (shortVersion == PhpEnv.phpInstall.version.short)
|
||||
? nil
|
||||
: action, keyEquivalent: "\(shortcutKey)"
|
||||
)
|
||||
|
||||
menuItem.version = shortVersion
|
||||
shortcutKey = shortcutKey + 1
|
||||
shortcutKey += 1
|
||||
|
||||
self.addItem(menuItem)
|
||||
}
|
||||
@ -251,9 +290,9 @@ class XdebugMenuItem: NSMenuItem {
|
||||
}
|
||||
|
||||
class ExtensionMenuItem: NSMenuItem {
|
||||
var phpExtension: PhpExtension? = nil
|
||||
var phpExtension: PhpExtension?
|
||||
}
|
||||
|
||||
class EditorMenuItem: NSMenuItem {
|
||||
var editor: Application? = nil
|
||||
var editor: Application?
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class BetterAlert {
|
||||
}
|
||||
|
||||
init() {
|
||||
let storyboard = NSStoryboard(name: "Main" , bundle : nil)
|
||||
let storyboard = NSStoryboard(name: "Main", bundle: nil)
|
||||
|
||||
self.windowController = storyboard.instantiateController(
|
||||
withIdentifier: "noticeWindow"
|
||||
@ -31,8 +31,8 @@ class BetterAlert {
|
||||
|
||||
public func withPrimary(
|
||||
text: String,
|
||||
action: @escaping (BetterAlertVC) -> Void = {
|
||||
vc in vc.close(with: .alertFirstButtonReturn)
|
||||
action: @escaping (BetterAlertVC) -> Void = { vc in
|
||||
vc.close(with: .alertFirstButtonReturn)
|
||||
}
|
||||
) -> Self {
|
||||
self.noticeVC.buttonPrimary.title = text
|
||||
@ -42,8 +42,8 @@ class BetterAlert {
|
||||
|
||||
public func withSecondary(
|
||||
text: String,
|
||||
action: ((BetterAlertVC) -> Void)? = {
|
||||
vc in vc.close(with: .alertSecondButtonReturn)
|
||||
action: ((BetterAlertVC) -> Void)? = { vc in
|
||||
vc.close(with: .alertSecondButtonReturn)
|
||||
}
|
||||
) -> Self {
|
||||
self.noticeVC.buttonSecondary.title = text
|
||||
@ -73,7 +73,7 @@ class BetterAlert {
|
||||
self.noticeVC.labelDescription.stringValue = description
|
||||
|
||||
// If the description is missing, handle the excess space and change the top margin
|
||||
if (description == "") {
|
||||
if description == "" {
|
||||
self.noticeVC.labelDescription.isHidden = true
|
||||
self.noticeVC.primaryButtonTopMargin.constant = 0
|
||||
}
|
||||
|
@ -46,7 +46,6 @@ class BetterAlertVC: NSViewController {
|
||||
view.window?.makeFirstResponder(buttonPrimary)
|
||||
}
|
||||
|
||||
|
||||
deinit {
|
||||
Log.perf("A BetterAlert has been deinitialized.")
|
||||
}
|
||||
|
@ -12,15 +12,15 @@ struct GlobalKeybindPreference: Codable, CustomStringConvertible {
|
||||
|
||||
// MARK: - Internal variables
|
||||
|
||||
let function : Bool
|
||||
let control : Bool
|
||||
let command : Bool
|
||||
let shift : Bool
|
||||
let option : Bool
|
||||
let capsLock : Bool
|
||||
let carbonFlags : UInt32
|
||||
let characters : String?
|
||||
let keyCode : UInt32
|
||||
let function: Bool
|
||||
let control: Bool
|
||||
let command: Bool
|
||||
let shift: Bool
|
||||
let option: Bool
|
||||
let capsLock: Bool
|
||||
let carbonFlags: UInt32
|
||||
let characters: String?
|
||||
let keyCode: UInt32
|
||||
|
||||
// MARK: - How the keybind is display in Preferences
|
||||
|
||||
|
@ -99,10 +99,9 @@ class Preferences {
|
||||
*/
|
||||
static func handleMigration() {
|
||||
// If the user chose the "no icon" option, migrate it over
|
||||
if (
|
||||
if
|
||||
UserDefaults.standard.value(forKey: RetiredPreferenceName.shouldDisplayPhpHintInIcon.rawValue) != nil &&
|
||||
UserDefaults.standard.bool(forKey: RetiredPreferenceName.shouldDisplayPhpHintInIcon.rawValue) == false
|
||||
) {
|
||||
UserDefaults.standard.bool(forKey: RetiredPreferenceName.shouldDisplayPhpHintInIcon.rawValue) == false {
|
||||
Log.info("The preference where the user chose no icon has been migrated over.")
|
||||
UserDefaults.standard.set(MenuBarIcon.noIcon.rawValue, forKey: PreferenceName.iconTypeToDisplay.rawValue)
|
||||
UserDefaults.standard.removeObject(forKey: RetiredPreferenceName.shouldDisplayPhpHintInIcon.rawValue)
|
||||
@ -136,20 +135,27 @@ class Preferences {
|
||||
private static func cache() -> [PreferenceName: Any] {
|
||||
return [
|
||||
// Part 1: Always Booleans
|
||||
.shouldDisplayDynamicIcon: UserDefaults.standard.bool(forKey: PreferenceName.shouldDisplayDynamicIcon.rawValue) as Any,
|
||||
.fullPhpVersionDynamicIcon: UserDefaults.standard.bool(forKey: PreferenceName.fullPhpVersionDynamicIcon.rawValue) as Any,
|
||||
.autoServiceRestartAfterExtensionToggle: UserDefaults.standard.bool(forKey: PreferenceName.autoServiceRestartAfterExtensionToggle.rawValue) as Any,
|
||||
.autoComposerGlobalUpdateAfterSwitch: UserDefaults.standard.bool(forKey: PreferenceName.autoComposerGlobalUpdateAfterSwitch.rawValue) as Any,
|
||||
.allowProtocolForIntegrations: UserDefaults.standard.bool(forKey: PreferenceName.allowProtocolForIntegrations.rawValue) as Any,
|
||||
.shouldDisplayDynamicIcon: UserDefaults.standard.bool(
|
||||
forKey: PreferenceName.shouldDisplayDynamicIcon.rawValue) as Any,
|
||||
.fullPhpVersionDynamicIcon: UserDefaults.standard.bool(
|
||||
forKey: PreferenceName.fullPhpVersionDynamicIcon.rawValue) as Any,
|
||||
.autoServiceRestartAfterExtensionToggle: UserDefaults.standard.bool(
|
||||
forKey: PreferenceName.autoServiceRestartAfterExtensionToggle.rawValue) as Any,
|
||||
.autoComposerGlobalUpdateAfterSwitch: UserDefaults.standard.bool(
|
||||
forKey: PreferenceName.autoComposerGlobalUpdateAfterSwitch.rawValue) as Any,
|
||||
.allowProtocolForIntegrations: UserDefaults.standard.bool(
|
||||
forKey: PreferenceName.allowProtocolForIntegrations.rawValue) as Any,
|
||||
|
||||
// Part 2: Always Strings
|
||||
.globalHotkey: UserDefaults.standard.string(forKey: PreferenceName.globalHotkey.rawValue) as Any,
|
||||
.iconTypeToDisplay: UserDefaults.standard.string(forKey: PreferenceName.iconTypeToDisplay.rawValue) as Any,
|
||||
.globalHotkey: UserDefaults.standard.string(
|
||||
forKey: PreferenceName.globalHotkey.rawValue) as Any,
|
||||
.iconTypeToDisplay: UserDefaults.standard.string(
|
||||
forKey: PreferenceName.iconTypeToDisplay.rawValue) as Any
|
||||
]
|
||||
}
|
||||
|
||||
static func update(_ preference: PreferenceName, value: Any?) {
|
||||
if (value == nil) {
|
||||
if value == nil {
|
||||
UserDefaults.standard.removeObject(forKey: preference.rawValue)
|
||||
} else {
|
||||
UserDefaults.standard.setValue(value, forKey: preference.rawValue)
|
||||
|
@ -18,7 +18,7 @@ class PrefsVC: NSViewController {
|
||||
// MARK: - Display
|
||||
|
||||
public static func create(delegate: NSWindowDelegate?) {
|
||||
let storyboard = NSStoryboard(name: "Main" , bundle : nil)
|
||||
let storyboard = NSStoryboard(name: "Main", bundle: nil)
|
||||
|
||||
let windowController = storyboard.instantiateController(
|
||||
withIdentifier: "preferencesWindow"
|
||||
@ -35,7 +35,7 @@ class PrefsVC: NSViewController {
|
||||
}
|
||||
|
||||
public static func show(delegate: NSWindowDelegate? = nil) {
|
||||
if (App.shared.preferencesWindowController == nil) {
|
||||
if App.shared.preferencesWindowController == nil {
|
||||
Self.create(delegate: delegate)
|
||||
}
|
||||
|
||||
@ -47,67 +47,95 @@ class PrefsVC: NSViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
[
|
||||
CheckboxPreferenceView.make(
|
||||
sectionText: "prefs.dynamic_icon".localized,
|
||||
descriptionText: "prefs.dynamic_icon_desc".localized,
|
||||
checkboxText: "prefs.dynamic_icon_title".localized,
|
||||
preference: .shouldDisplayDynamicIcon,
|
||||
action: {
|
||||
MainMenu.shared.refreshIcon()
|
||||
}
|
||||
),
|
||||
SelectPreferenceView.make(
|
||||
sectionText: "",
|
||||
descriptionText: "prefs.icon_options_desc".localized,
|
||||
options: MenuBarIcon.allCases.map({ return $0.rawValue }),
|
||||
localizationPrefix: "prefs.icon_options",
|
||||
preference: .iconTypeToDisplay,
|
||||
action: {
|
||||
MainMenu.shared.refreshIcon()
|
||||
}
|
||||
),
|
||||
CheckboxPreferenceView.make(
|
||||
sectionText: "prefs.info_density".localized,
|
||||
descriptionText: "prefs.display_full_php_version_desc".localized,
|
||||
checkboxText: "prefs.display_full_php_version".localized,
|
||||
preference: .fullPhpVersionDynamicIcon,
|
||||
action: {
|
||||
MainMenu.shared.refreshIcon()
|
||||
MainMenu.shared.rebuild()
|
||||
}
|
||||
),
|
||||
CheckboxPreferenceView.make(
|
||||
sectionText: "prefs.services".localized,
|
||||
descriptionText: "prefs.auto_restart_services_desc".localized,
|
||||
checkboxText: "prefs.auto_restart_services_title".localized,
|
||||
preference: .autoServiceRestartAfterExtensionToggle,
|
||||
action: {}
|
||||
),
|
||||
CheckboxPreferenceView.make(
|
||||
sectionText: "prefs.switcher".localized,
|
||||
descriptionText: "prefs.auto_composer_update_desc".localized,
|
||||
checkboxText: "prefs.auto_composer_update_title".localized,
|
||||
preference: .autoComposerGlobalUpdateAfterSwitch,
|
||||
action: {}
|
||||
),
|
||||
HotkeyPreferenceView.make(
|
||||
sectionText: "prefs.global_shortcut".localized,
|
||||
descriptionText: "prefs.shortcut_desc".localized,
|
||||
self
|
||||
),
|
||||
CheckboxPreferenceView.make(
|
||||
sectionText: "prefs.integrations".localized,
|
||||
descriptionText: "prefs.open_protocol_desc".localized,
|
||||
checkboxText: "prefs.open_protocol_title".localized,
|
||||
preference: .allowProtocolForIntegrations,
|
||||
action: {}
|
||||
),
|
||||
getDynamicIconPreferenceView(),
|
||||
getIconOptionsPreferenceView(),
|
||||
getIconDensityPreferenceView(),
|
||||
getAutoRestartPreferenceView(),
|
||||
getAutomaticComposerUpdatePreferenceView(),
|
||||
getShortcutPreferenceView(),
|
||||
getIntegrationsPreferenceView()
|
||||
].forEach({ self.stackView.addArrangedSubview($0) })
|
||||
}
|
||||
|
||||
private func getDynamicIconPreferenceView() -> NSView {
|
||||
return CheckboxPreferenceView.make(
|
||||
sectionText: "prefs.dynamic_icon".localized,
|
||||
descriptionText: "prefs.dynamic_icon_desc".localized,
|
||||
checkboxText: "prefs.dynamic_icon_title".localized,
|
||||
preference: .shouldDisplayDynamicIcon,
|
||||
action: {
|
||||
MainMenu.shared.refreshIcon()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private func getIconOptionsPreferenceView() -> NSView {
|
||||
return SelectPreferenceView.make(
|
||||
sectionText: "",
|
||||
descriptionText: "prefs.icon_options_desc".localized,
|
||||
options: MenuBarIcon.allCases.map({ return $0.rawValue }),
|
||||
localizationPrefix: "prefs.icon_options",
|
||||
preference: .iconTypeToDisplay,
|
||||
action: {
|
||||
MainMenu.shared.refreshIcon()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private func getIconDensityPreferenceView() -> NSView {
|
||||
return CheckboxPreferenceView.make(
|
||||
sectionText: "prefs.info_density".localized,
|
||||
descriptionText: "prefs.display_full_php_version_desc".localized,
|
||||
checkboxText: "prefs.display_full_php_version".localized,
|
||||
preference: .fullPhpVersionDynamicIcon,
|
||||
action: {
|
||||
MainMenu.shared.refreshIcon()
|
||||
MainMenu.shared.rebuild()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private func getAutoRestartPreferenceView() -> NSView {
|
||||
return CheckboxPreferenceView.make(
|
||||
sectionText: "prefs.services".localized,
|
||||
descriptionText: "prefs.auto_restart_services_desc".localized,
|
||||
checkboxText: "prefs.auto_restart_services_title".localized,
|
||||
preference: .autoServiceRestartAfterExtensionToggle,
|
||||
action: {}
|
||||
)
|
||||
}
|
||||
|
||||
private func getAutomaticComposerUpdatePreferenceView() -> NSView {
|
||||
CheckboxPreferenceView.make(
|
||||
sectionText: "prefs.switcher".localized,
|
||||
descriptionText: "prefs.auto_composer_update_desc".localized,
|
||||
checkboxText: "prefs.auto_composer_update_title".localized,
|
||||
preference: .autoComposerGlobalUpdateAfterSwitch,
|
||||
action: {}
|
||||
)
|
||||
}
|
||||
|
||||
private func getShortcutPreferenceView() -> NSView {
|
||||
return HotkeyPreferenceView.make(
|
||||
sectionText: "prefs.global_shortcut".localized,
|
||||
descriptionText: "prefs.shortcut_desc".localized,
|
||||
self
|
||||
)
|
||||
}
|
||||
|
||||
private func getIntegrationsPreferenceView() -> NSView {
|
||||
return CheckboxPreferenceView.make(
|
||||
sectionText: "prefs.integrations".localized,
|
||||
descriptionText: "prefs.open_protocol_desc".localized,
|
||||
checkboxText: "prefs.open_protocol_title".localized,
|
||||
preference: .allowProtocolForIntegrations,
|
||||
action: {}
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Listening for hotkey delegate
|
||||
|
||||
var listeningForHotkeyView: HotkeyPreferenceView? = nil
|
||||
var listeningForHotkeyView: HotkeyPreferenceView?
|
||||
|
||||
override func viewWillDisappear() {
|
||||
if listeningForHotkeyView !== nil {
|
||||
|
@ -96,7 +96,8 @@ class Stats {
|
||||
}
|
||||
|
||||
if Stats.successfulLaunchCount < 7 && Stats.successfulSwitchCount < 40 {
|
||||
return Log.info("It is too soon to see the sponsor message (launched \(Stats.successfulLaunchCount) times, switched \(Stats.successfulSwitchCount) times).")
|
||||
return Log.info("It is too soon to see the sponsor message (launched \(Stats.successfulLaunchCount) " +
|
||||
"times, switched \(Stats.successfulSwitchCount) times).")
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
|
@ -6,8 +6,6 @@
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
import Foundation
|
||||
import Cocoa
|
||||
|
||||
@ -25,7 +23,13 @@ class CheckboxPreferenceView: NSView, XibLoadable {
|
||||
}
|
||||
}
|
||||
|
||||
static func make(sectionText: String, descriptionText: String, checkboxText: String, preference: PreferenceName, action: @escaping () -> Void) -> NSView {
|
||||
static func make(
|
||||
sectionText: String,
|
||||
descriptionText: String,
|
||||
checkboxText: String,
|
||||
preference: PreferenceName,
|
||||
action: @escaping () -> Void
|
||||
) -> NSView {
|
||||
let view = Self.createFromXib()!
|
||||
view.labelSection.stringValue = sectionText
|
||||
view.labelDescription.stringValue = descriptionText
|
||||
|
@ -6,8 +6,6 @@
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
import Foundation
|
||||
import Cocoa
|
||||
|
||||
@ -66,7 +64,7 @@ class HotkeyPreferenceView: NSView, XibLoadable {
|
||||
func loadGlobalKeybindFromPreferences() {
|
||||
let globalKeybind = GlobalKeybindPreference.fromJson(Preferences.preferences[.globalHotkey] as! String?)
|
||||
|
||||
if (globalKeybind != nil) {
|
||||
if globalKeybind != nil {
|
||||
updateKeybindButton(globalKeybind!)
|
||||
} else {
|
||||
buttonSetShortcut.title = "prefs.shortcut_set".localized
|
||||
|
@ -16,7 +16,7 @@ class SelectPreferenceView: NSView, XibLoadable {
|
||||
@IBOutlet weak var popupButton: NSPopUpButton!
|
||||
|
||||
var localizationPrefix: String = ""
|
||||
var imagePrefix: String? = nil
|
||||
var imagePrefix: String?
|
||||
|
||||
var options: [String] = [] {
|
||||
didSet {
|
||||
@ -50,6 +50,7 @@ class SelectPreferenceView: NSView, XibLoadable {
|
||||
}
|
||||
}
|
||||
|
||||
// swiftlint:disable function_parameter_count
|
||||
static func make(
|
||||
sectionText: String,
|
||||
descriptionText: String,
|
||||
@ -57,8 +58,7 @@ class SelectPreferenceView: NSView, XibLoadable {
|
||||
localizationPrefix: String,
|
||||
imagePrefix: String? = nil,
|
||||
preference: PreferenceName,
|
||||
action: @escaping () -> Void) -> NSView
|
||||
{
|
||||
action: @escaping () -> Void) -> NSView {
|
||||
let view = Self.createFromXib()!
|
||||
|
||||
view.labelSection.stringValue = sectionText
|
||||
@ -72,6 +72,7 @@ class SelectPreferenceView: NSView, XibLoadable {
|
||||
|
||||
return view
|
||||
}
|
||||
// swiftlint:enable function_parameter_count
|
||||
|
||||
@IBAction func valueChanged(_ sender: Any) {
|
||||
let index = self.popupButton.indexOfSelectedItem
|
||||
|
@ -12,7 +12,7 @@ import AppKit
|
||||
class ProgressWindowController: NSWindowController, NSWindowDelegate {
|
||||
|
||||
static func display(title: String, description: String) -> ProgressWindowController {
|
||||
let storyboard = NSStoryboard(name: "ProgressWindow" , bundle : nil)
|
||||
let storyboard = NSStoryboard(name: "ProgressWindow", bundle: nil)
|
||||
|
||||
let windowController = storyboard.instantiateController(
|
||||
withIdentifier: "progressWindow"
|
||||
@ -39,7 +39,7 @@ class ProgressWindowController: NSWindowController, NSWindowDelegate {
|
||||
return
|
||||
}
|
||||
|
||||
textView.string = textView.string + string
|
||||
textView.string += string
|
||||
textView.scrollToEndOfDocument(nil)
|
||||
}
|
||||
|
||||
|
@ -15,17 +15,17 @@ enum HomebrewDir: String {
|
||||
class Paths {
|
||||
|
||||
static let shared = Paths()
|
||||
var baseDir : HomebrewDir
|
||||
var baseDir: HomebrewDir
|
||||
var userName = String(Shell.pipe("whoami").split(separator: "\n")[0])
|
||||
|
||||
init() {
|
||||
let optBrewFound = Shell.fileExists("\(HomebrewDir.opt.rawValue)/bin/brew")
|
||||
let usrBrewFound = Shell.fileExists("\(HomebrewDir.usr.rawValue)/bin/brew")
|
||||
|
||||
if (optBrewFound) {
|
||||
if optBrewFound {
|
||||
// This is usually the case with Homebrew installed on Apple Silicon
|
||||
baseDir = .opt
|
||||
} else if (usrBrewFound) {
|
||||
} else if usrBrewFound {
|
||||
// This is usually the case with Homebrew installed on Intel (or Rosetta 2)
|
||||
baseDir = .usr
|
||||
} else {
|
||||
|
@ -16,7 +16,7 @@ class PhpConfigWatcher {
|
||||
|
||||
var didChange: ((URL) -> Void)?
|
||||
|
||||
var lastUpdate: TimeInterval? = nil
|
||||
var lastUpdate: TimeInterval?
|
||||
|
||||
var watchers: [FSWatcher] = []
|
||||
|
||||
@ -46,7 +46,11 @@ class PhpConfigWatcher {
|
||||
}))
|
||||
}
|
||||
|
||||
func addWatcher(for url: URL, eventMask: DispatchSource.FileSystemEvent, behaviour: FSWatcherBehaviour = .reloadsMenu) {
|
||||
func addWatcher(
|
||||
for url: URL,
|
||||
eventMask: DispatchSource.FileSystemEvent,
|
||||
behaviour: FSWatcherBehaviour = .reloadsMenu
|
||||
) {
|
||||
if !Filesystem.fileExists(url.path) {
|
||||
Log.warn("No watcher was created for \(url.path) because the requested file does not exist.")
|
||||
return
|
||||
@ -84,13 +88,21 @@ class FSWatcher {
|
||||
|
||||
let url: URL
|
||||
|
||||
init(for url: URL, eventMask: DispatchSource.FileSystemEvent, parent: PhpConfigWatcher, behaviour: FSWatcherBehaviour = .reloadsMenu) {
|
||||
init(
|
||||
for url: URL,
|
||||
eventMask: DispatchSource.FileSystemEvent,
|
||||
parent: PhpConfigWatcher,
|
||||
behaviour: FSWatcherBehaviour = .reloadsMenu
|
||||
) {
|
||||
self.url = url
|
||||
self.parent = parent
|
||||
self.startMonitoring(eventMask, behaviour: behaviour)
|
||||
}
|
||||
|
||||
func startMonitoring(_ eventMask: DispatchSource.FileSystemEvent, behaviour: FSWatcherBehaviour) {
|
||||
func startMonitoring(
|
||||
_ eventMask: DispatchSource.FileSystemEvent,
|
||||
behaviour: FSWatcherBehaviour
|
||||
) {
|
||||
guard folderMonitorSource == nil && monitoredFolderFileDescriptor == -1 else {
|
||||
return
|
||||
}
|
||||
|
2
phpmon/Vendor/HotKey/HotKeysController.swift
vendored
2
phpmon/Vendor/HotKey/HotKeysController.swift
vendored
@ -91,7 +91,6 @@ final class HotKeysController {
|
||||
hotKeys.removeValue(forKey: box.carbonHotKeyID)
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Events
|
||||
|
||||
static func handleCarbonEvent(_ event: EventRef?) -> OSStatus {
|
||||
@ -157,7 +156,6 @@ final class HotKeysController {
|
||||
InstallEventHandler(GetEventDispatcherTarget(), hotKeyEventHandler, 2, eventSpec, nil, &eventHandler)
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Querying
|
||||
|
||||
private static func hotKey(for carbonHotKeyID: UInt32) -> HotKey? {
|
||||
|
Reference in New Issue
Block a user