Changeset 13178 for trunk/src/bp-core/bp-core-avatars.php
- Timestamp:
- 12/11/2021 02:13:14 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/bp-core/bp-core-avatars.php
r13177 r13178 2241 2241 return wp_filter_object_list( $avatars, array( 'type' => $type ) ); 2242 2242 } 2243 2244 /** 2245 * Recycle a previously uploaded avatar as the current avatar. 2246 * 2247 * @since 10.0.0 2248 */ 2249 function bp_avatar_ajax_recycle_previous_avatar() { 2250 if ( ! bp_is_post_request() ) { 2251 wp_send_json_error(); 2252 } 2253 2254 $avatar_data = bp_parse_args( 2255 $_POST, 2256 array( 2257 'object' => '', 2258 'item_id' => 0, 2259 'avatar_id' => '', 2260 ) 2261 ); 2262 2263 if ( ! $avatar_data['object'] || ! $avatar_data['item_id'] || ! $avatar_data['avatar_id'] ) { 2264 wp_send_json_error(); 2265 } 2266 2267 // Check the nonce. 2268 check_admin_referer( 'bp_avatar_recycle_previous', 'nonce' ); 2269 2270 // Capability check. 2271 if ( ! bp_attachments_current_user_can( 'edit_avatar', $avatar_data ) ) { 2272 wp_send_json_error(); 2273 } 2274 2275 // Set the Avatar Attachment Instance. 2276 $avatar_attachment = new BP_Attachment_Avatar(); 2277 $object = sanitize_key( $avatar_data['object'] ); 2278 2279 if ( 'user' === $object ) { 2280 $avatar_dir = 'avatars'; 2281 } else { 2282 $avatar_dir = $object . '-avatars'; 2283 } 2284 2285 $item_id = (int) $avatar_data['item_id']; 2286 $avatar_dir_path = $avatar_attachment->upload_path . '/' . $avatar_dir . '/' . $item_id; 2287 $current_avatars = bp_attachments_list_directory_files( $avatar_dir_path ); 2288 $revision_errors = array(); 2289 2290 // This path will be needed to get the avatar revision object. 2291 $avatar_full_revision_path = ''; 2292 2293 // Add a revision of the current avatar if it's not a mystery man! 2294 if ( $current_avatars ) { 2295 foreach( $current_avatars as $current_avatar ) { 2296 if ( ! isset( $current_avatar->name, $current_avatar->id, $current_avatar->path ) ) { 2297 continue; 2298 } 2299 2300 $is_full = preg_match( "/-bpfull/", $current_avatar->name ); 2301 $is_thumb = preg_match( "/-bpthumb/", $current_avatar->name ); 2302 2303 if ( $is_full || $is_thumb ) { 2304 // Add a revision of the current avatar. 2305 $revision = $avatar_attachment->add_revision( 2306 'avatar', 2307 array( 2308 'file_abspath' => $current_avatar->path, 2309 'file_id' => $current_avatar->id, 2310 ) 2311 ); 2312 2313 if ( is_wp_error( $revision ) ) { 2314 $revision_errors[] = $revision->get_error_message(); 2315 } elseif ( $is_full ) { 2316 $avatar_full_revision_path = $revision->path; 2317 } 2318 } 2319 } 2320 } 2321 2322 // No errors, let's recycle the previous avatar. 2323 if ( ! $revision_errors ) { 2324 $avatar_id = sanitize_file_name( $avatar_data['avatar_id'] ); 2325 $suffix = '-bpfull'; 2326 $history_dir = trailingslashit( bp_core_avatar_upload_path() ) . $avatar_dir . '/' . $item_id . '/history'; 2327 $avatars = bp_attachments_list_directory_files( $history_dir ); 2328 2329 if ( ! isset( $avatars[ $avatar_id ] ) ) { 2330 wp_send_json_error( 2331 array( 2332 'message' => __( 'The profile photo you want to recycle cannot be found.', 'buddypress' ), 2333 ) 2334 ); 2335 } 2336 2337 // Init recycle vars. 2338 $recycle_timestamp = bp_core_current_time( true, 'timestamp' ); 2339 $recycle_errors = array(); 2340 $avatar_types = array( 2341 'full' => '', 2342 'thumb' => '', 2343 ); 2344 2345 // Use the found previous avatar. 2346 $avatar = $avatars[ $avatar_id ]; 2347 $avatar_types['full'] = $avatar->path; 2348 $avatar_types['thumb'] = str_replace( $suffix, '-bpthumb', $avatar->path ); 2349 $historical_types = $avatar_types; 2350 2351 // It's a legacy avatar, we need to crop it again and remove the thumb file that is not using a timestamp in its name. 2352 if ( ! file_exists( $avatar_types['thumb'] ) ) { 2353 $full_avatar_path = $avatar_dir_path . '/' . str_replace( 'bpfull', 'original-file', wp_basename( $avatar->path ) ); 2354 2355 // Move the full version back to avatar dir. 2356 rename( $avatar->path, $full_avatar_path ); 2357 2358 $avatar_types = $avatar_attachment->crop( 2359 array( 2360 'original_file' => $full_avatar_path, 2361 'avatar_dir' => $avatar_dir, 2362 'object' => $object, 2363 'item_id' => $item_id, 2364 ) 2365 ); 2366 2367 // loop into the history directory to delete the legacy thumb version file. 2368 foreach ( $avatars as $avatar_object ) { 2369 $timestamp = str_replace( array( '-bpthumb', '-bpfull' ), '', $avatar_object->id ); 2370 2371 if ( ! is_numeric( $timestamp ) && false !== strpos( $avatar_object->id, '-bpthumb' ) ) { 2372 @unlink( $avatar_object->path ); 2373 } 2374 } 2375 } else { 2376 foreach( $avatar_types as $type_key => $avatar_path ) { 2377 $filename = wp_basename( $avatar_path ); 2378 $avatar_id = pathinfo( $filename, PATHINFO_FILENAME ); 2379 $recycle_path = $avatar_dir_path . '/' . str_replace( $avatar_id, $recycle_timestamp . '-bp' . $type_key, $filename ); 2380 2381 if ( ! rename( $avatar_path, $recycle_path ) ) { 2382 $recycle_errors[] = __( 'An unexpected error occured while recycling the previous profile photo.', 'buddypress' ); 2383 } else { 2384 $avatar_types[ $type_key ] = $recycle_path; 2385 } 2386 } 2387 2388 $avatar_types = array_merge( 2389 $avatar_types, 2390 array( 2391 'timestamp' => $recycle_timestamp, 2392 ) 2393 ); 2394 } 2395 2396 // No errors, fire the hook used when an avatar is set. 2397 if ( ! $recycle_errors && $historical_types['full'] !== $avatar_types['full'] ) { 2398 $r = array( 2399 'item_id' => $item_id, 2400 'object' => $object, 2401 'avatar_dir' => $avatar_dir, 2402 ); 2403 2404 $action_hook = 'bp_members_avatar_uploaded'; 2405 if ( 'group' === $object ) { 2406 $action_hook = 'groups_avatar_uploaded'; 2407 } 2408 2409 /** This action is documented in bp-core/bp-core-avatars.php */ 2410 do_action( $action_hook, $item_id, 'recycle', $r, $avatar_types ); 2411 } else { 2412 $recycle_error = reset( $recycle_errors ); 2413 2414 wp_send_json_error( 2415 array( 2416 'message' => join( "\n", $recycle_error ), 2417 ) 2418 ); 2419 } 2420 } else { 2421 wp_send_json_error( 2422 array( 2423 'message' => join( "\n", $revision_errors ), 2424 ) 2425 ); 2426 } 2427 2428 $return = array( 2429 'avatar' => esc_url( 2430 bp_core_fetch_avatar( 2431 array( 2432 'object' => $object, 2433 'item_id' => $item_id, 2434 'html' => false, 2435 'type' => 'full', 2436 ) 2437 ) 2438 ), 2439 'feedback_code' => 5, 2440 'item_id' => $item_id, 2441 ); 2442 2443 // Get the created revision object if it exists. 2444 if ( $avatar_full_revision_path ) { 2445 $history_dir = dirname( $avatar_full_revision_path ); 2446 $avatars_history = bp_attachments_list_directory_files( $history_dir ); 2447 $latest_id = pathinfo( wp_basename( $avatar_full_revision_path ), PATHINFO_FILENAME ); 2448 2449 if ( isset( $avatars_history[ $latest_id ] ) ) { 2450 $gmdate = gmdate( 'Y-m-d H:i:s', $avatars_history[ $latest_id ]->last_modified ); 2451 $date = strtotime( get_date_from_gmt( $gmdate ) ); 2452 $history_url = trailingslashit( bp_core_avatar_url() ) . $avatar_dir . '/' . $item_id . '/history'; 2453 2454 // Prepare the avatar object for JavaScript. 2455 $avatars_history[ $latest_id ]->date = sprintf( 2456 '%1$s (%2$s)', 2457 date_i18n( get_option( 'date_format' ), $date ), 2458 date_i18n( get_option( 'time_format' ), $date ) 2459 ); 2460 $avatars_history[ $latest_id ]->type = 'full'; 2461 $avatars_history[ $latest_id ]->url = $history_url . '/' . $avatars_history[ $latest_id ]->name; 2462 2463 // Remove the path. 2464 unset( $avatars_history[ $latest_id ]->path ); 2465 2466 // Set the new object to add to the revision list. 2467 $return['historicalAvatar'] = $avatars_history[ $latest_id ]; 2468 } 2469 } 2470 2471 wp_send_json_success( $return ); 2472 } 2473 add_action( 'wp_ajax_bp_avatar_recycle_previous', 'bp_avatar_ajax_recycle_previous_avatar' ); 2474 2475 /** 2476 * Delete a previously uploaded avatar from avatars history. 2477 * 2478 * @since 10.0.0 2479 */ 2480 function bp_avatar_ajax_delete_previous_avatar() { 2481 if ( ! bp_is_post_request() ) { 2482 wp_send_json_error(); 2483 } 2484 2485 $avatar_data = bp_parse_args( 2486 $_POST, 2487 array( 2488 'object' => '', 2489 'item_id' => 0, 2490 'avatar_id' => '', 2491 ) 2492 ); 2493 2494 if ( ! $avatar_data['object'] || ! $avatar_data['item_id'] || ! $avatar_data['avatar_id'] ) { 2495 wp_send_json_error(); 2496 } 2497 2498 // Check the nonce. 2499 check_admin_referer( 'bp_avatar_delete_previous', 'nonce' ); 2500 2501 // Capability check. 2502 if ( ! bp_attachments_current_user_can( 'edit_avatar', $avatar_data ) ) { 2503 wp_send_json_error(); 2504 } 2505 2506 $object = sanitize_key( $avatar_data['object'] ); 2507 if ( 'user' === $object ) { 2508 $avatar_dir = 'avatars'; 2509 } else { 2510 $avatar_dir = $object . '-avatars'; 2511 } 2512 2513 $item_id = (int) $avatar_data['item_id']; 2514 $avatar_id = sanitize_file_name( $avatar_data['avatar_id'] ); 2515 $suffix = '-bpfull'; 2516 $history_dir = trailingslashit( bp_core_avatar_upload_path() ) . $avatar_dir . '/' . $item_id . '/history'; 2517 $avatars = bp_attachments_list_directory_files( $history_dir ); 2518 2519 if ( ! isset( $avatars[ $avatar_id ] ) ) { 2520 wp_send_json_error( 2521 array( 2522 'message' => __( 'The profile photo you want to delete cannot be found.', 'buddypress' ), 2523 ) 2524 ); 2525 } 2526 2527 $avatar_types = array( 2528 'full' => '', 2529 'thumb' => '', 2530 ); 2531 2532 // Use the found previous avatar. 2533 $avatar = $avatars[ $avatar_id ]; 2534 $avatar_types['full'] = $avatar->path; 2535 $avatar_types['thumb'] = str_replace( $suffix, '-bpthumb', $avatar->path ); 2536 2537 // It's a legacy avatar, we need to find the thumb version using file last modified date. 2538 if ( ! file_exists( $avatar_types['thumb'] ) ) { 2539 $avatar_types['thumb'] = ''; 2540 $possible_thumb_avatars = wp_list_pluck( $avatars, 'last_modified', 'id' ); 2541 2542 foreach ( $possible_thumb_avatars as $type_id => $modified_date ) { 2543 $timediff = $avatar->last_modified - $modified_date; 2544 if ( 1000 >= absint( $timediff ) && $avatar_id !== $type_id ) { 2545 $avatar_types['thumb'] = $avatars[ $type_id ]->path; 2546 break; 2547 } 2548 } 2549 } 2550 2551 // Remove the files. 2552 foreach ( $avatar_types as $avatar_path ) { 2553 if ( ! $avatar_path ) { 2554 continue; 2555 } 2556 2557 @unlink( $avatar_path ); 2558 } 2559 2560 $timestamp = str_replace( '-bpfull', '', $avatar_id ); 2561 if ( ! is_numeric( $timestamp ) ) { 2562 $timestamp = $avatar->last_modified; 2563 } 2564 2565 /** 2566 * Hook here to run custom code once the previous avatar has been deleted. 2567 * 2568 * @since 10.0.0 2569 * 2570 * @param int $item_id The object ID. 2571 * @param int $timestamp The avatar timestamp. 2572 */ 2573 do_action( "bp_previous_{$object}_avatar_deleted", $item_id, $timestamp ); 2574 2575 // Finally inform about the deletion success. 2576 wp_send_json_success( 2577 array( 2578 'feedback_code' => 6, 2579 ) 2580 ); 2581 } 2582 add_action( 'wp_ajax_bp_avatar_delete_previous', 'bp_avatar_ajax_delete_previous_avatar' );
Note: See TracChangeset
for help on using the changeset viewer.