diff --git a/PHP Monitor.xcodeproj/project.pbxproj b/PHP Monitor.xcodeproj/project.pbxproj index bc7351e..c935ef7 100644 --- a/PHP Monitor.xcodeproj/project.pbxproj +++ b/PHP Monitor.xcodeproj/project.pbxproj @@ -159,7 +159,6 @@ C4EE55A927708B9E001DF387 /* PMHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EE55A627708B9E001DF387 /* PMHeaderView.swift */; }; C4EE55AA27708B9E001DF387 /* PMHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EE55A627708B9E001DF387 /* PMHeaderView.swift */; }; C4EE55AB27708B9E001DF387 /* Preview.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EE55A727708B9E001DF387 /* Preview.swift */; }; - C4EE55AC27708B9E001DF387 /* Preview.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EE55A727708B9E001DF387 /* Preview.swift */; }; C4EE55AD27708B9E001DF387 /* PMStatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EE55A827708B9E001DF387 /* PMStatsView.swift */; }; C4EE55AE27708B9E001DF387 /* PMStatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EE55A827708B9E001DF387 /* PMStatsView.swift */; }; C4EED88927A48778006D7272 /* InterAppHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EED88827A48778006D7272 /* InterAppHandler.swift */; }; @@ -967,7 +966,6 @@ 54AB03272763858F00A29D5F /* Timer.swift in Sources */, 54FCFD2B276C8AA4004CE748 /* CheckboxPreferenceView.swift in Sources */, C415D3B82770F294005EF286 /* Actions.swift in Sources */, - C4EE55AC27708B9E001DF387 /* Preview.swift in Sources */, 54B48B60275F66AE006D90C5 /* Application.swift in Sources */, C4F780C825D80B75000DBC97 /* DateExtension.swift in Sources */, C493084B279F331F009C240B /* AddSiteVC.swift in Sources */, diff --git a/phpmon-common/PHP/PHP Version/PhpVersionNumber.swift b/phpmon-common/PHP/PHP Version/PhpVersionNumber.swift index c8c718b..624e829 100644 --- a/phpmon-common/PHP/PHP Version/PhpVersionNumber.swift +++ b/phpmon-common/PHP/PHP Version/PhpVersionNumber.swift @@ -32,7 +32,7 @@ public struct PhpVersionNumberCollection: Equatable { https://getcomposer.org/doc/articles/versions.md#writing-version-constraints - Parameter constraint: The full constraint as a string (e.g. "^7.0") - - Parameter strict: Whether the minor version check is strict. See more below. + - Parameter strict: Whether the patch version check is strict. See more below. The strict mode does not matter if a patch version is provided for all versions in the collection. @@ -45,7 +45,8 @@ public struct PhpVersionNumberCollection: Equatable { Given versions 8.0.? and 8.1.?, but the requirement is ^8.0.1, in strict mode only 8.1.? will be considered valid (8.0 translates to 8.0.0 and as such is older than 8.0.1, 8.1.0 is OK). - When checking against actual PHP versions installed by the user, use strict mode. + When checking against actual PHP versions installed by the user (with patch precision), use + strict mode. **NON-STRICT MODE (= patch precision off)** @@ -77,6 +78,14 @@ public struct PhpVersionNumberCollection: Equatable { : $0.hasSameMajorButNewerOrSameMinor(version, strict) } } + + if let version = PhpVersionNumber.make(from: constraint, type: .greaterThanOrEqual) { + return self.versions.filter { $0.isSameAs(version, strict) || $0.isNewerThan(version, strict) } + } + + if let version = PhpVersionNumber.make(from: constraint, type: .greaterThan) { + return self.versions.filter { $0.isNewerThan(version, strict) } + } return [] } @@ -87,7 +96,7 @@ public struct PhpVersionNumber: Equatable { let minor: Int let patch: Int? - public func patch(_ strictFallback: Bool, _ constraint: PhpVersionNumber? = nil) -> Int { + public func patch(_ strictFallback: Bool = true, _ constraint: PhpVersionNumber? = nil) -> Int { return patch ?? (strictFallback ? 0 : constraint?.patch ?? 999) } @@ -99,11 +108,11 @@ public struct PhpVersionNumber: Equatable { case versionOnly = #"^(?\d+).(?\d+).?(?\d+)?\z"# case caretVersionRange = #"^\^(?\d+).(?\d+).?(?\d+)?\z"# case tildeVersionRange = #"^~(?\d+).(?\d+).?(?\d+)?\z"# - - // TODO: (5.0) Handle these cases - /* case greaterThanOrEqual = #"^>=(?\d+).(?\d+).?(?\d+)?\z"# case greaterThan = #"^>(?\d+).(?\d+).?(?\d+)?\z"# + + // TODO: (5.1) Handle these cases (even though I suspect these are uncommon) + /* case smallerThanOrEqual = #"^<=(?\d+).(?\d+).?(?\d+)?\z"# case smallerThan = #"^<(?\d+).(?\d+).?(?\d+)?\z"# */ @@ -138,6 +147,15 @@ public struct PhpVersionNumber: Equatable { && (strict ? self.patch(strict, version) == version.patch(strict) : true) } + internal func isNewerThan(_ version: PhpVersionNumber, _ strict: Bool) -> Bool { + return ( + self.major > version.major || + self.major == version.major && self.minor > version.minor || + self.major == version.major && self.minor == version.minor + && self.patch(strict) > version.patch(strict) + ) + } + internal func hasNewerMinorVersionOrPatch(_ version: PhpVersionNumber, _ strict: Bool) -> Bool { return self.major == version.major && ( @@ -148,7 +166,7 @@ public struct PhpVersionNumber: Equatable { internal func hasSameMajorAndMinorButNewerOrSamePatch(_ version: PhpVersionNumber, _ strict: Bool) -> Bool { return self.major == version.major && self.minor == version.minor - && self.patch(strict, version) >= version.patch! + && self.patch(strict, version) >= version.patch(strict) } internal func hasSameMajorButNewerOrSameMinor(_ version: PhpVersionNumber, _ strict: Bool) -> Bool { diff --git a/phpmon-tests/PhpVersionNumberTest.swift b/phpmon-tests/PhpVersionNumberTest.swift index dc9f1cb..2a059e3 100644 --- a/phpmon-tests/PhpVersionNumberTest.swift +++ b/phpmon-tests/PhpVersionNumberTest.swift @@ -191,4 +191,86 @@ class PhpVersionNumberTest: XCTestCase { .make(from: ["7.4.10", "7.3.10", "7.2.10", "7.1.10", "7.0.10"]).all ) } + + func testCanCheckGreaterThanOrEqualConstraints() throws { + XCTAssertEqual( + PhpVersionNumberCollection + .make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"]) + .matching(constraint: ">=7.0", strict: true), + PhpVersionNumberCollection + .make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"]).all + ) + + XCTAssertEqual( + PhpVersionNumberCollection + .make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"]) + .matching(constraint: ">=7.0.0", strict: true), + PhpVersionNumberCollection + .make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"]).all + ) + + // Strict check (>7.2.5 is too new for 7.2 which resolves to 7.2.0) + XCTAssertEqual( + PhpVersionNumberCollection + .make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"]) + .matching(constraint: ">=7.2.5", strict: true), + PhpVersionNumberCollection + .make(from: ["7.4", "7.3"]).all + ) + + // Non-strict check (ignoring patch, 7.2 resolves to 7.2.999) + XCTAssertEqual( + PhpVersionNumberCollection + .make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"]) + .matching(constraint: ">=7.2.5", strict: false), + PhpVersionNumberCollection + .make(from: ["7.4", "7.3", "7.2"]).all + ) + } + + func testCanCheckGreaterThanConstraints() throws { + XCTAssertEqual( + PhpVersionNumberCollection + .make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"]) + .matching(constraint: ">7.0"), + PhpVersionNumberCollection + .make(from: ["7.4", "7.3", "7.2", "7.1"]).all + ) + + XCTAssertEqual( + PhpVersionNumberCollection + .make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"]) + .matching(constraint: ">7.2.5"), + // 7.2 will be valid due to non-strict mode (resolves to 7.2.999) + PhpVersionNumberCollection + .make(from: ["7.4", "7.3", "7.2"]).all + ) + + XCTAssertEqual( + PhpVersionNumberCollection + .make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"]) + .matching(constraint: ">7.2.5", strict: true), + // 7.2 will not be valid due to strict mode (resolves to 7.2.0) + PhpVersionNumberCollection + .make(from: ["7.4", "7.3"]).all + ) + + XCTAssertEqual( + PhpVersionNumberCollection + .make(from: ["7.3.1", "7.2.9", "7.2.8", "7.2.6", "7.2.5", "7.2"]) + .matching(constraint: ">7.2.8"), + // 7.2 will be valid due to non-strict mode (resolves to 7.2.999) + PhpVersionNumberCollection + .make(from: ["7.3.1", "7.2.9", "7.2"]).all + ) + + XCTAssertEqual( + PhpVersionNumberCollection + .make(from: ["7.3.1", "7.2.9", "7.2.8", "7.2.6", "7.2.5", "7.2"]) + .matching(constraint: ">7.2.8", strict: true), + // 7.2 will not be valid due to strict mode (resolves to 7.2.0) + PhpVersionNumberCollection + .make(from: ["7.3.1", "7.2.9"]).all + ) + } }