diff --git a/achievements.admin.inc b/achievements.admin.inc index 1247ccc749dc24dfaae4a482564e06e5d492385b..263417b7d944669f1363ce75ccd5535d99cdd5ae 100644 --- a/achievements.admin.inc +++ b/achievements.admin.inc @@ -70,7 +70,7 @@ function achievements_settings() { * Submit callback; clear achievement info cache. */ function achievements_clear_info_cache_submit() { - achievements_load(NULL, TRUE); + achievements_load(NULL, FALSE, TRUE); drupal_set_message(t('Achievements information cache cleared.')); } diff --git a/achievements.api.php b/achievements.api.php index 84d44791c169e574beca118c23e14b069651dd4a..a10b6e1249d4226c47391369483eef82303df6a8 100644 --- a/achievements.api.php +++ b/achievements.api.php @@ -45,7 +45,7 @@ * - hidden: (optional) The achievement is a sekrit until it is unlocked. */ function hook_achievements_info() { - return array( + $achievements = array( 'comment-count-50' => array( 'title' => t('Posted 50 comments!'), 'description' => t("We no longer think you're a spam bot. Maybe."), @@ -58,7 +58,7 @@ function hook_achievements_info() { 'storage' => 'comment-count', 'points' => 100, 'images' => array( - 'unlocked' => '/sites/default/files/example.png', + 'unlocked' => '/sites/default/files/example1.png', // 'hidden' and 'locked' will use the defaults. ), ), @@ -74,6 +74,8 @@ function hook_achievements_info() { ), ), ); + + return $achievements; } /** diff --git a/achievements.module b/achievements.module index f4fd16e6714252423c5e256837b56f8d97f848e5..f9ce394e033bd975f3615212755df18e8e0dd7f8 100644 --- a/achievements.module +++ b/achievements.module @@ -146,35 +146,61 @@ function achievements_block_view($delta = '') { * * @param $achievement_id * The (optional) achievement this request applies against. + * @param $grouped + * Whether to return the achievements list flattened (FALSE, the default) + * or grouped into achievement-defined categories. If TRUE, but there is no + * group specified for an achievement, it'll be stored in a "__NONE__" group + * intended to simplify display code. Not compatible with $achievement_id. * @param $reset * Forces a refresh of the cached achievement data. * * @return $achievements * An array of all achievements, or just the one passed. */ -function achievements_load($achievement_id = NULL, $reset = FALSE) { +function achievements_load($achievement_id = NULL, $grouped = FALSE, $reset = FALSE) { $achievements = &drupal_static(__FUNCTION__); if (!isset($achievements) || $reset) { - if (!$reset && $cache = cache_get('achievement_info')) { + if (!$reset && $cache = cache_get('achievements_info')) { $achievements = $cache->data; } else { - $achievements = module_invoke_all('achievements_info'); - - // loop through 'em all and set some defaults. - foreach ($achievements as $id => $achievement) { - $achievements[$id]['id'] = $id; // shorthand. + $result = module_invoke_all('achievements_info'); + + // determine if we're looking at an achievement or group and create our + // master $achievements array. we store the achievements in two separate + // forms: one with a tree (for display purposes) and one flattened (for + // lookup purposes). the flattened index is referenced so that we save + // space in the final serialized blob that cache_set() sends. + foreach ($result as $key => $value) { + if (isset($value['achievements']) && is_array($value['achievements'])) { + $achievements['grouped'][$key] = $value; // copy the whole shebang into realz. + foreach ($achievements['grouped'][$key]['achievements'] as $id => $achievement) { + $achievement[$id]['id'] = $id; + $achievement[$id]['group_id'] = $key; + $achievement[$id]['group_title'] = $value['title']; + $achievements['flat'][$id] = &$achievements['grouped'][$key]['achievements'][$id]; + } + } + else { + $value['id'] = $key; + $value['group_id'] = '__NONE__'; + $value['group_title'] = NULL; // moo. + $achievements['grouped']['__NONE__']['achievements'][$key] = $value; + $achievements['flat'][$key] = &$achievements['grouped']['__NONE__']['achievements'][$key]; + } } - // no magically-useful way to say "on file change". le sigh. - cache_set('achievement_info', $achievements, 'cache', CACHE_TEMPORARY); + cache_set('achievements_info', $achievements, 'cache', CACHE_TEMPORARY); } } - return $achievement_id - ? (isset($achievements[$achievement_id]) ? $achievements[$achievement_id] : FALSE) - : $achievements; // return FALSE to stop bum URLs (via the menu %loader callback). + if ($achievement_id) { // all my majesty and brilliance, and you just want one result? /me weeps. + return isset($achievements['flat'][$achievement_id]) ? $achievements['flat'][$achievement_id] : FALSE; + } + + // return the whole shebang in groups or a flattened lookup bucket. + return $grouped ? $achievements['grouped'] : $achievements['flat']; } /** @@ -259,7 +285,7 @@ function achievements_unlocked($achievement_id, $uid = NULL) { // grab information about the achievement. $achievement = achievements_load($achievement_id); if (!isset($achievement)) { // hrm... try a cache refresh? - $achievement = achievements_load($achievement_id, TRUE); + $achievement = achievements_load($achievement_id, FALSE, TRUE); } if (isset($achievement) && !achievements_unlocked_already($achievement_id, $uid)) { diff --git a/achievements.pages.inc b/achievements.pages.inc index 474f4ea01ebddb4230cf33d6c974ce4a8e8bcee3..4b3f91f8df33f1bfc2d9bc98383ab3107ae3e2cc 100644 --- a/achievements.pages.inc +++ b/achievements.pages.inc @@ -138,7 +138,7 @@ function achievements_user_page($account) { drupal_add_css(drupal_get_path('module', 'achievements') . '/achievements.css'); drupal_set_title(t('Achievements for @name', array('@name' => $account->name))); - $achievements = achievements_load(); + $achievements = achievements_load(NULL, TRUE); $unlocks = db_select('achievement_unlocks', 'au')->fields('au', array('achievement_id', 'rank', 'timestamp')) ->condition('uid', $account->uid)->orderBy('timestamp', 'DESC')->execute()->fetchAllAssoc('achievement_id'); @@ -152,23 +152,18 @@ function achievements_user_page($account) { '@total_count' => count($achievements))), '#suffix' => '', ); - foreach ($unlocks as $achievement_id => $unlock) { - $build['achievements']['unlocks'][$achievement_id] = array( - '#theme' => 'achievement', - '#achievement' => $achievements[$achievement_id], - '#unlock' => (array) $unlock, - ); - // don't show it again in locked loop. - unset($achievements[$achievement_id]); - } + foreach ($achievements as $group_id => $group) { + foreach ($group['achievements'] as $achievement_id => $achievement) { + $build['achievements'][$group_id][$achievement_id]['#theme'] = 'achievement'; + $build['achievements'][$group_id][$achievement_id]['#achievement'] = $achievement; - // display all the remaining locked achievements. - foreach ($achievements as $achievement_id => $achievement) { - $build['achievements']['locks'][$achievement_id] = array( - '#theme' => 'achievement', - '#achievement' => $achievement, - ); + if (isset($unlocks[$achievement_id])) { + $build['achievements'][$group_id][$achievement_id]['#unlock'] = (array) $unlocks[$achievement_id]; + $build['achievements'][$group_id][$achievement_id]['#weight'] = -$unlocks[$achievement_id]->timestamp; + // by setting the weight to the timestamp, the latest unlocks are always shown at the top. + } + } } return $build;