I have installed Drupal a month ago for an "opencourseware" project (see http://ocw.mit.edu). And admittedly, I am new to CMS development (I was a webapp developer) and can't seem to find a way to associate node types due primarily to pressure (I am supposed to submit a prototype by October 22)

I have installed CCK to create my node types: School, Curriculum, Subject, Professor, Syllabus, etc. and I want them to be presented acording to their heirarchy. So I installed the Views module to create a listing of nodes under a specific category. As a primary test of the views module, I followed the instructions found here [20 Steps to Views Happiness] (http://drupal.org/node/63230) and I successfully listed the contents on a block. I tried to list nodes under "School" but I can't seem to make it work. I don't know what to put under categories (please help me)

Is there a way to associate these nodes (school, curriculum, subject, professor, etc) and make a listing of children nodes on a parent page. For example, I have a list of Schools:

  • Stanford
  • MIT
  • Caltech
  • ...

I click on MIT, I will be directed to a page which shows some introductory
text about MIT, its address and its website. At the footer (under the text about MIT), I want to show a list of curricula:

  • Computer Science
  • Aeronautics
  • ...

When I click on computer science, I will be directed to a page with introductory text for Computer Science in MIT, and under it are courses offered under computer science:

  • programming languages
  • artificial intelligence
  • operating systems
  • ...

I have tried to google on "drupal heirarchical categories" and "drupal heirarchical nodes" and i think the best result i got is this http://drupal.org/node/90618 (Hierarchical nodes: possible?). However, I can't try to try the book module, nodeorder, or node relativity modules yet since I am in an internet shop and my laptop is at home. Is there a way to do this?

Any response that will point me to the right direction will be much appreciated. Thank you.

-------------
Kyle Domingo

Comments

kedomingo’s picture

I browsed some school websites under the education category in http://drupalsites.net and looked at their academic programs but the heirarchy of departments to programs to courses seems to be hardcoded.

I think I forgot to say: what i want to do is an automatically generated list from user submitted school, department, programs, courses, etc. and hardcoding links to nodes will be definitely out of the options.

I will look for more solutions and keep you guys posted of my progress.

Again, any pointers will be appreciated. Thanks!

nevets’s picture

The book module sounds like a good solution, it supports both the introductry text (the contents of a particular page) plus lists all the child pages.

cog.rusty’s picture

The biggest danger here is to lose time mixing up different methods, because of the many options available for setting up content relationships.

The simplest way is probably a navigation hierarchy between individual nodes, using the book module. For each top-level entity (let's say School) you create a top level book (that is how the Drupal Handbook is made). You start with one particular school (it must be of type "book"). Under it you attach nodes (of any type) for its curricula. Under them you attach more child nodes. Besides text, all these nodes can contain php or embedded views. Then you use a module such as http://drupal.org/project/node_template or http://drupal.org/project/skeleton to clone the whole book structure and edit it for the next school. A bit primitive but simple.

A second method is to use views, as you did. The "category" which were wondering about is a category tag coming from taxonomy module. After you enable the taxonomy module, you can go to /admin/content/categories, and set up a vocabulary for schools containing the schools as terms (categories). You set up this vocabulary to apply to your node types, and then, whenever you edit a node, you can tag it with the school you want. So, you can tell a view to "list nodes of that type, which are for that school". Also read about views arguments to make this more efficient, instead of defining a view for each individual school.

A third method is to establish relationships between node types This can be done by using a CCK node reference fields, using the nodereference module included in CCK to create fields which pull a particular parent node. So, a curriculum node can draw info from the school. For the reverse relationship, you can look into http://drupal.org/project/nodereferrer module and and the http://drupal.org/project/viewfield. Obviously this is not simple.

All the above can be assisted by sidebar blocks, which may appear conditionally on pages of some level, can filter and refine categories, etc.

kedomingo’s picture

I tried using the Book module. However, at my level, I think I won't be able to control the creation of books.

I also tried to establish relationships between node types using CCK's node reference fields. So I created a content type School and added it as a reference field in a new type College. Ok, when I create a college, I can choose what school that college is affiliated. For example College of Law of Vietnam National University. I was excited. So I created another content type under College: Curriculum and now I don't know what to do. I tried to add a College reference field and it listed ALL the colleges in the database. What I want to do is to filter these colleges according to their parent school (chain select). So I should have 2 reference fields: School and College, and only when I choose a school should the colleges of that school display. Is this possible?

Also, I want to associate users to their schools. For example, If I use the Book module for creating the heirarchy, (one book per school, as you suggested), is there any way to allow users to edit the Book which represents their school only (and not be able to touch other books (schools))? This also means I need to add another field on the user data. Is there a way to add more details to a user? I remember only supplying my username, password and email on the registration form. How can I add other fields?

Thanks so much for all your help. I believe my boat is moving.

cog.rusty’s picture

For the Book solution, you can use some additional module for better control.

One solution is the http://drupal.org/project/bookexpand module, so that you can assign different roles to schools and allow each one add pages only to one book.

Another solution is to use the http://drupal.org/project/outline module instead of the book module (I have heard that the dev version is the working one). This will allow you to create "outlines" of different content types (not the book type) for which you can assign different "create" and "edit" permissions to different roles in /admin/user/access.

For the nodereference fields:

To be able to do "reverse references", you would probably need the http://drupal.org/project/nodereferrer module. Unfortunately nodereferrer seems to have been taken out of the repository, not sure why.

So, maybe you can use taxonomy-based fields to tag curricula with a college, for example http://drupal.org/project/cck-taxonomy, or the more complex http://drupal.org/project/content-taxonomy which has an activeselect widget (like the pair of fields you described). I haven't tried them.

The http://drupal.org/project/viewfield module could also be useful here for inserting views with a table of the dependent nodes.

kedomingo’s picture

I've finally decided to use the Book Module along with Organic Groups and Book Expand filtering.
There is only one problem with Book Expand though, whenever I tag a book page public, it can be edited/attached with pages by everyone. But when you don't tag a book page public, then it can only be seen (and edited) by the members of the group. What I wanted to do is when I tag it public, I want it to be viewable by but not editable by the public (or anyone from any other group/school).

The listing of child at the bottom page is OK for my needs so I don't need to use viewfield.

I will try later to create a view to list all the privately tagged schools to be viewable by the public and i will post my progress here.

But if you have better Ideas, please let me know.

Thanks a lot!

--Kyle

kedomingo’s picture

Or i'll see if I can hack the book expand module : )

Blitter’s picture

You can manage it using Taxonomy terms and the Taxonomy Access Control module. Its not super elegant but it will get you going quickly and easily.

netentropy’s picture

I have been dealing with this also. I have so often looked over book module but I need it.

The only thing I don't like is that you can always navigat back to root. I wish the root categories could be more like a section and section intro so that the person doesn't see where they can click back to say the root

for instance

my first "book" page i called "chapter 1" because would like the child pages to be the actual pages and the first "book" page to be a container only.....any ideas on this?

netentropy’s picture

I just found the site browser and the taxonomy context modules. they both do about the same thing. both are lacking just a bit. they are almost the perfect solution to what we describe above.

if sitebrowser had a dynamic menu

and if taxomonomy content had the ability to turn off and on taxonomoy descriptions it would be perfect...

http://www.netentropy.com/blog

kedomingo’s picture

I tried to do some hacks to the Node, Bookexpand and Organic Groups modules to do what I wanted (If a book is tagged private, it should be viewable by EVERYONE but only editable by the group who made it or assigned to edit it) but I failed simply because of the way drupal remembers "node access."

The node_access table contains 2 important columns: gid and realm (I'm not sure if these are present if OG is not installed). gid is the group ID (which group the node belongs to) and realm, well, how do i explain this? it has 3 distinct values: all, og_subscriber, and og_public. If a node was created by a certain group, gid will have a value (the id of the group). If that node is tagged private, realm will have 'og_subscriber' else 'og_public'. I think the 'all' realm was there when OG was not installed yet.

When displaying the nodes, OG displays nodes that does not belong to a group and whose realm is 'og_public.' I disabled that check in the _node_access_where_sql function in node.module (see following code).

$grants[] = "($node_access_alias.gid = $gid AND $node_access_alias.realm = '$realm')";

to

// $grants[] = "($node_access_alias.gid = $gid AND $node_access_alias.realm = '$realm')";

OK. now the main page displays nodes without checking gid and realm but when I click on a node tagged private by a group (which is displayed on the main page), it won't display the details. I am led to drupal_access_denied().

Is there a better way to do this? Letting everyone see every book but those books must be only editable by the group assigned to them?

Thanks for your patience and help.

--Kyle

kedomingo’s picture

I thought of something... I remembered, what I wanted to do actually was for other groups not be able to add pages to a book page not intended for them. So I searched for "Add child page" in book.module and voila! I was led to book_link.

the ownership of a book is stored in og_book. it has only two columns og_nid (the "node" id of the group) and book_nid (obviously, the node id of the book/bookpage)

I can get book_nid through

$node->nid

My problem now is, I don't know how to get the uid (userid) of the user currently logged in.

If i can get that, then I can get the groups that user is subscribed to (via og_uid) and see if there is an entry in og_book, using the book_nid and iterating through the og_uid.nid's of the user.

If there is no result for any combination, then I should not display the "Add child page" link. The pseudocode should look something like this

...
$book_nid = $node->nid
$uid = ??? // how do i get this?

$groupids = get_group_ids($uid)

foreach($groupids as $group_id) {
    // if book with id $book_nid belongs to
    // group with id $group_id
    if(bookBelongsTo($group_id, $book_nid)) {
    
        // display the link
        $links['book_add_child'] = array(
          'title' => t('Add child page'),
          'href' => "node/add/book/parent/$node->nid"
        );
        
    }
    
    // else do nothing
}
...

Again, how do i get the userid of the logged user?

Thanks for all your help!

--Kyle

cog.rusty’s picture

It is in a global object variable:

global $user;
print_r ($user);
if ($user->uid == ... 
  ...

etc

kedomingo’s picture

I finally got it running. here is the code I put in the book_link function of book.module.

I think i got the og_book wrong. The books stored there are the handbooks automatically created when creating a group using OG. So I used node_access.nid and node_access.gid.

<?php
...

        $userid = $user->uid;
        $bookid = $node->nid;
        
        $user_groups = db_query("SELECT n.nid FROM {og_uid} n WHERE n.uid = %d", $user->uid);
        
        $user_book_related = false;
        while(($group = db_fetch_object($user_groups)) != null){
            // echo "hey! <br />";
            $result = db_query("SELECT * FROM {node_access} na WHERE na.nid = %d AND na.gid = %d", $bookid, $group->nid);
            $row = db_fetch_object($result);
            
            if($row != null){
                $user_book_related = true;
                break;
            }
        }
        
        if($user_book_related){
            $links['book_add_child'] = array(
              'title' => t('Add child page'),
              'href' => "node/add/book/parent/$node->nid"
            );
        }

...
?>

--Kyle

kedomingo’s picture

Okay, so, the (hacked) book module, along with book expand, and OG, are serving my hierarchical needs well (I just found out that the correct spelling of hierarchical is hierarchical and not heirarchical :D ). Problem is, I will have a node that will be adopted by several parent pages. That is, it will be used in one node and in other several nodes as well. To be specific, this will be used in listing law cases in different syllabi.

For example, the syllabus of Law 99 references a case (say, Cormen vs. Leiserson (which is not a real case by the way. they are professors at MIT)). At the same time, another course, say Law 131 references the same case as well. As far as I know, according to my extent of use of the Book module, a page can only be a child by another single parent page (a tree structure), and not of several pages (graph structure).

        OK             |       NOT OK
                       |
    College of Law     |    College of Law      
          /\           |         /\
    law 99  Law 131    |   Law 99  Law 131
        /    \         |         \/
  case A      case A   |       case A

Am I just missing the feature I want from the Book module, or are there other modules that does this?

Thanks so much for all your help!

-- Kyle

cog.rusty’s picture

Generally book does not do multiple hierarchies. It has been discussed a bit and one of the problems was backwards navigation to the parent and remembering where the user came from.

Taxonomy does do multiple hierarchies but is no good for navigation because terms don't carry content.

Perhaps the simplest is to stay with book and clone the child node to keep everything tidy.

http://drupal.org/project/node_clone for cloning nodes
http://drupal.org/project/node_template or http://drupal.org/project/skeleton for cloning whole book structures

netentropy’s picture

this is interesting what would it do exactly?

cog.rusty’s picture

A node clone is just an identical copy, a different node. It is mostly used for creating identical-looking nodes, with titles, subtitles etc which others can fill-in to provide a standard look, but it could serve here too.

The idea was to keep a single hierarchy but use duplicate nodes for the common children, so that each child knows only one parent for navigating back.

The other modules do the same thing, but they copy whole hierarchies, possibly containing trees of node types with different fields if needed.

kedomingo’s picture

I have duplicated the book module as stated in this tutorial (http://drupal.org/node/102446 [How to make a duplicate Book module]) to make several instances of links that creates pages of the same type: "book." I did this so I will know which levels to show in the parent field when creating a page.

For instance, I have duplicated it and renamed the clone to "ContentContainer." This is a "place holder" for similar book pages like "LawSchools" or "LawFirms." This is a top-level book page and so it only shows "". I created another duplicate and named it to "LawFirms." This on the other hand are collection of law firms. So when i try to add a "LawFirm" page, I only show the pages with type "ContentContainer", on the parent field, and the other pages on the other levels are really not needed.

I was able to do this with one or two duplicates but here is the problem, at times (which I really cannot pinpoint), when I click on the "Administer" link on the main menu, the page goes blank.

I must have done something wrong. Any tips on cloning/"renaming" the book module better? Also, how can I know what happened on the site? How do i see the debug messages? I tried googling on "debugging drupal" but they all seem to require another piece of software. Please advise.

Thanks!

--Kyle

cog.rusty’s picture

The most common cause of blank screens is the php memory limit. So it is possible that the problem is caused by loading more of those cloned modules. Try an 24M memory limit.

http://drupal.org/node/76156

In Drupal 5 the error logs are in /admin/logs page. But usually errors caused by lack of resources are not reported there because of... lack of resources, so you may need access to the server's logs to see what happens.

kedomingo’s picture

I backtracked and found that stupidity caused the blank screen. I only renamed book.install to _CLONE_.install and did not rename the functions inside it: book_install and book_uninstall, thus resulting to redeclarations of those functions.

The info on memory limits won't go to waste though. Thanks a lot!

--Kyle

summit’s picture

Subscribing, greetings, Martijn