From bcf60aeddbb855bf11a227409072daad2749bbb2 Mon Sep 17 00:00:00 2001 From: Glomberg Date: Thu, 16 Jul 2026 15:05:04 +0300 Subject: [PATCH 1/7] New. Code. Implementing the library main class. --- BotDetectorService.php | 98 ++++++++++++++++++++++++++++++++++++++++++ composer.json | 5 ++- 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 BotDetectorService.php diff --git a/BotDetectorService.php b/BotDetectorService.php new file mode 100644 index 0000000..ce7b9f1 --- /dev/null +++ b/BotDetectorService.php @@ -0,0 +1,98 @@ +loadWrapperURL() ) { + return htmlspecialchars($url_from_bd, ENT_QUOTES); + } + + return htmlspecialchars( + sprintf("https://%s/%s", self::BD_DEFAULT_DOMAIN, self::BD_DEFAULT_SCRIPT_NAME) + , ENT_QUOTES + ); + } + + /** + * @param string $api_key + * @return void + */ + public function updateWrapperURL($api_key) + { + $url_from_api = $this->callAPIMethod($api_key); + if ( ! $this->validateWrapperURL($url_from_api) ) { + return; + } + if ( ! $this->isWrapperAvailable($url_from_api) ) { + return; + } + if ( ! $this->validateWrapperContent($url_from_api) ) { + return; + } + + $url_from_bd = $this->loadWrapperURL(); + + if ( $url_from_api !== $url_from_bd ) { + $this->saveWrapperURL($url_from_api); + } + } + + /** + * @param string $wrapper_url + * @return bool + */ + private function validateWrapperURL($wrapper_url) + { + return (bool) preg_match("/^https?:\/\/.*cleantalk\..*/", $wrapper_url); + } + + /** + * @param $wrapper_url + * @return bool + */ + private function validateWrapperContent($wrapper_url) + { + // 1) Get content from $wrapper_url + // 2) Validate this + return true; + } +} diff --git a/composer.json b/composer.json index 8e98efb..7f40073 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,9 @@ "Cleantalk\\Common\\BotDetectorService\\": "/" } }, + "require": { + "cleantalk/http": "*" + }, "require-dev": { "vimeo/psalm": "^4.8", "phpunit/phpunit": "^8.5.52", @@ -33,4 +36,4 @@ "vendor/bin/psalm --no-cache --config=tests/psalm.xml --taint-analysis" ] } -} \ No newline at end of file +} From 4c5f33986a23fcc57a772a50f0e4e2be67f557c5 Mon Sep 17 00:00:00 2001 From: Glomberg Date: Thu, 16 Jul 2026 15:08:20 +0300 Subject: [PATCH 2/7] Fix. Code. Code style fixed. --- .gitignore | 3 +++ BotDetectorService.php | 12 ++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 485dee6..ecbdba1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ .idea +/composer.lock +/tests/.phpunit.result.cache +/vendor/ diff --git a/BotDetectorService.php b/BotDetectorService.php index ce7b9f1..b1d5902 100644 --- a/BotDetectorService.php +++ b/BotDetectorService.php @@ -18,24 +18,24 @@ abstract class BotDetectorService * @param string $api_key * @return string|false */ - abstract function callAPIMethod($api_key); + abstract public function callAPIMethod($api_key); /** * @param string $wrapper_url * @return bool */ - abstract function isWrapperAvailable($wrapper_url); + abstract public function isWrapperAvailable($wrapper_url); /** * @param string $wrapper_url * @return void */ - abstract function saveWrapperURL($wrapper_url); + abstract public function saveWrapperURL($wrapper_url); /** * @return string */ - abstract function loadWrapperURL(); + abstract public function loadWrapperURL(); /** * @return string @@ -47,8 +47,8 @@ public function getWrapperURL() } return htmlspecialchars( - sprintf("https://%s/%s", self::BD_DEFAULT_DOMAIN, self::BD_DEFAULT_SCRIPT_NAME) - , ENT_QUOTES + sprintf("https://%s/%s", self::BD_DEFAULT_DOMAIN, self::BD_DEFAULT_SCRIPT_NAME), + ENT_QUOTES ); } From 4083a86b752e0a1e06819ac0e83ba1213957d784 Mon Sep 17 00:00:00 2001 From: Glomberg Date: Thu, 16 Jul 2026 15:29:49 +0300 Subject: [PATCH 3/7] Fix. Code. Copilot review fixed #1. --- BotDetectorService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BotDetectorService.php b/BotDetectorService.php index b1d5902..f7b152d 100644 --- a/BotDetectorService.php +++ b/BotDetectorService.php @@ -33,7 +33,7 @@ abstract public function isWrapperAvailable($wrapper_url); abstract public function saveWrapperURL($wrapper_url); /** - * @return string + * @return string|false */ abstract public function loadWrapperURL(); From b2e4e52c498ed8a8cee6b8b722e8d6e723c6f695 Mon Sep 17 00:00:00 2001 From: Glomberg Date: Thu, 16 Jul 2026 15:32:05 +0300 Subject: [PATCH 4/7] Fix. Code. Copilot review fixed #2. --- BotDetectorService.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/BotDetectorService.php b/BotDetectorService.php index f7b152d..3dc2315 100644 --- a/BotDetectorService.php +++ b/BotDetectorService.php @@ -82,7 +82,21 @@ public function updateWrapperURL($api_key) */ private function validateWrapperURL($wrapper_url) { - return (bool) preg_match("/^https?:\/\/.*cleantalk\..*/", $wrapper_url); + if ( ! is_string($wrapper_url) || $wrapper_url === '' ) { + return false; + } + $parts = parse_url($wrapper_url); + if ( empty($parts['scheme']) || empty($parts['host']) ) { + return false; + } + $scheme = strtolower($parts['scheme']); + if ( $scheme !== 'https' && $scheme !== 'http' ) { + return false; + } + $host = strtolower($parts['host']); + + // Allow cleantalk. and subdomains like fd.cleantalk.org + return (bool) preg_match('/(^|\.)cleantalk\.[a-z0-9-]{2,}$/', $host); } /** From 033b1880c177029f9be8c141dc8715aa7e04693c Mon Sep 17 00:00:00 2001 From: Glomberg Date: Thu, 16 Jul 2026 15:33:45 +0300 Subject: [PATCH 5/7] Fix. Code. Copilot review fixed #3. --- BotDetectorService.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/BotDetectorService.php b/BotDetectorService.php index 3dc2315..79168dd 100644 --- a/BotDetectorService.php +++ b/BotDetectorService.php @@ -43,12 +43,13 @@ abstract public function loadWrapperURL(); public function getWrapperURL() { if ( $url_from_bd = $this->loadWrapperURL() ) { - return htmlspecialchars($url_from_bd, ENT_QUOTES); + return htmlspecialchars($url_from_bd, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); } return htmlspecialchars( sprintf("https://%s/%s", self::BD_DEFAULT_DOMAIN, self::BD_DEFAULT_SCRIPT_NAME), - ENT_QUOTES + ENT_QUOTES | ENT_SUBSTITUTE, + 'UTF-8' ); } From 2d0147b2aa05334689d8704838f9e7f0c93d588e Mon Sep 17 00:00:00 2001 From: Glomberg Date: Fri, 17 Jul 2026 14:38:35 +0300 Subject: [PATCH 6/7] Fix. Code. Review notice fixed. --- BotDetectorService.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/BotDetectorService.php b/BotDetectorService.php index 79168dd..750a6d1 100644 --- a/BotDetectorService.php +++ b/BotDetectorService.php @@ -42,7 +42,8 @@ abstract public function loadWrapperURL(); */ public function getWrapperURL() { - if ( $url_from_bd = $this->loadWrapperURL() ) { + $url_from_bd = $this->loadWrapperURL(); + if ( $url_from_bd ) { return htmlspecialchars($url_from_bd, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); } From 666b2210d4a7a9ef5be020936a92426498419ece Mon Sep 17 00:00:00 2001 From: Glomberg Date: Fri, 17 Jul 2026 14:39:09 +0300 Subject: [PATCH 7/7] Fix. API. API calling implemented. --- Api/Api.php | 22 ++++++++++++++++++++++ BotDetectorService.php | 23 ++++++++++++++++++++--- composer.json | 6 +++++- 3 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 Api/Api.php diff --git a/Api/Api.php b/Api/Api.php new file mode 100644 index 0000000..4ab314b --- /dev/null +++ b/Api/Api.php @@ -0,0 +1,22 @@ + self::METHOD_NAME, + 'auth_key' => $api_key, + ); + + return self::sendRequest($request);*/ + } +} diff --git a/BotDetectorService.php b/BotDetectorService.php index 750a6d1..fd41282 100644 --- a/BotDetectorService.php +++ b/BotDetectorService.php @@ -2,9 +2,13 @@ namespace Cleantalk\Common\BotDetectorService; +use Cleantalk\Common\BotDetectorService\Api\Api; +use Cleantalk\Common\Mloader\Mloader; +use Cleantalk\Common\Templates\Singleton; + abstract class BotDetectorService { - const METHOD_NAME = "get_bot_detector_wrapper_url"; + use Singleton; const BD_DEFAULT_DOMAIN = "fd.cleantalk.org"; @@ -18,13 +22,26 @@ abstract class BotDetectorService * @param string $api_key * @return string|false */ - abstract public function callAPIMethod($api_key); + public function callAPIMethod($api_key) + { + return Api::methodGetBotDetectorWrapperUrl($api_key); + } /** * @param string $wrapper_url * @return bool */ - abstract public function isWrapperAvailable($wrapper_url); + public function isWrapperAvailable($wrapper_url) + { + $request_class = Mloader::get('Http\Request'); + $http = new $request_class(); + + $response = $http->setUrl($wrapper_url) + ->setPresets(['get_code']) + ->request(); + + return 200 === $response; + } /** * @param string $wrapper_url diff --git a/composer.json b/composer.json index 7f40073..e4893f2 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,11 @@ } }, "require": { - "cleantalk/http": "*" + "cleantalk/http": "*", + "cleantalk/templates": "*", + "cleantalk/api": "*", + "cleantalk/mloader": "*" + }, "require-dev": { "vimeo/psalm": "^4.8",