From 86d7ae49fb5dd49ace523ac35ee47c9a946eaf3e Mon Sep 17 00:00:00 2001 From: Mark Gregory Date: Tue, 20 Oct 2026 09:19:57 +0100 Subject: [PATCH] row editing --- DBSyn.xcodeproj/project.pbxproj | 8 +++--- DBSyn/MainView.swift | 30 ++++++++++++++++++----- docs/DBSyn-1.0.4-build77-release-notes.md | 9 +++++++ 3 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 docs/DBSyn-1.0.4-build77-release-notes.md diff --git a/DBSyn.xcodeproj/project.pbxproj b/DBSyn.xcodeproj/project.pbxproj index ef7e3db..e59358c 100644 --- a/DBSyn.xcodeproj/project.pbxproj +++ b/DBSyn.xcodeproj/project.pbxproj @@ -221,8 +221,8 @@ ENABLE_APP_SANDBOX = NO; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_CFBundleDisplayName = "DBSyn"; - MARKETING_VERSION = 1.0.3; - CURRENT_PROJECT_VERSION = 76; + MARKETING_VERSION = 1.0.4; + CURRENT_PROJECT_VERSION = 77; ENABLE_TESTABILITY = YES; ONLY_ACTIVE_ARCH = YES; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 ABSDEV. All rights reserved."; @@ -244,8 +244,8 @@ ENABLE_APP_SANDBOX = NO; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_CFBundleDisplayName = "DBSyn"; - MARKETING_VERSION = 1.0.3; - CURRENT_PROJECT_VERSION = 76; + MARKETING_VERSION = 1.0.4; + CURRENT_PROJECT_VERSION = 77; ENABLE_TESTABILITY = YES; ONLY_ACTIVE_ARCH = YES; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 ABSDEV. All rights reserved."; diff --git a/DBSyn/MainView.swift b/DBSyn/MainView.swift index d02dc50..a8e209d 100644 --- a/DBSyn/MainView.swift +++ b/DBSyn/MainView.swift @@ -7909,11 +7909,26 @@ private enum LaravelBcryptService { return String(result.prefix(length)) } + static func resolvedPHPPath(_ preferred: String = "") -> String? { + let fm = FileManager.default + let root = "/Applications/ServBay/package/php" + let versions = (try? fm.contentsOfDirectory(atPath: root)) ?? [] + let servBay = versions.sorted { $0.compare($1, options: .numeric) == .orderedDescending } + .map { version -> String in + let base = "\(root)/\(version)" + let builds = (try? fm.contentsOfDirectory(atPath: base)) ?? [] + let latest = builds.sorted { $0.compare($1, options: .numeric) == .orderedDescending } + return latest.first(where: { fm.isExecutableFile(atPath: "\(base)/\($0)/bin/php") }) + .map { "\(base)/\($0)/bin/php" } ?? "" + } + let candidates = [preferred.trimmingCharacters(in: .whitespacesAndNewlines), + "/Applications/ServBay/script/alias/php"] + servBay + + ["/opt/homebrew/bin/php", "/usr/local/bin/php", "/usr/bin/php"] + return candidates.first(where: { !$0.isEmpty && $0.hasPrefix("/") && fm.isExecutableFile(atPath: $0) }) + } + static func hash(_ plaintext: String, phpPath: String) throws -> String { - let candidates = [phpPath, "/opt/homebrew/bin/php", "/usr/local/bin/php", "/usr/bin/php"] - guard let executable = candidates.first(where: { - !$0.isEmpty && $0.hasPrefix("/") && FileManager.default.isExecutableFile(atPath: $0) - }) else { throw HashError.noPHP } + guard let executable = resolvedPHPPath(phpPath) else { throw HashError.noPHP } let process = Process() process.executableURL = URL(fileURLWithPath: executable) @@ -7946,7 +7961,7 @@ private struct DBSynLaravelPasswordGenerator: View { let onUseHash: (String) -> Void @State private var plaintext = "" @State private var hashed = "" - @State private var phpPath = "" + @AppStorage("DBSyn.LaravelPHPPath") private var phpPath = "" @State private var showPassword = false @State private var busy = false @State private var errorText: String? @@ -7974,9 +7989,12 @@ private struct DBSynLaravelPasswordGenerator: View { HStack { TextField("PHP executable path (optional)", text: $phpPath) .textFieldStyle(.roundedBorder) - Text("Uses Homebrew PHP automatically when available") + Text("Detects ServBay and Homebrew PHP automatically") .font(.caption).foregroundStyle(.secondary) } + Text("PHP: " + (LaravelBcryptService.resolvedPHPPath(phpPath) ?? "Not found")) + .font(.caption.monospaced()).foregroundStyle(.secondary) + .textSelection(.enabled) HStack { Button(busy ? "Hashing…" : "Generate bcrypt Hash") { generateHash() } .disabled(plaintext.isEmpty || busy) diff --git a/docs/DBSyn-1.0.4-build77-release-notes.md b/docs/DBSyn-1.0.4-build77-release-notes.md new file mode 100644 index 0000000..723f80e --- /dev/null +++ b/docs/DBSyn-1.0.4-build77-release-notes.md @@ -0,0 +1,9 @@ +# DBSyn 1.0.4 (Build 77) + +- Automatically discovers ServBay PHP installations, preferring the highest installed PHP version. +- Falls back to ServBay alias, Homebrew and standard PHP paths. +- Remembers an optional manually specified PHP executable between launches. +- Shows the resolved executable in the Laravel Password Generator. +- Retains stdin-based bcrypt generation and the existing Use Hash in Row workflow. + +Source patch only; Xcode build and macOS runtime validation have not been performed.