diff --git a/README.md b/README.md
index 0e8010f..40a977c 100644
--- a/README.md
+++ b/README.md
@@ -4,91 +4,70 @@ php-antispam
[](https://packagist.org/packages/cleantalk/php-antispam)
-A PHP API for antispam service cleantalk.org. Invisible protection from spam, no captches, no puzzles, no animals and no math.
+## The Invisible protection from spam, no captcha, no recaptcha, no puzzles, no math captcha.
+_API for antispam service cleantalk.org_
-## How API stops spam?
-API uses several simple tests to stop spammers.
- * Spam bots signatures.
- * Blacklists checks by Email, IP, web-sites domain names.
- * JavaScript availability.
- * Relevance test for the comment.
+#### Requirements
+* PHP 5.6 and above
+* CURL support
-## How API works?
-API sends a comment's text and several previous approved comments to the servers. Servers evaluates the relevance of the comment's text on the topic, tests on spam and finaly provides a solution - to publish or put on manual moderation of comments. If a comment is placed on manual moderation, the plugin adds to the text of a comment explaining the reason for the ban server publishing.
+### How we stop spam?
+PHP Anti-Spam library providing invisible spam protection for your websites, registration forms, and comment sections. CleanTalk API offers an effective CAPTCHA alternative that silently blocks spam without interrupting your users' experience.
-## Requirements
+When users submit forms on your website form, the form data is securely sent to CleanTalk’s cloud servers. CleanTalk analyzes submissions using advanced heuristics. CleanTalk then returns a real-time verdict— legitimate requests or spam.
- * PHP 5.6 and above
- * CURL support
+You are free to do anything with spam, or just allow as to block spam (we will interrupt desirable request).
-You can unpack the archive with the plugin to the root of the site or install it using the composer
+## Interesting? Let's make some settings (it will take few minutes)
+
+
+### Step 1 - install our SDK (2 variants ability)
+
+Through composer install **OR** through download zip arhive and unzip it to root directory (with your index.php)
```php
composer require cleantalk/php-antispam
```
-
-### Sample SPAM test for text comment
-
-Notice: You can use the example PHP file from ./examples/form_with_handler
-```php
-handle();
+```
-//require_once "lib/cleantalk-php-patch.php"; -- PHP-FPM
+### Step 2.1 - add js lib to your html template
+```html
+
+```
+_Need for gathering frontend data._
-$cleantalk_antispam = new CleantalkAntispam($apikey, $email_field, $user_name_field, $message_field, $type_form);
-$api_result = $cleantalk_antispam->handle();
-if ($api_result) { // the check fired
- if ($api_result->account_status !== 1) {
- // something wrong with your key or license, to know why read $api_result->codes
- echo 'Allowed. Spam protection disabled.'; // or do nothing
- } else {
- if ($api_result->allow === 1) {
- echo 'Allowed. Spam protection OK.'; // or do nothing
- } else {
- die('Blocked. Spam protection OK. Reason: ' . $api_result->comment); // or make your own handler
- }
- }
+### Step 3 - do whatever you want with cloud result
+For example add die block for spam.
+```php
+if ($api_result && $api_result->allow === 0) {
+ die('Blocked. Spam protection OK. Reason: ' . $api_result->comment);
+ // or make your own actions/logs/messages ...
}
-// your further code flow here
-?>
-
-
-
-frontendScript(); ?>
```
-## API Response description
-API returns (`$api_result`) PHP object:
- * allow (0|1) - allow to publish or not, in other words spam or ham
- * comment (string) - server comment for requests.
- * id (string MD5 HEX hash) - unique request idenifier.
- * errno (int) - error number. errno == 0 if requests successfull.
- * errstr (string) - comment for error issue, errstr == null if requests successfull.
- * account_status - 0 account disabled, 1 account enabled, -1 unknown status.
+### Step 4 (not required) - we prepare for you special troubleshooting method
+To find possible problems, just add follow snippet after getVerdict method.
+```php
+// TROUBLESHOOTING: logging the suggestions
+error_log($cleantalk_antispam->whatsWrong(true));
+```
+In [example file](https://github.com/CleanTalk/php-antispam/blob/dev/examples/form_with_handler/form_with_handler.php) you can see context.
+
+### Step 5 (not required) - if you have any question, please, feel free to ask it in issue here or in our tiket system
+
+## Examples
+- [api response description](https://github.com/CleanTalk/php-antispam/tree/dev/examples/api_response_description.md)
+- [example with form handler](https://github.com/CleanTalk/php-antispam/blob/dev/examples/form_with_handler/form_with_handler.php)
+
## Don't want to deal with all this?
Universal solution for any CMS or custom website: https://github.com/CleanTalk/php-uni
diff --git a/cleantalk-antispam.php b/cleantalk-antispam.php
index b56e377..26928a4 100644
--- a/cleantalk-antispam.php
+++ b/cleantalk-antispam.php
@@ -1,8 +1,8 @@
valid;
-
-echo "Access key validation result:";
-echo CleantalkAPI::method__notice_validate_key($auth_key, 'php-api');
-echo "\n";
-
-if (!$is_valid) {
- echo "Access key is not valid. Please check access key in the config.\n";
- exit;
-}
-
-// The facility in which to store the query parameters
-$ct_request = new CleantalkRequest();
-
-$ct_request->auth_key = $auth_key;
-$ct_request->message = 'stop_word';
-$ct_request->sender_email = 'stop_email@example.com';
-$ct_request->sender_nickname = 'John Dow';
-$ct_request->example = str_repeat('Just text ', 10);
-$ct_request->agent = 'php-api';
-$ct_request->sender_ip = '178.32.183.43';
-$ct_request->event_token = isset($_POST['ct_bot_detector_event_token']) ? $_POST['ct_bot_detector_event_token'] : null;
-
-$ct = new Cleantalk();
-$ct->server_url = $config_url;
-
-// Check
-$ct_result = $ct->isAllowMessage($ct_request);
-
-if ( $ct_result->allow == 1 ) {
- echo 'Comment allowed. Reason ' . $ct_result->comment;
-} else {
- echo 'Comment blocked. Reason ' . $ct_result->comment;
-}
diff --git a/examples/form_with_handler/form_with_handler.php b/examples/form_with_handler/form_with_handler.php
index df2ff7b..929b1ab 100644
--- a/examples/form_with_handler/form_with_handler.php
+++ b/examples/form_with_handler/form_with_handler.php
@@ -1,47 +1,147 @@
handle();
-if ($api_result) { // the check fired
- if ($api_result->account_status !== 1) {
- // something wrong with your key or license, to know why read $api_result->codes
- echo 'Allowed. Spam protection disabled.'; // or do nothing
- } else {
- if ($api_result->allow === 1) {
- echo 'Allowed. Spam protection OK.'; // or do nothing
- } else {
- die('Blocked. Spam protection OK. Reason: ' . $api_result->comment); // or make your own handler
+require_once '../../../php-antispam/cleantalk-antispam.php';
+
+use CleanTalk\CleantalkAntispam;
+
+?>
+
+
+
+
+
+ Contact Form
+
+
+
+
+
+
+
+
Contact Us
+
+ handle();
+ if ($api_result->allow === 0) {
+ $statusMessage = 'Spam detected - ' . $api_result->comment;
+ $messageType = 'error';
+ }
+
+ // TROUBLESHOOTING: logging the suggestions
+ error_log($cleantalk_antispam->whatsWrong(true));
+ }
+ // END OF HANDLE CLEANTALK ANTISPAM
+
+ if ($messageType !== 'error') {
+ $logEntry = date('Y-m-d H:i:s') . " | Name: $name | Email: $email | Message: $message\n";
+ if (file_put_contents('./contacts.log', $logEntry, FILE_APPEND)) {
+ $statusMessage = 'Thank you for your message! We will get back to you soon.';
+ $messageType = 'success';
+ $name = $email = $message = ''; // Clear form data after successful submission
+ }
}
}
-}
-// your further code flow here
-?>
+ ?>
-
+
+
+
+
+
+
+
+
+
diff --git a/lib/Cleantalk.php b/lib/Cleantalk.php
deleted file mode 100644
index ffa487c..0000000
--- a/lib/Cleantalk.php
+++ /dev/null
@@ -1,635 +0,0 @@
-filterRequest($request);
- $filtered_request = $this->createMsg('check_message', $request);
-
- $this->sender_ip = $filtered_request->sender_ip;
- $this->sender_email = $filtered_request->sender_email;
-
- return $this->httpRequest($filtered_request);
- }
-
- /**
- * Function checks whether it is possible to publish the message
- *
- * @param CleantalkRequest $request
- *
- * @return CleantalkResponse
- * @throws TransportException
- */
- public function isAllowUser(CleantalkRequest $request)
- {
- $request = $this->filterRequest($request);
- $filtered_request = $this->createMsg('check_newuser', $request);
-
- $this->sender_ip = $filtered_request->sender_ip;
- $this->sender_email = $filtered_request->sender_email;
-
- return $this->httpRequest($filtered_request);
- }
-
- /**
- * Function sends the results of manual moderation
- *
- * @param CleantalkRequest $request
- *
- * @return CleantalkResponse
- * @throws TransportException
- */
- public function sendFeedback(CleantalkRequest $request)
- {
- $request = $this->filterRequest($request);
- $filtered_request = $this->createMsg('send_feedback', $request);
-
- $this->sender_ip = $filtered_request->sender_ip;
- $this->sender_email = $filtered_request->sender_email;
-
- return $this->httpRequest($filtered_request);
- }
-
- /**
- * Function checks if visitor is bot or not based on the Bot-detector event token.
- *
- * @param CleantalkRequest $request
- *
- * @return CleantalkResponse
- * @throws TransportException
- */
- public function checkBot(CleantalkRequest $request)
- {
- $request = $this->filterRequest($request);
- $filtered_request = $this->createMsg('check_bot', $request);
-
- return $this->httpRequest($filtered_request);
- }
-
- /**
- * Filter request params
- *
- * @param CleantalkRequest $request
- *
- * @return CleantalkRequest
- */
- private function filterRequest(CleantalkRequest $request)
- {
- // general and optional
- foreach ( $request as $param => $value ) {
- if ( $param == 'js_on' ) {
- if ( ! is_int($value) ) {
- $request->$param = null;
- }
- }
- if ( $param == 'submit_time' ) {
- if ( ! is_int($value) ) {
- $request->$param = null;
- }
- }
- if ( $param == 'message' ) {
- if ( ! is_string($value) ) {
- $request->$param = null;
- }
- } // Should be array, but servers understand only JSON
- if ( $param == 'example' ) {
- if ( ! is_string($value) ) {
- $request->$param = null;
- }
- } // Should be array, but servers understand only JSON
- if ( $param == 'sender_info' ) {
- if ( ! is_string($value) ) {
- $request->$param = null;
- }
- } // Should be array, but servers understand only JSON
- if ( $param == 'post_info' ) {
- if ( ! is_string($value) ) {
- $request->$param = null;
- }
- } // Should be array, but servers understand only JSON
- if ( $param == 'agent' ) {
- if ( ! is_string($value) ) {
- $request->$param = null;
- }
- }
- if ( $param == 'sender_nickname' ) {
- if ( ! is_string($value) ) {
- $request->$param = null;
- }
- }
- if ( $param == 'phone' ) {
- if ( ! is_string($value) ) {
- $request->$param = null;
- }
- }
- if ( $param == 'sender_email' ) {
- if ( ! is_string($value) ) {
- $request->$param = null;
- }
- }
- if ( $param == 'sender_ip' ) {
- if ( ! is_string($value) ) {
- $request->$param = null;
- }
- }
- }
-
- return $request;
- }
-
- /**
- * Compress data and encode to base64
- *
- * @param string $data
- * @psalm-suppress UnusedMethod
- * @return string
- */
- private function compressData($data = '')
- {
- if ( strlen($data) > $this->dataMaxSise && function_exists('gzencode') && function_exists('base64_encode') ) {
- $localData = gzencode($data, $this->compressRate, FORCE_GZIP);
-
- if ( $localData === false ) {
- return $data;
- }
-
- $localData = base64_encode($localData);
-
- if ( $localData === false ) {
- return $data;
- }
-
- return $localData;
- }
-
- return $data;
- }
-
- /**
- * Create msg for cleantalk server
- *
- * @param string $method
- * @param CleantalkRequest $request
- *
- * @return CleantalkRequest
- */
- private function createMsg($method, CleantalkRequest $request)
- {
- switch ($method) {
- case 'check_message':
- // Convert strings to UTF8
- $request->message = CleantalkHelper::stringToUTF8($request->message, $this->data_codepage);
- $request->example = CleantalkHelper::stringToUTF8($request->example, $this->data_codepage);
- $request->sender_email = CleantalkHelper::stringToUTF8($request->sender_email, $this->data_codepage);
- $request->sender_nickname = CleantalkHelper::stringToUTF8(
- $request->sender_nickname,
- $this->data_codepage
- );
-
- // $request->message = $this->compressData($request->message);
- // $request->example = $this->compressData($request->example);
- break;
-
- case 'check_newuser':
- // Convert strings to UTF8
- $request->sender_email = CleantalkHelper::stringToUTF8($request->sender_email, $this->data_codepage);
- $request->sender_nickname = CleantalkHelper::stringToUTF8(
- $request->sender_nickname,
- $this->data_codepage
- );
- break;
-
- case 'send_feedback':
- if ( is_array($request->feedback) ) {
- $request->feedback = implode(';', $request->feedback);
- }
- break;
- }
-
- $request->method_name = $method;
-
- // Removing non UTF8 characters from request, because non UTF8 or malformed characters break json_encode().
- foreach ( $request as $param => $value ) {
- if ( is_array($request->$param) ) {
- $request->$param = CleantalkHelper::removeNonUTF8FromArray($value);
- }
- if ( is_string($request->$param) || is_int($request->$param) ) {
- $request->$param = CleantalkHelper::removeNonUTF8FromString($value);
- }
- }
-
- return $request;
- }
-
- /**
- * Send JSON request to servers
- *
- * @param $data
- * @param $url
- * @param int $server_timeout
- *
- * @return boolean|CleantalkResponse
- */
- private function sendRequest($data, $url, $server_timeout = 3)
- {
- // Convert to array
- $data = (array)json_decode(json_encode($data), true);
-
- //Cleaning from 'null' values
- $tmp_data = array();
- foreach ( $data as $key => $value ) {
- if ( $value !== null ) {
- $tmp_data[$key] = $value;
- }
- }
- $data = $tmp_data;
- unset($key, $value, $tmp_data);
-
- // Convert to JSON
- $data = json_encode($data);
-
- if ( isset($this->api_version) ) {
- $url = $url . $this->api_version;
- }
-
- // Switching to secure connection
- if ( $this->ssl_on && ! preg_match("/^https:/", $url) ) {
- $url = preg_replace("/^(http)/i", "$1s", $url);
- }
-
- $result = false;
- $curl_error = null;
- if ( function_exists('curl_init') ) {
- $ch = curl_init();
-
- curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_TIMEOUT, $server_timeout);
- curl_setopt($ch, CURLOPT_POST, 1);
- curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // receive server response ...
- curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:')); // resolve 'Expect: 100-continue' issue
-
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Disabling CA cert verivication and
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // Disabling common name verification
-
- if ( $this->ssl_on && $this->ssl_path != '' ) {
- curl_setopt($ch, CURLOPT_CAINFO, $this->ssl_path);
- }
-
- $result = curl_exec($ch);
- if ( ! $result ) {
- $curl_error = curl_error($ch);
- // Use SSL next time, if error occurs.
- if ( ! $this->ssl_on ) {
- $this->ssl_on = true;
- return $this->sendRequest($data, $url, $server_timeout);
- }
- }
-
- curl_close($ch);
- }
-
- if ( ! $result ) {
- $allow_url_fopen = ini_get('allow_url_fopen');
- if ( function_exists('file_get_contents') && !empty($allow_url_fopen) && $allow_url_fopen == '1' ) {
- $opts = array(
- 'http' =>
- array(
- 'method' => 'POST',
- 'header' => "Content-Type: text/html\r\n",
- 'content' => $data,
- 'timeout' => $server_timeout
- )
- );
-
- $context = stream_context_create($opts);
- $result = @file_get_contents($url, false, $context);
- }
- }
-
- if ( !is_string($result) || ! CleantalkHelper::is_json($result) ) {
- $response = null;
- $response['errno'] = 1;
- if ( $curl_error ) {
- $response['errstr'] = sprintf("CURL error: '%s'", $curl_error);
- } else {
- $response['errstr'] = 'No CURL support compiled in';
- }
- $response['errstr'] .= ' or disabled allow_url_fopen in php.ini.';
- $response = json_decode(json_encode($response));
-
- return $response;
- }
-
- $errstr = null;
- $response = json_decode($result);
- if ( is_object($response) ) {
- $response->errno = 0;
- $response->errstr = $errstr;
- } else {
- $errstr = 'Unknown response from ' . $url . '.' . ' ' . $result;
-
- $response = null;
- $response['errno'] = 1;
- $response['errstr'] = $errstr;
- $response = json_decode(json_encode($response));
- }
-
-
- return $response;
- }
-
- /**
- * httpRequest
- *
- * @param $msg
- *
- * @return CleantalkResponse
- * @throws TransportException
- */
- private function httpRequest($msg)
- {
- // Wiping session cookies from request
-
- $ct_tmp = apache_request_headers();
-
- if ( isset($ct_tmp['Cookie']) ) {
- $cookie_name = 'Cookie';
- } elseif ( isset($ct_tmp['cookie']) ) {
- $cookie_name = 'cookie';
- } else {
- $cookie_name = 'COOKIE';
- }
-
- if ( isset($ct_tmp[$cookie_name]) ) {
- unset($ct_tmp[$cookie_name]);
- }
-
- $msg->all_headers = ! empty($ct_tmp) ? json_encode($ct_tmp) : '';
-
- // Using current server without changing it
- if ( ! empty($this->work_url) && ($this->server_changed + $this->server_ttl > time()) ) {
- $url = ! empty($this->work_url) ? $this->work_url : $this->server_url;
- $result = $this->sendRequest($msg, $url, $this->server_timeout);
- } else {
- $result = false;
- }
-
- // Changing server
- if ($result === false || $result->errno != 0) {
- // Split server url to parts
- preg_match("@^(https?://)([^/:]+)(.*)@i", $this->server_url, $matches);
-
- $url_prefix = isset($matches[1]) ? $matches[1] : '';
- $url_host = isset($matches[2]) ? $matches[2] : '';
- $url_suffix = isset($matches[3]) ? $matches[3] : '';
-
- if ( empty($url_host) ) {
- throw TransportException::fromUrlHostError($url_host);
- } elseif ( null !== $servers = $this->get_servers_ip($url_host) ) {
- // Loop until find work server
- foreach ( $servers as $server ) {
- $this->work_url = $url_prefix . $server['ip'] . $url_suffix;
- $this->server_ttl = $server['ttl'];
-
- $result = $this->sendRequest($msg, $this->work_url, $this->server_timeout);
-
- if ( $result !== false && $result->errno === 0 ) {
- $this->server_change = true;
- break;
- }
- }
- } else {
- throw TransportException::fromUrlHostError($url_host);
- }
- }
-
- $response = new CleantalkResponse(null, $result);
-
- $response->sender_ip = $this->sender_ip;
- $response->sender_email = $this->sender_email;
-
- if ( ! empty($this->data_codepage) && $this->data_codepage !== 'UTF-8' ) {
- if ( ! empty($response->comment) ) {
- $response->comment = CleantalkHelper::stringFromUTF8($response->comment, $this->data_codepage);
- }
- if ( ! empty($response->errstr) ) {
- $response->errstr = CleantalkHelper::stringFromUTF8($response->errstr, $this->data_codepage);
- }
- if ( ! empty($response->sms_error_text) ) {
- $response->sms_error_text = CleantalkHelper::stringFromUTF8($response->sms_error_text, $this->data_codepage);
- }
- }
-
- return $response;
- }
-
- /**
- * Function DNS request
- *
- * @param $host
- *
- * @return array|null
- */
- private function get_servers_ip($host) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
- {
- if ( ! isset($host) ) {
- return null;
- }
-
- $servers = array();
-
- // Get DNS records about URL
- if ( function_exists('dns_get_record') ) {
- $records = dns_get_record($host, DNS_A);
- if ( $records !== false ) {
- foreach ( $records as $server ) {
- $servers[] = $server;
- }
- }
- }
-
- // Another try if first failed
- if ( count($servers) == 0 && function_exists('gethostbynamel') ) {
- $records = gethostbynamel($host);
- if ( $records !== false ) {
- foreach ( $records as $server ) {
- $servers[] = array(
- "ip" => $server,
- "host" => $host,
- "ttl" => $this->server_ttl
- );
- }
- }
- }
-
- // If couldn't get records
- if ( count($servers) == 0 ) {
- $servers[] = array(
- "ip" => null,
- "host" => $host,
- "ttl" => $this->server_ttl
- );
- // If records recieved
- } else {
- $tmp = array();
- $fast_server_found = false;
-
- foreach ( $servers as $server ) {
- if ( $fast_server_found ) {
- $ping = $this->max_server_timeout;
- } else {
- $ping = $this->httpPing($server['ip']);
- $ping = $ping * 1000;
- }
-
- $tmp[(int)$ping] = $server;
-
- $fast_server_found = $ping < $this->min_server_timeout ? true : false;
- }
-
- ksort($tmp);
- $response = $tmp;
- }
-
- return empty($response) ? null : $response;
- }
-
- /**
- * Function to check response time
- * param string
- * @return float
- */
- private function httpPing($host)
- {
- // Skip localhost ping cause it raise error at fsockopen.
- // And return minimun value
- if ( $host == 'localhost' ) {
- return 0.001;
- }
-
- $starttime = microtime(true);
- $file = @fsockopen($host, 443, $errno, $errstr, $this->max_server_timeout / 1000);
- $stoptime = microtime(true);
-
- if ( ! $file ) {
- $status = $this->max_server_timeout / 1000; // Site is down
- } else {
- fclose($file);
- $status = ($stoptime - $starttime);
- $status = round($status, 4);
- }
-
- return $status;
- }
-}
diff --git a/lib/CleantalkAPI.php b/lib/CleantalkAPI.php
deleted file mode 100644
index 70291da..0000000
--- a/lib/CleantalkAPI.php
+++ /dev/null
@@ -1,299 +0,0 @@
- 'get_api_key',
- 'product_name' => 'antispam',
- 'email' => $email,
- 'website' => $host,
- 'platform' => $platform,
- 'timezone' => $timezone,
- 'http_accept_language' => $language,
- 'user_ip' => $ip,
- 'hoster_whitelabel' => $white_label,
- 'hoster_api_key' => $hoster_api_key,
- );
-
- $result = self::send_request($request);
- $result = $do_check ? self::check_response($result, 'get_api_key') : $result;
-
- return $result;
- }
-
- /**
- * Function gets spam report
- *
- * @param string $host website host
- * @param integer $period report days
- * @param bool $do_check do_check
- *
- * @return string
- */
- public static function method__get_antispam_report($host, $period = 1, $do_check = true) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
- {
- $request = array(
- 'method_name' => 'get_antispam_report',
- 'hostname' => $host,
- 'period' => $period
- );
-
- $result = self::send_request($request);
- $result = $do_check ? self::check_response($result, 'get_antispam_report') : $result;
-
- return $result;
- }
-
- /**
- * Function gets spam statistics
- *
- * @param string $api_key
- * @param bool $do_check
- *
- * @return string
- */
- public static function method__get_antispam_report_breif($api_key, $do_check = true) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
- {
- $request = array(
- 'method_name' => 'get_antispam_report_breif',
- 'auth_key' => $api_key,
- );
-
- $result = self::send_request($request);
- $result = $do_check ? self::check_response($result, 'get_antispam_report_breif') : $result;
-
- return $result;
- }
-
- /**
- * Function gets information about renew notice
- *
- * @param string $api_key
- * @param string $path_to_cms
- * @param bool $do_check
- *
- * @return string
- */
- public static function method__notice_validate_key($api_key = '', $path_to_cms = '', $do_check = true) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
- {
- $request = array(
- 'method_name' => 'notice_validate_key',
- 'auth_key' => $api_key,
- 'path_to_cms' => $path_to_cms
- );
-
- $result = self::send_request($request);
- $result = $do_check ? self::check_response($result, 'notice_validate_key') : $result;
-
- return $result;
- }
-
- /**
- * Function gets information about renew notice
- *
- * @param string api_key
- *
- * @return string
- */
- public static function method__notice_paid_till($api_key, $do_check = true) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
- {
- $request = array(
- 'method_name' => 'notice_paid_till',
- 'auth_key' => $api_key
- );
-
- $result = self::send_request($request);
- $result = $do_check ? self::check_response($result, 'notice_paid_till') : $result;
-
- return $result;
- }
-
- /**
- * Function sends raw request to API server
- *
- * @param array $data to send
- * @param string $url of API server
- * @param int $timeout is data have to be JSON encoded or not
- * @param bool $ssl should use ssl
- * @psalm-suppress PossiblyUnusedParam
- * @return string JSON encoded string
- */
- public static function send_request($data, $url = self::URL, $timeout = 5, $ssl = false) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
- {
- // Possibility to switch API url
- $url = defined('CLEANTALK_API_URL') ? CLEANTALK_API_URL : $url;
-
- // Adding agent version to data
- if ( defined('CLEANTALK_AGENT') ) {
- $data['agent'] = CLEANTALK_AGENT;
- }
-
- // Make URL string
- $data_string = http_build_query($data);
- $data_string = str_replace("&", "&", $data_string);
-
- if ( function_exists('curl_init') ) {
- $ch = curl_init();
-
- // Set diff options
- curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
- curl_setopt($ch, CURLOPT_POST, true);
- curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
-
- // Switch on/off SSL
- if ( $ssl === true ) {
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
- } else {
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
- }
-
- // Make a request
- $result = curl_exec($ch);
- $errors = curl_error($ch);
- curl_close($ch);
-
- // Get cURL error if result failed
- if ( $result === false ) {
- // And retry with SSL enabled
- if ( $ssl === false ) {
- return self::send_request($data, $url, $timeout, true);
- }
- }
- } else {
- $errors = 'CURL_NOT_INSTALLED';
- }
-
- // Trying to use file_get_contents() to make a API call
- if ( ! empty($errors) && ini_get('allow_url_fopen') ) {
- $opts = array(
- 'http' => array(
- 'method' => "POST",
- 'timeout' => $timeout,
- 'content' => $data_string,
- )
- );
- $context = stream_context_create($opts);
- $result = file_get_contents($url, false, $context);
- } else {
- $errors .= '_AND_ALLOW_URL_FOPEN_IS_DISABLED';
- }
-
- if ( empty($result) && ! empty($errors) ) {
- $json_error = json_encode(array('error' => true, 'error_string' => $errors));
- return false !== $json_error ? $json_error : 'CURL_ERROR';
- }
-
- return $result;
- }
-
- /**
- * Function checks server response
- *
- * @param string $result
- * @param string|null $method_name
- *
- * @return string JSON encoded string
- */
- public static function check_response($result, $method_name = null) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
- {
- $out = array('error' => false);
-
- // Errors handling
-
- // Bad connection
- if ( empty($result) ) {
- $out = array(
- 'error' => true,
- 'error_string' => 'CONNECTION_ERROR'
- );
- }
-
- // JSON decode errors
- $result = json_decode($result, true);
- if ( empty($result) ) {
- $out = array(
- 'error' => true,
- 'error_string' => 'JSON_DECODE_ERROR'
- );
- }
-
- // cURL error
- if ( ! empty($result['error']) ) {
- $out = array(
- 'error' => true,
- 'error_string' => 'CONNECTION_ERROR: ' . $result['error_string'],
- );
- }
-
- // Server errors
- if ( $result && (isset($result['error_no']) || isset($result['error_message'])) ) {
- $out = array(
- 'error' => true,
- 'error_string' => "SERVER_ERROR NO: {$result['error_no']} MSG: {$result['error_message']}",
- 'error_no' => $result['error_no'],
- 'error_message' => $result['error_message']
- );
- }
-
- // Patches for different methods
- if ( !$out['error'] ) {
- // mehod_name = notice_validate_key
- if ( $method_name == 'notice_validate_key' && isset($result['valid']) ) {
- $out = $result;
- }
-
- // Other methods
- if ( isset($result['data']) && is_array($result['data']) ) {
- $out = $result['data'];
- }
- }
-
- // method_name = get_antispam_report_breif
- if ( $method_name == 'get_antispam_report_breif' ) {
- if ( !$out['error'] ) {
- $result = $result['data'];
- }
-
- for ( $tmp = array(), $i = 0; $i < 7; $i++ ) {
- $tmp[date('Y-m-d', time() - 86400 * 7 + 86400 * $i)] = 0;
- }
-
- $result['spam_stat'] = array_merge($tmp, isset($result['spam_stat']) ? $result['spam_stat'] : array());
- $result['top5_spam_ip'] = isset($result['top5_spam_ip']) ? $result['top5_spam_ip'] : array();
- $out = array_merge($result, $out);
- }
-
- $out = json_encode($out);
-
- return false !== $out ? $out : 'JSON_ENCODE_ERROR';
- }
-}
diff --git a/lib/CleantalkAntispam.php b/lib/CleantalkAntispam.php
index 5226ad2..88c2abe 100644
--- a/lib/CleantalkAntispam.php
+++ b/lib/CleantalkAntispam.php
@@ -1,73 +1,626 @@
apikey = $apikey;
- $this->email_field = $email_field;
- $this->user_name_field = $user_name_field;
- $this->message_field = $message_field;
- $this->type_form = $type_form;
- }
-
- /**
- * @return CleantalkResponse|null
- * @throws TransportException
+ const MODERATE_URL = 'https://moderate.cleantalk.org/api2.0';
+ const BOT_DETECTOR_LIBRARY_URL = 'https://moderate.cleantalk.org/ct-bot-detector-wrapper.js';
+ const EVENT_TOKEN_FIELD_NAME = 'ct_bot_detector_event_token';
+ const EMAIL_ADDRESS_REGEXP = '/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/';
+
+ /**
+ * @var string Access key for CleanTalk API
+ */
+ private $access_key;
+ /**
+ * @var string Event token for CleanTalk API
+ */
+ private $event_token;
+ /**
+ * @var bool
+ */
+ private $block_no_js_visitor = false;
+ /**
+ * @var string Nickname of the sender
+ */
+ private $nickname;
+ /**
+ * @var string Email of the sender
+ */
+ private $email;
+
+ /**
+ * @var string Message content
+ */
+ private $message;
+
+ /**
+ * @var string IP address of the sender
+ */
+ private $ip;
+
+ /**
+ * @var string Method name for the CleanTalk API request
+ */
+ private $method_name;
+
+ /**
+ * @var CleantalkVerdict Verdict object to store the result of the CleanTalk check
+ */
+ private $verdict;
+
+ /**
+ * @var array Suggestions for improving the data quality
+ */
+ private $improvement_suggestions = array();
+
+ /**
+ * @var array Stack of method calls for fluid interface
+ */
+ private $fluid_call_stack = array();
+
+ /**
+ * @var CleantalkResponse Response object from the CleanTalk API
+ */
+ private $cleantalk_response;
+
+ /**
+ * @var false|string CleanTalk request data in JSON format
+ */
+ private $cleantalk_request_data;
+
+ /**
+ * @var array Data container to get the data from the form, usually is $_POST
+ */
+ private $data_container;
+
+ /**
+ * ------------ Construction kit methods ------------
+ */
+
+ /**
+ * Constructor for the CleanTalkCheck class.
+ *
+ * @param string $accessKey Access key for CleanTalk API
+ * @psalm-suppress PossiblyUnusedParam
+ */
+ public function __construct($accessKey, $email = '', $user_name_field = '', $message_field = '', $type_form = '')
+ {
+ $this->access_key = $accessKey;
+ $this->verdict = new CleantalkVerdict();
+ //default data preparing
+ $this->data_container = $_POST;
+ if (isset($this->data_container[static::EVENT_TOKEN_FIELD_NAME])) {
+ $this->event_token = $this->data_container[static::EVENT_TOKEN_FIELD_NAME];
+ }
+ $this->ip = Helper::ipGet();
+ if ($email) {
+ $this->email = $email;
+ } else {
+ $this->setEmailAutomatically();
+ }
+ }
+
+ private function setEmailAutomatically()
+ {
+ foreach ($this->data_container as $_key => $value) {
+ if (preg_match(static::EMAIL_ADDRESS_REGEXP, $value)) {
+ $this->email = $value;
+ break;
+ }
+ }
+ }
+
+ /**
+ * ------------ Frontend methods ------------
+ */
+
+ /**
+ * Get the frontend HTML code for the CleanTalk bot detector.
+ *
+ * @param bool $warn_if_js_disabled Flag to include a warning if JavaScript is disabled
+ * @return string HTML code
+ */
+ public static function getFrontendHTMLCode($warn_if_js_disabled = false)
+ {
+ $warn = $warn_if_js_disabled ? '' : '';
+ $html = '%s';
+ return sprintf($html, static::BOT_DETECTOR_LIBRARY_URL, $warn);
+ }
+
+ /**
+ * ------------ Internal processing methods ------------
+ */
+
+ /**
+ * Get the response from the CleanTalk API.
+ *
+ * @return CleantalkResponse Response object from the CleanTalk API
+ */
+ private function getCleanTalkResponse()
+ {
+ $http = new Request();
+ $this->cleantalk_request_data = $this->prepareCleanTalkRequestData();
+ $response_raw = $http->setUrl(static::MODERATE_URL)
+ ->setData($this->cleantalk_request_data)
+ ->request();
+
+ /** @psalm-suppress InvalidArgument */
+ return new CleantalkResponse(@json_decode($response_raw), null);
+ }
+
+ /**
+ * Prepare the request data for the CleanTalk API.
+ *
+ * @return string JSON encoded request data
+ */
+ private function prepareCleanTalkRequestData()
+ {
+ $data = array(
+ 'method_name' => $this->method_name,
+ 'auth_key' => $this->access_key,
+ 'message' => $this->message,
+ 'sender_nickname' => $this->nickname,
+ 'sender_email' => $this->email,
+ 'sender_ip' => $this->ip,
+ 'js_on' => !empty($this->event_token) ? 1 : 0,
+ 'event_token' => $this->event_token,
+ 'agent' => 'php-cleantalk-check',
+ 'sender_info' => @json_encode(
+ array(
+ 'REFFERRER' => !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '',
+ )
+ ),
+ );
+ return @json_encode($data);
+ }
+
+ /**
+ * Get the CleanTalk request data.
+ *
+ * @return string JSON encoded request data
+ */
+ public function getCleanTalkRequestData()
+ {
+ if (empty($this->cleantalk_request_data)) {
+ return '';
+ }
+ $data = @json_decode($this->cleantalk_request_data);
+ return $data ?: '';
+ }
+
+ /**
+ * Verify the data before sending the request to CleanTalk API.
+ */
+ private function verifyData()
+ {
+ try {
+ $this->checkAccessKey();
+ } catch (\Exception $e) {
+ $this->verdict->error = $e->getMessage();
+ $this->verdict->allow = true;
+ }
+
+ try {
+ $this->checkEventToken();
+ } catch (\Exception $e) {
+ if ($this->block_no_js_visitor) {
+ $this->verdict->error = $e->getMessage();
+ $this->verdict->allow = false;
+ $this->verdict->comment = 'Please, enable JavaScript to process the form.';
+ } else {
+ $this->verdict->allow = true;
+ }
+ }
+ }
+
+ /**
+ * Check if the access key is valid.
+ *
+ * @throws \Exception If the access key is invalid
+ */
+ private function checkAccessKey()
+ {
+ if (empty($this->access_key)) {
+ throw new \Exception('Access key is empty');
+ }
+
+ if (!is_string($this->access_key)) {
+ throw new \Exception('Access key is not a string');
+ }
+ }
+
+ /**
+ * Check if the event token is valid.
+ *
+ * @throws \Exception If the event token is invalid
+ */
+ private function checkEventToken()
+ {
+ if (empty($this->event_token)) {
+ throw new \Exception('Event token is empty');
+ }
+
+ if (!is_string($this->event_token)) {
+ throw new \Exception('Event token is not a string');
+ }
+
+ if (strlen($this->event_token) !== 64) {
+ throw new \Exception('Event token is not valid');
+ }
+ }
+
+ /**
+ * Perform actions before returning the verdict.
+ *
+ * @return CleantalkVerdict Verdict object with the result of the CleanTalk check
+ */
+ private function beforeReturnVerdict()
+ {
+ $this->setImprovementSuggestions();
+ return $this->verdict;
+ }
+
+ /**
+ * ------------ Fluid public calls ------------
+ */
+
+ /**
+ * Set the email of the sender.
+ *
+ * @param string $email Email of the sender
+ * @return $this
+ */
+ public function setEmail($email)
+ {
+ $this->fluidCallStack(__FUNCTION__);
+ $this->email = is_string($email) ? $email : null;
+ return $this;
+ }
+
+ /**
+ * Set the nickname of the sender.
+ *
+ * @param string $nickname Nickname of the sender
+ * @return $this
+ */
+ public function setNickName($nickname)
+ {
+ $this->fluidCallStack(__FUNCTION__);
+ $this->nickname = is_string($nickname) ? $nickname : null;
+ return $this;
+ }
+
+ /**
+ * Set the message content.
+ *
+ * @param string $message Message content
+ * @return $this
+ */
+ public function setMessage($message)
+ {
+ $this->fluidCallStack(__FUNCTION__);
+ $this->message = is_string($message) ? $message : null;
+ return $this;
+ }
+
+ /**
+ * Set the IP address of the sender.
+ *
+ * @param string|null $ip IP address of the sender
+ * @return $this
+ */
+ public function setIP($ip = null)
+ {
+ $this->fluidCallStack(__FUNCTION__);
+ if (!Helper::ipValidate($ip)) {
+ $this->setImprovementSuggestion('critical', 'IP address is not valid, the value has been set form the request', 'setIP()');
+ } else {
+ $this->ip = $ip;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Enable blocking of visitors without JavaScript.
+ *
+ * @return $this
+ */
+ public function setDoBlockNoJSVisitor()
+ {
+ $this->fluidCallStack(__FUNCTION__);
+ $this->block_no_js_visitor = true;
+ return $this;
+ }
+
+ /**
+ * Set the event token.
+ *
+ * @param string|null $event_token Event token
+ * @return $this
+ */
+ public function setEventToken($event_token = null)
+ {
+ $this->fluidCallStack(__FUNCTION__);
+ $this->event_token = $event_token;
+ return $this;
+ }
+
+ /**
+ * Use the registration check method.
+ *
+ * @return $this
+ */
+ public function useRegistrationCheck()
+ {
+ $this->fluidCallStack(__FUNCTION__);
+ $this->method_name = 'check_newuser';
+ return $this;
+ }
+
+ /**
+ * Use the contact form check method.
+ *
+ * @return $this
+ */
+ public function useContactFormCheck()
+ {
+ $this->fluidCallStack(__FUNCTION__);
+ $this->method_name = 'check_message';
+ return $this;
+ }
+
+ /**
+ * Set own data container.
+ * @param $data_container
+ *
+ * @return $this
+ */
+ public function setCustomFormDataContainer($data_container)
+ {
+ $this->data_container = $data_container;
+ return $this;
+ }
+
+ /**
+ * Get the verdict from the CleanTalk API.
+ *
+ * @return CleantalkVerdict Verdict object with the result of the CleanTalk check
*/
public function handle()
{
- if ( count($_POST) === 0 ) {
- $_SESSION['ct_submit_time'] = time();
+ $this->verifyData();
- return null;
+ if ($this->verdict->error) {
+ return $this->beforeReturnVerdict();
}
- $sender_email = isset($_POST[$this->email_field]) ? $_POST[$this->email_field] : '';
- $sender_nickname = isset($_POST[$this->user_name_field]) ? $_POST[$this->user_name_field] : '';
- $message = isset($_POST[$this->message_field]) ? $_POST[$this->message_field] : '';
- $sender_ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null;
+ if (empty($this->method_name)) {
+ $this->method_name = empty($this->message) ? 'check_newuser' : 'check_message';
+ }
- $ct_request = new CleantalkRequest();
+ $this->cleantalk_response = $this->getCleanTalkResponse();
- $ct_request->auth_key = $this->apikey;
- $ct_request->agent = 'php-api';
- $ct_request->sender_email = $sender_email;
- $ct_request->sender_ip = $sender_ip;
- $ct_request->sender_nickname = $sender_nickname;
- $ct_request->message = $message;
- $ct_request->submit_time = isset($_SESSION['ct_submit_time']) ? $_SESSION['ct_submit_time'] : null;
- $ct_request->event_token = isset($_POST['ct_bot_detector_event_token']) ? $_POST['ct_bot_detector_event_token'] : null;
+ if ($this->cleantalk_response->error) {
+ /** @psalm-suppress InvalidOperand */
+ $this->verdict->error = 'CleanTalk moderate server error: ' . $this->cleantalk_response->error;
+ return $this->beforeReturnVerdict();
+ }
+
+ $this->verdict->allow = $this->cleantalk_response->allow;
+ $this->verdict->comment = $this->cleantalk_response->comment;
+ $this->verdict->request_link = !empty($this->cleantalk_response->id)
+ ? 'https://cleantalk.org/my/show_requests?request_id=' . $this->cleantalk_response->id
+ : null
+ ;
+
+ return $this->beforeReturnVerdict();
+ }
- $ct = new Cleantalk();
- $ct->server_url = $ct_request::CLEANTALK_API_URL;
+ /**
+ * ------------ Improvement suggestions feature ------------
+ */
- // Check
- if ( $this->type_form === 'signup' ) {
- $ct_result = $ct->isAllowUser($ct_request);
+ /**
+ * Set suggestions for improving the data quality.
+ */
+ private function setImprovementSuggestions()
+ {
+ if ( $this->cleantalk_response instanceof CleantalkResponse ) {
+ if (empty($this->cleantalk_response->comment)) {
+ $this->setImprovementSuggestion(
+ 'critical',
+ 'Something is wrong with connection to the CleanTalk server ' . static::MODERATE_URL,
+ 'getCleanTalkResponse()'
+ );
+ return;
+ }
+ if ($this->cleantalk_response->error) {
+ $this->setImprovementSuggestion(
+ 'critical',
+ 'Please, check the error message from the CleanTalk server',
+ 'getCleanTalkResponse()'
+ );
+ return;
+ }
+ if ($this->cleantalk_response->account_status !== 1) {
+ $this->setImprovementSuggestion(
+ 'critical',
+ 'Something wrong with your CleanTalk license, visit your CleanTalk dashboard to check the license status',
+ 'getCleanTalkResponse()'
+ );
+ return;
+ }
}
- if ( $this->type_form === 'contact' ) {
- $ct_result = $ct->isAllowMessage($ct_request);
+
+ if (!empty($this->verdict->error)) {
+ $this->setImprovementSuggestion('critical', 'Error occurred due the CleanTalk check: ' . $this->verdict->error);
}
- return $ct_result;
+ if (empty($this->ip)) {
+ $fluid_method = 'setIP';
+ $stack = !$this->fluidCallExist($fluid_method)
+ ? "interface method ->$fluid_method() has not been called"
+ : "interface method ->$fluid_method() has been called, but provided var is invalid or automatic IP get has failed";
+ $this->setImprovementSuggestion(
+ 'average',
+ 'Please, provide the visitor IP address to improve check quality.',
+ $stack
+ );
+ }
+
+ if (empty($this->event_token)) {
+ $fluid_method = 'setEventToken';
+ $stack = !$this->fluidCallExist($fluid_method)
+ ? "interface method ->$fluid_method() has not been called, make sure the form data contains the field " . static::EVENT_TOKEN_FIELD_NAME
+ : "interface method ->$fluid_method() has been called, but provided var is invalid";
+ $common_token_message = 'Event token is not provided. Most likely the visitor has JavaScript disabled.';
+ $this->setImprovementSuggestion('critical', $common_token_message, $stack);
+
+ $fluid_method = 'setDoBlockNoJSVisitor';
+ if ($this->fluidCallExist($fluid_method)) {
+ $stack = "seen the call ->$fluid_method()";
+ $common_token_message .= ' All the visitors without token are BLOCKED due the current setting to block users without JS.';
+ } else {
+ $stack = "interface method ->$fluid_method() has not been called";
+ $common_token_message .= ' All the visitors without token are PASSED due the current setting to pass users without JS.';
+ }
+ $this->setImprovementSuggestion('critical', $common_token_message, $stack);
+ }
+
+ if (empty($this->access_key)) {
+ $this->setImprovementSuggestion(
+ 'critical',
+ 'Please, provide the access key via constructor call ' . __CLASS__ . '()',
+ 'construct()'
+ );
+ }
+
+ if (empty($this->email)) {
+ $fluid_method = 'setEmail';
+ $stack = !$this->fluidCallExist($fluid_method)
+ ? "interface method ->$fluid_method() has not been called"
+ : "interface method ->$fluid_method() has been called, but provided var is invalid";
+ $this->setImprovementSuggestion(
+ 'average',
+ 'Please, provide the email field content to improve check quality.',
+ $stack
+ );
+ }
+
+ if (empty($this->nickname)) {
+ $fluid_method = 'setNickName';
+ $stack = !$this->fluidCallExist($fluid_method)
+ ? "interface method ->$fluid_method() has not been called"
+ : "interface method ->$fluid_method() has been called, but provided var is invalid";
+ $this->setImprovementSuggestion(
+ 'average',
+ 'Please, provide the nickname field content to improve check quality.',
+ $stack
+ );
+ }
+
+ if (empty($this->message)) {
+ if ($this->fluidCallExist('useContactFormCheck')) {
+ if ($this->fluidCallExist('setMessage')) {
+ $stack = 'seen the call ->setMessage(), but provided value is invalid';
+ } else {
+ $stack = 'seen the call ->useContactFormCheck(), but interface method ->setMessage() has not been called';
+ }
+ $this->setImprovementSuggestion(
+ 'average',
+ 'Please, provide the message field to improve check quality.',
+ $stack
+ );
+ }
+ }
}
- public function frontendScript()
+ /**
+ * Set an improvement suggestion.
+ *
+ * @param string $level Severity level of the suggestion
+ * @param string $message Suggestion message
+ * @param string|null $stack Call stack information
+ */
+ private function setImprovementSuggestion($level, $message, $stack = null)
{
- echo '';
+ $this->improvement_suggestions[$level][] = array('stack' => $stack, 'message' => $message);
+ }
+
+ /**
+ * Get the improvement suggestions.
+ *
+ * @return array Improvement suggestions
+ */
+ private function getImprovementSuggestions()
+ {
+ if (empty($this->improvement_suggestions)) {
+ return array('Everything looks well!');
+ }
+ ksort($this->improvement_suggestions, SORT_STRING);
+ return $this->improvement_suggestions;
+ }
+
+ /**
+ * Add a method to the fluid call stack.
+ *
+ * @param string $method Method name
+ */
+ private function fluidCallStack($method)
+ {
+ $this->fluid_call_stack[] = $method;
+ }
+
+ /**
+ * Check if a method exists in the fluid call stack.
+ *
+ * @param string $method Method name
+ * @return bool True if the method exists in the stack, false otherwise
+ */
+ private function fluidCallExist($method)
+ {
+ return in_array($method, $this->fluid_call_stack);
+ }
+
+ /**
+ * Get the suggestions for improving the data quality.
+ * @param $return_as_json
+ *
+ * @return false|string
+ */
+ public function whatsWrong($return_as_json = false)
+ {
+ $array = array(
+ 'suggestions' => $this->getImprovementSuggestions(),
+ 'request_data' => $this->getCleanTalkRequestData(),
+ 'verdict' => $this->verdict instanceof CleantalkVerdict ? $this->verdict->getArray() : null,
+ );
+
+ if (empty($array['verdict'])) {
+ $array['verdict'] = 'Verdict is not processed. Maybe you forgot to call ->getVerdict() method before';
+ }
+
+ if ($return_as_json) {
+ return @json_encode($array);
+ }
+
+ /** @psalm-suppress InvalidScalarArgument */
+ $suggestions = var_export($array['suggestions'], 1);
+ /** @psalm-suppress InvalidScalarArgument */
+ $data = var_export($array['request_data'], 1);
+ /** @psalm-suppress InvalidScalarArgument */
+ $verdict = var_export($array['verdict'], 1);
+ echo "