Plugin Directory

Changeset 3032462


Ignore:
Timestamp:
02/07/2024 01:06:59 AM (2 years ago)
Author:
RokuMetal
Message:

Update to version 1.3.0 from GitHub

Location:
like-post-block
Files:
16 edited
1 copied

Legend:

Unmodified
Added
Removed
  • like-post-block/tags/1.3.0/constants.php

    r2981402 r3032462  
    1010 * @since 1.0.0
    1111 */
    12 const ROLPB_VERSION = '1.2.0';
     12const ROLPB_VERSION = '1.3.0';
    1313
    1414/**
  • like-post-block/tags/1.3.0/helpers.php

    r2981402 r3032462  
    3939 *
    4040 * @since  1.0.0
     41 * @since  1.3.0 Change parameter type to WP_Post to get custom properties inside function.
    4142 *
    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.
    4546 * @return string                 The rendered block HTML.
    4647 */
    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' : '';
     48function 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' : '';
    5354    $block_attributes = ! str_contains( $_SERVER['REQUEST_URI'], '/wp-json/' )
    5455        ? get_block_wrapper_attributes( array( 'class' => 'wp-like-post__count' ) )
     
    6162    $attributes['iconWidth']      ??= ROLPB_DEFAULT_ICON_WIDTH;
    6263
    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'] );
    6871    $html .= '</button>';
    6972
    70     $html .= '<div ' . $block_attributes . '>' . $likes . '</div>';
     73    $html .= '<div ' . $block_attributes . '>' . esc_html( $total_likes ) . '</div>';
    7174    $html .= '</div>';
    7275
     
    7578     *
    7679     * @since 1.1.0
     80     * @since 1.3.0 Add `$post_id` parameters.
    7781     *
    7882     * @param string   $html         The rendered block HTML.
     83     * @param int      $post_id      The post id.
    7984     * @param array    $attributes   The block attributes.
    8085     */
    81     return apply_filters( 'rolpb_likes_rendered_html', $html, $attributes );
     86    return apply_filters( 'rolpb_likes_rendered_html', $html, $post_id, $attributes );
    8287}
    8388
  • like-post-block/tags/1.3.0/includes/class-rolpb-block.php

    r2981402 r3032462  
    5151        }
    5252
    53         $rolpb_post = new ROLPB_Post( $post );
    54 
    5553        wp_enqueue_script(
    5654            'lpb-like',
     
    7573                'getLikes' => wp_create_nonce( 'rolpb-get-post-likes-nonce' ),
    7674                '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(),
    8275            ),
    8376            'url'        => admin_url( 'admin-ajax.php' ),
     
    128121     *
    129122     * @since  1.0.0
     123     * @since  1.3.0 Send custom attributes inside `$attributes` array.
    130124     *
    131125     * @param  array   $attributes   The block attributes.
     
    136130
    137131        if ( ! $post ) {
    138             return rolpb_get_rendered_html( 0, $attributes );
     132            return rolpb_get_rendered_html( 0, 0, $attributes );
    139133        }
    140134
    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();
    144138
    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 );
    146144    }
    147145}
  • like-post-block/tags/1.3.0/includes/class-rolpb-like.php

    r2981402 r3032462  
    2727     *
    2828     * @since 1.1.0
     29     * @since 1.3.0 Accept post ids as a comma-separated string (bulk mode).
    2930     */
    3031    public function get(): void {
     
    3536        }
    3637
    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.' );
    3940        }
    4041
    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'] ) );
    4343
    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 );
    4856    }
    4957
  • like-post-block/tags/1.3.0/like-post-block.php

    r2981402 r3032462  
    66 * Requires at least: 6.2
    77 * Requires PHP:      7.4
    8  * Version:           1.2.0
     8 * Version:           1.3.0
    99 * Author:            Roel Magdaleno
    1010 * Author URI:        https://roelmagdaleno.com
  • like-post-block/tags/1.3.0/public/js/rolpb-like.js

    r2981402 r3032462  
    11let rolpbTimerId;
    2 let rolpbLike = 0;
    32
    43/**
     
    3029 *
    3130 * @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 */
     34function rolbp_animateIcon(likeButton) {
     35    const icon = likeButton.querySelector('svg');
    3536
    3637    if (!icon) {
     
    4849 * @since 1.0.0
    4950 */
    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')) {
     51function rolpb_replaceIcon(likeButton) {
     52    if (!likeButton || likeButton.classList.contains('wp-like-post__button--liked')) {
    5453        return;
    5554    }
    5655
    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;
    5958}
    6059
     
    7978}
    8079
     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 */
     89function 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
    81136let lpbPost = (function () {
    82137    /**
     
    85140     * @since 1.0.0
    86141     *
     142     * @param {object} likeButton The like button element.
    87143     * @param {object} settings The settings object.
    88144     *
    89145     * @constructor
    90146     */
    91     function Constructor(settings) {
     147    function Constructor(likeButton, settings) {
    92148        // Freeze settings so that they cannot be modified
    93149        Object.freeze(settings);
    94150
     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
    95157        // Define instance properties
    96158        Object.defineProperties(this, {
     159            likeButton: { value: likeButton },
     160            postId: { value: postId },
    97161            likes: {
    98162                value: {
    99                     total: settings.likes.total,
    100                     fromUser: settings.likes.fromUser,
     163                    total: likes.total,
     164                    fromUser: likes.fromUser,
     165                    toAdd: 0,
    101166                },
    102167                writable: true
     
    119184     */
    120185    Constructor.prototype.like = function () {
    121         if (parseInt(this.likes.fromUser) >= parseInt(this._settings.limit)) {
     186        if (this.likes.fromUser >= parseInt(this._settings.limit)) {
    122187            return;
    123188        }
    124189
    125         rolpbLike++;
     190        this.likes.toAdd++;
    126191        this.likes.fromUser++;
    127192
    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();
    132197
    133198        const processChanges = rolpb_debounce(() => {
     
    136201            request.onload = () => {
    137202                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();
    140207                }
    141208            };
    142209
    143             const postId = this._settings.post_id;
     210            const postId = this.postId;
    144211            const nonce = this._settings.nonces.likePost;
    145212
    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}`);
    147214        }, 500);
    148215
    149216        processChanges();
    150217
    151         rolpb_replaceIcon();
    152         rolbp_animateIcon();
     218        rolpb_replaceIcon(this.likeButton);
     219        rolbp_animateIcon(this.likeButton);
    153220    };
    154221
     
    160227     */
    161228    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);
    195230    }
    196231
     
    199234
    200235document.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);
    214259});
  • 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()))}));
     1let 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  
    33Tags:              like, heart, like post, block
    44Requires at least: 6.2
    5 Tested up to:      6.3.1
     5Tested up to:      6.4.3
    66Requires PHP:      7.4
    7 Stable tag:        1.2.0
     7Stable tag:        1.3.0
    88License:           GPL-2.0-or-later
    99License URI:       https://www.gnu.org/licenses/gpl-2.0.html
     
    6464== Changelog ==
    6565
     66= 1.3.0 =
     67
     68* Like counter functionality uses last post inside query loop (#8).
     69
    6670= 1.2.0 =
    6771
  • like-post-block/trunk/constants.php

    r2981402 r3032462  
    1010 * @since 1.0.0
    1111 */
    12 const ROLPB_VERSION = '1.2.0';
     12const ROLPB_VERSION = '1.3.0';
    1313
    1414/**
  • like-post-block/trunk/helpers.php

    r2981402 r3032462  
    3939 *
    4040 * @since  1.0.0
     41 * @since  1.3.0 Change parameter type to WP_Post to get custom properties inside function.
    4142 *
    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.
    4546 * @return string                 The rendered block HTML.
    4647 */
    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' : '';
     48function 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' : '';
    5354    $block_attributes = ! str_contains( $_SERVER['REQUEST_URI'], '/wp-json/' )
    5455        ? get_block_wrapper_attributes( array( 'class' => 'wp-like-post__count' ) )
     
    6162    $attributes['iconWidth']      ??= ROLPB_DEFAULT_ICON_WIDTH;
    6263
    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'] );
    6871    $html .= '</button>';
    6972
    70     $html .= '<div ' . $block_attributes . '>' . $likes . '</div>';
     73    $html .= '<div ' . $block_attributes . '>' . esc_html( $total_likes ) . '</div>';
    7174    $html .= '</div>';
    7275
     
    7578     *
    7679     * @since 1.1.0
     80     * @since 1.3.0 Add `$post_id` parameters.
    7781     *
    7882     * @param string   $html         The rendered block HTML.
     83     * @param int      $post_id      The post id.
    7984     * @param array    $attributes   The block attributes.
    8085     */
    81     return apply_filters( 'rolpb_likes_rendered_html', $html, $attributes );
     86    return apply_filters( 'rolpb_likes_rendered_html', $html, $post_id, $attributes );
    8287}
    8388
  • like-post-block/trunk/includes/class-rolpb-block.php

    r2981402 r3032462  
    5151        }
    5252
    53         $rolpb_post = new ROLPB_Post( $post );
    54 
    5553        wp_enqueue_script(
    5654            'lpb-like',
     
    7573                'getLikes' => wp_create_nonce( 'rolpb-get-post-likes-nonce' ),
    7674                '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(),
    8275            ),
    8376            'url'        => admin_url( 'admin-ajax.php' ),
     
    128121     *
    129122     * @since  1.0.0
     123     * @since  1.3.0 Send custom attributes inside `$attributes` array.
    130124     *
    131125     * @param  array   $attributes   The block attributes.
     
    136130
    137131        if ( ! $post ) {
    138             return rolpb_get_rendered_html( 0, $attributes );
     132            return rolpb_get_rendered_html( 0, 0, $attributes );
    139133        }
    140134
    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();
    144138
    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 );
    146144    }
    147145}
  • like-post-block/trunk/includes/class-rolpb-like.php

    r2981402 r3032462  
    2727     *
    2828     * @since 1.1.0
     29     * @since 1.3.0 Accept post ids as a comma-separated string (bulk mode).
    2930     */
    3031    public function get(): void {
     
    3536        }
    3637
    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.' );
    3940        }
    4041
    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'] ) );
    4343
    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 );
    4856    }
    4957
  • like-post-block/trunk/like-post-block.php

    r2981402 r3032462  
    66 * Requires at least: 6.2
    77 * Requires PHP:      7.4
    8  * Version:           1.2.0
     8 * Version:           1.3.0
    99 * Author:            Roel Magdaleno
    1010 * Author URI:        https://roelmagdaleno.com
  • like-post-block/trunk/public/js/rolpb-like.js

    r2981402 r3032462  
    11let rolpbTimerId;
    2 let rolpbLike = 0;
    32
    43/**
     
    3029 *
    3130 * @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 */
     34function rolbp_animateIcon(likeButton) {
     35    const icon = likeButton.querySelector('svg');
    3536
    3637    if (!icon) {
     
    4849 * @since 1.0.0
    4950 */
    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')) {
     51function rolpb_replaceIcon(likeButton) {
     52    if (!likeButton || likeButton.classList.contains('wp-like-post__button--liked')) {
    5453        return;
    5554    }
    5655
    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;
    5958}
    6059
     
    7978}
    8079
     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 */
     89function 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
    81136let lpbPost = (function () {
    82137    /**
     
    85140     * @since 1.0.0
    86141     *
     142     * @param {object} likeButton The like button element.
    87143     * @param {object} settings The settings object.
    88144     *
    89145     * @constructor
    90146     */
    91     function Constructor(settings) {
     147    function Constructor(likeButton, settings) {
    92148        // Freeze settings so that they cannot be modified
    93149        Object.freeze(settings);
    94150
     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
    95157        // Define instance properties
    96158        Object.defineProperties(this, {
     159            likeButton: { value: likeButton },
     160            postId: { value: postId },
    97161            likes: {
    98162                value: {
    99                     total: settings.likes.total,
    100                     fromUser: settings.likes.fromUser,
     163                    total: likes.total,
     164                    fromUser: likes.fromUser,
     165                    toAdd: 0,
    101166                },
    102167                writable: true
     
    119184     */
    120185    Constructor.prototype.like = function () {
    121         if (parseInt(this.likes.fromUser) >= parseInt(this._settings.limit)) {
     186        if (this.likes.fromUser >= parseInt(this._settings.limit)) {
    122187            return;
    123188        }
    124189
    125         rolpbLike++;
     190        this.likes.toAdd++;
    126191        this.likes.fromUser++;
    127192
    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();
    132197
    133198        const processChanges = rolpb_debounce(() => {
     
    136201            request.onload = () => {
    137202                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();
    140207                }
    141208            };
    142209
    143             const postId = this._settings.post_id;
     210            const postId = this.postId;
    144211            const nonce = this._settings.nonces.likePost;
    145212
    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}`);
    147214        }, 500);
    148215
    149216        processChanges();
    150217
    151         rolpb_replaceIcon();
    152         rolbp_animateIcon();
     218        rolpb_replaceIcon(this.likeButton);
     219        rolbp_animateIcon(this.likeButton);
    153220    };
    154221
     
    160227     */
    161228    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);
    195230    }
    196231
     
    199234
    200235document.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);
    214259});
  • 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()))}));
     1let 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  
    33Tags:              like, heart, like post, block
    44Requires at least: 6.2
    5 Tested up to:      6.3.1
     5Tested up to:      6.4.3
    66Requires PHP:      7.4
    7 Stable tag:        1.2.0
     7Stable tag:        1.3.0
    88License:           GPL-2.0-or-later
    99License URI:       https://www.gnu.org/licenses/gpl-2.0.html
     
    6464== Changelog ==
    6565
     66= 1.3.0 =
     67
     68* Like counter functionality uses last post inside query loop (#8).
     69
    6670= 1.2.0 =
    6771
Note: See TracChangeset for help on using the changeset viewer.