diff --git a/PHP Monitor.xcodeproj/project.pbxproj b/PHP Monitor.xcodeproj/project.pbxproj index 4c53cfb..e2f4086 100644 --- a/PHP Monitor.xcodeproj/project.pbxproj +++ b/PHP Monitor.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 5420395926135DC100FB00FA /* PrefsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395826135DC100FB00FA /* PrefsVC.swift */; }; 5420395F2613607600FB00FA /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395E2613607600FB00FA /* Preferences.swift */; }; + 54A18D40282A566E000A0D81 /* nginx-secure-proxy-custom-tld.test in Resources */ = {isa = PBXBuildFile; fileRef = 54A18D3F282A566E000A0D81 /* nginx-secure-proxy-custom-tld.test */; }; 54B48B5F275F66AE006D90C5 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B48B5E275F66AE006D90C5 /* Application.swift */; }; 54B48B60275F66AE006D90C5 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B48B5E275F66AE006D90C5 /* Application.swift */; }; 54D9E0B227E4F51E003B9AD9 /* HotKeysController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D9E0AC27E4F51E003B9AD9 /* HotKeysController.swift */; }; @@ -51,6 +52,9 @@ C40C7F2927721FF600DDDCDC /* ActivePhpInstallation+Checks.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F2727721FF600DDDCDC /* ActivePhpInstallation+Checks.swift */; }; C40C7F3027722E8D00DDDCDC /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F2F27722E8D00DDDCDC /* Logger.swift */; }; C40C7F3127722E8D00DDDCDC /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40C7F2F27722E8D00DDDCDC /* Logger.swift */; }; + C40FE737282ABA4F00A302C2 /* AppVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40FE736282ABA4F00A302C2 /* AppVersion.swift */; }; + C40FE738282ABA4F00A302C2 /* AppVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40FE736282ABA4F00A302C2 /* AppVersion.swift */; }; + C40FE73B282ABB2E00A302C2 /* AppVersionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C40FE739282ABB2E00A302C2 /* AppVersionTest.swift */; }; C412E5FC25700D5300A1FB67 /* HomebrewPackage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */; }; C415937F27A1B54F00D2E1B7 /* PhpFrameworks.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415937E27A1B54F00D2E1B7 /* PhpFrameworks.swift */; }; C415938027A1B54F00D2E1B7 /* PhpFrameworks.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415937E27A1B54F00D2E1B7 /* PhpFrameworks.swift */; }; @@ -117,6 +121,9 @@ C464ADAF275A7A69003FCD53 /* DomainListVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C464ADAE275A7A69003FCD53 /* DomainListVC.swift */; }; C464ADB0275A7A6A003FCD53 /* DomainListVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C464ADAE275A7A69003FCD53 /* DomainListVC.swift */; }; C464ADB2275A87CA003FCD53 /* DomainListCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C464ADB1275A87CA003FCD53 /* DomainListCellProtocol.swift */; }; + C46E206D28299B3800D909D6 /* AppUpdateChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46E206C28299B3800D909D6 /* AppUpdateChecker.swift */; }; + C46E206E28299B3800D909D6 /* AppUpdateChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46E206C28299B3800D909D6 /* AppUpdateChecker.swift */; }; + C46E20702829D27F00D909D6 /* AppUpdaterCheckTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46E206F2829D27F00D909D6 /* AppUpdaterCheckTest.swift */; }; C46FA23F246C358E00944F05 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46FA23E246C358E00944F05 /* StringExtension.swift */; }; C46FA9882822EFDC00D78807 /* PhpConfigurationFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46FA9872822EFDC00D78807 /* PhpConfigurationFile.swift */; }; C46FA9892822EFDC00D78807 /* PhpConfigurationFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46FA9872822EFDC00D78807 /* PhpConfigurationFile.swift */; }; @@ -272,6 +279,7 @@ /* Begin PBXFileReference section */ 5420395826135DC100FB00FA /* PrefsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsVC.swift; sourceTree = ""; }; 5420395E2613607600FB00FA /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = ""; }; + 54A18D3F282A566E000A0D81 /* nginx-secure-proxy-custom-tld.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-secure-proxy-custom-tld.test"; sourceTree = ""; }; 54B48B5E275F66AE006D90C5 /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = ""; }; 54D9E0AC27E4F51E003B9AD9 /* HotKeysController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HotKeysController.swift; sourceTree = ""; }; 54D9E0AD27E4F51E003B9AD9 /* Key.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Key.swift; sourceTree = ""; }; @@ -294,6 +302,8 @@ C40C7F1D2772136000DDDCDC /* PhpEnv.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpEnv.swift; sourceTree = ""; }; C40C7F2727721FF600DDDCDC /* ActivePhpInstallation+Checks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ActivePhpInstallation+Checks.swift"; sourceTree = ""; }; C40C7F2F27722E8D00DDDCDC /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = ""; }; + C40FE736282ABA4F00A302C2 /* AppVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppVersion.swift; sourceTree = ""; }; + C40FE739282ABB2E00A302C2 /* AppVersionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppVersionTest.swift; sourceTree = ""; }; C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomebrewPackage.swift; sourceTree = ""; }; C415937E27A1B54F00D2E1B7 /* PhpFrameworks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpFrameworks.swift; sourceTree = ""; }; C415D3B62770F294005EF286 /* Actions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Actions.swift; sourceTree = ""; }; @@ -340,6 +350,8 @@ C464ADAB275A7A3F003FCD53 /* DomainListWC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainListWC.swift; sourceTree = ""; }; C464ADAE275A7A69003FCD53 /* DomainListVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainListVC.swift; sourceTree = ""; }; C464ADB1275A87CA003FCD53 /* DomainListCellProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainListCellProtocol.swift; sourceTree = ""; }; + C46E206C28299B3800D909D6 /* AppUpdateChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppUpdateChecker.swift; sourceTree = ""; }; + C46E206F2829D27F00D909D6 /* AppUpdaterCheckTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppUpdaterCheckTest.swift; sourceTree = ""; }; C46FA23E246C358E00944F05 /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; }; C46FA9872822EFDC00D78807 /* PhpConfigurationFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpConfigurationFile.swift; sourceTree = ""; }; C46FA98A2822F08F00D78807 /* PhpIniTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpIniTest.swift; sourceTree = ""; }; @@ -658,8 +670,9 @@ C459B4BE27F6093A00E9B4B4 /* nginx */ = { isa = PBXGroup; children = ( - C42F26752805FEE200938AC7 /* nginx-secure-proxy.test */, C459B4BC27F6093700E9B4B4 /* nginx-proxy.test */, + C42F26752805FEE200938AC7 /* nginx-secure-proxy.test */, + 54A18D3F282A566E000A0D81 /* nginx-secure-proxy-custom-tld.test */, C42CFB1527DFDE7900862737 /* nginx-site.test */, C42CFB1727DFDFDC00862737 /* nginx-site-isolated.test */, ); @@ -792,6 +805,8 @@ C4B97B7A275CF20A003F3378 /* App+GlobalHotkey.swift */, C4EED88827A48778006D7272 /* InterAppHandler.swift */, C4D8016522B1584700C6DA1B /* Startup.swift */, + C46E206C28299B3800D909D6 /* AppUpdateChecker.swift */, + C40FE736282ABA4F00A302C2 /* AppVersion.swift */, ); path = App; sourceTree = ""; @@ -874,6 +889,8 @@ C48D6C73279CD3E400F26D7E /* PhpVersionNumberTest.swift */, C4B56360276AB0A500F12CCB /* VersionExtractorTest.swift */, C4AF9F7C275454A900D44ED0 /* ValetVersionExtractorTest.swift */, + C40FE739282ABB2E00A302C2 /* AppVersionTest.swift */, + C46E206F2829D27F00D909D6 /* AppUpdaterCheckTest.swift */, ); path = Versions; sourceTree = ""; @@ -1093,6 +1110,7 @@ C44C1992276E44CB0072762D /* ProgressWindow.storyboard in Resources */, C42F26762805FEE200938AC7 /* nginx-secure-proxy.test in Resources */, C4F30B08278E195800755FCE /* brew-services.json in Resources */, + 54A18D40282A566E000A0D81 /* nginx-secure-proxy-custom-tld.test in Resources */, C42CFB1627DFDE7900862737 /* nginx-site.test in Resources */, C459B4BD27F6093700E9B4B4 /* nginx-proxy.test in Resources */, ); @@ -1157,6 +1175,7 @@ C41C02A927E61A65009F26CB /* ValetSite+Fake.swift in Sources */, C4C0E8DF27F88AEB002D32A9 /* FakeSiteScanner.swift in Sources */, C4F2E4372752F0870020E974 /* HomebrewDiagnostics.swift in Sources */, + C40FE737282ABA4F00A302C2 /* AppVersion.swift in Sources */, C4CCBA6C275C567B008C7055 /* PMWindowController.swift in Sources */, C4B585442770FE3900DA4FBE /* Command.swift in Sources */, C44067F527E2582B0045BD4E /* DomainListNameCell.swift in Sources */, @@ -1186,6 +1205,7 @@ C4811D2A22D70F9A00B5F6B3 /* MainMenu.swift in Sources */, C40C7F3027722E8D00DDDCDC /* Logger.swift in Sources */, C41CA5ED2774F8EE00A2C80E /* DomainListVC+Actions.swift in Sources */, + C46E206D28299B3800D909D6 /* AppUpdateChecker.swift in Sources */, C412E5FC25700D5300A1FB67 /* HomebrewPackage.swift in Sources */, C4D9ADBF277610E1007277F4 /* PhpSwitcher.swift in Sources */, C4068CAA27B0890D00544CD5 /* MenuBarIcons.swift in Sources */, @@ -1298,6 +1318,7 @@ C40C7F3127722E8D00DDDCDC /* Logger.swift in Sources */, C4068CAB27B0890D00544CD5 /* MenuBarIcons.swift in Sources */, C4F30B09278E1A0E00755FCE /* CustomPrefs.swift in Sources */, + C40FE738282ABA4F00A302C2 /* AppVersion.swift in Sources */, C415D3E92770F692005EF286 /* AppDelegate+InterApp.swift in Sources */, C484437C2804BB560041A78A /* ValetProxyScanner.swift in Sources */, C4AF9F78275447F100D44ED0 /* ValetConfigurationTest.swift in Sources */, @@ -1309,6 +1330,7 @@ 54D9E0B327E4F51E003B9AD9 /* HotKeysController.swift in Sources */, C4B97B79275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */, C4CE3BBB27B324230086CA49 /* MainMenu+Switcher.swift in Sources */, + C46E20702829D27F00D909D6 /* AppUpdaterCheckTest.swift in Sources */, C4F7809C25D80344000DBC97 /* CommandTest.swift in Sources */, C44CCD4127AFE2FC00CE40E5 /* AlertableError.swift in Sources */, C4D936CA27E3EB6100BD69FE /* PhpHelper.swift in Sources */, @@ -1354,8 +1376,10 @@ C464ADB0275A7A6A003FCD53 /* DomainListVC.swift in Sources */, C43A8A1A25D9CD1000591B77 /* Utility.swift in Sources */, C418898A275FE8CB001EF227 /* Filesystem.swift in Sources */, + C40FE73B282ABB2E00A302C2 /* AppVersionTest.swift in Sources */, C4F780C625D80B75000DBC97 /* XibLoadable.swift in Sources */, C4EE55AA27708B9E001DF387 /* PMHeaderView.swift in Sources */, + C46E206E28299B3800D909D6 /* AppUpdateChecker.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1501,12 +1525,12 @@ C41C1B4422B0098000E7CF16 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIconDev; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = phpmon/phpmon.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 770; + CURRENT_PROJECT_VERSION = 786; DEBUG = YES; DEVELOPMENT_TEAM = 8M54J5J787; ENABLE_HARDENED_RUNTIME = YES; @@ -1516,7 +1540,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = "5.3-dev"; + MARKETING_VERSION = 5.3; PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1527,12 +1551,12 @@ C41C1B4522B0098000E7CF16 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIconDev; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = phpmon/phpmon.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 770; + CURRENT_PROJECT_VERSION = 786; DEBUG = NO; DEVELOPMENT_TEAM = 8M54J5J787; ENABLE_HARDENED_RUNTIME = YES; @@ -1542,7 +1566,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = "5.3-dev"; + MARKETING_VERSION = 5.3; PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/PHP Monitor.xcodeproj/xcshareddata/xcschemes/PHP Monitor.xcscheme b/PHP Monitor.xcodeproj/xcshareddata/xcschemes/PHP Monitor.xcscheme index 4c3c9fa..ada3675 100644 --- a/PHP Monitor.xcodeproj/xcshareddata/xcschemes/PHP Monitor.xcscheme +++ b/PHP Monitor.xcodeproj/xcshareddata/xcschemes/PHP Monitor.xcscheme @@ -61,6 +61,12 @@ ReferencedContainer = "container:PHP Monitor.xcodeproj"> + + + + +
+How frequently does PHP Monitor check for updates? + +PHP Monitor will check if an update is available every time you start the app. + +You can disable this behaviour by going to Preferences (via the PHP Monitor icon in the menu bar) and unchecking "Automatically check for updates". You can always check for updates manually. + +
+
I have PHP Monitor installed, and it works. I want to upgrade my PHP installations to the latest version, what's the best way to do this? @@ -278,9 +287,13 @@ PHP Monitor is a universal app and supports both architectures, so [find out her
Why is the app doing network requests? -It's Homebrew. I can't prevent `brew` from doing things via the network when I invoke it. +The app will automatically check for updates, which is the most likely culprit. -PHP Monitor itself doesn't do any network requests. Feel free to check the source code or intercept the traffic, if you don't believe me. +This happens at launch (unless disabled), and the app directly checks the Caskfile hosted on GitHub. This data is not, and will not be used for analytics (and, as far as I can tell, cannot). + +I also can't prevent `brew` from doing things via the network when PHP Monitor uses the binary. + +The app includes an Internet Access Policy file, so if you're using something like Little Snitch there should be a description why these calls occur.
diff --git a/phpmon-tests/Commands/CommandTest.swift b/phpmon-tests/Commands/CommandTest.swift index 32e2ed4..74e4969 100644 --- a/phpmon-tests/Commands/CommandTest.swift +++ b/phpmon-tests/Commands/CommandTest.swift @@ -3,7 +3,7 @@ // phpmon-tests // // Created by Nico Verbruggen on 13/02/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import XCTest diff --git a/phpmon-tests/Parsers/HomebrewPackageTest.swift b/phpmon-tests/Parsers/HomebrewPackageTest.swift index d58c8ab..02f2fdf 100644 --- a/phpmon-tests/Parsers/HomebrewPackageTest.swift +++ b/phpmon-tests/Parsers/HomebrewPackageTest.swift @@ -3,7 +3,7 @@ // phpmon-tests // // Created by Nico Verbruggen on 14/02/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import XCTest diff --git a/phpmon-tests/Parsers/NginxConfigurationTest.swift b/phpmon-tests/Parsers/NginxConfigurationTest.swift index adccb2b..15a73af 100644 --- a/phpmon-tests/Parsers/NginxConfigurationTest.swift +++ b/phpmon-tests/Parsers/NginxConfigurationTest.swift @@ -3,13 +3,15 @@ // phpmon-tests // // Created by Nico Verbruggen on 29/11/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import XCTest class NginxConfigurationTest: XCTestCase { + // MARK: - Test Files + static var regularUrl: URL { return Bundle(for: Self.self).url(forResource: "nginx-site", withExtension: "test")! } @@ -26,42 +28,54 @@ class NginxConfigurationTest: XCTestCase { return Bundle(for: Self.self).url(forResource: "nginx-secure-proxy", withExtension: "test")! } + static var customTldProxyUrl: URL { + return Bundle(for: Self.self).url(forResource: "nginx-secure-proxy-custom-tld", withExtension: "test")! + } + + // MARK: - Tests + func testCanDetermineSiteNameAndTld() throws { XCTAssertEqual( "nginx-site", - NginxConfiguration(filePath: NginxConfigurationTest.regularUrl.path).domain + NginxConfiguration.from(filePath: NginxConfigurationTest.regularUrl.path)?.domain ) XCTAssertEqual( "test", - NginxConfiguration(filePath: NginxConfigurationTest.regularUrl.path).tld + NginxConfiguration.from(filePath: NginxConfigurationTest.regularUrl.path)?.tld ) } func testCanDetermineIsolation() throws { XCTAssertNil( - NginxConfiguration(filePath: NginxConfigurationTest.regularUrl.path).isolatedVersion + NginxConfiguration.from(filePath: NginxConfigurationTest.regularUrl.path)?.isolatedVersion ) XCTAssertEqual( "8.1", - NginxConfiguration(filePath: NginxConfigurationTest.isolatedUrl.path).isolatedVersion + NginxConfiguration.from(filePath: NginxConfigurationTest.isolatedUrl.path)?.isolatedVersion ) } func testCanDetermineProxy() throws { - let proxied = NginxConfiguration(filePath: NginxConfigurationTest.proxyUrl.path) + let proxied = NginxConfiguration.from(filePath: NginxConfigurationTest.proxyUrl.path)! XCTAssertTrue(proxied.contents.contains("# valet stub: proxy.valet.conf")) XCTAssertEqual("http://127.0.0.1:90", proxied.proxy) - let normal = NginxConfiguration(filePath: NginxConfigurationTest.regularUrl.path) + let normal = NginxConfiguration.from(filePath: NginxConfigurationTest.regularUrl.path)! XCTAssertFalse(normal.contents.contains("# valet stub: proxy.valet.conf")) XCTAssertEqual(nil, normal.proxy) } func testCanDetermineSecuredProxy() throws { - let proxied = NginxConfiguration(filePath: NginxConfigurationTest.secureProxyUrl.path) + let proxied = NginxConfiguration.from(filePath: NginxConfigurationTest.secureProxyUrl.path)! XCTAssertTrue(proxied.contents.contains("# valet stub: secure.proxy.valet.conf")) XCTAssertEqual("http://127.0.0.1:90", proxied.proxy) } + func testCanDetermineProxyWithCustomTld() throws { + let proxied = NginxConfiguration.from(filePath: NginxConfigurationTest.customTldProxyUrl.path)! + XCTAssertTrue(proxied.contents.contains("# valet stub: secure.proxy.valet.conf")) + XCTAssertEqual("http://localhost:8080", proxied.proxy) + } + } diff --git a/phpmon-tests/Parsers/PhpExtensionTest.swift b/phpmon-tests/Parsers/PhpExtensionTest.swift index b4866ee..375760b 100644 --- a/phpmon-tests/Parsers/PhpExtensionTest.swift +++ b/phpmon-tests/Parsers/PhpExtensionTest.swift @@ -3,7 +3,7 @@ // phpmon-tests // // Created by Nico Verbruggen on 13/02/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import XCTest diff --git a/phpmon-tests/Parsers/ValetConfigurationTest.swift b/phpmon-tests/Parsers/ValetConfigurationTest.swift index 73048f7..fab1e15 100644 --- a/phpmon-tests/Parsers/ValetConfigurationTest.swift +++ b/phpmon-tests/Parsers/ValetConfigurationTest.swift @@ -3,7 +3,7 @@ // phpmon-tests // // Created by Nico Verbruggen on 29/11/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import XCTest diff --git a/phpmon-tests/Test Files/nginx/nginx-secure-proxy-custom-tld.test b/phpmon-tests/Test Files/nginx/nginx-secure-proxy-custom-tld.test new file mode 100644 index 0000000..6dbe50b --- /dev/null +++ b/phpmon-tests/Test Files/nginx/nginx-secure-proxy-custom-tld.test @@ -0,0 +1,57 @@ +# valet stub: secure.proxy.valet.conf + +server { + listen 127.0.0.1:80; + #listen 127.0.0.1:80; # valet loopback + server_name live.whatagraph.dev.com www.live.whatagraph.dev.com *.live.whatagraph.dev.com; + return 301 https://$host$request_uri; +} + +server { + listen 127.0.0.1:443 ssl http2; + #listen 127.0.0.1:443 ssl http2; # valet loopback + server_name live.whatagraph.dev.com www.live.whatagraph.dev.com *.live.whatagraph.dev.com; + root /; + charset utf-8; + client_max_body_size 128M; + http2_push_preload on; + + location /41c270e4-5535-4daa-b23e-c269744c2f45/ { + internal; + alias /; + try_files $uri $uri/; + } + + ssl_certificate "/Users/phpmon/.config/valet/Certificates/live.whatagraph.dev.com.crt"; + ssl_certificate_key "/Users/phpmon/.config/valet/Certificates/live.whatagraph.dev.com.key"; + + access_log off; + error_log "/Users/phpmon/.config/valet/Log/live.whatagraph.dev.com-error.log"; + + error_page 404 "/Users/phpmon/.composer/vendor/laravel/valet/server.php"; + + location / { + proxy_pass http://localhost:8080/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Client-Verify SUCCESS; + proxy_set_header X-Client-DN $ssl_client_s_dn; + proxy_set_header X-SSL-Subject $ssl_client_s_dn; + proxy_set_header X-SSL-Issuer $ssl_client_i_dn; + proxy_set_header X-NginX-Proxy true; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_http_version 1.1; + proxy_read_timeout 1800; + proxy_connect_timeout 1800; + chunked_transfer_encoding on; + proxy_redirect off; + proxy_buffering off; + } + + location ~ /\.ht { + deny all; + } +} diff --git a/phpmon-tests/Utility.swift b/phpmon-tests/Utility.swift index 49afe81..abf2b78 100644 --- a/phpmon-tests/Utility.swift +++ b/phpmon-tests/Utility.swift @@ -3,7 +3,7 @@ // phpmon-tests // // Created by Nico Verbruggen on 14/02/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon-tests/Versions/AppUpdaterCheckTest.swift b/phpmon-tests/Versions/AppUpdaterCheckTest.swift new file mode 100644 index 0000000..64a2854 --- /dev/null +++ b/phpmon-tests/Versions/AppUpdaterCheckTest.swift @@ -0,0 +1,21 @@ +// +// AppUpdaterCheckTest.swift +// phpmon-tests +// +// Created by Nico Verbruggen on 10/05/2022. +// Copyright © 2022 Nico Verbruggen. All rights reserved. +// + +import XCTest + +class AppUpdaterCheckTest: XCTestCase { + + func testCanRetrieveVersionFromCask() { + let caskVersion = AppUpdateChecker.retrieveVersionFromCask() + + let version = VersionExtractor.from(caskVersion) + + XCTAssertNotNil(version) + } + +} diff --git a/phpmon-tests/Versions/AppVersionTest.swift b/phpmon-tests/Versions/AppVersionTest.swift new file mode 100644 index 0000000..e96846e --- /dev/null +++ b/phpmon-tests/Versions/AppVersionTest.swift @@ -0,0 +1,62 @@ +// +// AppVersionTest.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 10/05/2022. +// Copyright © 2022 Nico Verbruggen. All rights reserved. +// + +import XCTest + +class AppVersionTest: XCTestCase { + + func testCanRetrieveInternalAppVersion() { + XCTAssertNotNil(AppVersion.fromCurrentVersion()) + } + + func testCanParseNormalVersionString() { + let version = AppVersion.from("1.0.0") + + XCTAssertNotNil(version) + XCTAssertEqual("1.0.0", version?.version) + XCTAssertEqual(nil, version?.build) + XCTAssertEqual(nil, version?.suffix) + } + + func testCanParseCaskVersionString() { + let version = AppVersion.from("1.0.0_600") + + XCTAssertNotNil(version) + XCTAssertEqual("1.0.0", version?.version) + XCTAssertEqual("600", version?.build) + XCTAssertEqual(nil, version?.suffix) + } + + func testCanParseDevVersionStringWithoutBuildNumber() { + let version = AppVersion.from("1.0.0-dev") + + XCTAssertNotNil(version) + XCTAssertEqual("1.0.0", version?.version) + XCTAssertEqual(nil, version?.build) + XCTAssertEqual("dev", version?.suffix) + } + + func testCanParseDevVersionStringWithBuildNumber() { + let version = AppVersion.from("1.0.0-dev,870") + + XCTAssertNotNil(version) + XCTAssertEqual("1.0.0", version?.version) + XCTAssertEqual("870", version?.build) + XCTAssertEqual("dev", version?.suffix) + } + + func testCanParseUnderscoresAsBuildSeparatorToo() { + let version = AppVersion.from("1.0.0-dev_870") + + XCTAssertNotNil(version) + XCTAssertEqual("1.0.0", version?.version) + XCTAssertEqual("870", version?.build) + XCTAssertEqual("dev", version?.suffix) + } + +} diff --git a/phpmon-tests/Versions/PhpVersionDetectionTest.swift b/phpmon-tests/Versions/PhpVersionDetectionTest.swift index a16dc84..ac92e33 100644 --- a/phpmon-tests/Versions/PhpVersionDetectionTest.swift +++ b/phpmon-tests/Versions/PhpVersionDetectionTest.swift @@ -3,7 +3,7 @@ // phpmon-tests // // Created by Nico Verbruggen on 01/04/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import XCTest diff --git a/phpmon-tests/Versions/ValetVersionExtractorTest.swift b/phpmon-tests/Versions/ValetVersionExtractorTest.swift index 6ce22a1..aab593c 100644 --- a/phpmon-tests/Versions/ValetVersionExtractorTest.swift +++ b/phpmon-tests/Versions/ValetVersionExtractorTest.swift @@ -3,7 +3,7 @@ // phpmon-tests // // Created by Nico Verbruggen on 29/11/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import XCTest diff --git a/phpmon-tests/Versions/VersionExtractorTest.swift b/phpmon-tests/Versions/VersionExtractorTest.swift index 872e71f..5a32ba0 100644 --- a/phpmon-tests/Versions/VersionExtractorTest.swift +++ b/phpmon-tests/Versions/VersionExtractorTest.swift @@ -3,7 +3,7 @@ // phpmon-tests // // Created by Nico Verbruggen on 16/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import XCTest diff --git a/phpmon/Common/Core/Actions.swift b/phpmon/Common/Core/Actions.swift index 6b4bef2..e8aaf5f 100644 --- a/phpmon/Common/Core/Actions.swift +++ b/phpmon/Common/Core/Actions.swift @@ -2,7 +2,7 @@ // Services.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Common/Core/Command.swift b/phpmon/Common/Core/Command.swift index 4975bbd..d7c8e90 100644 --- a/phpmon/Common/Core/Command.swift +++ b/phpmon/Common/Core/Command.swift @@ -2,7 +2,7 @@ // Command.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa diff --git a/phpmon/Common/Core/Constants.swift b/phpmon/Common/Core/Constants.swift index 2c5c7ec..affe18c 100644 --- a/phpmon/Common/Core/Constants.swift +++ b/phpmon/Common/Core/Constants.swift @@ -2,7 +2,7 @@ // Constants.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa @@ -56,13 +56,27 @@ struct Constants { static let DonationPayment = URL( string: "https://nicoverbruggen.be/sponsor#pay-now" )! + static let DonationPage = URL( string: "https://nicoverbruggen.be/sponsor" )! + static let FrequentlyAskedQuestions = URL( string: "https://github.com/nicoverbruggen/phpmon#%EF%B8%8F-faq--troubleshooting" )! + static let GitHubReleases = URL( + string: "https://github.com/nicoverbruggen/phpmon/releases" + )! + + static let StableBuildCaskFile = URL( + string: "https://raw.githubusercontent.com/nicoverbruggen/homebrew-cask/master/Casks/phpmon.rb" + )! + + static let DevBuildCaskFile = URL( + string: "https://raw.githubusercontent.com/nicoverbruggen/homebrew-cask/master/Casks/phpmon-dev.rb" + )! + } } diff --git a/phpmon/Common/Core/Helpers.swift b/phpmon/Common/Core/Helpers.swift index e9b703f..8d122c5 100644 --- a/phpmon/Common/Core/Helpers.swift +++ b/phpmon/Common/Core/Helpers.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 24/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // // MARK: Common Shell Commands diff --git a/phpmon/Common/Core/Logger.swift b/phpmon/Common/Core/Logger.swift index 172aedf..7ab6592 100644 --- a/phpmon/Common/Core/Logger.swift +++ b/phpmon/Common/Core/Logger.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 21/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Common/Core/Paths.swift b/phpmon/Common/Core/Paths.swift index 096f169..465951b 100644 --- a/phpmon/Common/Core/Paths.swift +++ b/phpmon/Common/Core/Paths.swift @@ -2,7 +2,7 @@ // Paths.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Common/Core/Shell.swift b/phpmon/Common/Core/Shell.swift index 85eee1e..3258e8d 100644 --- a/phpmon/Common/Core/Shell.swift +++ b/phpmon/Common/Core/Shell.swift @@ -2,7 +2,7 @@ // Shell.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa @@ -91,7 +91,7 @@ public class Shell { task.launch() task.waitUntilExit() - return Shell.Output( + let output = Shell.Output( standardOutput: String( data: outputPipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8 @@ -102,6 +102,12 @@ public class Shell { )!, task: task ) + + if CommandLine.arguments.contains("--v") { + log(task: task, output: output) + } + + return output } /** @@ -119,6 +125,23 @@ public class Shell { return task } + /** + Verbose logging for PHP Monitor's synchronous shell output. + */ + private func log(task: Process, output: Output) { + Log.info("") + Log.info("==== COMMAND ====") + Log.info("") + Log.info("\(self.shell) \(task.arguments?.joined(separator: " ") ?? "")") + Log.info("") + Log.info("==== OUTPUT ====") + Log.info("") + dump(output) + Log.info("") + Log.info("==== END OUTPUT ====") + Log.info("") + } + public class Output { public let standardOutput: String public let errorOutput: String diff --git a/phpmon/Common/Extensions/DateExtension.swift b/phpmon/Common/Extensions/DateExtension.swift index fb5e0c1..5481ecb 100644 --- a/phpmon/Common/Extensions/DateExtension.swift +++ b/phpmon/Common/Extensions/DateExtension.swift @@ -2,7 +2,7 @@ // Date.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa diff --git a/phpmon/Common/Extensions/NSMenuExtension.swift b/phpmon/Common/Extensions/NSMenuExtension.swift index 547142c..eeed88d 100644 --- a/phpmon/Common/Extensions/NSMenuExtension.swift +++ b/phpmon/Common/Extensions/NSMenuExtension.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 14/04/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa diff --git a/phpmon/Common/Extensions/StringExtension.swift b/phpmon/Common/Extensions/StringExtension.swift index 52860e9..74702df 100644 --- a/phpmon/Common/Extensions/StringExtension.swift +++ b/phpmon/Common/Extensions/StringExtension.swift @@ -2,7 +2,7 @@ // StringExtension.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Common/Extensions/XibLoadable.swift b/phpmon/Common/Extensions/XibLoadable.swift index e720fe4..e1cdbf9 100644 --- a/phpmon/Common/Extensions/XibLoadable.swift +++ b/phpmon/Common/Extensions/XibLoadable.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 04/02/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Common/Helpers/Alert.swift b/phpmon/Common/Helpers/Alert.swift index c08db58..8b6534a 100644 --- a/phpmon/Common/Helpers/Alert.swift +++ b/phpmon/Common/Helpers/Alert.swift @@ -2,7 +2,7 @@ // Alert.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa diff --git a/phpmon/Common/Helpers/Application.swift b/phpmon/Common/Helpers/Application.swift index d44dc7b..ad0e854 100644 --- a/phpmon/Common/Helpers/Application.swift +++ b/phpmon/Common/Helpers/Application.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 07/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Common/Helpers/Filesystem.swift b/phpmon/Common/Helpers/Filesystem.swift index 1f043b4..129763c 100644 --- a/phpmon/Common/Helpers/Filesystem.swift +++ b/phpmon/Common/Helpers/Filesystem.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 07/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa diff --git a/phpmon/Common/Helpers/LocalNotification.swift b/phpmon/Common/Helpers/LocalNotification.swift index 790bec5..51ca179 100644 --- a/phpmon/Common/Helpers/LocalNotification.swift +++ b/phpmon/Common/Helpers/LocalNotification.swift @@ -2,7 +2,7 @@ // LocalNotification.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Common/Helpers/MenuBarImageGenerator.swift b/phpmon/Common/Helpers/MenuBarImageGenerator.swift index 150ae4e..97843dc 100644 --- a/phpmon/Common/Helpers/MenuBarImageGenerator.swift +++ b/phpmon/Common/Helpers/MenuBarImageGenerator.swift @@ -2,7 +2,7 @@ // ImageGenerator.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa diff --git a/phpmon/Common/Helpers/PMWindowController.swift b/phpmon/Common/Helpers/PMWindowController.swift index d714082..f9e75b4 100644 --- a/phpmon/Common/Helpers/PMWindowController.swift +++ b/phpmon/Common/Helpers/PMWindowController.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 05/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa diff --git a/phpmon/Common/Helpers/VersionExtractor.swift b/phpmon/Common/Helpers/VersionExtractor.swift index 3c4e0b0..3f6cb06 100644 --- a/phpmon/Common/Helpers/VersionExtractor.swift +++ b/phpmon/Common/Helpers/VersionExtractor.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 16/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Common/PHP/ActivePhpInstallation.swift b/phpmon/Common/PHP/ActivePhpInstallation.swift index a423fbf..d3a4d68 100644 --- a/phpmon/Common/PHP/ActivePhpInstallation.swift +++ b/phpmon/Common/PHP/ActivePhpInstallation.swift @@ -2,7 +2,7 @@ // ActivePhpInstallation.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Common/PHP/Homebrew/HomebrewPackage.swift b/phpmon/Common/PHP/Homebrew/HomebrewPackage.swift index 150203f..79bebaa 100644 --- a/phpmon/Common/PHP/Homebrew/HomebrewPackage.swift +++ b/phpmon/Common/PHP/Homebrew/HomebrewPackage.swift @@ -2,7 +2,7 @@ // HomebrewPackage.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Common/PHP/PHP Version/PhpEnv.swift b/phpmon/Common/PHP/PHP Version/PhpEnv.swift index b74c2ce..54c36f9 100644 --- a/phpmon/Common/PHP/PHP Version/PhpEnv.swift +++ b/phpmon/Common/PHP/PHP Version/PhpEnv.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 21/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Common/PHP/PhpExtension.swift b/phpmon/Common/PHP/PhpExtension.swift index 0933af4..c6d86d7 100644 --- a/phpmon/Common/PHP/PhpExtension.swift +++ b/phpmon/Common/PHP/PhpExtension.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 31/01/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Common/PHP/PhpInstallation.swift b/phpmon/Common/PHP/PhpInstallation.swift index 9933684..61e6995 100644 --- a/phpmon/Common/PHP/PhpInstallation.swift +++ b/phpmon/Common/PHP/PhpInstallation.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 28/11/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Common/PHP/Switcher/InternalSwitcher.swift b/phpmon/Common/PHP/Switcher/InternalSwitcher.swift index bfbb103..d9a6b71 100644 --- a/phpmon/Common/PHP/Switcher/InternalSwitcher.swift +++ b/phpmon/Common/PHP/Switcher/InternalSwitcher.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 24/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Common/PHP/Switcher/PhpSwitcher.swift b/phpmon/Common/PHP/Switcher/PhpSwitcher.swift index ca89c59..d2e2bb1 100644 --- a/phpmon/Common/PHP/Switcher/PhpSwitcher.swift +++ b/phpmon/Common/PHP/Switcher/PhpSwitcher.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 24/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Domain/App/App+ActivationPolicy.swift b/phpmon/Domain/App/App+ActivationPolicy.swift index 2d512cf..31db8d6 100644 --- a/phpmon/Domain/App/App+ActivationPolicy.swift +++ b/phpmon/Domain/App/App+ActivationPolicy.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 05/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa diff --git a/phpmon/Domain/App/App+GlobalHotkey.swift b/phpmon/Domain/App/App+GlobalHotkey.swift index 9cbc7f7..5f3e237 100644 --- a/phpmon/Domain/App/App+GlobalHotkey.swift +++ b/phpmon/Domain/App/App+GlobalHotkey.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 05/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa diff --git a/phpmon/Domain/App/App.swift b/phpmon/Domain/App/App.swift index 27fa5a3..51bfc89 100644 --- a/phpmon/Domain/App/App.swift +++ b/phpmon/Domain/App/App.swift @@ -2,7 +2,7 @@ // StateManager.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa @@ -21,6 +21,16 @@ class App { return "\(version) (\(build))" } + /** Just the bundle version (build). */ + static var bundleVersion: String { + return Bundle.main.infoDictionary?["CFBundleVersion"] as! String + } + + /** Just the version number. */ + static var shortVersion: String { + return Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String + } + static var architecture: String { var systeminfo = utsname() uname(&systeminfo) diff --git a/phpmon/Domain/App/AppDelegate+InterApp.swift b/phpmon/Domain/App/AppDelegate+InterApp.swift index 7a0723a..3c1f089 100644 --- a/phpmon/Domain/App/AppDelegate+InterApp.swift +++ b/phpmon/Domain/App/AppDelegate+InterApp.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 20/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa diff --git a/phpmon/Domain/App/AppDelegate+MenuOutlets.swift b/phpmon/Domain/App/AppDelegate+MenuOutlets.swift index 80d83c4..9461de7 100644 --- a/phpmon/Domain/App/AppDelegate+MenuOutlets.swift +++ b/phpmon/Domain/App/AppDelegate+MenuOutlets.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 05/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Domain/App/AppDelegate+Notifications.swift b/phpmon/Domain/App/AppDelegate+Notifications.swift index 5315405..50dc36b 100644 --- a/phpmon/Domain/App/AppDelegate+Notifications.swift +++ b/phpmon/Domain/App/AppDelegate+Notifications.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 06/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Domain/App/AppDelegate.swift b/phpmon/Domain/App/AppDelegate.swift index 2909247..c455fff 100644 --- a/phpmon/Domain/App/AppDelegate.swift +++ b/phpmon/Domain/App/AppDelegate.swift @@ -2,7 +2,7 @@ // AppDelegate.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa @@ -67,6 +67,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele #if DEBUG logger.verbosity = .performance #endif + if CommandLine.arguments.contains("--v") { + logger.verbosity = .performance + Log.info("Extra verbose mode has been activated.") + } Log.separator(as: .info) Log.info("PHP MONITOR by Nico Verbruggen") Log.info("Version \(App.version)") diff --git a/phpmon/Domain/App/AppUpdateChecker.swift b/phpmon/Domain/App/AppUpdateChecker.swift new file mode 100644 index 0000000..4620ccd --- /dev/null +++ b/phpmon/Domain/App/AppUpdateChecker.swift @@ -0,0 +1,181 @@ +// +// Updater.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 09/05/2022. +// Copyright © 2022 Nico Verbruggen. All rights reserved. +// + +import Foundation +import AppKit + +class AppUpdateChecker { + + public static var enabled: Bool = { + return Preferences.isEnabled(.automaticBackgroundUpdateCheck) + }() + + public static var isDev: Bool = { + return App.version.contains("-dev") + }() + + public static func retrieveVersionFromCask( + _ initiatedFromBackground: Bool = true + ) -> String { + let caskFile = App.version.contains("-dev") + ? Constants.Urls.DevBuildCaskFile.absoluteString + : Constants.Urls.StableBuildCaskFile.absoluteString + + var command = "curl -s" + + if initiatedFromBackground { + command = "curl -s --max-time 5" + } + + return Shell.pipe( + "\(command) '\(caskFile)' | grep version" + ) + } + + public static func checkIfNewerVersionIsAvailable( + initiatedFromBackground: Bool = true + ) { + if initiatedFromBackground { + if !Preferences.isEnabled(.automaticBackgroundUpdateCheck) { + Log.info("Automatic updates are disabled. No check will be performed.") + return + } + + Log.info("Automatic updates are enabled, a check will be performed.") + } + + let versionString = retrieveVersionFromCask(initiatedFromBackground) + + guard let onlineVersion = AppVersion.from(versionString) else { + Log.err("We couldn't check for updates!") + + // Only notify about connection issues if the request to check for updates was explicit + if !initiatedFromBackground { + notifyAboutConnectionIssue() + } + + return + } + + let currentVersion = AppVersion.fromCurrentVersion() + + handleVersionComparison( + currentVersion, + onlineVersion, + initiatedFromBackground + ) + } + + private static func handleVersionComparison( + _ currentVersion: AppVersion, + _ onlineVersion: AppVersion, + _ background: Bool + ) { + switch onlineVersion.version.versionCompare(currentVersion.version) { + case .orderedAscending: + Log.info("You are running a newer version of PHP Monitor " + + "(\(currentVersion.computerReadable) > \(onlineVersion.computerReadable)).") + if !background { notifyVersionDoesNotNeedUpgrade() } + case .orderedDescending: + Log.info("There is a newer version (\(onlineVersion)) available! " + + "(\(onlineVersion.computerReadable) > \(currentVersion.computerReadable))") + notifyAboutNewerVersion(version: onlineVersion) + case .orderedSame: + if currentVersion.build != nil + && onlineVersion.build != nil + && buildDiffers(currentVersion, onlineVersion, background) { + return + } + + Log.info("The installed version (\(currentVersion.computerReadable)) matches the latest release " + + "(\(onlineVersion.computerReadable)).") + if !background { notifyVersionDoesNotNeedUpgrade() } + } + } + + private static func buildDiffers( + _ currentVersion: AppVersion, + _ onlineVersion: AppVersion, + _ background: Bool + ) -> Bool { + if Int(onlineVersion.build!)! > Int(currentVersion.build!)! { + Log.info("There is a newer build of PHP Monitor available! " + + "(\(onlineVersion.computerReadable) > \(currentVersion.computerReadable))") + notifyAboutNewerVersion(version: onlineVersion) + return true + } else if Int(onlineVersion.build!)! < Int(currentVersion.build!)! { + Log.info("You are running a newer build of PHP Monitor " + + "(\(currentVersion.computerReadable) > \(onlineVersion.computerReadable)).") + if !background { notifyVersionDoesNotNeedUpgrade() } + return true + } + + return false + } + + private static func notifyVersionDoesNotNeedUpgrade() { + DispatchQueue.main.async { + BetterAlert().withInformation( + title: "updater.alerts.is_latest_version.title".localized, + subtitle: "updater.alerts.is_latest_version.subtitle".localized(App.shortVersion), + description: "" + ) + .withPrimary(text: "OK") + .show() + } + } + + private static func notifyAboutNewerVersion(version: AppVersion) { + let devSuffix = isDev ? "-dev" : "" + let command = isDev ? "brew upgrade phpmon-dev" : "brew upgrade phpmon" + + DispatchQueue.main.async { + BetterAlert().withInformation( + title: "updater.alerts.newer_version_available.title".localized(version.humanReadable), + subtitle: "updater.alerts.newer_version_available.subtitle".localized, + description: HomebrewDiagnostics.customCaskInstalled + ? "updater.installation_source.brew".localized(command) + : "updater.installation_source.direct".localized + ) + .withPrimary( + text: "updater.alerts.buttons.release_notes".localized, + action: { vc in + vc.close(with: .OK) + NSWorkspace.shared.open( + Constants.Urls.GitHubReleases.appendingPathComponent("/tag/v\(version.version)\(devSuffix)") + ) + } + ) + .withTertiary(text: "Dismiss", action: { vc in + vc.close(with: .OK) + }) + .show() + } + } + + private static func notifyAboutConnectionIssue() { + DispatchQueue.main.async { + BetterAlert().withInformation( + title: "updater.errors.cannot_check_for_update.title".localized, + subtitle: "updater.errors.cannot_check_for_update.subtitle".localized, + description: "updater.errors.cannot_check_for_update.description".localized( + App.version + ) + ) + .withTertiary( + text: "updater.errors.buttons.releases_on_github".localized, + action: { _ in + NSWorkspace.shared.open(Constants.Urls.GitHubReleases) + } + ) + .withPrimary(text: "OK") + .show() + } + } + +} diff --git a/phpmon/Domain/App/AppVersion.swift b/phpmon/Domain/App/AppVersion.swift new file mode 100644 index 0000000..c554b2c --- /dev/null +++ b/phpmon/Domain/App/AppVersion.swift @@ -0,0 +1,77 @@ +// +// AppVersion.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 10/05/2022. +// Copyright © 2022 Nico Verbruggen. All rights reserved. +// + +import Foundation + +class AppVersion { + var version: String + var build: String? + var suffix: String? + + init(version: String, build: String?, suffix: String? = nil) { + self.version = version + self.build = build + self.suffix = suffix + } + + public static func from(_ string: String) -> AppVersion? { + do { + let regex = try NSRegularExpression( + pattern: #"(?(\d+)[.](\d+)([.](\d+))?)(-(?[a-z]+)){0,1}((,|_)(?\d+)){0,1}"#, + options: [] + ) + + let match = regex.matches( + in: string, + options: [], + range: NSRange(location: 0, length: string.count) + ).first + + guard let match = match else { + return nil + } + + var version: String = "" + var build: String? + var suffix: String? + + if let versionRange = Range(match.range(withName: "version"), in: string) { + version = String(string[versionRange]) + } + + if let buildRange = Range(match.range(withName: "build"), in: string) { + build = String(string[buildRange]) + } + + if let suffixRange = Range(match.range(withName: "suffix"), in: string) { + suffix = String(string[suffixRange]) + } + + return AppVersion( + version: version, + build: build, + suffix: suffix + ) + } catch { + return nil + } + } + + public static func fromCurrentVersion() -> AppVersion { + return AppVersion.from("\(App.shortVersion)_\(App.bundleVersion)")! + } + + var computerReadable: String { + return "\(version)_\(build ?? "0")" + } + + var humanReadable: String { + return "\(version) (\(build ?? "???"))" + } + +} diff --git a/phpmon/Domain/App/Startup.swift b/phpmon/Domain/App/Startup.swift index ae8f295..5016524 100644 --- a/phpmon/Domain/App/Startup.swift +++ b/phpmon/Domain/App/Startup.swift @@ -2,7 +2,7 @@ // Environment.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Domain/DomainList/AddProxyVC.swift b/phpmon/Domain/DomainList/AddProxyVC.swift index dea55cc..bd93779 100644 --- a/phpmon/Domain/DomainList/AddProxyVC.swift +++ b/phpmon/Domain/DomainList/AddProxyVC.swift @@ -63,8 +63,6 @@ class AddProxyVC: NSViewController, NSTextFieldDelegate { } @IBAction func pressedCreateProxy(_ sender: Any) { - // TODO: Validate the input before allowing proxy creation - let domain = self.inputDomainName.stringValue let proxyName = self.inputProxySubject.stringValue let secure = self.buttonSecure.state == .on ? " --secure" : "" @@ -104,18 +102,24 @@ class AddProxyVC: NSViewController, NSTextFieldDelegate { } private func validate(domain: String, proxy: String) -> Bool { - if domain.isEmpty { - textFieldError.isHidden = false - textFieldError.stringValue = "domain_list.add.errors.empty".localized - return false - } - if proxy.isEmpty { textFieldError.isHidden = false textFieldError.stringValue = "domain_list.add.errors.empty_proxy".localized return false } + if proxy.range(of: #"(http:\/\/|https:\/\/)(.+)(:)(\d+)$"#, options: .regularExpression) == nil { + textFieldError.isHidden = false + textFieldError.stringValue = "domain_list.add.errors.subject_invalid".localized + return false + } + + if domain.isEmpty { + textFieldError.isHidden = false + textFieldError.stringValue = "domain_list.add.errors.empty".localized + return false + } + if Valet.shared.sites.contains(where: { $0.name == domain }) { textFieldError.isHidden = false textFieldError.stringValue = "domain_list.add.errors.already_exists".localized @@ -130,6 +134,9 @@ class AddProxyVC: NSViewController, NSTextFieldDelegate { inputDomainName.stringValue = inputDomainName.stringValue .replacingOccurrences(of: " ", with: "-") + inputProxySubject.stringValue = inputProxySubject.stringValue + .replacingOccurrences(of: " ", with: "-") + buttonCreateProxy.isEnabled = validate( domain: inputDomainName.stringValue, proxy: inputProxySubject.stringValue diff --git a/phpmon/Domain/DomainList/Cells/DomainListCellProtocol.swift b/phpmon/Domain/DomainList/Cells/DomainListCellProtocol.swift index fa499e6..e5a3bab 100644 --- a/phpmon/Domain/DomainList/Cells/DomainListCellProtocol.swift +++ b/phpmon/Domain/DomainList/Cells/DomainListCellProtocol.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 03/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa diff --git a/phpmon/Domain/DomainList/DomainListVC+Actions.swift b/phpmon/Domain/DomainList/DomainListVC+Actions.swift index f271e41..61b01f6 100644 --- a/phpmon/Domain/DomainList/DomainListVC+Actions.swift +++ b/phpmon/Domain/DomainList/DomainListVC+Actions.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 23/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation @@ -12,6 +12,37 @@ import Cocoa extension DomainListVC { @objc func toggleSecure() { + if selected is ValetSite { + toggleSecureForSite() + } else { + toggleSecureForProxy() + } + } + + func toggleSecureForProxy() { + let originalSecureStatus = selectedProxy!.secured + let selectedProxy = selectedProxy! + + self.waitAndExecute { + // 1. Remove the original proxy + Shell.run("\(Paths.valet) unproxy \(selectedProxy.domain)", requiresPath: true) + + // 2. Add a new proxy, which is either secured/unsecured + let secure = originalSecureStatus ? "" : " --secure" + Shell.run("\(Paths.valet) proxy \(selectedProxy.domain) \(selectedProxy.target)\(secure)", + requiresPath: true) + + // 3. Restart nginx + Actions.restartNginx() + + // 4. Reload site list + DispatchQueue.main.async { + App.shared.domainListWindowController?.pressedReload(nil) + } + } + } + + func toggleSecureForSite() { let rowToReload = tableView.selectedRow let originalSecureStatus = selectedSite!.secured let action = selectedSite!.secured ? "unsecure" : "secure" @@ -122,8 +153,11 @@ extension DomainListVC { secondButtonTitle: "Cancel", style: .critical, onFirstButtonPressed: { - Shell.run("valet unlink '\(site.name)'", requiresPath: true) - self.reloadDomains() + self.waitAndExecute { + Shell.run("valet unlink '\(site.name)'", requiresPath: true) + } completion: { + self.reloadDomains() + } } ) } @@ -141,8 +175,11 @@ extension DomainListVC { secondButtonTitle: "Cancel", style: .critical, onFirstButtonPressed: { - Shell.run("valet unproxy '\(proxy.domain)'", requiresPath: true) - self.reloadDomains() + self.waitAndExecute { + Shell.run("valet unproxy '\(proxy.domain)'", requiresPath: true) + } completion: { + self.reloadDomains() + } } ) } diff --git a/phpmon/Domain/DomainList/DomainListVC+ContextMenu.swift b/phpmon/Domain/DomainList/DomainListVC+ContextMenu.swift index 84f7888..04ebb7b 100644 --- a/phpmon/Domain/DomainList/DomainListVC+ContextMenu.swift +++ b/phpmon/Domain/DomainList/DomainListVC+ContextMenu.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 10/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa @@ -43,7 +43,7 @@ extension DomainListVC { } addUnlink(to: menu, with: site) - addToggleSecure(to: menu, with: site) + addToggleSecure(to: menu, secured: site.secured) tableView.menu = menu } @@ -130,9 +130,9 @@ extension DomainListVC { } } - private func addToggleSecure(to menu: NSMenu, with site: ValetSite) { + private func addToggleSecure(to menu: NSMenu, secured: Bool) { menu.addItem( - withTitle: site.secured + withTitle: secured ? "domain_list.unsecure".localized : "domain_list.secure".localized, action: #selector(toggleSecure), @@ -146,6 +146,7 @@ extension DomainListVC { let menu = NSMenu() addOpenProxyInBrowser(to: menu) addSeparator(to: menu) + addToggleSecure(to: menu, secured: proxy.secured) addRemoveProxy(to: menu) tableView.menu = menu } diff --git a/phpmon/Domain/DomainList/DomainListVC.swift b/phpmon/Domain/DomainList/DomainListVC.swift index 4a1b186..9d8925d 100644 --- a/phpmon/Domain/DomainList/DomainListVC.swift +++ b/phpmon/Domain/DomainList/DomainListVC.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 30/03/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa diff --git a/phpmon/Domain/DomainList/DomainListWC.swift b/phpmon/Domain/DomainList/DomainListWC.swift index ed09183..6917680 100644 --- a/phpmon/Domain/DomainList/DomainListWC.swift +++ b/phpmon/Domain/DomainList/DomainListWC.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 03/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa diff --git a/phpmon/Domain/Integrations/Homebrew/HomebrewDiagnostics.swift b/phpmon/Domain/Integrations/Homebrew/HomebrewDiagnostics.swift index f8679d0..844c7c5 100644 --- a/phpmon/Domain/Integrations/Homebrew/HomebrewDiagnostics.swift +++ b/phpmon/Domain/Integrations/Homebrew/HomebrewDiagnostics.swift @@ -3,21 +3,49 @@ // PHP Monitor // // Created by Nico Verbruggen on 28/11/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation class HomebrewDiagnostics { + /** + Determines the Homebrew taps the user has installed. + */ + public static var installedTaps: [String] = { + return Shell + .pipe("\(Paths.brew) tap") + .split(separator: "\n") + .map { string in + return String(string) + } + }() + + /** + Determines whether the PHP Monitor Cask is installed. + */ + public static var customCaskInstalled: Bool = { + return installedTaps.contains("nicoverbruggen/cask") + }() + /** It is possible to have the `shivammathur/php` tap installed, and for the core homebrew information to be outdated. This will then result in two different aliases claiming to point to the same formula (`php`). This will break all linking functionality in PHP Monitor, and the user needs to be informed of this. - + This check only needs to be performed if the `shivammathur/php` tap is active. */ - public static func hasAliasConflict() -> Bool { + public static func checkForCaskConflict() { + if hasAliasConflict() { + presentAlertAboutConflict() + } + } + + /** + Check if the alias conflict as documented in `checkForCaskConflict` actually occurred. + */ + private 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") { @@ -55,7 +83,10 @@ class HomebrewDiagnostics { } } - public static func presentAlertAboutConflict() { + /** + Show this alert in case the tapped Cask does cause issues because of the conflict. + */ + private static func presentAlertAboutConflict() { DispatchQueue.main.async { BetterAlert() .withInformation( diff --git a/phpmon/Domain/Integrations/Nginx/NginxConfiguration.swift b/phpmon/Domain/Integrations/Nginx/NginxConfiguration.swift index ada62fe..e27270b 100644 --- a/phpmon/Domain/Integrations/Nginx/NginxConfiguration.swift +++ b/phpmon/Domain/Integrations/Nginx/NginxConfiguration.swift @@ -19,19 +19,30 @@ class NginxConfiguration { /** The TLD of the domain, usually derived from the name of the file. */ var tld: String - init(filePath: String) { + static func from(filePath: String) -> NginxConfiguration? { let path = filePath.replacingOccurrences( of: "~", with: "/Users/\(Paths.whoami)" ) - self.contents = try! String(contentsOfFile: path) + do { + let fileContents = try String(contentsOfFile: path) + return NginxConfiguration.init( + path: path, + contents: fileContents + ) + } catch { + Log.warn("Could not read the nginx configuration file at: `\(filePath)`") + return nil + } + } + init(path: String, contents: String) { let domain = String(path.split(separator: "/").last!) let tld = String(domain.split(separator: ".").last!) - self.domain = domain - .replacingOccurrences(of: ".\(tld)", with: "") + self.contents = contents + self.domain = domain.replacingOccurrences(of: ".\(tld)", with: "") self.tld = tld } @@ -40,7 +51,7 @@ class NginxConfiguration { */ lazy var proxy: String? = { let regex = try! NSRegularExpression( - pattern: #"proxy_pass (?.*:\d*);"#, + pattern: #"proxy_pass (?.*:\d*)(\/*);"#, options: [] ) diff --git a/phpmon/Domain/Integrations/Valet/Proxies/ProxyScanner/ValetProxyScanner.swift b/phpmon/Domain/Integrations/Valet/Proxies/ProxyScanner/ValetProxyScanner.swift index 20deb67..1941822 100644 --- a/phpmon/Domain/Integrations/Valet/Proxies/ProxyScanner/ValetProxyScanner.swift +++ b/phpmon/Domain/Integrations/Valet/Proxies/ProxyScanner/ValetProxyScanner.swift @@ -13,8 +13,8 @@ class ValetProxyScanner: ProxyScanner { return try! FileManager .default .contentsOfDirectory(atPath: directoryPath) - .map { - return NginxConfiguration.init(filePath: "\(directoryPath)/\($0)") + .compactMap { + return NginxConfiguration.from(filePath: "\(directoryPath)/\($0)") } .filter { return $0.proxy != nil diff --git a/phpmon/Domain/Integrations/Valet/Sites/ValetSite.swift b/phpmon/Domain/Integrations/Valet/Sites/ValetSite.swift index c3883bc..951ae04 100644 --- a/phpmon/Domain/Integrations/Valet/Sites/ValetSite.swift +++ b/phpmon/Domain/Integrations/Valet/Sites/ValetSite.swift @@ -226,8 +226,8 @@ class ValetSite: DomainListable { public static func isolatedVersion(_ filePath: String) -> String? { if Filesystem.fileExists(filePath) { return NginxConfiguration - .init(filePath: filePath) - .isolatedVersion + .from(filePath: filePath)? + .isolatedVersion ?? nil } return nil diff --git a/phpmon/Domain/Integrations/Valet/Valet.swift b/phpmon/Domain/Integrations/Valet/Valet.swift index 5028f96..7c8b6bd 100644 --- a/phpmon/Domain/Integrations/Valet/Valet.swift +++ b/phpmon/Domain/Integrations/Valet/Valet.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 29/11/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Domain/Menu/HeaderView.swift b/phpmon/Domain/Menu/HeaderView.swift index c7303cb..eb245e1 100644 --- a/phpmon/Domain/Menu/HeaderView.swift +++ b/phpmon/Domain/Menu/HeaderView.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 04/02/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Domain/Menu/MainMenu+Startup.swift b/phpmon/Domain/Menu/MainMenu+Startup.swift index ce287f0..43badf9 100644 --- a/phpmon/Domain/Menu/MainMenu+Startup.swift +++ b/phpmon/Domain/Menu/MainMenu+Startup.swift @@ -29,6 +29,12 @@ extension MainMenu { When the environment is all clear and the app can run, let's go. */ private func onEnvironmentPass() { + // Determine install method + Log.info(HomebrewDiagnostics.customCaskInstalled + ? "The app has probably been installed via Homebrew Cask." + : "The app has probably been installed directly." + ) + // Attempt to find out more info about Valet if Valet.shared.version != nil { Log.info("PHP Monitor has extracted the version number of Valet: \(Valet.shared.version!)") @@ -41,9 +47,7 @@ extension MainMenu { PhpEnv.detectPhpVersions() // Check for an alias conflict - if HomebrewDiagnostics.hasAliasConflict() { - HomebrewDiagnostics.presentAlertAboutConflict() - } + HomebrewDiagnostics.checkForCaskConflict() updatePhpVersionInStatusBar() @@ -86,8 +90,6 @@ extension MainMenu { NotificationCenter.default.post(name: Events.ServicesUpdated, object: nil) - Log.info("PHP Monitor is ready to serve!") - // Schedule a request to fetch the PHP version every 60 seconds DispatchQueue.main.async { [self] in App.shared.timer = Timer.scheduledTimer( @@ -101,6 +103,12 @@ extension MainMenu { Stats.incrementSuccessfulLaunchCount() Stats.evaluateSponsorMessageShouldBeDisplayed() + + DispatchQueue.global(qos: .utility).async { + AppUpdateChecker.checkIfNewerVersionIsAvailable() + } + + Log.info("PHP Monitor is ready to serve!") } /** diff --git a/phpmon/Domain/Menu/MainMenu.swift b/phpmon/Domain/Menu/MainMenu.swift index 63cc9da..69fb17b 100644 --- a/phpmon/Domain/Menu/MainMenu.swift +++ b/phpmon/Domain/Menu/MainMenu.swift @@ -2,7 +2,7 @@ // MainMenu.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa @@ -337,6 +337,12 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate, PhpSwitcherDelegate NSApplication.shared.terminate(nil) } + @objc func checkForUpdates() { + DispatchQueue.global(qos: .userInitiated).async { + AppUpdateChecker.checkIfNewerVersionIsAvailable(initiatedFromBackground: false) + } + } + // MARK: - Menu Delegate func menuWillOpen(_ menu: NSMenu) { diff --git a/phpmon/Domain/Menu/ServicesView.swift b/phpmon/Domain/Menu/ServicesView.swift index 1b2e6a6..36f099c 100644 --- a/phpmon/Domain/Menu/ServicesView.swift +++ b/phpmon/Domain/Menu/ServicesView.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 04/02/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Domain/Menu/StatsView.swift b/phpmon/Domain/Menu/StatsView.swift index 896184f..1cce675 100644 --- a/phpmon/Domain/Menu/StatsView.swift +++ b/phpmon/Domain/Menu/StatsView.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 04/02/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Domain/Menu/StatusMenu.swift b/phpmon/Domain/Menu/StatusMenu.swift index 31b2447..1647d51 100644 --- a/phpmon/Domain/Menu/StatusMenu.swift +++ b/phpmon/Domain/Menu/StatusMenu.swift @@ -2,7 +2,7 @@ // MainMenuBuilder.swift // PHP Monitor // -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa @@ -74,15 +74,16 @@ 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.separator()) + self.addItem(NSMenuItem(title: "mi_preferences".localized, + action: #selector(MainMenu.openPrefs), keyEquivalent: ",")) + self.addItem(NSMenuItem(title: "mi_check_for_updates".localized, + action: #selector(MainMenu.checkForUpdates), keyEquivalent: "")) + self.addItem(NSMenuItem.separator()) + 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 diff --git a/phpmon/Domain/Notice/BetterAlertVC.swift b/phpmon/Domain/Notice/BetterAlertVC.swift index a275f57..9f4797f 100644 --- a/phpmon/Domain/Notice/BetterAlertVC.swift +++ b/phpmon/Domain/Notice/BetterAlertVC.swift @@ -65,7 +65,7 @@ class BetterAlertVC: NSViewController { } @IBAction func tertiaryButtonAction(_ sender: Any) { - if self.actionSecondary != nil { + if self.actionTertiary != nil { self.actionTertiary!(self) } } diff --git a/phpmon/Domain/PHP/ActivePhpInstallation+Checks.swift b/phpmon/Domain/PHP/ActivePhpInstallation+Checks.swift index 108a930..fb30e73 100644 --- a/phpmon/Domain/PHP/ActivePhpInstallation+Checks.swift +++ b/phpmon/Domain/PHP/ActivePhpInstallation+Checks.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 21/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Domain/Preferences/Keybinds/GlobalKeybindPreference.swift b/phpmon/Domain/Preferences/Keybinds/GlobalKeybindPreference.swift index 5013ba1..7d3dccc 100644 --- a/phpmon/Domain/Preferences/Keybinds/GlobalKeybindPreference.swift +++ b/phpmon/Domain/Preferences/Keybinds/GlobalKeybindPreference.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 15/04/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Domain/Preferences/Preferences.swift b/phpmon/Domain/Preferences/Preferences.swift index c20ceef..96b7937 100644 --- a/phpmon/Domain/Preferences/Preferences.swift +++ b/phpmon/Domain/Preferences/Preferences.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 30/03/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation @@ -20,6 +20,7 @@ enum PreferenceName: String { case autoComposerGlobalUpdateAfterSwitch = "auto_composer_global_update_after_switch" case allowProtocolForIntegrations = "allow_protocol_for_integrations" case globalHotkey = "global_hotkey" + case automaticBackgroundUpdateCheck = "backgroundUpdateCheck" } /** @@ -76,6 +77,7 @@ class Preferences { PreferenceName.autoServiceRestartAfterExtensionToggle.rawValue: true, PreferenceName.autoComposerGlobalUpdateAfterSwitch.rawValue: false, PreferenceName.allowProtocolForIntegrations.rawValue: true, + PreferenceName.automaticBackgroundUpdateCheck.rawValue: true, /// Stats InternalStats.switchCount.rawValue: 0, InternalStats.launchCount.rawValue: 0, @@ -145,6 +147,8 @@ class Preferences { forKey: PreferenceName.autoComposerGlobalUpdateAfterSwitch.rawValue) as Any, .allowProtocolForIntegrations: UserDefaults.standard.bool( forKey: PreferenceName.allowProtocolForIntegrations.rawValue) as Any, + .automaticBackgroundUpdateCheck: UserDefaults.standard.bool( + forKey: PreferenceName.automaticBackgroundUpdateCheck.rawValue) as Any, // Part 2: Always Strings .globalHotkey: UserDefaults.standard.string( diff --git a/phpmon/Domain/Preferences/PrefsVC.swift b/phpmon/Domain/Preferences/PrefsVC.swift index 76b330b..c7689cf 100644 --- a/phpmon/Domain/Preferences/PrefsVC.swift +++ b/phpmon/Domain/Preferences/PrefsVC.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 30/03/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa @@ -53,7 +53,8 @@ class PrefsVC: NSViewController { getAutoRestartPreferenceView(), getAutomaticComposerUpdatePreferenceView(), getShortcutPreferenceView(), - getIntegrationsPreferenceView() + getIntegrationsPreferenceView(), + getAutomaticUpdateCheckPreferenceView() ].forEach({ self.stackView.addArrangedSubview($0) }) } @@ -133,6 +134,16 @@ class PrefsVC: NSViewController { ) } + private func getAutomaticUpdateCheckPreferenceView() -> NSView { + return CheckboxPreferenceView.make( + sectionText: "prefs.updates".localized, + descriptionText: "prefs.automatic_update_check_desc".localized, + checkboxText: "prefs.automatic_update_check_title".localized, + preference: .automaticBackgroundUpdateCheck, + action: {} + ) + } + // MARK: - Listening for hotkey delegate var listeningForHotkeyView: HotkeyPreferenceView? diff --git a/phpmon/Domain/Preferences/PrefsWC.swift b/phpmon/Domain/Preferences/PrefsWC.swift index 4d3b24c..f40e6de 100644 --- a/phpmon/Domain/Preferences/PrefsWC.swift +++ b/phpmon/Domain/Preferences/PrefsWC.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 02/04/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Cocoa diff --git a/phpmon/Domain/Preferences/Views/CheckboxPreferenceView.swift b/phpmon/Domain/Preferences/Views/CheckboxPreferenceView.swift index 04a7aad..6f4ea52 100644 --- a/phpmon/Domain/Preferences/Views/CheckboxPreferenceView.swift +++ b/phpmon/Domain/Preferences/Views/CheckboxPreferenceView.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 17/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Domain/Preferences/Views/HotkeyPreferenceView.swift b/phpmon/Domain/Preferences/Views/HotkeyPreferenceView.swift index 5bc3deb..bdf9a36 100644 --- a/phpmon/Domain/Preferences/Views/HotkeyPreferenceView.swift +++ b/phpmon/Domain/Preferences/Views/HotkeyPreferenceView.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 17/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Domain/Progress/ProgressWindow.swift b/phpmon/Domain/Progress/ProgressWindow.swift index e660f93..3cf5388 100644 --- a/phpmon/Domain/Progress/ProgressWindow.swift +++ b/phpmon/Domain/Progress/ProgressWindow.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 18/12/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Domain/SwiftUI/PMHeaderView.swift b/phpmon/Domain/SwiftUI/PMHeaderView.swift index 8beaf30..26526db 100644 --- a/phpmon/Domain/SwiftUI/PMHeaderView.swift +++ b/phpmon/Domain/SwiftUI/PMHeaderView.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 15/04/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import SwiftUI diff --git a/phpmon/Domain/SwiftUI/PMServicesView.swift b/phpmon/Domain/SwiftUI/PMServicesView.swift index d3e9418..ead38a4 100644 --- a/phpmon/Domain/SwiftUI/PMServicesView.swift +++ b/phpmon/Domain/SwiftUI/PMServicesView.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 15/04/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import SwiftUI diff --git a/phpmon/Domain/SwiftUI/PMStatsView.swift b/phpmon/Domain/SwiftUI/PMStatsView.swift index 078c463..95b3c72 100644 --- a/phpmon/Domain/SwiftUI/PMStatsView.swift +++ b/phpmon/Domain/SwiftUI/PMStatsView.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 15/04/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import SwiftUI diff --git a/phpmon/Domain/SwiftUI/Preview.swift b/phpmon/Domain/SwiftUI/Preview.swift index ffd3eb8..a0b673a 100644 --- a/phpmon/Domain/SwiftUI/Preview.swift +++ b/phpmon/Domain/SwiftUI/Preview.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 15/04/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import SwiftUI diff --git a/phpmon/Domain/Watcher/App+ConfigWatch.swift b/phpmon/Domain/Watcher/App+ConfigWatch.swift index cedc858..6c57a9b 100644 --- a/phpmon/Domain/Watcher/App+ConfigWatch.swift +++ b/phpmon/Domain/Watcher/App+ConfigWatch.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 30/03/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/Domain/Watcher/PhpConfigWatcher.swift b/phpmon/Domain/Watcher/PhpConfigWatcher.swift index b9a0084..b3ad98d 100644 --- a/phpmon/Domain/Watcher/PhpConfigWatcher.swift +++ b/phpmon/Domain/Watcher/PhpConfigWatcher.swift @@ -3,7 +3,7 @@ // PHP Monitor // // Created by Nico Verbruggen on 30/03/2021. -// Copyright © 2021 Nico Verbruggen. All rights reserved. +// Copyright © 2022 Nico Verbruggen. All rights reserved. // import Foundation diff --git a/phpmon/IAP/InternetAccessPolicy.plist b/phpmon/IAP/InternetAccessPolicy.plist index a6582ff..5d5a97c 100644 --- a/phpmon/IAP/InternetAccessPolicy.plist +++ b/phpmon/IAP/InternetAccessPolicy.plist @@ -10,6 +10,22 @@ https://github.com/nicoverbruggen/phpmon Connections + + IsIncoming + + Host + raw.githubusercontent.com + NetworkProtocol + TCP + Port + 80, 443 + Relevance + Essential + Purpose + PHP Monitor connects to GitHub to check the Cask file to determine what the latest release of PHP Monitor is. + DenyConsequences + If you deny this connection, PHP Monitor will not be able to search for updates. If you don't want this check to happen, you can disable automatic updates in the Preferences menu instead. + IsIncoming diff --git a/phpmon/Localizable.strings b/phpmon/Localizable.strings index 481c5a9..cd918c6 100644 --- a/phpmon/Localizable.strings +++ b/phpmon/Localizable.strings @@ -3,7 +3,7 @@ PHP Monitor Created by Nico Verbruggen on 16/05/2020. - Copyright © 2020 Nico Verbruggen. All rights reserved. + Copyright © 2022 Nico Verbruggen. All rights reserved. */ // MENU ITEMS (MI) @@ -59,6 +59,7 @@ "mi_preferences" = "Preferences..."; "mi_donate" = "Donate..."; +"mi_check_for_updates" = "Check for Updates..."; "mi_quit" = "Quit PHP Monitor"; "mi_about" = "About PHP Monitor"; @@ -105,7 +106,7 @@ // ADD PROXY TO DOMAINS LIST "domain_list.add.set_up_proxy" = "Set up a Proxy"; -"domain_list.add.proxy_subject" = "Proxy subject (usually: protocol, IP address and port)"; +"domain_list.add.proxy_subject" = "Proxy subject (must include protocol and port)"; "domain_list.add.domain_name" = "Domain name"; "domain_list.add.create_proxy" = "Create Proxy"; "domain_list.add.proxy_available" = "%@ will be proxied and will be available via: %@://%@.%@"; @@ -123,6 +124,7 @@ "domain_list.add.empty_fields" = "One or more fields are empty. Please fill all required fields."; "domain_list.add.errors.empty" = "You must enter a domain name."; "domain_list.add.errors.empty_proxy" = "You must enter what will be proxied."; +"domain_list.add.errors.subject_invalid" = "The subject you've entered is not valid.\nYou must include the protocol and port."; "domain_list.add.errors.already_exists" = "A link with that name already exists."; // ADD SITE ERROR: FOLDER MISSING SINCE SELECTION @@ -183,6 +185,7 @@ "prefs.services" = "Services:"; "prefs.switcher" = "Switcher:"; "prefs.integrations" = "Integrations:"; +"prefs.updates" = "Updates:"; "prefs.icon_options.php" = "Display PHP Icon"; "prefs.icon_options.elephant" = "Display Elephant Icon"; @@ -204,6 +207,9 @@ "prefs.open_protocol_title" = "Allow third-party integrations"; "prefs.open_protocol_desc" = "When checked, this will allow the interaction with third party utilities to work (e.g. Alfred, Raycast). If you disable this, PHP Monitor will still receive the commands, but will not act upon them."; + +"prefs.automatic_update_check_title" = "Automatically check for updates"; +"prefs.automatic_update_check_desc" = "When checked, PHP Monitor will automatically check if there is a newer version available, and notify you if that is the case."; "prefs.shortcut_set" = "Set global shortcut"; "prefs.shortcut_listening" = ""; @@ -372,6 +378,23 @@ You can do this by running `composer global update` in your terminal. After that "alert.errors.homebrew_permissions.applescript_returned_nil.title" = "Restore Homebrew Permissions has been cancelled."; "alert.errors.homebrew_permissions.applescript_returned_nil.description" = "The outcome of the script that is executed to adjust the permissions returned nil, which usually means that you did not grant administrative permissions to PHP Monitor.\n\nIf you clicked on Cancel during the authentication prompt, this is normal. If you did actually authenticate and you are still seeing this message, something probably went wrong."; +// CHECK FOR UPDATES + +"updater.alerts.newer_version_available.title" = "PHP Monitor v%@ is now available!"; +"updater.alerts.newer_version_available.subtitle" = "Keeping PHP Monitor up-to-date is highly recommended, since newer versions usually fix bugs and include fixes to support the latest versions of Valet and PHP."; +"updater.alerts.newer_version_available.description" = "PHP Monitor is supposed to be updated via Homebrew, so there is no built-in updater. This check is only meant to inform you of the existence of a new version, you do not need to upgrade."; +"updater.installation_source.brew" = "You appear to have installed PHP Monitor via Homebrew (or have at least tapped the required Caskfile) so it is recommended that you upgrade via the terminal by running `%@`."; +"updater.installation_source.direct" = "You do not appear to have installed PHP Monitor via Homebrew, so you will need to visit GitHub to download the latest update."; +"updater.alerts.buttons.release_notes" = "View Release Notes"; + +"updater.alerts.is_latest_version.title" = "PHP Monitor is up-to-date!"; +"updater.alerts.is_latest_version.subtitle" = "The currently installed version (v%@) is up-to-date.\nThere is no newer version available."; + +"updater.alerts.cannot_check_for_update.title" = "PHP Monitor could not determine if a newer version is available."; +"updater.alerts.cannot_check_for_update.subtitle" = "You might not be connected to the internet, are blocking traffic or GitHub is down and won't allow you to check for updates. If you keep seeing this message, you may want to manually check the releases page."; +"updater.alerts.cannot_check_for_update.description" = "The currently installed version is: %@. You can go to the list of the latest releases (on GitHub) by clicking on the button on the left."; +"updater.alerts.buttons.releases_on_github" = "View Releases"; + // WARNINGS ABOUT NON-DEFAULT TLD "alert.warnings.tld_issue.title" = "You are not using `.test` as the TLD for Valet.";