1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2025-08-07 20:10:08 +02:00

Compare commits

...

12 Commits
v2.0 ... v2.2

Author SHA1 Message Date
1617b57b1e 🚀 Version 2.2
Merge branch 'develop'

* develop:
  📝 Update README
  📝 Amend modal copy
  🐛 Improved startup procedure
  🚧 Add Internet Access Policy
   Add shared scheme
2020-07-16 19:37:21 +02:00
33825e7b66 📝 Update README 2020-07-16 19:34:38 +02:00
464b7106b2 📝 Amend modal copy 2020-07-16 19:29:01 +02:00
0cf85f9958 🐛 Improved startup procedure
- First issue encountered will notify the user
- User has the option to Retry or Terminate the app
- Retry will go through launch checks again
- Some issues are marked as non-breaking, meaning the user will be
  notified, but the app will just start as usual
2020-07-16 19:26:29 +02:00
00cf2bc360 🚧 Add Internet Access Policy 2020-07-11 11:18:31 +02:00
dbb5329908 Add shared scheme 2020-07-11 10:54:05 +02:00
9fd8e7042a 🚀 Version 2.1
Merge branch 'develop'

* develop:
  📝 Add installation instructions
  📝 Added docs for release procedure
  📝 Updated README
  🔧 Hardened runtime (required for notarization)
  🍱 Updated icon for macOS 11 style, updated alert
2020-07-11 10:41:11 +02:00
cb62a20f2a 📝 Add installation instructions 2020-07-11 10:40:02 +02:00
bb1742a390 📝 Added docs for release procedure 2020-07-11 10:05:47 +02:00
6db43beddf 📝 Updated README 2020-07-11 01:07:51 +02:00
7e2c7cdd59 🔧 Hardened runtime (required for notarization) 2020-07-11 01:00:31 +02:00
e76dd0daeb 🍱 Updated icon for macOS 11 style, updated alert 2020-07-11 00:49:32 +02:00
22 changed files with 419 additions and 139 deletions

View File

