Skip to content

Commit

Permalink
🚀 Version 5.8.0
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoverbruggen committed Mar 3, 2023
2 parents 3f14754 + e149a25 commit 13ee618
Show file tree
Hide file tree
Showing 62 changed files with 1,128 additions and 491 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ phpmon.xcodeproj/project.xcworkspace
phpmon.xcodeproj/xcuserdata
PHP Monitor.xcodeproj/project.xcworkspace
PHP Monitor.xcodeproj/xcuserdata
phpmon-updater/PHP Monitor Self-Updater.app
.DS_Store
126 changes: 94 additions & 32 deletions PHP Monitor.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
</CommandLineArgument>
<CommandLineArgument
argument = "--cli"
isEnabled = "YES">
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "--configuration:~/.phpmon_fconf_working.json"
Expand Down
30 changes: 18 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@

**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 app</u> (consult the FAQ below with info about how to set up your environment).

<img src="./docs/screenshot.jpg#gh-light-mode-only" width="1280px" alt="phpmon screenshot (menu bar app)"/>
<img src="./docs/screenshot-dark.jpg#gh-dark-mode-only" width="1280px" alt="phpmon screenshot (menu bar app)"/>
<img src="./docs/screenshot.jpg" width="1280px" alt="phpmon screenshot (menu bar app)"/>

<small><i>Screenshot: Showing the key functionality of PHP Monitor.</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#gh-light-mode-only" width="370px" alt="phpmon screenshot (notification)"/>
<img src="./docs/notification-dark.png#gh-dark-mode-only" width="370px" alt="phpmon screenshot (notification)"/>
<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).

Expand All @@ -24,7 +22,7 @@ You can also add new domains as links, isolate sites, manage various services, a
PHP Monitor is a universal application that runs natively on Apple Silicon **and** Intel-based Macs.

