Hi Morbus iff,
First of all:
in this period I'm playing with your module and I absolutely have to thank you for your work: your module is simply great, flexible and adaptable to any situation: thank you very much for this!
Now the question:
do you think it would be possible to dynamically create specific achievements PER USER? See this use case:
- In my website, users uploads their works of art (= create work_of_art content type)
- Every work of art can be voted by other users
- I would like to create a "Your XXX work art has been voted 100 times: CONGRATULATIONS!" achievement
The problem is that I cannot know in advance how many and which works of art a user may upload: so here the necessity to dynamically create the specific achievement (on hook_node_insert?) for that bundle and that user (taking the title as the XXX in achievement description).
Do you think this would be possible?
Thank you very much!
Comments
Comment #1
morbus iffMmm, yes.
Whenever a new art type is submitted (per hook_node_insert()), run
achievements_load(NULL, FALSE, TRUE). This will reset the internal achievements cache (which, in effect, makes the code run around again looking for brand new achievements). Then, in yourhook_achievements_info, use a foreach alongside the rest of your achievement definitions, something like:Then, inside your voting hook, you'd check the number of votes on node 123 and unlock the matching art-123-for-456 achievement for user 456. You'd probably also want to make all the achievement "invisible", so that your users doesn't see achievements under user/#/achievements they can't complete (i.e., other user's artwork achievements). You might also then need to hide or modify the "You've earned ## of ### achievements" status line too, for the same reason.
I'd love to see your final site when you've got everything implemented.
Comment #2
mxtMorbus iFF: you gave me the key point: thank you!!!
I'll try to do something with your suggestion.
Only one doubt: in this way all users will see each other "xxx" achievements in their achievements tab in user profile page: is there a way to show these achievements only on their author tab?
EDIT: You have already answered to my doubt above: probably we was writing/editing in the same time...
AND YES: I'll show you the final achievements result for sure! ;-)
Comment #3
morbus iffThat's what the "invisible" flag kinda does - it hides these achievements from EVERYONE's achievement tabs UNTIL they've been earned. Since only one person can earn them (per your unlock code) the right achievements would only ever show up on the right user's page. Alternatively, and I've never done this so it might not even work, you could skip the "invisible" flag entirely and add your own flag - say "owner_only" - and then listen for that flag in a theme preprocess, checking against the current user and hiding/showing based on your own custom logic.
Comment #4
mxtHi Morbus,
I was thinking about performance: what about the above solution if thousand of art nodes are created? The for each iteration have to re-create all thousand dynamic achievements at every node insert? What are the repercussion talking about performance?
I was looking for an alternative using hook_achievements_info_alter to add the new achievements for the new created node to the existing ones, without recreating all the achievements, so:
I absolutely have no idea about:
return MYMODULE_achievements_info_alter(NULL, $node);is a good way to invoke a hook from within another hook?return MYMODULE_achievements_info_alter(NULL, $node);will the new added $node param work or it is an absurdity? It is right to pass NULL as first parameter? I don't know...What do you think about the above (NOT TESTED) approach? Any negative consequences? When I will clear the cache will all new dynamic achievements be still at their place?
Thank you for your support
Comment #5
Sizzly1 commentedThis is brilliant! Thanks, Morbus. I needed exactly this (I was going down the path of custom code to open my module, parse the definitions and add the stuff I needed. Ick). This is way better. Thanks!
Comment #6
Sizzly1 commentedSo here's what I'm doing with this tidbit... There were a few things I wanted to do with Achievements that I was struggling with:
1. Facebook integration. I have an FB app and I wanted folks to be able to "Share" the fact that they unlocked an achievement. But getting the metadata somewhere where it could be used was tricky.
2. I wanted (like the OP) achievements specific to events on my site. Since users can create the events I wasn't sure how to add a new achievement or two when someone added an event.
3. I wanted to use the image styles so I could use achievements elsewhere on the site (like user profiles, recent activity, etc). I also needed this so that FB would show the image for the achievement on the page.
So. What I've done is create a content type called, appropriately enough, Achievements. This content type has all of the fields necessary to populate an object in my achievement definition module. I then use a variant of the code posted above coupled with the code below to parse the list of achievement entities and rebuild the achievements cache.
What this accomplishes (coupled with achievements_views):
1. Achievements themselves can now be treated as another node. I can give them token based meta tags using the Metatag module.
2. Achievements can be programatically generated. So when a user creates an event, an achievement for winning the event is generated (or whatever).
3. I can change the images on the fly.
4. I can show the images in oodles of different sizes on other parts of the site.
This is the code I use to replace the "$nodes = GET INFO ABOUT ALL SUBMITTED ART." in your example, Morbus.
Where can you see this in action? No where, right now. It's on my development box but initial tests are looking grand. The site is a battle stats tracking site (and league/event management) for miniature wargames so the idea of gamer style achievements makes me happy (and my beta users too, as it turns out). Once this bit is live I'll share it with you all 'cause this module has played a fairly major role in realizing my vision for the site.
Just thought I'd share what I'm doing with this. Thanks again.