[Elgg 1.8-1.12 & 2.X: Elggx Userpoints] v1.8.8

Release Notes

Changelog:

  • Added functionality to check integrity of a user's userpoint metadata entry on adding/substracting userpoints to avoid "Array()" issue to happen or fixing it if it already did happen (Can't promise this works as I've still not be able to reproduce this issue myself!),
  • Added option to awarding userpoints on uploading a profile image.
  • Hi, all points of all users constantly (every 4-5 days) will be deleted and I have to give points to restore all user... why?

  • Are ALL points of ALL users turned to zero at the same time? This is something that surely shouldn't happen and I've no idea what could cause it at the moment. If the resetting indeed happens for all users at the same time: can you give more details about it? Do the users have "0" userpoints or does it say "Array" on their profile pages where the number of userpoints should show up? Could you think of any other plugin on your site that might cause the problem?

    If the vanishing of userpoints does not happen at the same time: there's the "Expire points after a specific intervall?" setting on the "Plugin settings" tab of the Userpoints plugin. If you have the Expirationdate plugin installed and this plugin setting is set to something else but "Never" it would explain why userpoints are vanishing. In this case change this setting to "Never".

  • Hi @iionly.
    Great plugin! Recommended it.

    I want to extend some features.

    I have writed this construction:

    $owner = $reply->getOwnerEntity()->getGUID();
    $owner_replies = elgg_get_annotations(array(
    'annotation_names' => 'group_topic_post',
    'annotation_owner_guid' => $owner,
    'guid' => $topic_guid,
    'count' => true,
    ));

    With it I can take a count of replies in discussion of the Group's member .
    It's works like a charm :D

    var_dump returns amount replies of each member

    But when I'll want to add points for each user who replied on discussion:

    userpoints_update_user($owner, +$points);

    this returns amount of each reply for $owner but not summary of all replies for each owner:

    1 reply = 2 points

    Alice submitted 5 replies
    Bob submitted 2 replies

    I've got 5 replies for Alice and 2 replies for Bob

    But when I'll want award points my users returns this:

    Alice:
    1 reply * 2 point
    1 reply * 2 point
    1 reply * 2 point
    1 reply * 2 point
    1 reply * 2 point

    Bob:
    1 reply * 2 point
    1 reply * 2 point

    instead of
    Alice:
    5 replies * 2 point
    Bob:
    2 replies * 2 point

    Can you advice me what I do wrong?

    Very thanks

  • @maxvin:

    I think I understand what you want to achieve: award points to the member who started a discussion for each reply made to this discussion topic. Is that correct?

    As a sidenote: awarding points for a reply to the member who made the reply is already implemented if you want to achieve this.

    Question: do you intend to use this approach only to award points for already existing discussions / replies?

    I think it only makes sense for this case. For any future replies (new group_topic_post annotations) you would have to award the points by using an event hook (as you would award points for the same existing replies again and again otherwise). For the implementation of this approach you can study the elggx_userpoints_annotate_create function for the 'create','annotation' event in start.php.

    For your problem I would suggest using the userpoints_add() function:

    userpoints_add($owner_guid, $points, $optional_description);

    If you want to summarize the points to be awarded for all replies by a single user and add them in one go, you would have to calculate this first:

    $points = $owner_replies * $points_per_reply;

    (you did the annotation count but not the multiplication. I don't know if this is the missing part in your code as I don't know the full code you are using)

    A possible alternative approach would be using an ElggBatch:

    $batch = new ElggBatch('elgg_get_annotations', array(
        'annotation_name' => 'group_topic_post',
        'limit' => false,
    ));

    foreach ($batch as $reply) {

        // fetch the discussion entity the reply was made to
        $discussion = get_entity($reply->entity_guid);

        // who started the discussion
        $owner = $discussion->getOwnerEntity();

        // points per reply
        $points = 2; // points per reply

        // optional description
        $optional_description = 'Points for receiving a reply on a discussion';

        userpoints_add($owner->getGUID(), $points, $optional_description);
    }

     

  • @iionly, Very thanks for your help.

    Your code for user 'who started the discussion'. I want to award users 'who replied the discussion'.
    That's right, I want it for already existing replies.

    I know about elggx_userpoints_annotate_create function and I can count all replies and points.
    But I want to reward users based on my own amount, but don't set certain points.

    Maybe my code say more than I :D

    This is action:

    <?php

    gatekeeper();

    //Get discussion
    $guid = get_input('discussion');
    $discussion = get_entity($guid)

    $num_replies = elgg_get_annotations(array(
    'annotation_name' => 'group_topic_post',
    'guid' => $guid,
    'count' => true,
    ));

    //Get replies
    $batch = new ElggBatch('elgg_get_annotations', array(
    'annotation_name' => 'group_topic_post',
    'guid' => $guid,
    'limit' => false,
    ));

    if ($batch) {
    foreach ($batch as $reply) {
    $user = $reply->getOwnerEntity()->getGUID();

    //Get user's replies
    $user_replies = elgg_get_annotations(array(
    'annotation_names' => 'group_topic_post',
    'annotation_owner_guid' => $user,
    'guid' => $guid,
    'count' => true,
    ));

    //Set some value
    $sum = 50;

    //Get points
    $point = $sum / $num_replies;

    //Set points
    $user_points = $user_replies * $point;

    //Add points
    userpoints_update_user($user, +$user_points);
    }
    system_message(elgg_echo("success"));
    forward(REFERER);
    }

    My problem is $user_points adds to $user for each $reply like a loop instead once.

    Example:
    $user_replies=5
    $user_points=3
    userpoints_update_user($user, +$user_points) must return +3 points for $user
    but returns 15 (3 points for each 5 replies)

    Hope I explained :)

    PS: I tried it with userpoints_add but not work for me :(

    Very thanks again!

  • You are looping through all replies but each time you count the number of replies a user made in total and award a corresponding number of points. You have to change the code to correctly handle this. Easy way is posted below. Another way would be to loop through the users who made replies instead of replies. Then you could award them with the points for all their replies at once. But it's more difficult to extract the users who participated in a discussion by replying (a custom query would be necessary).

    I still don't fully understand what you have in mind: why setting a maximum number of points to be awarded per discussion and split this sum of points by number of replies (important: only assign whole number of point - I don't know what might happen otherwise).

    Is the awarding of points this way a one time thing? If yes, then I would include the code within another loop that runs over all discussion entities at once. This can then also be implemented as a script independent from any other plugin files. Add "require 'engine/start.php';" at the top of the file below <?php (path depending on where you save the script relative to engine/start.php) and you can call this script directly in the browser. If you replace gatekeeper() with admin_gatekeeper() only a logged-in admin can run it.

    Please use userpoints_add() and not userpoints_update_user(). The latter will only update a user's userpoints metadata value (used to quickly display the total number of a user's points) but it will not create the necessary userpoints entity in the database. If for any reason the metadata value gets corrupt, there would be no way to restore number of userpoints awarded for the discussion replies. Only if you use userpoints_add() the database entry will get created (and additionally userpoints_update_user() is used to update the metadata entry).

    So, the modified code would be:

    <?php

    gatekeeper();

    // Get discussion
    $guid = get_input('discussion');
    $discussion = get_entity($guid)

    $num_replies = elgg_get_annotations(array(
        'annotation_name' => 'group_topic_post',
        'guid' => $guid,
        'count' => true,
    ));

    // Total number of userpoints to be awarded per discussion
    $sum = 50;

    // Number of userpoints to be awarded per reply
    $points = (int)($sum / $num_replies); // better only whole numbers of points!

    // Get replies
    $batch = new ElggBatch('elgg_get_annotations', array(
        'annotation_name' => 'group_topic_post',
        'guid' => $guid,
        'limit' => false,
    ));

    if ($num_replies > 0) {
        foreach ($batch as $reply) {
            // User who made the reply
            $user_guid = $reply->owner_guid;

            // Award points to user for this reply
            $description = 'Points for replying in a group discussion';
            userpoints_add($user_guid, $points, $description, 'annotation', $reply->entity_guid);
        }
        system_message(elgg_echo("success"));
        forward(REFERER);
    }

    register_error('No replies found for this discussion');
    forward(REFERER);

    P.S: this code will also not work anymore on Elgg 1.9 because discussion replies are now saved as entities instead of annotations. So, you would have to modify the code, if you intend to use it on Elgg 1.9. The Userpoints plugin already has been updated accordingly. As I said, you can award userpoints (separately and independent of total number of replies) already.

  • hi...how to get user's points..bez i want denotes my user's point.example test your points is 250

  • @vv06:  I'm not sure what you want to achieve exactly. So, I'm not sure what to suggest exactly.

    Do you want to find out how many points a user has on the site for example by searching by username? Unfortunately, such a feature is not yet implemented. Right now you can only browse the list of users on the settings page. Of course, this is not very useful if you have many users and want to find a specific user. Or want to filter users with points larger than a certain number. Only via the profile page you can see directly how many points a user currently have.

    Or do you want to find out "in code" how many points a user has? This is possible by

    $points = $user_entity->userpoints_points;

    which the variable $user_entity holding the user entity of the user you want to know the number of points of. If you want to something specific to happen, if a user reaches some pre-defined number of points, you can register a callback function for the 'userpoints:update', 'all' plugin hook. This plugin hook gets triggered by the Userpoints plugin when a user receives points. For example the Badges plugin uses this plugin hook, too, for awarding badges automatically depending on the number of userpoints. If you have something similar in mind, I would suggest to study the code of the Badges plugin to see how it is done.

  • Great plugin!

    I want to make a plugin that users can transact their points.

    i.e., User A sets his page at two points. If User B wants to view this page, he needs to pay two points to A.

    I used userpoints_add function to subtract two points from B first and add two points to A. The subtraction section was OK but the adding section didn't work (funny thing the function didn't return false). However when B is the admin both sections work.

    if(wonovel_charge_add_points(get_loggedin_userid(), -$charge, $des.'  Author:'.get_user($author)->name, 'wonovel_charge')){
            system_message(sprintf(elgg_echo('wonovel_charge:substract_success'),$charge.'                               '.elgg_get_plugin_setting('lowerplural', 'elggx_userpoints')));
            
            $context = elgg_get_context();
            elgg_set_context('userpoints_access');
            wonovel_charge_elevate_usr();
            
            if(wonovel_charge_add_points($author, $charge, $des.' From:'.get_user(get_loggedin_userid())-               >name, 'wonovel_charge')){
                system_message(sprintf(elgg_echo('wonovel_charge:add_success'),$charge.'                                         '.elgg_get_plugin_setting('lowerplural', 'elggx_userpoints'),get_user($author)->name));
                $annotation = create_annotation($entity_guid,
                                        'paid',
                                        "paid",
                                        "",
                                        get_loggedin_userid(),
                                        $access);
                if (!$annotation) { 
                    //register_error(elgg_echo("wonovel_charge:record_fail"));
                    system_message(elgg_echo("wonovel_charge:record_fail"));
                }else{
                    system_message(elgg_echo("wonovel_charge:recorded"));
                }
            }else{
                system_message(sprintf(elgg_echo("wonovel_charge:add_fail"),get_user($author)->name));
            }
            
            wonovel_charge_elevate_usr(true);
            elgg_set_context($context);
         }else{
            system_message(elgg_echo('wonovel_charge:substract_fail'));
         }

    function wonovel_charge_add_points($user_guid, $points, $description, $type=null, $guid=null){
        return userpoints_add($user_guid, $points, $description, $type=null, $guid=null);
    }

    function wonovel_charge_get_points($user_guid){
        return userpoints_get($user_guid);
    }

    function wonovel_charge_add_points_pending($user_guid, $points, $description, $type=null, $guid=null){
        return userpoints_add_pending($user_guid, $points, $description, $type=null, $guid=null);
    }

    function wonovel_charge_elevate_usr($unsu=false){
        return elggx_userpoints_su($unsu=false);
    }

    function wonovel_charge_userpoints_exists($user_guid, $type, $guid){
        return userpoints_exists($user_guid, $type, $guid);
    }

    $user_entity->userpoints_points did change. But userpoints_get() didn't change. I think this maybe something about writing to database. 

    Any suggestions?

  • @jiao: the problem is due to write access restrictions on entities (in this case user entities) of others. By default, a user can't edit / write / delete content of other users and it also fails in this case here as your code tries to modify the userpoints metadata of another user with the access permissions of the currently logged in user. This fails for normal users - but works for admin users.

    It's possible to allow write access of other users data also for normal users:

    $access = elgg_set_ignore_access(true);

    < now the access level restrictions are ignored>

    elgg_set_ignore_access($access);

    < now the access level restrictions are in use again>

    Within the userpoints plugin this method is used for example on awarding userpoints for inviting other users (see elggx_userpoints_registration_award() function in start.php). The userpoints are awarded when the invited user registers an account but the points get the user who invited the new user. So, it's a similar situation to your problem.

    I'm not sure where exaxtly you would have the elgg_set_ignore() at the moment. The problem might turn out to be that you are calling the userpoints_add() function of the userpoints plugin where the access restrictions might be on again. As the awarding of userpoints for invitations was the only case (at least currently implemented in the userpoints plugin) where a user would modify the userpoint entities of another user, I had re-implemented the corresponding code within the elggx_userpoints_registration_award() with access level restrictions inactive instead of turning off the restrictions within userpoints_add() itself where ignoring the access restrictions would happen for all actions (even if not necessary).

    If you could try it out with elgg_set_ignore_access(), you hopefully get it working. If not (or if you have suggestions / ideas for improving the userpoints plugin) please don't hesitate to post again.

  • elgg_set_ignore_access() works!

    Thanks a lot O(∩_∩)O!

Stats

  • Category: Misc
  • License: GNU General Public License (GPL) version 2
  • Updated: 2019-4-7
  • Downloads: 12255
  • Recommendations: 51

Other Projects

View iionly's plugins