Changeset 3362830
- Timestamp:
- 09/17/2025 01:22:05 AM (6 months ago)
- Location:
- featured-image-from-url/trunk
- Files:
-
- 1 added
- 14 edited
-
admin/cron.php (modified) (1 diff)
-
admin/db.php (modified) (55 diffs)
-
admin/debug.php (modified) (2 diffs)
-
admin/html/column.html (modified) (1 diff)
-
admin/html/js/support-data.js (added)
-
admin/html/support-data.html (modified) (1 diff)
-
admin/log.php (modified) (1 diff)
-
admin/menu.php (modified) (1 diff)
-
featured-image-from-url.php (modified) (2 diffs)
-
includes/attachment.php (modified) (2 diffs)
-
includes/html/og-image.html (modified) (1 diff)
-
includes/html/twitter-image.html (modified) (1 diff)
-
includes/speedup.php (modified) (3 diffs)
-
includes/util.php (modified) (1 diff)
-
readme.txt (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
featured-image-from-url/trunk/admin/cron.php
r3244867 r3362830 66 66 } 67 67 68 function fifu_should_stop_job($option_name) {69 $field = $option_name . '_stop';70 71 global $wpdb;72 if ($wpdb->get_col("SELECT 1 FROM " . $wpdb->options . " WHERE option_name = '" . $field . "'")) {73 delete_option($field);74 return true;75 }76 return false;77 }78 79 68 function fifu_run_cron_now() { 80 69 wp_remote_request(site_url('wp-cron.php')); -
featured-image-from-url/trunk/admin/db.php
r3352132 r3362830 35 35 } 36 36 37 function get_types() { 38 $post_types = fifu_get_post_types(); 39 return join("','", $post_types); 37 function get_types(): string { 38 $raw = (array) fifu_get_post_types(); 39 40 // Sanitize and validate against registered post types 41 $registered = get_post_types([], 'names'); // array of valid names 42 $safe = []; 43 foreach ($raw as $pt) { 44 $pt = sanitize_key($pt); 45 if ($pt !== '' && isset($registered[$pt])) { 46 $safe[] = $pt; 47 } 48 } 49 // Deduplicate while preserving order 50 $safe = array_values(array_unique($safe)); 51 return implode("','", $safe); 52 } 53 54 function sanitize_ids_csv($ids, bool $allow_zero = false): string { 55 // Normalize $ids to an array 56 if (is_string($ids)) { 57 $ids = explode(',', $ids); 58 } elseif (is_int($ids)) { 59 $ids = [$ids]; 60 } elseif (!is_array($ids)) { 61 $ids = []; 62 } 63 64 $set = []; 65 foreach ($ids as $id) { 66 if (is_int($id)) { 67 $n = $id; 68 } elseif (is_string($id)) { 69 $id = trim($id); 70 if ($id === '' || !ctype_digit($id)) { // digits only 71 continue; 72 } 73 $n = (int) $id; // safe after ctype_digit 74 } else { 75 continue; 76 } 77 78 if ($n > 0 || ($allow_zero && $n === 0)) { 79 $set[$n] = true; // dedupe 80 } 81 } 82 83 if (!$set) { 84 return '0'; // ensures valid "IN (0)" => no matches 85 } 86 87 return implode(',', array_keys($set)); 88 } 89 90 // Sanitize a list of post types (array or CSV string) for safe IN (...) usage 91 function sanitize_post_types_list($post_types) { 92 // Normalize input to array 93 if (is_string($post_types)) { 94 $post_types = explode(',', str_replace(['"', "'"], '', $post_types)); 95 } elseif (!is_array($post_types)) { 96 $post_types = []; 97 } 98 99 // Whitelist of registered post types 100 $registered = array_flip(get_post_types([], 'names')); 101 102 // Sanitize + dedupe 103 $set = []; 104 foreach ($post_types as $pt) { 105 $pt = sanitize_key(trim((string) $pt)); // [a-z0-9_-], lowercased 106 if ($pt === '' || !isset($registered[$pt])) { 107 continue; 108 } 109 $set[$pt] = true; 110 } 111 112 if (!$set) { 113 // If used in a class context that defines $this->types, keep compatibility 114 if (isset($this) && isset($this->types) && is_string($this->types) && $this->types !== '') { 115 return $this->types; 116 } 117 // Safe default: match nothing 118 return "''"; 119 } 120 121 $items = array_keys($set); 122 // sanitize_key already guarantees safe charset; quoting is enough for IN (...) 123 return "'" . implode("','", $items) . "'"; 124 } 125 126 function build_in_from_option_csv(string $base_key, string $option_name): array { 127 $field = (string) get_option($option_name); 128 129 $keys = [$base_key]; 130 if ($field !== '') { 131 foreach (explode(',', $field) as $k) { 132 $k = trim($k); 133 if ($k !== '') 134 $keys[] = $k; 135 } 136 } 137 $keys = array_values(array_unique($keys)); 138 139 $in = implode(',', array_fill(0, count($keys), '%s')); // e.g. ['fifu_isbn','custom1'] -> IN ('fifu_isbn','custom1') 140 return [$in, $keys]; 40 141 } 41 142 … … 45 146 function delete_attachment_meta($ids, $is_ctgr) { 46 147 $ctgr_sql = $is_ctgr ? "AND p.post_name LIKE 'fifu-category%'" : ""; 47 48 $this->wpdb->query(" 148 $ids_csv = $this->sanitize_ids_csv($ids); 149 $author = $this->author; 150 $sql = " 49 151 DELETE pm 50 152 FROM {$this->postmeta} pm JOIN {$this->posts} p ON pm.post_id = p.id 51 153 WHERE pm.meta_key IN ('_wp_attached_file', '_wp_attachment_image_alt', '_wp_attachment_metadata') 52 AND p.post_parent IN ({$ids })53 AND p.post_author = {$this->author}154 AND p.post_parent IN ({$ids_csv}) 155 AND p.post_author = %d 54 156 {$ctgr_sql} 55 "); 157 "; 158 $this->wpdb->query($this->wpdb->prepare($sql, $author)); 56 159 } 57 160 … … 73 176 // has attachment created by FIFU 74 177 function is_fifu_attachment($att_id) { 75 return $this->wpdb->get_row("76 SELECT 177 FROM {$this->posts}78 WHERE id = {$att_id}79 AND post_author = {$this->author}"80 ) != null;178 $sql = $this->wpdb->prepare( 179 "SELECT 1 FROM {$this->posts} WHERE id = %d AND post_author = %d", 180 (int) $att_id, 181 $this->author 182 ); 183 return $this->wpdb->get_row($sql) != null; 81 184 } 82 185 … … 84 187 function get_att_id($post_parent, $url, $is_ctgr) { 85 188 $ctgr_sql = $is_ctgr ? "AND p.post_name LIKE 'fifu-category%'" : ""; 86 $result = $this->wpdb->get_results(" 87 SELECT pm.post_id 88 FROM {$this->postmeta} pm 89 WHERE pm.meta_key = '_wp_attached_file' 90 AND pm.meta_value = '{$url}' 91 AND pm.post_id IN ( 92 SELECT p.id 93 FROM {$this->posts} p 94 WHERE p.post_parent = {$post_parent} 95 AND post_author = {$this->author} 96 {$ctgr_sql} 97 ) 98 LIMIT 1 99 "); 100 return $result ? $result[0]->post_id : null; 189 $sql = $this->wpdb->prepare( 190 "SELECT pm.post_id 191 FROM {$this->postmeta} pm 192 WHERE pm.meta_key = '_wp_attached_file' 193 AND pm.meta_value = %s 194 AND pm.post_id IN ( 195 SELECT p.id 196 FROM {$this->posts} p 197 WHERE p.post_parent = %d 198 AND post_author = %d {$ctgr_sql} 199 ) 200 LIMIT 1", 201 $url, 202 (int) $post_parent, 203 $this->author 204 ); 205 $row = $this->wpdb->get_row($sql); 206 return $row ? (int) $row->post_id : null; 101 207 } 102 208 … … 116 222 117 223 function get_count_wp_posts_fifu() { 118 return $this->wpdb->get_results("119 SELECT COUNT(1) AS amount120 FROM {$this->posts}121 WHERE post_author = {$this->author}122 ");224 $sql = $this->wpdb->prepare( 225 "SELECT COUNT(1) AS amount FROM {$this->posts} WHERE post_author = %d", 226 $this->author 227 ); 228 return $this->wpdb->get_results($sql); 123 229 } 124 230 125 231 function get_count_wp_postmeta_fifu() { 126 return $this->wpdb->get_results("127 SELECT COUNT(1) AS amount128 FROM {$this->postmeta}129 WHERE meta_key = '_wp_attached_file'130 AND EXISTS (131 SELECT 1132 FROM {$this->posts}133 WHERE id = post_id134 AND post_author = {$this->author}135 )136 ");232 $sql = $this->wpdb->prepare( 233 "SELECT COUNT(1) AS amount 234 FROM {$this->postmeta} 235 WHERE meta_key = '_wp_attached_file' 236 AND EXISTS ( 237 SELECT 1 FROM {$this->posts} 238 WHERE id = post_id AND post_author = %d 239 )", 240 $this->author 241 ); 242 return $this->wpdb->get_results($sql); 137 243 } 138 244 … … 142 248 143 249 function debug_slug($slug) { 144 $sql = $this->wpdb->prepare("SELECT ID, post_author, post_content, post_title, post_status, post_parent, post_content_filtered, guid, post_type FROM {$this->posts} WHERE post_name = %s", $slug); 250 $sql = $this->wpdb->prepare( 251 "SELECT ID, post_author, post_content, post_title, post_status, post_parent, post_content_filtered, guid, post_type 252 FROM {$this->posts} 253 WHERE post_name = %s 254 AND post_status <> 'private' 255 AND (post_password = '' OR post_password IS NULL)", 256 $slug 257 ); 145 258 return $this->wpdb->get_results($sql); 146 259 } … … 148 261 function debug_postmeta($post_id) { 149 262 $sql = $this->wpdb->prepare(" 150 SELECT meta_key, meta_value 151 FROM {$this->postmeta} 152 WHERE post_id = %d 153 AND ( 154 meta_key LIKE 'fifu%' 155 OR meta_key IN ('_thumbnail_id', '_wp_attached_file', '_wp_attachment_image_alt', '_product_image_gallery', '_wc_additional_variation_images') 156 )" 263 SELECT pm.meta_key, pm.meta_value 264 FROM {$this->postmeta} pm 265 INNER JOIN {$this->posts} p ON p.ID = pm.post_id 266 WHERE pm.post_id = %d 267 AND p.post_status <> 'private' 268 AND (p.post_password = '' OR p.post_password IS NULL) 269 AND ( 270 pm.meta_key LIKE 'fifu%' 271 OR pm.meta_key IN ('_thumbnail_id', '_wp_attached_file', '_wp_attachment_image_alt', '_product_image_gallery', '_wc_additional_variation_images') 272 )" 157 273 , $post_id); 158 274 return $this->wpdb->get_results($sql); … … 163 279 SELECT post_author, post_content, post_title, post_status, post_parent, post_content_filtered, guid, post_type 164 280 FROM {$this->posts} 165 WHERE id = %d" 281 WHERE id = %d 282 AND post_status <> 'private' 283 AND (post_password = '' OR post_password IS NULL)" 166 284 , $id); 167 285 return $this->wpdb->get_results($sql); … … 169 287 170 288 function debug_metain() { 171 $sql = $this->wpdb->prepare("SELECT * FROM {$this->fifu_meta_in}");172 return $this->wpdb->get_results( $sql);289 // No placeholders here; do not call prepare() 290 return $this->wpdb->get_results("SELECT * FROM {$this->fifu_meta_in}"); 173 291 } 174 292 175 293 function debug_metaout() { 176 $sql = $this->wpdb->prepare("SELECT * FROM {$this->fifu_meta_out}");177 return $this->wpdb->get_results( $sql);294 // No placeholders here; do not call prepare() 295 return $this->wpdb->get_results("SELECT * FROM {$this->fifu_meta_out}"); 178 296 } 179 297 180 298 // count images without dimensions 181 299 function get_count_posts_without_dimensions() { 182 return $this->wpdb->get_results(" 300 $author = $this->author; 301 $sql = $this->wpdb->prepare(" 183 302 SELECT COUNT(1) AS amount 184 303 FROM {$this->posts} p … … 188 307 WHERE p.id = b.post_id AND meta_key = '_wp_attachment_metadata' 189 308 ) 190 AND p.post_author = {$this->author} 191 "); 309 AND p.post_author = %d 310 ", $author); 311 return $this->wpdb->get_results($sql); 192 312 } 193 313 194 314 // count urls with metadata 195 315 function get_count_urls_with_metadata() { 196 return $this->wpdb->get_results(" 316 $author = $this->author; 317 $sql = $this->wpdb->prepare(" 197 318 SELECT COUNT(1) AS amount 198 319 FROM {$this->posts} p 199 WHERE p.post_author = {$this->author} 200 "); 201 } 202 203 // count urls 320 WHERE p.post_author = %d 321 ", $author); 322 return $this->wpdb->get_results($sql); 323 } 324 325 // Count URLs across postmeta and termmeta (no UNION; no meta_value filters; no tm '%list%' filter) 204 326 function get_count_urls() { 205 return $this->wpdb->get_results(" 206 SELECT SUM(id) AS amount 207 FROM ( 208 SELECT count(post_id) AS id 209 FROM {$this->postmeta} pm 210 WHERE pm.meta_key LIKE 'fifu_%' 211 AND pm.meta_key LIKE '%url%' 212 AND pm.meta_key NOT LIKE '%list%' 213 UNION 214 SELECT count(term_id) AS id 215 FROM {$this->termmeta} tm 216 WHERE tm.meta_key LIKE 'fifu_%' 217 AND tm.meta_key LIKE '%url%' 218 ) x 219 "); 327 $sql = " 328 SELECT 329 ( 330 SELECT COUNT(*) 331 FROM {$this->postmeta} AS pm 332 WHERE pm.meta_key LIKE 'fifu!_%' ESCAPE '!' 333 AND pm.meta_key LIKE '%url%' 334 AND pm.meta_key NOT LIKE '%list%' 335 ) + 336 ( 337 SELECT COUNT(*) 338 FROM {$this->termmeta} AS tm 339 WHERE tm.meta_key LIKE 'fifu!_%' ESCAPE '!' 340 AND tm.meta_key LIKE '%url%' 341 ) AS amount 342 "; 343 return (int) $this->wpdb->get_var($sql); 220 344 } 221 345 … … 250 374 // get last (images/videos/sliders) 251 375 function get_last($meta_key) { 252 return $this->wpdb->get_results("253 SELECT p.id, pm.meta_value376 $sql = $this->wpdb->prepare( 377 "SELECT p.id, pm.meta_value 254 378 FROM {$this->posts} p 255 379 INNER JOIN {$this->postmeta} pm ON p.id = pm.post_id 256 WHERE pm.meta_key = '{$meta_key}'380 WHERE pm.meta_key = %s 257 381 ORDER BY p.post_date DESC 258 LIMIT 3 259 "); 382 LIMIT 3", 383 $meta_key 384 ); 385 return $this->wpdb->get_results($sql); 260 386 } 261 387 … … 270 396 } 271 397 272 // get attachments withoutpost398 // get child posts (excluding the featured image) for a given post 273 399 function get_attachments_without_post($post_id) { 274 $ result = $this->wpdb->get_results("275 SELECT GROUP_CONCAT(id) AS ids276 FROM {$this->posts} 277 WHERE p ost_parent = {$post_id}278 AND p ost_author = {$this->author}279 AND p ost_name NOT LIKE 'fifu-category%'400 $sql = $this->wpdb->prepare( 401 "SELECT GROUP_CONCAT(p.ID) AS ids 402 FROM {$this->posts} p 403 WHERE p.post_parent = %d 404 AND p.post_author = %d 405 AND p.post_name NOT LIKE %s 280 406 AND NOT EXISTS ( 281 SELECT 1 282 FROM {$this->postmeta} 283 WHERE post_id = post_parent 284 AND meta_key = '_thumbnail_id' 285 AND meta_value = id 286 ) 287 GROUP BY post_parent 288 "); 289 return $result ? $result[0]->ids : null; 407 SELECT 1 408 FROM {$this->postmeta} pm2 409 WHERE pm2.post_id = p.post_parent 410 AND pm2.meta_key = '_thumbnail_id' 411 AND pm2.meta_value = p.ID 412 )", 413 (int) $post_id, 414 (int) $this->author, 415 'fifu-category%' // no need for %% since it's a %s value 416 ); 417 418 // One row expected; return CSV string or null 419 $ids_csv = $this->wpdb->get_var($sql); 420 return $ids_csv ?: null; 290 421 } 291 422 292 423 function get_ctgr_attachments_without_post($term_id) { 293 $ result = $this->wpdb->get_results("294 SELECT GROUP_CONCAT(id) AS ids295 FROM {$this->posts} 296 WHERE p ost_parent = {$term_id}297 AND p ost_author = {$this->author}298 AND p ost_name LIKE 'fifu-category%'424 $sql = $this->wpdb->prepare( 425 "SELECT GROUP_CONCAT(p.ID) AS ids 426 FROM {$this->posts} p 427 WHERE p.post_parent = %d 428 AND p.post_author = %d 429 AND p.post_name LIKE %s 299 430 AND NOT EXISTS ( 300 SELECT 1 301 FROM {$this->termmeta} 302 WHERE term_id = post_parent 303 AND meta_key = 'thumbnail_id' 304 AND meta_value = id 305 ) 306 GROUP BY post_parent 307 "); 308 return $result ? $result[0]->ids : null; 431 SELECT 1 432 FROM {$this->termmeta} tm 433 WHERE tm.term_id = p.post_parent 434 AND tm.meta_key = 'thumbnail_id' 435 AND tm.meta_value = p.ID 436 )", 437 (int) $term_id, 438 (int) $this->author, 439 'fifu-category%' // pass pattern as a value; no %% needed 440 ); 441 442 $ids_csv = $this->wpdb->get_var($sql); 443 return $ids_csv ?: null; 309 444 } 310 445 311 446 function get_posts_without_featured_image($post_types) { 447 $safe = $this->sanitize_post_types_list($post_types); 312 448 return $this->wpdb->get_results(" 313 449 SELECT id, post_title 314 450 FROM {$this->posts} 315 WHERE post_type IN ( '$post_types')451 WHERE post_type IN ($safe) 316 452 AND post_status = 'publish' 317 453 AND NOT EXISTS ( … … 335 471 336 472 function get_featured_and_gallery_ids($post_id) { 337 return $this->wpdb->get_results("338 SELECT GROUP_CONCAT(meta_value SEPARATOR ',') as 'ids'473 $sql = $this->wpdb->prepare( 474 "SELECT GROUP_CONCAT(meta_value SEPARATOR ',') as 'ids' 339 475 FROM {$this->postmeta} 340 WHERE post_id = {$post_id} 341 AND meta_key IN ('_thumbnail_id') 342 "); 476 WHERE post_id = %d 477 AND meta_key IN ('_thumbnail_id')", 478 (int) $post_id 479 ); 480 return $this->wpdb->get_results($sql); 343 481 } 344 482 … … 353 491 354 492 function delete_attachments($ids) { 355 $this->wpdb->query(" 356 DELETE FROM {$this->posts} 357 WHERE id IN ({$ids}) 358 AND post_author = {$this->author} 359 "); 493 $ids_csv = $this->sanitize_ids_csv($ids); 494 $sql = $this->wpdb->prepare( 495 "DELETE FROM {$this->posts} WHERE id IN ({$ids_csv}) AND post_author = %d", 496 $this->author 497 ); 498 $this->wpdb->query($sql); 360 499 } 361 500 362 501 function delete_attachment_meta_url_and_alt($ids) { 363 $this->wpdb->query(" 364 DELETE FROM {$this->postmeta} 502 $ids_csv = $this->sanitize_ids_csv($ids); 503 $sql = $this->wpdb->prepare( 504 "DELETE FROM {$this->postmeta} 365 505 WHERE meta_key IN ('_wp_attached_file', '_wp_attachment_image_alt', '_wp_attachment_metadata') 366 AND post_id IN ({$ids}) 367 AND EXISTS ( 368 SELECT 1 369 FROM {$this->posts} 370 WHERE id = post_id 371 AND post_author = {$this->author} 372 ) 373 "); 506 AND post_id IN ({$ids_csv}) 507 AND EXISTS (SELECT 1 FROM {$this->posts} WHERE id = post_id AND post_author = %d)", 508 $this->author 509 ); 510 $this->wpdb->query($sql); 374 511 } 375 512 … … 399 536 400 537 function select_option_prefix($prefix) { 401 return $this->wpdb->get_results(" 402 SELECT option_name, option_value 538 if ($prefix === '') 539 return []; // avoid SELECT all 540 $like = $this->wpdb->esc_like($prefix) . '%'; // escape LIKE wildcards safely 541 $sql = $this->wpdb->prepare( 542 "SELECT option_name, option_value 403 543 FROM {$this->options} 404 WHERE option_name LIKE '{$prefix}%' 405 ORDER BY option_name 406 "); 544 WHERE option_name LIKE %s 545 ORDER BY option_name", 546 $like 547 ); 548 return $this->wpdb->get_results($sql); 407 549 } 408 550 409 551 function delete_option_prefix($prefix) { 410 $this->wpdb->query(" 411 DELETE 412 FROM {$this->options} 413 WHERE option_name LIKE '{$prefix}%' 414 "); 552 if ($prefix === '') { 553 return 0; // safety: avoid deleting everything 554 } 555 $like = $this->wpdb->esc_like($prefix) . '%'; // escape % and _ 556 $sql_select = $this->wpdb->prepare( 557 "SELECT option_name FROM {$this->options} WHERE option_name LIKE %s", 558 $like 559 ); 560 $options_to_delete = $this->wpdb->get_col($sql_select); 561 $sql_delete = $this->wpdb->prepare( 562 "DELETE FROM {$this->options} WHERE option_name LIKE %s", 563 $like 564 ); 565 $deleted_count = (int) $this->wpdb->query($sql_delete); 566 // Clear cache for deleted options 567 foreach ($options_to_delete as $option_name) { 568 wp_cache_delete($option_name, 'options'); 569 } 570 return $deleted_count; 415 571 } 416 572 … … 418 574 419 575 function get_all_urls($page, $type, $keyword) { 576 $page = max(0, (int) $page); // Ensure page is non-negative 420 577 $start = $page * 1000; 421 578 422 $filter = ""; 579 // Posts filter 580 $filter_posts = ''; 423 581 if ($keyword) { 582 $like = '%' . $this->wpdb->esc_like($keyword) . '%'; 424 583 if ($type == 'title') 425 $filter = "AND p.post_title LIKE '%{$keyword}%'";584 $filter_posts = $this->wpdb->prepare('AND p.post_title LIKE %s', $like); 426 585 elseif ($type == 'url') 427 $filter = "AND pm.meta_value LIKE '%{$keyword}%'";586 $filter_posts = $this->wpdb->prepare('AND pm.meta_value LIKE %s', $like); 428 587 } 429 588 … … 432 591 SELECT pm.meta_id, pm.post_id, pm.meta_value AS url, pm.meta_key, p.post_name, p.post_title, p.post_date, false AS category, null AS video_url 433 592 FROM {$this->postmeta} pm 434 INNER JOIN {$this->posts} p ON pm.post_id = p.id {$filter }593 INNER JOIN {$this->posts} p ON pm.post_id = p.id {$filter_posts} 435 594 WHERE pm.meta_key = 'fifu_image_url' 436 595 AND pm.meta_value NOT LIKE '%https://cdn.fifu.app/%' … … 440 599 "; 441 600 if (class_exists('WooCommerce')) { 442 $filter = ""; 601 // Terms filter 602 $filter_terms = ''; 443 603 if ($keyword) { 604 $like = '%' . $this->wpdb->esc_like($keyword) . '%'; 444 605 if ($type == 'title') 445 $filter = "AND t.name LIKE '%{$keyword}%'";606 $filter_terms = $this->wpdb->prepare('AND t.name LIKE %s', $like); 446 607 elseif ($type == 'url') 447 $filter = "AND tm.meta_value LIKE '%{$keyword}%'";608 $filter_terms = $this->wpdb->prepare('AND tm.meta_value LIKE %s', $like); 448 609 } 449 610 $sql .= " … … 452 613 SELECT tm.meta_id, tm.term_id AS post_id, tm.meta_value AS url, tm.meta_key, null AS post_name, t.name AS post_title, null AS post_date, true AS category, null AS video_url 453 614 FROM {$this->termmeta} tm 454 INNER JOIN {$this->terms} t ON tm.term_id = t.term_id {$filter }615 INNER JOIN {$this->terms} t ON tm.term_id = t.term_id {$filter_terms} 455 616 WHERE tm.meta_key IN ('fifu_image_url') 456 617 AND tm.meta_value NOT LIKE '%https://cdn.fifu.app/%' … … 495 656 496 657 function get_posts_with_internal_featured_image($page, $type, $keyword) { 497 $start = $page* 1000;658 $start = max(0, (int) $page) * 1000; 498 659 499 660 $filter = ""; 500 661 if ($keyword) { 501 if ($type == 'title') 502 $filter = "AND p.post_title LIKE '%{$keyword}%'"; 503 elseif ($type == 'postid') 504 $filter = "AND pm.post_id = {$keyword}"; 505 } 662 if ($type == 'title') { 663 $like = '%' . $this->wpdb->esc_like($keyword) . '%'; 664 $filter = $this->wpdb->prepare('AND p.post_title LIKE %s', $like); 665 } elseif ($type == 'postid') { 666 $filter = $this->wpdb->prepare('AND pm.post_id = %d', (int) $keyword); 667 } 668 } 669 670 // Prepare author filter fragments once to avoid preparing the whole query later 671 $author_clause_posts = $this->wpdb->prepare('AND att.post_author <> %d', $this->author); 672 $author_clause_terms = $author_clause_posts; 506 673 507 674 $sql = " … … 521 688 pm.meta_key = '_thumbnail_id' 522 689 AND pm.meta_value = att.id 523 AND att.post_author <> {$this->author}690 {$author_clause_posts} 524 691 ) 525 692 WHERE NOT EXISTS ( … … 541 708 $filter = ""; 542 709 if ($keyword) { 543 if ($type == 'title') 544 $filter = "AND t.name LIKE '%{$keyword}%'"; 545 elseif ($type == 'postid') 546 $filter = "AND tm.term_id = {$keyword}"; 710 if ($type == 'title') { 711 $like = '%' . $this->wpdb->esc_like($keyword) . '%'; 712 $filter = $this->wpdb->prepare('AND t.name LIKE %s', $like); 713 } elseif ($type == 'postid') { 714 $filter = $this->wpdb->prepare('AND tm.term_id = %d', (int) $keyword); 715 } 547 716 } 548 717 $sql .= " … … 563 732 tm.meta_key = 'thumbnail_id' 564 733 AND tm.meta_value = att.id 565 AND att.post_author <> {$this->author}734 {$author_clause_terms} 566 735 ) 567 736 WHERE NOT EXISTS ( … … 582 751 583 752 function get_posts_su($storage_ids) { 584 if ($storage_ids) { 585 $storage_ids = '"' . implode('","', $storage_ids) . '"'; 586 $filter_post_image = "AND SUBSTRING_INDEX(SUBSTRING_INDEX(pm.meta_value, '/', 5), '/', -1) IN ({$storage_ids})"; 587 $filter_term_image = "AND SUBSTRING_INDEX(SUBSTRING_INDEX(tm.meta_value, '/', 5), '/', -1) IN ({$storage_ids})"; 588 } else 753 if (!empty($storage_ids)) { 754 // normalize and drop empties 755 $ids = array_values(array_filter(array_map('strval', (array) $storage_ids), static fn($v) => $v !== '')); 756 if ($ids) { 757 $in = implode(',', array_fill(0, count($ids), '%s')); 758 $filter_post_image = $this->wpdb->prepare( 759 "AND SUBSTRING_INDEX(SUBSTRING_INDEX(pm.meta_value, '/', 5), '/', -1) IN ($in)", $ids 760 ); 761 $filter_term_image = $this->wpdb->prepare( 762 "AND SUBSTRING_INDEX(SUBSTRING_INDEX(tm.meta_value, '/', 5), '/', -1) IN ($in)", $ids 763 ); 764 } else { 765 $filter_post_image = $filter_term_image = ""; 766 } 767 } else { 589 768 $filter_post_image = $filter_term_image = ""; 769 } 590 770 591 771 $sql = " … … 601 781 INNER JOIN {$this->posts} p ON pm.post_id = p.id 602 782 WHERE pm.meta_key LIKE 'fifu_%image_url%' 603 AND pm.meta_value LIKE 'https://cdn.fifu.app/%' " .604 $filter_post_image . "783 AND pm.meta_value LIKE 'https://cdn.fifu.app/%' 784 {$filter_post_image} 605 785 ) 606 786 "; 607 787 if (class_exists('WooCommerce')) { 608 $sql .= " 788 $sql .= " 609 789 UNION 610 790 ( 611 791 SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(tm.meta_value, '/', 5), '/', -1) AS storage_id, 612 792 t.name AS post_title, 613 nullAS post_date,793 NULL AS post_date, 614 794 tm.meta_id, 615 795 tm.term_id AS post_id, … … 619 799 INNER JOIN {$this->terms} t ON tm.term_id = t.term_id 620 800 WHERE tm.meta_key = 'fifu_image_url' 621 AND tm.meta_value LIKE 'https://cdn.fifu.app/%' " .622 $filter_term_image . "801 AND tm.meta_value LIKE 'https://cdn.fifu.app/%' 802 {$filter_term_image} 623 803 ) 624 804 "; 625 805 } 806 626 807 return $this->wpdb->get_results($sql); 627 808 } … … 679 860 $table = $is_ctgr ? $this->termmeta : $this->postmeta; 680 861 681 $ query = "682 INSERT INTO {$table} (meta_id, meta_value) VALUES ";683 $count = 0; 862 $values = []; 863 $args = []; 864 684 865 foreach ($thumbnails as $thumbnail) { 685 866 $su_url = $this->get_su_url($bucket_id, $thumbnail->storage_id); 686 867 687 if ($count++ != 0) 688 $query .= ", "; 689 $query .= "({$thumbnail->meta_id},'{$su_url}') "; 690 } 691 $query .= "ON DUPLICATE KEY UPDATE meta_value=VALUES(meta_value)"; 692 return $this->wpdb->get_results($query); 868 $values[] = '(%d,%s)'; 869 $args[] = (int) $thumbnail->meta_id; 870 $args[] = $su_url; 871 } 872 873 if (!$values) 874 return 0; 875 876 $query = " 877 INSERT INTO {$table} (meta_id, meta_value) 878 VALUES " . implode(', ', $values) . " 879 ON DUPLICATE KEY UPDATE meta_value = VALUES(meta_value) 880 "; 881 882 return $this->wpdb->query($this->wpdb->prepare($query, $args)); 693 883 } 694 884 695 885 function get_thumbnail_ids($thumbnails, $is_ctgr) { 696 // join post_ids 697 $i = 0; 698 $ids = null; 886 // join post_ids (sanitized) 887 $ids_list = array(); 699 888 foreach ($thumbnails as $thumbnail) 700 $ids = ($i++ == 0) ? $thumbnail->post_id : ($ids . "," . $thumbnail->post_id); 889 $ids_list[] = (int) $thumbnail->post_id; 890 $ids = $this->sanitize_ids_csv($ids_list); 701 891 702 892 // get featured ids … … 746 936 if ($count++ != 0) 747 937 $query .= ", "; 748 $query .= "(" . $att_ids_map[$thumbnail->meta_id] . ",'{$su_url}')";938 $query .= $this->wpdb->prepare("(%d, %s)", $att_ids_map[$thumbnail->meta_id], $su_url) . " "; 749 939 } 750 940 $query .= "ON DUPLICATE KEY UPDATE post_content_filtered=VALUES(post_content_filtered)"; … … 753 943 754 944 function get_thumbnail_meta_ids($thumbnails, $att_ids_map) { 755 // join post_ids 756 $i = 0; 757 $ids = null; 945 // Collect distinct numeric attachment post_ids 946 $ids_arr = array(); 758 947 foreach ($thumbnails as $thumbnail) { 759 948 if (!isset($att_ids_map[$thumbnail->meta_id])) // no metadata, only custom field 760 949 continue; 761 $ids = ($i++ == 0) ? $att_ids_map[$thumbnail->meta_id] : ($ids . "," . $att_ids_map[$thumbnail->meta_id]); 762 } 763 764 // get meta ids 765 $result = $this->wpdb->get_results(" 950 $ids_arr[] = (int) $att_ids_map[$thumbnail->meta_id]; 951 } 952 $ids_arr = array_values(array_unique(array_filter($ids_arr, function ($v) { 953 return $v > 0; 954 }))); 955 956 // No IDs -> nothing to query 957 if (empty($ids_arr)) { 958 return array(); 959 } 960 961 // Build prepared IN(...) and run the safe query 962 $placeholders = implode(',', array_fill(0, count($ids_arr), '%d')); 963 $sql = " 766 964 SELECT meta_id, post_id 767 FROM {$this->postmeta} 768 WHERE post_id IN ({$ids}) 769 AND meta_key = '_wp_attached_file' 770 "); 965 FROM {$this->postmeta} 966 WHERE post_id IN ($placeholders) 967 AND meta_key = %s 968 "; 969 $params = array_merge($ids_arr, array('_wp_attached_file')); 970 $result = $this->wpdb->get_results($this->wpdb->prepare($sql, $params)); 771 971 772 972 // map att_id -> meta_id 773 973 $attid_metaid_map = array(); 774 foreach ($result as $res) 974 foreach ($result as $res) { 775 975 $attid_metaid_map[$res->post_id] = $res->meta_id; 776 777 // map meta_id (fifu metadata) -> meta_id (atachment metadata) 976 } 977 978 // map meta_id (fifu metadata) -> meta_id (attachment metadata) 778 979 $map = array(); 779 980 foreach ($thumbnails as $thumbnail) { 780 981 if (!isset($att_ids_map[$thumbnail->meta_id])) // no metadata, only custom field 781 982 continue; 782 if (!isset($attid_metaid_map[$att_ids_map[$thumbnail->meta_id]])) // no metadata, only custom field 983 $att_id = (int) $att_ids_map[$thumbnail->meta_id]; 984 if (!isset($attid_metaid_map[$att_id])) // no attachment metadata 783 985 continue; 784 $ att_meta_id = $attid_metaid_map[$att_ids_map[$thumbnail->meta_id]];785 $map[$thumbnail->meta_id] = $att_meta_id;786 } 986 $map[$thumbnail->meta_id] = $attid_metaid_map[$att_id]; 987 } 988 787 989 return $map; 788 990 } … … 792 994 $query = " 793 995 INSERT INTO {$this->postmeta} (meta_id, meta_value) VALUES "; 996 794 997 foreach ($thumbnails as $thumbnail) { 795 998 if (!isset($meta_ids_map[$thumbnail->meta_id])) // no metadata, only custom field … … 800 1003 if ($count++ != 0) 801 1004 $query .= ", "; 802 $query .= "(" . $meta_ids_map[$thumbnail->meta_id] . ",'{$su_url}') "; 803 } 1005 1006 // Minimal change: use prepare to safely build each VALUES tuple 1007 $query .= $this->wpdb->prepare("(%d, %s)", $meta_ids_map[$thumbnail->meta_id], $su_url) . " "; 1008 } 1009 804 1010 $query .= "ON DUPLICATE KEY UPDATE meta_value=VALUES(meta_value)"; 805 1011 return $this->wpdb->get_results($query); … … 908 1114 $table = $is_ctgr ? $this->termmeta : $this->postmeta; 909 1115 1116 // Return early if no thumbnails to process 1117 if (empty($thumbnails)) { 1118 return null; 1119 } 1120 910 1121 $query = " 911 1122 INSERT INTO {$table} (meta_id, meta_value) VALUES "; 912 1123 $count = 0; 1124 913 1125 foreach ($thumbnails as $thumbnail) { 914 if ($count++ != 0) 1126 if ($count++ != 0) { 915 1127 $query .= ", "; 916 $url = $urls[$thumbnail->storage_id]; 917 $query .= "({$thumbnail->meta_id},'{$url}')"; 918 } 919 $query .= "ON DUPLICATE KEY UPDATE meta_value=VALUES(meta_value)"; 1128 } 1129 1130 $url = (isset($urls[$thumbnail->storage_id]) ? $urls[$thumbnail->storage_id] : ''); 1131 1132 // Minimal change: build each VALUES tuple with prepare to avoid SQL injection 1133 $query .= $this->wpdb->prepare("(%d, %s)", (int) $thumbnail->meta_id, $url); 1134 } 1135 1136 $query .= " ON DUPLICATE KEY UPDATE meta_value=VALUES(meta_value)"; 920 1137 return $this->wpdb->get_results($query); 921 1138 } 922 1139 923 1140 function revert_attachments($urls, $thumbnails, $att_ids_map) { 1141 // Handle null or invalid parameters 1142 if ($urls === null || !is_array($urls)) 1143 $urls = []; 1144 if ($thumbnails === null || !is_array($thumbnails)) 1145 $thumbnails = []; 1146 if ($att_ids_map === null || !is_array($att_ids_map)) 1147 $att_ids_map = []; 1148 924 1149 $count = 0; 925 1150 $query = " 926 1151 INSERT INTO {$this->posts} (id, post_content_filtered) VALUES "; 1152 927 1153 foreach ($thumbnails as $thumbnail) { 928 1154 if (!isset($att_ids_map[$thumbnail->meta_id])) // no metadata, only custom field 929 1155 continue; 1156 930 1157 if ($count++ != 0) 931 1158 $query .= ", "; 932 $query .= "(" . $att_ids_map[$thumbnail->meta_id] . ",'" . $urls[$thumbnail->storage_id] . "')"; 933 } 1159 1160 $url = isset($urls[$thumbnail->storage_id]) ? $urls[$thumbnail->storage_id] : ''; 1161 1162 // Minimal change: use prepare to safely build each VALUES tuple 1163 $query .= $this->wpdb->prepare("(%d, %s)", (int) $att_ids_map[$thumbnail->meta_id], $url); 1164 } 1165 1166 // If no thumbnails were processed, return early 1167 if ($count == 0) { 1168 return array(); // Return empty array instead of running invalid query 1169 } 1170 934 1171 $query .= "ON DUPLICATE KEY UPDATE post_content_filtered=VALUES(post_content_filtered)"; 935 1172 return $this->wpdb->get_results($query); … … 940 1177 $query = " 941 1178 INSERT INTO {$this->postmeta} (meta_id, meta_value) VALUES "; 1179 942 1180 foreach ($thumbnails as $thumbnail) { 943 1181 if (!isset($meta_ids_map[$thumbnail->meta_id])) // no metadata, only custom field 944 1182 continue; 1183 945 1184 if ($count++ != 0) 946 1185 $query .= ", "; 947 $query .= "(" . $meta_ids_map[$thumbnail->meta_id] . ",'" . $urls[$thumbnail->storage_id] . "')"; 948 } 949 $query .= "ON DUPLICATE KEY UPDATE meta_value=VALUES(meta_value)"; 950 return $this->wpdb->get_results($query); 1186 1187 $url = isset($urls[$thumbnail->storage_id]) ? $urls[$thumbnail->storage_id] : ''; 1188 1189 // Minimal change: safely build each VALUES tuple 1190 $query .= $this->wpdb->prepare("(%d, %s)", (int) $meta_ids_map[$thumbnail->meta_id], $url); 1191 } 1192 1193 // Only execute query if there are valid operations to perform 1194 if ($count > 0) { 1195 $query .= "ON DUPLICATE KEY UPDATE meta_value=VALUES(meta_value)"; 1196 return $this->wpdb->get_results($query); 1197 } 1198 1199 // Return empty array if no valid operations were found 1200 return array(); 951 1201 } 952 1202 … … 966 1216 967 1217 function insert_invalid_media_su($url) { 1218 if ($url === null || $url === '') 1219 return; 968 1220 if ($this->get_attempts_invalid_media_su($url)) { 969 1221 $this->update_invalid_media_su($url); … … 972 1224 973 1225 $md5 = md5($url); 974 $this->wpdb->query(" 975 INSERT INTO {$this->fifu_invalid_media_su} (md5, attempts) 976 VALUES ('{$md5}', 1) 977 "); 1226 $this->wpdb->query( 1227 $this->wpdb->prepare( 1228 "INSERT INTO {$this->fifu_invalid_media_su} (md5, attempts) VALUES (%s, 1)", 1229 $md5 1230 ) 1231 ); 978 1232 } 979 1233 980 1234 function update_invalid_media_su($url) { 1235 if ($url === null || $url === '') 1236 return; 981 1237 $md5 = md5($url); 982 $this->wpdb->query(" 983 UPDATE {$this->fifu_invalid_media_su} 984 SET attempts = attempts + 1 985 WHERE md5 = '{$md5}' 986 "); 1238 $this->wpdb->query( 1239 $this->wpdb->prepare( 1240 "UPDATE {$this->fifu_invalid_media_su} SET attempts = attempts + 1 WHERE md5 = %s", 1241 $md5 1242 ) 1243 ); 987 1244 } 988 1245 989 1246 function get_attempts_invalid_media_su($url) { 1247 if ($url === null || $url === '') 1248 return 0; 990 1249 $md5 = md5($url); 991 $result = $this->wpdb->get_row(" 992 SELECT attempts 993 FROM {$this->fifu_invalid_media_su} 994 WHERE md5 = '{$md5}' 995 "); 1250 $result = $this->wpdb->get_row( 1251 $this->wpdb->prepare( 1252 "SELECT attempts FROM {$this->fifu_invalid_media_su} WHERE md5 = %s", 1253 $md5 1254 ) 1255 ); 996 1256 return $result ? (int) $result->attempts : 0; 997 1257 } 998 1258 999 1259 function delete_invalid_media_su($url) { 1260 if ($url === null || $url === '') 1261 return; 1000 1262 $md5 = md5($url); 1001 $this->wpdb->query(" 1002 DELETE FROM {$this->fifu_invalid_media_su} 1003 WHERE md5 = '{$md5}' 1004 "); 1263 $this->wpdb->query( 1264 $this->wpdb->prepare( 1265 "DELETE FROM {$this->fifu_invalid_media_su} WHERE md5 = %s", 1266 $md5 1267 ) 1268 ); 1005 1269 } 1006 1270 … … 1042 1306 1043 1307 function insert_attachment_by($value) { 1044 $this->wpdb->query(" 1045 INSERT INTO {$this->posts} (post_author, guid, post_title, post_excerpt, post_mime_type, post_type, post_status, post_parent, post_date, post_date_gmt, post_modified, post_modified_gmt, post_content, to_ping, pinged, post_content_filtered) 1046 VALUES " . str_replace('\\', '', $value)); 1308 // $value should be a list of PREPARED tuples (e.g., from get_formatted_value), joined by ', ' 1309 $values_sql = is_array($value) ? implode(', ', $value) : (string) $value; 1310 1311 $sql = " 1312 INSERT INTO {$this->posts} 1313 (post_author, guid, post_title, post_excerpt, post_mime_type, post_type, post_status, post_parent, 1314 post_date, post_date_gmt, post_modified, post_modified_gmt, post_content, to_ping, pinged, post_content_filtered) 1315 VALUES {$values_sql}"; 1316 return $this->wpdb->query($sql); 1047 1317 } 1048 1318 1049 1319 function insert_ctgr_attachment_by($value) { 1050 $this->wpdb->query(" 1051 INSERT INTO {$this->posts} (post_author, guid, post_title, post_excerpt, post_mime_type, post_type, post_status, post_parent, post_date, post_date_gmt, post_modified, post_modified_gmt, post_content, to_ping, pinged, post_content_filtered, post_name) 1052 VALUES " . str_replace('\\', '', $value)); 1320 // $value should be a list of PREPARED tuples (e.g., from get_ctgr_formatted_value), joined by ', ' 1321 $values_sql = is_array($value) ? implode(', ', $value) : (string) $value; 1322 1323 $sql = " 1324 INSERT INTO {$this->posts} 1325 (post_author, guid, post_title, post_excerpt, post_mime_type, post_type, post_status, post_parent, 1326 post_date, post_date_gmt, post_modified, post_modified_gmt, post_content, to_ping, pinged, post_content_filtered, post_name) 1327 VALUES {$values_sql}"; 1328 return $this->wpdb->query($sql); 1053 1329 } 1054 1330 1055 1331 function get_formatted_value($url, $alt, $post_parent) { 1056 1332 $alt = $alt ?? ''; 1057 $alt = str_replace("'", "", $alt); 1058 return "({$this->author}, '', '{$alt}', '{$alt}', 'image/jpeg', 'attachment', 'inherit', '{$post_parent}', now(), now(), now(), now(), '', '', '', '{$url}')"; 1333 // Return a PREPARED tuple; caller concatenates multiple with ", " 1334 return $this->wpdb->prepare( 1335 "(%d, %s, %s, %s, %s, %s, %s, %d, NOW(), NOW(), NOW(), NOW(), %s, %s, %s, %s)", 1336 (int) $this->author, // post_author 1337 '', // guid 1338 $alt, // post_title 1339 $alt, // post_excerpt 1340 'image/jpeg', // post_mime_type 1341 'attachment', // post_type 1342 'inherit', // post_status 1343 (int) $post_parent, // post_parent 1344 '', // post_content 1345 '', // to_ping 1346 '', // pinged 1347 $url // post_content_filtered 1348 ); 1059 1349 } 1060 1350 1061 1351 function get_ctgr_formatted_value($url, $alt, $post_parent) { 1062 1352 $alt = $alt ?? ''; 1063 $alt = str_replace("'", "", $alt); 1064 return "({$this->author}, '', '{$alt}', '{$alt}', 'image/jpeg', 'attachment', 'inherit', '{$post_parent}', now(), now(), now(), now(), '', '', '', '{$url}', 'fifu-category-{$post_parent}')"; 1353 // Return a PREPARED tuple; caller concatenates multiple with ", " 1354 return $this->wpdb->prepare( 1355 "(%d, %s, %s, %s, %s, %s, %s, %d, NOW(), NOW(), NOW(), NOW(), %s, %s, %s, %s, %s)", 1356 (int) $this->author, // post_author 1357 '', // guid 1358 $alt, // post_title 1359 $alt, // post_excerpt 1360 'image/jpeg', // post_mime_type 1361 'attachment', // post_type 1362 'inherit', // post_status 1363 (int) $post_parent, // post_parent 1364 '', // post_content 1365 '', // to_ping 1366 '', // pinged 1367 $url, // post_content_filtered 1368 'fifu-category-' . (int) $post_parent// post_name 1369 ); 1065 1370 } 1066 1371 … … 1068 1373 1069 1374 function clean_dimensions_all() { 1070 $this->wpdb->query(" 1071 DELETE FROM {$this->postmeta} pm 1072 WHERE pm.meta_key = '_wp_attachment_metadata' 1375 // Ensure author ID is numeric 1376 $author_id = (int) $this->author; 1377 1378 // Build a prepared statement with placeholders 1379 $query = $this->wpdb->prepare( 1380 " 1381 DELETE FROM {$this->postmeta} pm 1382 WHERE pm.meta_key = %s 1073 1383 AND EXISTS ( 1074 SELECT 1 1075 FROM {$this->posts} p 1384 SELECT 1 1385 FROM {$this->posts} p 1076 1386 WHERE p.id = pm.post_id 1077 AND p.post_author = {$this->author}1387 AND p.post_author = %d 1078 1388 ) 1079 "); 1389 ", 1390 '_wp_attachment_metadata', // %s placeholder for meta_key 1391 $author_id // %d placeholder for author 1392 ); 1393 1394 // Execute the prepared query 1395 $this->wpdb->query($query); 1080 1396 } 1081 1397 … … 1183 1499 1184 1500 function set_default_url() { 1185 $att_id = get_option('fifu_default_attach_id');1501 $att_id = (int) get_option('fifu_default_attach_id'); 1186 1502 if (!$att_id) 1187 1503 return; 1188 $post_types = join("','", explode(',', str_replace(' ', '', get_option('fifu_default_cpt')))); 1189 $post_types ? $post_types : $this->types; 1190 $value = null; 1191 foreach ($this->get_posts_without_featured_image($post_types) as $res) { 1192 $aux = "({$res->id}, '_thumbnail_id', {$att_id})"; 1193 $value = $value ? $value . ',' . $aux : $aux; 1194 } 1195 if ($value) { 1196 $this->insert_default_thumbnail_id($value); 1197 update_post_meta($att_id, '_wp_attached_file', get_option('fifu_default_url')); 1504 1505 $post_types_csv = $this->sanitize_post_types_list((string) get_option('fifu_default_cpt')); 1506 1507 $tuples = []; 1508 foreach ($this->get_posts_without_featured_image($post_types_csv) as $res) { 1509 // (%d, %s, %d) -> (post_id, meta_key, meta_value) 1510 $tuples[] = $this->wpdb->prepare("(%d, %s, %d)", (int) $res->id, '_thumbnail_id', $att_id); 1511 } 1512 1513 if ($tuples) { 1514 $this->insert_default_thumbnail_id(implode(',', $tuples)); 1515 update_post_meta($att_id, '_wp_attached_file', (string) get_option('fifu_default_url')); 1198 1516 } 1199 1517 } 1200 1518 1201 1519 function update_default_url($url) { 1202 $att_id = get_option('fifu_default_attach_id');1520 $att_id = (int) get_option('fifu_default_attach_id'); 1203 1521 if ($url != wp_get_attachment_url($att_id)) { 1204 1522 $this->wpdb->update($this->posts, $set = array('post_content_filtered' => $url), $where = array('id' => $att_id), null, null); … … 1208 1526 1209 1527 function delete_default_url() { 1210 $att_id = get_option('fifu_default_attach_id');1528 $att_id = (int) get_option('fifu_default_attach_id'); 1211 1529 wp_delete_attachment($att_id); 1212 1530 delete_option('fifu_default_attach_id'); … … 1218 1536 function before_delete_post($post_id) { 1219 1537 $default_url_enabled = fifu_is_on('fifu_enable_default_url'); 1220 $default_att_id = $default_url_enabled ? get_option('fifu_default_attach_id') : null;1538 $default_att_id = $default_url_enabled ? (int) get_option('fifu_default_attach_id') : null; 1221 1539 $result = $this->get_featured_and_gallery_ids($post_id); 1222 1540 if ($result) { … … 1388 1706 $this->wpdb->query("SET SESSION group_concat_max_len = 1048576;"); // because GROUP_CONCAT is limited to 1024 characters 1389 1707 1390 $ this->wpdb->query("1708 $sql = " 1391 1709 INSERT INTO {$this->fifu_meta_out} (post_ids, type) 1392 1710 SELECT GROUP_CONCAT(DISTINCT id ORDER BY id SEPARATOR ','), 'att' 1393 1711 FROM {$this->posts} 1394 WHERE post_author = {$this->author}1712 WHERE post_author = %d 1395 1713 GROUP BY FLOOR(id / 5000) 1396 "); 1714 "; 1715 $this->wpdb->query($this->wpdb->prepare($sql, $this->author)); 1397 1716 1398 1717 $last_insert_id = $this->wpdb->insert_id; … … 1482 1801 1483 1802 function log_prepare($last_insert_id, $table) { 1484 $inserted_records = $this->wpdb->get_results(" 1485 SELECT id, post_ids, type 1486 FROM {$table} 1487 WHERE id = {$last_insert_id} 1488 "); 1803 $inserted_records = $this->wpdb->get_results( 1804 $this->wpdb->prepare( 1805 "SELECT id, post_ids, type FROM {$table} WHERE id = %d", 1806 (int) $last_insert_id 1807 ) 1808 ); 1489 1809 1490 1810 foreach ($inserted_records as $record) { … … 1508 1828 1509 1829 function insert_postmeta($id) { 1510 $result = $this->wpdb->get_results(" 1511 SELECT post_ids 1512 FROM {$this->fifu_meta_in} 1513 WHERE id = {$id} 1514 "); 1515 1516 $this->wpdb->query(" 1517 DELETE FROM {$this->fifu_meta_in} 1518 WHERE id = {$id} 1519 "); 1830 $result = $this->wpdb->get_results( 1831 $this->wpdb->prepare( 1832 "SELECT post_ids FROM {$this->fifu_meta_in} WHERE id = %d", 1833 (int) $id 1834 ) 1835 ); 1836 1837 $this->wpdb->query( 1838 $this->wpdb->prepare( 1839 "DELETE FROM {$this->fifu_meta_in} WHERE id = %d", 1840 (int) $id 1841 ) 1842 ); 1520 1843 1521 1844 if (count($result) == 0) … … 1542 1865 1543 1866 function delete_attmeta($id) { 1544 $result = $this->wpdb->get_results(" 1545 SELECT post_ids 1546 FROM {$this->fifu_meta_out} 1547 WHERE id = {$id} 1548 "); 1549 1550 $this->wpdb->query(" 1551 DELETE FROM {$this->fifu_meta_out} 1552 WHERE id = {$id} 1553 "); 1867 $result = $this->wpdb->get_results( 1868 $this->wpdb->prepare( 1869 "SELECT post_ids FROM {$this->fifu_meta_out} WHERE id = %d", 1870 (int) $id 1871 ) 1872 ); 1873 1874 $this->wpdb->query( 1875 $this->wpdb->prepare( 1876 "DELETE FROM {$this->fifu_meta_out} WHERE id = %d", 1877 (int) $id 1878 ) 1879 ); 1554 1880 1555 1881 if (count($result) == 0) … … 1569 1895 wp_cache_flush(); 1570 1896 1897 // Cast option-derived IDs to integers to avoid SQL injection 1898 $fake_attach_id = (int) get_option('fifu_fake_attach_id'); 1899 $default_attach_id = (int) get_option('fifu_default_attach_id'); 1900 1571 1901 $this->wpdb->query('START TRANSACTION'); 1572 1902 1573 1903 try { 1574 $fake_attach_id = get_option('fifu_fake_attach_id');1575 1904 $fake_attach_sql = $fake_attach_id ? "OR meta_value = {$fake_attach_id}" : ""; 1576 1577 $default_attach_id = get_option('fifu_default_attach_id');1578 1905 $default_attach_sql = $default_attach_id ? "OR meta_value = {$default_attach_id}" : ""; 1579 1906 … … 1670 1997 1671 1998 function delete_termmeta($id) { 1672 $result = $this->wpdb->get_results(" 1673 SELECT post_ids 1674 FROM {$this->fifu_meta_out} 1675 WHERE id = {$id} 1676 "); 1677 1678 $this->wpdb->query(" 1679 DELETE FROM {$this->fifu_meta_out} 1680 WHERE id = {$id} 1681 "); 1999 $result = $this->wpdb->get_results( 2000 $this->wpdb->prepare( 2001 "SELECT post_ids FROM {$this->fifu_meta_out} WHERE id = %d", 2002 (int) $id 2003 ) 2004 ); 2005 2006 $this->wpdb->query( 2007 $this->wpdb->prepare( 2008 "DELETE FROM {$this->fifu_meta_out} WHERE id = %d", 2009 (int) $id 2010 ) 2011 ); 1682 2012 1683 2013 if (count($result) == 0) … … 1696 2026 function insert_postmeta2($value, $ids) { 1697 2027 $this->wpdb->query('START TRANSACTION'); 2028 $ids_csv = $this->sanitize_ids_csv($ids); 1698 2029 1699 2030 try { 1700 $this->wpdb->query(" 1701 INSERT INTO {$this->posts} (post_author, guid, post_title, post_excerpt, post_mime_type, post_type, post_status, post_parent, post_date, post_date_gmt, post_modified, post_modified_gmt, post_content, to_ping, pinged, post_content_filtered) 1702 VALUES " . str_replace('\\', '', $value)); 1703 1704 $this->wpdb->query(" 2031 $this->wpdb->query( 2032 "INSERT INTO {$this->posts} (post_author, guid, post_title, post_excerpt, post_mime_type, post_type, post_status, post_parent, post_date, post_date_gmt, post_modified, post_modified_gmt, post_content, to_ping, pinged, post_content_filtered) 2033 VALUES " . $value 2034 ); 2035 2036 $author = $this->author; 2037 $sql_thumb = $this->wpdb->prepare(" 1705 2038 INSERT INTO {$this->postmeta} (post_id, meta_key, meta_value) ( 1706 2039 SELECT p.post_parent, '_thumbnail_id', p.id 1707 2040 FROM {$this->posts} p 1708 WHERE p.post_parent IN ({$ids}) 1709 AND p.post_author = {$this->author} 1710 ) 1711 "); 1712 1713 $this->wpdb->query(" 2041 WHERE p.post_parent IN ({$ids_csv}) 2042 AND p.post_author = %d 2043 ) 2044 ", $author); 2045 $this->wpdb->query($sql_thumb); 2046 2047 $sql_file = $this->wpdb->prepare(" 1714 2048 INSERT INTO {$this->postmeta} (post_id, meta_key, meta_value) ( 1715 2049 SELECT p.id, '_wp_attached_file', p.post_content_filtered 1716 2050 FROM {$this->posts} p 1717 WHERE p.post_parent IN ({$ids}) 1718 AND p.post_author = {$this->author} 1719 ) 1720 "); 1721 1722 $this->wpdb->query(" 2051 WHERE p.post_parent IN ({$ids_csv}) 2052 AND p.post_author = %d 2053 ) 2054 ", $author); 2055 $this->wpdb->query($sql_file); 2056 2057 $sql_alt = $this->wpdb->prepare(" 1723 2058 INSERT INTO {$this->postmeta} (post_id, meta_key, meta_value) ( 1724 2059 SELECT p.id, '_wp_attachment_image_alt', p.post_title 1725 2060 FROM {$this->posts} p 1726 WHERE p.post_parent IN ({$ids })1727 AND p.post_author = {$this->author}2061 WHERE p.post_parent IN ({$ids_csv}) 2062 AND p.post_author = %d 1728 2063 AND p.post_title IS NOT NULL 1729 2064 AND p.post_title != '' 1730 2065 ) 1731 "); 2066 ", $author); 2067 $this->wpdb->query($sql_alt); 1732 2068 1733 2069 $this->wpdb->query('COMMIT'); … … 1739 2075 function delete_attmeta2($ids) { 1740 2076 $this->wpdb->query('START TRANSACTION'); 2077 $ids_csv = $this->sanitize_ids_csv($ids); 1741 2078 1742 2079 try { … … 1744 2081 DELETE FROM {$this->postmeta} 1745 2082 WHERE meta_key = '_thumbnail_id' 1746 AND meta_value IN (0, {$ids })2083 AND meta_value IN (0, {$ids_csv}) 1747 2084 "); 1748 2085 1749 $this->wpdb->query(" 2086 $author = $this->author; 2087 $sql_del_posts = $this->wpdb->prepare(" 1750 2088 DELETE FROM {$this->posts} 1751 WHERE id IN ({$ids}) 1752 AND post_author = {$this->author} 1753 "); 2089 WHERE id IN ({$ids_csv}) 2090 AND post_author = %d 2091 ", $author); 2092 $this->wpdb->query($sql_del_posts); 1754 2093 1755 2094 $this->wpdb->query(" 1756 2095 DELETE FROM {$this->postmeta} 1757 2096 WHERE meta_key IN ('_wp_attached_file', '_wp_attachment_image_alt', '_wp_attachment_metadata') 1758 AND post_id IN ({$ids })2097 AND post_id IN ({$ids_csv}) 1759 2098 "); 1760 2099 … … 1767 2106 function delete_termmeta2($ids) { 1768 2107 $this->wpdb->query('START TRANSACTION'); 2108 $ids_csv = $this->sanitize_ids_csv($ids); 1769 2109 1770 2110 try { … … 1772 2112 DELETE FROM {$this->termmeta} 1773 2113 WHERE meta_key = 'thumbnail_id' 1774 AND term_id IN ({$ids })2114 AND term_id IN ({$ids_csv}) 1775 2115 "); 1776 2116 1777 $this->wpdb->query(" 2117 $author = $this->author; 2118 $sql_del_pm = $this->wpdb->prepare(" 1778 2119 DELETE pm 1779 2120 FROM {$this->postmeta} pm JOIN {$this->posts} p ON pm.post_id = p.id 1780 2121 WHERE pm.meta_key IN ('_wp_attached_file', '_wp_attachment_image_alt', '_wp_attachment_metadata') 1781 AND p.post_parent IN ({$ids })1782 AND p.post_author = {$this->author}2122 AND p.post_parent IN ({$ids_csv}) 2123 AND p.post_author = %d 1783 2124 AND p.post_name LIKE 'fifu-category%' 1784 "); 2125 ", $author); 2126 $this->wpdb->query($sql_del_pm); 1785 2127 1786 2128 $this->wpdb->query('COMMIT'); … … 1791 2133 1792 2134 function insert_termmeta($id) { 1793 $result = $this->wpdb->get_results(" 1794 SELECT post_ids 1795 FROM {$this->fifu_meta_in} 1796 WHERE id = {$id} 1797 "); 1798 1799 $this->wpdb->query(" 1800 DELETE FROM {$this->fifu_meta_in} 1801 WHERE id = {$id} 1802 "); 2135 $result = $this->wpdb->get_results( 2136 $this->wpdb->prepare( 2137 "SELECT post_ids FROM {$this->fifu_meta_in} WHERE id = %d", 2138 (int) $id 2139 ) 2140 ); 2141 2142 $this->wpdb->query( 2143 $this->wpdb->prepare( 2144 "DELETE FROM {$this->fifu_meta_in} WHERE id = %d", 2145 (int) $id 2146 ) 2147 ); 1803 2148 1804 2149 if (count($result) == 0) … … 1826 2171 function insert_termmeta2($value, $ids) { 1827 2172 $this->wpdb->query('START TRANSACTION'); 2173 $ids_csv = $this->sanitize_ids_csv($ids); 1828 2174 1829 2175 try { 1830 $this->wpdb->query(" 1831 INSERT INTO {$this->posts} (post_author, guid, post_title, post_excerpt, post_mime_type, post_type, post_status, post_parent, post_date, post_date_gmt, post_modified, post_modified_gmt, post_content, to_ping, pinged, post_content_filtered, post_name) 1832 VALUES " . str_replace('\\', '', $value)); 1833 1834 $this->wpdb->query(" 2176 $this->wpdb->query( 2177 "INSERT INTO {$this->posts} (post_author, guid, post_title, post_excerpt, post_mime_type, post_type, post_status, post_parent, post_date, post_date_gmt, post_modified, post_modified_gmt, post_content, to_ping, pinged, post_content_filtered, post_name) 2178 VALUES " . $value 2179 ); 2180 2181 $author = $this->author; 2182 $sql_term_thumbnail = $this->wpdb->prepare(" 1835 2183 INSERT INTO {$this->termmeta} (term_id, meta_key, meta_value) ( 1836 2184 SELECT p.post_parent, 'thumbnail_id', p.id 1837 2185 FROM {$this->posts} p 1838 WHERE p.post_parent IN ({$ids })1839 AND p.post_author = {$this->author}2186 WHERE p.post_parent IN ({$ids_csv}) 2187 AND p.post_author = %d 1840 2188 AND p.post_name LIKE 'fifu-category%' 1841 2189 ) 1842 "); 1843 1844 $this->wpdb->query(" 2190 ", $author); 2191 $this->wpdb->query($sql_term_thumbnail); 2192 2193 $sql_term_file = $this->wpdb->prepare(" 1845 2194 INSERT INTO {$this->postmeta} (post_id, meta_key, meta_value) ( 1846 2195 SELECT p.id, '_wp_attached_file', p.post_content_filtered 1847 2196 FROM {$this->posts} p 1848 WHERE p.post_parent IN ({$ids })1849 AND p.post_author = {$this->author}2197 WHERE p.post_parent IN ({$ids_csv}) 2198 AND p.post_author = %d 1850 2199 AND p.post_name LIKE 'fifu-category%' 1851 2200 ) 1852 "); 1853 1854 $this->wpdb->query(" 2201 ", $author); 2202 $this->wpdb->query($sql_term_file); 2203 2204 $sql_term_alt = $this->wpdb->prepare(" 1855 2205 INSERT INTO {$this->postmeta} (post_id, meta_key, meta_value) ( 1856 2206 SELECT p.id, '_wp_attachment_image_alt', p.post_title 1857 2207 FROM {$this->posts} p 1858 WHERE p.post_parent IN ({$ids })1859 AND p.post_author = {$this->author}2208 WHERE p.post_parent IN ({$ids_csv}) 2209 AND p.post_author = %d 1860 2210 AND p.post_title IS NOT NULL 1861 2211 AND p.post_title != '' 1862 2212 AND p.post_name LIKE 'fifu-category%' 1863 2213 ) 1864 "); 2214 ", $author); 2215 $this->wpdb->query($sql_term_alt); 1865 2216 1866 2217 $this->wpdb->query('COMMIT'); … … 1871 2222 1872 2223 function get_fifu_fields($ids) { 2224 $ids_csv = $this->sanitize_ids_csv($ids); 1873 2225 $results = $this->wpdb->get_results(" 1874 2226 SELECT post_id, meta_key, meta_value 1875 2227 FROM {$this->postmeta} 1876 WHERE post_id IN ({$ids })2228 WHERE post_id IN ({$ids_csv}) 1877 2229 AND meta_key IN ('fifu_image_url', 'fifu_image_alt') 1878 2230 "); … … 1948 2300 function fifu_db_count_urls() { 1949 2301 $db = new FifuDb(); 1950 $aux = $db->get_count_urls() [0];1951 return $aux ? $aux ->amount: 0;2302 $aux = $db->get_count_urls(); 2303 return $aux ? $aux : 0; 1952 2304 } 1953 2305 -
featured-image-from-url/trunk/admin/debug.php
r3328447 r3362830 27 27 $metaout = fifu_db_debug_metaout(); 28 28 return new WP_REST_Response($metaout, 200); 29 } 30 31 function fifu_api_debug_log(WP_REST_Request $request) { 32 $type = $request->get_param('type') ?? 'plugin'; 33 $lines = intval($request->get_param('lines') ?? 200); 34 if ($lines <= 0) { 35 $lines = 200; 36 } 37 if ($lines > 5000) { // hard cap to avoid huge responses 38 $lines = 5000; 39 } 40 41 $upload_dir = wp_upload_dir(); 42 $basedir = $upload_dir['basedir'] ?? ''; 43 $filename = $type === 'cloud' ? 'fifu-cloud.log' : 'fifu-plugin.log'; 44 $path = $basedir ? (rtrim($basedir, '/\\') . '/' . $filename) : ''; 45 46 if (!$path || !file_exists($path)) { 47 return new WP_REST_Response('Log file not found', 404); 48 } 49 50 // Ensure readable for this request 51 @chmod($path, 0600); 52 $content = @file_get_contents($path); 53 // Preserve permission according to current toggle 54 $debug_on = function_exists('fifu_is_on') ? fifu_is_on('fifu_debug') : false; 55 @chmod($path, $debug_on ? 0600 : 0200); 56 if ($content === false) { 57 return new WP_REST_Response('Unable to read log file', 403); 58 } 59 60 $parts = preg_split('/\r?\n/', rtrim($content, "\r\n")); 61 $slice = array_slice($parts, -$lines); 62 $text = implode("\n", $slice) . "\n"; 63 64 $response = new WP_REST_Response($text, 200); 65 $response->header('Content-Type', 'text/plain; charset=' . get_option('blog_charset')); 66 return $response; 29 67 } 30 68 … … 89 127 }, 90 128 )); 129 register_rest_route('featured-image-from-url/v2', '/debug-log/(?P<type>(cloud|plugin))', array( 130 'methods' => 'GET', 131 'callback' => 'fifu_api_debug_log', 132 'permission_callback' => function ($request) { 133 return fifu_is_on('fifu_debug'); 134 }, 135 'args' => array( 136 'type' => array( 137 'required' => true, 138 'validate_callback' => function ($param) { 139 return in_array($param, array('cloud', 'plugin'), true); 140 } 141 ), 142 'lines' => array( 143 'required' => false, 144 'validate_callback' => function ($param) { 145 return is_numeric($param) && intval($param) > 0; // capped inside handler 146 } 147 ), 148 ), 149 )); 91 150 }); -
featured-image-from-url/trunk/admin/html/column.html
r3341179 r3362830 1 1 <div 2 2 class="fifu-quick" 3 post-id="<?php echo $post_id?>"4 is-ctgr="<?php echo $is_ctgr?>"5 image-url="<?php echo $image_url?>"6 is-variable="<?php echo $is_variable?>"7 style="height: <?php echo $height ?>px; width: <?php echo $width ?>px; background:url('<?php echo $url ?>') no-repeat center center; background-size:cover; <?php echo $border?>; cursor:pointer; border-radius: 8px;">3 post-id="<?php echo esc_attr($post_id) ?>" 4 is-ctgr="<?php echo esc_attr($is_ctgr) ?>" 5 image-url="<?php echo esc_url($image_url) ?>" 6 is-variable="<?php echo esc_attr($is_variable) ?>" 7 style="height: <?php echo esc_attr($height) ?>px; width: <?php echo esc_attr($width) ?>px; background:url('<?php echo esc_url($url) ?>') no-repeat center center; background-size:cover; <?php echo esc_attr($border) ?>; cursor:pointer; border-radius: 8px;"> 8 8 </div> -
featured-image-from-url/trunk/admin/html/support-data.html
r3356282 r3362830 13 13 Theme:<?php echo wp_get_theme() ?><?php echo fifu_woo_theme() ? ' (WooCommerce)' : '' ?>; 14 14 PHP:<?php echo phpversion() ?>; 15 PHP_INT_SIZE:<?php echo PHP_INT_SIZE ?>; 15 16 WooCommerce:<?php echo class_exists('WooCommerce') ? WC()->version : '' ?>; 16 17 Pages:<?php echo wp_count_posts('page')->publish ?>; -
featured-image-from-url/trunk/admin/log.php
r3328447 r3362830 13 13 $filepath = "{$upload_dir}/{$file}.log"; 14 14 15 // Remove the file 16 if (file_exists($filepath) && filesize($filepath) > 10 * 1024 * 1024) 17 unlink($filepath); 15 // Rotate the .log file if it exceeds 10MB 16 if (file_exists($filepath) && filesize($filepath) > 10 * 1024 * 1024) { 17 @unlink($filepath); 18 } 18 19 19 if (is_array($entry)) 20 if (is_array($entry)) { 20 21 $entry = json_encode([current_time('mysql') => $entry], JSON_UNESCAPED_SLASHES); 22 } 21 23 22 $file = fopen($filepath, $mode); 23 $bytes = fwrite($file, "{$entry}\n"); 24 fclose($file); 24 // Ensure file exists before adjusting permissions 25 if (!file_exists($filepath)) { 26 @touch($filepath); 27 } 28 29 // Set permissions based on current debug toggle 30 $debug_on = function_exists('fifu_is_on') ? fifu_is_on('fifu_debug') : false; 31 @chmod($filepath, $debug_on ? 0600 : 0200); 32 33 $fh = fopen($filepath, $mode); 34 $bytes = fwrite($fh, "{$entry}\n"); 35 fclose($fh); 25 36 26 37 return $bytes; 27 38 } 28 39 40 // Immediately adjust log file permissions when fifu_debug changes 41 function fifu_set_log_permissions($debug_on) { 42 $upload_dir = wp_upload_dir()['basedir'] ?? ''; 43 if (!$upload_dir) 44 return; 45 $files = [ 46 $upload_dir . '/fifu-plugin.log', 47 $upload_dir . '/fifu-cloud.log', 48 ]; 49 $perm = $debug_on ? 0600 : 0200; 50 foreach ($files as $file) { 51 if (file_exists($file)) { 52 @chmod($file, $perm); 53 } 54 } 55 } 56 57 add_action('updated_option', function ($option, $old_value, $value) { 58 if ($option === 'fifu_debug') { 59 fifu_set_log_permissions($value === 'toggleon'); 60 } 61 }, 10, 3); 62 63 -
featured-image-from-url/trunk/admin/menu.php
r3356282 r3362830 162 162 wp_enqueue_style('fifu-menu-css', plugins_url('/html/css/menu.css', __FILE__), array(), fifu_version_number_enq()); 163 163 164 // page-specific JS to hide admin notices, matching other FIFU pages 165 wp_enqueue_script('fifu-support-data-js', plugins_url('/html/js/support-data.js', __FILE__), array('jquery', 'jquery-ui'), fifu_version_number_enq()); 166 164 167 $skip = esc_attr(get_option('fifu_skip')); 165 168 $html_cpt = esc_attr(get_option('fifu_html_cpt')); -
featured-image-from-url/trunk/featured-image-from-url.php
r3356282 r3362830 5 5 * Plugin URI: https://fifu.app/ 6 6 * Description: Use remote media as the featured image and beyond. 7 * Version: 5.2. 77 * Version: 5.2.8 8 8 * Author: fifu.app 9 9 * Author URI: https://fifu.app/ … … 21 21 define('FIFU_GRAVITY_DIR', FIFU_PLUGIN_DIR . 'gravity-forms'); 22 22 define('FIFU_LANGUAGES_DIR', WP_CONTENT_DIR . '/uploads/fifu/languages/'); 23 define('FIFU_DELETE_ALL_URLS', false);24 23 define('FIFU_CLOUD_DEBUG', false); 24 25 if (!defined('FIFU_DELETE_ALL_URLS')) { 26 define('FIFU_DELETE_ALL_URLS', false); 27 } 25 28 26 29 $FIFU_SESSION = array(); -
featured-image-from-url/trunk/includes/attachment.php
r3352132 r3362830 64 64 global $wpdb; 65 65 if (fifu_is_web_story() || (($_POST['action'] ?? '') == 'query-attachments' || ($_POST['action'] ?? '') == 'get-attachment')) 66 $where .= ' AND ' . $wpdb->prefix . 'posts.post_author <> ' . FIFU_AUTHOR . ' ';66 $where .= $wpdb->prepare(" AND {$wpdb->posts}.post_author <> %d ", FIFU_AUTHOR); 67 67 return $where; 68 68 } … … 71 71 global $wpdb; 72 72 if (fifu_is_web_story() || (is_admin() && $q->is_main_query() && strpos($where, 'attachment') !== false)) 73 $where .= ' AND ' . $wpdb->prefix . 'posts.post_author <> ' . FIFU_AUTHOR . ' ';73 $where .= $wpdb->prepare(" AND {$wpdb->posts}.post_author <> %d ", FIFU_AUTHOR); 74 74 return $where; 75 75 }, 10, 2); -
featured-image-from-url/trunk/includes/html/og-image.html
r3352132 r3362830 1 1 <!-- FIFU:meta:begin:image --> 2 <meta property="og:image" content="<?php echo $url?>" />2 <meta property="og:image" content="<?php echo esc_attr(esc_url($url)) ?>" /> 3 3 <!-- FIFU:meta:end:image --> -
featured-image-from-url/trunk/includes/html/twitter-image.html
r3352132 r3362830 1 1 <!-- FIFU:meta:begin:twitter --> 2 <meta name="twitter:image" content="<?php echo $url?>" />2 <meta name="twitter:image" content="<?php echo esc_attr(esc_url($url)) ?>" /> 3 3 <!-- FIFU:meta:end:twitter --> -
featured-image-from-url/trunk/includes/speedup.php
r3344902 r3362830 190 190 $sizes = unserialize(FIFU_SPEEDUP_SIZES); 191 191 192 // Check if the width is present in the available sizes 192 // Preserve original width for aspect ratio calculation 193 $original_width = $width; 194 195 // Snap width to the next allowed size if needed 193 196 if (!in_array($width, $sizes)) { 194 // Look for the next higher value195 197 foreach ($sizes as $size) { 196 198 if ($size >= $width) { … … 200 202 } 201 203 202 // If the next higher value is bigger than 1920, use1920204 // Hard cap at 1920 203 205 if ($width > 1920) { 204 206 $width = 1920; … … 206 208 } 207 209 208 // Calculate the new height to maintain theaspect ratio210 // Recalculate height to preserve original aspect ratio 209 211 if ($height) { 210 $aspect_ratio = $height / $width;211 $new_height = $width * $aspect_ratio;212 $aspect_ratio = $height / max(1, $original_width); 213 $new_height = (int) round($width * $aspect_ratio); 212 214 } else { 213 $new_height = $height; 215 $new_height = $height; // keep as is (0 or null) 214 216 } 215 217 -
featured-image-from-url/trunk/includes/util.php
r3356282 r3362830 289 289 } 290 290 291 function fifu_unit_test() { 292 return 'Hello, World!'; 293 } 294 291 295 // developers 292 296 -
featured-image-from-url/trunk/readme.txt
r3356282 r3362830 5 5 Requires at least: 5.6 6 6 Tested up to: 6.8.2 7 Stable tag: 5.2. 77 Stable tag: 5.2.8 8 8 License: GPLv3 9 9 License URI: https://www.gnu.org/licenses/gpl-3.0.html … … 247 247 == Changelog == 248 248 249 = 5.2.8 = 250 * Fixes: vulnerabilities reported by the Wordfence Security team. 251 249 252 = 5.2.7 = 250 253 * New: Notice to rate the plugin; Enhancement: Auto set featured media from post content (now supports local relative URLs); Fix: Incomplete product data generated for Rich Results. … … 274 277 * Notice: the plugin collects the theme name anonymously (the goal is to identify the most common themes and ensure FIFU works correctly with all of them). 275 278 276 = 5.1.8 =277 * Fix: Optimized Images (performance issue when serving full image size and possible conflicts with images from Cloudinary); Fix: images in the WooCommerce product gallery (not displayed when Optimized Images was disabled).278 279 279 = others = 280 280 * [more](https://fifu.app/changelog) … … 283 283 == Upgrade Notice == 284 284 285 = 5.2. 7=286 * New: Notice to rate the plugin; Enhancement: Auto set featured media from post content (now supports local relative URLs); Fix: Incomplete product data generated for Rich Results.285 = 5.2.8 = 286 * Fixes: vulnerabilities reported by the Wordfence Security team.
Note: See TracChangeset
for help on using the changeset viewer.