Ranking users based on how many likes their uploaded files get

Hi everyone :)

I am currently trying to rank users of my elgg website based on the various actions they perform. I am using the following plugin: http://community.elgg.org/plugins/813379/1.8.5/elgg-18-elggx-userpoints

I would like to grant points to a user each time a file he uploaded gets liked, since i am begining in elgg development digging through the code wasn't enough to understand how to implement it. 

Thanks in advance for your help ;)

  • Sorry, had no time to reply on your PM yet. So, let me give you some hints here how to implement the "reverse" assigning of userpoints when someone's content got liked. A "like" is saved in Elgg as an annotation to the content entity. In start.php of the userpoints plugin there's an elgg event handler defined (elgg_register_event_handler('create','annotation','elggx_userpoints_annotate_create');). The function elggx_userpoints_annotate_create checks if a user should receive point when he does an action involving annotations (comments, likes, fivestar ratings):

    function elggx_userpoints_annotate_create($event, $object_type, $object) {
        if ($points = elgg_get_plugin_setting($object->name)) {
            if (function_exists('userpoints_add')) {
                $description = $object->name;
                userpoints_add(elgg_get_logged_in_user_guid(), $points, $description, $object_type, $object->entity_guid);
            }
        }

        return(true);
    }

    This function is were you would need to start with the modification.

    if ($points = elgg_get_plugin_setting($object->name)) {

    checks if there's any points action defined for the annotation. For example if the name in $object->name is "likes" the points defined for liking something will be awarded.

    Now it depends on for what exactly you want to award reverse points for. For example for liking uploaded files you would need something like that:

    if ($points = elgg_get_plugin_setting($object->name)) {

            if (function_exists('userpoints_add')) {

                $description = $object->name;

                userpoints_add(elgg_get_logged_in_user_guid(), $points, $description, $object_type, $object->entity_guid);

                if ($object->name == "likes" {

                    $entity = get_entity($object->entity_guid);

                    if ($entity->getSubtype() == "file") {

                        $entity_owner_guid = $entity->owner_guid;

                        $description = "A description";

                        $reverse_points = 10; // how many points? Simplest solution is hardcoded definition here. Otherwise via modifying actions.php accordingly.

                        userpoints_add($entity_owner_guid, $points, $description, $object_type, $object->entity_guid);

                    }

                }

        }

    }

     

  • Thank you! Exactly what i needed.

    An problem emerges though as liking a file your user account do not own (or having no admin rights) will cause the following error:

    "Fatal Error.

    An unrecoverable error has occurred and has been logged. Contact the site administrator with the following information:

    Exception #1371040771."

     

    I think it is an autorisation matter, due to the fact that access_id of userpoints is 0 (private.

    Another issue is that unliking a file do not removes point, is it due to the fact this event is not handled the same way as a like?

  • Sorry, it seems I had been not really concentrated on the code when I thought about it yesterday. The write access on the userpoints metadata entry of the other user (file uploader) has only been one thing I forgot to consider. Try it with this code:

    function elggx_userpoints_annotate_create($event, $object_type, $object) {

        if ($points = elgg_get_plugin_setting($object->name)) {
            if (function_exists('userpoints_add')) {
                $description = $object->name;
                userpoints_add(elgg_get_logged_in_user_guid(), $points, $description, $object_type, $object->entity_guid);

                if ($object->name == "likes") {

                    $entity = get_entity($object->entity_guid);

                    if ($entity->getSubtype() == "file") {
                        $entity_owner_guid = $entity->owner_guid;
                        $reverse_points = 10; // how many points? Simplest solution is hardcoded definition here. Otherwise via modifying actions.php accordingly.

                        $context = elgg_get_context();
                        elgg_set_context('userpoints_access');
                        elggx_userpoints_su();

                        userpoints_add($entity_owner_guid, $reverse_points, $description, 'admin');

                        elggx_userpoints_su(true);
                        elgg_set_context($context);
                    }
                }
            }
        }

        return(true);
    }

    Now I've also tested it. Works for me. Still, it's quite limited in its functionality - not a very general approach.

    The removal of points gained on actions that are handled by Elgg annotations (comments, likes and similar) is (currently) not implemented. I've already tried to implement it recently, but I've not yet found a way to make it possible.

  • Thanks again for your insight :)

    Maybe the problem lies in the fact that the like plugin works with two functions add.php and delete.php that aren't performing in the same way.

    <?php
    /**
    * Elgg delete like action
    *
    */

    // Support deleting by id in case we're deleting another user's likes
    $id = (int) get_input('id');

    $like = NULL;
    if ($id) {
    $like = elgg_get_annotation_from_id($id);
    }

    if (!$like) {
    $likes = elgg_get_annotations(array(
    'guid' => (int) get_input('guid'),
    'annotation_owner_guid' => elgg_get_logged_in_user_guid(),
    'annotation_name' => 'likes',
    ));
    $like = $likes[0]; //problem here?
    }

    if ($like && $like->canEdit()) {
    $like->delete();
    system_message(elgg_echo("likes:deleted"));
    forward(REFERER);
    }

    register_error(elgg_echo("likes:notdeleted"));
    forward(REFERER);

    Maybe recoding this function in the elgg like plugin in the same vein as add.php could allow us to handle this annotation?

  • It's not a matter of the likes plugin's add/delete actions. The userpoints plugin adds and removes userpoints by providing several callback functions for Elgg plugin hooks and Elgg events. If these events and plugin hooks are fired the userpoint plugin checks if there is anything to do. For Elgg entities like blogs, files, tidypics images and others there is both a callback function defined for the "create" and "delete" hook or event respectively.

    For Elgg annotations this is different. Here's only a callback function for the "create" event defined but not for the "delete" event. The reason lies in the history of the userpoints plugin. The original developer did not include a callback function for the delete event. The reason he gave for this is "there's no delete event for annotations defined in Elgg". I don't know if this was true back then when he wrote the userpoints plugin or if he simply overlooked it. By now there is such a delete event also for annotations available.

    But it's not that easy to implement the substraction of points even with the delete event firing now also for annotations... I already tried that once. The problem is that the information currently saved in the database when adding userpoints for annotations for example for likes is not sufficient to be able to check if any points need to be deleted later when an annotation is deleted (for example a like taken back). So, there would be some more changes necessary in the userpoints plugin. I don't know if these changes would be possible without losing backward compatibility. While it would be tolerable (maybe unavoidable) to delete userpoints for annotations only for actions performed with a new version of the userpoints plugin it would surely be not okay if you wouldn't be able to use a new version of the userpoints plugin on an existing site anymore at all due to a change in the data handling.

    I surely am not happy about the missing option to remove userpoints given on annotation actions either and as soon as I have some free time I will try to fix the problem. But for the present I don't have the time unfortunately due to working on other plugins at the moment.

Beginning Developers

Beginning Developers

This space is for newcomers, who wish to build a new plugin or to customize an existing one to their liking