Add PSR HTTP Message Interfaces and Dependencies

- Implemented StreamInterface, UploadedFileInterface, and UriInterface as per PSR standards.
- Added getallheaders function to retrieve HTTP headers in a compatible manner.
- Included LICENSE files for ralouphie/getallheaders and symfony/deprecation-contracts.
- Introduced function for triggering deprecation notices in Symfony.
This commit is contained in:
2025-12-28 12:44:00 +01:00
parent cf600ae727
commit cd264483f8
410 changed files with 60841 additions and 16 deletions

View File

@@ -0,0 +1,82 @@
.cpt-review-notice{
position: relative;
margin: 10px 20px 10px 0 !important;
padding: 5px;
display: flex;
align-items: center;
border-radius: 5px;
max-width: 790px;
padding-left: 11px;
padding-bottom: 11px;
}
.cpt-review-notice .cpt-review-notice-icon{
max-width: 80px;
height: auto;
margin-right: 10px;
}
.cpt-review-notice div p{
margin: 0;
margin-bottom: .5rem;
}
.cpt-review-notice .atfpp-review-notice-dismiss {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
gap: 10px;
}
body.rtl .cpt-review-notice .cpt-not-interested {
right: auto;
left: 5px;
}
.cpt-review-notice :where(.cpt-not-interested, .cpt-already-reviewed)::before {
color: #cc0000;
content: "\f153";
font: normal 16px/20px dashicons;
display: inline-block;
vertical-align: middle;
margin-right: 4px;
height: 22px;
}
.cpt-dashboard {
padding: 20px;
}
.cpt-dashboard .cpt-dashboard-tabs {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
gap: 2px;
border-bottom: 1px solid #ccc;
}
.cpt-dashboard .cpt-dashboard-tabs .cpt-dashboard-tab {
padding: 10px 20px;
cursor: pointer;
background: #f5f5f5;
border: 1px solid #ccc;
border-bottom: none;
border-radius: 4px 4px 0 0;
}
.cpt-dashboard .cpt-dashboard-tabs .cpt-dashboard-tab:hover {
background: #fff;
}
.cpt-dashboard .cpt-dashboard-tabs .cpt-dashboard-tab.cpt-active {
background: #fff;
border-bottom: 1px solid #fff;
}
.cpt-dashboard .cpt-dashboard-table {
display: none;
}
.cpt-dashboard .cpt-dashboard-table.cpt-active {
display: table;
}

View File

@@ -0,0 +1,22 @@
jQuery(document).ready(function($){
$('.cpt-dashboard-tab').click(function(){
var tab = $(this).data('tab');
$('.cpt-dashboard-table').hide();
$('#cpt-'+tab+'-table').show();
$('.cpt-dashboard-tab').removeClass('cpt-active');
$(this).addClass('cpt-active');
$('.cpt-dashboard-tables').find('table').hide();
$('#cpt-'+tab+'-table').show();
});
$('.atfpp-review-notice-dismiss button').click(function(){
var prefix = $(this).closest('.atfpp-review-notice-dismiss').data('prefix');
var nonce = $(this).closest('.atfpp-review-notice-dismiss').data('nonce');
$.post(ajaxurl, {action: 'atfpp_hide_review_notice', prefix: prefix, nonce: nonce}, (response)=>{
$(this).closest('.cpt-review-notice').slideUp();
});
});
});

View File