* Your user account can administer your computer (required for some functionality, e.g. certificate generation)
* macOS Monterey 12.4 or later (Ventura supported)
* macOS 12.4 or later (Monterey and Ventura are supported)
* Homebrew is installed in `/usr/local/homebrew` or `/opt/homebrew`
* Homebrew `php` formula is installed
* Laravel Valet (works with Valet v2, v3 and v4)
Expand All @@ -43,22 +41,28 @@ valet install
valet trust
```

Once that's done, you can install PHP Monitor via Homebrew (recommended), or (alternatively) you may download the latest release on GitHub.
#### Manual installation (recommended, first time only)

To install via Homebrew, run:
Once that's done, you can [download the latest release](https://github.com/nicoverbruggen/phpmon/releases/latest), unzip it and place it in `/Applications`.

#### Installation via Homebrew

*Prior to version 5.8, this was the recommended way of installing PHP Monitor.*

If you prefer to install the app via Homebrew, you can also run the following:

```sh
brew tap nicoverbruggen/homebrew-cask
brew install --cask phpmon
```

To upgrade your existing installation, run:
## ⬆️ How to update

```sh
brew upgrade phpmon
```
The recommended method of updating the app to the latest version is to use **the built-in updater**.

If you have a very slow internet connection, the updater may report that the download has timed out. In that case, you may wish to manually update by [downloading the latest release](https://github.com/nicoverbruggen/phpmon/releases/latest) and placing the app in `/Applications`.

(You may need to run `brew update` or `brew update-reset` first in order to update the cask file if you ran a Homebrew operation recently.)
(You may also use Homebrew to update PHP Monitor, but this will require you to approve the app every time an update is installed. If you use the built-in updater, this won't be necessary.)

## ⚡️ Launchers (Alfred, Raycast)

Expand Down Expand Up @@ -273,6 +277,8 @@ This problem is usually resolved by upgrading Valet and running `valet install`

composer global update
valet install

If you are seeing a 502 (Bad Gateway) error after about 30 seconds or so, your request is likely timing out. You may need to solve a performance issue with your own code.

</details>

Expand Down
3 changes: 2 additions & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Generally speaking, only the latest version of **PHP Monitor** is supported, exc

| Version | Apple Silicon | Supported | Supported macOS | Deployment Target | Detected PHP Versions | Recommended Valet Version |
| ------- | ------------- | ------------------ | ----- | ----- | ----- | ----
| 5.7 | ✅ Universal binary | ✅ Yes | Monterey (12.4+)<br/>Ventura (13.0) | macOS 11+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)<br/>PHP 7.0—PHP 8.2 (w/ Valet 3.x)<br/>PHP 7.1-PHP 8.2 (w/ Valet 4.x*) | 3.0 or higher recommended<br/> 2.16.2 minimum |
| 5.8 | ✅ Universal binary | ✅ Yes | Monterey (12.4+)<br/>Ventura (13.0+) | macOS 12.4 | PHP 5.6—PHP 8.2 (w/ Valet 2.x)<br/>PHP 7.0—PHP 8.2 (w/ Valet 3.x)<br/>PHP 7.1-PHP 8.2 (w/ Valet 4.x*) | 3.0 or higher recommended<br/> 2.16.2 minimum |

(*) Preliminary listing. Valet 4 hasn't been released yet and the versions of PHP Valet can work with might still change.

Expand All @@ -16,6 +16,7 @@ These versions of PHP Monitor are no longer supported, but if you’re using an

| Version | Apple Silicon | Supported | Supported macOS | Deployment Target | Detected PHP Versions | Minimum Required Valet Version |
| ------- | ------------- | ------------------ | ----- | ----- | ----- | ----
| 5.7 | ✅ Universal binary || Big Sur (11.0)<br/>Monterey (12.0)<br/>Ventura (13.0)* | macOS 11+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)<br/>PHP 7.0—PHP 8.2 (w/ Valet 3.x) | 3.0 recommended<br/> 2.16.2 minimum |
| 5.6 | ✅ Universal binary || Big Sur (11.0)<br/>Monterey (12.0)<br/>Ventura (13.0)* | macOS 11+ | PHP 5.6—PHP 8.2 (w/ Valet 2.x)<br/>PHP 7.0—PHP 8.2 (w/ Valet 3.x) | 3.0 recommended<br/> 2.16.2 minimum |
| 4.1 | ✅ Universal binary || Big Sur (11.0)<br/>Monterey (12.0) | macOS 11+ | PHP 5.6—PHP 8.2 | 2.16.2 |
| 4.0 | ✅ Universal binary || Big Sur (11.0)<br/>Monterey (12.0) | macOS 10.14+ | PHP 5.6—PHP 8.2 | 2.13 |
Expand Down
Binary file removed docs/notification-dark.png
Binary file not shown.
Binary file removed docs/screenshot-dark.jpg
Binary file not shown.
Binary file modified docs/screenshot.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 0 additions & 68 deletions phpmon/Assets.xcassets/AppIconEA.appiconset/Contents.json

This file was deleted.

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
15 changes: 8 additions & 7 deletions phpmon/Common/Core/Paths.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,12 @@ public class Paths {
public static let shared = Paths()

internal var baseDir: Paths.HomebrewDir

private var userName: String! = nil
private var userName: String

init() {
baseDir = App.architecture != "x86_64" ? .opt : .usr
}

public func loadUser() async {
let output = await Shell.pipe("id -un").out
userName = String(output.split(separator: "\n")[0])
userName = identity()
Log.info("[ID] The current username is `\(userName)`.")
}

public func detectBinaryPaths() {
Expand Down Expand Up @@ -90,6 +86,11 @@ public class Paths {
return "\(shared.baseDir.rawValue)/etc"
}

public static var caskroomPath: String {
return "\(shared.baseDir.rawValue)/Caskroom/"
+ (App.identifier.contains(".dev") ? "phpmon-dev" : "phpmon")
}

// MARK: - Flexible Binaries
// (these can be in multiple locations, so we scan common places because)
// (PHP Monitor will not use the user's own PATH)
Expand Down
11 changes: 7 additions & 4 deletions phpmon/Common/Filesystem/RealFileSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,24 @@ class RealFileSystem: FileSystemProtocol {
}

func getShallowContentsOfDirectory(_ path: String) throws -> [String] {
return try FileManager.default.contentsOfDirectory(atPath: path)
return try FileManager.default.contentsOfDirectory(atPath: path.replacingTildeWithHomeDirectory)
}

func getDestinationOfSymlink(_ path: String) throws -> String {
return try FileManager.default.destinationOfSymbolicLink(atPath: path)
return try FileManager.default.destinationOfSymbolicLink(atPath: path.replacingTildeWithHomeDirectory)
}

// MARK: - Move & Delete Files

func move(from path: String, to newPath: String) throws {
try FileManager.default.moveItem(atPath: path, toPath: newPath)
try FileManager.default.moveItem(
atPath: path.replacingTildeWithHomeDirectory,
toPath: newPath.replacingTildeWithHomeDirectory
)
}

func remove(_ path: String) throws {
try FileManager.default.removeItem(atPath: path)
try FileManager.default.removeItem(atPath: path.replacingTildeWithHomeDirectory)
}

// MARK: — FS Attributes
Expand Down
4 changes: 2 additions & 2 deletions phpmon/Common/Helpers/LocalNotification.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import UserNotifications

class LocalNotification {

@MainActor public static func send(title: String, subtitle: String, preference: PreferenceName) {
if !Preferences.isEnabled(preference) {
@MainActor public static func send(title: String, subtitle: String, preference: PreferenceName?) {
if preference != nil && !Preferences.isEnabled(preference!) {
return
}

Expand Down
25 changes: 25 additions & 0 deletions phpmon/Common/Helpers/LoginItemManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// LoginItemManager.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 15/02/2023.
// Copyright © 2023 Nico Verbruggen. All rights reserved.
//

import AppKit
import ServiceManagement

@available(macOS 13.0, *)
class LoginItemManager {
func loginItemIsEnabled() -> Bool {
return SMAppService.mainApp.status == .enabled
}

func disableLoginItem() {
try? SMAppService.mainApp.unregister()
}

func enableLoginItem() {
try? SMAppService.mainApp.register()
}
}
28 changes: 28 additions & 0 deletions phpmon/Common/Helpers/System.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,31 @@ public func system(_ command: String) -> String {

return output
}

/** Same as the `system` command, but does not return the output. */
public func system_quiet(_ command: String) {
_ = system(command)
}

/**
Retrieves the username for the currently signed in user via `/usr/bin/id`.
This cannot fail or the application will crash.
*/
public func identity() -> String {
let task = Process()
task.launchPath = "/usr/bin/id"
task.arguments = ["-un"]

let pipe = Pipe()
task.standardOutput = pipe
task.launch()

guard let output = String(
data: pipe.fileHandleForReading.readDataToEndOfFile(),
encoding: String.Encoding.utf8
) else {
fatalError("Could not retrieve username via `id -un`!")
}

return output.trimmingCharacters(in: .whitespacesAndNewlines)
}
17 changes: 17 additions & 0 deletions phpmon/Common/PHP/PHP Version/PhpVersionNumberCollection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public struct PhpVersionNumberCollection: Equatable {
- Parameter strict: Whether the patch version check is strict. See more below.

The strict mode does not matter if a patch version is provided for all versions in the collection.
It also does not matter for certain comparisons (e.g. when dealing with wildcards).

Strict mode assumes that any PHP version lacking precise patch information, e.g. inferred
from Homebrew corresponds to the .0 patch version of that version. The default, which is imprecise,
Expand All @@ -45,18 +46,34 @@ public struct PhpVersionNumberCollection: Equatable {

Given versions 8.0.? and 8.1.?, but the requirement is ^8.0.1, in strict mode only 8.1.? will
be considered valid (8.0 translates to 8.0.0 and as such is older than 8.0.1, 8.1.0 is OK).

When checking against actual PHP versions installed by the user (with patch precision), use
strict mode.

**NON-STRICT MODE (= patch precision off)**

Given versions 8.0.? and 8.1.?, but the requirement is ^8.0.1, in non-strict mode version 8.0
is assumed to be equal to version 8.0.999, which is actually fine if 8.0.1 is the required version.

In non-strict mode, the patch version is ignored for regular version checks (no caret / tilde).
If checking compatibility with general Homebrew versions of PHP, do NOT use strict mode, since
the patch version there is not used. (The formula [email protected] suffices for ^8.0.1.)
*/
public func matching(constraint: String, strict: Bool = false) -> [VersionNumber] {
if constraint == "*" {
return self.versions
}

if let version = VersionNumber.make(from: constraint, type: .wildCardPatch) {
// Wildcard for patch (e.g. "7.4.*") must match major and minor (any patch)
return self.versions.filter { $0.hasSameMajorAndMinor(version) }
}

if let version = VersionNumber.make(from: constraint, type: .wildCardMinor) {
// Strict constraint (e.g. "7.*") -> must only match major (any patch, minor)
return self.versions.filter { $0.isSameMajorVersionAs(version) }
}

if let version = VersionNumber.make(from: constraint, type: .versionOnly) {
// Strict constraint (e.g. "7.0") -> returns specific version
return self.versions.filter { $0.isSameAs(version, strict) }
Expand Down
Loading

0 comments on commit 13ee618

Please sign in to comment.