Skip to content

Commit

Permalink
type hinting
Browse files Browse the repository at this point in the history
new tests testSetURL(), testFallbackURL()
code improvements, cosmetics
  • Loading branch information
mambax7 committed Jul 1, 2024
1 parent 84caf85 commit ceb6811
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 103 deletions.
77 changes: 32 additions & 45 deletions src/PublicSuffixList.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php
<?php declare(strict_types=1);

namespace Xoops\RegDom;

/**
Expand All @@ -13,19 +14,17 @@
*/
class PublicSuffixList
{
protected $sourceURL = 'https://publicsuffix.org/list/public_suffix_list.dat';
protected $localPSL = 'public_suffix_list.dat';
protected $cachedPrefix = 'cached_';

protected $tree;
protected $url;
protected $dataDir = '/../data/'; // relative to __DIR__

private string $sourceURL = 'https://publicsuffix.org/list/public_suffix_list.dat';
private string $localPSL = 'public_suffix_list.dat';
private string $cachedPrefix = 'cached_';
private ?array $tree = null;
private ?string $url = null;
private string $dataDir = '/../data/'; // relative to __DIR__
/**
* PublicSuffixList constructor.
* @param string|null $url URL for the PSL or null to use default
*/
public function __construct($url = null)
public function __construct(?string $url = null)
{
$this->setURL($url);
}
Expand All @@ -34,10 +33,9 @@ public function __construct($url = null)
* Set the URL, and clear any existing tree
*
* @param string|null $url URL for the PSL or null to use default
*
* @return void
*/
public function setURL($url)
public function setURL(?string $url): void
{
$this->url = $url;
$this->tree = null;
Expand All @@ -49,7 +47,7 @@ public function setURL($url)
*
* @return void
*/
protected function setFallbackURL()
private function setFallbackURL(): void
{
$this->setLocalPSLName($this->url);
if (null === $this->url) {
Expand All @@ -61,15 +59,14 @@ protected function setFallbackURL()
* Load the PSL tree, automatically handling caches
*
* @return void (results in $this->tree)
*
* @throws \RuntimeException
*/
protected function loadTree()
private function loadTree(): void
{
$this->setFallbackURL();

$this->tree = $this->readCachedPSL($this->url);
if (false !== $this->tree) {
if (null !== $this->tree) {
return;
}

Expand All @@ -88,15 +85,14 @@ protected function loadTree()
* Parse the PSL data
*
* @param string $fileData the PSL data
*
* @return void (results in $this->tree)
*/
protected function parsePSL($fileData)
private function parsePSL(string $fileData): void
{
$lines = explode("\n", $fileData);

foreach ($lines as $line) {
if ($this->startsWith($line, '//') || '' == $line) {
if ('' === $line || $this->startsWith($line, '//')) {
continue;
}

Expand All @@ -110,25 +106,23 @@ protected function parsePSL($fileData)
/**
* Does $search start with $startString?
*
* @param string $search the string to test
* @param string $search the string to test
* @param string $startString the starting string to match
*
* @return bool
*/
protected function startsWith($search, $startString)
private function startsWith(string $search, string $startString): bool
{
return (0 === strpos($search, $startString));
}

/**
* Add domains to tree
*
* @param array $node tree array by reference
* @param array $node tree array by reference
* @param string[] $tldParts array of domain parts
*
* @return void - changes made to $node by reference
*/
protected function buildSubDomain(&$node, $tldParts)
private function buildSubDomain(array &$node, array $tldParts): void
{
$dom = trim(array_pop($tldParts));

Expand All @@ -146,7 +140,7 @@ protected function buildSubDomain(&$node, $tldParts)
}
}

if (!$isNotDomain && count($tldParts) > 0) {
if (!$isNotDomain && 0 < count($tldParts)) {
$this->buildSubDomain($node[$dom], $tldParts);
}
}
Expand All @@ -157,7 +151,7 @@ protected function buildSubDomain(&$node, $tldParts)
* @return array the PSL tree
* @throws \RuntimeException if PSL cannot be loaded
*/
public function getTree()
public function getTree(): array
{
if (null === $this->tree) {
$this->loadTree();
Expand All @@ -171,7 +165,7 @@ public function getTree()
*
* @return string|false PSL file contents or false on error
*/
protected function readPSL()
private function readPSL()
{
$parts = parse_url($this->url);
$remote = isset($parts['scheme']) || isset($parts['host']);
Expand Down Expand Up @@ -206,10 +200,9 @@ protected function readPSL()
* Determine cache file name for a specified source
*
* @param string $url URL/filename of source PSL
*
* @return string cache file name for given resource
*/
protected function getCacheFileName($url)
private function getCacheFileName(string $url): string
{
return __DIR__ . $this->dataDir . $this->cachedPrefix . md5($url);
}
Expand All @@ -218,26 +211,23 @@ protected function getCacheFileName($url)
* Attempt to load a cached Public Suffix List tree for a given source
*
* @param string $url URL/filename of source PSL
*
* @return false|string[] PSL tree
*/
protected function readCachedPSL($url)
private function readCachedPSL(string $url)
{
$cacheFile = $this->getCacheFileName($url);
return file_exists($cacheFile)
? unserialize(file_get_contents($cacheFile), ['allowed_classes' => false])
: false;
: null;
}


/**
* Cache the current Public Suffix List tree and associate with the specified source
*
* @param string $url URL/filename of source PSL
*
* @return bool|int the number of bytes that were written to the file, or false on failure
*/
protected function cachePSL($url)
private function cachePSL(string $url)
{
return file_put_contents($this->getCacheFileName($url), serialize($this->tree));
}
Expand All @@ -246,22 +236,20 @@ protected function cachePSL($url)
* Save a local copy of a retrieved Public Suffix List
*
* @param string $fileContents URL/filename of source PSL
*
* @return bool|int the number of bytes that were written to the file, or false on failure
*/
protected function saveLocalPSL($fileContents)
private function saveLocalPSL(string $fileContents)
{
return file_put_contents(__DIR__ . $this->localPSL, $fileContents);
}

/**
* Set localPSL name based on URL
*
* @param null|string $url the URL for the PSL
*
* @param string|null $url the URL for the PSL
* @return void (sets $this->localPSL)
*/
protected function setLocalPSLName($url)
private function setLocalPSLName(?string $url): void
{
if (null === $url) {
$url = $this->sourceURL;
Expand All @@ -275,17 +263,16 @@ protected function setLocalPSLName($url)
* Delete files in the data directory
*
* @param bool $cacheOnly true to limit clearing to cached serialized PSLs, false to clear all
*
* @return void
*/
public function clearDataDirectory($cacheOnly = false)
public function clearDataDirectory(bool $cacheOnly = false): void
{
$dir = __DIR__ . $this->dataDir;
if (is_dir($dir)) {
if ($dirHandle = opendir($dir)) {
if (false !== ($dirHandle = opendir($dir))) {
while (false !== ($file = readdir($dirHandle))) {
if ('file' === filetype($dir . $file)
&& (false === $cacheOnly || $this->startsWith($file, $this->cachedPrefix))) {
&& (!$cacheOnly || $this->startsWith($file, $this->cachedPrefix))) {
unlink($dir . $file);
}
}
Expand Down
65 changes: 33 additions & 32 deletions src/RegisteredDomain.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php
<?php declare(strict_types=1);

namespace Xoops\RegDom;

/**
Expand All @@ -12,22 +13,20 @@
* @author Richard Griffith <[email protected]>
* @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
*/

class RegisteredDomain
{
protected $tree;
protected $psl;
private ?array $tree = null;
private PublicSuffixList $psl;

/**
* RegisteredDomain constructor.
*
* @param PublicSuffixList|null $psl PublicSuffixList object, or null to use defaults
*/
public function __construct(PublicSuffixList $psl = null)
public function __construct(?PublicSuffixList $psl = null)
{
if (null === $psl) {
$psl = new PublicSuffixList();
}
$this->psl = $psl;
$this->psl = $psl ?? new PublicSuffixList();
}

/**
Expand All @@ -38,7 +37,7 @@ public function __construct(PublicSuffixList $psl = null)
*
* @return string
*/
protected function normalizeHost($url)
protected function normalizeHost(string $url): string
{
if (empty($url)) {
return '';
Expand All @@ -59,35 +58,32 @@ protected function normalizeHost($url)
}

/**
* Convert a punycode string to UTF-8 if needed
* Convert a punycode string to UTF-8 if needed.
*
* @param string $part host component
* @param string $part Host component
*
* @return string host component as UTF-8
* @return string Host component as UTF-8
*/
protected function convertPunycode($part)
protected function convertPunycode(string $part): string
{
if (0 === strpos($part, 'xn--')) {
if (function_exists('idn_to_utf8')) {
if (defined('INTL_IDNA_VARIANT_UTS46')) { // PHP 7.2
return idn_to_utf8($part, 0, INTL_IDNA_VARIANT_UTS46);
}
return idn_to_utf8($part);
return defined('INTL_IDNA_VARIANT_UTS46') ? idn_to_utf8($part, 0, INTL_IDNA_VARIANT_UTS46) : idn_to_utf8($part);
}
return $this->decodePunycode($part);
}
return $part;
}

/**
* convert punycode to UTF-8 (the hard way) Used only if idn_to_utf8() is not available
* Convert punycode to UTF-8 (the hard way) if idn_to_utf8() is not available.
*
* This fallback adapted from https://ckon.wordpress.com/2010/08/24/punycode-to-unicode-converter-php/
*
* @param string $encoded
* @return string
*/
protected function decodePunycode($encoded)
protected function decodePunycode(string $encoded): string
{
$prefix = 'xn--';
$safe_char = 0xFFFC;
Expand All @@ -97,7 +93,12 @@ protected function decodePunycode($encoded)
$skew = 38;
$damp = 700;

if (null === $encoded || 0 !== strpos($encoded, $prefix) || 0 == strlen(trim(str_replace($prefix, '', $encoded)))) {
if (0 !== strpos($encoded, $prefix)) {
return $encoded;
}

$trimmed = trim(str_replace($prefix, '', $encoded));
if ('' === $trimmed) {
return $encoded;
}

Expand Down Expand Up @@ -171,13 +172,13 @@ protected function decodePunycode($encoded)
}

/**
* Determine the registered domain portion of the supplied host string
* Determine the registered domain portion of the supplied host string.
*
* @param string $host a host name or URL containing a host name
* @param string $host A host name or URL containing a host name
*
* @return string|null shortest registrable domain portion of the supplied host or null if invalid
* @return string|null Shortest registrable domain portion of the supplied host or null if invalid
*/
public function getRegisteredDomain($host)
public function getRegisteredDomain(string $host): ?string
{
$this->tree = $this->psl->getTree();

Expand All @@ -194,7 +195,7 @@ public function getRegisteredDomain($host)
// assure there is at least 1 TLD in the stripped signing domain
if (!strpos($result, '.')) {
$cnt = count($signingDomainParts);
if (1 == $cnt || '' == $signingDomainParts[$cnt-2]) {
if (1 === $cnt || '' === $signingDomainParts[$cnt-2]) {
return null;
}
return $signingDomainParts[$cnt-2] . '.' . $signingDomainParts[$cnt-1];
Expand All @@ -203,23 +204,23 @@ public function getRegisteredDomain($host)
}

/**
* Recursive helper method to query the PSL tree
* Recursive helper method to query the PSL tree.
*
* @param string[] $remainingSigningDomainParts parts of domain being queried
* @param string[] $treeNode subset of tree array by reference
* @param string[] $remainingSigningDomainParts Parts of domain being queried
* @param array $treeNode Subset of tree array by reference
*
* @return null|string
* @return string|null
*/
protected function findRegisteredDomain($remainingSigningDomainParts, &$treeNode)
protected function findRegisteredDomain(array $remainingSigningDomainParts, array &$treeNode): ?string
{
$sub = array_pop($remainingSigningDomainParts);

$result = null;
if (isset($treeNode['!'])) {
return '';
} elseif (is_array($treeNode) && array_key_exists($sub, $treeNode)) {
} elseif (array_key_exists($sub, $treeNode)) {
$result = $this->findRegisteredDomain($remainingSigningDomainParts, $treeNode[$sub]);
} elseif (is_array($treeNode) && array_key_exists('*', $treeNode)) {
} elseif (array_key_exists('*', $treeNode)) {
$result = $this->findRegisteredDomain($remainingSigningDomainParts, $treeNode['*']);
} else {
return $sub;
Expand Down
Loading

0 comments on commit ceb6811

Please sign in to comment.