Skip to content

desafio wordpress #53

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
vendor
28 changes: 28 additions & 0 deletions assets/css/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.like-button {
padding: 10px;
cursor: pointer;
border-radius: 5px;
transition: all 0.4s ease;
display: flex;
justify-content: center;
}

.like-button:not(.liked){
border: 1px solid green!important;
color: green;
}

.like-button:not(.liked):hover {
background: green;
color: white;
}

.like-button.liked {
color: red;
border: 1px solid red!important;
}

.like-button.liked:hover {
background: red;
color: white;
}
40 changes: 40 additions & 0 deletions assets/js/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
document.addEventListener('DOMContentLoaded', function () {
const buttons = document.querySelectorAll('.like-button');

buttons.forEach(button => {
button.addEventListener('click', function () {
const postId = this.getAttribute('data-post-id');
const isLiked = this.classList.contains('liked');

const method = isLiked ? 'DELETE' : 'POST';
const endpoint = isLiked ? 'delete' : 'add';
const url = `/wp-json/like/v1/${endpoint}`;

fetch(url, {
method: method,
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': wpApiSettings.nonce
},
body: JSON.stringify({
post_id: postId
})
})
.then(response => {
console.log(response);
if (!response.ok) {
throw new Error('Erro na requisição');
}
return response.json();
})
.then(data => {
console.log(data.message);
this.classList.toggle('liked', !isLiked);
this.textContent = isLiked ? 'Favoritar' : 'Desfavoritar';
})
.catch(error => {
alert('Erro: ' + error.message);
});
});
});
});
13 changes: 13 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "andre-nascimento/favoritar-posts",
"description": "Plugin para favoritar posts no WordPress.",
"type": "wordpress-plugin",
"autoload": {
"psr-4": {
"LikePosts\\": "includes/"
}
},
"require": {
"php": ">=7.4"
}
}
20 changes: 20 additions & 0 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

93 changes: 93 additions & 0 deletions includes/Controllers/LikePostsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

namespace LikePosts\Controllers;

use LikePosts\Models\LikePostsModel;
use LikePosts\Views\LikePostsView\LikePostsView;
use WP_REST_Response;

class LikePostsController {
private $model;
private $view;

public function __construct() {
$this->model = new LikePostsModel();
$this->model->create_table();
$this->view = new LikePostsView();

add_action('rest_api_init', [$this, 'register_rest_routes']);
add_action('the_content', [$this, 'add_like_button']);
add_action('wp_enqueue_scripts', [$this, 'enqueue_assets']);
}

public function register_rest_routes() {
register_rest_route('like/v1', '/add', [
'methods' => 'POST',
'callback' => [$this, 'like_post'],
'permission_callback' => [$this, 'is_user_logged_in']
]);

register_rest_route('like/v1', '/delete', [
'methods' => 'DELETE',
'callback' => [$this, 'dislike_post'],
'permission_callback' => [$this, 'is_user_logged_in']
]);
}

public function is_user_logged_in() {
return is_user_logged_in();
}

public function like_post($request) {
$user_id = get_current_user_id();
$post_id = intval($request['post_id']);

if (!$this->is_valid_post($post_id)) {
return new WP_REST_Response(['message' => 'Post inválido!'], 400);
}

$this->model->like($user_id, $post_id);
return new WP_REST_Response(['message' => 'Post favoritado!'], 200);
}

public function dislike_post($request) {
$user_id = get_current_user_id();
$post_id = intval($request['post_id']);

if (!$this->is_valid_post($post_id)) {
return new WP_REST_Response(['message' => 'Post inválido!'], 400);
}

$this->model->dislike($user_id, $post_id);
return new WP_REST_Response(['message' => 'Post desfavoritado!'], 200);
}


public function add_like_button($content) {
if (!is_single()) {
return $content;
}

ob_start();
$this->view->render(get_the_ID());
$button = ob_get_clean();

return $content . $button;
}

public function enqueue_assets() {
wp_enqueue_style('like-posts-style', plugin_dir_url(__FILE__) . '../../assets/css/style.css');
wp_enqueue_script('like-posts-script', plugin_dir_url(__FILE__) . '../../assets/js/script.js', [], time(), true);
wp_localize_script('like-posts-script', 'wpApiSettings', [
'nonce' => wp_create_nonce('wp_rest')
]);
}

public function has_liked_post($user_id, $post_id){
return $this->model->user_has_liked_post($user_id, $post_id);
}

private function is_valid_post($post_id) {
return get_post($post_id) !== null;
}
}
68 changes: 68 additions & 0 deletions includes/Models/LikePostsModel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace LikePosts\Models;

class LikePostsModel
{
private $table_name;

public function __construct()
{
global $wpdb;
$this->table_name = $wpdb->prefix . 'most_liked';
}

public function create_table()
{
global $wpdb;

$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS $this->table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
user_id bigint(20) NOT NULL,
post_id bigint(20) NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY user_post (user_id, post_id)
) $charset_collate;";

require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}

public function like($user_id, $post_id)
{
global $wpdb;
$wpdb->insert($this->table_name, [
'user_id' => $user_id,
'post_id' => $post_id
]);
}

public function dislike($user_id, $post_id)
{
global $wpdb;
$wpdb->delete($this->table_name, [
'user_id' => $user_id,
'post_id' => $post_id
]);
}

public function user_has_liked_post($user_id, $post_id)
{
global $wpdb;

if (!$user_id || !$post_id) {
return false;
}

$query = $wpdb->prepare(
"SELECT COUNT(*) FROM $this->table_name WHERE user_id = %d AND post_id = %d",
$user_id,
$post_id
);

$like_count = $wpdb->get_var($query);

return $like_count > 0;
}
}
Empty file.
15 changes: 15 additions & 0 deletions includes/Views/LikePostsView/LikePostsView.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace LikePosts\Views\LikePostsView;

use LikePosts\Controllers\LikePostsController;

class LikePostsView
{
public function render($post_id)
{
$like = new LikePostsController();
$has_liked = $like->has_liked_post(get_current_user_id(), $post_id);
include plugin_dir_path(__FILE__) . 'template.php';
}
}
9 changes: 9 additions & 0 deletions includes/Views/LikePostsView/template.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php if (is_user_logged_in()): ?>
<button class="like-button <?php echo $has_liked ? 'liked' : ''; ?>" data-post-id="<?php echo esc_attr($post_id); ?>">
<?php echo $has_liked ? 'Desfavoritar' : 'Favoritar' ;?>
</button>
<?php else: ?>
<p>Você precisa estar logado para curtir este post.
<a href="<?php echo esc_url(wp_login_url(get_permalink($post_id))); ?>">Clique aqui para fazer login</a>.
</p>
<?php endif; ?>
18 changes: 18 additions & 0 deletions wordpress-back-end-challenge.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

/**
* Plugin Name: Favoritar Posts
* Description: Permite que usuários logados possam favoritar e desfavoritar posts.
* Version: 1.0
* Author: André Nascimento
*/

if (!defined('ABSPATH')) {
exit;
}

require_once plugin_dir_path(__FILE__) . 'vendor/autoload.php';

use LikePosts\Controllers\LikePostsController;
$like_posts_controller = new LikePostsController();