WP Manifestindependent plugin directory
manifest / social / air-reactions

Air Reactions WP Registry grade B. Medium-severity findings · 1 findingWP RegistryMedium-severity findings · 1 findingOpen the reportB

A developer-friendly WordPress-plugin for adding customizable reactions (likes, hearts, dislikes, shrugs or whatever you feel like) to your content.

★ 24stars
1.0.1latest · 5 years ago

Install

Download source zip No release zip yet

This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/digitoimistodude/air-reactions/archive/refs/heads/master.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

A developer-friendly WordPress-plugin for adding customizable reactions (likes, hearts, dislikes, shrugs or whatever you feel like) to your content.

Usage

Basic usage

Use shortcode [air-reactions] in your content or call hook air_reactions_display on your template file

do_action( 'air_reactions_display', [] );

It will echo the reaction container with default buttons where called. You can specify the reaction types using 'air_reactions_types' filter.

Advanced usage

Available parameters are:

  [
    'echo'    => (bool),
    'types'   => (array),
    'post_id' => (int),
  ]

Example:

This will return the markup for reacting the post id '5' with only hearts

do_action(
  'air_reactions_display',
  [
    'echo' => false,
    'post_id' => 5,
    'types' => [ 'heart' ],
  ]
)

Same as a shortcode (echoing is always disabled in shortcode):

[air-reactions types="heart" post_id="5"]

Usage in comments

Prefix comment id with comment- to enable reaction for a comment

do_action(
  'air_reactions_display',
  [ 'post_id' => 'comment-' . $comment->comment_ID, ]
)

Hooks

Load default styles

Set false to not load reaction styles from plugin, if you are going to write them in your theme

Default: true

  add_filter( 'air_reactions_load_default_styles', '__return_false' );

Set allowed post types

Liking is allowed only on these post types.

Default: [ 'post', 'page', 'comment' ]

  add_filter( 'air_reactions_post_types', function( (array) $post_types ) {
    return [ 'post', 'page' ];
  } );

Allow only registered users to react

If this is set to true, only logged in users can react. On default mode where everyone can react, use localstorage and FingerprintJS to set browser fingerprints to reaction events and save the reactions to the posts only. If limited to logged in users only, reactions will be saved to user meta to allow users to react once per post.

Default: false

  add_filter( 'air_reactions_require_login', function( (bool) $require_login ) {
    return true;
  } );

Set capability for reacting posts

You can use any capability recognized by current_user_can() function

Default: read

  add_filter( 'air_reactions_capability', function( (string) $capability ) {
    return 'read';
  } );

Filter post reactions after they are loaded from meta and counted

  add_filter( 'air_reactions_count_post_reactions', function( (array) $post_reactions, (int) $post_id, (string) $meta_key ) {
    // Do something
    return $post_reactions;
  } )

Set default reaction types

Default:

  [
    'heart' => [
      'icon_path' => plugin_dir_path( __DIR__ ) . 'svg/heart.svg',
      'texts'     => [
        'reaction'   => __( 'Love this post', 'air-reactions' ),
        'amount_pre' => __( 'Loved', 'air-reactions' ),
        'amount_post' => __( 'times', 'air-reactions' ),
      ],
    ],
    'like' => [
      'icon_path' => plugin_dir_path( __DIR__ ) . 'svg/thumbs-up.svg',
      'texts'     => [
        'reaction'   => __( 'Like this post', 'air-reactions' ),
        'amount_pre' => __( 'Liked', 'air-reactions' ),
        'amount_post' => __( 'times', 'air-reactions' ),
      ],
    ],
    'dislike' => [
      'icon_path' => plugin_dir_path( __DIR__ ) . 'svg/thumbs-down.svg',
      'texts'     => [
        'reaction'   => __( 'Dislike this post', 'air-reactions' ),
        'amount_pre' => __( 'Disliked', 'air-reactions' ),
        'amount_post' => __( 'times', 'air-reactions' ),
      ],
    ],
  ]