@@ -0,0 +1,316 @@
<?php
if(!defined('ABSPATH')){
exit;
}
/**
* Dashboard
*
* example:
*
* Dashbord initialize
* if(!class_exists('Atfpp_Dashboard')){
* $dashboard=Atfpp_Dashboard::instance();
* }
*
* Store options
* if(class_exists('Atfpp_Dashboard')){
* Atfpp_Dashboard::store_options(
* 'prefix', // Required plugin prefix
* 'unique_key',// Optional unique key is used to update the data based on post/page id or plugin/themes name
* 'update', // Optional preview string count or character count update or replace
* array(
* 'post/page or theme/plugin name' => 'name or id',
* 'post_title (optional)' => 'Post Title',
* 'service_provider' => 'google', // don't change this key
* 'source_language' => 'en', // don't change this key
* 'target_language' => 'fr', // don't change this key
* 'time_taken' => '10', // don't change this key
* 'string_count'=>10,
* 'character_count'=>100,
* 'date_time' => date('Y-m-d H:i:s'),
* ) // Required data array
* );
* }
*
* Add Tabs
* add_filter('Atfpp_Dashboard_tabs', function($tabs){
* $tabs[]=array(
* 'prefix'=>'tab_name', // Required
* 'tab_name'=>'Tab Name', // Required
* 'columns'=>array(
* 'post_id or plugin_name'=>'Post Id or Plugin Name',
* 'post_title (optional)'=>'Post Title',
* 'string_count'=>'String Count',
* 'character_count'=>'Character Count',
* 'service_provider'=>'Service Provider',
* 'time_taken'=>'Time Taken',
* 'date_time'=>'Date Time',
* ) // columns Required
* );
* return $tabs;
* });
*
* Display review notice
* if(class_exists('Atfpp_Dashboard')){
* Atfpp_Dashboard::review_notice(
* 'prefix', // Required
* 'plugin_name', // Required
* 'url', // Required
* );
* }
*
* Get translation data
* if(class_exists('Atfpp_Dashboard')){
* Atfpp_Dashboard::get_translation_data(
* 'prefix', // Required
* array(
* 'editor_type' => 'gutenberg', // optional return data based on editor type
* 'post_id' => '123', // optional return data based on post id
* ) // Optional
* );
* }
*/
if(!class_exists('Atfpp_Dashboard')){
class Atfpp_Dashboard{
/**
* Init
* @var object
*/
private static $init;
/**
* Tabs data
* @var array
*/
private $tabs_data=array();
/**
* Instance
* @return object
*/
public static function instance(){
if(!isset(self::$init)){
self::$init = new self();
}
return self::$init;
}
public function __construct(){
add_action('wp_ajax_atfpp_hide_review_notice', array($this, 'atfpp_hide_review_notice'));
}
/**
* Sort column data
* @param array $columns
* @param array $value
* @return array
*/
public function sort_column_data($columns, $value){
$result = array();
foreach($columns as $key => $label) {
$result[$key] = isset($value[$key]) ? sanitize_text_field($value[$key]) : '';
}
return $result;
}
/**
* Store options
* @param string $plugin_name
* @param string $prefix
* @param array $data
* @return void
*/
public static function store_options($prefix='', $unique_key='', $old_data='update', array $data = array()){
if(!empty($prefix) && isset($data['string_count']) && isset($data['character_count'])){
$prefix = sanitize_key($prefix);
$all_data = get_option('cpt_dashboard_data', array());
if(isset($all_data[$prefix])){
$data_update = false;
foreach($all_data[$prefix] as $key => $translate_data){
if(!empty($unique_key) && isset($translate_data[$unique_key]) &&
sanitize_text_field($translate_data[$unique_key]) === sanitize_text_field($data[$unique_key]) &&
sanitize_text_field($translate_data['service_provider']) === sanitize_text_field($data['service_provider']) &&
sanitize_text_field($translate_data['target_language']) === sanitize_text_field($data['target_language']) &&
sanitize_text_field($translate_data['source_language']) === sanitize_text_field($data['source_language'])
){
if($old_data=='update'){
$data['string_count'] = absint($data['string_count']) + absint($translate_data['string_count']);
$data['character_count'] = absint($data['character_count']) + absint($translate_data['character_count']);
$data['time_taken'] = absint($data['time_taken']) + absint($translate_data['time_taken']);
}
foreach($data as $id => $value){
$all_data[$prefix][$key][sanitize_key($id)] = sanitize_text_field($value);
}
$data_update = true;
}
}
if(!$data_update){
$all_data[$prefix][] = array_map('sanitize_text_field', $data);
}
}else{
$all_data[$prefix][] = array_map('sanitize_text_field', $data);
}
update_option('cpt_dashboard_data', $all_data);
}
}
/**
* Get translation data
* @param string $prefix
* @return array
*/
public static function get_translation_data($prefix, $key_exists=array()){
$prefix = sanitize_key($prefix);
$all_data = get_option('cpt_dashboard_data', array());
$data = array();
if(isset($all_data[$prefix])){
$total_string_count = 0;
$total_character_count = 0;
foreach($all_data[$prefix] as $key => $value){
$continue=false;
foreach($key_exists as $key_exists_key => $key_exists_value){
if(!isset($value[$key_exists_key]) || (isset($value[$key_exists_key]) && $value[$key_exists_key] !== $key_exists_value)){
$continue=true;
break;
}
}
if($continue){
continue;
}
$total_string_count += isset($value['string_count']) ? absint($value['string_count']) : 0;
$total_character_count += isset($value['character_count']) ? absint($value['character_count']) : 0;
}
$data = array(
'prefix' => $prefix,
'data' => array_map(function($item) {
return array_map('sanitize_text_field', $item);
}, $all_data[$prefix]),
'total_string_count' => $total_string_count,
'total_character_count' => $total_character_count,
);
}else{
$data = array(
'prefix' => $prefix,
'total_string_count' => 0,
'total_character_count' => 0,
);
}
return $data;
}
public static function ctp_enqueue_assets(){
if(function_exists('wp_style_is') && !wp_style_is('atfpp-review-style', 'enqueued')){
$plugin_url = plugin_dir_url(__FILE__);
wp_enqueue_style('atfpp-review-style', esc_url($plugin_url.'assets/css/cpt-dashboard.css'), array(), '1.0.0', 'all');
wp_enqueue_script('atfpp-review-script', esc_url($plugin_url.'assets/js/cpt-dashboard.js'), array('jquery'), '1.0.0', true);
}
}
public static function format_number_count($number){
if ($number >= 1000000) {
return round($number / 1000000, 1) . 'M';
} elseif ($number >= 1000) {
return round($number / 1000, 1) . 'K';
}
return $number;
}
public static function review_notice($prefix, $plugin_name, $url){
if(self::atfpp_hide_review_notice_status($prefix)){
return;
}
$translation_data = self::get_translation_data($prefix);
$total_character_count = is_array($translation_data) && isset($translation_data['total_character_count']) ? $translation_data['total_character_count'] : 0;
if($total_character_count < 50000){
return;
}
$total_character_count = self::format_number_count($total_character_count);
add_action('admin_enqueue_scripts', array(self::class, 'ctp_enqueue_assets'));
$message = sprintf(
__('Thanks for using <b>%1$s</b>! You have translated <b>%2$s</b> characters so far using our plugin!<br>Please give us a quick rating, it works as a boost for us to keep working on more <a style="text-decoration: none;" href="%3$s" target="_blank" rel="noopener noreferrer"><b>Cool Plugins</b></a>!', 'cp-notice'),
$plugin_name,
$total_character_count,
esc_url('https://coolplugins.net/')
);
$prefix = sanitize_key($prefix);
$url = esc_url($url);
$plugin_name = sanitize_text_field($plugin_name);
$allowed = [
'div' => [ 'class' => true, 'data-prefix' => true, 'data-nonce' => true ],
'p' => [],
'a' => [ 'href' => true, 'target' => true, 'class' => true, 'style' => true, 'rel' => true ],
'button' => [ 'class' => true ],
'b' => [],
'br' => [],
'strong' => [],
];
$message = wp_kses($message, $allowed);
add_action('admin_notices', function() use ($message, $prefix, $url, $allowed){
$html= '<div class="notice notice-info is-dismissible cpt-review-notice">';
$html .= '<div class="cpt-review-notice-content"><p>'.$message.'</p><div class="atfpp-review-notice-dismiss" data-prefix="'.esc_attr($prefix).'" data-nonce="'.esc_attr(wp_create_nonce('atfpp_hide_review_notice')).'"><a href="'.esc_url($url).'" target="_blank" class="button button-primary">Rate Now! ★★★★★</a><button class="button cpt-already-reviewed">'.esc_html__('Already Reviewed', 'cp-notice').'</button><button class="button cpt-not-interested">'.esc_html__('Not Interested', 'cp-notice').'</button></div></div></div>';
echo wp_kses($html, $allowed);
});
add_action('atfpp_display_admin_notices', function() use ($message, $prefix, $url, $allowed){
$html= '<div class="notice notice-info is-dismissible cpt-review-notice">';
$html .= '<div class="cpt-review-notice-content"><p>'.$message.'</p><div class="atfpp-review-notice-dismiss" data-prefix="'.$prefix.'" data-nonce="'.wp_create_nonce('atfpp_hide_review_notice').'"><a href="'. $url .'" target="_blank" class="button button-primary">Rate Now! ★★★★★</a><button class="button cpt-not-interested">'.__('Not Interested', 'cp-notice').'</button><button class="button cpt-already-reviewed">'.__('Already Reviewed', 'cp-notice').'</button></div></div></div>';
echo wp_kses($html, $allowed);
});
}
public static function atfpp_hide_review_notice_status($prefix){
$review_notice_dismissed = get_option('cpt_review_notice_dismissed', array());
return isset($review_notice_dismissed[$prefix]) ? $review_notice_dismissed[$prefix] : false;
}
public function atfpp_hide_review_notice(){
if(!current_user_can('manage_options')){
wp_send_json_error( __( 'Unauthorized', 'autopoly-ai-translation-for-polylang-pro' ), 403 );
wp_die( '0', 403 );
}
if(wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'atfpp_hide_review_notice')){
$prefix = sanitize_key(wp_unslash($_POST['prefix']));
$review_notice_dismissed = get_option('cpt_review_notice_dismissed', array());
$review_notice_dismissed[$prefix] = true;
update_option('cpt_review_notice_dismissed', $review_notice_dismissed);
wp_send_json_success();
}else{
wp_send_json_error( __( 'Invalid nonce', 'autopoly-ai-translation-for-polylang-pro' ), 400 );
wp_die( '0', 400 );
}
}
}
}