// ===== PHASE 1: ENDPOINT - Rename & Update Description ===== function aiofilm_update_playlist( WP_REST_Request $request ) { global $wpdb; $playlist_id = (int) $request['id']; $new_name = isset( $request['name'] ) ? sanitize_text_field( $request['name'] ) : ''; $new_description = isset( $request['description'] ) ? wp_kses_post( $request['description'] ) : ''; // Validate playlist ID if ( empty( $playlist_id ) ) { return new WP_Error( 'invalid-id', __( 'شناسه پلی لیست معتبر نیست.', 'aiofilm-playlists' ), array( 'status' => 400 ) ); } // Check if at least one field is provided if ( empty( $new_name ) && empty( $new_description ) ) { return new WP_Error( 'no-data', __( 'حداقل یک فیلد (نام یا توضیح) الزامی است.', 'aiofilm-playlists' ), array( 'status' => 400 ) ); } $playlists_table = $wpdb->prefix . 'aiofilm_playlists'; // Get current playlist and verify ownership $playlist = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$playlists_table} WHERE playlist_id = %d", $playlist_id ) ); if ( ! $playlist ) { return new WP_Error( 'not-found', __( 'پلی لیست پیدا نشد.', 'aiofilm-playlists' ), array( 'status' => 404 ) ); } $user_id = get_current_user_id(); $guest_token = aiofilm_playlists_get_guest_token(); // Verify ownership or guest token if ( $user_id > 0 ) { if ( (int) $playlist->user_id !== $user_id ) { return new WP_Error( 'forbidden', __( 'شما اجازه ویرایش این پلی لیست را ندارید.', 'aiofilm-playlists' ), array( 'status' => 403 ) ); } } else { if ( $playlist->guest_token !== $guest_token ) { return new WP_Error( 'forbidden', __( 'شما اجازه ویرایش این پلی لیست را ندارید.', 'aiofilm-playlists' ), array( 'status' => 403 ) ); } } // Validate name if provided if ( ! empty( $new_name ) && strlen( $new_name ) > 255 ) { return new WP_Error( 'name-too-long', __( 'نام پلی لیست نباید بیش از 255 کاراکتر باشد.', 'aiofilm-playlists' ), array( 'status' => 400 ) ); } // Prepare update data $update_data = array(); if ( ! empty( $new_name ) ) { $update_data['name'] = $new_name; } if ( isset( $request['description'] ) ) { $update_data['description'] = $new_description; } // Update playlist $result = $wpdb->update( $playlists_table, $update_data, array( 'playlist_id' => $playlist_id ), array_fill( 0, count( $update_data ), '%s' ), array( '%d' ) ); if ( false === $result ) { aiofilm_playlists_log( 'Error updating playlist: ' . $wpdb->last_error ); return new WP_Error( 'db-error', __( 'خطایی در بروزرسانی پلی لیست رخ داد.', 'aiofilm-playlists' ), array( 'status' => 500 ) ); } // Fetch updated playlist $updated_playlist = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$playlists_table} WHERE playlist_id = %d", $playlist_id ) ); aiofilm_playlists_log( "Playlist $playlist_id updated by user $user_id" ); return new WP_REST_Response( array( 'success' => true, 'message' => __( 'پلی لیست با موفقیت بروزرسانی شد.', 'aiofilm-playlists' ), 'playlist' => array( 'id' => (int) $updated_playlist->playlist_id, 'name' => $updated_playlist->name, 'description' => $updated_playlist->description, ), ), 200 ); } // ===== PHASE 1: ENDPOINT - Update Visibility ===== function aiofilm_update_playlist_visibility( WP_REST_Request $request ) { global $wpdb; $playlist_id = (int) $request['id']; $visibility = sanitize_key( $request['visibility'] ); // Validate inputs if ( empty( $playlist_id ) ) { return new WP_Error( 'invalid-id', __( 'شناسه پلی لیست معتبر نیست.', 'aiofilm-playlists' ), array( 'status' => 400 ) ); } $valid_visibilities = array( 'public', 'private', 'unlisted' ); if ( ! in_array( $visibility, $valid_visibilities, true ) ) { return new WP_Error( 'invalid-visibility', __( 'مقدار مرئی‌بودن معتبر نیست. مقادیر معتبر: public, private, unlisted', 'aiofilm-playlists' ), array( 'status' => 400 ) ); } $playlists_table = $wpdb->prefix . 'aiofilm_playlists'; // Get playlist and verify ownership $playlist = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$playlists_table} WHERE playlist_id = %d", $playlist_id ) ); if ( ! $playlist ) { return new WP_Error( 'not-found', __( 'پلی لیست پیدا نشد.', 'aiofilm-playlists' ), array( 'status' => 404 ) ); } $user_id = get_current_user_id(); $guest_token = aiofilm_playlists_get_guest_token(); // Verify ownership if ( $user_id > 0 ) { if ( (int) $playlist->user_id !== $user_id ) { return new WP_Error( 'forbidden', __( 'شما اجازه تغییر مرئی‌بودن این پلی لیست را ندارید.', 'aiofilm-playlists' ), array( 'status' => 403 ) ); } } else { if ( $playlist->guest_token !== $guest_token ) { return new WP_Error( 'forbidden', __( 'شما اجازه تغییر مرئی‌بودن این پلی لیست را ندارید.', 'aiofilm-playlists' ), array( 'status' => 403 ) ); } } // Update visibility $result = $wpdb->update( $playlists_table, array( 'visibility' => $visibility ), array( 'playlist_id' => $playlist_id ), array( '%s' ), array( '%d' ) ); if ( false === $result ) { aiofilm_playlists_log( 'Error updating visibility: ' . $wpdb->last_error ); return new WP_Error( 'db-error', __( 'خطایی در بروزرسانی مرئی‌بودن رخ داد.', 'aiofilm-playlists' ), array( 'status' => 500 ) ); } aiofilm_playlists_log( "Playlist $playlist_id visibility changed to $visibility by user $user_id" ); return new WP_REST_Response( array( 'success' => true, 'message' => __( 'مرئی‌بودن پلی لیست با موفقیت تغییر کرد.', 'aiofilm-playlists' ), 'visibility' => $visibility, ), 200 ); } // ===== PHASE 1: ENDPOINT - Reorder Playlist Items ===== function aiofilm_reorder_items( WP_REST_Request $request ) { global $wpdb; $playlist_id = (int) $request['playlist_id']; $items = $request['items']; // Array of {id, position} objects // Validate inputs if ( empty( $playlist_id ) || ! is_array( $items ) || empty( $items ) ) { return new WP_Error( 'invalid-data', __( 'شناسه پلی لیست و آیتم‌ها الزامی است.', 'aiofilm-playlists' ), array( 'status' => 400 ) ); } $playlists_table = $wpdb->prefix . 'aiofilm_playlists'; $items_table = $wpdb->prefix . 'aiofilm_playlist_items'; // Verify playlist exists and user owns it $playlist = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$playlists_table} WHERE playlist_id = %d", $playlist_id ) ); if ( ! $playlist ) { return new WP_Error( 'not-found', __( 'پلی لیست پیدا نشد.', 'aiofilm-playlists' ), array( 'status' => 404 ) ); } $user_id = get_current_user_id(); $guest_token = aiofilm_playlists_get_guest_token(); // Verify ownership if ( $user_id > 0 ) { if ( (int) $playlist->user_id !== $user_id ) { return new WP_Error( 'forbidden', __( 'شما اجازه تغییر ترتیب این پلی لیست را ندارید.', 'aiofilm-playlists' ), array( 'status' => 403 ) ); } } else { if ( $playlist->guest_token !== $guest_token ) { return new WP_Error( 'forbidden', __( 'شما اجازه تغییر ترتیب این پلی لیست را ندارید.', 'aiofilm-playlists' ), array( 'status' => 403 ) ); } } // Update positions $updated_count = 0; foreach ( $items as $item ) { $item_id = (int) $item['id']; $position = (int) $item['position']; // Verify item belongs to this playlist $item_check = $wpdb->get_var( $wpdb->prepare( "SELECT item_id FROM {$items_table} WHERE item_id = %d AND playlist_id = %d", $item_id, $playlist_id ) ); if ( ! $item_check ) { continue; // Skip items that don't belong to this playlist } $result = $wpdb->update( $items_table, array( 'position' => $position ), array( 'item_id' => $item_id ), array( '%d' ), array( '%d' ) ); if ( $result !== false ) { $updated_count++; } } aiofilm_playlists_log( "Playlist $playlist_id reordered: $updated_count items updated by user $user_id" ); return new WP_REST_Response( array( 'success' => true, 'message' => sprintf( __( '%d آیتم با موفقیت مرتب شد.', 'aiofilm-playlists' ), $updated_count ), 'updated_count' => $updated_count, ), 200 ); } // ===== PHASE 1: ENDPOINT - Bulk Delete Items ===== function aiofilm_bulk_delete_items( WP_REST_Request $request ) { global $wpdb; $playlist_id = (int) $request['playlist_id']; $item_ids = $request['item_ids']; // Array of item IDs // Validate inputs if ( empty( $playlist_id ) || ! is_array( $item_ids ) || empty( $item_ids ) ) { return new WP_Error( 'invalid-data', __( 'شناسه پلی لیست و آیتم‌ها الزامی است.', 'aiofilm-playlists' ), array( 'status' => 400 ) ); } // Sanitize item IDs $item_ids = array_map( 'absint', $item_ids ); $item_ids = array_filter( $item_ids ); if ( empty( $item_ids ) ) { return new WP_Error( 'invalid-items', __( 'شناسه آیتم‌های نامعتبر.', 'aiofilm-playlists' ), array( 'status' => 400 ) ); } $playlists_table = $wpdb->prefix . 'aiofilm_playlists'; $items_table = $wpdb->prefix . 'aiofilm_playlist_items'; // Verify playlist exists and user owns it $playlist = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$playlists_table} WHERE playlist_id = %d", $playlist_id ) ); if ( ! $playlist ) { return new WP_Error( 'not-found', __( 'پلی لیست پیدا نشد.', 'aiofilm-playlists' ), array( 'status' => 404 ) ); } $user_id = get_current_user_id(); $guest_token = aiofilm_playlists_get_guest_token(); // Verify ownership if ( $user_id > 0 ) { if ( (int) $playlist->user_id !== $user_id ) { return new WP_Error( 'forbidden', __( 'شما اجازه حذف از این پلی لیست را ندارید.', 'aiofilm-playlists' ), array( 'status' => 403 ) ); } } else { if ( $playlist->guest_token !== $guest_token ) { return new WP_Error( 'forbidden', __( 'شما اجازه حذف از این پلی لیست را ندارید.', 'aiofilm-playlists' ), array( 'status' => 403 ) ); } } // Verify all items belong to this playlist $placeholders = implode( ',', array_fill( 0, count( $item_ids ), '%d' ) ); $items_check = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$items_table} WHERE playlist_id = %d AND item_id NOT IN ($placeholders)", array_merge( array( $playlist_id ), $item_ids ) ) ); // Get count of items that belong to this playlist $valid_items = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$items_table} WHERE playlist_id = %d AND item_id IN ($placeholders)", array_merge( array( $playlist_id ), $item_ids ) ) ); if ( empty( $valid_items ) ) { return new WP_Error( 'no-items', __( 'هیچ آیتم معتبری برای حذف پیدا نشد.', 'aiofilm-playlists' ), array( 'status' => 400 ) ); } // Delete items $delete_query = $wpdb->prepare( "DELETE FROM {$items_table} WHERE playlist_id = %d AND item_id IN ($placeholders)", array_merge( array( $playlist_id ), $item_ids ) ); $result = $wpdb->query( $delete_query ); if ( false === $result ) { aiofilm_playlists_log( 'Error deleting items: ' . $wpdb->last_error ); return new WP_Error( 'db-error', __( 'خطایی در حذف آیتم‌ها رخ داد.', 'aiofilm-playlists' ), array( 'status' => 500 ) ); } aiofilm_playlists_log( "Deleted $result items from playlist $playlist_id by user $user_id" ); return new WP_REST_Response( array( 'success' => true, 'message' => sprintf( __( '%d آیتم با موفقیت حذف شد.', 'aiofilm-playlists' ), $result ), 'deleted_count' => (int) $result, ), 200 ); } // ===== PHASE 1: ENDPOINT - Duplicate Playlist ===== function aiofilm_duplicate_playlist( WP_REST_Request $request ) { global $wpdb; $playlist_id = (int) $request['id']; $new_name = isset( $request['name'] ) ? sanitize_text_field( $request['name'] ) : ''; // Validate inputs if ( empty( $playlist_id ) ) { return new WP_Error( 'invalid-id', __( 'شناسه پلی لیست معتبر نیست.', 'aiofilm-playlists' ), array( 'status' => 400 ) ); } $playlists_table = $wpdb->prefix . 'aiofilm_playlists'; $items_table = $wpdb->prefix . 'aiofilm_playlist_items'; // Get original playlist $original = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$playlists_table} WHERE playlist_id = %d", $playlist_id ) ); if ( ! $original ) { return new WP_Error( 'not-found', __( 'پلی لیست اصلی پیدا نشد.', 'aiofilm-playlists' ), array( 'status' => 404 ) ); } $user_id = get_current_user_id(); // Set default name if not provided if ( empty( $new_name ) ) { $new_name = $original->name . ' (' . __( 'کپی', 'aiofilm-playlists' ) . ')'; } // Create new playlist (owned by current user, private visibility) $insert_result = $wpdb->insert( $playlists_table, array( 'user_id' => $user_id > 0 ? $user_id : 0, 'guest_token' => $user_id > 0 ? '' : aiofilm_playlists_get_guest_token(), 'name' => $new_name, 'description' => $original->description, 'visibility' => 'private', // New playlists are private by default 'created_at' => current_time( 'mysql' ), ), array( '%d', '%s', '%s', '%s', '%s', '%s' ) ); if ( ! $insert_result ) { aiofilm_playlists_log( 'Error duplicating playlist: ' . $wpdb->last_error ); return new WP_Error( 'db-error', __( 'خطایی در کپی کردن پلی لیست رخ داد.', 'aiofilm-playlists' ), array( 'status' => 500 ) ); } $new_playlist_id = $wpdb->insert_id; // Copy all items from original playlist $items = $wpdb->get_results( $wpdb->prepare( "SELECT post_id, position FROM {$items_table} WHERE playlist_id = %d ORDER BY position ASC", $playlist_id ) ); foreach ( $items as $item ) { $wpdb->insert( $items_table, array( 'playlist_id' => $new_playlist_id, 'post_id' => $item->post_id, 'position' => $item->position, 'added_at' => current_time( 'mysql' ), ), array( '%d', '%d', '%d', '%s' ) ); } aiofilm_playlists_log( "Playlist $playlist_id duplicated to $new_playlist_id by user $user_id" ); return new WP_REST_Response( array( 'success' => true, 'message' => __( 'پلی لیست با موفقیت کپی شد.', 'aiofilm-playlists' ), 'new_playlist_id' => (int) $new_playlist_id, 'new_playlist_name' => $new_name, ), 201 ); } // ===== PHASE 1: ENDPOINT - Get Playlist Statistics ===== function aiofilm_get_playlist_stats( WP_REST_Request $request ) { global $wpdb; $playlist_id = (int) $request['id']; // Validate input if ( empty( $playlist_id ) ) { return new WP_Error( 'invalid-id', __( 'شناسه پلی لیست معتبر نیست.', 'aiofilm-playlists' ), array( 'status' => 400 ) ); } // Check cache first $cache_key = "playlist_stats_$playlist_id"; $cached_stats = get_transient( $cache_key ); if ( $cached_stats !== false ) { return new WP_REST_Response( $cached_stats, 200 ); } $playlists_table = $wpdb->prefix . 'aiofilm_playlists'; $items_table = $wpdb->prefix . 'aiofilm_playlist_items'; $likes_table = $wpdb->prefix . 'aiofilm_playlist_likes'; // Check playlist exists $playlist = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$playlists_table} WHERE playlist_id = %d", $playlist_id ) ); if ( ! $playlist ) { return new WP_Error( 'not-found', __( 'پلی لیست پیدا نشد.', 'aiofilm-playlists' ), array( 'status' => 404 ) ); } // Calculate statistics $stats = array( 'playlist_id' => (int) $playlist_id, 'name' => $playlist->name, 'description' => $playlist->description, ); // Items count $stats['items_count'] = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$items_table} WHERE playlist_id = %d", $playlist_id ) ); // Likes count $stats['likes_count'] = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$likes_table} WHERE playlist_id = %d", $playlist_id ) ); // Duration (sum of post meta if available) $stats['total_duration'] = 0; $stats['total_duration_formatted'] = '0 ساعت'; // Average rating (if rating system exists) $stats['average_rating'] = 0; // Cache for 1 hour set_transient( $cache_key, $stats, HOUR_IN_SECONDS ); aiofilm_playlists_log( "Statistics retrieved for playlist $playlist_id" ); return new WP_REST_Response( $stats, 200 ); } ?>