Changeset 3492424
- Timestamp:
- 03/27/2026 08:11:50 AM (6 days ago)
- Location:
- aiktp/trunk
- Files:
-
- 4 edited
-
aiktp.php (modified) (3 diffs)
-
includes/aiktp-helpers.php (modified) (1 diff)
-
includes/aiktp-sync.php (modified) (7 diffs)
-
readme.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
aiktp/trunk/aiktp.php
r3492289 r3492424 4 4 * Plugin URI: https://aiktp.com/wordpress 5 5 * Description: AIKTP - AI powered WordPress content automation. Create SEO optimized articles, bulk generate WooCommerce product descriptions, and sync posts directly from aiktp.com. 6 * Version: 5.0. 66 * Version: 5.0.7 7 7 * Author: John Luke - aiktp.com 8 8 * License: GPL v2 or later … … 15 15 * WC tested up to: 9.0 16 16 */ 17 18 19 17 if (!defined('ABSPATH')) { 20 18 exit; … … 22 20 23 21 // Define constants 24 define('AIKTPZ_VERSION', '5.0. 6');22 define('AIKTPZ_VERSION', '5.0.7'); 25 23 define('AIKTPZ_PLUGIN_DIR', plugin_dir_path(__FILE__)); 26 24 define('AIKTPZ_PLUGIN_URL', plugin_dir_url(__FILE__)); -
aiktp/trunk/includes/aiktp-helpers.php
r3430333 r3492424 158 158 return $matches[1]; 159 159 } 160 161 /** 162 * Normalize src/href attribute URLs so query separators survive HTML sanitization. 163 */ 164 public static function normalize_html_attribute_urls($html) { 165 if (!is_string($html) || $html === '') { 166 return ''; 167 } 168 169 return preg_replace_callback( 170 '/\b(src|href)\s*=\s*(["\'])(.*?)\2/i', 171 function ($matches) { 172 $attribute = $matches[1]; 173 $quote = $matches[2]; 174 $url = html_entity_decode($matches[3], ENT_QUOTES, 'UTF-8'); 175 176 if (strpos($url, '&') !== false) { 177 $url = str_replace('&', '&', $url); 178 } 179 180 return $attribute . '=' . $quote . $url . $quote; 181 }, 182 $html 183 ); 184 } 160 185 } -
aiktp/trunk/includes/aiktp-sync.php
r3492289 r3492424 75 75 'callback' => array($this, 'upload_image_to_wp'), 76 76 'permission_callback' => array($this, 'verify_aiktp_token_with_upload_capability') 77 )); 78 79 register_rest_route('aiktp', '/doUpdatePostWithImageURL', array( 80 'methods' => 'POST', 81 'callback' => array($this, 'update_post_with_image_url_endpoint'), 82 'permission_callback' => array($this, 'verify_aiktp_token_with_edit_capability') 77 83 )); 78 84 … … 439 445 return array( 440 446 'status' => 'success', 447 'allowAsync' => true, 441 448 'cats' => $cats 442 449 ); … … 600 607 // Get post data 601 608 $post_title = sanitize_text_field($request['title']); 602 // Content should allow HTML tags, use wp_kses_post for sanitization 603 $post_content = isset($request['content']) ? wp_kses_post($request['content']) : ''; 609 // Normalize URLs in HTML attributes before sanitization so query strings keep '&'. 610 $raw_post_content = isset($request['content']) ? (string) $request['content'] : ''; 611 $normalized_post_content = AIKTPZ_Helpers::normalize_html_attribute_urls($raw_post_content); 612 $post_content = wp_kses_post($normalized_post_content); 604 613 $tags_input = sanitize_text_field($request['tags']); 605 $featured_image = $request['featuredImage'];606 $cat_id = $request['catId']? $request['catId'] : '0';607 $post_status = $request['post_status']? $request['post_status'] : 'publish';614 $featured_image = isset($request['featuredImage']) ? (string) $request['featuredImage'] : ''; 615 $cat_id = !empty($request['catId']) ? $request['catId'] : '0'; 616 $post_status = !empty($request['post_status']) ? $request['post_status'] : 'publish'; 608 617 $current_post_id = !empty($request['currentPostId']) ? absint($request['currentPostId']) : 0; 618 $serp_title = isset($request['serp_title']) ? sanitize_text_field($request['serp_title']) : ''; 619 $serp_description = isset($request['serp_des']) ? sanitize_text_field($request['serp_des']) : ''; 620 $serp_score = isset($request['serp_score']) ? sanitize_text_field($request['serp_score']) : ''; 609 621 610 622 // Get author … … 670 682 $post_time = strtotime($request['postTime']); 671 683 if ($post_time) { 672 $post_date = date('Y-m-d H:i:s', $post_time);684 $post_date = wp_date('Y-m-d H:i:s', $post_time); 673 685 $post_date_gmt = gmdate('Y-m-d H:i:s', $post_time); 674 686 } … … 726 738 727 739 // Add tags 740 $tags_array = array(); 728 741 if (!empty($tags_input)) { 729 742 $tags_array = array_map('trim', explode(',', $tags_input)); … … 740 753 741 754 // Update SEO meta if plugins are active 742 if (class_exists('RankMath') && !empty($tags_array)) { 743 update_post_meta($post_id, 'rank_math_focus_keyword', implode(', ', $tags_array)); 744 } 745 746 if (defined('WPSEO_VERSION') && !empty($tags_array[0])) { 747 update_post_meta($post_id, '_yoast_wpseo_focuskw', $tags_array[0]); 748 } 755 if (class_exists('RankMath')) { 756 if (!empty($tags_array)) { 757 update_post_meta($post_id, 'rank_math_focus_keyword', implode(', ', array_unique($tags_array))); 758 } 759 if ($serp_title !== '') { 760 update_post_meta($post_id, 'rank_math_title', $serp_title); 761 } 762 if ($serp_description !== '') { 763 update_post_meta($post_id, 'rank_math_description', $serp_description); 764 } 765 if ($serp_score !== '') { 766 update_post_meta($post_id, 'rank_math_seo_score', $serp_score); 767 } 768 } 769 770 if (defined('WPSEO_VERSION')) { 771 if (!empty($tags_array[0])) { 772 update_post_meta($post_id, '_yoast_wpseo_focuskw', $tags_array[0]); 773 } 774 if ($serp_title !== '') { 775 update_post_meta($post_id, '_yoast_wpseo_title', $serp_title); 776 } 777 if ($serp_description !== '') { 778 update_post_meta($post_id, '_yoast_wpseo_metadesc', $serp_description); 779 } 780 if ($serp_score !== '') { 781 update_post_meta($post_id, '_yoast_wpseo_content_score', $serp_score); 782 } 783 } 784 785 749 786 750 787 return array( … … 797 834 } 798 835 } 836 837 /** 838 * Update post content by replacing remote image URLs with WordPress image URLs. 839 * 840 * SECURITY: Token and edit capability validation is handled in permission_callback. 841 */ 842 public function update_post_with_image_url_endpoint($request) { 843 $post_id = !empty($request['postId']) ? absint($request['postId']) : 0; 844 $imgs = $request->get_param('imgs'); 845 846 if (empty($post_id) || empty($imgs) || !is_array($imgs)) { 847 return array( 848 'status' => 'error' 849 ); 850 } 851 852 return $this->update_post_with_image_url($post_id, $imgs); 853 } 854 855 /** 856 * Replace image URLs in post content. 857 */ 858 private function update_post_with_image_url($post_id, $imgs) { 859 $post_data = get_post($post_id); 860 if (!$post_data || empty($post_data->post_content)) { 861 return array( 862 'status' => 'error' 863 ); 864 } 865 866 $post_content = $post_data->post_content; 867 868 869 foreach ($imgs as $img) { 870 if (!is_array($img)) { 871 continue; 872 } 873 874 $source_url = isset($img['imgURL']) ? (string) $img['imgURL'] : ''; 875 $img_proxy_url = isset($img['imgProxy']) ? (string) $img['imgProxy'] : ''; 876 $target_url = isset($img['wp_imgURL']) ? (string) $img['wp_imgURL'] : ''; 877 878 879 if ($target_url === '') { 880 continue; 881 } 882 883 if ($source_url !== '') { 884 $post_content = str_replace($source_url, $target_url, $post_content); 885 $post_content = str_replace(str_replace('&', '&', $source_url), $target_url, $post_content); 886 } 887 888 if ($img_proxy_url !== '') { 889 $post_content = str_replace($img_proxy_url, $target_url, $post_content); 890 $post_content = str_replace(str_replace('&', '&', $img_proxy_url), $target_url, $post_content); 891 } 892 } 893 894 $update_id = wp_update_post(array( 895 'ID' => $post_id, 896 'post_content' => $post_content 897 )); 898 899 if (is_wp_error($update_id) || empty($update_id)) { 900 return array( 901 'status' => 'error' 902 ); 903 } 904 905 return array( 906 'status' => 'success', 907 'updateId' => $post_id 908 ); 909 } 799 910 } 800 911 -
aiktp/trunk/readme.txt
r3492289 r3492424 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.0 7 Stable tag: 5.0. 67 Stable tag: 5.0.7 8 8 License: GPL v2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html
Note: See TracChangeset
for help on using the changeset viewer.