diff --git a/ENHANCE_INTEGRATION.md b/ENHANCE_INTEGRATION.md new file mode 100644 index 0000000..db18f1e --- /dev/null +++ b/ENHANCE_INTEGRATION.md @@ -0,0 +1,139 @@ +# Enhance Platform Integration +_Comprehensive documentation for the `software/enhance.php` checker_ + +--- + +## 1  What We’ve Built +`software/enhance.php` adds **real-time version monitoring** for the [Enhance](https://enhance.com) hosting platform to VersionCheck. +Key capabilities: + +* Scrapes the public **Release Notes** page + `https://enhance.com/support/release-notes.html` +* Parses every core release (v9 → v12) including patch versions + (e.g. `12.6.0`, `12.5.1`, `12.0.30`) +* Detects which release is flagged **“Latest”** and records an _announcement_ + link for notification e-mails +* Stores/updates one entry per **major.minor branch** + (`12.6`, `12.5`, `11.0`, …) keeping only the highest patch + +The integration means administrators and subscribers will be alerted within +minutes of any new Enhance release. + +--- + +## 2  How It Works + +| Phase | Details | +|-------|---------| +| **Fetch** | `http::get()` (cURL) downloads the raw HTML. | +| **Parse** | `DOMDocument` iterates `

` elements (each version header). | +| **Filter** | Non-core headers (`Appcd…`, `WHMCS…`, `PHP packages`) are ignored. | +| **Extract** | • Version number (`^\d+\.\d+\.\d+`)
• Branch = first two octets
• Release date from the first subsequent `

` (ex “27th May 2025”) – converted to `Y-m-d H:i:s`.
• “Latest” determined by scanning sibling nodes for the word **Latest** (case-insensitive). | +| **Reduce** | All patch releases within the same branch are sorted by PATCH descending; only newest kept. | +| **Return** | Array structure consumed by `check.php`: ```php ['12.6' => ['version'=>'12.6.0','release_date'=>'2025-05-27 00:00:00','announcement'=>..., 'estimated'=>false], …]``` | + +--- + +## 3  Data Extracted + +| Field | Example | Notes | +|------------------|--------------------------|-----------------------------------------| +| `software` | `enhance` (class name) | Stored automatically by core logic | +| `branch` | `12.6` | Major.Minor | +| `version` | `12.6.0` | Highest patch for branch | +| `release_date` | `2025-05-27 00:00:00` | Parsed; fallback = now + `estimated=1` | +| `announcement` | `https://enhance.com/support/release-notes.html#12.6.0` | Only present for branch marked **Latest** | +| `estimated` | `0`/`1` | `1` if date parsing failed | + +--- + +## 4  Setup Instructions + +1. **Pull the code** + ```bash + git fetch origin + git checkout feature/add-enhance-platform + ``` + +2. **Verify file exists** + ``` + software/enhance.php + ``` + +3. **Enable (optional)** + `public static $enabled = true;` by default. + Set to `false` to disable without deleting the file. + +4. **Database** + No schema changes. `check.php` will auto-insert rows into `versions` and + `notifications` tables. + +5. **Cron** + Ensure your existing cron that executes `check.php` remains active + (per installation guide). No additional jobs are required. + +--- + +## 5  Testing & Troubleshooting + +### Quick CLI Test +```bash +php -r " +include 'software/enhance.php'; +\$e = new enhance(); +\$versions = \$e->get_versions(\$e->get_data()); +print_r(array_slice(\$versions,0,3,true)); +" +``` + +Expected trimmed output: +``` +Array +( + [12.6] => Array + ( + [version] => 12.6.0 + [release_date] => 2025-05-27 00:00:00 + [announcement] => https://enhance.com/support/release-notes.html#12.6.0 + [estimated] => + ) + [12.5] => Array + ( + [version] => 12.5.1 + [release_date] => 2025-05-21 00:00:00 + [estimated] => + ) + [12.4] => … +) +``` + +### Common Issues + +| Symptom | Possible Cause | Resolution | +|---------|----------------|------------| +| **`RuntimeException` from `http::get`** | cURL blocked / TLS failure | Check outbound HTTPS, update CA bundle | +| **No versions detected** | HTML structure changed | Inspect page, update DOM traversal/regex | +| **Dates show “estimated”** | Release lacks `

