| Commit | Line | Data |
|---|---|---|
| 6cdda368 MI |
1 | <?php |
| 2 | ||
| 3 | /** | |
| 4 | * @file | |
| 5 | * Hooks provided by the Achievements module and how to implement them. | |
| 6 | */ | |
| 7 | ||
| 8 | /** | |
| 9 | * Define an achievement. | |
| 10 | * | |
| 11 | * This hook describes your achievements to the base module so that it can | |
| 12 | * create the pages and caches necessary for site-wide display. The base | |
| 09abe3cf MI |
13 | * module doesn't know how to unlock any of your achievements... instead, you |
| 14 | * use Drupal's existing hooks, the achievement storage tables, and a few | |
| 15 | * helper functions to complete the workflow. See the remaining documentation | |
| 16 | * in this file for further code samples. | |
| 17 | * | |
| 18 | * There are many different kinds of achievements, and it's accurate enough to | |
| 19 | * say that if you can measure or respond to an action, it can be made into a | |
| 20 | * matching achievement. Be creative. Look at what others are doing. Have fun. | |
| 21 | * Your gamification efforts will fail or be un-fun if you don't have a gamer | |
| 22 | * helping you, if you make everything a mindless grind, or if you simply | |
| 23 | * copy achievements from another site or install. | |
| 6cdda368 MI |
24 | * |
| 25 | * @return | |
| 0d348f03 MI |
26 | * An array whose keys are internal achievement IDs (32 chars max) and whose |
| 27 | * values identify properties of the achievement. These properties are: | |
| 6cdda368 MI |
28 | * - title: (required) The title of the achievement. |
| 29 | * - description: (required) A description of the achievement. | |
| 30 | * - points: (required) How many points the user will earn when unlocked. | |
| 0d348f03 | 31 | * - images: (optional) An array of (optional) keys 'locked', 'unlocked', |
| 43551281 | 32 | * and 'hidden' whose values are image file paths. Achievements exist in |
| 0d348f03 MI |
33 | * three separate display states: unlocked (the user has it), locked (the |
| 34 | * user doesn't have it), and hidden (the user doesn't have it, and the | |
| 35 | * achievement is a secret). Each state can have its own default image | |
| 36 | * associated with it (which administrators can configure), or achievements | |
| 37 | * can specify their own images for one, some, or all states. | |
| 28acbf3e MI |
38 | * - storage: (optional) If you store statistics for your achievement, the |
| 39 | * core module assumes you've used the achievement ID for the storage | |
| 40 | * location. If you haven't, specify the storage location here. This lets | |
| 41 | * the core module know what to delete when an administrator manually | |
| 09abe3cf MI |
42 | * removes an achievement unlock from a user. If your achievement |
| 43 | * tracks statistics that are NOT set with achievements_storage_get() | |
| 44 | * or _set, you don't have to define the 'storage' key. | |
| 6cdda368 | 45 | * - hidden: (optional) The achievement is a sekrit until it is unlocked. |
| 4fd35678 MI |
46 | * |
| 47 | * Achievements can also be categorized into groups. Groups are simply | |
| 48 | * arrays whose keys are internal group IDs and whose values identify | |
| 49 | * the 'title' of the group as well as the array of 'achievements' that | |
| 50 | * correspond to that group. If some achievements are within a group and | |
| 51 | * some achievements are without a group, the groupless achievements will | |
| 52 | * automatically be placed into a "Miscellany" category. | |
| 6cdda368 MI |
53 | */ |
| 54 | function hook_achievements_info() { | |
| 512d7719 | 55 | $achievements = array( |
| 6cdda368 | 56 | 'comment-count-50' => array( |
| 6cdda368 MI |
57 | 'title' => t('Posted 50 comments!'), |
| 58 | 'description' => t("We no longer think you're a spam bot. Maybe."), | |
| 09abe3cf | 59 | 'storage' => 'comment-count', |
| 6cdda368 MI |
60 | 'points' => 50, |
| 61 | ), | |
| 62 | 'comment-count-100' => array( | |
| 6cdda368 MI |
63 | 'title' => t('Posted 100 comments!'), |
| 64 | 'description' => t('But what about the children?!'), | |
| 09abe3cf | 65 | 'storage' => 'comment-count', |
| 6cdda368 | 66 | 'points' => 100, |
| 0d348f03 | 67 | 'images' => array( |
| 512d7719 | 68 | 'unlocked' => '/sites/default/files/example1.png', |
| 0d348f03 MI |
69 | // 'hidden' and 'locked' will use the defaults. |
| 70 | ), | |
| 6cdda368 | 71 | ), |
| 4fd35678 | 72 | |
| 43551281 | 73 | // An example of achievement groups: 'article-creation' is the group ID, |
| 4fd35678 MI |
74 | // "Article creation" is the group title, and all relevant achievements are |
| 75 | // placed in an 'achievements' array. The ungrouped comment achievements | |
| 76 | // above will be automatically pushed into a "Miscellany" group. | |
| 77 | 'article-creation' => array( | |
| 78 | 'title' => t('Article creation'), | |
| 79 | 'achievements' => array( | |
| 80 | 'node-mondays' => array( | |
| 81 | 'title' => t('Published some content on a Monday'), | |
| 82 | 'description' => t("Go back to bed: it's still the weekend!"), | |
| 83 | 'points' => 5, | |
| 84 | 'images' => array( | |
| 85 | 'unlocked' => '/sites/default/files/example1.png', | |
| 86 | 'locked' => '/sites/default/files/example2.png', | |
| 87 | 'hidden' => '/sites/default/files/example3.png', | |
| 88 | // all default images have been replaced. | |
| 89 | ), | |
| 90 | ), | |
| 0d348f03 | 91 | ), |
| 28acbf3e | 92 | ), |
| 6cdda368 | 93 | ); |
| 512d7719 MI |
94 | |
| 95 | return $achievements; | |
| 6cdda368 MI |
96 | } |
| 97 | ||
| 98 | /** | |
| 99 | * Implements hook_comment_insert(). | |
| 100 | */ | |
| efac995d | 101 | function example_comment_insert($comment) { |
| 09abe3cf MI |
102 | // Most achievements measure some kind of statistical data that must be |
| 103 | // aggregated over time. To ease the storage of this data, the achievement | |
| 104 | // module ships with achievement_storage_get() and _set(), which allow you | |
| 105 | // to store custom data on a per-user basis. In most cases, the storage | |
| 106 | // location is the same as your achievement ID but in situations where you | |
| 107 | // have progressive achievements (1, 2, 50 comments etc.), it's better to | |
| 108 | // share a single place like we do below. If you don't use the achievement | |
| 109 | // ID for the storage location, you must specify the new location in the | |
| 110 | // 'storage' key of hook_achievements_info(). | |
| 111 | // | |
| 112 | // Here we're grabbing the number of comments that the current commenter has | |
| 113 | // left in the past (which might be 0), adding 1 (for the current insert), | |
| 114 | // and then saving the count back to the database. The saved data is | |
| 115 | // serialized so can be as simple or as complex as you need it to be. | |
| 116 | $current_count = achievements_storage_get('comment-count', $comment->uid) + 1; | |
| 117 | achievements_storage_set('comment-count', $current_count, $comment->uid); | |
| 6cdda368 | 118 | |
| 09abe3cf MI |
119 | // Note that we're not checking if the user has previously earned any of the |
| 120 | // commenting achievements yet. There are two reasons: first, we might want | |
| 121 | // to add another commenting achievement for, say, 250 comments, and if we | |
| 122 | // had stopped the storage counter above at 100, someone who currently has | |
| 123 | // 300 comments wouldn't unlock the achievement until they added another 150 | |
| 124 | // nuggets of wisdom to the site. Generally speaking, if you need to store | |
| 125 | // incremental data for an achievement, you should continue to store it even | |
| 126 | // after the achievement has been unlocked - you never know if you'll want | |
| 127 | // to add a future milestone that will unlock on higher increments. | |
| 128 | // | |
| 129 | // Secondly, the achievements_unlocked() function below automatically checks | |
| 130 | // if the user has unlocked the achievement already, and will not reward it | |
| 28acbf3e MI |
131 | // again if they have. This saves you a small bit of repetitive coding but |
| 132 | // you're welcome to use achievements_unlocked_already() as needed. | |
| 09abe3cf MI |
133 | // |
| 134 | // Knowing that we currently have 50 and 100 comment achievements, we simply | |
| 135 | // loop through each milestone and check if the current count value matches. | |
| 6cdda368 MI |
136 | foreach (array(50, 100) as $count) { |
| 137 | if ($current_count == $count) { | |
| 28acbf3e | 138 | achievements_unlocked('comment-count-' . $count, $comment->uid); |
| 6cdda368 MI |
139 | } |
| 140 | } | |
| 141 | } | |
| efac995d MI |
142 | |
| 143 | /** | |
| 144 | * Implements hook_node_insert(). | |
| 145 | */ | |
| 146 | function example_node_insert($node) { | |
| 09abe3cf | 147 | // Sometimes, we don't need any storage at all. |
| efac995d | 148 | if (format_date(REQUEST_TIME, 'custom', 'D') == 'Mon') { |
| 09abe3cf | 149 | achievements_unlocked('node-mondays', $node->uid); |
| efac995d | 150 | } |
| b830eedf | 151 | } |