Compare commits
428 Commits
Author | SHA1 | Date | |
---|---|---|---|
2e58bbb5e8 | |||
bb6abc5e9a | |||
e4f9d491c3 | |||
1ba7ee37db | |||
34cfbae3a9 | |||
9fabda545f | |||
7cd50aed7b | |||
cdc082071d | |||
d1479672c8 | |||
ffb112cfb2 | |||
f5af33c098 | |||
0f464f5814 | |||
776c2095e6 | |||
82a2833161 | |||
b14d7bdf07 | |||
ffa22eea25 | |||
8220e6409d | |||
927e1c02fa | |||
a13a17b106 | |||
18d6d73f94 | |||
54d101acbe | |||
76f720cb71 | |||
033e485ce1 | |||
82ee830de1 | |||
55cd1cccee | |||
5f13ba3d1b | |||
298aa0aa8d | |||
5d49be6f7e | |||
ab81bf5875 | |||
5d8765683a | |||
6c22bc0145 | |||
5c1908668f | |||
94da7fb255 | |||
46d2d35c1a | |||
cba41b29bc | |||
7a8f47b995 | |||
40062c5091 | |||
6081ef6b02 | |||
4cffe5a662 | |||
813aec2b42 | |||
f2452bbc70 | |||
28fb685bfc | |||
0661ca00ff | |||
0b04619003 | |||
85d7b6aa57 | |||
bba961269c | |||
d0f7d2c5e9 | |||
eeeb3eb184 | |||
f00f8d26f6 | |||
74817beec6 | |||
7b6809245c | |||
5b40a8fd41 | |||
193f459be1 | |||
c4c19a5b47 | |||
7d103c70e7 | |||
2ffe90948e | |||
8e61aaacde | |||
29c8fcbde2 | |||
8dd21f46aa | |||
e688dde2aa | |||
987e1e1bdb | |||
510257c436 | |||
bb1572f32a | |||
45276034b1 | |||
0d4a144524 | |||
a0e5102ca7 | |||
69c0f5ace9 | |||
d0962c2387 | |||
4670894cfd | |||
a2f6c70a03 | |||
ef469868d8 | |||
c9ba872529 | |||
1e15042be2 | |||
7647978da5 | |||
f82f3052f2 | |||
10b299ff65 | |||
e4ff0418fd | |||
a2b25e31ca | |||
c4772db808 | |||
b59a5d31a5 | |||
e4b1f75c53 | |||
338a87d503 | |||
0f0e91273e | |||
20959501c9 | |||
aeeecd6996 | |||
e9ae989200 | |||
f6378e7b73 | |||
d7e8652f5f | |||
5293c437d1 | |||
f75bfc9c4a | |||
42fc0e3698 | |||
626b7a735d | |||
567373f8da | |||
32e8878a68 | |||
46005a3c68 | |||
03a409281a | |||
e0dd778bb3 | |||
c3f8a53ac3 | |||
d8579bd7d1 | |||
d2cd567fd2 | |||
a5212b436e | |||
b16250c2be | |||
3b4a1a0654 | |||
9ab6231337 | |||
38c2d9131b | |||
1566323fca | |||
dc44538a7b | |||
bf0a923eb2 | |||
04bf5a3251 | |||
23f3204fa8 | |||
6dc74e94aa | |||
422aefe831 | |||
3c3a0c8b45 | |||
0cdeeec0a4 | |||
e4c3e78a8a | |||
7f320897be | |||
9ef184331e | |||
e372480249 | |||
3bca3117f9 | |||
722e082526 | |||
40a0bd6cab | |||
78510ea3fe | |||
8624573e74 | |||
dd251936b9 | |||
c647aee8ea | |||
b7766aeec2 | |||
5af1f09ee1 | |||
6646ceda76 | |||
0b05bb44a2 | |||
1fbb1a8aa8 | |||
8cb2074d76 | |||
c408d62118 | |||
665bba86dd | |||
0d29fbf796 | |||
69042042ea | |||
63f4f8b078 | |||
e76c6e14e4 | |||
ceb168c6cf | |||
a6387e96e7 | |||
2dbf775ad6 | |||
acdcce7f7a | |||
7a3dc9a145 | |||
1ca49f6cbc | |||
fa2de1f77c | |||
fe695bb026 | |||
f82a3bb008 | |||
e7df254dcc | |||
ea9538f116 | |||
0d75e4c3b2 | |||
a90703e525 | |||
f74f9f69b2 | |||
a950587e84 | |||
267a1dac94 | |||
ed49362291 | |||
3f0f070245 | |||
bd79f42e96 | |||
35ae681c2d | |||
313e806414 | |||
a8dc366038 | |||
eaf653e3c0 | |||
5c391917d2 | |||
09b5aa7f93 | |||
66a8c17f1f | |||
adc31984a8 | |||
8114eef381 | |||
9190420c66 | |||
e5ba074936 | |||
e4f1efe26a | |||
498f4e7b79 | |||
d9a526e828 | |||
2f93b4980b | |||
ac0ca06d7f | |||
17320a19cf | |||
3faa251216 | |||
a9f140fabc | |||
b6b5a94bbd | |||
c05f0fe5cb | |||
eaf1423fb1 | |||
7feb13856d | |||
ca2ca9df3b | |||
4259915ff6 | |||
89e7a9b1ea | |||
8c25d23d09 | |||
f44811b9dc | |||
f65fd513f2 | |||
327c88a745 | |||
63aa8c2f44 | |||
afbfc55088 | |||
d13714c1ea | |||
92a6d506dc | |||
e381880675 | |||
7e185154ef | |||
27c25378b1 | |||
1159a6cc2e | |||
489bf13707 | |||
5d3faceb5a | |||
29d34a6b62 | |||
be80d74141 | |||
d37e86ce2c | |||
d8fc857d23 | |||
e0bec333ed | |||
46867ad25e | |||
924edf6f96 | |||
010c8eddde | |||
96602b1a9c | |||
d536499799 | |||
ad016c54b2 | |||
f8b0b38e9e | |||
912e549104 | |||
93bdb0ed7f | |||
87713bbe64 | |||
dce27059ff | |||
c919326480 | |||
1e124a90f3 | |||
d1fc9de4bd | |||
04db3f50ed | |||
4e347adf69 | |||
79de14c9aa | |||
7448e89965 | |||
967743715b | |||
d37913005b | |||
0986b97051 | |||
bbb04f7907 | |||
015f406ddf | |||
e1a97672b5 | |||
493b5945f9 | |||
52606aae8b | |||
2d6ca0f841 | |||
34900f929f | |||
5dbd05fdfb | |||
fe3cf9adb1 | |||
9bc8460cce | |||
4cbd2fd6eb | |||
6fef3fe37a | |||
72a20d1ed9 | |||
73ed80434a | |||
a78672927b | |||
4256eae442 | |||
76412b68f3 | |||
9153bb140a | |||
c9c15d10f9 | |||
e8c2277ef5 | |||
23720c5dc9 | |||
f881f07cba | |||
b072ee8dec | |||
acfbc0b66f | |||
c738a03934 | |||
84d62f3583 | |||
f9faa03b92 | |||
55f6c3c6cd | |||
a0c6753761 | |||
327125608a | |||
6c0045302b | |||
9c85bebe72 | |||
fb56cd551e | |||
e83d507e79 | |||
0c0e7fc87d | |||
faf49fbe1d | |||
2925b0ff79 | |||
acb18474c8 | |||
ed61490398 | |||
abb76273c9 | |||
2f15af4ff8 | |||
e29e8416d5 | |||
5d423210dd | |||
340c36fdf8 | |||
3085158b80 | |||
c2585f9bf4 | |||
d478137742 | |||
827bd182b1 | |||
f7500637fe | |||
7c884610b1 | |||
d3d219751e | |||
16d2e7d06f | |||
47b86ff9fa | |||
6e574b9154 | |||
485001403d | |||
694c5e7f7d | |||
d9ff26385a | |||
0cfb7c65bb | |||
3cbc2a0367 | |||
7733c90206 | |||
0ad6e5cb1c | |||
8a47cfd5f1 | |||
db4c0399fd | |||
b0f29b72cd | |||
98a1622ccc | |||
a6ac737590 | |||
bba719012f | |||
cdc0cea01c | |||
d3a4f2091c | |||
c7dc17dded | |||
d70f8627bb | |||
7661f4643d | |||
11d74277e5 | |||
e4096ab662 | |||
d367f1f353 | |||
79fbdef41b | |||
37ede7e2a3 | |||
80eabe3bf3 | |||
aa07a42d8f | |||
b6b3a9a74c | |||
ec4371e6da | |||
c7a92d502f | |||
172a38e459 | |||
d18e8298b6 | |||
df325474c6 | |||
60278d7817 | |||
9e8117d31f | |||
3d042b24ed | |||
fcf3483dd0 | |||
3db333dd77 | |||
b0f0fd8c6b | |||
69755cd8cc | |||
6b2fa0c605 | |||
dd41b5a1e0 | |||
a3fe09ed8a | |||
ad81c4a3db | |||
572b0f69dd | |||
c1b80552a0 | |||
0493f61dc8 | |||
9824ed2b83 | |||
3e0a16cc73 | |||
5a50e7fdab | |||
1dc85a4d48 | |||
85ef3ff067 | |||
2958378411 | |||
3a2cd3bff6 | |||
fbe791902c | |||
77f4de8ca9 | |||
0f6e47a594 | |||
7408da2a91 | |||
12a66f3467 | |||
d3615138dd | |||
dd27b91527 | |||
bc093cc945 | |||
fd46ce6b35 | |||
e35acadeaf | |||
7b8aab85d6 | |||
ec59715b3d | |||
6f21913ae2 | |||
b53fbe471b | |||
209f3e889d | |||
5825e8d0b0 | |||
4ea11c5f59 | |||
94f086881a | |||
e73474e30c | |||
c7a0e25336 | |||
e353fb7524 | |||
458868d051 | |||
932fafc728 | |||
b70c4f690a | |||
4147cc7b4b | |||
72b309a716 | |||
12c2716715 | |||
4d4019204b | |||
157033a3b3 | |||
717cddacdd | |||
f13ed5dd90 | |||
a8f823cd04 | |||
51fd22f595 | |||
bf6ebff3bf | |||
1887b19329 | |||
a53972404c | |||
64a605235a | |||
a194ecdebe | |||
03158a568c | |||
bdc6be7384 | |||
4908dba57e | |||
0f0aa176b6 | |||
485729f9a5 | |||
5eb36a9bdf | |||
86113d2067 | |||
70c04d4dc7 | |||
5d69b423c1 | |||
1617b57b1e | |||
33825e7b66 | |||
464b7106b2 | |||
0cf85f9958 | |||
00cf2bc360 | |||
dbb5329908 | |||
9fd8e7042a | |||
cb62a20f2a | |||
bb1742a390 | |||
6db43beddf | |||
7e2c7cdd59 | |||
e76dd0daeb | |||
0c33e8f8cc | |||
a6a196518a | |||
a287ebf6e4 | |||
2200b395f1 | |||
bc8a572072 | |||
1c455ea05a | |||
f2d01748be | |||
d3e59e560f | |||
55e849c21b | |||
50f6afb3c5 | |||
67e80aac8d | |||
e683b6bc9a | |||
e854ebe114 | |||
b792f55e5f | |||
cbf5526881 | |||
f62297ee3d | |||
2f017f6732 | |||
1c62a100af | |||
e176d6fa2d | |||
ea60626c47 | |||
69c3386088 | |||
3e898d435b | |||
a4dcd0cd3d | |||
bb382c0f74 | |||
c87c532d1c | |||
b26099369f | |||
90a8e7c336 | |||
398dad9d5e | |||
48d0878dfd | |||
4ba3415bf4 | |||
0fc7f2c905 | |||
eebfa823f1 | |||
edc23f97de | |||
7b79cb7fe8 | |||
88d81f343e | |||
8486997f01 | |||
af55e7fabc | |||
2025c951e8 | |||
a71c6afc0d | |||
1bfcdd546b | |||
78702ae325 |
2
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
github: nicoverbruggen
|
||||
custom: ['https://nicoverbruggen.be/sponsor']
|
35
.github/pull_request_template.md
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
Hello there! Thank you for considering a pull request for PHP Monitor.
|
||||
|
||||
Please read the text below first before you submit your PR.
|
||||
|
||||
## Do not PR unless...
|
||||
|
||||
In order to make development and maintenance of PHP Monitor easier, I ask that you _avoid_ making a pull request in the following situations:
|
||||
|
||||
* No issue has been associated with the changes you‘d like to merge
|
||||
* You have not announced you will be addressing a particular issue
|
||||
* The PR is a low effort change: e.g. commits that only fix typos or phrasing may not be accepted
|
||||
|
||||
(If you believe the phrasing of particular text in the app is unclear or incorrect, please open an issue first.)
|
||||
|
||||
In short: It is usually best to *get in touch first* if you are making substantial changes.
|
||||
|
||||
## About destination branches
|
||||
|
||||
Please keep in mind that `main` is reserved for the current code state of the latest release and should *never* be the destination branch unless a new release is happening. **Merge requests that target `main` will be closed without mercy.**
|
||||
|
||||
Usually, the best target is the stable `dev/x.x` branch that corresponds with the latest major version that is released.
|
||||
|
||||
There may be a newer branch available, which is an appropriate place for bigger changes, but please keep in mind that it is usually best to announce you‘ll be working on such a change before you spend the time, since as the lead contributor I might not even want said change in the app. Thank you.
|
||||
|
||||
## Your changes
|
||||
|
||||
(feel free to remove the disclaimer above)
|
||||
|
||||
* Affected parts of the app: shared code / UI code / CLI (remove what does not apply)
|
||||
* Estimated impact on performance: none / low / high (remove what does not apply)
|
||||
* Made a new build with Xcode and tested this: yes / no (remove what does not apply)
|
||||
* Tested on macOS version + architecture: (e.g. "Monterey on M1" or "Big Sur on Intel")
|
||||
* References issue(s): (please reference the issue here, using # and the number of the issue)
|
||||
|
||||
(please describe what you have changed here)
|
3
.gitignore
vendored
@ -1,2 +1,5 @@
|
||||
phpmon.xcodeproj/project.xcworkspace
|
||||
phpmon.xcodeproj/xcuserdata
|
||||
PHP Monitor.xcodeproj/project.xcworkspace
|
||||
PHP Monitor.xcodeproj/xcuserdata
|
||||
.DS_Store
|
46
DEVELOPER.md
Normal file
@ -0,0 +1,46 @@
|
||||
# DEVELOPER README
|
||||
|
||||
## 🔧 Build instructions
|
||||
|
||||
<img src="./docs/build.png" width="404px" alt="build button in Xcode"/>
|
||||
|
||||
If you'd like to build PHP Monitor yourself, you need:
|
||||
|
||||
* Xcode (usually the latest version)
|
||||
* The contents of this repository
|
||||
|
||||
Once you have downloaded this repository, open `PHP Monitor.xcodeproj`, and you should be able to immediately build the app for your system by pressing Cmd-R. This will create a debug build. (If Xcode complains about code signing, you can turn it off.)
|
||||
|
||||
If you'd like to create a production build, choose "Any Mac" as the target and select Product > Archive.
|
||||
|
||||
## 🐛 Symbolication of crashes
|
||||
|
||||
If you have an archived build of the app and exported the DSYM, it is possible to symbolicate .ips crash logs.
|
||||
|
||||
For example, given the following crash (from an .ips file):
|
||||
|
||||
```
|
||||
Thread 2 Crashed:: Dispatch queue: com.apple.root.user-initiated-qos
|
||||
0 libswiftDispatch.dylib 0x7ff82aa3ab8c static OS_dispatch_source.makeProcessSource(identifier:eventMask:queue:) + 28
|
||||
1 PHP Monitor 0x1096907d8 0x10965e000 + 206808
|
||||
| |
|
||||
address load address
|
||||
2 PHP Monitor 0x1096903ac 0x10965e000 + 205740
|
||||
3 PHP Monitor 0x10968f88b 0x10965e000 + 202891
|
||||
```
|
||||
|
||||
You must use the correct order for the the address and load address in the command below:
|
||||
|
||||
```
|
||||
$ atos -arch x86_64 -o '/path/to/PHP Monitor.app.dSYM/Contents/Resources/DWARF/PHP Monitor' -l 0x10965e000 0x1096907d8
|
||||
| | | |
|
||||
architecture path to DSYM load address address
|
||||
```
|
||||
|
||||
This will return the relevant information, for example:
|
||||
|
||||
```
|
||||
FSWatcher.startMonitoring(_:behaviour:) (in PHP Monitor) (PhpConfigWatcher.swift:95)
|
||||
```
|
||||
|
||||
For more information, see [Apple's documentation](https://developer.apple.com/documentation/xcode/adding-identifiable-symbol-names-to-a-crash-report).
|
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Nico Verbruggen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
1282
PHP Monitor.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1320"
|
||||
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>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C4F7807825D7F84B000DBC97"
|
||||
BuildableName = "phpmon-tests.xctest"
|
||||
BlueprintName = "phpmon-tests"
|
||||
ReferencedContainer = "container:PHP Monitor.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</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"
|
||||
enableGPUValidationMode = "1"
|
||||
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>
|
404
README.md
@ -1,30 +1,402 @@
|
||||
# phpmon
|
||||
> If this software has been useful to you, I ask that you **please star the repository**, that way I know that the software is being used. Also, please consider leaving [a one-time donation](https://nicoverbruggen.be/sponsor) to support the project.
|
||||
> You can also send me [feedback](https://twitter.com/nicoverbruggen) if the app came in handy.<br>**Thank you!** ⭐️
|
||||
|
||||
<img src="./docs/phpmon.png" width="306px" alt="phpmon screenshot"/>
|
||||
<h1 align="center"><b>PHP Monitor</b> (phpmon)</h1>
|
||||
|
||||
phpmon is a macOS utility that runs on your Mac and displays the active PHP version in your status bar. Handy if you're running multiple versions of PHP with Homebrew and wish to see which version is currently linked & active with Laravel Valet.
|
||||
<p align="center">
|
||||
<img src="./phpmon/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png" alt="phpmon icon" width="128px" />
|
||||
</p>
|
||||
|
||||
## How it works
|
||||
**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's tightly integrated with [Laravel Valet](https://github.com/laravel/valet), so <u>you need to have it set up before you can use this</u>.
|
||||
|
||||
### Version detection
|
||||
<img src="./docs/screenshot50.jpg" width="1085px" alt="phpmon screenshot (menu bar app)"/>
|
||||
|
||||
This utility runs `php -r 'print phpversion();'` in the background periodically and extracts the version number.
|
||||
<small><i>Screenshot: Showing the key functionality of PHP Monitor. You can also add new domains as links, manage various services, and perform First Aid to fix all kinds of common PHP link issues.</i></small>
|
||||
|
||||
It's super convenient to switch between different versions of PHP. You'll even get notifications (only if you choose to opt-in, of course)!
|
||||
|
||||
<img src="./docs/notification.png" width="370px" alt="phpmon screenshot (notification)"/>
|
||||
|
||||
PHP Monitor also gives you quick access to various useful functionality (like accessing configuration files, restarting services, and more).
|
||||
|
||||
## 🖥 System requirements
|
||||
|
||||
PHP Monitor is a universal application that runs natively on Apple Silicon **and** Intel-based Macs.
|
||||
|
||||
* macOS 11 Big Sur or higher (supports macOS 12 Monterey)
|
||||
* Homebrew is installed in `/usr/local/homebrew` or `/opt/homebrew`
|
||||
* The brew formula `php` has to be installed (which version is detected)
|
||||
* Laravel Valet 2.16.2 or higher (older versions might be compatible but are not supported)
|
||||
|
||||
_You may need to update your Valet installation to keep everything working if a major version update of PHP has been released. You can do this by running `composer global update && valet install`._
|
||||
|
||||
## 🚀 How to install
|
||||
|
||||
Again, make sure you have **Laravel Valet** installed first. Once that's done, you can install via Homebrew (recommended), or may download the latest release on GitHub.
|
||||
|
||||
To install via Homebrew, run:
|
||||
|
||||
brew tap nicoverbruggen/homebrew-cask
|
||||
brew install --cask phpmon
|
||||
|
||||
To upgrade your existing installation, run:
|
||||
|
||||
brew upgrade phpmon
|
||||
|
||||
(You may need to run `brew update` first in order to update the cask file if you ran a Homebrew operation recently.)
|
||||
|
||||
## 🔑 Is the app signed & notarized?
|
||||
|
||||
Yes, the app is signed and notarized, meaning all you have to do is approve its first launch (or whenever it updates).
|
||||
|
||||
## 👨💻 Why build 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 it has now been replaced with this utility, which also does a good job at displaying additional information at a glance, like the current PHP version, memory limits, and more.
|
||||
|
||||
## 🤬 The app won't start?!
|
||||
|
||||
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 a variety of scenarios.
|
||||
|
||||
**Follow instructions as specified in the alert in order to resolve any issues.**
|
||||
|
||||
(If the app crashes at launch without showing you any of these messages, you might have a non-standard Homebrew and Valet setup. Those are not supported.)
|
||||
|
||||
## 🙋♂️ FAQ & Troubleshooting
|
||||
|
||||
> If you are having issues, the first thing you should be doing is installing the latest version of PHP Monitor _and_ Laravel Valet. This can resolve a variety of issues. To upgrade Valet, run `composer global update`. Don't forget to run `valet install` after upgrading.
|
||||
|
||||
If you're still having issues, here's a few common questions & answers, as well as issues and solutions:
|
||||
|
||||
<details>
|
||||
<summary><strong>Which versions of PHP are supported?</strong></summary>
|
||||
|
||||
<ul>
|
||||
<li>PHP 5.6</li>
|
||||
<li>PHP 7.0</li>
|
||||
<li>PHP 7.1</li>
|
||||
<li>PHP 7.2</li>
|
||||
<li>PHP 7.3</li>
|
||||
<li>PHP 7.4</li>
|
||||
<li>PHP 8.0</li>
|
||||
<li>PHP 8.1</li>
|
||||
<li>PHP 8.2 (experimental)</li>
|
||||
</ul>
|
||||
|
||||
For more details, consult the [constants file](https://github.com/nicoverbruggen/phpmon/blob/main/phpmon/Constants.swift#L16) file to see which versions are supported.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>I want PHP Monitor to start up when I boot my Mac!</strong></summary>
|
||||
|
||||
You can do this by dragging *PHP Monitor.app* into the **Login Items** section in **System Preferences > Users & Groups** for your account.
|
||||
|
||||
Super convenient!
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>I want to set up PHP Monitor from scratch! I don't have Homebrew installed either, where do I begin?</strong></summary>
|
||||
|
||||
If you want to set up your computer for the very first time with PHP Monitor, 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:
|
||||
|
||||
# on an Intel Mac
|
||||
export PATH=$HOME/bin:/usr/local/bin:$PATH
|
||||
|
||||
If you're on an Apple Silicon-based Mac, you'll need to add:
|
||||
|
||||
# on an M1 Mac
|
||||
export PATH=$HOME/bin:/opt/homebrew/bin:$PATH
|
||||
|
||||
and add the following to your .zshrc, but add this BEFORE the homebrew PATH additions:
|
||||
|
||||
export PATH=$HOME/bin:~/.composer/vendor/bin:$PATH
|
||||
|
||||
If you're adding composer and Homebrew binaries, ensure that Homebrew binaries are preferred by adding these to the path last. On my system, that looks like this:
|
||||
|
||||
export PATH=$HOME/bin:/usr/local/bin:$PATH
|
||||
export PATH=$HOME/bin:~/.composer/vendor/bin:$PATH
|
||||
export PATH=$HOME/bin:/opt/homebrew/bin:$PATH
|
||||
|
||||
Make sure PHP is linked correctly:
|
||||
|
||||
which php
|
||||
|
||||
should return: `/usr/local/bin/php` (or `/opt/homebrew/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.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>PHP Monitor tells me `php` is not installed...</strong></summary>
|
||||
|
||||
Try installing again using `brew install php`.
|
||||
|
||||
This should resolve the issue! If that does not fix the issue, run `brew link php --force`. (Afterwards, you may need to restart your terminal to make sure the new linked version is detected.)
|
||||
|
||||
brew install php
|
||||
brew link php --force
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Valet sites won't load. I'm getting a 502 Bad Gateway error!</strong></summary>
|
||||
|
||||
If you're visiting your `.test` domain, and you're getting a 502 (Bad Gateway) after switching to a different PHP version, you're dealing with a common issue.
|
||||
|
||||
This problem is usually resolved by upgrading Valet and running `valet install` again.
|
||||
|
||||
composer global update
|
||||
valet install
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>PHP Monitor tells me my installation is broken, but I don't see why!</strong></summary>
|
||||
|
||||
PHP Monitor tells you that a PHP installation is broken, if the configuration is causing warnings or errors when determining the version number.
|
||||
|
||||
Since PHP Monitor changes the linked version via Homebrew, both Valet *and* your terminal (CLI) should use the new PHP version.
|
||||
|
||||
However, this might not be the case on your system. You _might_ have a specific version of PHP linked if that is not the case. In that case, you may need to change your `.bashrc` or `.zshrc` file where the PATH is set (depending on the terminal you use).
|
||||
|
||||
You can find out which version of PHP is being used by running `which php`.
|
||||
|
||||
You can find out what exactly is causing the issue by running a command. On Intel, you can run (replace `7.4` with the version that is broken):
|
||||
|
||||
```
|
||||
/usr/local/opt/php@7.4/bin/php -r "print phpversion();"
|
||||
```
|
||||
|
||||
On Apple Silicon, you can run (replace `7.4` with the version that is broken):
|
||||
|
||||
```
|
||||
/opt/homebrew/opt/php@7.4/bin/php -r "print phpversion();"
|
||||
```
|
||||
|
||||
You should see an error or a warning here in the output.
|
||||
|
||||
Usually this is a duplicate extension declaration causing issues, or an extension that couldn't be loaded. You'll have to solve that issue yourself (usually by removing the offending extension or reinstalling).
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>One of the limits (memory limit, max POST size, max upload size) shows an exclamation mark!</strong></summary>
|
||||
|
||||
The value you provided in your INI file is invalid. If that is the case, PHP will attempt to parse your value as bytes, which is usually unintended. (`1GB` will resolve to merely a few bytes, and all of your applications will run out of memory!)
|
||||
|
||||
You must a provide a value like so: `1024K`, `256M`, `1G`. Alternatively, `-1` is also allowed, or just an integer (which will result in N amount of bytes being the limit).
|
||||
|
||||
**Example**: Trying to use `1GB` as the memory limit, for example, will result in this exclamation mark. The correct way to set a 1GB limit is by using `1G` as the value. (Note: The displayed value will append `B` for clarity, so if you set `1G`, the value reported by PHP Monitor will be 1 GB.)
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>One of my commented out extensions is not being detected...</strong></summary>
|
||||
|
||||
The app searches in the relevant `.ini` files for a specific pattern. For regular extensions:
|
||||
|
||||
* `extension="*.so"`
|
||||
* `; extension="*.so"`
|
||||
|
||||
For Zend extensions:
|
||||
|
||||
* `zend_extension="*.so"`
|
||||
* `; zend_extension="*.so"`
|
||||
|
||||
The `*` is a wildcard and the name of the extension. If you've commented out the extension, make sure you've commented it out with a semicolon (;) and a single space after the semicolon for PHP Monitor to detect it.
|
||||
|
||||
Since v3.4 all of the loaded .ini files are sourced to determine which extensions are enabled.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>I've got two Homebrew installations on my Apple Silicon Mac, can I choose which installation to use with PHP Monitor?</strong></summary>
|
||||
|
||||
Not at this time, no. PHP Monitor will prefer the `/opt/homebrew` installation over the classic installation directory.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Why is the app doing network requests?</strong></summary>
|
||||
|
||||
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.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>How do I get various applications to show up in the domain list's right-click menu?</strong></summary>
|
||||
|
||||
When you select and right-click on a domain, you can open these directories with various applications. This can help speed up your workflow. However, for these apps to show up, they must be detected first.
|
||||
|
||||
The supported apps are: <i>PhpStorm, Visual Studio Code, Sublime Text, Sublime Merge, iTerm</i>.
|
||||
|
||||
All of these apps should just be detected correctly, no matter their location on your system. If you can open it using `open -a "appname"`, the app should be detected and work. If you have renamed the app, there might be an issue getting it detected.
|
||||
|
||||
To see which files are checked to determine availability, see [this file](./phpmon/Domain/Helpers/Application.swift).
|
||||
|
||||
You can add your own apps by creating and editing a `~/.phpmon.conf.json` file, with the following entry:
|
||||
|
||||
<pre>
|
||||
{
|
||||
"scan_apps": ["Xcode", "Kraken"]
|
||||
}
|
||||
</pre>
|
||||
|
||||
You can put as many apps as you'd like in the `scan_apps` array, and PHP Monitor will check for the existence of these apps. You do not need to set the full path, just the name of the app should work. Not all apps support opening a folder, though, so your success might vary.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>How can the app integrate with third party tools, like Alfred?</strong></summary>
|
||||
|
||||
There's an Alfred workflow usually included in the release list, you can grab it by going to releases and downloading the asset `phpmon.alfredworkflow`.
|
||||
|
||||
If you'd like to integrate something yourself, all you need to to is use the `phpmon://` protocol and ensure that third party app integrations are enabled in Preferences (in PHP Monitor).
|
||||
|
||||
Using app callbacks, macOS and PHP Monitor allow for the following to be called:
|
||||
|
||||
* phpmon://list
|
||||
* phpmon://services/stop
|
||||
* phpmon://services/restart/all
|
||||
* phpmon://services/restart/nginx
|
||||
* phpmon://services/restart/php
|
||||
* phpmon://services/restart/dnsmasq
|
||||
* phpmon://locate/config
|
||||
* phpmon://locate/composer
|
||||
* phpmon://locate/valet
|
||||
* phpmon://phpinfo
|
||||
* phpmon://switch/php/{version}
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>How does the app know what PHP version is required for my app?</strong></summary>
|
||||
|
||||
The `composer.json` file in the root of the folder (if it exists) is scanned and interpreted.
|
||||
|
||||
If the version is set in `platform`, it takes precendence.
|
||||
If the version is not set in `platform` but it is in `require` (most common) then that version is used.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>What do the checkmarks next to the PHP version mean in the site list?</strong></summary>
|
||||
|
||||
You'll see a checkmark next to the version number if the currently enabled PHP version is compatible with the version required to run the site.
|
||||
|
||||
This is determined by evaluating the PHP requirement constraint (e.g. `^8.0`, `~8.0` or a specific version: `8.0`).
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Why can't I see the driver type any more? It says "Project Type" now.</strong></summary>
|
||||
|
||||
PHP Monitor currently checks your `composer.json` file to try to figure out what project you are running.
|
||||
|
||||
This approach is a lot faster than asking for a driver when you have many sites linked, but is slightly less reliable since the framework or type of project inferred via `composer.json` might not be 100% accurate.
|
||||
|
||||
You can always still ask Valet using the command line, should it be necessary. In my experience fetching the drivers slowed down the app unnecessarily.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>After running PHP Monitor, Homebrew sometimes has issues with `brew upgrade` or `brew cleanup`!</strong></summary>
|
||||
|
||||
You can now use **First Aid & Services > Restore Homebrew Permissions** to (temporarily) resolve this issue and allow for a clean and painless `brew upgrade` or `brew cleanup` process.
|
||||
|
||||
If you would like to know more, consult [this issue](https://github.com/nicoverbruggen/phpmon/issues/85) for more information about why this is needed.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>The app has crashed!</strong></summary>
|
||||
|
||||
Please get in touch and open an issue. PHP Monitor shouldn't crash... (unless you are actually removing PHP *while* the app is running, that’s considered normal behaviour!)
|
||||
|
||||
If you would like to report a crash, please include the associated **log files** so I can find out what exactly went wrong.
|
||||
|
||||
To find the logs, take a look in `~/Library/Logs/DiagnosticReports` (in Finder) and see if there's any (log) files that start with "PHP Monitor".
|
||||
|
||||
</details>
|
||||
|
||||
## 📝 Having another issue?
|
||||
|
||||
I did not include any tracking or analytics software, so if you encounter issues, let me know [via an issue](https://github.com/nicoverbruggen/phpmon/issues/new).
|
||||
|
||||
## 💵 Support me?
|
||||
|
||||
PHP Monitor is available entirely **free of charge**, but if you can afford it a donation helps keep the project alive and the app maintained.
|
||||
|
||||
You can find a [sponsor](https://nicoverbruggen.be/sponsor) link at the top of this repo or you could click the link here to be taken to my sponsorship page.
|
||||
|
||||
Donations really help with the Apple Developer Program cost, and keep me motivated to keep working on PHP Monitor outside of work hours (I do have a day job!).
|
||||
|
||||
## 😎 Acknowledgements
|
||||
|
||||
While I did make this application during my own free time, I have been lucky enough to do various experiments during work hours at [DIVE](https://dive.be). I'd also like to shout out the following folks:
|
||||
|
||||
* My colleagues at [DIVE](https://dive.be)
|
||||
* The [Homebrew](https://brew.sh/) team & [Valet maintainers](https://github.com/laravel/valet/graphs/contributors)
|
||||
* Various folks who [reached](https://twitter.com/stauffermatt) [out](https://twitter.com/marcelpociot) when PHP Monitor was still very much a small app with a handful of stars or so
|
||||
* Everyone in the Laravel community who shared the app (thanks!)
|
||||
* Everyone who left feedback via issues & who donated to keep the project up and running
|
||||
|
||||
Thank you very much for your contributions, kind words and support.
|
||||
|
||||
## 🚜 How it works
|
||||
|
||||
### Loading info about PHP in the background
|
||||
|
||||
This utility runs `php-config --version` in the background periodically. It also checks your `.ini` files for extensions and loads more information about your limits (memory limit, POST limit, upload limit).
|
||||
|
||||
In order to save power, this only happens once every 60 seconds.
|
||||
|
||||
### Switching PHP versions
|
||||
|
||||
This utility will detect which PHP versions you have installed via Homebrew, and then allows you to switch between them.
|
||||
|
||||
This means:
|
||||
The switcher will disable all PHP-FPM services not belonging to the version you wish to use, and link the desired version of PHP. Then, it'll restart your desired PHP version's FPM process. This all happens in parallel, so this should be much faster than Valet’s switcher.
|
||||
|
||||
- You have at least the latest version of PHP installed (`php@7.3`)
|
||||
- You have installed Laravel Valet (`which valet` returns `/usr/local/bin/valet`)
|
||||
- You ran `valet trust`, which means Valet commands can be run without using sudo
|
||||
### Config change detection
|
||||
|
||||
The utility runs the following commands:
|
||||
PHP Monitor watches your filesystem in the relevant `conf.d` directory for the currently linked PHP version.
|
||||
|
||||
- Unlink all detected PHP versions
|
||||
- Switch to PHP 7.3 (this is done in order to ensure that Valet works, even when attempting to use PHP 5.6)
|
||||
- Tell Valet to switch to a specific PHP version
|
||||
- Link the desired version of PHP
|
||||
Whenever an .ini file is modified, PHP Monitor will attempt to reload the current information about the active PHP installation.
|
||||
|
||||
If you want to know more about how this works, you can find the file Services.swift under the Helpers directory to learn more about how switching PHP versions works. In the end, this just executes some shell commands.
|
||||
If an extension or other process writes to a single file a bunch of times in a short span of time (< 1 sec), PHP Monitor will only reload the active configuration information after a while (with a slight delay).
|
||||
|
||||
### Site detection
|
||||
|
||||
1. **Location of your sites**: PHP Monitor uses the Valet configuration file to determine which folders to look into. Each folder is scanned and then PHP Monitor will validate if a composer.json file exists to determine the desired PHP version.
|
||||
1. **Sites secured or not secured**: Whether the directory has been secured is determined by checking if a matching certificate exists under Valet's `Certificates` directory for that site name.
|
||||
1. **Project type**: PHP Monitor checks your `composer.json` file for "notable dependencies". If you have `laravel/framework` in your `require`, there's a good chance the project type is `Laravel`, after all.
|
||||
|
||||
*Note*: If you have linked a folder in Documents, Desktop or Downloads you might need to grant PHP Monitor access to those directories for PHP Monitor to work correctly.
|
||||
|
||||
### Want to know more?
|
||||
|
||||
If you want to know more about how this works, I recommend you check out the source code.
|
||||
|
||||
I have done my best to annotate as much as humanly possible, and have avoided using an overly complicated architecture to keep the code as easy to maintain as possible. The code isn't perfect by a long shot (lots of cleanup can still happen!) but the application works well.
|
||||
|
||||
I also have a few tests for key parts of the application that I found needed to be tested. In the future, I would like to add even more tests for some of the UI stuff, but for now the tests are more unit tests than feature tests.
|
||||
|
||||
For more detailed information for developers, please see [the documentation file for developers](./DEVS.md).
|
||||
|
13
RELEASE.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Release Procedure
|
||||
|
||||
1. Merge into `main`
|
||||
2. Create tag
|
||||
3. Add changes to changelog + update security document
|
||||
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.zip`
|
||||
9. Upload to GitHub and add to tagged release
|
||||
10. Update Cask with new version + hash
|
||||
11. Check new version can be installed via Cask
|
28
SECURITY.md
Normal file
@ -0,0 +1,28 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported versions
|
||||
|
||||
Generally speaking, only the latest version of **PHP Monitor** is supported, except during transition periods (for example, when particular system requirements go up):
|
||||
|
||||
| Version | Apple Silicon | Supported | Supported macOS | Deployment Target | Detected PHP Versions | Minimum Required Valet Version |
|
||||
| ------- | ------------- | ------------------ | ----- | ----- | ----- | ----
|
||||
| 5.0 | ✅ Universal binary | ✅ Yes | Big Sur (11.0) and Monterey (12.0) | macOS 11+ | PHP 5.6—PHP 8.2 | 2.16.2 |
|
||||
|
||||
## Legacy versions
|
||||
|
||||
These versions of PHP Monitor are no longer supported, but if you’re using an older computer with an older version of Homebrew, Valet or macOS, you might want to use one of these versions.
|
||||
|
||||
| Version | Apple Silicon | Supported | Supported macOS | Deployment Target | Detected PHP Versions | Minimum Required Valet Version |
|
||||
| ------- | ------------- | ------------------ | ----- | ----- | ----- | ----
|
||||
| 4.1 | ✅ Universal binary | ❌ | Big Sur (11.0) and Monterey (12.0) | macOS 11+ | PHP 5.6—PHP 8.2 | 2.16.2 |
|
||||
| 4.0 | ✅ Universal binary | ❌ | Big Sur (11.0) and Monterey (12.0) | macOS 10.14+ | PHP 5.6—PHP 8.2 | 2.13 |
|
||||
| 3.5 | ✅ Universal binary | ❌ | Big Sur (11.0) and Monterey (12.0) | macOS 10.14+ | PHP 5.6—PHP 8.2 | 2.13 |
|
||||
| 3.0—3.4 | ✅ Universal binary | ❌ | Big Sur (11.0) | macOS 10.14+ | PHP 5.6—PHP 8.1 | 2.13 |
|
||||
| 2.6 | ✅ Universal binary | ❌ | Big Sur (11.0) | macOS 10.14+ | PHP 5.6—PHP 8.0 | 2.13 |
|
||||
| 2.5 | ✴️ Universal binary<br/>`/usr/local/homebrew` installations only | ❌ | Big Sur (11.0)<br/>Catalina (10.15) | macOS 10.14+ | not applicable | not applicable |
|
||||
| 2.4 | ✴️ Universal binary<br/>`/usr/local/homebrew` installations only | ❌ | Big Sur (11.0)<br/>Catalina (10.15) | macOS 10.14+ | not applicable | not applicable |
|
||||
| < 2.4 | ❌ Intel binary<br/>`/usr/local/homebrew` installations only | ❌ | Catalina (10.15) | macOS 10.14+ | not applicable | not applicable |
|
||||
|
||||
## Reporting a vulnerability
|
||||
|
||||
Contact me (Nico Verbruggen) at the email address used for the commits in the repository. Please include "PHP Monitor" in the subject.
|
BIN
assets.sketch
1
assets/icon.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg width="512" height="512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><filter x="-4.6%" y="-3.4%" width="109.2%" height="109.2%" filterUnits="objectBoundingBox" id="b"><feOffset dy="5" in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur stdDeviation="5.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.26 0" in="shadowBlurOuter1"/></filter><filter x="-8.6%" y="-11%" width="117.1%" height="121.9%" filterUnits="objectBoundingBox" id="d"><feOffset dx="1" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur stdDeviation="6.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.372049825 0" in="shadowBlurOuter1" result="shadowMatrixOuter1"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="SourceGraphic"/></feMerge></filter><linearGradient x1="50.023%" y1="-15.482%" x2="50.023%" y2="104.493%" id="e"><stop stop-color="#51C2FB" offset=".053%"/><stop stop-color="#1C91FE" offset="100%"/></linearGradient><path d="M167.939 50H344.06c41.01 0 55.881 4.27 70.874 12.288 14.992 8.018 26.759 19.785 34.777 34.777C457.73 112.058 462 126.93 462 167.94V344.06c0 41.01-4.27 55.881-12.288 70.874-8.018 14.992-19.785 26.759-34.777 34.777C399.942 457.73 385.07 462 344.06 462H167.94c-41.01 0-55.881-4.27-70.874-12.288-14.992-8.018-26.759-19.785-34.777-34.777C54.27 399.942 50 385.07 50 344.06V167.94c0-41.01 4.27-55.881 12.288-70.874 8.018-14.992 19.785-26.759 34.777-34.777C112.058 54.27 126.93 50 167.94 50z" id="a"/></defs><g fill="none" fill-rule="evenodd"><mask id="c" fill="#fff"><use xlink:href="#a"/></mask><use filter="url(#b)" xlink:href="#a" fill-rule="nonzero" fill="#000"/><g mask="url(#c)"><path fill="#FFF" d="M50 50h412v412H50z"/></g><g filter="url(#d)" mask="url(#c)"><path fill="#FFF" d="M131.535 155.144l63.377-8.907 33.68 239.645-63.377 8.907zM315.79 263.497l63.377-8.907 15.17 107.94-63.377 8.906z"/><path fill="#FFF" d="M315.79 263.497l63.377-8.907 15.17 107.94-63.377 8.906z"/><path fill="#FFF" d="M316.01 173.224l84.001 68.319-53.919 66.92-84-68.318z"/><path fill="#FFF" d="M93.155 157.813l164.384-23.102 21.433 152.5-164.385 23.104z"/><path d="M133.3 83.75h-12.9V54.437c0-2.303-1.935-4.187-4.3-4.187h-8.6c-2.365 0-4.3 1.884-4.3 4.188v41.874c0 2.304 1.935 4.188 4.3 4.188h25.8c2.365 0 4.3-1.884 4.3-4.188v-8.374c0-2.304-1.935-4.188-4.3-4.188zm202.1 100.5h-8.6v-56.584c0-6.647-2.741-13.033-7.579-17.744L265.525 57.63c-4.837-4.71-11.395-7.38-18.221-7.38H223.6V25.125C223.6 11.254 212.044 0 197.8 0h-172C11.556 0 0 11.254 0 25.125v167.5c0 13.871 11.556 25.125 25.8 25.125h8.6C34.4 245.492 57.513 268 86 268c28.487 0 51.6-22.508 51.6-50.25h68.8c0 27.742 23.112 50.25 51.6 50.25 28.488 0 51.6-22.508 51.6-50.25h25.8c4.73 0 8.6-3.769 8.6-8.375v-16.75c0-4.606-3.87-8.375-8.6-8.375zM86 242.875c-14.244 0-25.8-11.254-25.8-25.125s11.556-25.125 25.8-25.125c14.244 0 25.8 11.254 25.8 25.125s-11.556 25.125-25.8 25.125zm25.8-92.125c-33.271 0-60.2-26.224-60.2-58.625 0-32.4 26.929-58.625 60.2-58.625S172 59.724 172 92.125c0 32.4-26.929 58.625-60.2 58.625zM258 242.875c-14.244 0-25.8-11.254-25.8-25.125s11.556-25.125 25.8-25.125c14.244 0 25.8 11.254 25.8 25.125s-11.556 25.125-25.8 25.125zM301 134h-77.4V75.375h23.704L301 127.666V134z" fill="url(#e)" fill-rule="nonzero" transform="rotate(-8 1129.292 -453.38)"/></g></g></svg>
|
After Width: | Height: | Size: 3.4 KiB |
BIN
assets/icons.afdesign
Normal file
1
assets/menubar.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg width="22" height="22" xmlns="http://www.w3.org/2000/svg"><path d="M8.975 8.375H8.3V6.844a.223.223 0 00-.225-.219h-.45a.223.223 0 00-.225.219V9.03c0 .12.101.219.225.219h1.35a.223.223 0 00.225-.219v-.437a.223.223 0 00-.225-.219zm10.575 5.25h-.45v-2.956c0-.347-.143-.68-.397-.927l-2.81-2.731a1.37 1.37 0 00-.953-.386H13.7V5.312C13.7 4.588 13.095 4 12.35 4h-9C2.605 4 2 4.588 2 5.313v8.75c0 .724.605 1.312 1.35 1.312h.45C3.8 16.825 5.01 18 6.5 18c1.49 0 2.7-1.176 2.7-2.625h3.6c0 1.45 1.21 2.625 2.7 2.625 1.49 0 2.7-1.176 2.7-2.625h1.35c.247 0 .45-.197.45-.438v-.874a.445.445 0 00-.45-.438zM6.5 16.688c-.745 0-1.35-.588-1.35-1.313s.605-1.313 1.35-1.313c.745 0 1.35.588 1.35 1.313s-.605 1.313-1.35 1.313zm1.35-4.813c-1.74 0-3.15-1.37-3.15-3.063C4.7 7.12 6.11 5.75 7.85 5.75S11 7.12 11 8.813c0 1.692-1.41 3.062-3.15 3.062zm7.65 4.813c-.745 0-1.35-.588-1.35-1.313s.605-1.313 1.35-1.313c.745 0 1.35.588 1.35 1.313s-.605 1.313-1.35 1.313zM17.75 11H13.7V7.937h1.24l2.81 2.732V11z" fill="#000" fill-rule="nonzero"/></svg>
|
After Width: | Height: | Size: 1017 B |
87
assets/source.svg
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
docs/build.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
docs/notification.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
docs/phpmon.png
Before Width: | Height: | Size: 317 KiB |
BIN
docs/screenshot50.jpg
Normal file
After Width: | Height: | Size: 370 KiB |
BIN
integrations/phpmon.alfredworkflow
Normal file
85
phpmon-tests/BrewJsonParserTest.swift
Normal file
@ -0,0 +1,85 @@
|
||||
//
|
||||
// BrewJsonParserTest.swift
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 14/02/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
class BrewJsonParserTest: XCTestCase {
|
||||
|
||||
// - MARK: SYNTHETIC TESTS
|
||||
|
||||
static var jsonBrewFile: URL {
|
||||
return Bundle(for: Self.self)
|
||||
.url(forResource: "brew", withExtension: "json")!
|
||||
}
|
||||
|
||||
func testCanLoadExtensionJson() throws {
|
||||
let json = try! String(contentsOf: Self.jsonBrewFile, encoding: .utf8)
|
||||
let package = try! JSONDecoder().decode(
|
||||
[HomebrewPackage].self, from: json.data(using: .utf8)!
|
||||
).first!
|
||||
|
||||
XCTAssertEqual(package.name, "php")
|
||||
XCTAssertEqual(package.full_name, "php")
|
||||
XCTAssertEqual(package.aliases.first!, "php@8.0")
|
||||
XCTAssertEqual(package.installed.contains(where: { installed in
|
||||
installed.version.starts(with: "8.0")
|
||||
}), true)
|
||||
}
|
||||
|
||||
static var jsonBrewServicesFile: URL {
|
||||
return Bundle(for: Self.self)
|
||||
.url(forResource: "brew-services", withExtension: "json")!
|
||||
}
|
||||
|
||||
func testCanParseServicesJson() throws {
|
||||
let json = try! String(contentsOf: Self.jsonBrewServicesFile, encoding: .utf8)
|
||||
let services = try! JSONDecoder().decode(
|
||||
[HomebrewService].self, from: json.data(using: .utf8)!
|
||||
)
|
||||
|
||||
XCTAssertGreaterThan(services.count, 0)
|
||||
XCTAssertEqual(services.first?.name, "dnsmasq")
|
||||
XCTAssertEqual(services.first?.service_name, "homebrew.mxcl.dnsmasq")
|
||||
}
|
||||
|
||||
// - MARK: LIVE TESTS
|
||||
|
||||
/// This test requires that you have a valid Homebrew installation set up,
|
||||
/// and requires the Valet services to be installed: php, nginx and dnsmasq.
|
||||
/// If this test fails, there is an issue with your Homebrew installation
|
||||
/// or the JSON API of the Homebrew output may have changed.
|
||||
func testCanParseServicesJsonFromCliOutput() throws {
|
||||
let services = try! JSONDecoder().decode(
|
||||
[HomebrewService].self,
|
||||
from: Shell.pipe(
|
||||
"sudo \(Paths.brew) services info --all --json",
|
||||
requiresPath: true
|
||||
).data(using: .utf8)!
|
||||
).filter({ service in
|
||||
return ["php", "nginx", "dnsmasq"].contains(service.name)
|
||||
})
|
||||
|
||||
XCTAssertTrue(services.contains(where: {$0.name == "php"} ))
|
||||
XCTAssertTrue(services.contains(where: {$0.name == "nginx"} ))
|
||||
XCTAssertTrue(services.contains(where: {$0.name == "dnsmasq"} ))
|
||||
XCTAssertEqual(services.count, 3)
|
||||
}
|
||||
|
||||
/// This test requires that you have a valid Homebrew installation set up,
|
||||
/// and requires the `php` formula to be installed.
|
||||
/// If this test fails, there is an issue with your Homebrew installation
|
||||
/// or the JSON API of the Homebrew output may have changed.
|
||||
func testCanLoadExtensionJsonFromCliOutput() throws {
|
||||
let package = try! JSONDecoder().decode(
|
||||
[HomebrewPackage].self,
|
||||
from: Shell.pipe("\(Paths.brew) info php --json", requiresPath: true).data(using: .utf8)!
|
||||
).first!
|
||||
|
||||
XCTAssertTrue(package.name == "php")
|
||||
}
|
||||
}
|
25
phpmon-tests/CommandTest.swift
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// CommandTest.swift
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 13/02/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
class CommandTest: XCTestCase {
|
||||
|
||||
func testDeterminePhpVersion() {
|
||||
let version = Command.execute(
|
||||
path: Paths.php,
|
||||
arguments: ["-v"]
|
||||
)
|
||||
|
||||
XCTAssert(version.contains("(cli)"))
|
||||
XCTAssert(version.contains("NTS"))
|
||||
XCTAssert(version.contains("built"))
|
||||
XCTAssert(version.contains("Zend"))
|
||||
}
|
||||
|
||||
}
|
72
phpmon-tests/ExtensionParserTest.swift
Normal file
@ -0,0 +1,72 @@
|
||||
//
|
||||
// ExtensionParserTest.swift
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 13/02/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
class ExtensionParserTest: XCTestCase {
|
||||
|
||||
static var phpIniFileUrl: URL {
|
||||
return Bundle(for: Self.self).url(forResource: "php", withExtension: "ini")!
|
||||
}
|
||||
|
||||
func testCanLoadExtension() throws {
|
||||
let extensions = PhpExtension.load(from: Self.phpIniFileUrl)
|
||||
|
||||
XCTAssertGreaterThan(extensions.count, 0)
|
||||
}
|
||||
|
||||
func testExtensionNameIsCorrect() throws {
|
||||
let extensions = PhpExtension.load(from: Self.phpIniFileUrl)
|
||||
|
||||
let extensionNames = extensions.map { (ext) -> String in
|
||||
return ext.name
|
||||
}
|
||||
|
||||
// These 6 should be found
|
||||
XCTAssertTrue(extensionNames.contains("xdebug"))
|
||||
XCTAssertTrue(extensionNames.contains("imagick"))
|
||||
XCTAssertTrue(extensionNames.contains("sodium-next"))
|
||||
XCTAssertTrue(extensionNames.contains("opcache"))
|
||||
XCTAssertTrue(extensionNames.contains("yaml"))
|
||||
XCTAssertTrue(extensionNames.contains("custom"))
|
||||
|
||||
XCTAssertFalse(extensionNames.contains("fake"))
|
||||
XCTAssertFalse(extensionNames.contains("nice"))
|
||||
}
|
||||
|
||||
func testExtensionStatusIsCorrect() throws {
|
||||
let extensions = PhpExtension.load(from: Self.phpIniFileUrl)
|
||||
|
||||
// xdebug should be enabled
|
||||
XCTAssertEqual(extensions[0].enabled, true)
|
||||
|
||||
// imagick should be disabled
|
||||
XCTAssertEqual(extensions[1].enabled, false)
|
||||
}
|
||||
|
||||
func testToggleWorksAsExpected() throws {
|
||||
let destination = Utility.copyToTemporaryFile(resourceName: "php", fileExtension: "ini")!
|
||||
let extensions = PhpExtension.load(from: destination)
|
||||
XCTAssertEqual(extensions.count, 6)
|
||||
|
||||
// Try to disable xdebug (should be detected first)!
|
||||
let xdebug = extensions.first!
|
||||
XCTAssertTrue(xdebug.name == "xdebug")
|
||||
XCTAssertEqual(xdebug.enabled, true)
|
||||
xdebug.toggle()
|
||||
XCTAssertEqual(xdebug.enabled, false)
|
||||
|
||||
// Check if the file contains the appropriate data
|
||||
let file = try! String(contentsOf: destination, encoding: .utf8)
|
||||
XCTAssertTrue(file.contains("; zend_extension=\"xdebug.so\""))
|
||||
|
||||
// Make sure if we load the data again, it's disabled
|
||||
XCTAssertEqual(PhpExtension.load(from: destination).first!.enabled, false)
|
||||
}
|
||||
|
||||
}
|
22
phpmon-tests/Info.plist
Normal file
@ -0,0 +1,22 @@
|
||||
<?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>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
29
phpmon-tests/PhpVersionDetectionTest.swift
Normal file
@ -0,0 +1,29 @@
|
||||
//
|
||||
// PhpVersionDetectionTest.swift
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 01/04/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
class PhpVersionDetectionTest: XCTestCase {
|
||||
|
||||
func testCanDetectValidPhpVersions() throws {
|
||||
let outcome = PhpEnv.shared.extractPhpVersions(from: [
|
||||
"", // empty lines should be omitted
|
||||
"php@8.0",
|
||||
"php@8.0", // should only be detected once
|
||||
"meta-php@8.0", // should be omitted, invalid
|
||||
"php@8.0-coolio", // should be omitted, invalid
|
||||
"php@7.0",
|
||||
"",
|
||||
"unrelatedphp@1.0", // should be omitted, invalid
|
||||
"php@5.6",
|
||||
"php@5.4" // should be omitted, not supported
|
||||
], checkBinaries: false)
|
||||
|
||||
XCTAssertEqual(outcome, ["8.0", "7.0", "5.6"])
|
||||
}
|
||||
}
|
286
phpmon-tests/PhpVersionNumberTest.swift
Normal file
@ -0,0 +1,286 @@
|
||||
//
|
||||
// PhpVersionNumberTest.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 23/01/2022.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
class PhpVersionNumberTest: XCTestCase {
|
||||
|
||||
func testCanDeconstructPhpVersion() throws {
|
||||
XCTAssertEqual(
|
||||
try! PhpVersionNumber.parse("PHP 8.1.0RC5-dev"),
|
||||
PhpVersionNumber(major: 8, minor: 1, patch: 0)
|
||||
)
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumber.make(from: "8.0.11"),
|
||||
PhpVersionNumber(major: 8, minor: 0, patch: 11)
|
||||
)
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumber.make(from: "7.4.2"),
|
||||
PhpVersionNumber(major: 7, minor: 4, patch: 2)
|
||||
)
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumber.make(from: "7.4"),
|
||||
PhpVersionNumber(major: 7, minor: 4, patch: nil)
|
||||
)
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumber.make(from: "7"),
|
||||
nil
|
||||
)
|
||||
}
|
||||
|
||||
func testPhpVersionNumberParse() throws {
|
||||
XCTAssertThrowsError(try PhpVersionNumber.parse("OOF")) { error in
|
||||
XCTAssertTrue(error is VersionParseError)
|
||||
}
|
||||
}
|
||||
|
||||
func testCanCheckFixedConstraints() throws {
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||
.matching(constraint: "7.0"),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.0"]).all
|
||||
)
|
||||
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4.3", "7.3.3", "7.2.3", "7.1.3", "7.0.3"])
|
||||
.matching(constraint: "7.0.3"),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.0.3"]).all
|
||||
)
|
||||
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||
.matching(constraint: "7.0.3", strict: false),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.0"]).all
|
||||
)
|
||||
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||
.matching(constraint: "7.0.3", strict: true),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: []).all
|
||||
)
|
||||
}
|
||||
|
||||
func testCanCheckCaretConstraints() throws {
|
||||
// 1. Imprecise checks
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||
.matching(constraint: "^7.0", strict: true),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"]).all
|
||||
)
|
||||
|
||||
// 2. Imprecise check with precise constraint (lenient AKA not strict)
|
||||
// These versions are interpreted as 7.4.999, 7.3.999, 7.2.999, etc.
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||
.matching(constraint: "^7.0.1", strict: false),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"]).all
|
||||
)
|
||||
|
||||
// 3. Imprecise check with precise constraint (strict mode)
|
||||
// These versions are interpreted as 7.4.0, 7.3.0, 7.2.0, etc.
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||
.matching(constraint: "^7.0.1", strict: true),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1"]).all
|
||||
)
|
||||
|
||||
// 4. Precise members and constraint all around
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4.10", "7.3.10", "7.2.10", "7.1.10", "7.0.10"])
|
||||
.matching(constraint: "^7.0.1", strict: true),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4.10", "7.3.10", "7.2.10", "7.1.10", "7.0.10"]).all
|
||||
)
|
||||
|
||||
// 5. Precise members but imprecise constraint (strict mode)
|
||||
// In strict mode the constraint's patch version is assumed to be 0
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4.10", "7.3.10", "7.2.10", "7.1.10", "7.0.10"])
|
||||
.matching(constraint: "^7.0", strict: true),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4.10", "7.3.10", "7.2.10", "7.1.10", "7.0.10"]).all
|
||||
)
|
||||
|
||||
// 6. Precise members but imprecise constraint (lenient mode)
|
||||
// In lenient mode the constraint's patch version is assumed to be equal
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4.10", "7.3.10", "7.2.10", "7.1.10", "7.0.10"])
|
||||
.matching(constraint: "^7.0", strict: false),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4.10", "7.3.10", "7.2.10", "7.1.10", "7.0.10"]).all
|
||||
)
|
||||
}
|
||||
|
||||
func testCanCheckTildeConstraints() throws {
|
||||
// 1. Imprecise checks
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||
.matching(constraint: "~7.0", strict: true),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"]).all
|
||||
)
|
||||
|
||||
// 2. Imprecise check with precise constraint (lenient AKA not strict)
|
||||
// These versions are interpreted as 7.4.999, 7.3.999, 7.2.999, etc.
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||
.matching(constraint: "~7.0.1", strict: false),
|
||||
// One result because 7.0.1 to 7.0.x is expected.
|
||||
// 7.0.999 (assumed due to no strictness) is valid.
|
||||
// 7.1.0 and up are not valid (minor version is too high).
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.0"]).all
|
||||
)
|
||||
|
||||
// 3. Imprecise check with precise constraint (strict mode)
|
||||
// These versions are interpreted as 7.4.0, 7.3.0, 7.2.0, etc.
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||
.matching(constraint: "~7.0.1", strict: true),
|
||||
// No results because 7.0.1 to 7.0.x is expected.
|
||||
// 7.0.0 (assumed due to strictness) is not valid.
|
||||
// 7.1.0 and up are also not valid (minor version is too high).
|
||||
PhpVersionNumberCollection
|
||||
.make(from: []).all
|
||||
)
|
||||
|
||||
// 4. Precise members and constraint all around
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4.10", "7.3.10", "7.2.10", "7.1.10", "7.0.10"])
|
||||
.matching(constraint: "~7.0.1", strict: true),
|
||||
// Only 7.0 with a patch version of .1 or higher is OK.
|
||||
// In this example, 7.0.10 is OK but all other versions are too new.
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.0.10"]).all
|
||||
)
|
||||
|
||||
// 5. Precise members but imprecise constraint (strict mode)
|
||||
// In strict mode the constraint's patch version is assumed to be 0.
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4.10", "7.3.10", "7.2.10", "7.1.10", "7.0.10"])
|
||||
.matching(constraint: "~7.0", strict: true),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4.10", "7.3.10", "7.2.10", "7.1.10", "7.0.10"]).all
|
||||
)
|
||||
|
||||
// 6. Precise members but imprecise constraint (lenient mode)
|
||||
// In lenient mode the constraint's patch version is assumed to be equal.
|
||||
// (Strictness does not make any difference here, but both should be tested.)
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4.10", "7.3.10", "7.2.10", "7.1.10", "7.0.10"])
|
||||
.matching(constraint: "~7.0", strict: false),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4.10", "7.3.10", "7.2.10", "7.1.10", "7.0.10"]).all
|
||||
)
|
||||
}
|
||||
|
||||
func testCanCheckGreaterThanOrEqualConstraints() throws {
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||
.matching(constraint: ">=7.0", strict: true),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"]).all
|
||||
)
|
||||
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||
.matching(constraint: ">=7.0.0", strict: true),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"]).all
|
||||
)
|
||||
|
||||
// Strict check (>7.2.5 is too new for 7.2 which resolves to 7.2.0)
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||
.matching(constraint: ">=7.2.5", strict: true),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3"]).all
|
||||
)
|
||||
|
||||
// Non-strict check (ignoring patch, 7.2 resolves to 7.2.999)
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||
.matching(constraint: ">=7.2.5", strict: false),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2"]).all
|
||||
)
|
||||
}
|
||||
|
||||
func testCanCheckGreaterThanConstraints() throws {
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||
.matching(constraint: ">7.0"),
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1"]).all
|
||||
)
|
||||
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||
.matching(constraint: ">7.2.5"),
|
||||
// 7.2 will be valid due to non-strict mode (resolves to 7.2.999)
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2"]).all
|
||||
)
|
||||
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
|
||||
.matching(constraint: ">7.2.5", strict: true),
|
||||
// 7.2 will not be valid due to strict mode (resolves to 7.2.0)
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.4", "7.3"]).all
|
||||
)
|
||||
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.3.1", "7.2.9", "7.2.8", "7.2.6", "7.2.5", "7.2"])
|
||||
.matching(constraint: ">7.2.8"),
|
||||
// 7.2 will be valid due to non-strict mode (resolves to 7.2.999)
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.3.1", "7.2.9", "7.2"]).all
|
||||
)
|
||||
|
||||
XCTAssertEqual(
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.3.1", "7.2.9", "7.2.8", "7.2.6", "7.2.5", "7.2"])
|
||||
.matching(constraint: ">7.2.8", strict: true),
|
||||
// 7.2 will not be valid due to strict mode (resolves to 7.2.0)
|
||||
PhpVersionNumberCollection
|
||||
.make(from: ["7.3.1", "7.2.9"]).all
|
||||
)
|
||||
}
|
||||
}
|
135
phpmon-tests/Test Files/brew-services.json
Normal file
@ -0,0 +1,135 @@
|
||||
[
|
||||
{
|
||||
"name": "dnsmasq",
|
||||
"service_name": "homebrew.mxcl.dnsmasq",
|
||||
"running": true,
|
||||
"loaded": true,
|
||||
"schedulable": false,
|
||||
"pid": 106,
|
||||
"exit_code": 0,
|
||||
"user": "root",
|
||||
"status": "started",
|
||||
"file": "/Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist",
|
||||
"command": "/opt/homebrew/opt/dnsmasq/sbin/dnsmasq --keep-in-foreground -C /opt/homebrew/etc/dnsmasq.conf -7 /opt/homebrew/etc/dnsmasq.d,*.conf",
|
||||
"working_dir": null,
|
||||
"root_dir": null,
|
||||
"log_path": null,
|
||||
"error_log_path": null,
|
||||
"interval": null,
|
||||
"cron": null
|
||||
},
|
||||
{
|
||||
"name": "httpd",
|
||||
"service_name": "homebrew.mxcl.httpd",
|
||||
"running": false,
|
||||
"loaded": false,
|
||||
"schedulable": false,
|
||||
"pid": null,
|
||||
"exit_code": null,
|
||||
"user": null,
|
||||
"status": "none",
|
||||
"file": "/opt/homebrew/opt/httpd/homebrew.mxcl.httpd.plist",
|
||||
"command": "/opt/homebrew/opt/httpd/bin/httpd -D FOREGROUND",
|
||||
"working_dir": null,
|
||||
"root_dir": null,
|
||||
"log_path": null,
|
||||
"error_log_path": null,
|
||||
"interval": null,
|
||||
"cron": null
|
||||
},
|
||||
{
|
||||
"name": "mailhog",
|
||||
"service_name": "homebrew.mxcl.mailhog",
|
||||
"running": false,
|
||||
"loaded": false,
|
||||
"schedulable": false,
|
||||
"pid": null,
|
||||
"exit_code": null,
|
||||
"user": null,
|
||||
"status": "none",
|
||||
"file": "/opt/homebrew/opt/mailhog/homebrew.mxcl.mailhog.plist",
|
||||
"command": "/opt/homebrew/opt/mailhog/bin/MailHog",
|
||||
"working_dir": null,
|
||||
"root_dir": null,
|
||||
"log_path": "/opt/homebrew/var/log/mailhog.log",
|
||||
"error_log_path": "/opt/homebrew/var/log/mailhog.log",
|
||||
"interval": null,
|
||||
"cron": null
|
||||
},
|
||||
{
|
||||
"name": "nginx",
|
||||
"service_name": "homebrew.mxcl.nginx",
|
||||
"running": true,
|
||||
"loaded": true,
|
||||
"schedulable": false,
|
||||
"pid": 116,
|
||||
"exit_code": 0,
|
||||
"user": "root",
|
||||
"status": "started",
|
||||
"file": "/Library/LaunchDaemons/homebrew.mxcl.nginx.plist",
|
||||
"command": "/opt/homebrew/opt/nginx/bin/nginx -g daemon off;",
|
||||
"working_dir": "/opt/homebrew",
|
||||
"root_dir": null,
|
||||
"log_path": null,
|
||||
"error_log_path": null,
|
||||
"interval": null,
|
||||
"cron": null
|
||||
},
|
||||
{
|
||||
"name": "php",
|
||||
"service_name": "homebrew.mxcl.php",
|
||||
"running": true,
|
||||
"loaded": true,
|
||||
"schedulable": false,
|
||||
"pid": 142,
|
||||
"exit_code": 0,
|
||||
"user": "root",
|
||||
"status": "started",
|
||||
"file": "/Library/LaunchDaemons/homebrew.mxcl.php.plist",
|
||||
"command": "/opt/homebrew/opt/php/sbin/php-fpm --nodaemonize",
|
||||
"working_dir": "/opt/homebrew/var",
|
||||
"root_dir": null,
|
||||
"log_path": null,
|
||||
"error_log_path": "/opt/homebrew/var/log/php-fpm.log",
|
||||
"interval": null,
|
||||
"cron": null
|
||||
},
|
||||
{
|
||||
"name": "php@8.0",
|
||||
"service_name": "homebrew.mxcl.php@8.0",
|
||||
"running": false,
|
||||
"loaded": false,
|
||||
"schedulable": false,
|
||||
"pid": null,
|
||||
"exit_code": null,
|
||||
"user": null,
|
||||
"status": "none",
|
||||
"file": "/opt/homebrew/opt/php@8.0/homebrew.mxcl.php@8.0.plist",
|
||||
"command": "/opt/homebrew/opt/php@8.0/sbin/php-fpm --nodaemonize",
|
||||
"working_dir": "/opt/homebrew/var",
|
||||
"root_dir": null,
|
||||
"log_path": null,
|
||||
"error_log_path": "/opt/homebrew/var/log/php-fpm.log",
|
||||
"interval": null,
|
||||
"cron": null
|
||||
},
|
||||
{
|
||||
"name": "unbound",
|
||||
"service_name": "homebrew.mxcl.unbound",
|
||||
"running": false,
|
||||
"loaded": false,
|
||||
"schedulable": false,
|
||||
"pid": null,
|
||||
"exit_code": null,
|
||||
"user": null,
|
||||
"status": "none",
|
||||
"file": "/opt/homebrew/opt/unbound/homebrew.mxcl.unbound.plist",
|
||||
"command": "/opt/homebrew/opt/unbound/sbin/unbound -d -c /opt/homebrew/etc/unbound/unbound.conf",
|
||||
"working_dir": null,
|
||||
"root_dir": null,
|
||||
"log_path": null,
|
||||
"error_log_path": null,
|
||||
"interval": null,
|
||||
"cron": null
|
||||
}
|
||||
]
|
332
phpmon-tests/Test Files/brew.json
Normal file
@ -0,0 +1,332 @@
|
||||
[
|
||||
{
|
||||
"name":"php",
|
||||
"full_name":"php",
|
||||
"tap":"homebrew/core",
|
||||
"oldname":null,
|
||||
"aliases":[
|
||||
"php@8.0"
|
||||
],
|
||||
"versioned_formulae":[
|
||||
"php@7.4",
|
||||
"php@7.3",
|
||||
"php@7.2"
|
||||
],
|
||||
"desc":"General-purpose scripting language",
|
||||
"license":"PHP-3.01",
|
||||
"homepage":"https://www.php.net/",
|
||||
"versions":{
|
||||
"stable":"8.0.2",
|
||||
"head":"HEAD",
|
||||
"bottle":true
|
||||
},
|
||||
"urls":{
|
||||
"stable":{
|
||||
"url":"https://www.php.net/distributions/php-8.0.2.tar.xz",
|
||||
"tag":null,
|
||||
"revision":null
|
||||
}
|
||||
},
|
||||
"revision":0,
|
||||
"version_scheme":0,
|
||||
"bottle":{
|
||||
"stable":{
|
||||
"rebuild":0,
|
||||
"cellar":"/opt/homebrew/Cellar",
|
||||
"prefix":"/opt/homebrew",
|
||||
"root_url":"https://homebrew.bintray.com/bottles",
|
||||
"files":{
|
||||
"arm64_big_sur":{
|
||||
"url":"https://homebrew.bintray.com/bottles/php-8.0.2.arm64_big_sur.bottle.tar.gz",
|
||||
"sha256":"cbefa1db73d08b9af4593a44512b8d727e43033ee8517736bae5f16315501b12"
|
||||
},
|
||||
"big_sur":{
|
||||
"url":"https://homebrew.bintray.com/bottles/php-8.0.2.big_sur.bottle.tar.gz",
|
||||
"sha256":"6857142e12254b15da4e74c2986dd24faca57dac8d467b04621db349e277dd63"
|
||||
},
|
||||
"catalina":{
|
||||
"url":"https://homebrew.bintray.com/bottles/php-8.0.2.catalina.bottle.tar.gz",
|
||||
"sha256":"b651611134c18f93fdf121a4277b51b197a896a19ccb8020289b4e19e0638349"
|
||||
},
|
||||
"mojave":{
|
||||
"url":"https://homebrew.bintray.com/bottles/php-8.0.2.mojave.bottle.tar.gz",
|
||||
"sha256":"9583a51fcc6f804aadbb14e18f770d4fb4973deaed6ddc4770342e62974ffbca"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"keg_only":false,
|
||||
"bottle_disabled":false,
|
||||
"options":[
|
||||
|
||||
],
|
||||
"build_dependencies":[
|
||||
"httpd",
|
||||
"pkg-config"
|
||||
],
|
||||
"dependencies":[
|
||||
"apr",
|
||||
"apr-util",
|
||||
"argon2",
|
||||
"aspell",
|
||||
"autoconf",
|
||||
"curl",
|
||||
"freetds",
|
||||
"gd",
|
||||
"gettext",
|
||||
"glib",
|
||||
"gmp",
|
||||
"icu4c",
|
||||
"krb5",
|
||||
"libffi",
|
||||
"libpq",
|
||||
"libsodium",
|
||||
"libzip",
|
||||
"oniguruma",
|
||||
"openldap",
|
||||
"openssl@1.1",
|
||||
"pcre2",
|
||||
"sqlite",
|
||||
"tidy-html5",
|
||||
"unixodbc"
|
||||
],
|
||||
"recommended_dependencies":[
|
||||
|
||||
],
|
||||
"optional_dependencies":[
|
||||
|
||||
],
|
||||
"uses_from_macos":[
|
||||
{
|
||||
"xz":"build"
|
||||
},
|
||||
"bzip2",
|
||||
"libedit",
|
||||
"libxml2",
|
||||
"libxslt",
|
||||
"zlib"
|
||||
],
|
||||
"requirements":[
|
||||
|
||||
],
|
||||
"conflicts_with":[
|
||||
|
||||
],
|
||||
"caveats":"To enable PHP in Apache add the following to httpd.conf and restart Apache:\n LoadModule php_module $(brew --prefix)/opt/php/lib/httpd/modules/libphp.so\n\n <FilesMatch \\.php$>\n SetHandler application/x-httpd-php\n </FilesMatch>\n\nFinally, check DirectoryIndex includes index.php\n DirectoryIndex index.php index.html\n\nThe php.ini and php-fpm.ini file can be found in:\n $(brew --prefix)/etc/php/8.0/\n",
|
||||
"installed":[
|
||||
{
|
||||
"version":"8.0.2",
|
||||
"used_options":[
|
||||
|
||||
],
|
||||
"built_as_bottle":true,
|
||||
"poured_from_bottle":true,
|
||||
"runtime_dependencies":[
|
||||
{
|
||||
"full_name":"apr",
|
||||
"version":"1.7.0"
|
||||
},
|
||||
{
|
||||
"full_name":"openssl@1.1",
|
||||
"version":"1.1.1i"
|
||||
},
|
||||
{
|
||||
"full_name":"apr-util",
|
||||
"version":"1.6.1"
|
||||
},
|
||||
{
|
||||
"full_name":"argon2",
|
||||
"version":"20190702"
|
||||
},
|
||||
{
|
||||
"full_name":"aspell",
|
||||
"version":"0.60.8"
|
||||
},
|
||||
{
|
||||
"full_name":"autoconf",
|
||||
"version":"2.69"
|
||||
},
|
||||
{
|
||||
"full_name":"brotli",
|
||||
"version":"1.0.9"
|
||||
},
|
||||
{
|
||||
"full_name":"gettext",
|
||||
"version":"0.21"
|
||||
},
|
||||
{
|
||||
"full_name":"libunistring",
|
||||
"version":"0.9.10"
|
||||
},
|
||||
{
|
||||
"full_name":"libidn2",
|
||||
"version":"2.3.0"
|
||||
},
|
||||
{
|
||||
"full_name":"libmetalink",
|
||||
"version":"0.1.3"
|
||||
},
|
||||
{
|
||||
"full_name":"libssh2",
|
||||
"version":"1.9.0"
|
||||
},
|
||||
{
|
||||
"full_name":"c-ares",
|
||||
"version":"1.17.1"
|
||||
},
|
||||
{
|
||||
"full_name":"jemalloc",
|
||||
"version":"5.2.1"
|
||||
},
|
||||
{
|
||||
"full_name":"libev",
|
||||
"version":"4.33"
|
||||
},
|
||||
{
|
||||
"full_name":"nghttp2",
|
||||
"version":"1.43.0"
|
||||
},
|
||||
{
|
||||
"full_name":"openldap",
|
||||
"version":"2.4.57"
|
||||
},
|
||||
{
|
||||
"full_name":"rtmpdump",
|
||||
"version":"2.4+20151223"
|
||||
},
|
||||
{
|
||||
"full_name":"zstd",
|
||||
"version":"1.4.8"
|
||||
},
|
||||
{
|
||||
"full_name":"curl",
|
||||
"version":"7.75.0"
|
||||
},
|
||||
{
|
||||
"full_name":"libtool",
|
||||
"version":"2.4.6"
|
||||
},
|
||||
{
|
||||
"full_name":"unixodbc",
|
||||
"version":"2.3.9"
|
||||
},
|
||||
{
|
||||
"full_name":"freetds",
|
||||
"version":"1.2.18"
|
||||
},
|
||||
{
|
||||
"full_name":"libpng",
|
||||
"version":"1.6.37"
|
||||
},
|
||||
{
|
||||
"full_name":"freetype",
|
||||
"version":"2.10.4"
|
||||
},
|
||||
{
|
||||
"full_name":"fontconfig",
|
||||
"version":"2.13.1"
|
||||
},
|
||||
{
|
||||
"full_name":"jpeg",
|
||||
"version":"9d"
|
||||
},
|
||||
{
|
||||
"full_name":"libtiff",
|
||||
"version":"4.2.0"
|
||||
},
|
||||
{
|
||||
"full_name":"webp",
|
||||
"version":"1.2.0"
|
||||
},
|
||||
{
|
||||
"full_name":"gd",
|
||||
"version":"2.3.1"
|
||||
},
|
||||
{
|
||||
"full_name":"libffi",
|
||||
"version":"3.3"
|
||||
},
|
||||
{
|
||||
"full_name":"pcre",
|
||||
"version":"8.44"
|
||||
},
|
||||
{
|
||||
"full_name":"gdbm",
|
||||
"version":"1.18.1"
|
||||
},
|
||||
{
|
||||
"full_name":"readline",
|
||||
"version":"8.1"
|
||||
},
|
||||
{
|
||||
"full_name":"sqlite",
|
||||
"version":"3.34.0"
|
||||
},
|
||||
{
|
||||
"full_name":"tcl-tk",
|
||||
"version":"8.6.11"
|
||||
},
|
||||
{
|
||||
"full_name":"xz",
|
||||
"version":"5.2.5"
|
||||
},
|
||||
{
|
||||
"full_name":"python@3.9",
|
||||
"version":"3.9.1"
|
||||
},
|
||||
{
|
||||
"full_name":"glib",
|
||||
"version":"2.66.6"
|
||||
},
|
||||
{
|
||||
"full_name":"gmp",
|
||||
"version":"6.2.1"
|
||||
},
|
||||
{
|
||||
"full_name":"icu4c",
|
||||
"version":"67.1"
|
||||
},
|
||||
{
|
||||
"full_name":"krb5",
|
||||
"version":"1.19"
|
||||
},
|
||||
{
|
||||
"full_name":"libpq",
|
||||
"version":"13.1"
|
||||
},
|
||||
{
|
||||
"full_name":"libsodium",
|
||||
"version":"1.0.18"
|
||||
},
|
||||
{
|
||||
"full_name":"libzip",
|
||||
"version":"1.7.3"
|
||||
},
|
||||
{
|
||||
"full_name":"oniguruma",
|
||||
"version":"6.9.6"
|
||||
},
|
||||
{
|
||||
"full_name":"pcre2",
|
||||
"version":"10.36"
|
||||
},
|
||||
{
|
||||
"full_name":"tidy-html5",
|
||||
"version":"5.6.0"
|
||||
}
|
||||
],
|
||||
"installed_as_dependency":false,
|
||||
"installed_on_request":true
|
||||
}
|
||||
],
|
||||
"linked_keg":"8.0.2",
|
||||
"pinned":false,
|
||||
"outdated":false,
|
||||
"deprecated":false,
|
||||
"deprecation_date":null,
|
||||
"deprecation_reason":null,
|
||||
"disabled":false,
|
||||
"disable_date":null,
|
||||
"disable_reason":null
|
||||
}
|
||||
]
|
1957
phpmon-tests/Test Files/php.ini
Normal file
8
phpmon-tests/Test Files/valet-config.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"tld": "test",
|
||||
"paths": [
|
||||
"/Users/username/.config/valet/Sites",
|
||||
"/Users/username/Sites"
|
||||
],
|
||||
"loopback": "127.0.0.1"
|
||||
}
|
28
phpmon-tests/Utility.swift
Normal file
@ -0,0 +1,28 @@
|
||||
//
|
||||
// Utility.swift
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 14/02/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class Utility {
|
||||
|
||||
public static func copyToTemporaryFile(resourceName: String, fileExtension: String) -> URL? {
|
||||
if let bundleURL = Bundle(for: Self.self).url(forResource: resourceName, withExtension: fileExtension) {
|
||||
let tempDirectoryURL = NSURL.fileURL(withPath: NSTemporaryDirectory(), isDirectory: true)
|
||||
let targetURL = tempDirectoryURL.appendingPathComponent("\(UUID().uuidString).\(fileExtension)")
|
||||
|
||||
do {
|
||||
try FileManager.default.copyItem(at: bundleURL, to: targetURL)
|
||||
return targetURL
|
||||
} catch let error {
|
||||
Log.err("Unable to copy file: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
38
phpmon-tests/ValetConfigParserTest.swift
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// ValetConfigParserTest.swift
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 29/11/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
class ValetConfigParserTest: XCTestCase {
|
||||
|
||||
static var jsonConfigFileUrl: URL {
|
||||
return Bundle(for: Self.self).url(
|
||||
forResource: "valet-config",
|
||||
withExtension: "json"
|
||||
)!
|
||||
}
|
||||
|
||||
func testCanLoadConfigFile() throws {
|
||||
let json = try? String(
|
||||
contentsOf: Self.jsonConfigFileUrl,
|
||||
encoding: .utf8
|
||||
)
|
||||
let config = try! JSONDecoder().decode(
|
||||
Valet.Configuration.self,
|
||||
from: json!.data(using: .utf8)!
|
||||
)
|
||||
|
||||
XCTAssertEqual(config.tld, "test")
|
||||
XCTAssertEqual(config.paths, [
|
||||
"/Users/username/.config/valet/Sites",
|
||||
"/Users/username/Sites"
|
||||
])
|
||||
XCTAssertEqual(config.loopback, "127.0.0.1")
|
||||
}
|
||||
|
||||
}
|
18
phpmon-tests/ValetTest.swift
Normal file
@ -0,0 +1,18 @@
|
||||
//
|
||||
// ValetTest.swift
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 29/11/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
class ValetTest: XCTestCase {
|
||||
|
||||
func testDetermineValetVersion() {
|
||||
let version = valet("--version")
|
||||
XCTAssert(version.contains("Laravel Valet 2."))
|
||||
}
|
||||
|
||||
}
|
25
phpmon-tests/VersionExtractorTest.swift
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// VersionExtractorTest.swift
|
||||
// phpmon-tests
|
||||
//
|
||||
// Created by Nico Verbruggen on 16/12/2021.
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
class VersionExtractorTest: XCTestCase {
|
||||
|
||||
func testExtractVersion() {
|
||||
XCTAssertEqual(VersionExtractor.from("Laravel Valet 2.17.1"), "2.17.1")
|
||||
XCTAssertEqual(VersionExtractor.from("Laravel Valet 2.0"), "2.0")
|
||||
}
|
||||
|
||||
func testVersionComparison() {
|
||||
XCTAssertEqual("2.0".versionCompare("2.1"), .orderedAscending)
|
||||
XCTAssertEqual("2.1".versionCompare("2.0"), .orderedDescending)
|
||||
XCTAssertEqual("2.0".versionCompare("2.0"), .orderedSame)
|
||||
XCTAssertEqual("2.17.0".versionCompare("2.17.1"), .orderedAscending)
|
||||
}
|
||||
|
||||
}
|
@ -1,396 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 50;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
C41C1B3722B0097F00E7CF16 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B3622B0097F00E7CF16 /* AppDelegate.swift */; };
|
||||
C41C1B3922B0097F00E7CF16 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B3822B0097F00E7CF16 /* ViewController.swift */; };
|
||||
C41C1B3B22B0098000E7CF16 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C41C1B3A22B0098000E7CF16 /* Assets.xcassets */; };
|
||||
C41C1B3E22B0098000E7CF16 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C41C1B3C22B0098000E7CF16 /* Main.storyboard */; };
|
||||
C41C1B4722B009A400E7CF16 /* Shell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4622B009A400E7CF16 /* Shell.swift */; };
|
||||
C41C1B4922B00A9800E7CF16 /* ImageGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4822B00A9800E7CF16 /* ImageGenerator.swift */; };
|
||||
C41C1B4B22B019FF00E7CF16 /* PhpVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4A22B019FF00E7CF16 /* PhpVersion.swift */; };
|
||||
C41C1B4D22B0215A00E7CF16 /* Services.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4C22B0215A00E7CF16 /* Services.swift */; };
|
||||
C476FF9822B0DD830098105B /* Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = C476FF9722B0DD830098105B /* Alert.swift */; };
|
||||
C4D8016622B1584700C6DA1B /* BootChecks.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D8016522B1584700C6DA1B /* BootChecks.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
C41C1B3322B0097F00E7CF16 /* phpmon.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = phpmon.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C41C1B3622B0097F00E7CF16 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
C41C1B3822B0097F00E7CF16 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
C41C1B3A22B0098000E7CF16 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
C41C1B3D22B0098000E7CF16 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
C41C1B3F22B0098000E7CF16 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
C41C1B4022B0098000E7CF16 /* phpmon.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = phpmon.entitlements; sourceTree = "<group>"; };
|
||||
C41C1B4622B009A400E7CF16 /* Shell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shell.swift; sourceTree = "<group>"; };
|
||||
C41C1B4822B00A9800E7CF16 /* ImageGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageGenerator.swift; sourceTree = "<group>"; };
|
||||
C41C1B4A22B019FF00E7CF16 /* PhpVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpVersion.swift; sourceTree = "<group>"; };
|
||||
C41C1B4C22B0215A00E7CF16 /* Services.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Services.swift; sourceTree = "<group>"; };
|
||||
C476FF9722B0DD830098105B /* Alert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Alert.swift; sourceTree = "<group>"; };
|
||||
C4D8016522B1584700C6DA1B /* BootChecks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BootChecks.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
C41C1B3022B0097F00E7CF16 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
C41C1B2A22B0097F00E7CF16 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C41C1B3522B0097F00E7CF16 /* phpmon */,
|
||||
C41C1B3422B0097F00E7CF16 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C41C1B3422B0097F00E7CF16 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C41C1B3322B0097F00E7CF16 /* phpmon.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C41C1B3522B0097F00E7CF16 /* phpmon */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C41E181722CB61EB0072CF09 /* Classes */,
|
||||
C41E181622CB61890072CF09 /* Startup */,
|
||||
C41E181522CB614C0072CF09 /* Terminal */,
|
||||
C41C1B4E22B024F100E7CF16 /* Helpers */,
|
||||
C41E181822CB62200072CF09 /* View Controllers */,
|
||||
C41C1B3622B0097F00E7CF16 /* AppDelegate.swift */,
|
||||
C41C1B3F22B0098000E7CF16 /* Info.plist */,
|
||||
C41C1B4022B0098000E7CF16 /* phpmon.entitlements */,
|
||||
C41C1B3A22B0098000E7CF16 /* Assets.xcassets */,
|
||||
);
|
||||
path = phpmon;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C41C1B4E22B024F100E7CF16 /* Helpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C41C1B4822B00A9800E7CF16 /* ImageGenerator.swift */,
|
||||
C476FF9722B0DD830098105B /* Alert.swift */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C41E181522CB614C0072CF09 /* Terminal */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C41C1B4622B009A400E7CF16 /* Shell.swift */,
|
||||
C41C1B4C22B0215A00E7CF16 /* Services.swift */,
|
||||
);
|
||||
path = Terminal;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C41E181622CB61890072CF09 /* Startup */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C4D8016522B1584700C6DA1B /* BootChecks.swift */,
|
||||
);
|
||||
path = Startup;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C41E181722CB61EB0072CF09 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C41C1B4A22B019FF00E7CF16 /* PhpVersion.swift */,
|
||||
);
|
||||
path = Classes;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C41E181822CB62200072CF09 /* View Controllers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C41C1B3C22B0098000E7CF16 /* Main.storyboard */,
|
||||
C41C1B3822B0097F00E7CF16 /* ViewController.swift */,
|
||||
);
|
||||
path = "View Controllers";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
C41C1B3222B0097F00E7CF16 /* phpmon */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = C41C1B4322B0098000E7CF16 /* Build configuration list for PBXNativeTarget "phpmon" */;
|
||||
buildPhases = (
|
||||
C41C1B2F22B0097F00E7CF16 /* Sources */,
|
||||
C41C1B3022B0097F00E7CF16 /* Frameworks */,
|
||||
C41C1B3122B0097F00E7CF16 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = phpmon;
|
||||
productName = phpmon;
|
||||
productReference = C41C1B3322B0097F00E7CF16 /* phpmon.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
C41C1B2B22B0097F00E7CF16 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1020;
|
||||
LastUpgradeCheck = 1020;
|
||||
ORGANIZATIONNAME = "Nico Verbruggen";
|
||||
TargetAttributes = {
|
||||
C41C1B3222B0097F00E7CF16 = {
|
||||
CreatedOnToolsVersion = 10.2.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = C41C1B2E22B0097F00E7CF16 /* Build configuration list for PBXProject "phpmon" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = C41C1B2A22B0097F00E7CF16;
|
||||
productRefGroup = C41C1B3422B0097F00E7CF16 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
C41C1B3222B0097F00E7CF16 /* phpmon */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
C41C1B3122B0097F00E7CF16 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C41C1B3B22B0098000E7CF16 /* Assets.xcassets in Resources */,
|
||||
C41C1B3E22B0098000E7CF16 /* Main.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
C41C1B2F22B0097F00E7CF16 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C4D8016622B1584700C6DA1B /* BootChecks.swift in Sources */,
|
||||
C41C1B4722B009A400E7CF16 /* Shell.swift in Sources */,
|
||||
C41C1B4D22B0215A00E7CF16 /* Services.swift in Sources */,
|
||||
C41C1B4922B00A9800E7CF16 /* ImageGenerator.swift in Sources */,
|
||||
C41C1B3922B0097F00E7CF16 /* ViewController.swift in Sources */,
|
||||
C41C1B3722B0097F00E7CF16 /* AppDelegate.swift in Sources */,
|
||||
C41C1B4B22B019FF00E7CF16 /* PhpVersion.swift in Sources */,
|
||||
C476FF9822B0DD830098105B /* Alert.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
C41C1B3C22B0098000E7CF16 /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
C41C1B3D22B0098000E7CF16 /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
C41C1B4122B0098000E7CF16 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C41C1B4222B0098000E7CF16 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
C41C1B4422B0098000E7CF16 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = phpmon/phpmon.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = 8M54J5J787;
|
||||
INFOPLIST_FILE = phpmon/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C41C1B4522B0098000E7CF16 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = phpmon/phpmon.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = 8M54J5J787;
|
||||
INFOPLIST_FILE = phpmon/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
C41C1B2E22B0097F00E7CF16 /* Build configuration list for PBXProject "phpmon" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C41C1B4122B0098000E7CF16 /* Debug */,
|
||||
C41C1B4222B0098000E7CF16 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
C41C1B4322B0098000E7CF16 /* Build configuration list for PBXNativeTarget "phpmon" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C41C1B4422B0098000E7CF16 /* Debug */,
|
||||
C41C1B4522B0098000E7CF16 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = C41C1B2B22B0097F00E7CF16 /* Project object */;
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:phpmon.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
@ -1,8 +0,0 @@
|
||||
<?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>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
@ -1,152 +0,0 @@
|
||||
//
|
||||
// AppDelegate.swift
|
||||
// phpmon
|
||||
//
|
||||
// Created by Nico Verbruggen on 11/06/2019.
|
||||
// Copyright © 2019 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
||||
@NSApplicationMain
|
||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
|
||||
// MARK: - Variables
|
||||
|
||||
let statusItem = NSStatusBar.system.statusItem(withLength: 32)
|
||||
var timer: Timer?
|
||||
var version: PhpVersion? = nil
|
||||
var availablePhpVersions : [String] = []
|
||||
var busy: Bool = false
|
||||
|
||||
// MARK: - Lifecycle
|
||||
|
||||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||||
// Start with the icon
|
||||
self.setStatusBar(image: NSImage(named: NSImage.Name("StatusBarIcon"))!)
|
||||
// Perform environment boot checks
|
||||
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
|
||||
BootChecks.perform()
|
||||
self.availablePhpVersions = Services.detectPhpVersions()
|
||||
print("The following PHP versions were detected:")
|
||||
print(self.availablePhpVersions)
|
||||
self.updatePhpVersionInStatusBar()
|
||||
// Schedule a request to fetch the PHP version every 15 seconds
|
||||
Timer.scheduledTimer(
|
||||
timeInterval: 15,
|
||||
target: self,
|
||||
selector: #selector(self.updatePhpVersionInStatusBar),
|
||||
userInfo: nil,
|
||||
repeats: true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ aNotification: Notification) {
|
||||
// Insert code here to tear down your application
|
||||
}
|
||||
|
||||
// MARK: - UI related
|
||||
|
||||
func setStatusBarImage(version: String) {
|
||||
self.setStatusBar(image: ImageGenerator.generateImageForStatusBar(width: 32.0, text: version))
|
||||
}
|
||||
|
||||
func setStatusBar(image: NSImage) {
|
||||
if let button = statusItem.button {
|
||||
image.isTemplate = true
|
||||
button.image = image
|
||||
}
|
||||
}
|
||||
|
||||
func updateMenu() {
|
||||
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
|
||||
let menu = NSMenu()
|
||||
var string = "We are not sure what version of PHP you are running."
|
||||
if (self.version != nil) {
|
||||
string = "You are running PHP \(self.version!.long)"
|
||||
}
|
||||
menu.addItem(NSMenuItem(title: string, action: nil, keyEquivalent: ""))
|
||||
if (self.version != nil) {
|
||||
// Actions
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
menu.addItem(NSMenuItem(title: "Open php.ini in Finder", action: #selector(self.openActiveConfigFolder), keyEquivalent: ""))
|
||||
// menu.addItem(NSMenuItem(title: "Restart PHP \(self.version!.short) service", action: #selector(self.restartPhp), keyEquivalent: ""))
|
||||
}
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
if (self.availablePhpVersions.count > 0 && !self.busy) {
|
||||
var shortcutKey = 1
|
||||
for index in (0..<self.availablePhpVersions.count).reversed() {
|
||||
let version = self.availablePhpVersions[index]
|
||||
let action = #selector(self.switchToPhpVersion(sender:))
|
||||
let menuItem = NSMenuItem(title: "Switch to PHP \(version)", action: (version == self.version?.short) ? nil : action, keyEquivalent: "\(shortcutKey)")
|
||||
menuItem.tag = index
|
||||
shortcutKey = shortcutKey + 1
|
||||
menu.addItem(menuItem)
|
||||
}
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
}
|
||||
if (self.busy) {
|
||||
menu.addItem(NSMenuItem(title: "Switching PHP versions...", action: nil, keyEquivalent: ""))
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
}
|
||||
menu.addItem(NSMenuItem(title: "About phpmon", action: #selector(self.openAbout), keyEquivalent: ""))
|
||||
menu.addItem(NSMenuItem(title: "Quit phpmon", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q"))
|
||||
DispatchQueue.main.async {
|
||||
self.statusItem.menu = menu
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Callable via Obj-C (#selector)
|
||||
|
||||
@objc func updatePhpVersionInStatusBar() {
|
||||
self.version = PhpVersion()
|
||||
if (self.busy) {
|
||||
DispatchQueue.main.async {
|
||||
self.setStatusBar(image: NSImage(named: NSImage.Name("StatusBarIcon"))!)
|
||||
}
|
||||
} else {
|
||||
DispatchQueue.main.async {
|
||||
self.setStatusBarImage(version: self.version!.short)
|
||||
}
|
||||
}
|
||||
self.updateMenu()
|
||||
}
|
||||
|
||||
@objc public func openAbout() {
|
||||
NSApplication.shared.activate(ignoringOtherApps: true)
|
||||
NSApplication.shared.orderFrontStandardAboutPanel()
|
||||
}
|
||||
|
||||
@objc public func openActiveConfigFolder() {
|
||||
Services.openPhpConfigFolder(version: self.version!.short)
|
||||
}
|
||||
|
||||
@objc public func restartPhp() {
|
||||
Services.restartPhp(version: self.version!.short)
|
||||
}
|
||||
|
||||
@objc public func switchToPhpVersion(sender: AnyObject) {
|
||||
self.setStatusBar(image: NSImage(named: NSImage.Name("StatusBarIcon"))!)
|
||||
let index = sender.tag!
|
||||
let version = self.availablePhpVersions[index]
|
||||
self.busy = true
|
||||
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
|
||||
// Update the PHP version in the status bar
|
||||
self.updatePhpVersionInStatusBar()
|
||||
// Update the menu
|
||||
self.updateMenu()
|
||||
// Switch the PHP version
|
||||
Services.switchToPhpVersion(version: version, availableVersions: self.availablePhpVersions)
|
||||
// Mark as no longer busy
|
||||
self.busy = false
|
||||
// Perform UI updates on main thread
|
||||
DispatchQueue.main.async {
|
||||
self.updatePhpVersionInStatusBar()
|
||||
self.updateMenu()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 647 B After Width: | Height: | Size: 558 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 422 KiB After Width: | Height: | Size: 148 KiB |
68
phpmon/Assets.xcassets/AppIconBeta.appiconset/Contents.json
Normal file
@ -0,0 +1,68 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "icon_16x16.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"filename" : "icon_16x16@2x.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"filename" : "icon_32x32.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "icon_32x32@2x.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "icon_128x128.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"filename" : "icon_128x128@2x.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"filename" : "icon_256x256.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"filename" : "icon_256x256@2x.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"filename" : "icon_512x512.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "512x512"
|
||||
},
|
||||
{
|
||||
"filename" : "icon_512x512@2x.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "512x512"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
phpmon/Assets.xcassets/AppIconBeta.appiconset/icon_128x128.png
Normal file
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 19 KiB |
BIN
phpmon/Assets.xcassets/AppIconBeta.appiconset/icon_16x16.png
Normal file
After Width: | Height: | Size: 585 B |
BIN
phpmon/Assets.xcassets/AppIconBeta.appiconset/icon_16x16@2x.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
phpmon/Assets.xcassets/AppIconBeta.appiconset/icon_256x256.png
Normal file
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 52 KiB |
BIN
phpmon/Assets.xcassets/AppIconBeta.appiconset/icon_32x32.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
phpmon/Assets.xcassets/AppIconBeta.appiconset/icon_32x32@2x.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
phpmon/Assets.xcassets/AppIconBeta.appiconset/icon_512x512.png
Normal file
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 134 KiB |
24
phpmon/Assets.xcassets/Checkmark.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "check.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
1
phpmon/Assets.xcassets/Checkmark.imageset/check.svg
vendored
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Pro 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M435.848 83.466L172.804 346.51l-96.652-96.652c-4.686-4.686-12.284-4.686-16.971 0l-28.284 28.284c-4.686 4.686-4.686 12.284 0 16.971l133.421 133.421c4.686 4.686 12.284 4.686 16.971 0l299.813-299.813c4.686-4.686 4.686-12.284 0-16.971l-28.284-28.284c-4.686-4.686-12.284-4.686-16.97 0z"/></svg>
|
After Width: | Height: | Size: 497 B |
@ -1,6 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
38
phpmon/Assets.xcassets/IconColorGreen.colorset/Contents.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.501",
|
||||
"green" : "0.697",
|
||||
"red" : "0.247"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.501",
|
||||
"green" : "0.765",
|
||||
"red" : "0.247"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.000",
|
||||
"green" : "0.000",
|
||||
"red" : "0.000"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "1.000",
|
||||
"green" : "1.000",
|
||||
"red" : "1.000"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
38
phpmon/Assets.xcassets/IconColorRed.colorset/Contents.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.180",
|
||||
"green" : "0.000",
|
||||
"red" : "1.000"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.426",
|
||||
"green" : "0.363",
|
||||
"red" : "1.000"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
25
phpmon/Assets.xcassets/IconLinked.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "Linked.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Linked@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
phpmon/Assets.xcassets/IconLinked.imageset/Linked.png
vendored
Normal file
After Width: | Height: | Size: 978 B |
BIN
phpmon/Assets.xcassets/IconLinked.imageset/Linked@2x.png
vendored
Normal file
After Width: | Height: | Size: 1.5 KiB |
25
phpmon/Assets.xcassets/IconParked.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "Parked.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Parked@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
phpmon/Assets.xcassets/IconParked.imageset/Parked.png
vendored
Normal file
After Width: | Height: | Size: 868 B |
BIN
phpmon/Assets.xcassets/IconParked.imageset/Parked@2x.png
vendored
Normal file
After Width: | Height: | Size: 1.2 KiB |
24
phpmon/Assets.xcassets/Lock.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Locked.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
10
phpmon/Assets.xcassets/Lock.imageset/Locked.svg
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 30 30" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<rect id="Locked" x="0" y="0" width="30" height="30" style="fill:none;"/>
|
||||
<g id="Locked1" serif:id="Locked">
|
||||
<g transform="matrix(0.0468317,0,0,0.0468317,4.50971,3.01112)">
|
||||
<path d="M400,256L152,256L152,152.9C152,113.3 183.7,80.4 223.3,80C263.3,79.6 296,112.1 296,152L296,266.079C296,279.379 376,279.137 376,265.837L376,152C376,68 307.5,-0.3 223.5,0C139.5,0.3 72,69.5 72,153.5L72,256L48,256C21.5,256 0,277.5 0,304L0,464C0,490.5 21.5,512 48,512L400,512C426.5,512 448,490.5 448,464L448,304C448,277.5 426.5,256 400,256Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
24
phpmon/Assets.xcassets/LockUnlocked.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Unlocked.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
10
phpmon/Assets.xcassets/LockUnlocked.imageset/Unlocked.svg
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 30 30" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<rect id="Locked" x="0" y="0" width="30" height="30" style="fill:none;"/>
|
||||
<g id="Locked1" serif:id="Locked">
|
||||
<g transform="matrix(0.0468317,0,0,0.0468317,4.50971,3.01112)">
|
||||
<path d="M400,256L152,256L152,152.9C152,113.3 183.7,80.4 223.3,80C263.3,79.6 296,112.1 296,152L296,168C296,181.3 322.386,192 322.386,192L352,192C365.3,192 376,181.3 376,168L376,152C376,68 307.5,-0.3 223.5,0C139.5,0.3 72,69.5 72,153.5L72,256L48,256C21.5,256 0,277.5 0,304L0,464C0,490.5 21.5,512 48,512L400,512C426.5,512 448,490.5 448,464L448,304C448,277.5 426.5,256 400,256Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
6
phpmon/Assets.xcassets/Menu Bar Icons/Contents.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
22
phpmon/Assets.xcassets/Menu Bar Icons/MenuBar_elephant.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "Menu Bar Elephant.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Menu Bar Elephant@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
phpmon/Assets.xcassets/Menu Bar Icons/MenuBar_elephant.imageset/Menu Bar Elephant.png
vendored
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
phpmon/Assets.xcassets/Menu Bar Icons/MenuBar_elephant.imageset/Menu Bar Elephant@2x.png
vendored
Normal file
After Width: | Height: | Size: 2.5 KiB |
22
phpmon/Assets.xcassets/Menu Bar Icons/MenuBar_php.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "Menu Bar.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Menu Bar@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
phpmon/Assets.xcassets/Menu Bar Icons/MenuBar_php.imageset/Menu Bar.png
vendored
Normal file
After Width: | Height: | Size: 658 B |
BIN
phpmon/Assets.xcassets/Menu Bar Icons/MenuBar_php.imageset/Menu Bar@2x.png
vendored
Normal file
After Width: | Height: | Size: 793 B |
25
phpmon/Assets.xcassets/ServiceLoading.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ServiceLoading.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "ServiceLoading@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
phpmon/Assets.xcassets/ServiceLoading.imageset/ServiceLoading.png
vendored
Normal file
After Width: | Height: | Size: 854 B |
BIN
phpmon/Assets.xcassets/ServiceLoading.imageset/ServiceLoading@2x.png
vendored
Normal file
After Width: | Height: | Size: 1.3 KiB |
25
phpmon/Assets.xcassets/ServiceOff.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ServiceOff.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "ServiceOff@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
phpmon/Assets.xcassets/ServiceOff.imageset/ServiceOff.png
vendored
Normal file
After Width: | Height: | Size: 826 B |
BIN
phpmon/Assets.xcassets/ServiceOff.imageset/ServiceOff@2x.png
vendored
Normal file
After Width: | Height: | Size: 1.2 KiB |
25
phpmon/Assets.xcassets/ServiceOn.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ServiceOn.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "ServiceOn@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
phpmon/Assets.xcassets/ServiceOn.imageset/ServiceOn.png
vendored
Normal file
After Width: | Height: | Size: 819 B |
BIN
phpmon/Assets.xcassets/ServiceOn.imageset/ServiceOn@2x.png
vendored
Normal file
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 386 B After Width: | Height: | Size: 278 B |
Before Width: | Height: | Size: 780 B After Width: | Height: | Size: 500 B |
22
phpmon/Assets.xcassets/StatusBarIconStatic.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "phpmon.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "phpmon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
phpmon/Assets.xcassets/StatusBarIconStatic.imageset/phpmon.png
vendored
Normal file
After Width: | Height: | Size: 229 B |
BIN
phpmon/Assets.xcassets/StatusBarIconStatic.imageset/phpmon@2x.png
vendored
Normal file
After Width: | Height: | Size: 353 B |
@ -1,31 +0,0 @@
|
||||
//
|
||||
// PhpVersionExtractor.swift
|
||||
// phpmon
|
||||
//
|
||||
// Created by Nico Verbruggen on 11/06/2019.
|
||||
// Copyright © 2019 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class PhpVersion {
|
||||
|
||||
var short : String = "???"
|
||||
var long : String = "???"
|
||||
|
||||
init() {
|
||||
let version = Shell
|
||||
// Get the version directly from PHP
|
||||
.execute(command: "php -r 'print phpversion();'")
|
||||
// also remove any colors
|
||||
.replacingOccurrences(of: "\u{1b}(B\u{1b}[m", with: "")
|
||||
|
||||
// That's the long version
|
||||
self.long = version
|
||||
|
||||
// Next up, let's strip away the minor version number
|
||||
let segments = long.components(separatedBy: ".")
|
||||
// Get the first two elements
|
||||
self.short = segments[0...1].joined(separator: ".")
|
||||
}
|
||||
}
|
146
phpmon/Common/Core/Actions.swift
Normal file
@ -0,0 +1,146 @@
|
||||
//
|
||||
// Services.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import AppKit
|
||||
|
||||
class Actions {
|
||||
|
||||
// MARK: - Services
|
||||
|
||||
public static func restartPhpFpm()
|
||||
{
|
||||
brew("services restart \(PhpEnv.phpInstall.formula)", sudo: true)
|
||||
}
|
||||
|
||||
public static func restartNginx()
|
||||
{
|
||||
brew("services restart nginx", sudo: true)
|
||||
}
|
||||
|
||||
public static func restartDnsMasq()
|
||||
{
|
||||
brew("services restart dnsmasq", sudo: true)
|
||||
}
|
||||
|
||||
public static func stopAllServices()
|
||||
{
|
||||
brew("services stop \(PhpEnv.phpInstall.formula)", sudo: true)
|
||||
brew("services stop nginx", sudo: true)
|
||||
brew("services stop dnsmasq", sudo: true)
|
||||
}
|
||||
|
||||
public static func fixHomebrewPermissions() throws
|
||||
{
|
||||
var servicesCommands = [
|
||||
"\(Paths.brew) services stop nginx",
|
||||
"\(Paths.brew) services stop dnsmasq",
|
||||
]
|
||||
var cellarCommands = [
|
||||
"chown -R \(Paths.whoami):staff \(Paths.cellarPath)/nginx",
|
||||
"chown -R \(Paths.whoami):staff \(Paths.cellarPath)/dnsmasq"
|
||||
]
|
||||
|
||||
PhpEnv.shared.availablePhpVersions.forEach { version in
|
||||
let formula = version == PhpEnv.brewPhpVersion
|
||||
? "php"
|
||||
: "php@\(version)"
|
||||
servicesCommands.append("\(Paths.brew) services stop \(formula)")
|
||||
cellarCommands.append("chown -R \(Paths.whoami):staff \(Paths.cellarPath)/\(formula)")
|
||||
}
|
||||
|
||||
let script =
|
||||
servicesCommands.joined(separator: " && ")
|
||||
+ " && "
|
||||
+ cellarCommands.joined(separator: " && ")
|
||||
|
||||
let appleScript = NSAppleScript(
|
||||
source: "do shell script \"\(script)\" with administrator privileges"
|
||||
)
|
||||
|
||||
let eventResult: NSAppleEventDescriptor? = appleScript?.executeAndReturnError(nil)
|
||||
|
||||
if (eventResult == nil) {
|
||||
throw HomebrewPermissionError(kind: .applescriptNilError)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Finding Config Files
|
||||
|
||||
public static func openGenericPhpConfigFolder()
|
||||
{
|
||||
let files = [NSURL(fileURLWithPath: "\(Paths.etcPath)/php")];
|
||||
NSWorkspace.shared.activateFileViewerSelecting(files as [URL])
|
||||
}
|
||||
|
||||
public static func openGlobalComposerFolder()
|
||||
{
|
||||
let file = FileManager.default.homeDirectoryForCurrentUser
|
||||
.appendingPathComponent(".composer/composer.json")
|
||||
NSWorkspace.shared.activateFileViewerSelecting([file] as [URL])
|
||||
}
|
||||
|
||||
public static func openPhpConfigFolder(version: String)
|
||||
{
|
||||
let files = [NSURL(fileURLWithPath: "\(Paths.etcPath)/php/\(version)/php.ini")];
|
||||
NSWorkspace.shared.activateFileViewerSelecting(files as [URL])
|
||||
}
|
||||
|
||||
public static func openValetConfigFolder()
|
||||
{
|
||||
let file = FileManager.default.homeDirectoryForCurrentUser
|
||||
.appendingPathComponent(".config/valet")
|
||||
NSWorkspace.shared.activateFileViewerSelecting([file] as [URL])
|
||||
}
|
||||
|
||||
// MARK: - Other Actions
|
||||
|
||||
public static func createTempPhpInfoFile() -> URL
|
||||
{
|
||||
// Write a file called `phpmon_phpinfo.php` to /tmp
|
||||
try! "<?php phpinfo();".write(toFile: "/tmp/phpmon_phpinfo.php", atomically: true, encoding: .utf8)
|
||||
|
||||
// Tell php-cgi to run the PHP and output as an .html file
|
||||
Shell.run("\(Paths.binPath)/php-cgi -q /tmp/phpmon_phpinfo.php > /tmp/phpmon_phpinfo.html")
|
||||
|
||||
return URL(string: "file:///private/tmp/phpmon_phpinfo.html")!
|
||||
}
|
||||
|
||||
// MARK: - Fix My Valet
|
||||
|
||||
/**
|
||||
Detects all currently available PHP versions,
|
||||
and unlinks each and every one of them.
|
||||
|
||||
After this, the brew services are also stopped,
|
||||
the latest PHP version is linked, and php + nginx are restarted.
|
||||
|
||||
If this does not solve the issue, the user may need to install additional
|
||||
extensions and/or run `composer global update`.
|
||||
*/
|
||||
public static func fixMyValet()
|
||||
{
|
||||
brew("services restart dnsmasq", sudo: true)
|
||||
|
||||
PhpEnv.shared.detectPhpVersions().forEach { (version) in
|
||||
let formula = (version == PhpEnv.brewPhpVersion) ? "php" : "php@\(version)"
|
||||
brew("unlink php@\(version)")
|
||||
brew("services stop \(formula)")
|
||||
brew("services stop \(formula)", sudo: true)
|
||||
}
|
||||
|
||||
brew("services stop dnsmasq")
|
||||
brew("services stop php")
|
||||
brew("services stop nginx")
|
||||
|
||||
brew("link php --overwrite --force")
|
||||
|
||||
brew("services restart dnsmasq", sudo: true)
|
||||
brew("services restart php", sudo: true)
|
||||
brew("services restart nginx", sudo: true)
|
||||
}
|
||||
}
|
40
phpmon/Common/Core/Command.swift
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// Command.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
||||
public class Command {
|
||||
|
||||
/**
|
||||
Immediately executes a command.
|
||||
|
||||
- Parameter path: The path of the command or program to invoke.
|
||||
- Parameter arguments: A list of arguments that are passed on.
|
||||
- Parameter trimNewlines: Removes empty new line output.
|
||||
*/
|
||||
public static func execute(path: String, arguments: [String], trimNewlines: Bool = false) -> String {
|
||||
let task = Process()
|
||||
task.launchPath = path
|
||||
task.arguments = arguments
|
||||
|
||||
let pipe = Pipe()
|
||||
task.standardOutput = pipe
|
||||
task.launch()
|
||||
|
||||
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||
let output: String = String.init(data: data, encoding: String.Encoding.utf8)!
|
||||
|
||||
if (trimNewlines) {
|
||||
return output.components(separatedBy: .newlines)
|
||||
.filter({ !$0.isEmpty })
|
||||
.joined(separator: "\n")
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
}
|