Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 51 additions & 45 deletions .github/workflows/pr_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,62 +3,68 @@ name: CI
on: [push, pull_request]

jobs:
phpunit-9-6:
strategy:
fail-fast: false
matrix:
php_version: ["7.4", "8.1", "8.2", "8.3"]
tests:
name: PHP ${{ matrix.php }} / Deps ${{ matrix.deps }}${{ matrix.coverage && ' / Coverage' || '' }}
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: php-actions/composer@v6
with:
php_version: "7.4"
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php_version }}
coverage: xdebug
- name: Unit Tests with PHPUnit 9.6
run: vendor/bin/phpunit --stderr --version 9.6

phpunit-10-5:
strategy:
fail-fast: false
matrix:
php_version: ["8.1", "8.2", "8.3"]
runs-on: ubuntu-latest
php: ['7.4', '8.0', '8.1', '8.2']
deps: ['latest']
coverage: [false]
include:
- php: '7.4'
deps: 'lowest'
coverage: false
- php: '8.3'
deps: 'latest'
coverage: true

steps:
- uses: actions/checkout@v2
- uses: php-actions/composer@v6
with:
php_version: "8.1"
- name: Checkout Code
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php_version }}
coverage: xdebug
- name: Unit Tests with PHPUnit 10.5
run: vendor/bin/phpunit --stderr --version 10.5
php-version: ${{ matrix.php }}
extensions: intl, mbstring
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}

phpunit-11-2:
strategy:
fail-fast: false
matrix:
php_version: ["8.2", "8.3"]
runs-on: ubuntu-latest
- name: Get Composer Cache Directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

steps:
- uses: actions/checkout@v2
- uses: php-actions/composer@v6
- name: Cache Composer Dependencies
uses: actions/cache@v4
with:
php_version: "8.2"
- name: Setup PHP
uses: shivammathur/setup-php@v2
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-php-${{ matrix.php }}-deps-${{ matrix.deps }}-${{ hashFiles('**/composer.json') }}
restore-keys: |
${{ runner.os }}-php-${{ matrix.php }}-deps-

- name: Install Dependencies
run: |
if [ "${{ matrix.deps }}" = "lowest" ]; then
composer update --prefer-lowest --prefer-stable --no-interaction
else
composer update --prefer-dist --no-interaction
fi

- name: Validate composer.json
run: composer validate --strict

- name: Ensure Build Directory Exists
run: mkdir -p build/logs

- name: Run All CI Checks
run: composer ci

- name: Upload Coverage to Codecov
if: ${{ matrix.coverage }}
uses: codecov/codecov-action@v4
with:
php-version: ${{ matrix.php_version }}
coverage: xdebug
- name: Unit Tests with PHPUnit 11.2
run: vendor/bin/phpunit --stderr --version 11.2
token: ${{ secrets.CODECOV_TOKEN }} # Recommended for private repos
file: build/logs/clover.xml
fail_ci_if_error: false # Optional: Prevents CI failure if upload fails
62 changes: 50 additions & 12 deletions .scrutinizer.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,57 @@
# .scrutinizer.yml
build:
nodes:
analysis:
environment:
php:
version: 7.4
project_setup:
override: true
tests:
override:
- php-scrutinizer-run
nodes:
analysis:
tests:
override:
- php-scrutinizer-run

php74:
environment:
php: 7.4
tests:
override:
- command: php -v

php80:
environment:
php: 8.0
tests:
override:
- command: php -v

php81:
environment:
php: 8.1
tests:
override:
- command: php -v

php82:
environment:
php: 8.2
tests:
override:
- command: php -v

# php83:
# environment:
# php: 8.3
# tests:
# override:
# - command: php -v

# php84:
# environment:
# php: 8.4
# tests:
# override:
# - command: php -v
filter:
excluded_paths:
- '_archive/*'
- 'tests/*'
tools:
external_code_coverage:
timeout: 300 # Timeout in seconds.
php_analyzer: true
# external_code_coverage:
# timeout: 300 # Timeout in seconds.
103 changes: 103 additions & 0 deletions bin/update-psl.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env php
<?php
/**
* XOOPS RegDom Public Suffix List Updater
*
* Downloads and caches the Mozilla Public Suffix List.
* This script is safe to run in any environment and handles multiple failure scenarios gracefully.
*
* @license The PSL is licensed under MPL-2.0 by Mozilla Foundation
* @source https://publicsuffix.org/
*/

echo "Updating XOOPS RegDom Public Suffix List...\n";

