I have also confirmed this behaviour in my install - Moodle 1.7.1+ (2006101010).
I made several attempts to test, reproduce and overcome this issue:
- setting both the moodle/category:visibility and moodle/course:viewhiddencourses permissions to teachers (as in the proposed bugfix and the comment from Jenny Toller)
- creating a role with only those permissions and assigning teachers from the hidden categories and courses to it at the site level
- creating several combinations of depth in categories and courses (0 to 3)
even then invisible categories and courses remained only visible to the administrator.
Since I manage a Moodle site with this version and it's already being used by students at my university the matter became rather urgent. Giving administration privileges to all teachers that had courses to prepare was clearly not an option. I decided to look in the code and try my best to find a potential solution.
Notice: I do not claim this to be a good solution. I'm NOT a Moodle expert, far from it
. However, I have tested this code thoroughly and I believe it to be a possible bugfix and perhaps close this bug.
I commented all insertions and modifications in the code. I left all previous functionality untouched. Forgive me if I do not follow Moodle coding conventions. Feel free to try this patch at your own risk 
Proposed patch
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
File: lib/datalib.php
Line: 782
PATCH:
/**
- Returns a sorted list of categories
*
- @param string $parent The parent category if any
- @param string $sort the sortorder
- @return array of categories
*/
/// Patched by andre.martins [29/Feb/2007]
function get_categories($parent='none', $sort='sortorder ASC') {
if ($parent === 'none') {
$categories = get_records('course_categories', '', '', $sort);
} else {
$categories = get_records('course_categories', 'parent', $parent, $sort);
}
if ($categories) { /// Remove unavailable categories from the list
$creator = has_capability('moodle/course:create', get_context_instance(CONTEXT_SYSTEM, SITEID));
// ----- Patch : New -> Testing if a user can see hidden categories
$hidden_category_allowed = has_capability('moodle/category:visibility', get_context_instance(CONTEXT_SYSTEM, SITEID));
// *****
foreach ($categories as $key => $category) {
if (!$category->visible) {
// ----- Patch: Modified -> checking for both conditions - a category is only removed from the listing if a user
// is not a creator nor can see hidden categories
if (!$creator and !$hidden_category_allowed) {
// *****
unset($categories[$key]);
}
}
}
}
return $categories;
}
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
File: course/lib.php
Line: 1340
function print_whole_category_list($category=NULL, $displaylist=NULL, $parentslist=NULL, $depth=-1, $files = true) {
/// Recursive function to print out all the categories in a nice format
/// with or without courses included
/// Patched by andre.martins [29/Feb/2007]
...... (Line: 1351)
if ($category) {
// ----- Patch: New -> Can the user view hidden categories?
$can_view_hidden_categories = has_capability('moodle/category:visibility', get_context_instance(CONTEXT_SYSTEM, SITEID));
// *****
// ----- Patch: Modified -> the category will be shown wether it's visible, the user can update course settings or
// can view hidden categories
if ($category->visible or has_capability('moodle/course:update', get_context_instance(CONTEXT_SYSTEM, SITEID))
or $can_view_hidden_categories) {
// *****
print_category_info($category, $depth, $files);
} else {
return; // Don't bother printing children of invisible categories
}
} else {
$category->id = "0";
}
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
I have verified this behaviour with my install.
Admins can see hidden course and teachers cannot.
Jeff