Changeset 3032462
- Timestamp:
- 02/07/2024 01:06:59 AM (2 years ago)
- Location:
- like-post-block
- Files:
-
- 16 edited
- 1 copied
-
tags/1.3.0 (copied) (copied from like-post-block/trunk)
-
tags/1.3.0/constants.php (modified) (1 diff)
-
tags/1.3.0/helpers.php (modified) (3 diffs)
-
tags/1.3.0/includes/class-rolpb-block.php (modified) (4 diffs)
-
tags/1.3.0/includes/class-rolpb-like.php (modified) (2 diffs)
-
tags/1.3.0/like-post-block.php (modified) (1 diff)
-
tags/1.3.0/public/js/rolpb-like.js (modified) (9 diffs)
-
tags/1.3.0/public/js/rolpb-like.min.js (modified) (1 diff)
-
tags/1.3.0/readme.txt (modified) (2 diffs)
-
trunk/constants.php (modified) (1 diff)
-
trunk/helpers.php (modified) (3 diffs)
-
trunk/includes/class-rolpb-block.php (modified) (4 diffs)
-
trunk/includes/class-rolpb-like.php (modified) (2 diffs)
-
trunk/like-post-block.php (modified) (1 diff)
-
trunk/public/js/rolpb-like.js (modified) (9 diffs)
-
trunk/public/js/rolpb-like.min.js (modified) (1 diff)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
like-post-block/tags/1.3.0/constants.php
r2981402 r3032462 10 10 * @since 1.0.0 11 11 */ 12 const ROLPB_VERSION = '1. 2.0';12 const ROLPB_VERSION = '1.3.0'; 13 13 14 14 /** -
like-post-block/tags/1.3.0/helpers.php
r2981402 r3032462 39 39 * 40 40 * @since 1.0.0 41 * @since 1.3.0 Change parameter type to WP_Post to get custom properties inside function. 41 42 * 42 * @param int $likes The number of likes.43 * @param array $attributes The block attributes.44 * @param string $icon_type The icon type.43 * @param int $total_likes The total number of likes for the post. 44 * @param int $post_id The post ID. 45 * @param array $attributes The block attributes. 45 46 * @return string The rendered block HTML. 46 47 */ 47 function rolpb_get_rendered_html( 48 int $likes,49 array $attributes,50 string $icon_type = 'inactive'51 ): string { 52 $button_css = 'active' === $ icon_type? 'wp-like-post__button--liked' : '';48 function rolpb_get_rendered_html( int $total_likes, int $post_id, array $attributes ): string { 49 // Set default for custom attributes. 50 $attributes['icon_type'] ??= 'inactive'; 51 $attributes['likes_from_user'] ??= 0; 52 53 $button_css = 'active' === $attributes['icon_type'] ? 'wp-like-post__button--liked' : ''; 53 54 $block_attributes = ! str_contains( $_SERVER['REQUEST_URI'], '/wp-json/' ) 54 55 ? get_block_wrapper_attributes( array( 'class' => 'wp-like-post__count' ) ) … … 61 62 $attributes['iconWidth'] ??= ROLPB_DEFAULT_ICON_WIDTH; 62 63 63 $html = '<div class="wp-like-post__wrapper" style="' . $gap_styles . '">'; 64 $html .= '<button type="button" class="wp-like-post__button ' . $button_css . '" '; 65 $html .= 'style="height: ' . $attributes['iconWidth'] . 'px; '; 66 $html .= 'color: ' . $attributes['iconColorValue'] . ';">'; 67 $html .= rolpb_get_svg_icon( $attributes['icon'], $attributes['iconWidth'], $icon_type ); 64 $html = '<div class="wp-like-post__wrapper" style="' . esc_attr( $gap_styles ) . '">'; 65 $html .= '<button type="button" class="wp-like-post__button ' . esc_attr( $button_css ) . '" '; 66 $html .= 'style="height: ' . esc_attr( $attributes['iconWidth'] ) . 'px; '; 67 $html .= 'color: ' . esc_attr( $attributes['iconColorValue'] ) . ';" '; 68 $html .= 'data-post-id="' . esc_attr( $post_id ) . '" data-total-likes="' . esc_attr( $total_likes ) . '" '; 69 $html .= 'data-likes-from-user="' . esc_attr( $attributes['likes_from_user'] ) . '">'; 70 $html .= rolpb_get_svg_icon( $attributes['icon'], $attributes['iconWidth'], $attributes['icon_type'] ); 68 71 $html .= '</button>'; 69 72 70 $html .= '<div ' . $block_attributes . '>' . $likes. '</div>';73 $html .= '<div ' . $block_attributes . '>' . esc_html( $total_likes ) . '</div>'; 71 74 $html .= '</div>'; 72 75 … … 75 78 * 76 79 * @since 1.1.0 80 * @since 1.3.0 Add `$post_id` parameters. 77 81 * 78 82 * @param string $html The rendered block HTML. 83 * @param int $post_id The post id. 79 84 * @param array $attributes The block attributes. 80 85 */ 81 return apply_filters( 'rolpb_likes_rendered_html', $html, $ attributes );86 return apply_filters( 'rolpb_likes_rendered_html', $html, $post_id, $attributes ); 82 87 } 83 88 -
like-post-block/tags/1.3.0/includes/class-rolpb-block.php
r2981402 r3032462 51 51 } 52 52 53 $rolpb_post = new ROLPB_Post( $post );54 55 53 wp_enqueue_script( 56 54 'lpb-like', … … 75 73 'getLikes' => wp_create_nonce( 'rolpb-get-post-likes-nonce' ), 76 74 'likePost' => wp_create_nonce( 'rolpb-like-post-nonce' ), 77 ),78 'post_id' => $post->ID,79 'likes' => array(80 'total' => $rolpb_post->likes(),81 'fromUser' => $rolpb_post->likes_from_user(),82 75 ), 83 76 'url' => admin_url( 'admin-ajax.php' ), … … 128 121 * 129 122 * @since 1.0.0 123 * @since 1.3.0 Send custom attributes inside `$attributes` array. 130 124 * 131 125 * @param array $attributes The block attributes. … … 136 130 137 131 if ( ! $post ) { 138 return rolpb_get_rendered_html( 0, $attributes );132 return rolpb_get_rendered_html( 0, 0, $attributes ); 139 133 } 140 134 141 $rolpb_post = new ROLPB_Post( $post );142 $likes = $rolpb_post->likes();143 $ icon_type = $likes && $rolpb_post->likes_from_user() ? 'active' : 'inactive';135 $rolpb_post = new ROLPB_Post( $post ); 136 $likes = $rolpb_post->likes(); 137 $likes_from_user = $rolpb_post->likes_from_user(); 144 138 145 return rolpb_get_rendered_html( $likes, $attributes, $icon_type ); 139 // Set custom attributes. 140 $attributes['icon_type'] = $likes && $likes_from_user ? 'active' : 'inactive'; 141 $attributes['likes_from_user'] = $likes_from_user; 142 143 return rolpb_get_rendered_html( $likes, $post->ID, $attributes ); 146 144 } 147 145 } -
like-post-block/tags/1.3.0/includes/class-rolpb-like.php
r2981402 r3032462 27 27 * 28 28 * @since 1.1.0 29 * @since 1.3.0 Accept post ids as a comma-separated string (bulk mode). 29 30 */ 30 31 public function get(): void { … … 35 36 } 36 37 37 if ( ! isset( $_POST['post_id'] ) ) {38 wp_send_json_error( ' The required data does not exist.' );38 if ( empty( $_POST['post_ids'] ) ) { 39 wp_send_json_error( 'Missing post ids.' ); 39 40 } 40 41 41 $post_id = intval( sanitize_text_field( $_POST['post_id'] ) ); 42 $post = new ROLPB_Post( $post_id ); 42 $post_ids = explode( ',', sanitize_text_field( $_POST['post_ids'] ) ); 43 43 44 wp_send_json_success( array( 45 'likes' => $post->likes(), 46 'post_id' => $post_id, 47 ) ); 44 if ( empty( $post_ids ) ) { 45 wp_send_json_error( 'Invalid post ids.' ); 46 } 47 48 $likes = array(); 49 50 foreach ( $post_ids as $post_id ) { 51 $post = new ROLPB_Post( $post_id ); 52 $likes[ $post_id ] = $post->likes(); 53 } 54 55 wp_send_json_success( $likes ); 48 56 } 49 57 -
like-post-block/tags/1.3.0/like-post-block.php
r2981402 r3032462 6 6 * Requires at least: 6.2 7 7 * Requires PHP: 7.4 8 * Version: 1. 2.08 * Version: 1.3.0 9 9 * Author: Roel Magdaleno 10 10 * Author URI: https://roelmagdaleno.com -
like-post-block/tags/1.3.0/public/js/rolpb-like.js
r2981402 r3032462 1 1 let rolpbTimerId; 2 let rolpbLike = 0;3 2 4 3 /** … … 30 29 * 31 30 * @since 1.0.0 32 */ 33 function rolbp_animateIcon() { 34 const icon = document.querySelector('.wp-like-post__button svg'); 31 * 32 * @param {object} likeButton The like button element. 33 */ 34 function rolbp_animateIcon(likeButton) { 35 const icon = likeButton.querySelector('svg'); 35 36 36 37 if (!icon) { … … 48 49 * @since 1.0.0 49 50 */ 50 function rolpb_replaceIcon() { 51 const button = document.querySelector('.wp-like-post__button'); 52 53 if (!button || button.classList.contains('wp-like-post__button--liked')) { 51 function rolpb_replaceIcon(likeButton) { 52 if (!likeButton || likeButton.classList.contains('wp-like-post__button--liked')) { 54 53 return; 55 54 } 56 55 57 button.classList.add('wp-like-post__button--liked');58 button.innerHTML = ROLPB.icons.active;56 likeButton.classList.add('wp-like-post__button--liked'); 57 likeButton.innerHTML = ROLPB.icons.active; 59 58 } 60 59 … … 79 78 } 80 79 80 /** 81 * Get the total number of likes for multiple posts. 82 * We send an AJAX request to the server and update the like count. 83 * 84 * @since 1.3.0 85 * 86 * @param {array} postIds The post IDs. 87 * @param {object} settings The settings object. 88 */ 89 function rolpb_getBulkLikes(postIds, settings) { 90 const request = rolpb_getXHR(settings.url); 91 92 request.onload = () => { 93 if (request.status >= 200 && request.status < 400) { 94 const response = JSON.parse(request.responseText); 95 96 if (response.success) { 97 const postsWithLikes = response.data; 98 99 postIds.forEach((id) => { 100 const likeButton = document.querySelector(`.wp-like-post__button[data-post-id="${id}"]`); 101 102 if (!likeButton) { 103 return; 104 } 105 106 const countEl = likeButton.parentElement.querySelector('.wp-like-post__count'); 107 108 if (!countEl) { 109 return; 110 } 111 112 const likes = parseInt(postsWithLikes[id]); 113 const printedLikes = parseInt(likeButton.getAttribute('data-total-likes')); 114 115 if (likes === printedLikes) { 116 return; 117 } 118 119 if (likes > 0) { 120 likeButton.classList.add('wp-like-post__button--liked'); 121 likeButton.innerHTML = settings.icons.active; 122 } 123 124 countEl.innerHTML = likes.toString(); 125 }); 126 } 127 } 128 }; 129 130 const nonce = settings.nonces.getLikes; 131 const attributes = JSON.stringify(settings.block); 132 133 request.send(`action=rolpb_get_post_likes&post_ids=${postIds}&nonce=${nonce}&attributes=${attributes}`); 134 } 135 81 136 let lpbPost = (function () { 82 137 /** … … 85 140 * @since 1.0.0 86 141 * 142 * @param {object} likeButton The like button element. 87 143 * @param {object} settings The settings object. 88 144 * 89 145 * @constructor 90 146 */ 91 function Constructor( settings) {147 function Constructor(likeButton, settings) { 92 148 // Freeze settings so that they cannot be modified 93 149 Object.freeze(settings); 94 150 151 const postId = parseInt(likeButton.getAttribute('data-post-id')); 152 const likes = { 153 total: parseInt(likeButton.getAttribute('data-total-likes')), 154 fromUser: parseInt(likeButton.getAttribute('data-likes-from-user')), 155 }; 156 95 157 // Define instance properties 96 158 Object.defineProperties(this, { 159 likeButton: { value: likeButton }, 160 postId: { value: postId }, 97 161 likes: { 98 162 value: { 99 total: settings.likes.total, 100 fromUser: settings.likes.fromUser, 163 total: likes.total, 164 fromUser: likes.fromUser, 165 toAdd: 0, 101 166 }, 102 167 writable: true … … 119 184 */ 120 185 Constructor.prototype.like = function () { 121 if ( parseInt(this.likes.fromUser)>= parseInt(this._settings.limit)) {186 if (this.likes.fromUser >= parseInt(this._settings.limit)) { 122 187 return; 123 188 } 124 189 125 rolpbLike++;190 this.likes.toAdd++; 126 191 this.likes.fromUser++; 127 192 128 const postLikes = parseInt(this.likes.total);129 const likeCount = document.querySelector('.wp-like-post__count');130 131 likeCount.innerHTML = (postLikes + rolpbLike).toString();193 const postLikes = this.likes.total; 194 const likeCount = this.likeButton.parentElement.querySelector('.wp-like-post__count'); 195 196 likeCount.innerHTML = (postLikes + this.likes.toAdd).toString(); 132 197 133 198 const processChanges = rolpb_debounce(() => { … … 136 201 request.onload = () => { 137 202 if (request.status >= 200 && request.status < 400) { 138 this.likes.total = this.likes.total + rolpbLike; 139 rolpbLike = 0; 203 this.likes.total = this.likes.total + this.likes.toAdd; 204 this.likes.toAdd = 0; 205 206 this.likeButton.dataset.totalLikes = this.likes.total.toString(); 140 207 } 141 208 }; 142 209 143 const postId = this. _settings.post_id;210 const postId = this.postId; 144 211 const nonce = this._settings.nonces.likePost; 145 212 146 request.send(`action=rolpb_like_post&post_id=${postId}&count=${ rolpbLike}&nonce=${nonce}`);213 request.send(`action=rolpb_like_post&post_id=${postId}&count=${this.likes.toAdd}&nonce=${nonce}`); 147 214 }, 500); 148 215 149 216 processChanges(); 150 217 151 rolpb_replaceIcon( );152 rolbp_animateIcon( );218 rolpb_replaceIcon(this.likeButton); 219 rolbp_animateIcon(this.likeButton); 153 220 }; 154 221 … … 160 227 */ 161 228 Constructor.prototype.getLikes = function () { 162 const request = rolpb_getXHR(this._settings.url); 163 164 request.onload = () => { 165 if (request.status >= 200 && request.status < 400) { 166 const response = JSON.parse(request.responseText); 167 const countEl = document.querySelector('.wp-like-post__count'); 168 const buttonEl = document.querySelector('.wp-like-post__button'); 169 170 if (!countEl || !buttonEl) { 171 return; 172 } 173 174 const likes = parseInt(response.data.likes); 175 const printedLikes = parseInt(this.likes.total); 176 177 if (likes === printedLikes) { 178 return; 179 } 180 181 if (likes > 0) { 182 buttonEl.classList.add('wp-like-post__button--liked'); 183 buttonEl.innerHTML = ROLPB.icons.active; 184 } 185 186 countEl.innerHTML = likes.toString(); 187 } 188 }; 189 190 const postId = this._settings.post_id; 191 const nonce = this._settings.nonces.getLikes; 192 const attributes = JSON.stringify(this._settings.block); 193 194 request.send(`action=rolpb_get_post_likes&post_id=${postId}&nonce=${nonce}&attributes=${attributes}`); 229 rolpb_getBulkLikes([this.postId], this._settings); 195 230 } 196 231 … … 199 234 200 235 document.addEventListener('DOMContentLoaded', () => { 201 const button = document.querySelector('.wp-like-post__button'); 202 203 if (!button || !window.ROLPB) { 204 return; 205 } 206 207 const currentPost = new lpbPost(window.ROLPB); 208 209 if (ROLPB.attributes.renderWithAjax) { 210 currentPost.getLikes(); 211 } 212 213 button.addEventListener('click', () => currentPost.like()); 236 const likeButtons = document.querySelectorAll('.wp-like-post__button'); 237 238 if (likeButtons.length === 0 || !window.ROLPB) { 239 return; 240 } 241 242 let postIds = []; 243 244 likeButtons.forEach((likeButton) => { 245 let currentPost = new lpbPost(likeButton, window.ROLPB); 246 247 if (currentPost._settings.attributes.renderWithAjax) { 248 postIds.push(currentPost.postId); 249 } 250 251 likeButton.addEventListener('click', () => currentPost.like()); 252 }); 253 254 if (postIds.length === 0) { 255 return; 256 } 257 258 rolpb_getBulkLikes(postIds, window.ROLPB); 214 259 }); -
like-post-block/tags/1.3.0/public/js/rolpb-like.min.js
r2981402 r3032462 1 let rolpbTimerId ,rolpbLike=0;function rolpb_debounce(t,e){return function(...o){rolpbTimerId&&clearTimeout(rolpbTimerId),rolpbTimerId=setTimeout((()=>{t.apply(this,o)}),e)}}function rolbp_animateIcon(){const t=document.querySelector(".wp-like-post__button svg");t&&(t.style.transform="scale(1.1)",setTimeout((()=>t.style.transform="scale(1.0)"),100))}function rolpb_replaceIcon(){const t=document.querySelector(".wp-like-post__button");t&&!t.classList.contains("wp-like-post__button--liked")&&(t.classList.add("wp-like-post__button--liked"),t.innerHTML=ROLPB.icons.active)}function rolpb_getXHR(t){const e=new XMLHttpRequest;return e.open("POST",t,!0),e.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8"),e}let lpbPost=function(){function t(t){Object.freeze(t),Object.defineProperties(this,{likes:{value:{total:t.likes.total,fromUser:t.likes.fromUser},writable:!0},_settings:{value:t}})}return t.prototype.like=function(){if(parseInt(this.likes.fromUser)>=parseInt(this._settings.limit))return;rolpbLike++,this.likes.fromUser++;const t=parseInt(this.likes.total);document.querySelector(".wp-like-post__count").innerHTML=(t+rolpbLike).toString();rolpb_debounce((()=>{const t=rolpb_getXHR(this._settings.url);t.onload=()=>{t.status>=200&&t.status<400&&(this.likes.total=this.likes.total+rolpbLike,rolpbLike=0)};const e=this._settings.post_id,o=this._settings.nonces.likePost;t.send(`action=rolpb_like_post&post_id=${e}&count=${rolpbLike}&nonce=${o}`)}),500)(),rolpb_replaceIcon(),rolbp_animateIcon()},t.prototype.getLikes=function(){const t=rolpb_getXHR(this._settings.url);t.onload=()=>{if(t.status>=200&&t.status<400){const e=JSON.parse(t.responseText),o=document.querySelector(".wp-like-post__count"),s=document.querySelector(".wp-like-post__button");if(!o||!s)return;const n=parseInt(e.data.likes);if(n===parseInt(this.likes.total))return;n>0&&(s.classList.add("wp-like-post__button--liked"),s.innerHTML=ROLPB.icons.active),o.innerHTML=n.toString()}};const e=this._settings.post_id,o=this._settings.nonces.getLikes,s=JSON.stringify(this._settings.block);t.send(`action=rolpb_get_post_likes&post_id=${e}&nonce=${o}&attributes=${s}`)},t}();document.addEventListener("DOMContentLoaded",(()=>{const t=document.querySelector(".wp-like-post__button");if(!t||!window.ROLPB)return;const e=new lpbPost(window.ROLPB);ROLPB.attributes.renderWithAjax&&e.getLikes(),t.addEventListener("click",(()=>e.like()))}));1 let rolpbTimerId;function rolpb_debounce(t,e){return function(...s){rolpbTimerId&&clearTimeout(rolpbTimerId),rolpbTimerId=setTimeout((()=>{t.apply(this,s)}),e)}}function rolbp_animateIcon(t){const e=t.querySelector("svg");e&&(e.style.transform="scale(1.1)",setTimeout((()=>e.style.transform="scale(1.0)"),100))}function rolpb_replaceIcon(t){t&&!t.classList.contains("wp-like-post__button--liked")&&(t.classList.add("wp-like-post__button--liked"),t.innerHTML=ROLPB.icons.active)}function rolpb_getXHR(t){const e=new XMLHttpRequest;return e.open("POST",t,!0),e.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8"),e}function rolpb_getBulkLikes(t,e){const s=rolpb_getXHR(e.url);s.onload=()=>{if(s.status>=200&&s.status<400){const o=JSON.parse(s.responseText);if(o.success){const s=o.data;t.forEach((t=>{const o=document.querySelector(`.wp-like-post__button[data-post-id="${t}"]`);if(!o)return;const i=o.parentElement.querySelector(".wp-like-post__count");if(!i)return;const n=parseInt(s[t]);n!==parseInt(o.getAttribute("data-total-likes"))&&(n>0&&(o.classList.add("wp-like-post__button--liked"),o.innerHTML=e.icons.active),i.innerHTML=n.toString())}))}}};const o=e.nonces.getLikes,i=JSON.stringify(e.block);s.send(`action=rolpb_get_post_likes&post_ids=${t}&nonce=${o}&attributes=${i}`)}let lpbPost=function(){function t(t,e){Object.freeze(e);const s=parseInt(t.getAttribute("data-post-id")),o={total:parseInt(t.getAttribute("data-total-likes")),fromUser:parseInt(t.getAttribute("data-likes-from-user"))};Object.defineProperties(this,{likeButton:{value:t},postId:{value:s},likes:{value:{total:o.total,fromUser:o.fromUser,toAdd:0},writable:!0},_settings:{value:e}})}return t.prototype.like=function(){if(this.likes.fromUser>=parseInt(this._settings.limit))return;this.likes.toAdd++,this.likes.fromUser++;const t=this.likes.total;this.likeButton.parentElement.querySelector(".wp-like-post__count").innerHTML=(t+this.likes.toAdd).toString();rolpb_debounce((()=>{const t=rolpb_getXHR(this._settings.url);t.onload=()=>{t.status>=200&&t.status<400&&(this.likes.total=this.likes.total+this.likes.toAdd,this.likes.toAdd=0,this.likeButton.dataset.totalLikes=this.likes.total.toString())};const e=this.postId,s=this._settings.nonces.likePost;t.send(`action=rolpb_like_post&post_id=${e}&count=${this.likes.toAdd}&nonce=${s}`)}),500)(),rolpb_replaceIcon(this.likeButton),rolbp_animateIcon(this.likeButton)},t.prototype.getLikes=function(){rolpb_getBulkLikes([this.postId],this._settings)},t}();document.addEventListener("DOMContentLoaded",(()=>{const t=document.querySelectorAll(".wp-like-post__button");if(0===t.length||!window.ROLPB)return;let e=[];t.forEach((t=>{let s=new lpbPost(t,window.ROLPB);s._settings.attributes.renderWithAjax&&e.push(s.postId),t.addEventListener("click",(()=>s.like()))})),0!==e.length&&rolpb_getBulkLikes(e,window.ROLPB)})); -
like-post-block/tags/1.3.0/readme.txt
r2981402 r3032462 3 3 Tags: like, heart, like post, block 4 4 Requires at least: 6.2 5 Tested up to: 6. 3.15 Tested up to: 6.4.3 6 6 Requires PHP: 7.4 7 Stable tag: 1. 2.07 Stable tag: 1.3.0 8 8 License: GPL-2.0-or-later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 64 64 == Changelog == 65 65 66 = 1.3.0 = 67 68 * Like counter functionality uses last post inside query loop (#8). 69 66 70 = 1.2.0 = 67 71 -
like-post-block/trunk/constants.php
r2981402 r3032462 10 10 * @since 1.0.0 11 11 */ 12 const ROLPB_VERSION = '1. 2.0';12 const ROLPB_VERSION = '1.3.0'; 13 13 14 14 /** -
like-post-block/trunk/helpers.php
r2981402 r3032462 39 39 * 40 40 * @since 1.0.0 41 * @since 1.3.0 Change parameter type to WP_Post to get custom properties inside function. 41 42 * 42 * @param int $likes The number of likes.43 * @param array $attributes The block attributes.44 * @param string $icon_type The icon type.43 * @param int $total_likes The total number of likes for the post. 44 * @param int $post_id The post ID. 45 * @param array $attributes The block attributes. 45 46 * @return string The rendered block HTML. 46 47 */ 47 function rolpb_get_rendered_html( 48 int $likes,49 array $attributes,50 string $icon_type = 'inactive'51 ): string { 52 $button_css = 'active' === $ icon_type? 'wp-like-post__button--liked' : '';48 function rolpb_get_rendered_html( int $total_likes, int $post_id, array $attributes ): string { 49 // Set default for custom attributes. 50 $attributes['icon_type'] ??= 'inactive'; 51 $attributes['likes_from_user'] ??= 0; 52 53 $button_css = 'active' === $attributes['icon_type'] ? 'wp-like-post__button--liked' : ''; 53 54 $block_attributes = ! str_contains( $_SERVER['REQUEST_URI'], '/wp-json/' ) 54 55 ? get_block_wrapper_attributes( array( 'class' => 'wp-like-post__count' ) ) … … 61 62 $attributes['iconWidth'] ??= ROLPB_DEFAULT_ICON_WIDTH; 62 63 63 $html = '<div class="wp-like-post__wrapper" style="' . $gap_styles . '">'; 64 $html .= '<button type="button" class="wp-like-post__button ' . $button_css . '" '; 65 $html .= 'style="height: ' . $attributes['iconWidth'] . 'px; '; 66 $html .= 'color: ' . $attributes['iconColorValue'] . ';">'; 67 $html .= rolpb_get_svg_icon( $attributes['icon'], $attributes['iconWidth'], $icon_type ); 64 $html = '<div class="wp-like-post__wrapper" style="' . esc_attr( $gap_styles ) . '">'; 65 $html .= '<button type="button" class="wp-like-post__button ' . esc_attr( $button_css ) . '" '; 66 $html .= 'style="height: ' . esc_attr( $attributes['iconWidth'] ) . 'px; '; 67 $html .= 'color: ' . esc_attr( $attributes['iconColorValue'] ) . ';" '; 68 $html .= 'data-post-id="' . esc_attr( $post_id ) . '" data-total-likes="' . esc_attr( $total_likes ) . '" '; 69 $html .= 'data-likes-from-user="' . esc_attr( $attributes['likes_from_user'] ) . '">'; 70 $html .= rolpb_get_svg_icon( $attributes['icon'], $attributes['iconWidth'], $attributes['icon_type'] ); 68 71 $html .= '</button>'; 69 72 70 $html .= '<div ' . $block_attributes . '>' . $likes. '</div>';73 $html .= '<div ' . $block_attributes . '>' . esc_html( $total_likes ) . '</div>'; 71 74 $html .= '</div>'; 72 75 … … 75 78 * 76 79 * @since 1.1.0 80 * @since 1.3.0 Add `$post_id` parameters. 77 81 * 78 82 * @param string $html The rendered block HTML. 83 * @param int $post_id The post id. 79 84 * @param array $attributes The block attributes. 80 85 */ 81 return apply_filters( 'rolpb_likes_rendered_html', $html, $ attributes );86 return apply_filters( 'rolpb_likes_rendered_html', $html, $post_id, $attributes ); 82 87 } 83 88 -
like-post-block/trunk/includes/class-rolpb-block.php
r2981402 r3032462 51 51 } 52 52 53 $rolpb_post = new ROLPB_Post( $post );54 55 53 wp_enqueue_script( 56 54 'lpb-like', … … 75 73 'getLikes' => wp_create_nonce( 'rolpb-get-post-likes-nonce' ), 76 74 'likePost' => wp_create_nonce( 'rolpb-like-post-nonce' ), 77 ),78 'post_id' => $post->ID,79 'likes' => array(80 'total' => $rolpb_post->likes(),81 'fromUser' => $rolpb_post->likes_from_user(),82 75 ), 83 76 'url' => admin_url( 'admin-ajax.php' ), … … 128 121 * 129 122 * @since 1.0.0 123 * @since 1.3.0 Send custom attributes inside `$attributes` array. 130 124 * 131 125 * @param array $attributes The block attributes. … … 136 130 137 131 if ( ! $post ) { 138 return rolpb_get_rendered_html( 0, $attributes );132 return rolpb_get_rendered_html( 0, 0, $attributes ); 139 133 } 140 134 141 $rolpb_post = new ROLPB_Post( $post );142 $likes = $rolpb_post->likes();143 $ icon_type = $likes && $rolpb_post->likes_from_user() ? 'active' : 'inactive';135 $rolpb_post = new ROLPB_Post( $post ); 136 $likes = $rolpb_post->likes(); 137 $likes_from_user = $rolpb_post->likes_from_user(); 144 138 145 return rolpb_get_rendered_html( $likes, $attributes, $icon_type ); 139 // Set custom attributes. 140 $attributes['icon_type'] = $likes && $likes_from_user ? 'active' : 'inactive'; 141 $attributes['likes_from_user'] = $likes_from_user; 142 143 return rolpb_get_rendered_html( $likes, $post->ID, $attributes ); 146 144 } 147 145 } -
like-post-block/trunk/includes/class-rolpb-like.php
r2981402 r3032462 27 27 * 28 28 * @since 1.1.0 29 * @since 1.3.0 Accept post ids as a comma-separated string (bulk mode). 29 30 */ 30 31 public function get(): void { … … 35 36 } 36 37 37 if ( ! isset( $_POST['post_id'] ) ) {38 wp_send_json_error( ' The required data does not exist.' );38 if ( empty( $_POST['post_ids'] ) ) { 39 wp_send_json_error( 'Missing post ids.' ); 39 40 } 40 41 41 $post_id = intval( sanitize_text_field( $_POST['post_id'] ) ); 42 $post = new ROLPB_Post( $post_id ); 42 $post_ids = explode( ',', sanitize_text_field( $_POST['post_ids'] ) ); 43 43 44 wp_send_json_success( array( 45 'likes' => $post->likes(), 46 'post_id' => $post_id, 47 ) ); 44 if ( empty( $post_ids ) ) { 45 wp_send_json_error( 'Invalid post ids.' ); 46 } 47 48 $likes = array(); 49 50 foreach ( $post_ids as $post_id ) { 51 $post = new ROLPB_Post( $post_id ); 52 $likes[ $post_id ] = $post->likes(); 53 } 54 55 wp_send_json_success( $likes ); 48 56 } 49 57 -
like-post-block/trunk/like-post-block.php
r2981402 r3032462 6 6 * Requires at least: 6.2 7 7 * Requires PHP: 7.4 8 * Version: 1. 2.08 * Version: 1.3.0 9 9 * Author: Roel Magdaleno 10 10 * Author URI: https://roelmagdaleno.com -
like-post-block/trunk/public/js/rolpb-like.js
r2981402 r3032462 1 1 let rolpbTimerId; 2 let rolpbLike = 0;3 2 4 3 /** … … 30 29 * 31 30 * @since 1.0.0 32 */ 33 function rolbp_animateIcon() { 34 const icon = document.querySelector('.wp-like-post__button svg'); 31 * 32 * @param {object} likeButton The like button element. 33 */ 34 function rolbp_animateIcon(likeButton) { 35 const icon = likeButton.querySelector('svg'); 35 36 36 37 if (!icon) { … … 48 49 * @since 1.0.0 49 50 */ 50 function rolpb_replaceIcon() { 51 const button = document.querySelector('.wp-like-post__button'); 52 53 if (!button || button.classList.contains('wp-like-post__button--liked')) { 51 function rolpb_replaceIcon(likeButton) { 52 if (!likeButton || likeButton.classList.contains('wp-like-post__button--liked')) { 54 53 return; 55 54 } 56 55 57 button.classList.add('wp-like-post__button--liked');58 button.innerHTML = ROLPB.icons.active;56 likeButton.classList.add('wp-like-post__button--liked'); 57 likeButton.innerHTML = ROLPB.icons.active; 59 58 } 60 59 … … 79 78 } 80 79 80 /** 81 * Get the total number of likes for multiple posts. 82 * We send an AJAX request to the server and update the like count. 83 * 84 * @since 1.3.0 85 * 86 * @param {array} postIds The post IDs. 87 * @param {object} settings The settings object. 88 */ 89 function rolpb_getBulkLikes(postIds, settings) { 90 const request = rolpb_getXHR(settings.url); 91 92 request.onload = () => { 93 if (request.status >= 200 && request.status < 400) { 94 const response = JSON.parse(request.responseText); 95 96 if (response.success) { 97 const postsWithLikes = response.data; 98 99 postIds.forEach((id) => { 100 const likeButton = document.querySelector(`.wp-like-post__button[data-post-id="${id}"]`); 101 102 if (!likeButton) { 103 return; 104 } 105 106 const countEl = likeButton.parentElement.querySelector('.wp-like-post__count'); 107 108 if (!countEl) { 109 return; 110 } 111 112 const likes = parseInt(postsWithLikes[id]); 113 const printedLikes = parseInt(likeButton.getAttribute('data-total-likes')); 114 115 if (likes === printedLikes) { 116 return; 117 } 118 119 if (likes > 0) { 120 likeButton.classList.add('wp-like-post__button--liked'); 121 likeButton.innerHTML = settings.icons.active; 122 } 123 124 countEl.innerHTML = likes.toString(); 125 }); 126 } 127 } 128 }; 129 130 const nonce = settings.nonces.getLikes; 131 const attributes = JSON.stringify(settings.block); 132 133 request.send(`action=rolpb_get_post_likes&post_ids=${postIds}&nonce=${nonce}&attributes=${attributes}`); 134 } 135 81 136 let lpbPost = (function () { 82 137 /** … … 85 140 * @since 1.0.0 86 141 * 142 * @param {object} likeButton The like button element. 87 143 * @param {object} settings The settings object. 88 144 * 89 145 * @constructor 90 146 */ 91 function Constructor( settings) {147 function Constructor(likeButton, settings) { 92 148 // Freeze settings so that they cannot be modified 93 149 Object.freeze(settings); 94 150 151 const postId = parseInt(likeButton.getAttribute('data-post-id')); 152 const likes = { 153 total: parseInt(likeButton.getAttribute('data-total-likes')), 154 fromUser: parseInt(likeButton.getAttribute('data-likes-from-user')), 155 }; 156 95 157 // Define instance properties 96 158 Object.defineProperties(this, { 159 likeButton: { value: likeButton }, 160 postId: { value: postId }, 97 161 likes: { 98 162 value: { 99 total: settings.likes.total, 100 fromUser: settings.likes.fromUser, 163 total: likes.total, 164 fromUser: likes.fromUser, 165 toAdd: 0, 101 166 }, 102 167 writable: true … … 119 184 */ 120 185 Constructor.prototype.like = function () { 121 if ( parseInt(this.likes.fromUser)>= parseInt(this._settings.limit)) {186 if (this.likes.fromUser >= parseInt(this._settings.limit)) { 122 187 return; 123 188 } 124 189 125 rolpbLike++;190 this.likes.toAdd++; 126 191 this.likes.fromUser++; 127 192 128 const postLikes = parseInt(this.likes.total);129 const likeCount = document.querySelector('.wp-like-post__count');130 131 likeCount.innerHTML = (postLikes + rolpbLike).toString();193 const postLikes = this.likes.total; 194 const likeCount = this.likeButton.parentElement.querySelector('.wp-like-post__count'); 195 196 likeCount.innerHTML = (postLikes + this.likes.toAdd).toString(); 132 197 133 198 const processChanges = rolpb_debounce(() => { … … 136 201 request.onload = () => { 137 202 if (request.status >= 200 && request.status < 400) { 138 this.likes.total = this.likes.total + rolpbLike; 139 rolpbLike = 0; 203 this.likes.total = this.likes.total + this.likes.toAdd; 204 this.likes.toAdd = 0; 205 206 this.likeButton.dataset.totalLikes = this.likes.total.toString(); 140 207 } 141 208 }; 142 209 143 const postId = this. _settings.post_id;210 const postId = this.postId; 144 211 const nonce = this._settings.nonces.likePost; 145 212 146 request.send(`action=rolpb_like_post&post_id=${postId}&count=${ rolpbLike}&nonce=${nonce}`);213 request.send(`action=rolpb_like_post&post_id=${postId}&count=${this.likes.toAdd}&nonce=${nonce}`); 147 214 }, 500); 148 215 149 216 processChanges(); 150 217 151 rolpb_replaceIcon( );152 rolbp_animateIcon( );218 rolpb_replaceIcon(this.likeButton); 219 rolbp_animateIcon(this.likeButton); 153 220 }; 154 221 … … 160 227 */ 161 228 Constructor.prototype.getLikes = function () { 162 const request = rolpb_getXHR(this._settings.url); 163 164 request.onload = () => { 165 if (request.status >= 200 && request.status < 400) { 166 const response = JSON.parse(request.responseText); 167 const countEl = document.querySelector('.wp-like-post__count'); 168 const buttonEl = document.querySelector('.wp-like-post__button'); 169 170 if (!countEl || !buttonEl) { 171 return; 172 } 173 174 const likes = parseInt(response.data.likes); 175 const printedLikes = parseInt(this.likes.total); 176 177 if (likes === printedLikes) { 178 return; 179 } 180 181 if (likes > 0) { 182 buttonEl.classList.add('wp-like-post__button--liked'); 183 buttonEl.innerHTML = ROLPB.icons.active; 184 } 185 186 countEl.innerHTML = likes.toString(); 187 } 188 }; 189 190 const postId = this._settings.post_id; 191 const nonce = this._settings.nonces.getLikes; 192 const attributes = JSON.stringify(this._settings.block); 193 194 request.send(`action=rolpb_get_post_likes&post_id=${postId}&nonce=${nonce}&attributes=${attributes}`); 229 rolpb_getBulkLikes([this.postId], this._settings); 195 230 } 196 231 … … 199 234 200 235 document.addEventListener('DOMContentLoaded', () => { 201 const button = document.querySelector('.wp-like-post__button'); 202 203 if (!button || !window.ROLPB) { 204 return; 205 } 206 207 const currentPost = new lpbPost(window.ROLPB); 208 209 if (ROLPB.attributes.renderWithAjax) { 210 currentPost.getLikes(); 211 } 212 213 button.addEventListener('click', () => currentPost.like()); 236 const likeButtons = document.querySelectorAll('.wp-like-post__button'); 237 238 if (likeButtons.length === 0 || !window.ROLPB) { 239 return; 240 } 241 242 let postIds = []; 243 244 likeButtons.forEach((likeButton) => { 245 let currentPost = new lpbPost(likeButton, window.ROLPB); 246 247 if (currentPost._settings.attributes.renderWithAjax) { 248 postIds.push(currentPost.postId); 249 } 250 251 likeButton.addEventListener('click', () => currentPost.like()); 252 }); 253 254 if (postIds.length === 0) { 255 return; 256 } 257 258 rolpb_getBulkLikes(postIds, window.ROLPB); 214 259 }); -
like-post-block/trunk/public/js/rolpb-like.min.js
r2981402 r3032462 1 let rolpbTimerId ,rolpbLike=0;function rolpb_debounce(t,e){return function(...o){rolpbTimerId&&clearTimeout(rolpbTimerId),rolpbTimerId=setTimeout((()=>{t.apply(this,o)}),e)}}function rolbp_animateIcon(){const t=document.querySelector(".wp-like-post__button svg");t&&(t.style.transform="scale(1.1)",setTimeout((()=>t.style.transform="scale(1.0)"),100))}function rolpb_replaceIcon(){const t=document.querySelector(".wp-like-post__button");t&&!t.classList.contains("wp-like-post__button--liked")&&(t.classList.add("wp-like-post__button--liked"),t.innerHTML=ROLPB.icons.active)}function rolpb_getXHR(t){const e=new XMLHttpRequest;return e.open("POST",t,!0),e.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8"),e}let lpbPost=function(){function t(t){Object.freeze(t),Object.defineProperties(this,{likes:{value:{total:t.likes.total,fromUser:t.likes.fromUser},writable:!0},_settings:{value:t}})}return t.prototype.like=function(){if(parseInt(this.likes.fromUser)>=parseInt(this._settings.limit))return;rolpbLike++,this.likes.fromUser++;const t=parseInt(this.likes.total);document.querySelector(".wp-like-post__count").innerHTML=(t+rolpbLike).toString();rolpb_debounce((()=>{const t=rolpb_getXHR(this._settings.url);t.onload=()=>{t.status>=200&&t.status<400&&(this.likes.total=this.likes.total+rolpbLike,rolpbLike=0)};const e=this._settings.post_id,o=this._settings.nonces.likePost;t.send(`action=rolpb_like_post&post_id=${e}&count=${rolpbLike}&nonce=${o}`)}),500)(),rolpb_replaceIcon(),rolbp_animateIcon()},t.prototype.getLikes=function(){const t=rolpb_getXHR(this._settings.url);t.onload=()=>{if(t.status>=200&&t.status<400){const e=JSON.parse(t.responseText),o=document.querySelector(".wp-like-post__count"),s=document.querySelector(".wp-like-post__button");if(!o||!s)return;const n=parseInt(e.data.likes);if(n===parseInt(this.likes.total))return;n>0&&(s.classList.add("wp-like-post__button--liked"),s.innerHTML=ROLPB.icons.active),o.innerHTML=n.toString()}};const e=this._settings.post_id,o=this._settings.nonces.getLikes,s=JSON.stringify(this._settings.block);t.send(`action=rolpb_get_post_likes&post_id=${e}&nonce=${o}&attributes=${s}`)},t}();document.addEventListener("DOMContentLoaded",(()=>{const t=document.querySelector(".wp-like-post__button");if(!t||!window.ROLPB)return;const e=new lpbPost(window.ROLPB);ROLPB.attributes.renderWithAjax&&e.getLikes(),t.addEventListener("click",(()=>e.like()))}));1 let rolpbTimerId;function rolpb_debounce(t,e){return function(...s){rolpbTimerId&&clearTimeout(rolpbTimerId),rolpbTimerId=setTimeout((()=>{t.apply(this,s)}),e)}}function rolbp_animateIcon(t){const e=t.querySelector("svg");e&&(e.style.transform="scale(1.1)",setTimeout((()=>e.style.transform="scale(1.0)"),100))}function rolpb_replaceIcon(t){t&&!t.classList.contains("wp-like-post__button--liked")&&(t.classList.add("wp-like-post__button--liked"),t.innerHTML=ROLPB.icons.active)}function rolpb_getXHR(t){const e=new XMLHttpRequest;return e.open("POST",t,!0),e.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8"),e}function rolpb_getBulkLikes(t,e){const s=rolpb_getXHR(e.url);s.onload=()=>{if(s.status>=200&&s.status<400){const o=JSON.parse(s.responseText);if(o.success){const s=o.data;t.forEach((t=>{const o=document.querySelector(`.wp-like-post__button[data-post-id="${t}"]`);if(!o)return;const i=o.parentElement.querySelector(".wp-like-post__count");if(!i)return;const n=parseInt(s[t]);n!==parseInt(o.getAttribute("data-total-likes"))&&(n>0&&(o.classList.add("wp-like-post__button--liked"),o.innerHTML=e.icons.active),i.innerHTML=n.toString())}))}}};const o=e.nonces.getLikes,i=JSON.stringify(e.block);s.send(`action=rolpb_get_post_likes&post_ids=${t}&nonce=${o}&attributes=${i}`)}let lpbPost=function(){function t(t,e){Object.freeze(e);const s=parseInt(t.getAttribute("data-post-id")),o={total:parseInt(t.getAttribute("data-total-likes")),fromUser:parseInt(t.getAttribute("data-likes-from-user"))};Object.defineProperties(this,{likeButton:{value:t},postId:{value:s},likes:{value:{total:o.total,fromUser:o.fromUser,toAdd:0},writable:!0},_settings:{value:e}})}return t.prototype.like=function(){if(this.likes.fromUser>=parseInt(this._settings.limit))return;this.likes.toAdd++,this.likes.fromUser++;const t=this.likes.total;this.likeButton.parentElement.querySelector(".wp-like-post__count").innerHTML=(t+this.likes.toAdd).toString();rolpb_debounce((()=>{const t=rolpb_getXHR(this._settings.url);t.onload=()=>{t.status>=200&&t.status<400&&(this.likes.total=this.likes.total+this.likes.toAdd,this.likes.toAdd=0,this.likeButton.dataset.totalLikes=this.likes.total.toString())};const e=this.postId,s=this._settings.nonces.likePost;t.send(`action=rolpb_like_post&post_id=${e}&count=${this.likes.toAdd}&nonce=${s}`)}),500)(),rolpb_replaceIcon(this.likeButton),rolbp_animateIcon(this.likeButton)},t.prototype.getLikes=function(){rolpb_getBulkLikes([this.postId],this._settings)},t}();document.addEventListener("DOMContentLoaded",(()=>{const t=document.querySelectorAll(".wp-like-post__button");if(0===t.length||!window.ROLPB)return;let e=[];t.forEach((t=>{let s=new lpbPost(t,window.ROLPB);s._settings.attributes.renderWithAjax&&e.push(s.postId),t.addEventListener("click",(()=>s.like()))})),0!==e.length&&rolpb_getBulkLikes(e,window.ROLPB)})); -
like-post-block/trunk/readme.txt
r2981402 r3032462 3 3 Tags: like, heart, like post, block 4 4 Requires at least: 6.2 5 Tested up to: 6. 3.15 Tested up to: 6.4.3 6 6 Requires PHP: 7.4 7 Stable tag: 1. 2.07 Stable tag: 1.3.0 8 8 License: GPL-2.0-or-later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 64 64 == Changelog == 65 65 66 = 1.3.0 = 67 68 * Like counter functionality uses last post inside query loop (#8). 69 66 70 = 1.2.0 = 67 71
Note: See TracChangeset
for help on using the changeset viewer.