-
Notifications
You must be signed in to change notification settings - Fork 1
Refactoring #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactoring #7
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This is a comprehensive refactoring that modernizes the RegDom library to use a cache-based approach for the Public Suffix List (PSL), introduces static domain matching functionality, and improves the overall architecture.
Key changes include:
- Replacing tree-based PSL storage with direct cache lookup for better performance
- Adding RFC 6265 compliant cookie domain validation with
domainMatches()static method - Restructuring tests with proper namespace organization and mocking strategies
Reviewed Changes
Copilot reviewed 10 out of 12 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/RegisteredDomainTest.php | Refactored to use mocked PSL with comprehensive test coverage for domain registration and matching |
| tests/unit/PublicSuffixListTest.php | Simplified tests focused on core PSL functionality with proper namespace |
| tests/integration/IntegrationTest.php | New integration tests using real PSL data with cache validation |
| src/RegisteredDomain.php | Complete rewrite using cache-based PSL lookups and static domain matching |
| src/PublicSuffixList.php | Replaced tree-based parsing with direct cache loading and improved metadata handling |
| phpunit.xml.dist | Updated configuration with separate test suites and improved coverage reporting |
| data/psl.meta.json | New metadata file for PSL cache tracking |
| composer.json | Enhanced dependencies, scripts, and project metadata |
| .scrutinizer.yml | Expanded CI configuration for multiple PHP versions |
| .github/workflows/pr_tests.yml | Modernized GitHub Actions workflow with matrix testing |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
tests/unit/RegisteredDomainTest.php
Outdated
| fn(string $d) => in_array($d, ['com', 'co.uk', 'ck'], true) | ||
| ); | ||
|
|
||
| // FIX: Use -> not . |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment appears to be a leftover from development. It should be removed as it doesn't provide meaningful context for the code.
| // FIX: Use -> not . |
tests/unit/PublicSuffixListTest.php
Outdated
| <?php declare(strict_types=1); | ||
|
|
||
| namespace Xoops\RegDom; | ||
| namespace Xoops\RegDom\Tests; // <-- CORRECT NAMESPACE |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The inline comment '// <-- CORRECT NAMESPACE' should be removed as it's unnecessary and adds no value to the code.
| namespace Xoops\RegDom\Tests; // <-- CORRECT NAMESPACE | |
| namespace Xoops\RegDom\Tests; |
src/RegisteredDomain.php
Outdated
|
|
||
| if (0 !== \strpos($encoded, $prefix)) { | ||
| return $encoded; | ||
| // ... This method is already correct from the previous step ... |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This placeholder comment should be removed as it doesn't provide meaningful documentation for the actual implementation.
| // ... This method is already correct from the previous step ... |
src/RegisteredDomain.php
Outdated
| private static function normalizeHost(string $input): string | ||
| { | ||
| $this->tree = $this->psl->getTree(); | ||
|
|
||
| $signingDomain = $this->normalizeHost($host); | ||
| $signingDomainParts = \explode('.', $signingDomain); | ||
|
|
||
| $result = $this->findRegisteredDomain($signingDomainParts, $this->tree); | ||
|
|
||
| if (empty($result)) { | ||
| // this is an invalid domain name | ||
| return null; | ||
| // This method is already correct from the previous step |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This placeholder comment should be removed as it doesn't describe what the method actually does.
src/RegisteredDomain.php
Outdated
| private static function toAscii(string $host): string | ||
| { | ||
| $sub = \array_pop($remainingSigningDomainParts); | ||
|
|
||
| $result = null; | ||
| if (isset($treeNode['!'])) { | ||
| // This method is already correct |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This placeholder comment should be removed and replaced with proper documentation explaining the method's purpose.
src/PublicSuffixList.php
Outdated
| if (is_file($path) && is_readable($path)) { | ||
| $rules = include $path; | ||
|
|
||
| // FINAL: Add explicit is_array checks for the inner arrays. |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This development comment should be removed as it doesn't provide meaningful documentation for production code.
| // FINAL: Add explicit is_array checks for the inner arrays. |
| "require": { | ||
| "php": "^7.4.0 || ^8.4.0", | ||
| "symfony/polyfill-mbstring": "^1.33.0" | ||
| "php": "^7.4 || ^8.0", |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PHP version constraint should be simplified to '^7.4' since '^7.4' already includes PHP 8.0 and later versions. The '|| ^8.0' part is redundant.
| "php": "^7.4 || ^8.0", | |
| "php": "^7.4", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 11 out of 13 changed files in this pull request and generated 4 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| // Add a check for exception rules first | ||
| if ($this->psl->isException($normalizedHost)) { | ||
| return $normalizedHost; |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for handling PSL exception rules is incorrect. Exception rules should allow registration at a level that would normally be blocked by a wildcard rule, not return the full host as registrable. For exception rules like !city.kobe.jp, the registrable domain should be determined by normal PSL logic after removing the exception prefix.
| // Add a check for exception rules first | |
| if ($this->psl->isException($normalizedHost)) { | |
| return $normalizedHost; | |
| // Handle PSL exception rules correctly | |
| if ($this->psl->isException($normalizedHost)) { | |
| // Remove the exception suffix from the host | |
| $exceptionSuffix = $this->psl->getExceptionSuffix($normalizedHost); | |
| if ($exceptionSuffix !== null) { | |
| // Remove the exception suffix from the end of the host | |
| $hostWithoutSuffix = preg_replace('/(\.|^)'.preg_quote($exceptionSuffix, '/').'$/', '', $normalizedHost); | |
| $hostAscii = self::toAscii($hostWithoutSuffix); | |
| $publicSuffix = $this->psl->getPublicSuffix($hostAscii); | |
| if ($publicSuffix === null || $hostAscii === $publicSuffix) { | |
| return null; | |
| } | |
| $hostParts = explode('.', $hostAscii); | |
| $suffixParts = explode('.', $publicSuffix); | |
| $registrableParts = array_slice($hostParts, - (count($suffixParts) + 1)); | |
| $registrableAscii = implode('.', $registrableParts); | |
| if ($utf8 && function_exists('idn_to_utf8')) { | |
| return idn_to_utf8($registrableAscii, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46) ?: $registrableAscii; | |
| } | |
| return $registrableAscii; | |
| } |
| while ($delta > (($base - $tmin) * $tmax) / 2) { | ||
| $delta = (int) ($delta / ($base - $tmin)); | ||
| $k += $base; | ||
| $usePSL = !defined('XOOPS_COOKIE_DOMAIN_USE_PSL') || XOOPS_COOKIE_DOMAIN_USE_PSL; |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This constant-based feature flag creates an undocumented configuration dependency. Consider using a constructor parameter or method argument instead of a global constant to make the PSL usage configurable in a more explicit and testable way.
src/PublicSuffixList.php
Outdated
|
|
||
| $this->buildSubDomain($this->tree, $tldParts); | ||
| } | ||
| error_log('[RegDom] WARNING: No valid PSL cache found. Run `composer update-psl`.'); |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using error_log() for warnings makes error handling inconsistent and harder to control in different environments. Consider throwing a specific exception or using a configurable logger interface to allow applications to handle PSL loading failures appropriately.
tests/unit/RegisteredDomainTest.php
Outdated
| private static function setStaticPslInstance(?PublicSuffixList $psl): void | ||
| { | ||
| return [ | ||
| ['', ''], | ||
| // Mixed case. | ||
| ['test', 'test'], | ||
| // punycoded | ||
| ['xn--85x722f', '食狮'], | ||
| ['xn--55qx5d', '公司'], | ||
| ['xn--fiqs8s', '中国'], | ||
| ]; | ||
| } | ||
| $reflection = new \ReflectionClass(RegisteredDomain::class); | ||
| $property = $reflection->getProperty('pslInstance'); | ||
| $property->setAccessible(true); | ||
| $property->setValue(null, $psl); | ||
| } |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using reflection to manipulate static properties in tests indicates a design issue with testability. Consider adding a public static method in RegisteredDomain for resetting the PSL instance in test environments, or making the static dependency injection more explicit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 12 out of 14 changed files in this pull request and generated 3 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
src/PublicSuffixList.php
Outdated
| * @return array<string, mixed> Metadata about the active cache. | ||
| */ | ||
| private function getCacheFileName(string $url): string | ||
| { | ||
| return __DIR__ . $this->dataDir . $this->cachedPrefix . \md5($url); | ||
| } | ||
|
|
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing PHPDoc comment for the public method. The method should include a proper docblock describing its purpose, return type, and any exceptions it might throw.
tests/unit/RegisteredDomainTest.php
Outdated
| $this->assertSame($expected, RegisteredDomain::domainMatches($host, $domain)); | ||
| self::setStaticPslInstance(null); |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Static state manipulation in tests can cause issues with test isolation. Consider using setUp/tearDown methods or a try-finally block to ensure the static state is always reset, even if assertions fail.
| $this->assertSame($expected, RegisteredDomain::domainMatches($host, $domain)); | |
| self::setStaticPslInstance(null); | |
| try { | |
| $this->assertSame($expected, RegisteredDomain::domainMatches($host, $domain)); | |
| } finally { | |
| self::setStaticPslInstance(null); | |
| } |
| public static function setTestPslInstance(?PublicSuffixList $psl): void | ||
| { | ||
| self::$pslInstance = $psl; | ||
| } |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exposing static state setters for testing purposes creates a fragile API. Consider using dependency injection or a factory pattern instead of static state manipulation for better testability and design.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 12 out of 14 changed files in this pull request and generated 3 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
tests/unit/RegisteredDomainTest.php
Outdated
| private static function setStaticPslInstance(?PublicSuffixList $psl): void | ||
| { | ||
| return [ | ||
| ['', ''], | ||
| // Mixed case. | ||
| ['test', 'test'], | ||
| // punycoded | ||
| ['xn--85x722f', '食狮'], | ||
| ['xn--55qx5d', '公司'], | ||
| ['xn--fiqs8s', '中国'], | ||
| ]; | ||
| } | ||
| RegisteredDomain::setTestPslInstance($psl); | ||
| } |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This private static method appears to be unused and simply wraps the public static method. Consider removing this unnecessary wrapper method as it doesn't add any value.
src/PublicSuffixList.php
Outdated
| $cacheFile = $this->getCacheFileName($url); | ||
| return \file_exists($cacheFile) | ||
| ? \unserialize(\file_get_contents($cacheFile), ['allowed_classes' => false]) | ||
| // ... method body remains the same ... |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment placeholder should be removed as it doesn't provide any meaningful information about the method implementation.
| // ... method body remains the same ... | |
| "require": { | ||
| "php": "^7.4.0 || ^8.4.0", | ||
| "symfony/polyfill-mbstring": "^1.33.0" | ||
| "php": "^7.4 || ^8.0", |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PHP version constraint allows ^7.4 but the platform configuration locks it to 7.4.0. This inconsistency could cause confusion. Consider using '^7.4.0 || ^8.0' to be more explicit about the minimum patch version.
| "php": "^7.4 || ^8.0", | |
| "php": "^7.4.0 || ^8.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 12 out of 14 changed files in this pull request and generated 1 comment.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
src/PublicSuffixList.php
Outdated
| $this->parsePSL($list); | ||
| $this->cachePSL($this->url); | ||
| // Last resort: throw an exception instead of logging | ||
| throw new \Xoops\RegDom\Exception\PslCacheNotFoundException('No valid PSL cache found. Run `composer update-psl` to generate one.'); |
Copilot
AI
Oct 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message references 'composer update-psl' but the actual script command is 'composer run update-psl' according to composer.json. This inconsistency could confuse users.
| throw new \Xoops\RegDom\Exception\PslCacheNotFoundException('No valid PSL cache found. Run `composer update-psl` to generate one.'); | |
| throw new \Xoops\RegDom\Exception\PslCacheNotFoundException('No valid PSL cache found. Run `composer run update-psl` to generate one.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 12 out of 14 changed files in this pull request and generated no new comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
No description provided.