Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions apiki-favorites/apiki-favorites.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php
/**
* Plugin Name: Apiki Favorites
* Description: Permite usuários logados favoritar e desfavoritar posts via REST API.
* Version: 1.0.0
* Author: Mainart Moretto
* Text Domain: apiki-favorites
*
* @package Apiki_Favorites
*/

defined( 'ABSPATH' ) || exit;

define( 'APIKI_FAVORITES_VERSION', '1.0.0' );
define( 'APIKI_FAVORITES_PATH', plugin_dir_path( __FILE__ ) );

require_once APIKI_FAVORITES_PATH . 'includes/class-database.php';
require_once APIKI_FAVORITES_PATH . 'includes/class-rest-api.php';

register_activation_hook( __FILE__, array( 'Apiki_Favorites_Database', 'create_table' ) );

add_action( 'rest_api_init', array( 'Apiki_Favorites_Rest_Api', 'register_routes' ) );
145 changes: 145 additions & 0 deletions apiki-favorites/includes/class-database.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?php
/**
* Classe responsável pela tabela customizada de favoritos.
*
* @package Apiki_Favorites
*/

defined( 'ABSPATH' ) || exit;

class Apiki_Favorites_Database {

/**
* Retorna o nome da tabela.
*
* @return string
*/
public static function get_table_name() {
global $wpdb;
return $wpdb->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
)
);
}
}
172 changes: 172 additions & 0 deletions apiki-favorites/includes/class-rest-api.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<?php
/**
* Classe responsável pelos endpoints da REST API.
*
* @package Apiki_Favorites
*/

defined( 'ABSPATH' ) || exit;

class Apiki_Favorites_Rest_Api {

const NAMESPACE = 'apiki/v1';

/**
* Registra as rotas da API.
*/
public static function register_routes() {
register_rest_route(
self::NAMESPACE,
'/favorites',
array(
array(
'methods' => 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<post_id>\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 );
}
}