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.
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]
bootstrap()only does work when the requested script isplugins.php, that is on the plugin list of the Admin Panel. AJAX requests (X-Requested-With: XMLHttpRequest) are ignored.UpdateCheckPluginreads the settings from the first active instance.PluginUpdateCollectorgoes through all plugins known viaPluginManager::allInstalled()and reads their metadata withPluginManager::getInfoForPath().- For each plugin with a GitHub URL,
GitHubReleaseCheckerfetches the latest release, first from the cache, otherwise from GitHub. - If at least one update exists, the plugin starts an output buffer.
AssetInjectorinserts the CSS before</head>and the update data plus JavaScript before</body>. - 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.
- Recognized are
https://github.com/owner/repo,http://github.com/owner/repoandgithub.com/owner/repo, each with an optional.gitand an optional trailing slash. - URLs with further path segments (for example
/tree/main) are not recognized. - The repository name must not contain a dot. A repository such as
owner/my.pluginis skipped. - The plugin's developer must publish a GitHub release. A bare Git tag is not enough because the query is
releases/latest. - The installed version is the
versionfrom the checked plugin's metadata.
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 |
- Location: folder
osticket-update-checkin the PHP temp directory (sys_get_temp_dir()), created with permissions0755. - One JSON file per repository,
github_release_<owner>_<repo>.json, with the fieldsexpires_atanddata. The token is not part of the cache. - Expired or damaged files are deleted when read. If the folder is not writable, the plugin continues without a cache.
- Counted as errors are HTTP responses other than 200, missing cURL, connection errors, invalid JSON and a release without a tag name.
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
- The JSON data is encoded with
JSON_HEX_TAGandJSON_HEX_APOSso it cannot close a script tag. - The JavaScript only sets a badge if the release URL starts with
http:orhttps:, and writes the values viatextContent. - A marker
data-plugin="update-check"prevents double insertion. - If the insertion throws an error, the output buffer callback returns the page unchanged and writes
[UpdateCheck] Asset injection failedto the PHP error log. - The plugin creates no database tables of its own and changes neither the database schema nor osTicket files. The only database entry is the plugin instance with its configuration (including a token, if entered), which osTicket manages. In addition there are the cache files in the temp directory.
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)