Skip to:
Content

BuddyPress.org


Ignore:
Timestamp:
12/11/2021 02:13:14 PM (5 years ago)
Author:
imath
Message:

Add Ajax handlers for the recycle and delete previous avatar actions

These handlers will be used by the avatar UI:

  • to reset a previously uploaded user avatar as the current user avatar (bp_avatar_ajax_recycle_previous_avatar()),
  • to permanently remove a previously uploaded user avatar (bp_avatar_ajax_delete_previous_avatar()).

Props vapvarun, oztaser

See #8581

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-core/bp-core-avatars.php

    r13177 r13178  
    22412241        return wp_filter_object_list( $avatars, array( 'type' => $type ) );
    22422242}
     2243
     2244/**
     2245 * Recycle a previously uploaded avatar as the current avatar.
     2246 *
     2247 * @since 10.0.0
     2248 */
     2249function 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}
     2473add_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 */
     2480function 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}
     2582add_action( 'wp_ajax_bp_avatar_delete_previous', 'bp_avatar_ajax_delete_previous_avatar' );
Note: See TracChangeset for help on using the changeset viewer.