ver 1.4.0
This commit is contained in:
182
includes/class-Checker.php
Normal file
182
includes/class-Checker.php
Normal file
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
class UPDATE_CHECKER extends SHEET_DATA_CHECKER_PRO{
|
||||
|
||||
public $plugin_slug;
|
||||
public $version;
|
||||
public $cache_key;
|
||||
public $cache_allowed;
|
||||
|
||||
/**
|
||||
* Returns an instance of this class.
|
||||
*/
|
||||
public static function get_instance() {
|
||||
|
||||
return self::$instance;
|
||||
|
||||
}
|
||||
|
||||
public function __construct() {
|
||||
|
||||
$this->plugin_slug = SHEET_CHECKER_PRO_DOMAIN;
|
||||
$this->version = SHEET_CHECKER_PRO_VERSION;
|
||||
$this->cache_key = SHEET_CHECKER_PRO_DOMAIN.'_update_checker';
|
||||
$this->cache_allowed = false;
|
||||
|
||||
add_filter( 'plugins_api', array( $this, 'info' ), 20, 3 );
|
||||
add_filter( 'site_transient_update_plugins', array( $this, 'update' ) );
|
||||
add_action( 'upgrader_process_complete', array( $this, 'purge' ), 10, 2 );
|
||||
|
||||
// add_action( 'wp_head' , [$this, 'header']);
|
||||
|
||||
}
|
||||
|
||||
public function header() {
|
||||
$remote = wp_remote_get(
|
||||
'https://member.dwindi.com/wp-content/uploads/updater/info.json?product='.SHEET_CHECKER_PRO_DOMAIN,
|
||||
array(
|
||||
'timeout' => 10,
|
||||
'headers' => array(
|
||||
'Accept' => 'application/json'
|
||||
)
|
||||
)
|
||||
);
|
||||
// $remote = json_decode( wp_remote_retrieve_body( $remote ) );
|
||||
echo '<pre>';
|
||||
print_r($remote);
|
||||
echo '</pre>';
|
||||
}
|
||||
|
||||
public function request(){
|
||||
|
||||
$remote = get_transient( $this->cache_key );
|
||||
|
||||
if( false === $remote || ! $this->cache_allowed ) {
|
||||
|
||||
$remote = wp_remote_get(
|
||||
'https://member.dwindi.com/wp-content/uploads/updater/info.json',
|
||||
array(
|
||||
'timeout' => 10,
|
||||
'headers' => array(
|
||||
'Accept' => 'application/json'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if(
|
||||
is_wp_error( $remote )
|
||||
|| 200 !== wp_remote_retrieve_response_code( $remote )
|
||||
|| empty( wp_remote_retrieve_body( $remote ) )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
set_transient( $this->cache_key, $remote, DAY_IN_SECONDS );
|
||||
|
||||
}
|
||||
|
||||
$remote = json_decode( wp_remote_retrieve_body( $remote ) );
|
||||
|
||||
return $remote;
|
||||
|
||||
}
|
||||
|
||||
|
||||
function info( $res, $action, $args ) {
|
||||
|
||||
// print_r( $action );
|
||||
// print_r( $args );
|
||||
|
||||
// do nothing if you're not getting plugin information right now
|
||||
if( 'plugin_information' !== $action ) {
|
||||
return $res;
|
||||
}
|
||||
|
||||
// do nothing if it is not our plugin
|
||||
if( $this->plugin_slug !== $args->slug ) {
|
||||
return $res;
|
||||
}
|
||||
|
||||
// get updates
|
||||
$remote = $this->request();
|
||||
|
||||
if( ! $remote ) {
|
||||
return $res;
|
||||
}
|
||||
|
||||
$res = new stdClass();
|
||||
|
||||
$res->name = $remote->name;
|
||||
$res->slug = $remote->slug;
|
||||
$res->version = $remote->version;
|
||||
$res->tested = $remote->tested;
|
||||
$res->requires = $remote->requires;
|
||||
$res->author = $remote->author;
|
||||
$res->download_link = $remote->download_url;
|
||||
$res->trunk = $remote->download_url;
|
||||
$res->requires_php = $remote->requires_php;
|
||||
$res->last_updated = $remote->last_updated;
|
||||
|
||||
$res->sections = array(
|
||||
'description' => $remote->sections->description,
|
||||
'installation' => $remote->sections->installation,
|
||||
'changelog' => $remote->sections->changelog
|
||||
);
|
||||
|
||||
if( ! empty( $remote->banners ) ) {
|
||||
$res->banners = array(
|
||||
'low' => $remote->banners->low,
|
||||
'high' => $remote->banners->high
|
||||
);
|
||||
}
|
||||
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
public function update( $transient ) {
|
||||
|
||||
if ( empty($transient->checked ) ) {
|
||||
return $transient;
|
||||
}
|
||||
|
||||
$remote = $this->request();
|
||||
|
||||
if(
|
||||
$remote
|
||||
&& version_compare( $this->version, $remote->version, '<' )
|
||||
&& version_compare( $remote->requires, get_bloginfo( 'version' ), '<=' )
|
||||
&& version_compare( $remote->requires_php, PHP_VERSION, '<' )
|
||||
) {
|
||||
$res = new stdClass();
|
||||
$res->slug = $this->plugin_slug;
|
||||
$res->plugin = SHEET_CHECKER_PRO_DOMAIN.'/'.SHEET_CHECKER_PRO_DOMAIN.'.php'; // misha-update-plugin/misha-update-plugin.php
|
||||
$res->new_version = $remote->version;
|
||||
$res->tested = $remote->tested;
|
||||
$res->package = $remote->download_url;
|
||||
|
||||
$transient->response[ $res->plugin ] = $res;
|
||||
|
||||
}
|
||||
|
||||
return $transient;
|
||||
|
||||
}
|
||||
|
||||
public function purge( $upgrader, $options ){
|
||||
|
||||
if (
|
||||
$this->cache_allowed
|
||||
&& 'update' === $options['action']
|
||||
&& 'plugin' === $options[ 'type' ]
|
||||
) {
|
||||
// just clean the cache when new plugin version is installed
|
||||
delete_transient( $this->cache_key );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
296
includes/class-License.php
Normal file
296
includes/class-License.php
Normal file
@@ -0,0 +1,296 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) exit;
|
||||
|
||||
class CHECKER_LICENSE extends SHEET_DATA_CHECKER_PRO {
|
||||
|
||||
/**
|
||||
* A reference to a contact's name of this class.
|
||||
*/
|
||||
private $license = true;
|
||||
|
||||
/**
|
||||
* Returns an instance of this class.
|
||||
*/
|
||||
public static function get_instance() {
|
||||
|
||||
return self::$instance;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the plugin by setting filters and administration functions.
|
||||
*/
|
||||
|
||||
public function __construct() {
|
||||
|
||||
add_action('plugins_loaded', [$this, 'check_license'], 1);
|
||||
add_action('admin_init', [$this, 'register_routine'], 1);
|
||||
add_action('sheetcheckerpro/license/check', [$this, 'check_license_routine'], 1);
|
||||
add_action('admin_notices', [$this, 'display_license_message'], 1);
|
||||
add_action('admin_menu', [$this, 'admin_menu_license']);
|
||||
add_action('admin_init', [$this, 'check_form'], 1 );
|
||||
|
||||
// if(false !== $this->the_lis()){
|
||||
// require 'class-Checker.php';
|
||||
// new UPDATE_CHECKER();
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
public function set_license(bool $data){
|
||||
$this->license = $data;
|
||||
}
|
||||
|
||||
public function get_status(){
|
||||
return $this->license;
|
||||
}
|
||||
|
||||
public function the_lis() {
|
||||
|
||||
return true;
|
||||
|
||||
global $sheet_checker_pro;
|
||||
|
||||
$check = get_option('_sheetcheckerpro_license_check');
|
||||
|
||||
if(false !== $check && is_array($check)){
|
||||
return boolval($check['valid']);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function check_license() {
|
||||
|
||||
global $sheet_checker_pro;
|
||||
|
||||
$check = get_option('_sheetcheckerpro_license_check');
|
||||
|
||||
if(false === $check) :
|
||||
$this->set_license(false);
|
||||
$license_valid = false;
|
||||
$license_detail = [
|
||||
'valid' => false,
|
||||
'messages' => [
|
||||
__('Activate License for getting started with <b>Onesender Broadcaster</b>!', SHEET_CHECKER_PRO_DOMAIN)
|
||||
]
|
||||
];
|
||||
else :
|
||||
$check = wp_parse_args($check, [
|
||||
'valid' => true,
|
||||
'detail' => [],
|
||||
'messages' => []
|
||||
]);
|
||||
|
||||
$license_valid = $check['valid'];
|
||||
$license_detail = $check;
|
||||
$this->set_license(true);
|
||||
endif;
|
||||
|
||||
$sheet_checker_pro['license'] = [
|
||||
'valid' => $license_valid,
|
||||
'detail' => $license_detail
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
public function check_license_routine() {
|
||||
$post_data = [
|
||||
'host' => $_SERVER['HTTP_HOST']
|
||||
];
|
||||
|
||||
$request_url = add_query_arg($post_data, SHEET_CHECKER_PRO_MEMBER.'/sejoli-validate-license/');
|
||||
$response = wp_remote_get($request_url);
|
||||
$json_result = json_decode(wp_remote_retrieve_body($response), true);
|
||||
$response_code = (int) wp_remote_retrieve_response_code($response);
|
||||
|
||||
if(200 === $response_code && isset($json_result['valid'])) :
|
||||
|
||||
if(true === boolval($json_result['valid'])) :
|
||||
|
||||
else:
|
||||
|
||||
delete_option('_sheetcheckerpro_license_check');
|
||||
|
||||
endif;
|
||||
|
||||
else :
|
||||
|
||||
array(
|
||||
'code' => $response_code,
|
||||
'message' => $response['response']['message']
|
||||
);
|
||||
|
||||
endif;
|
||||
|
||||
}
|
||||
|
||||
public function register_routine() {
|
||||
|
||||
if(false === wp_next_scheduled('sheetcheckerpro/license/check')) :
|
||||
wp_schedule_event(time(),'twicedaily','sheetcheckerpro/license/check');
|
||||
endif;
|
||||
|
||||
}
|
||||
|
||||
public function display_license_message() {
|
||||
|
||||
if(false === $this->the_lis()) :
|
||||
|
||||
global $sheet_checker_pro;
|
||||
|
||||
$license_form_link = add_query_arg([
|
||||
'post_type' => 'checker',
|
||||
'page' => 'sheetcheckerpro-license'
|
||||
], admin_url('edit.php'));
|
||||
return;
|
||||
?>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
||||
<div class="wrap">
|
||||
<div class="alert alert-dark d-flex align-items-center gap-2 alert-dismissible fade show" role="alert">
|
||||
<i class="fa-regular fa-circle-check"></i>
|
||||
<div>
|
||||
<p class="mb-0"><?php echo implode('<br />', $sheet_checker_pro['license']['detail']['messages']); ?></p>
|
||||
<p class="mb-0">
|
||||
<a href='<?php echo $license_form_link; ?>' class='button button-primary'>
|
||||
<?php _e('Activate Here', SHEET_CHECKER_PRO_DOMAIN); ?>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
endif;
|
||||
|
||||
if(isset($_GET['error']) && 'sheetcheckerpro-license-not-valid' === $_GET['error']) :
|
||||
?>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
||||
<div class="wrap">
|
||||
<div class="alert alert-danger d-flex align-items-center gap-2" role="alert">
|
||||
<i class="fa-regular fa-circle-exclamation"></i>
|
||||
<div>
|
||||
<p class="mb-0">Ups! Your license is not detected, have been used or expired. Please input another license code or get a new one. <a class="sheetcheckerpro-checkout-btn btn btn-primary" href="https://member.dwindi.com/product/onesender-broadcaster/">Get a license code</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
|
||||
if(isset($_GET['success']) && 'sheetcheckerpro-license-valid' === $_GET['success']) :
|
||||
?>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
||||
<div class="wrap">
|
||||
<div class="alert alert-success d-flex align-items-center gap-2 alert-dismissible fade show" role="alert">
|
||||
<i class="fa-regular fa-circle-check"></i>
|
||||
<div>
|
||||
<p class="mb-0"><?php _e('Thank you! <b>Data Sheet Checker Pro</b> can be used now.'); ?></p>
|
||||
</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function admin_menu_license() {
|
||||
$is_admin = current_user_can('manage_options');
|
||||
if ( $is_admin ) {
|
||||
if(false === $this->the_lis()) :
|
||||
add_submenu_page(
|
||||
'edit.php?post_type=checker',
|
||||
'License',
|
||||
'License',
|
||||
'manage_options',
|
||||
'sheetcheckerpro-license',
|
||||
[$this, 'display_license_page'],
|
||||
12
|
||||
);
|
||||
endif;
|
||||
}
|
||||
}
|
||||
|
||||
public function display_license_page() {
|
||||
require SHEET_CHECKER_PRO_PATH . 'templates/license.php';
|
||||
}
|
||||
|
||||
public function check_form() {
|
||||
|
||||
if(isset($_POST['_wpnonce']) && wp_verify_nonce($_POST['_wpnonce'], 'sheetcheckerpro-input-license') && isset($_POST['data'])) :
|
||||
|
||||
$post_data = wp_parse_args($_POST['data'],[
|
||||
'user_email' => NULL,
|
||||
'user_pass' => NULL,
|
||||
'license' => NULL
|
||||
]);
|
||||
|
||||
$post_data['string'] = $_SERVER['HTTP_HOST'];
|
||||
$request_url = SHEET_CHECKER_PRO_MEMBER.'/sejoli-license/';
|
||||
$response = wp_remote_post($request_url, array(
|
||||
'timeout' => 120,
|
||||
'body' => $post_data
|
||||
));
|
||||
|
||||
if(is_wp_error($response)) :
|
||||
|
||||
wp_die(
|
||||
__( 'Something is happened because of your hosting. <br />Please contact your hosting provider and attach this message below:', SHEET_CHECKER_PRO_DOMAIN) . '<br /> <br />' .
|
||||
implode('<br />', $response->get_error_messages()),
|
||||
__( 'Cannot access license server', SHEET_CHECKER_PRO_DOMAIN)
|
||||
);
|
||||
|
||||
exit;
|
||||
else :
|
||||
$json_result = json_decode(wp_remote_retrieve_body($response), true);
|
||||
$response_code = intval(wp_remote_retrieve_response_code($response));
|
||||
|
||||
if(200 === $response_code) :
|
||||
|
||||
if(isset($json_result['valid']) && true === boolval($json_result['valid'])) :
|
||||
|
||||
update_option('_sheetcheckerpro_license_check', $json_result);
|
||||
|
||||
$theme_option_url = add_query_arg([
|
||||
'post_type' => 'checker',
|
||||
'success' => 'sheetcheckerpro-license-valid'
|
||||
], admin_url('edit.php'));
|
||||
|
||||
wp_redirect($theme_option_url);
|
||||
|
||||
|
||||
else :
|
||||
|
||||
$args = array();
|
||||
$args['post_type'] = 'checker';
|
||||
$args['error'] = 'sheetcheckerpro-license-not-valid';
|
||||
$args['messages'] = array_map('urlencode', array_map('strip_tags', $json_result['messages']));
|
||||
|
||||
wp_redirect(add_query_arg($args, admin_url('edit.php')));
|
||||
|
||||
endif;
|
||||
|
||||
// beside response code
|
||||
else :
|
||||
$args = array();
|
||||
$args['post_type'] = 'checker';
|
||||
$args['page'] = 'sheetcheckerpro-license';
|
||||
$args['error'] = 'sheetcheckerpro-license-not-valid';
|
||||
$args['messages'][] = sprintf( __('Error response code : %s. Cannot connect to license server', SHEET_CHECKER_PRO_DOMAIN), $response_code );
|
||||
|
||||
wp_redirect(add_query_arg($args, admin_url('admin.php')));
|
||||
|
||||
endif;
|
||||
|
||||
endif;
|
||||
|
||||
exit;
|
||||
|
||||
endif;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
217
includes/class-Security.php
Normal file
217
includes/class-Security.php
Normal file
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
|
||||
class CHECKER_SECURITY {
|
||||
|
||||
/**
|
||||
* Check rate limit for an IP address
|
||||
*
|
||||
* @param int $checker_id Checker post ID
|
||||
* @param string $ip IP address to check
|
||||
* @return array ['allowed' => bool, 'message' => string, 'remaining' => int]
|
||||
*/
|
||||
public static function check_rate_limit($checker_id, $ip) {
|
||||
$checker = get_post_meta($checker_id, 'checker', true);
|
||||
|
||||
// Check if rate limiting is enabled
|
||||
if (!isset($checker['security']['rate_limit']['enabled']) || $checker['security']['rate_limit']['enabled'] !== 'yes') {
|
||||
return ['allowed' => true, 'remaining' => 999];
|
||||
}
|
||||
|
||||
// Get settings
|
||||
$max_attempts = isset($checker['security']['rate_limit']['max_attempts']) ? (int)$checker['security']['rate_limit']['max_attempts'] : 5;
|
||||
$time_window = isset($checker['security']['rate_limit']['time_window']) ? (int)$checker['security']['rate_limit']['time_window'] : 15;
|
||||
$block_duration = isset($checker['security']['rate_limit']['block_duration']) ? (int)$checker['security']['rate_limit']['block_duration'] : 60;
|
||||
$error_message = isset($checker['security']['rate_limit']['error_message']) ? $checker['security']['rate_limit']['error_message'] : 'Too many attempts. Please try again later.';
|
||||
|
||||
// Create transient keys
|
||||
$transient_key = 'checker_rate_' . $checker_id . '_' . md5($ip);
|
||||
$block_key = 'checker_block_' . $checker_id . '_' . md5($ip);
|
||||
|
||||
// Check if IP is blocked
|
||||
$blocked_until = get_transient($block_key);
|
||||
if ($blocked_until !== false) {
|
||||
$remaining_time = ceil(($blocked_until - time()) / 60);
|
||||
return [
|
||||
'allowed' => false,
|
||||
'message' => $error_message . ' (' . $remaining_time . ' minutes remaining)',
|
||||
'remaining' => 0
|
||||
];
|
||||
}
|
||||
|
||||
// Get current attempts
|
||||
$attempts = get_transient($transient_key);
|
||||
if ($attempts === false) {
|
||||
$attempts = 0;
|
||||
}
|
||||
|
||||
// Increment attempts
|
||||
$attempts++;
|
||||
|
||||
// Check if exceeded limit
|
||||
if ($attempts > $max_attempts) {
|
||||
// Block the IP
|
||||
set_transient($block_key, time() + ($block_duration * 60), $block_duration * 60);
|
||||
// Reset attempts counter
|
||||
delete_transient($transient_key);
|
||||
|
||||
return [
|
||||
'allowed' => false,
|
||||
'message' => $error_message,
|
||||
'remaining' => 0
|
||||
];
|
||||
}
|
||||
|
||||
// Update attempts counter
|
||||
set_transient($transient_key, $attempts, $time_window * 60);
|
||||
|
||||
return [
|
||||
'allowed' => true,
|
||||
'remaining' => $max_attempts - $attempts
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify reCAPTCHA v3 token
|
||||
*
|
||||
* @param int $checker_id Checker post ID
|
||||
* @param string $token reCAPTCHA token from frontend
|
||||
* @return array ['success' => bool, 'score' => float, 'message' => string]
|
||||
*/
|
||||
public static function verify_recaptcha($checker_id, $token) {
|
||||
$checker = get_post_meta($checker_id, 'checker', true);
|
||||
|
||||
// Check if reCAPTCHA is enabled
|
||||
if (!isset($checker['security']['recaptcha']['enabled']) || $checker['security']['recaptcha']['enabled'] !== 'yes') {
|
||||
return ['success' => true, 'score' => 1.0];
|
||||
}
|
||||
|
||||
// Get settings
|
||||
$secret_key = isset($checker['security']['recaptcha']['secret_key']) ? $checker['security']['recaptcha']['secret_key'] : '';
|
||||
$min_score = isset($checker['security']['recaptcha']['min_score']) ? (float)$checker['security']['recaptcha']['min_score'] : 0.5;
|
||||
|
||||
if (empty($secret_key) || empty($token)) {
|
||||
return [
|
||||
'success' => false,
|
||||
'score' => 0,
|
||||
'message' => 'reCAPTCHA verification failed: Missing credentials'
|
||||
];
|
||||
}
|
||||
|
||||
// Verify with Google
|
||||
$response = wp_remote_post('https://www.google.com/recaptcha/api/siteverify', [
|
||||
'body' => [
|
||||
'secret' => $secret_key,
|
||||
'response' => $token
|
||||
]
|
||||
]);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return [
|
||||
'success' => false,
|
||||
'score' => 0,
|
||||
'message' => 'reCAPTCHA verification failed: ' . $response->get_error_message()
|
||||
];
|
||||
}
|
||||
|
||||
$body = json_decode(wp_remote_retrieve_body($response), true);
|
||||
|
||||
if (!isset($body['success']) || !$body['success']) {
|
||||
return [
|
||||
'success' => false,
|
||||
'score' => 0,
|
||||
'message' => 'reCAPTCHA verification failed'
|
||||
];
|
||||
}
|
||||
|
||||
$score = isset($body['score']) ? (float)$body['score'] : 0;
|
||||
|
||||
if ($score < $min_score) {
|
||||
return [
|
||||
'success' => false,
|
||||
'score' => $score,
|
||||
'message' => 'reCAPTCHA score too low. Please try again.'
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'score' => $score
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify Cloudflare Turnstile token
|
||||
*
|
||||
* @param int $checker_id Checker post ID
|
||||
* @param string $token Turnstile token from frontend
|
||||
* @return array ['success' => bool, 'message' => string]
|
||||
*/
|
||||
public static function verify_turnstile($checker_id, $token) {
|
||||
$checker = get_post_meta($checker_id, 'checker', true);
|
||||
|
||||
// Check if Turnstile is enabled
|
||||
if (!isset($checker['security']['turnstile']['enabled']) || $checker['security']['turnstile']['enabled'] !== 'yes') {
|
||||
return ['success' => true];
|
||||
}
|
||||
|
||||
// Get settings
|
||||
$secret_key = isset($checker['security']['turnstile']['secret_key']) ? $checker['security']['turnstile']['secret_key'] : '';
|
||||
|
||||
if (empty($secret_key) || empty($token)) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Turnstile verification failed: Missing credentials'
|
||||
];
|
||||
}
|
||||
|
||||
// Verify with Cloudflare
|
||||
$response = wp_remote_post('https://challenges.cloudflare.com/turnstile/v0/siteverify', [
|
||||
'body' => [
|
||||
'secret' => $secret_key,
|
||||
'response' => $token
|
||||
]
|
||||
]);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Turnstile verification failed: ' . $response->get_error_message()
|
||||
];
|
||||
}
|
||||
|
||||
$body = json_decode(wp_remote_retrieve_body($response), true);
|
||||
|
||||
if (!isset($body['success']) || !$body['success']) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Turnstile verification failed'
|
||||
];
|
||||
}
|
||||
|
||||
return ['success' => true];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get client IP address
|
||||
*
|
||||
* @return string IP address
|
||||
*/
|
||||
public static function get_client_ip() {
|
||||
$ip = '';
|
||||
|
||||
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
|
||||
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
||||
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||
} else {
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
}
|
||||
|
||||
// If multiple IPs, get the first one
|
||||
if (strpos($ip, ',') !== false) {
|
||||
$ip = trim(explode(',', $ip)[0]);
|
||||
}
|
||||
|
||||
return $ip;
|
||||
}
|
||||
}
|
||||
545
includes/class-Sheet-Data-Checker-Pro.php
Normal file
545
includes/class-Sheet-Data-Checker-Pro.php
Normal file
@@ -0,0 +1,545 @@
|
||||
<?php
|
||||
|
||||
class SHEET_DATA_CHECKER_PRO {
|
||||
|
||||
/**
|
||||
* A reference to an instance of this class.
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* Returns an instance of this class.
|
||||
*/
|
||||
public static function get_instance() {
|
||||
|
||||
return self::$instance;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the plugin by setting filters and administration functions.
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
add_action( 'init', [$this, 'create_custom_post_type'] );
|
||||
add_action( 'admin_enqueue_scripts', [$this, 'enqueue_bootstrap_admin'] );
|
||||
|
||||
include SHEET_CHECKER_PRO_PATH . 'includes/class-License.php';
|
||||
$lis = new CHECKER_LICENSE();
|
||||
|
||||
if(true == $lis->the_lis()){
|
||||
|
||||
add_filter( 'manage_checker_posts_columns', [$this, 'filter_cpt_columns']);
|
||||
add_action( 'manage_checker_posts_custom_column', [$this, 'action_custom_columns_content'], 10, 2 );
|
||||
|
||||
add_action( 'add_meta_boxes', [$this, 'add_checker_metabox'] );
|
||||
add_action( 'save_post_checker', [$this, 'save_checker_metabox'] );
|
||||
|
||||
add_action( 'wp_ajax_load_repeater_field_card', [$this, 'load_repeater_field_card'] );
|
||||
add_action( 'wp_ajax_load_output_setting', [$this, 'load_output_setting'] );
|
||||
|
||||
require 'class-Shortcode.php';
|
||||
new CHECKER_SHORTCODE();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function create_custom_post_type() {
|
||||
|
||||
$labels = array(
|
||||
'name' => 'Checker',
|
||||
'singular_name' => 'Checker',
|
||||
'menu_name' => 'Checkers',
|
||||
'add_new' => 'Add New',
|
||||
'add_new_item' => 'Add New Checker',
|
||||
'edit' => 'Edit',
|
||||
'edit_item' => 'Edit Checker',
|
||||
'new_item' => 'New Checker',
|
||||
'view' => 'View',
|
||||
'view_item' => 'View Checker',
|
||||
'search_items' => 'Search Checkers',
|
||||
'not_found' => 'No checkers found',
|
||||
'not_found_in_trash' => 'No checkers found in trash',
|
||||
'parent' => 'Parent Checker'
|
||||
);
|
||||
|
||||
$args = array(
|
||||
'label' => 'Checkers',
|
||||
'description' => 'Checkers for your sheet data',
|
||||
'labels' => $labels,
|
||||
'public' => false,
|
||||
'menu_position' => 4,
|
||||
'menu_icon' => SHEET_CHECKER_PRO_URL .'assets/icons8-validation-menu-icon.png',
|
||||
'supports' => array( 'title' ),
|
||||
'hierarchical' => true,
|
||||
'taxonomies' => array( 'category' ),
|
||||
'has_archive' => false,
|
||||
'rewrite' => array( 'slug' => 'checkers' ),
|
||||
'show_ui' => true,
|
||||
'show_in_menu' => true,
|
||||
'show_in_rest' => false,
|
||||
'query_var' => true,
|
||||
);
|
||||
|
||||
register_post_type( 'checker', $args );
|
||||
|
||||
}
|
||||
|
||||
public function enqueue_bootstrap_admin() {
|
||||
$screen = get_current_screen();
|
||||
|
||||
// Check that we are on the 'Checker' post editor screen
|
||||
if ( $screen && $screen->id === 'checker' ) {
|
||||
// Enqueue Bootstrap CSS
|
||||
wp_enqueue_style( 'bootstrap', 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css' );
|
||||
// wp_enqueue_style( 'bs-table', 'https://unpkg.com/bootstrap-table@1.22.1/dist/bootstrap-table.min.css' );
|
||||
wp_enqueue_style( 'bs-icon', 'https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css' );
|
||||
wp_enqueue_style( 'checker-editor', SHEET_CHECKER_PRO_URL . 'assets/admin-editor.css' );
|
||||
wp_enqueue_style( 'datatables', 'https://cdn.datatables.net/2.2.2/css/dataTables.dataTables.css' );
|
||||
|
||||
// Enqueue Bootstrap JS
|
||||
wp_enqueue_script( 'bootstrap', 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js', array( 'jquery' ), '4.5.2', true );
|
||||
wp_enqueue_script( 'handlebarjs', 'https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.8/handlebars.min.js', ['jquery'], '4.7.8', true );
|
||||
// wp_enqueue_script( 'bs-table', 'https://unpkg.com/bootstrap-table@1.22.1/dist/bootstrap-table.min.js', ['jquery'], '1.22.1', true );
|
||||
wp_enqueue_script( 'checker-editor', SHEET_CHECKER_PRO_URL . 'assets/admin-editor-interactions.js', ['jquery', 'handlebarjs'], true );
|
||||
wp_enqueue_script( 'datatables', 'https://cdn.datatables.net/2.2.2/js/dataTables.js', ['jquery'], true );
|
||||
wp_enqueue_script( 'datatables', 'https://cdn.datatables.net/responsive/3.0.4/js/dataTables.responsive.js', ['jquery'], true );
|
||||
wp_enqueue_script( 'datatables', 'https://cdn.datatables.net/responsive/3.0.4/js/responsive.dataTables.js', ['jquery'], true );
|
||||
}
|
||||
|
||||
wp_enqueue_style( 'checker-editor', SHEET_CHECKER_PRO_URL . 'assets/admin.css' );
|
||||
}
|
||||
|
||||
public function filter_cpt_columns( $columns ) {
|
||||
// this will add the column to the end of the array
|
||||
$columns['shortcode'] = 'Shortcode';
|
||||
//add more columns as needed
|
||||
|
||||
// as with all filters, we need to return the passed content/variable
|
||||
return $columns;
|
||||
}
|
||||
|
||||
public function action_custom_columns_content ( $column_id, $post_id ) {
|
||||
//run a switch statement for all of the custom columns created
|
||||
switch( $column_id ) {
|
||||
case 'shortcode':
|
||||
echo '<input class="dw-checker-post-table-input" value=\'[checker id="'.$post_id.'"]\' />';
|
||||
break;
|
||||
|
||||
//add more items here as needed, just make sure to use the column_id in the filter for each new item.
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function add_checker_metabox() {
|
||||
|
||||
add_meta_box(
|
||||
'checker_preview',
|
||||
'Preview',
|
||||
[$this, 'preview_checker_metabox'],
|
||||
'checker',
|
||||
'normal',
|
||||
'default'
|
||||
);
|
||||
|
||||
add_meta_box(
|
||||
'checker_options',
|
||||
'Options',
|
||||
[$this, 'render_checker_metabox'],
|
||||
'checker',
|
||||
'normal',
|
||||
'default'
|
||||
);
|
||||
|
||||
if(isset($_GET['post']) && isset($_GET['action'])){
|
||||
add_meta_box(
|
||||
'checker_shortcode',
|
||||
'Shortcode',
|
||||
[$this, 'shortcode_checker_metabox'],
|
||||
'checker',
|
||||
'side',
|
||||
'high'
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function shortcode_checker_metabox() {
|
||||
?>
|
||||
<div class="mb-2">Use shortcode below:</div>
|
||||
<input value='[checker id="<?=$_GET['post']?>"]' class="form-control border-dark" readonly>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function preview_checker_metabox($post) {
|
||||
$checker = get_post_meta( $post->ID, 'checker', true );
|
||||
$checker = wp_parse_args( $checker, [
|
||||
'link' => '',
|
||||
'description' => '',
|
||||
'card' => [
|
||||
'width' => 500,
|
||||
'background' => '#cccccc',
|
||||
'border_radius' => 1,
|
||||
'box_shadow' => '10px 5px 15px -5px',
|
||||
'box_shadow_color' => '#333333',
|
||||
'title' => '#333333',
|
||||
'title_align' => 'left',
|
||||
'description' => '#333333',
|
||||
'description_align' => 'left',
|
||||
'divider' => '#333333',
|
||||
'divider_width' => 1
|
||||
],
|
||||
'field' => [
|
||||
'label' => 'block',
|
||||
'label-color' => '#333333'
|
||||
],
|
||||
'fields' => [],
|
||||
'search_button' => [
|
||||
'text' => 'Search',
|
||||
'bg_color' => '#cccccc',
|
||||
'text_color' => '#333333',
|
||||
'position' => 'flex-end'
|
||||
],
|
||||
'back_button' => [
|
||||
'text' => 'Back',
|
||||
'bg_color' => '#cccccc',
|
||||
'text_color' => '#333333',
|
||||
'position' => 'flex-start'
|
||||
],
|
||||
'result' => [
|
||||
'display' => 'tabel',
|
||||
'header' => '#333333',
|
||||
'value' => '#333333',
|
||||
'columns' => [],
|
||||
'border_width' => 1
|
||||
]
|
||||
] );
|
||||
|
||||
require_once SHEET_CHECKER_PRO_PATH . 'templates/editor/preview.php';
|
||||
}
|
||||
|
||||
public function render_checker_metabox( $post ) {
|
||||
// Retrieve existing values from the database
|
||||
$checker = get_post_meta( $post->ID, 'checker', true );
|
||||
$checker = wp_parse_args( $checker, [
|
||||
'link' => '',
|
||||
'description' => '',
|
||||
'card' => [
|
||||
'width' => 500,
|
||||
'background' => '#cccccc',
|
||||
'bg_opacity' => 100,
|
||||
'border_radius' => 1,
|
||||
'box_shadow' => '10px 5px 15px -5px',
|
||||
'box_shadow_color' => '#333333',
|
||||
'title' => '#333333',
|
||||
'title_align' => 'left',
|
||||
'description' => '#333333',
|
||||
'description_align' => 'left',
|
||||
'divider' => '#333333',
|
||||
'divider_width' => 1
|
||||
],
|
||||
'field' => [
|
||||
'label' => 'block',
|
||||
'label-color' => '#333333'
|
||||
],
|
||||
'fields' => [],
|
||||
'search_button' => [
|
||||
'text' => 'Search',
|
||||
'bg_color' => '#cccccc',
|
||||
'text_color' => '#333333',
|
||||
'position' => 'flex-end'
|
||||
],
|
||||
'back_button' => [
|
||||
'text' => 'Back',
|
||||
'bg_color' => '#cccccc',
|
||||
'text_color' => '#333333',
|
||||
'position' => 'flex-start'
|
||||
],
|
||||
'result' => [
|
||||
'display' => 'table',
|
||||
'header' => '#333333',
|
||||
'value' => '#333333',
|
||||
'divider' => '#333333',
|
||||
'divider_width' => 1
|
||||
]
|
||||
] );
|
||||
|
||||
require_once SHEET_CHECKER_PRO_PATH . 'templates/editor/settings.php';
|
||||
}
|
||||
|
||||
public function save_checker_metabox( $post_id ) {
|
||||
// Save metabox data
|
||||
if ( isset( $_POST['checker'] ) ) {
|
||||
error_log(print_r($_POST['checker'], true));
|
||||
update_post_meta( $post_id, 'checker', $_POST['checker'] );
|
||||
}
|
||||
}
|
||||
|
||||
public function load_repeater_field_card_depracated() {
|
||||
|
||||
$post_id = $_REQUEST['pid'];
|
||||
$checker = get_post_meta( $post_id, 'checker', true );
|
||||
$json = json_decode(stripslashes($_REQUEST['json']), true);
|
||||
|
||||
if(isset($checker['fields']) && count($checker['fields']) > 0){
|
||||
foreach($checker['fields'] as $key => $field){
|
||||
?>
|
||||
<div class="card shadow repeater-card gap-2 position-relative">
|
||||
<div class="card-body">
|
||||
<div class="row mb-2">
|
||||
<div class="col-3"><label class="form-label fw-bold mb-0">Field ID</label></div>
|
||||
<div class="col-9">
|
||||
<input class="form-control field-id" value="<?= $key ?>" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-3"><label class="form-label fw-bold mb-0">Column</label></div>
|
||||
<div class="col-9">
|
||||
<select name="checker[fields][<?= $key ?>][kolom]" class="form-select border select-kolom">
|
||||
<?php
|
||||
if($json){
|
||||
$header = $this->parse_header_kolom($json);
|
||||
if(!empty($header)){
|
||||
foreach($header as $name){
|
||||
if( $field['kolom'] == $name ){
|
||||
echo '<option value="'.$name.'" selected>'.$name.'</option>';
|
||||
}else{
|
||||
echo '<option value="'.$name.'">'.$name.'</option>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-3"><label class="form-label fw-bold mb-0">Type</label></div>
|
||||
<div class="col-9">
|
||||
<select name="checker[fields][<?= $key ?>][type]" class="form-select border select-field-type">
|
||||
<option value="text" <?= ($field['type'] == 'text') ? 'selected' : '' ?>>Text</option>
|
||||
<option value="select" <?= ($field['type'] == 'select') ? 'selected' : '' ?>>Select</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-3"><label class="form-label fw-bold mb-0">Label</label></div>
|
||||
<div class="col-9">
|
||||
<input name="checker[fields][<?= $key ?>][label]" class="form-control field-label" value="<?= $field['label'] ?? '' ?>" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-3"><label class="form-label fw-bold mb-0">Placeholder</label></div>
|
||||
<div class="col-9">
|
||||
<input name="checker[fields][<?= $key ?>][placeholder]" class="form-control field-placeholder" value="<?= $field['placeholder'] ?? '' ?>" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-3"><label class="form-label fw-bold mb-0">Value Matcher</label></div>
|
||||
<div class="col-9">
|
||||
<select name="checker[fields][<?= $key ?>][match]" class="form-select border select-match-type">
|
||||
<option value="match" <?= ($field['match'] == 'match') ? 'selected' : '' ?>>Match</option>
|
||||
<option value="contain" <?= ($field['match'] == 'contain') ? 'selected' : '' ?>>Contain</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-buttons d-flex gap-2 flex-column position-absolute">
|
||||
<button type="button" class="btn btn-primary py-1 px-2 add-form-card"><i class="bi bi-plus"></i></button>
|
||||
<button type="button" class="btn btn-danger py-1 px-2 delete-form-card"><i class="bi bi-dash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}else{
|
||||
?>
|
||||
<div class="card shadow repeater-card gap-2 position-relative">
|
||||
<div class="card-body">
|
||||
<div class="row mb-2">
|
||||
<div class="col-3"><label class="form-label fw-bold mb-0">Field ID</label></div>
|
||||
<div class="col-9">
|
||||
<input class="form-control field-id" value="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-3"><label class="form-label fw-bold mb-0">Column</label></div>
|
||||
<div class="col-9">
|
||||
<select name="" class="form-select border select-kolom">
|
||||
<?php
|
||||
if($json){
|
||||
$header = $this->parse_header_kolom($json);
|
||||
if(!empty($header)){
|
||||
foreach($header as $key => $name){
|
||||
if( $key == 0 ){
|
||||
echo '<option value="'.$name.'" selected>'.$name.'</option>';
|
||||
}else{
|
||||
echo '<option value="'.$name.'">'.$name.'</option>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-3"><label class="form-label fw-bold mb-0">Type</label></div>
|
||||
<div class="col-9">
|
||||
<select name="" class="form-select border select-field-type">
|
||||
<option value="text" selected>Text</option>
|
||||
<option value="select">Select</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-3"><label class="form-label fw-bold mb-0">Label</label></div>
|
||||
<div class="col-9">
|
||||
<input name="" class="form-control field-label" value="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-3"><label class="form-label fw-bold mb-0">Placeholder</label></div>
|
||||
<div class="col-9">
|
||||
<input name="" class="form-control field-placeholder" value="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-3"><label class="form-label fw-bold mb-0">Value Matcher</label></div>
|
||||
<div class="col-9">
|
||||
<select name="" class="form-select border select-match-type">
|
||||
<option value="match" selected>Match</option>
|
||||
<option value="contain">Contain</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-buttons d-flex gap-2 flex-column position-absolute">
|
||||
<button type="button" class="btn btn-primary py-1 px-2 add-form-card"><i class="bi bi-plus"></i></button>
|
||||
<button type="button" class="btn btn-danger py-1 px-2 delete-form-card"><i class="bi bi-dash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
exit();
|
||||
}
|
||||
|
||||
public function load_repeater_field_card() {
|
||||
$post_id = $_REQUEST['pid'];
|
||||
$checker = get_post_meta($post_id, 'checker', true);
|
||||
$headers = $_REQUEST['headers'];
|
||||
|
||||
$response = [];
|
||||
|
||||
if (isset($checker['fields']) && count($checker['fields']) > 0) {
|
||||
foreach ($checker['fields'] as $key => $field) {
|
||||
$response[$key] = $field;
|
||||
|
||||
$rowHeader = [];
|
||||
foreach($headers as $index => $header){
|
||||
$id = '_'.strtolower($header);
|
||||
$rowHeader[$index] = $id;
|
||||
}
|
||||
$response[$key]['selected_kolom'] = $response[$key]['kolom'];
|
||||
$response[$key]['kolom'] = $headers;
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json($response);
|
||||
exit();
|
||||
}
|
||||
|
||||
public function load_column_checkbox() {
|
||||
|
||||
$post_id = $_REQUEST['pid'];
|
||||
$checker = get_post_meta( $post_id, 'checker', true );
|
||||
$json = json_decode(stripslashes($_REQUEST['json']), true);
|
||||
|
||||
$header = $this->parse_header_kolom($json);
|
||||
|
||||
if(count($header) > 0){
|
||||
foreach($header as $key){
|
||||
$checked = '';
|
||||
if(isset($checker['result']['columns']) && in_array($key, $checker['result']['columns'])){
|
||||
$checked = ' checked';
|
||||
}
|
||||
?>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" value="<?= $key ?>" id="checker-item-<?= strtolower(str_replace(' ', '_', $key)) ?>" name="checker[result][columns][]"<?=$checked?>>
|
||||
<label class="form-check-label" for="checker-item-<?= strtolower(str_replace(' ', '_', $key)) ?>">
|
||||
<?= $key ?>
|
||||
</label>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
exit();
|
||||
|
||||
}
|
||||
|
||||
public function load_output_setting() {
|
||||
$post_id = $_REQUEST['pid'];
|
||||
$checker = get_post_meta($post_id, 'checker', true);
|
||||
$headers = $_REQUEST['headers'];
|
||||
|
||||
// $header = $this->parse_header_kolom($json);
|
||||
|
||||
if (!empty($headers)) {
|
||||
$output_data = [];
|
||||
|
||||
foreach ($headers as $key) {
|
||||
$id = strtolower(str_replace([' ', '.'], '_', $key));
|
||||
|
||||
$output_data[] = [
|
||||
'key' => $key,
|
||||
'id' => $id,
|
||||
'hide' => isset($checker['output'][$id]['hide']) ? $checker['output'][$id]['hide'] : 'no',
|
||||
'type' => isset($checker['output'][$id]['type']) ? $checker['output'][$id]['type'] : 'text',
|
||||
'button_text' => isset($checker['output'][$id]['button_text']) ? $checker['output'][$id]['button_text'] : '',
|
||||
'prefix' => isset($checker['output'][$id]['prefix']) ? $checker['output'][$id]['prefix'] : '',
|
||||
'bg_color' => isset($checker['output'][$id]['bg_color']) ? $checker['output'][$id]['bg_color'] : '#cccccc',
|
||||
'text_color' => isset($checker['output'][$id]['text_color']) ? $checker['output'][$id]['text_color'] : '#000000',
|
||||
'display' => isset($checker['result']['display']) && $checker['result']['display'] == 'card'
|
||||
];
|
||||
}
|
||||
|
||||
wp_send_json_success(['data' => $output_data]);
|
||||
} else {
|
||||
wp_send_json_error('No headers found');
|
||||
}
|
||||
exit();
|
||||
}
|
||||
|
||||
|
||||
public function parse_options($json, $kolom) {
|
||||
|
||||
$json = json_decode($json, true);
|
||||
$options = [];
|
||||
if($json){
|
||||
foreach($json as $key => $value){
|
||||
foreach($value as $name => $val){
|
||||
if($name == $kolom){
|
||||
if(!in_array($val, $options)){
|
||||
$options[] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
|
||||
}
|
||||
|
||||
public function parse_header_kolom($json) {
|
||||
|
||||
$header = [];
|
||||
if(!is_array($json)){
|
||||
$json = json_decode($json, true);
|
||||
}
|
||||
$header = array_keys($json[0]);
|
||||
return $header;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
409
includes/class-Shortcode.php
Normal file
409
includes/class-Shortcode.php
Normal file
@@ -0,0 +1,409 @@
|
||||
<?php
|
||||
|
||||
class CHECKER_SHORTCODE extends SHEET_DATA_CHECKER_PRO {
|
||||
|
||||
/**
|
||||
* A reference to an instance of this class.
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* Returns an instance of this class.
|
||||
*/
|
||||
public static function get_instance() {
|
||||
|
||||
return self::$instance;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the plugin by setting filters and administration functions.
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
// Load security class
|
||||
require_once SHEET_CHECKER_PRO_PATH . 'includes/class-Security.php';
|
||||
|
||||
add_shortcode('checker', [$this, 'content'] );
|
||||
add_action( 'wp_enqueue_scripts', [$this, 'enqueue'] );
|
||||
|
||||
add_action( 'wp_ajax_checker_public_validation', [$this, 'checker_public_validation'] );
|
||||
add_action( 'wp_ajax_nopriv_checker_public_validation', [$this, 'checker_public_validation'] );
|
||||
|
||||
add_action( 'wp_ajax_checker_load_all_data', [$this, 'checker_load_all_data'] );
|
||||
add_action( 'wp_ajax_nopriv_checker_load_all_data', [$this, 'checker_load_all_data'] );
|
||||
|
||||
}
|
||||
|
||||
public function enqueue() {
|
||||
wp_enqueue_style( 'datatable', 'https://cdn.datatables.net/1.13.7/css/jquery.dataTables.min.css', [], 'all' );
|
||||
wp_enqueue_style( 'checker-pro', SHEET_CHECKER_PRO_URL . 'assets/public.css?ver='.SHEET_CHECKER_PRO_VERSION, [], 'all' );
|
||||
|
||||
wp_enqueue_script( 'datatable', 'https://cdn.datatables.net/1.13.7/js/jquery.dataTables.min.js', ['jquery'], true );
|
||||
wp_enqueue_script( 'checker-pro', SHEET_CHECKER_PRO_URL . 'assets/public.js?ver='.SHEET_CHECKER_PRO_VERSION, ['jquery'], true );
|
||||
}
|
||||
|
||||
public function content ($atts, $content=null) {
|
||||
|
||||
if(!isset($atts['id'])){
|
||||
return;
|
||||
}
|
||||
|
||||
$post_id = $atts['id'];
|
||||
$checker = get_post_meta( $post_id, 'checker', true );
|
||||
$checker = wp_parse_args( $checker, [
|
||||
'link' => '',
|
||||
'description' => '',
|
||||
'card' => [
|
||||
'width' => 500,
|
||||
'background' => '#cccccc',
|
||||
'bg_opacity' => 50,
|
||||
'border_radius' => 1,
|
||||
'box_shadow' => '10px 5px 15px -5px',
|
||||
'box_shadow_color' => '#333333',
|
||||
'title' => '#333333',
|
||||
'title_align' => 'left',
|
||||
'description' => '#333333',
|
||||
'description_align' => 'left',
|
||||
'divider' => '#333333',
|
||||
'divider_width' => 1
|
||||
],
|
||||
'field' => [
|
||||
'label' => 'block',
|
||||
'label-color' => '#333333'
|
||||
],
|
||||
'fields' => [],
|
||||
'search_button' => [
|
||||
'text' => 'Search',
|
||||
'bg_color' => '#cccccc',
|
||||
'text_color' => '#333333',
|
||||
'position' => 'flex-end'
|
||||
],
|
||||
'back_button' => [
|
||||
'text' => 'Back',
|
||||
'bg_color' => '#cccccc',
|
||||
'text_color' => '#333333',
|
||||
'position' => 'flex-start'
|
||||
],
|
||||
'result' => [
|
||||
'display' => 'vertical-tabel',
|
||||
'header' => '#333333',
|
||||
'value' => '#333333',
|
||||
'columns' => [],
|
||||
'border_width' => 1
|
||||
]
|
||||
] );
|
||||
|
||||
$url = $checker['link'];
|
||||
|
||||
$link_format = substr($url, -3);
|
||||
|
||||
// Set the delimiter based on the format
|
||||
$delimiter = $link_format == 'tsv' ? "\t" : ","; // Use tab for TSV, comma for CSV
|
||||
|
||||
if (($handle = fopen($url, "r")) !== false) {
|
||||
$keys = fgetcsv($handle, 0, $delimiter); // Read the first row as keys
|
||||
while (($row = fgetcsv($handle, 0, $delimiter)) !== false) {
|
||||
$data[] = array_combine($keys, $row); // Combine keys with row values and add to the data array
|
||||
}
|
||||
fclose($handle);
|
||||
}
|
||||
$background_color = $checker['card']['background'];
|
||||
if($checker['card']['bg_opacity'] < 100){
|
||||
$background_color = $checker['card']['background'].''.$checker['card']['bg_opacity'];
|
||||
}
|
||||
|
||||
$render = '';
|
||||
$render .= '<div class="dw-checker-container" id="checker-'.$post_id.'">';
|
||||
$render .= '<form class="dw-checker-wrapper dw-checker-form"
|
||||
style="max-width: 100%;
|
||||
background-color: '.$background_color.';
|
||||
width: '.$checker['card']['width'].'px;
|
||||
padding: '.$checker['card']['padding'].'em;
|
||||
border-radius: '.$checker['card']['border_radius'].'em;
|
||||
box-shadow: '.$checker['card']['box_shadow'].' '.$checker['card']['box_shadow_color'].';
|
||||
">';
|
||||
$render .= '<div class="dw-checker-title"
|
||||
style="color: '.$checker['card']['title'].';
|
||||
text-align: '.$checker['card']['title_align'].';"
|
||||
>'.get_the_title($post_id).'</div>';
|
||||
$render .= '<div class="dw-checker-description"
|
||||
style="color: '.$checker['card']['description'].';
|
||||
text-align: '.$checker['card']['description_align'].';"
|
||||
>'.$checker['description'].'</div>';
|
||||
|
||||
$render .= '<hr class="dw-checker-divider"
|
||||
style="border-color: '.$checker['card']['divider'].';
|
||||
border-width: '.$checker['card']['divider_width'].'px;">';
|
||||
|
||||
$render .= '<div class="dw-checker-form-fields">';
|
||||
if(isset($checker['fields']) && !empty($checker['fields'])){
|
||||
foreach($checker['fields'] as $key => $field){
|
||||
if($field['type'] == 'text'){
|
||||
$render .= '<div class="dw-checker-field">
|
||||
<label for="'.$key.'" style="color: '.$checker['field']['label-color'].';display: '.$checker['field']['label'].';">
|
||||
'.$field['label'].'
|
||||
</label>
|
||||
<input name="'.$key.'" placeholder="'.$field['placeholder'].'" class="dw-checker-inputs" data-kolom="'.$field['kolom'].'" required/>
|
||||
</div>';
|
||||
}else{
|
||||
$options = '';
|
||||
$option_array = [];
|
||||
foreach($data as $all_data){
|
||||
foreach($all_data as $_key => $_value){
|
||||
if($_key == $field['kolom'] && !in_array($_value, $option_array)){
|
||||
$option_array[] = $_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
asort($option_array);
|
||||
if(!empty($option_array)){
|
||||
foreach($option_array as $val){
|
||||
$options .= '<option value="'.$val.'">'.$val.'</option>';
|
||||
}
|
||||
}
|
||||
$render .= '<div class="dw-checker-field">
|
||||
<label for="'.$key.'" style="color: '.$checker['field']['label-color'].';display: '.$checker['field']['label'].';">
|
||||
'.$field['kolom'].'
|
||||
</label>
|
||||
<select name="'.$key.'" placeholder="'.$field['placeholder'].'" class="dw-checker-inputs" data-kolom="'.$field['kolom'].'" required>
|
||||
<option value="" disabled selected>-- '.$field['placeholder'].' --</option>
|
||||
'.$options.'
|
||||
</select>
|
||||
</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
$render .= '</div>';
|
||||
|
||||
$render .= '<hr class="dw-checker-divider"
|
||||
style="border-color: '.$checker['card']['divider'].';
|
||||
border-width: '.$checker['card']['divider_width'].'px;">';
|
||||
|
||||
$render .= '<div class="dw-checker-buttons dw-checker-form-button" style="justify-content: '.$checker['search_button']['position'].'">';
|
||||
$render .= '<button type="submit" data-checker="'.$post_id.'" class="search-button"
|
||||
data-btn-text="'.$checker['search_button']['text'].'"
|
||||
style="background-color: '.$checker['search_button']['bg_color'].';
|
||||
color: '.$checker['search_button']['text_color'].';">
|
||||
'.$checker['search_button']['text'].'
|
||||
</button>';
|
||||
$render .= '</div>';
|
||||
|
||||
$render .= '</form>';
|
||||
|
||||
$render .= '<div class="dw-checker-wrapper dw-checker-result"
|
||||
style="display:none; max-width: 100%;
|
||||
background-color: '.$checker['card']['background'].';
|
||||
width: '.$checker['card']['width'].'px;
|
||||
padding: '.$checker['card']['padding'].'em;
|
||||
border-radius: '.$checker['card']['border_radius'].'em;
|
||||
box-shadow: '.$checker['card']['box_shadow'].' '.$checker['card']['box_shadow_color'].';
|
||||
">';
|
||||
$render .= '<div class="dw-checker-title"
|
||||
style="color: '.$checker['card']['title'].';
|
||||
text-align: '.$checker['card']['title_align'].';"
|
||||
></div>';
|
||||
$render .= '<div class="dw-checker-description"
|
||||
style="color: '.$checker['card']['description'].';
|
||||
text-align: '.$checker['card']['description_align'].';"
|
||||
></div>';
|
||||
|
||||
$render .= '<hr class="dw-checker-divider"
|
||||
style="border-color: '.$checker['card']['divider'].';
|
||||
border-width: '.$checker['card']['divider_width'].'px;">';
|
||||
|
||||
$render .= '<div class="dw-checker-results"></div>';
|
||||
|
||||
$render .= '<hr class="dw-checker-divider"
|
||||
style="border-color: '.$checker['card']['divider'].';
|
||||
border-width: '.$checker['card']['divider_width'].'px;">';
|
||||
|
||||
$render .= '<div class="dw-checker-buttons dw-checker-result-button" style="justify-content: '.$checker['back_button']['position'].'">';
|
||||
$render .= '<button type="button" class="back-button" data-checker='.$post_id.'
|
||||
style="background-color: '.$checker['back_button']['bg_color'].';
|
||||
color: '.$checker['back_button']['text_color'].';">
|
||||
'.$checker['back_button']['text'].'
|
||||
</button>';
|
||||
$render .= '</div>';
|
||||
|
||||
$render .= '</div>';
|
||||
$render .= '</div>';
|
||||
$render .= '<div class="dw-checker-bottom-results"></div>';
|
||||
|
||||
// Pass settings to frontend as data attributes
|
||||
$render .= '<script type="application/json" id="checker-settings-'.$post_id.'" class="checker-settings-data">';
|
||||
$render .= json_encode([
|
||||
'checker_id' => $post_id,
|
||||
'initial_display' => $checker['result']['initial_display'] ?? 'hidden',
|
||||
'filter_mode' => $checker['result']['filter_mode'] ?? 'search',
|
||||
'max_records' => $checker['result']['max_records'] ?? 100,
|
||||
'url_params_enabled' => $checker['url_params']['enabled'] ?? 'no',
|
||||
'url_params_auto_search' => $checker['url_params']['auto_search'] ?? 'no'
|
||||
]);
|
||||
$render .= '</script>';
|
||||
|
||||
return $render;
|
||||
|
||||
}
|
||||
|
||||
public function checker_public_validation() {
|
||||
|
||||
$post_id = $_REQUEST['checker_id'];
|
||||
$checker = get_post_meta( $post_id, 'checker', true );
|
||||
|
||||
// Security checks
|
||||
$ip = CHECKER_SECURITY::get_client_ip();
|
||||
|
||||
// Check rate limit
|
||||
$rate_limit = CHECKER_SECURITY::check_rate_limit($post_id, $ip);
|
||||
if (!$rate_limit['allowed']) {
|
||||
wp_send_json_error([
|
||||
'message' => $rate_limit['message'],
|
||||
'type' => 'rate_limit'
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check reCAPTCHA if enabled
|
||||
if (isset($_REQUEST['recaptcha_token'])) {
|
||||
$recaptcha = CHECKER_SECURITY::verify_recaptcha($post_id, $_REQUEST['recaptcha_token']);
|
||||
if (!$recaptcha['success']) {
|
||||
wp_send_json_error([
|
||||
'message' => $recaptcha['message'],
|
||||
'type' => 'recaptcha'
|
||||
]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check Turnstile if enabled
|
||||
if (isset($_REQUEST['turnstile_token'])) {
|
||||
$turnstile = CHECKER_SECURITY::verify_turnstile($post_id, $_REQUEST['turnstile_token']);
|
||||
if (!$turnstile['success']) {
|
||||
wp_send_json_error([
|
||||
'message' => $turnstile['message'],
|
||||
'type' => 'turnstile'
|
||||
]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$url = $checker['link'];
|
||||
|
||||
$link_format = substr($url, -3);
|
||||
|
||||
// Set the delimiter based on the format
|
||||
$delimiter = $link_format == 'tsv' ? "\t" : ","; // Use tab for TSV, comma for CSV
|
||||
|
||||
if (($handle = fopen($url, "r")) !== false) {
|
||||
$keys = fgetcsv($handle, 0, $delimiter); // Read the first row as keys
|
||||
while (($row = fgetcsv($handle, 0, $delimiter)) !== false) {
|
||||
$data[] = array_combine($keys, $row); // Combine keys with row values and add to the data array
|
||||
}
|
||||
fclose($handle);
|
||||
}
|
||||
|
||||
$validator = $_REQUEST['validate'];
|
||||
$validation = [];
|
||||
foreach($validator as $validate){
|
||||
$validation[$validate['kolom']] = $validate['value'];
|
||||
}
|
||||
$validator_count = count($validator);
|
||||
$result = [];
|
||||
if(!empty($data)){
|
||||
foreach($data as $row){
|
||||
$valid = [];
|
||||
foreach($row as $header => $value){
|
||||
$id = '_'.strtolower(str_replace(' ', '_', $header));
|
||||
$include = false;
|
||||
if(isset($validation[$header])){
|
||||
if($checker['fields'][$id]['match'] == 'match' && strtolower($value) == strtolower($validation[$header])){
|
||||
$include = true;
|
||||
}
|
||||
if($checker['fields'][$id]['match'] == 'contain' && false !== strpos(strtolower($value), strtolower($validation[$header]))){
|
||||
$include = true;
|
||||
}
|
||||
if($include){
|
||||
$valid[$header] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
if($validator_count !== count($valid)){
|
||||
continue;
|
||||
}
|
||||
$result[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
$send = [
|
||||
'count' => count($result),
|
||||
'rows' => $result,
|
||||
'settings' => $checker['result'],
|
||||
'output' => $checker['output']
|
||||
];
|
||||
|
||||
wp_send_json($send);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all data from sheet (for show all mode)
|
||||
*/
|
||||
public function checker_load_all_data() {
|
||||
$post_id = isset($_REQUEST['checker_id']) ? intval($_REQUEST['checker_id']) : 0;
|
||||
$limit = isset($_REQUEST['limit']) ? intval($_REQUEST['limit']) : 100;
|
||||
|
||||
if (!$post_id) {
|
||||
wp_send_json_error(['message' => 'Invalid checker ID']);
|
||||
return;
|
||||
}
|
||||
|
||||
$checker = get_post_meta($post_id, 'checker', true);
|
||||
|
||||
if (!$checker || !isset($checker['link'])) {
|
||||
wp_send_json_error(['message' => 'Checker not found']);
|
||||
return;
|
||||
}
|
||||
|
||||
// Security check - rate limiting only
|
||||
$ip = CHECKER_SECURITY::get_client_ip();
|
||||
$rate_limit = CHECKER_SECURITY::check_rate_limit($post_id, $ip);
|
||||
if (!$rate_limit['allowed']) {
|
||||
wp_send_json_error([
|
||||
'message' => $rate_limit['message'],
|
||||
'type' => 'rate_limit'
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
$url = $checker['link'];
|
||||
$link_format = substr($url, -3);
|
||||
$delimiter = $link_format == 'tsv' ? "\t" : ",";
|
||||
|
||||
$data = [];
|
||||
$handle = fopen($url, "r");
|
||||
|
||||
if ($handle !== false) {
|
||||
$keys = fgetcsv($handle, 0, $delimiter);
|
||||
$count = 0;
|
||||
|
||||
while (($row = fgetcsv($handle, 0, $delimiter)) !== false && $count < $limit) {
|
||||
if (count($keys) === count($row)) {
|
||||
$data[] = array_combine($keys, $row);
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
fclose($handle);
|
||||
}
|
||||
|
||||
wp_send_json([
|
||||
'count' => count($data),
|
||||
'rows' => $data,
|
||||
'settings' => $checker['result'],
|
||||
'output' => $checker['output'],
|
||||
'url_params' => $checker['url_params'] ?? [],
|
||||
'filter_mode' => $checker['result']['filter_mode'] ?? 'search'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user