diff --git a/likes-plugin/css/main.css b/likes-plugin/css/main.css new file mode 100644 index 0000000..d0ec103 --- /dev/null +++ b/likes-plugin/css/main.css @@ -0,0 +1,47 @@ +/* Like Box */ +.generic-content .like-box { + float: right; + font-size: 1rem; + background-color: #ededed; + box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.25); + color: red; + padding: 10px 10px 10px 25px; + border-radius: 4px; + cursor: pointer; + margin: 0 0 30px 30px; + position: relative; +} + +.generic-content .like-box:hover { + background-color: #dedede; +} + +.like-count { + padding-left: 10px; +} + +.like-box .fa-heart-o { + transition: all 0.35s ease-out; + position: absolute; + left: 10px; +} + +.like-box .fa-heart { + left: 10px; + transition: all 0.4s ease-out; + position: absolute; + visibility: hidden; + transform: scale(0.2); + opacity: 0; +} + +.like-box[data-exists=yes] .fa-heart { + transform: scale(1); + visibility: visible; + opacity: 1; +} + +.like-box[data-exists=yes] .fa-heart-o { + visibility: hidden; + opacity: 0; +} \ No newline at end of file diff --git a/likes-plugin/inc/LikeRoute.php b/likes-plugin/inc/LikeRoute.php new file mode 100644 index 0000000..0497950 --- /dev/null +++ b/likes-plugin/inc/LikeRoute.php @@ -0,0 +1,90 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link https://github.com/internick2017/wordpress-back-end-challenge + */ +class LikeRoute +{ + /** + * Função constructor init api + * + * + */ + public function __construct() + { + add_action('rest_api_init', array($this, 'postLikePluginRoute')); + } + + /** + * Registrar rota and methods da api + * + * @return void + */ + public function postLikePluginRoute(): void + { + register_rest_route('likeuri/v1', 'manageLike', array( + 'methods' => 'POST', + 'callback' => array($this, 'createLike') + )); + register_rest_route('likeuri/v1', 'manageLike', array( + 'methods' => 'DELETE', + 'callback' => array($this, 'deleteLike') + )); + } + + /** + * Função que cria o like + * + * @param $data + * @return int|void + */ + public function createLike($data) + { + if (is_user_logged_in()) { + global $wpdb; + $tableName = $wpdb->prefix . "likes"; + $user = sanitize_text_field($data['user']); + $post = sanitize_text_field($data['post']); + $like = array( + 'post_id' => $post, + 'user_id' => $user, + ); + $wpdb->insert($tableName, $like); + return $wpdb->insert_id; + } + + die('Só usuário logado pode curtir a postagem'); + } + + /** + * Função que exclui o like + * + * @param $data + * @return string|void + */ + public function deleteLike($data) + { + global $wpdb; + $like = sanitize_text_field($data['like']); + $userID = get_current_user_id(); + $post = sanitize_text_field($data['post']); + $tableName = $wpdb->prefix . "likes"; + $result = $wpdb->get_results("SELECT * FROM $tableName WHERE user_id = $userID AND post_id = $post"); + if (is_user_logged_in() && get_current_user_id() == $result[0]->user_id) { + $wpdb->delete($tableName, array('id' => $like)); + return 'like apagado'; + } + die('Só usuário logado pode curtir a postagem'); + } +} + + + diff --git a/likes-plugin/js/main.js b/likes-plugin/js/main.js new file mode 100644 index 0000000..04ff527 --- /dev/null +++ b/likes-plugin/js/main.js @@ -0,0 +1,71 @@ +class Like { + constructor() { + this.events() + } + + events() { + jQuery(".like-box").on("click", this.ourClickDispatcher.bind(this)) + } + + ourClickDispatcher(e) { + let currentLikeBox = jQuery(e.target).closest(".like-box"); + + if (currentLikeBox.attr("data-exists") == "yes") { + this.deleteLike(currentLikeBox) + } else { + this.createLike(currentLikeBox) + } + } + + createLike(currentLikeBox) { + jQuery.ajax({ + beforeSend: (xhr) => { + xhr.setRequestHeader('X-WP-Nonce', themeData.nonce); + }, + url: themeData.rootUrl + '/wp-json/likeuri/v1/manageLike', + type: 'POST', + data: { + 'user': currentLikeBox.data('user'), + 'post': currentLikeBox.data('post'), + }, + success: (response) => { + currentLikeBox.attr('data-exists', 'yes'); + let likeCount = parseInt(currentLikeBox.find(".like-count").html(), 10); + likeCount++; + currentLikeBox.find(".like-count").html(likeCount); + currentLikeBox.attr("data-like", response); + console.log(response); + }, + error: (response) => { + console.log(response); + } + }) + } + + deleteLike(currentLikeBox) { + jQuery.ajax({ + beforeSend: (xhr) => { + xhr.setRequestHeader('X-WP-Nonce', themeData.nonce); + }, + url: themeData.rootUrl + '/wp-json/likeuri/v1/manageLike', + data: { + 'like': parseInt(currentLikeBox.attr('data-like'), 10), + 'post': currentLikeBox.data('post'), + }, + type: 'DELETE', + success: (response) => { + console.log(response); + currentLikeBox.attr('data-exists', 'no'); + let likeCount = parseInt(currentLikeBox.find(".like-count").html(), 10); + likeCount--; + currentLikeBox.find(".like-count").html(likeCount); + currentLikeBox.attr("data-like", ''); + }, + error: (response) => { + console.log(response); + } + }) + } +} + +const like = new Like(); \ No newline at end of file diff --git a/likes-plugin/likes.php b/likes-plugin/likes.php new file mode 100644 index 0000000..3f9ef2a --- /dev/null +++ b/likes-plugin/likes.php @@ -0,0 +1,328 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link https://github.com/internick2017/wordpress-back-end-challenge + */ +class LikePlugin +{ + /** + * @var string Charset da base de dados + */ + private string $charset; + /** + * @var string Nome da tabela com prefixo + */ + private string $tableName; + + /** + * Função inicia os actions e hooks + * + */ + public function __construct() + { + global $wpdb; + $this->charset = $wpdb->get_charset_collate(); + $this->tableName = $wpdb->prefix . "likes"; + add_action('wp_enqueue_scripts', array($this, 'load_assets')); + add_action('activate_likes-plugin/likes.php', array($this, 'createTableDb')); + add_action('admin_post_createLike', array($this, 'createLike')); + add_action('admin_post_nopriv_createLike', array($this, 'createLike')); + add_action('admin_menu', array($this, 'adminPage')); + add_action('admin_init', array($this, 'settings')); + add_filter('the_content', array($this, 'ifWrap')); + } + + /** + * Carrega os arquivos css e javascript + * + * @return void + */ + public function load_assets(): void + { + wp_enqueue_style('font-awesome', '//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css'); + wp_enqueue_style('lp-css', plugins_url('/css/main.css', __FILE__)); + wp_enqueue_script('lp-js', plugins_url('/js/main.js', __FILE__), array('jquery'), '0.0.1', true); + wp_localize_script('lp-js', 'themeData', array( + 'rootUrl' => get_site_url(), + 'nonce' => wp_create_nonce('wp_rest') + )); + } + + /** + * Cria a tabela likes na base de dados + * + * @return void + */ + public function createTableDb(): void + { + global $plDbVersion; + $plDbVersion = '1.0'; + + $sql = "CREATE TABLE $this->tableName ( + id mediumint(9) NOT NULL AUTO_INCREMENT, + post_id mediumint(9) NOT NULL, + user_id mediumint(9) NOT NULL, + PRIMARY KEY (id), + UNIQUE KEY (post_id,user_id) + ) $this->charset;"; + + require_once ABSPATH . 'wp-admin/includes/upgrade.php'; + dbDelta($sql); + add_option('plDbVersion', $plDbVersion); + } + + /** + * Função para adicionar o html do botão de like no post + * + * @param $content + * + * @return mixed|void + */ + public function ifWrap($content) + { + if (is_main_query() && is_single() && (get_option('lpp_active', '1'))) { + return $this->createHTML($content); + } + return $content; + } + + /** + * Criar o conteúdo do HTML Butão de like + * + * @param $content + * + * @return void + */ + public function createHTML($content): void + { + global $wpdb; + global $post; + $countQuery = "SELECT COUNT(*) FROM $this->tableName WHERE post_id = $post->ID "; + $userID = get_current_user_id(); + $likeQuery = "SELECT * FROM $this->tableName WHERE user_id = $userID "; + $contentTop = ''; + $contentBottom = ''; + if (get_option('lpp_location', '0') == '0') { + $contentBottom = $content; + } else { + $contentTop = $content; + } + $likes = $wpdb->get_var($wpdb->prepare($countQuery, '')); + $likeID = $wpdb->get_var($wpdb->prepare($likeQuery, 'user_id')); + if ($likes) { + $existStatus = 'yes'; + } else { + $existStatus = 'no'; + } + echo $contentTop; + if (get_option('lpp_active', '1') && is_user_logged_in()) { + ?> +
+
+ +
+
+ array($this, 'sanitizeLocation'), 'default' => '0') + ); + add_settings_field( + 'lpp_location', + 'Local de exibição', + array($this, 'locationHTML'), + 'like-post-settings-page', + 'lpp_first_section' + ); + + + add_settings_field( + 'lpp_buttontext', + 'Texto do botão', + array($this, 'buttonTextHTML'), + 'like-post-settings-page', + 'lpp_first_section' + ); + register_setting( + 'likepostplugin', + 'lpp_buttontext', + array('sanitize_callback' => 'sanitize_text_field', 'default' => 'Post Statistics') + ); + + add_settings_field( + 'lpp_active', + 'Ativo?', + array($this, 'checkboxHTML'), + 'like-post-settings-page', + 'lpp_first_section', + ); + register_setting( + 'likepostplugin', + 'lpp_active', + array('sanitize_callback' => 'sanitize_text_field', 'default' => '1') + ); + } + + /** + * Validação personalizada do campo do checkbox + * + * @param $input + * + * @return false|mixed|void + */ + public function sanitizeLocation($input) + { + if ($input != '0' && $input != '1') { + add_settings_error( + 'lpp_location', + 'lpp_location_error', + 'O local de exibição deve ser no começo ou fim da postagem' + ); + return get_option('lpp_location'); + } + return $input; + } + + /** + * Função que gera o HTML do campo checkbox das configurações + * + * @return void + */ + public function checkboxHTML(): void + { ?> + > + + + + + +
+

Configurações de Like Post

+
+ +
+
+