` date or new format | Raise issue; consider regex fallback | +| **Latest not flagged** | “Latest” label moved | Adjust sibling scan range (`$max_siblings_to_check`) | +| **Database errors on first run** | Missing `config.php` or wrong credentials | Follow install README – import SQL & configure PDO | + +--- + +## 6  Future Improvements + +* **Caching / Rate-limit** – store fetched HTML to cut traffic & guard against + temporary site outages. +* **Unit tests** – mock HTML fixtures to detect parser breakage early. +* **Full historical capture** – store *all* patch versions, not just newest. +* **Security hardening** – sanitize/limit DOM parsing to reduce attack surface. +* **Graceful fallback** – if DOM parsing fails, attempt pure regex extraction. +* **Official API** – migrate to JSON endpoint if Enhance publishes one. +* **Notification granularity** – allow subscribers to opt into + major/minor/patch channels separately. + +--- + +### Maintainer Notes +* Written for **PHP ≥8.0** (uses `JSON_THROW_ON_ERROR` in other checkers). +* Keep `$uri` constant if domain changes (e.g. `.html` vs no extension). +* Test after core panel redesigns – header hierarchy may shift. diff --git a/software/enhance.php b/software/enhance.php new file mode 100644 index 0000000..9dfc1df --- /dev/null +++ b/software/enhance.php @@ -0,0 +1,150 @@ + +Installed-Size: 87858 +Depends: cron, curl, ecp-php56, ecp-php70, ecp-php71, ecp-php72, ecp-php73, ecp-php74, ecp-php80, ecp-php81, ecp-php82, ecp-php83, ecp-php84, libc6 (>= 2.34), libc6 (>= 2.38), libc6 (>= 2.39), libmilter1.0.1 (>= 8.14.1), libnss3-dev, libpam0g (>= 0.99.7.1), libssl3t64 (>= 3.0.0), linux-image-extra-virtual, openssh-server, openssl, quota, rsync, ufw, zlib1g (>= 1:1.1.4) +Conflicts: appcd +Replaces: appcd +Filename: pool/noble/ecp-core_12.6.0_amd64.deb +Size: 22096584 +MD5sum: b8d084689177aa18b52ff7ee01443156 +SHA1: b41084091113c5090f49a57f4f77b0f2d5774eec +SHA256: 4be9b14e6004debcdbc04819d07f2e78e2624760178cd7e72041722902f87704 +Priority: optional +Description: [generated from Rust crate appcd] + +Package: ecp-core +Version: 12.5.1 +... +*/ + +class enhance extends SoftwareCheck +{ + public static $name = 'Enhance Platform'; + public static $vendor = 'Enhance'; + public static $homepage = 'https://enhance.com/'; + public static $type = 'apt'; + public static $enabled = true; + var $uri = 'https://apt.enhance.com/dists/noble/main/binary-amd64/Packages'; + var $release_uri = 'https://apt.enhance.com/dists/noble/Release'; + + function get_data() + { + // Get the Packages file + $packages_data = http::get($this->uri); + + // Get the Release file for date information + try { + $release_data = http::get($this->release_uri); + } catch (Exception $e) { + // If we can't get the Release file, just use the Packages data + $release_data = ''; + } + + return [ + 'packages' => $packages_data, + 'release' => $release_data + ]; + } + + function get_versions($data = array()) + { + if (empty($data) || !isset($data['packages']) || empty($data['packages'])) { + return array(); + } + + // Extract repository date from Release file if available + $repo_date = date("Y-m-d H:i:s"); // Default to current date/time + $estimated = true; + + if (!empty($data['release'])) { + if (preg_match('/Date:\s+([^\n]+)/', $data['release'], $matches)) { + $date_str = trim($matches[1]); + if (($timestamp = strtotime($date_str)) !== false) { + $repo_date = date("Y-m-d H:i:s", $timestamp); + $estimated = false; + } + } + } + + // Parse Packages file + $versions = array(); + $branch_versions = array(); + $latest_version = null; + $latest_version_full = null; + + // Split the Packages file into individual package entries + $package_entries = explode("\n\n", $data['packages']); + + foreach ($package_entries as $entry) { + // Check if this is an ecp-core package + if (strpos($entry, 'Package: ecp-core') === false) { + continue; + } + + // Extract version + if (preg_match('/Version:\s+(\d+\.\d+\.\d+)/', $entry, $matches)) { + $version = $matches[1]; + + // Extract version components + $version_parts = explode('.', $version); + if (count($version_parts) < 3) { + continue; + } + + // Determine branch (major.minor) + $branch = $version_parts[0] . '.' . $version_parts[1]; + $patch = (int)$version_parts[2]; + + // Store in branch_versions for later processing + if (!isset($branch_versions[$branch])) { + $branch_versions[$branch] = array(); + } + + $branch_versions[$branch][] = array( + 'version' => $version, + 'patch' => $patch, + 'info' => array( + 'version' => $version, + 'release_date' => $repo_date, + 'estimated' => $estimated + ) + ); + + // Track the latest version (highest version number) + if ($latest_version === null || version_compare($version, $latest_version_full, '>')) { + $latest_version = $branch; + $latest_version_full = $version; + } + } + } + + // For each branch, keep only the highest patch version + foreach ($branch_versions as $branch => $branch_data) { + // Sort by patch version (descending) + usort($branch_data, function($a, $b) { + return $b['patch'] - $a['patch']; + }); + + // Keep only the highest patch version + if (!empty($branch_data)) { + $versions[$branch] = $branch_data[0]['info']; + } + } + + // Mark only the highest version as the latest with an announcement link + if ($latest_version !== null && isset($versions[$latest_version])) { + $versions[$latest_version]['announcement'] = 'https://enhance.com/support/release-notes.html#' . $latest_version_full; + } + + return $versions; + } +}