// --- Configuration ---
$sourceUrl = 'https://publicsuffix.org/list/public_suffix_list.dat';
$packageDir = dirname(__DIR__);
$dataDir = $packageDir . '/data';
$bundledCachePath = $dataDir . '/psl.cache.php';
$metaPath = $dataDir . '/psl.meta.json';
$runtimeCachePath = null;

// Determine runtime cache path if in a XOOPS context
if (defined('XOOPS_VAR_PATH')) {
$runtimeCacheDir = XOOPS_VAR_PATH . '/cache/regdom';
if (!is_dir($runtimeCacheDir)) {
@mkdir($runtimeCacheDir, 0777, true);
}
if (is_writable($runtimeCacheDir)) {
$runtimeCachePath = $runtimeCacheDir . '/psl.cache.php';
} else {
echo "WARNING: Runtime cache directory is not writable: {$runtimeCacheDir}\n";
}
}

// --- HTTP Conditional Download ---
$headers = ['User-Agent: XOOPS-RegDom/1.1 (https://xoops.org)'];
$meta = file_exists($metaPath) ? json_decode(file_get_contents($metaPath), true) : [];
if (!empty($meta['etag'])) $headers[] = "If-None-Match: {$meta['etag']}";
if (!empty($meta['last_modified'])) $headers[] = "If-Modified-Since: {$meta['last_modified']}";

echo "Downloading from publicsuffix.org...\n";
$context = stream_context_create(['http' => ['method' => 'GET', 'timeout' => 20, 'header' => implode("\r\n", $headers), 'ignore_errors' => true]]);
$latestList = @file_get_contents($sourceUrl, false, $context);
$responseHeaders = $http_response_header ?? [];
$statusCode = 0;
foreach ($responseHeaders as $header) if (preg_match('/^HTTP\/\d\.\d\s+(\d+)/', $header, $m)) $statusCode = (int)$m[1];

if ($statusCode === 304) {
echo "SUCCESS: Public Suffix List is already up-to-date (304 Not Modified).\n";
exit(0);
}

if ($latestList === false || $statusCode !== 200) {
echo "WARNING: Failed to download PSL (HTTP {$statusCode}). Keeping existing cache.\n";
exit(0); // Not a fatal error; existing cache is still valid.
}

// --- Parse and Generate Cache ---
echo "Parsing rules...\n";
$lines = explode("\n", $latestList);
$rules = ['NORMAL' => [], 'WILDCARD' => [], 'EXCEPTION' => []];
foreach ($lines as $line) {
$line = trim($line);
if (empty($line) || strpos($line, '//') === 0) continue;
if (strpos($line, '!') === 0) $rules['EXCEPTION'][substr($line, 1)] = true;
elseif (strpos($line, '*.') === 0) $rules['WILDCARD'][substr($line, 2)] = true;
else $rules['NORMAL'][$line] = true;
}

$totalRules = count($rules['NORMAL']) + count($rules['WILDCARD']) + count($rules['EXCEPTION']);
if ($totalRules < 1000) {
echo "ERROR: Parsed rule count ({$totalRules}) is suspiciously low. Aborting update.\n";
exit(1);
}

$cacheHeader = "<?php\n/**\n * Public Suffix List Cache\n * Generated: " . date('Y-m-d H:i:s T') . "\n * Source: {$sourceUrl}\n * License: Mozilla Public License 2.0 (https://publicsuffix.org/)\n */\n";
$cacheContent = $cacheHeader . "\nreturn " . var_export($rules, true) . ";\n";

// --- Atomic Write to Caches ---
$writePaths = ['bundled' => $bundledCachePath];
if ($runtimeCachePath) $writePaths['runtime'] = $runtimeCachePath;

foreach ($writePaths as $type => $cachePath) {
$tmpPath = $cachePath . '.tmp.' . getmypid();
if (file_put_contents($tmpPath, $cacheContent, LOCK_EX) && rename($tmpPath, $cachePath)) {
echo "SUCCESS: {$type} cache updated with {$totalRules} rules.\n";
} else {
echo "WARNING: Could not write {$type} cache to {$cachePath}.\n";
@unlink($tmpPath);
}
}

// --- Save Metadata ---
$newMeta = ['updated' => date('c'), 'etag' => null, 'last_modified' => null];
foreach ($responseHeaders as $header) {
if (stripos($header, 'ETag:') === 0) $newMeta['etag'] = trim(substr($header, 5));
if (stripos($header, 'Last-Modified:') === 0) $newMeta['last_modified'] = trim(substr($header, 14));
}
file_put_contents($metaPath, json_encode($newMeta, JSON_PRETTY_PRINT));

echo "Update complete.\n";
exit(0);
Loading
Loading