From 8e2e42f615329d10e7216f7bae3c44e6d810fae7 Mon Sep 17 00:00:00 2001 From: mainartmorettodev Date: Thu, 19 Mar 2026 20:18:40 -0300 Subject: [PATCH] feat: plugin de favoritar posts via REST API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Tabela customizada wp_apiki_favorites com dbDelta - Endpoints: POST/GET /apiki/v1/favorites e DELETE /apiki/v1/favorites/{id} - Só usuários logados podem favoritar/desfavoritar --- apiki-favorites/apiki-favorites.php | 22 +++ apiki-favorites/includes/class-database.php | 145 +++++++++++++++++ apiki-favorites/includes/class-rest-api.php | 172 ++++++++++++++++++++ 3 files changed, 339 insertions(+) create mode 100644 apiki-favorites/apiki-favorites.php create mode 100644 apiki-favorites/includes/class-database.php create mode 100644 apiki-favorites/includes/class-rest-api.php diff --git a/apiki-favorites/apiki-favorites.php b/apiki-favorites/apiki-favorites.php new file mode 100644 index 00000000..f2317cb2 --- /dev/null +++ b/apiki-favorites/apiki-favorites.php @@ -0,0 +1,22 @@ +prefix . 'apiki_favorites'; + } + + /** + * Cria a tabela customizada no banco de dados. + */ + public static function create_table() { + global $wpdb; + + $table_name = self::get_table_name(); + $charset_collate = $wpdb->get_charset_collate(); + + $sql = "CREATE TABLE {$table_name} ( + id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + user_id BIGINT(20) UNSIGNED NOT NULL, + post_id BIGINT(20) UNSIGNED NOT NULL, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (id), + UNIQUE KEY user_post (user_id, post_id) + ) {$charset_collate};"; + + require_once ABSPATH . 'wp-admin/includes/upgrade.php'; + dbDelta( $sql ); + } + + /** + * Adiciona um post aos favoritos do usuário. + * + * @param int $user_id ID do usuário. + * @param int $post_id ID do post. + * @return bool|WP_Error + */ + public static function add_favorite( $user_id, $post_id ) { + global $wpdb; + + if ( self::is_favorite( $user_id, $post_id ) ) { + return new WP_Error( + 'already_favorited', + 'Este post já está nos seus favoritos.', + array( 'status' => 400 ) + ); + } + + $result = $wpdb->insert( + self::get_table_name(), + array( + 'user_id' => $user_id, + 'post_id' => $post_id, + ), + array( '%d', '%d' ) + ); + + return false !== $result; + } + + /** + * Remove um post dos favoritos do usuário. + * + * @param int $user_id ID do usuário. + * @param int $post_id ID do post. + * @return bool|WP_Error + */ + public static function remove_favorite( $user_id, $post_id ) { + global $wpdb; + + if ( ! self::is_favorite( $user_id, $post_id ) ) { + return new WP_Error( + 'not_favorited', + 'Este post não está nos seus favoritos.', + array( 'status' => 404 ) + ); + } + + $result = $wpdb->delete( + self::get_table_name(), + array( + 'user_id' => $user_id, + 'post_id' => $post_id, + ), + array( '%d', '%d' ) + ); + + return false !== $result; + } + + /** + * Verifica se um post é favorito do usuário. + * + * @param int $user_id ID do usuário. + * @param int $post_id ID do post. + * @return bool + */ + public static function is_favorite( $user_id, $post_id ) { + global $wpdb; + + $table_name = self::get_table_name(); + + $count = $wpdb->get_var( + $wpdb->prepare( + "SELECT COUNT(*) FROM {$table_name} WHERE user_id = %d AND post_id = %d", + $user_id, + $post_id + ) + ); + + return absint( $count ) > 0; + } + + /** + * Retorna os favoritos de um usuário. + * + * @param int $user_id ID do usuário. + * @return array + */ + public static function get_user_favorites( $user_id ) { + global $wpdb; + + $table_name = self::get_table_name(); + + return $wpdb->get_results( + $wpdb->prepare( + "SELECT post_id, created_at FROM {$table_name} WHERE user_id = %d ORDER BY created_at DESC", + $user_id + ) + ); + } +} diff --git a/apiki-favorites/includes/class-rest-api.php b/apiki-favorites/includes/class-rest-api.php new file mode 100644 index 00000000..65ce0432 --- /dev/null +++ b/apiki-favorites/includes/class-rest-api.php @@ -0,0 +1,172 @@ + WP_REST_Server::CREATABLE, + 'callback' => array( __CLASS__, 'add_favorite' ), + 'permission_callback' => array( __CLASS__, 'check_permission' ), + 'args' => array( + 'post_id' => array( + 'required' => true, + 'validate_callback' => array( __CLASS__, 'validate_post_id' ), + 'sanitize_callback' => 'absint', + ), + ), + ), + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( __CLASS__, 'get_favorites' ), + 'permission_callback' => array( __CLASS__, 'check_permission' ), + ), + ) + ); + + register_rest_route( + self::NAMESPACE, + '/favorites/(?P\d+)', + array( + 'methods' => WP_REST_Server::DELETABLE, + 'callback' => array( __CLASS__, 'remove_favorite' ), + 'permission_callback' => array( __CLASS__, 'check_permission' ), + 'args' => array( + 'post_id' => array( + 'validate_callback' => array( __CLASS__, 'validate_post_id' ), + 'sanitize_callback' => 'absint', + ), + ), + ) + ); + } + + /** + * Verifica se o usuário está logado. + * + * @return bool|WP_Error + */ + public static function check_permission() { + if ( ! is_user_logged_in() ) { + return new WP_Error( + 'rest_not_logged_in', + 'Você precisa estar logado para usar esta funcionalidade.', + array( 'status' => 401 ) + ); + } + + return true; + } + + /** + * Valida o post_id. + * + * @param mixed $value Valor do parâmetro. + * @return bool + */ + public static function validate_post_id( $value ) { + $post_id = absint( $value ); + + if ( $post_id <= 0 ) { + return false; + } + + return get_post_status( $post_id ) !== false; + } + + /** + * Favoritar um post. + * + * @param WP_REST_Request $request Objeto da requisição. + * @return WP_REST_Response|WP_Error + */ + public static function add_favorite( $request ) { + $user_id = get_current_user_id(); + $post_id = $request->get_param( 'post_id' ); + + $result = Apiki_Favorites_Database::add_favorite( $user_id, $post_id ); + + if ( is_wp_error( $result ) ) { + return $result; + } + + return new WP_REST_Response( + array( + 'success' => true, + 'message' => 'Post adicionado aos favoritos.', + 'post_id' => $post_id, + ), + 201 + ); + } + + /** + * Desfavoritar um post. + * + * @param WP_REST_Request $request Objeto da requisição. + * @return WP_REST_Response|WP_Error + */ + public static function remove_favorite( $request ) { + $user_id = get_current_user_id(); + $post_id = $request->get_param( 'post_id' ); + + $result = Apiki_Favorites_Database::remove_favorite( $user_id, $post_id ); + + if ( is_wp_error( $result ) ) { + return $result; + } + + return new WP_REST_Response( + array( + 'success' => true, + 'message' => 'Post removido dos favoritos.', + 'post_id' => $post_id, + ), + 200 + ); + } + + /** + * Listar favoritos do usuário. + * + * @param WP_REST_Request $request Objeto da requisição. + * @return WP_REST_Response + */ + public static function get_favorites( $request ) { + $user_id = get_current_user_id(); + $favorites = Apiki_Favorites_Database::get_user_favorites( $user_id ); + + $data = array(); + + foreach ( $favorites as $favorite ) { + $post = get_post( $favorite->post_id ); + + if ( ! $post ) { + continue; + } + + $data[] = array( + 'post_id' => absint( $favorite->post_id ), + 'title' => $post->post_title, + 'created_at' => $favorite->created_at, + ); + } + + return new WP_REST_Response( $data, 200 ); + } +}