@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
C405A4D024B9B9140062FAFA /* InternetAccessPolicy.strings in Resources */ = {isa = PBXBuildFile; fileRef = C405A4CE24B9B9130062FAFA /* InternetAccessPolicy.strings */; };
C405A4D124B9B9140062FAFA /* InternetAccessPolicy.plist in Resources */ = {isa = PBXBuildFile; fileRef = C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */; };
C41C1B3722B0097F00E7CF16 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B3622B0097F00E7CF16 /* AppDelegate.swift */; };
C41C1B3B22B0098000E7CF16 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C41C1B3A22B0098000E7CF16 /* Assets.xcassets */; };
C41C1B3E22B0098000E7CF16 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C41C1B3C22B0098000E7CF16 /* Main.storyboard */; };
@ -27,6 +29,8 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
C405A4CE24B9B9130062FAFA /* InternetAccessPolicy.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = InternetAccessPolicy.strings; sourceTree = "<group>"; };
C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = InternetAccessPolicy.plist; sourceTree = "<group>"; };
C41C1B3322B0097F00E7CF16 /* PHP Monitor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "PHP Monitor.app"; sourceTree = BUILT_PRODUCTS_DIR; };
C41C1B3622B0097F00E7CF16 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
C41C1B3A22B0098000E7CF16 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@ -61,6 +65,15 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
C405A4CD24B9B9070062FAFA /* IAP */ = {
isa = PBXGroup;
children = (
C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */,
C405A4CE24B9B9130062FAFA /* InternetAccessPolicy.strings */,
);
path = IAP;
sourceTree = "<group>";
};
C41C1B2A22B0097F00E7CF16 = {
isa = PBXGroup;
children = (
@ -91,6 +104,7 @@
C41C1B4022B0098000E7CF16 /* phpmon.entitlements */,
C41C1B3A22B0098000E7CF16 /* Assets.xcassets */,
C473319E2470923A009A0597 /* Localizable.strings */,
C405A4CD24B9B9070062FAFA /* IAP */,
);
path = phpmon;
sourceTree = "<group>";
@ -220,7 +234,9 @@
files = (
C41C1B3B22B0098000E7CF16 /* Assets.xcassets in Resources */,
C41C1B3E22B0098000E7CF16 /* Main.storyboard in Resources */,
C405A4D124B9B9140062FAFA /* InternetAccessPolicy.plist in Resources */,
C473319F2470923A009A0597 /* Localizable.strings in Resources */,
C405A4D024B9B9140062FAFA /* InternetAccessPolicy.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -382,19 +398,21 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = phpmon/phpmon.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 22;
DEVELOPMENT_TEAM = "";
CURRENT_PROJECT_VERSION = 24;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = phpmon/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 2.0;
MARKETING_VERSION = 2.2;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
name = Debug;
@ -404,19 +422,21 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = phpmon/phpmon.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 22;
DEVELOPMENT_TEAM = "";
CURRENT_PROJECT_VERSION = 24;
DEVELOPMENT_TEAM = 8M54J5J787;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = phpmon/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 2.0;
MARKETING_VERSION = 2.2;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
name = Release;

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1150"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C41C1B3222B0097F00E7CF16"
BuildableName = "PHP Monitor.app"
BlueprintName = "PHP Monitor"
ReferencedContainer = "container:PHP Monitor.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C41C1B3222B0097F00E7CF16"
BuildableName = "PHP Monitor.app"
BlueprintName = "PHP Monitor"
ReferencedContainer = "container:PHP Monitor.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C41C1B3222B0097F00E7CF16"
BuildableName = "PHP Monitor.app"
BlueprintName = "PHP Monitor"
ReferencedContainer = "container:PHP Monitor.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,5 +1,7 @@
# PHP Monitor
<img src="./phpmon/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png" alt="phpmon icon" width="128px" />
PHP Monitor (or phpmon) is a lightweight macOS utility app that runs on your Mac and displays the active PHP version in your status bar.
It also gives you quick access to various useful functionality (like switching PHP versions, restarting services, accessing configuration files, and more).
@ -10,21 +12,30 @@ For me, it comes in handy when running multiple versions of PHP with Homebrew. I
It's also super convenient to and switch between versions.
## System requirements
## 🖥 System requirements
* macOS 10.15 Catalina
* macOS 10.15 Catalina or higher (works on macOS 11 Big Sur)
* PHP 7.4 installed with Homebrew 2.x
* Laravel Valet 2.x
_Please note that future versions of PHP will not work automatically, minor changes are required to add support for newer versions of PHP._
## Why I built this
## 🚀 How to install
You can install via Homebrew, or may download the latest [release](https://github.com/nicoverbruggen/phpmon/releases).
To install via Homebrew, run:
brew tap nicoverbruggen/homebrew-cask
brew cask install phpmon
## 👨‍💻 Why I built this
I wanted to be able to see at a glance which version of PHP was linked, and handle dealing with Laravel Valet in a simple app without having to deal with the terminal every time.
Initially, I had an Alfred workflow for this. But this does the job as well, while also showing me at all times which version of PHP is linked (which is the main benefit over e.g. an Alfred workflow).
## How it works
## 🚜 How it works
### Version detection
@ -54,12 +65,10 @@ If you want to know more about how this works, I recommend you check out the sou
This app isn't very complicated after all. In the end, this just (conveniently) executes some shell commands.
## Troubleshooting
## 🤬 Troubleshooting
**If you are having issues, the first thing you should be doing is installing the latest version of PHP Monitor. This can resolve a variety of issues.**
### Reasons for alerts at startup
PHP Monitor performs some integrity checks to ensure a good experience when using the app. You'll get a message telling you that PHP Monitor won't work correctly in the following scenarios:
- The PHP binary is not located in `/usr/local/bin/php`
@ -71,65 +80,10 @@ PHP Monitor performs some integrity checks to ensure a good experience when usin
Follow instructions as specified in the alert in order to resolve any issues.
### Additional troubleshooting
## 📝 Additional information
#### Q: I want PHP Monitor to start up when I boot my Mac!
Please consult the [additional information](docs/ADDITIONAL.md) file that contains more information.
You can do this by dragging *PHP Monitor.app* into the **Login Items** section in **System Preferences > Users & Groups** for your account.
Super convenient!
#### Q: PHP Monitor says that the latest version of PHP is not installed, but it is!
Try installing again using `brew install php@7.4`.
This should resolve the issue.
#### Q: PHP Monitor reports another version compared to phpinfo on my local website, what is going on?
_Beginning with version 2.0 you'll get alerts about this at startup._
If you're still seeing another version of PHP in your scripts running on your local webserver (nginx) — e.g. when running `phpinfo()` — I recommend you shut down all PHP services that are currently active. You can find out what services are active by running:
sudo brew services list | grep php
This will present to you a list of services, like so (depending on the installed versions of PHP):
```
php started root /Library/LaunchDaemons/homebrew.mxcl.php.plist
php@5.6 stopped
php@7.0 stopped
php@7.1 stopped
php@7.2 stopped
php@7.3 stopped
```
You'll want to make sure that **only one service is running** and that it is running **as `root`**. You can terminate a service by running:
sudo brew services stop {service_name}
So in order to disable PHP 7.3, you'd need to run:
sudo brew services stop php@7.3
If you notice that PHP FPM is running as your own user account, you can turn off the service by running:
brew services stop php@7.3
The easiest way to make sure that PHP Monitor works again is to run the following commands:
sudo brew services stop php
sudo brew services stop php@7.3
sudo brew services stop php@7.2
sudo brew services stop php@7.1
sudo brew services stop php@7.0
sudo brew services stop php@5.6
sudo brew services stop nginx
Then, in PHP Monitor, select "Restart php-fpm service", which should start the service.
Alternatively, you can run `sudo brew services start php@7.4` where `7.4` is your preferred version of PHP (for the latest version of PHP, you may omit `@7.4` like in the example above).
---
## ⭐️ Is this helpful?
If this software has been useful to you, star the repository so I know that the software is being used. I did not include any tracking or analytics software, so if you encounter issues, let me know via an issue.

Binary file not shown.

99
docs/ADDITIONAL.md Normal file
View File

@ -0,0 +1,99 @@
### Q&A
#### Q: This app is doing network requests?
It's Homebrew. I can't prevent `brew` from doing things via the network when I invoke it.
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.
#### Q: How can I set this up on a fresh Mac?
If you want to set up your computer for the very first time, here's how I do it:
Install [Homebrew](https://brew.sh) first.
Install PHP, composer, add to path:
brew install php
brew install composer
nano .zshrc
Make sure the following line is not in the comments:
export PATH=$HOME/bin:/usr/local/bin:$PATH
and add the following to your .zshrc:
export PATH=$HOME/bin:~/.composer/vendor/bin:$PATH
Make sure PHP is linked correctly:
which php
should return: `/usr/local/bin/php`
composer global require laravel/valet
valet install
This should install `dnsmasq` and set up Valet. Great, almost there!
valet trust
Finally, run PHP Monitor. Since the app is notarized and signed with a developer ID, it should work.
#### Q: I want PHP Monitor to start up when I boot my Mac!
You can do this by dragging *PHP Monitor.app* into the **Login Items** section in **System Preferences > Users & Groups** for your account.
Super convenient!
#### Q: PHP Monitor says that the latest version of PHP is not installed, but it is!
Try installing again using `brew install php@7.4`.
This should resolve the issue.
#### Q: PHP Monitor reports another version compared to phpinfo on my local website, what is going on?
_Beginning with version 2.0 you'll get alerts about this at startup._
If you're still seeing another version of PHP in your scripts running on your local webserver (nginx) — e.g. when running `phpinfo()` — I recommend you shut down all PHP services that are currently active. You can find out what services are active by running:
sudo brew services list | grep php
This will present to you a list of services, like so (depending on the installed versions of PHP):
```
php started root /Library/LaunchDaemons/homebrew.mxcl.php.plist
php@5.6 stopped
php@7.0 stopped
php@7.1 stopped
php@7.2 stopped
php@7.3 stopped
```
You'll want to make sure that **only one service is running** and that it is running **as `root`**. You can terminate a service by running:
sudo brew services stop {service_name}
So in order to disable PHP 7.3, you'd need to run:
sudo brew services stop php@7.3
If you notice that PHP FPM is running as your own user account, you can turn off the service by running:
brew services stop php@7.3
The easiest way to make sure that PHP Monitor works again is to run the following commands:
sudo brew services stop php
sudo brew services stop php@7.3
sudo brew services stop php@7.2
sudo brew services stop php@7.1
sudo brew services stop php@7.0
sudo brew services stop php@5.6
sudo brew services stop nginx
Then, in PHP Monitor, select "Restart php-fpm service", which should start the service.
Alternatively, you can run `sudo brew services start php@7.4` where `7.4` is your preferred version of PHP (for the latest version of PHP, you may omit `@7.4` like in the example above).

13
docs/RELEASE.md Normal file
View File

@ -0,0 +1,13 @@
# Release Procedure
1. Merge into `master`
2. Create tag
3. Add changes to changelog
4. Archive
5. Notarize and prepare for own distribution
6. After notarization, export .app
7. Create zipped version
8. Calculate SHA256: `openssl dgst -sha256 phpmon-2.x.zip`
9. Upload to GitHub
10. Update Cask
11. Check new version can be installed via Cask

View File

@ -1,68 +1,68 @@
{
"images" : [
{
"size" : "16x16",
"idiom" : "mac",
"filename" : "icon_16x16.png",
"scale" : "1x"
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"size" : "16x16",
"idiom" : "mac",
"filename" : "icon_16x16@2x.png",
"scale" : "2x"
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"size" : "32x32",
"idiom" : "mac",
"filename" : "icon_32x32.png",
"scale" : "1x"
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"size" : "32x32",
"idiom" : "mac",
"filename" : "icon_32x32@2x.png",
"scale" : "2x"
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"size" : "128x128",
"idiom" : "mac",
"filename" : "icon_128x128.png",
"scale" : "1x"
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"size" : "128x128",
"idiom" : "mac",
"filename" : "icon_128x128@2x.png",
"scale" : "2x"
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"size" : "256x256",
"idiom" : "mac",
"filename" : "icon_256x256.png",
"scale" : "1x"
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"size" : "256x256",
"idiom" : "mac",
"filename" : "icon_256x256@2x.png",
"scale" : "2x"
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "icon_512x512.png",
"scale" : "1x"
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "icon_512x512@2x.png",
"scale" : "2x"
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 647 B

After

Width:  |  Height:  |  Size: 714 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 422 KiB

After

Width:  |  Height:  |  Size: 315 KiB

View File

@ -10,62 +10,102 @@ import Foundation
class Startup {
public static func checkEnvironment()
public var failed : Bool = false
public var failureCallback = {}
/**
Checks the user's environment and checks if PHP Monitor can be used properly.
This checks if PHP is installed, Valet is running, the appropriate permissions are set, and more.
- Parameter success: Callback that is fired if the application can proceed with launch
- Parameter failure: Callback that is fired if the application must retry launch
*/
public func checkEnvironment(success: () -> Void, failure: @escaping () -> Void)
{
self.presentAlertOnMainThreadIf(
self.failureCallback = failure
self.performEnvironmentCheck(
!Shell.user.pipe("which php").contains("/usr/local/bin/php"),
messageText: "PHP is not correctly installed",
informativeText: "You must install PHP via brew. Try running `which php` in Terminal, it should return `/usr/local/bin/php`. The app will not work correctly until you resolve this issue. (Usually `brew link php` resolves this issue.)"
informativeText: "You must install PHP via brew. Try running `which php` in Terminal, it should return `/usr/local/bin/php`. The app will not work correctly until you resolve this issue. (Usually `brew link php` resolves this issue.)",
breaking: true
)
self.presentAlertOnMainThreadIf(
self.performEnvironmentCheck(
!Shell.user.pipe("ls /usr/local/opt | grep php@7.4").contains("php@7.4"),
messageText: "PHP 7.4 is not correctly installed",
informativeText: "PHP 7.4 alias was not found in `/usr/local/opt`. The app will not work correctly until you resolve this issue. If you already have the `php` formula installed, you may need to run `brew install php@7.4` in order for PHP Monitor to detect this installation."
informativeText: "PHP 7.4 alias was not found in `/usr/local/opt`. The app will not work correctly until you resolve this issue. If you already have the `php` formula installed, you may need to run `brew install php@7.4` in order for PHP Monitor to detect this installation.",
breaking: true
)
self.presentAlertOnMainThreadIf(
self.performEnvironmentCheck(
!Shell.user.pipe("which valet").contains("/usr/local/bin/valet"),
messageText: "Laravel Valet is not correctly installed",
informativeText: "You must install Valet via brew. Try running `which valet` in Terminal, it should return `/usr/local/bin/valet`. The app will not work correctly until you resolve this issue."
informativeText: "You must install Valet with composer. Try running `which valet` in Terminal, it should return `/usr/local/bin/valet`. The app will not work correctly until you resolve this issue.",
breaking: true
)
self.presentAlertOnMainThreadIf(
self.performEnvironmentCheck(
!Shell.user.pipe("cat /private/etc/sudoers.d/brew").contains("/usr/local/bin/brew"),
messageText: "Brew has not been added to sudoers.d",
informativeText: "You must run `sudo valet trust` to ensure Valet can start and stop services without having to use sudo every time. The app will not work correctly until you resolve this issue."
informativeText: "You must run `sudo valet trust` to ensure Valet can start and stop services without having to use sudo every time. The app will not work correctly until you resolve this issue.",
breaking: true
)
self.presentAlertOnMainThreadIf(
self.performEnvironmentCheck(
!Shell.user.pipe("cat /private/etc/sudoers.d/valet").contains("/usr/local/bin/valet"),
messageText: "Valet has not been added to sudoers.d",
informativeText: "You must run `sudo valet trust` to ensure Valet can start and stop services without having to use sudo every time. The app will not work correctly until you resolve this issue."
informativeText: "You must run `sudo valet trust` to ensure Valet can start and stop services without having to use sudo every time. The app will not work correctly until you resolve this issue.",
breaking: true
)
let services = Shell.user.pipe("brew services list | grep php")
self.presentAlertOnMainThreadIf(
self.performEnvironmentCheck(
(services.countInstances(of: "started") > 1),
messageText: "Multiple PHP services are active",
informativeText: "This can cause php-fpm to serve a more recent version of PHP than the one you'd like to see active. Please terminate all extra PHP processes." +
"\n\nThe easiest solution is to choose the option 'Force load latest PHP version' in the menu bar." +
"\n\nAlternatively, you can fix this manually. You can do this by running `brew services list` and running `sudo brew services stop php@7.3` (and use the version that applies)." +
"\n\nPHP Monitor usually handles the starting and stopping of these services, so once the correct version is the only PHP version running you should not have any issues. It is recommended to restart PHP Monitor once you have resolved this issue." +
"\n\nFor more information about this issue, please see the README.md file in the repository on GitHub."
"\n\nFor more information about this issue, please see the README.md file in the repository on GitHub.",
breaking: false
)
if (!self.failed) {
success()
}
}
private static func presentAlertOnMainThreadIf(
/**
* Perform an environment check. Will cause the application to terminate, if `breaking` is set to true.
*
* - Parameter condition: Condition to check for
* - Parameter messageText: Short description of what is wrong
* - Parameter informativeText: Expanded description of the environment check that failed
* - Parameter breaking: If the application should terminate afterwards
*/
private func performEnvironmentCheck(
_ condition: Bool,
messageText: String,
informativeText: String
informativeText: String,
breaking: Bool
)
{
if (condition) {
// Only breaking issues will cause the notification
if (breaking) {
self.failed = true
}
DispatchQueue.main.async {
Alert.present(
// Present the information to the user
_ = Alert.present(
messageText: messageText,
informativeText: informativeText
)
// Only breaking issues will throw the extra retry modal
if (breaking) {
self.failureCallback()
}
}
}
}

View File

@ -12,12 +12,16 @@ class Alert {
public static func present(
messageText: String,
informativeText: String,
buttonTitle: String = "OK"
) {
buttonTitle: String = "OK",
secondButtonTitle: String = ""
) -> Bool {
let alert = NSAlert.init()
alert.messageText = messageText
alert.informativeText = informativeText
alert.addButton(withTitle: buttonTitle)
alert.runModal()
if (!secondButtonTitle.isEmpty) {
alert.addButton(withTitle: secondButtonTitle)
}
return alert.runModal() == .alertFirstButtonReturn
}
}

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ApplicationDescription</key>
<string>PHP Monitor is a tool that shows the active PHP version in your menu bar and gives you easy access to certain PHP service actions and config files.</string>
<key>DeveloperName</key>
<string>Nico Verbruggen</string>
<key>Website</key>
<string>https://github.com/nicoverbruggen/phpmon</string>
<key>Connections</key>
<array>
<dict>
<key>IsIncoming</key>
<false/>
<key>Host</key>
<string>registry.npmjs.org</string>
<key>NetworkProtocol</key>
<string>TCP</string>
<key>Port</key>
<string>80, 443</string>
<key>Relevance</key>
<string>Essential</string>
<key>Purpose</key>
<string>PHP Monitor directly invokes Homebrew which contacts the NPM Registry.</string>
<key>DenyConsequences</key>
<string>If you deny these connections, PHP Monitor might not be able to complete its preset set of instructions, causing version switching to fail.</string>
</dict>
<dict>
<key>IsIncoming</key>
<false/>
<key>Host</key>
<string>github.com, api.github.com</string>
<key>NetworkProtocol</key>
<string>TCP</string>
<key>Port</key>
<string>443</string>
<key>Relevance</key>
<string>Essential</string>
<key>Purpose</key>
<string>PHP Monitor directly invokes Homebrew which contacts GitHub.</string>
<key>DenyConsequences</key>
<string>If you deny these connections, PHP Monitor might not be able to complete its preset set of instructions, causing version switching to fail.</string>
</dict>
</array>
</dict>
</plist>

View File

@ -0,0 +1,2 @@
// Top-level, general application description:
"ApplicationDescription" = "PHP Monitor is a tool that shows the active PHP version in your menu bar and gives you easy access to certain PHP service actions and config files.";

View File

@ -21,18 +21,41 @@ class MainMenu: NSObject, NSWindowDelegate {
self.setStatusBar(image: NSImage(named: NSImage.Name("StatusBarIcon"))!)
// Perform environment boot checks
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
Startup.checkEnvironment()
App.shared.availablePhpVersions = Actions.detectPhpVersions()
self.updatePhpVersionInStatusBar()
// Schedule a request to fetch the PHP version every 60 seconds
DispatchQueue.main.async {
App.shared.timer = Timer.scheduledTimer(
timeInterval: 60,
target: self,
selector: #selector(self.updatePhpVersionInStatusBar),
userInfo: nil,
repeats: true
)
Startup().checkEnvironment(success: {
self.onEnvironmentPass()
}, failure: {
self.onEnvironmentFail()
})
}
}
private func onEnvironmentPass() {
App.shared.availablePhpVersions = Actions.detectPhpVersions()
self.updatePhpVersionInStatusBar()
// Schedule a request to fetch the PHP version every 60 seconds
DispatchQueue.main.async {
App.shared.timer = Timer.scheduledTimer(
timeInterval: 60,
target: self,
selector: #selector(self.updatePhpVersionInStatusBar),
userInfo: nil,
repeats: true
)
}
}
private func onEnvironmentFail() {
DispatchQueue.main.async {
let close = Alert.present(
messageText: "PHP Monitor cannot start",
informativeText: "The issue you were just notified about is keeping PHP Monitor from functioning correctly. Please fix the issue and restart PHP Monitor. After clicking on OK, PHP Monitor will close.\n\nIf you have fixed the issue (or don't remember what the exact issue is) you can click on Retry, which will have PHP Monitor retry the startup checks.",
buttonTitle: "Close",
secondButtonTitle: "Retry"
)
if (!close) {
self.startup()
} else {
exit(1)
}
}
}
@ -140,12 +163,12 @@ class MainMenu: NSObject, NSWindowDelegate {
}
@objc public func forceRestartLatestPhp() {
Alert.present(
_ = Alert.present(
messageText: "alert.force_reload.title".localized,
informativeText: "alert.force_reload.info".localized
)
self.waitAndExecute({ Actions.fixMyPhp() }, {
Alert.present(
_ = Alert.present(
messageText: "alert.force_reload_done.title".localized,
informativeText: "alert.force_reload_done.info".localized
)