Example:

  add_filter( 'air_reactions_types', function( (array) $default_types ) {
    return [
      'heart' => [
        'icon_path' => get_theme_file_path( 'svg/heart.svg' ),
        'texts'     => [
          'reaction'   => 'Love this post',
          'amount_pre' => 'Loved',
          'amount_post' => 'times',
        ],
      ],
    ];
  });

Modify reaction item markup

You can use this to build your own reaction item, just remember to add data-attributes like in the original, the javascript depends entirely on those. Feel free to modify the structure and classes etc.

  add_filter( 'air_reactions_reaction_item', function( (string) $output, (string) $key, (array) $item ) {
    // Do something
    return $output;
  });

Modify container start and end markup

You can change the markup or add wrapper etc. Just remember to add data-attributes like in the original, the javascript depends entirely on those.

  add_filter( 'air_reactions_container_start', function( (string) $output, (array) $args, (bool), (int) $current_user_id ) {
    // Do something
    return $output;
  });
  add_filter( 'air_reactions_container_start', function( (string) $output, (array) $args, (bool), (int) $current_user_id ) {
    // Do something
    return $output;
  });

Customize message shown to non-logged in users when login is required

  add_filter( 'air_reactions_login_required_message', function() {
    return 'Login to like this';
  });

JavaScript functionality

Reaction items are queried from DOM and initialized once after page has loaded. You can check for new reaction items, for example after loading content from AJAX, by simply triggering the event initAirReactions.

  const event = new Event('initAirReactions');
  window.dispatchEvent(event);

Releases

2 releases.

Tag
Published
1.0.1 latest
May 7, 2021 5 years ago
Mar 18, 2021 5 years ago

These releases are tags only. The author does not attach a packaged zip, so there are no download counts to report.

B grade

Security

Air Reactions 1.0.1 · audited by WP Registry

Medium-severity findings.

1 medium
Audited release
1.0.1
Findings
1
Worst severity
medium
Content hash
fe4e1a385e6062bed17a5b40…

Findings

  • medium Public REST add-reaction trusts visitorId as any WordPress user ID

    missing_auth

    register_rest_route('air-reactions/v1','add-reaction/') is a public POST (permission_callback Air_Reactions\can_user_react). On a default install DEFAULT_REQUIRE_LOGIN is false, so can_user_react() returns true for unauthenticated callers and every logged-in role; WordPress core nonce checks are skipped when no auth cookie is sent. save_reaction_callback() sets $current_user from request param visitorId whenever it is truthy, rather than from get_current_user_id(). save_reaction() always writes that value as an array key in post or comment meta _air-reactions, then if get_user_by('id', $visitorId) succeeds (is_numeric IDs such as "1" or "1e2") it update_user_meta()s that user's _air-reactions map. An unauthenticated client can therefore add, change, or remove any user's reaction on any post/comment id and persist it as that user's own usermeta. The official JS only sends FingerprintJS hashes for guests, but the API does not enforce that. The same handler also skips is_post_type_allowed() and the get_types() allowlist that the renderer uses, so the write is not limited to post/page/comment or to heart/like/dislike. Blast radius is the _air-reactions key only (no role/password change, sanitize_key on all three params, counts rendered via esc_html/parseInt).

    inc/api.php:16-47

    Recommendation

    If get_current_user_id() is non-zero, ignore visitorId and always persist as that user. For guests, reject visitorId values that are_numeric or that match get_user_by('id'|login|slug) so fingerprints can never alias a WP user, and never call update_user_meta() on the guest path. Validate id with is_post_type_allowed() (and that the post/comment exists and is readable) and type against array_keys(get_types()) before writing. Keep permission_callback aligned with air_reactions_require_login so a site that requires login actually 403s unauth POSTs.

WP Registry hashes the installable build and reports on that exact bytes-for-bytes copy. Embargoed findings are withheld until they are disclosed, so a clean verdict means nothing public is outstanding. WP Manifest does not audit code itself.