Markus Michalski FAQ

Plugin Update Checker: Technical details

How the Plugin Update Checker works: flow, which plugins are checked, URL detection, version comparison, cache, badge output via output buffer, security and file structure.

Deutsche Version

Back to overview

Plugin Update Checker: Technical details

Identification

Property Value
Plugin name Plugin Update Checker
Plugin ID net.michalski:update-check
Composer package mmd/osticket-plugin-update-check (type osticket-plugin)
Plugin class UpdateCheckPlugin in class.UpdateCheckPlugin.php
Configuration class UpdateCheckConfig in config.php
Instances Singleton, created automatically when enabled

Flow

graph TD
    A[Page request in the Admin Panel] --> B{Script plugins.php?}
    B -->|No| Z[Do nothing]
    B -->|Yes| C{AJAX request?}
    C -->|Yes| Z
    C -->|No| D[Go through all installed plugins]
    D --> E{url in plugin.php is a GitHub repo?}
    E -->|No| F[Skip plugin]
    E -->|Yes| G{Cache entry valid?}
    G -->|Yes| H[Cached release data]
    G -->|No| I[GitHub API releases/latest]
    I --> H
    H --> J{Release newer than installed version?}
    J -->|No| F
    J -->|Yes| K[Collect badge data]
    K --> L[Insert CSS and JS inline into the page]
    L --> M[Browser places badge in the version column]
  1. bootstrap() only does work when the requested script is plugins.php, that is on the plugin list of the Admin Panel. AJAX requests (X-Requested-With: XMLHttpRequest) are ignored.
  2. UpdateCheckPlugin reads the settings from the first active instance.
  3. PluginUpdateCollector goes through all plugins known via PluginManager::allInstalled() and reads their metadata with PluginManager::getInfoForPath().
  4. For each plugin with a GitHub URL, GitHubReleaseChecker fetches the latest release, first from the cache, otherwise from GitHub.
  5. If at least one update exists, the plugin starts an output buffer. AssetInjector inserts the CSS before </head> and the update data plus JavaScript before </body>.
  6. The JavaScript finds the rows of the plugin list through the ids[] checkbox (its value is the plugin ID) and appends the badge to the third column, the version column.

If there is no update, the page stays unchanged and nothing is inserted.

Which plugins are checked

Every installed plugin whose plugin.php names a GitHub repository in the url field is checked. This applies to plugins by any developer, including the Plugin Update Checker itself.

Version comparison

A leading v is removed from the tag name and from the installed version. Then PHP version_compare() decides: a badge appears only if the release version is greater than the installed one. Equal or older versions and empty values produce no badge. Pre-release suffixes get no special treatment, they follow the rules of version_compare().

Cache

Case Duration Content
Successful lookup Setting Cache Duration (hours), default 6 hours tag_name and html_url of the release
Error or no release fixed 1 hour Marker none

Requests to GitHub

Property Value
URL https://api.github.com/repos/<owner>/<repo>/releases/latest
Method GET, via cURL
Headers Accept: application/vnd.github.v3+json, User-Agent: osTicket-Plugin-UpdateChecker/..., optional Authorization: Bearer <token>
Timeout 5 seconds total and 5 seconds for connecting
Redirects up to 3
TLS certificate and host name are verified

The requests run one after another while the plugin list page is built. With a cold cache and GitHub unreachable, the load time can grow by up to 5 seconds per checked plugin. After that the plugin remembers the failure for one hour. What data goes to GitHub is described under Privacy.

Badge output

The plugin's CSS and JavaScript live in the assets/ folder and are written inline into the page instead of being linked as external files. This needs no web server change. The update data is available as JSON in window.__pluginUpdates.

The badge is a link whose text is the new version. It leads to the release page on GitHub, opens in a new tab (rel="noopener noreferrer") and has the tooltip Update available: v<version>. The script also registers on pjax:end so the badges are set again after PJAX navigation.

Security

File structure

include/plugins/update-check/
+-- plugin.php                      Plugin metadata
+-- class.UpdateCheckPlugin.php     Plugin class
+-- config.php                      Configuration form
+-- src/
|   +-- AssetInjector.php           Inserts CSS/JS into the output buffer
|   +-- FileCache.php               File-based cache with expiry
|   +-- GitHubReleaseChecker.php    URL detection, GitHub query, version comparison
|   +-- PluginUpdateCollector.php   Walks the installed plugins
+-- assets/
|   +-- update-badges.css           Badge style
|   +-- update-badges.js            Places badges into the table
+-- vendor/                         Composer autoloader (after composer install)