4

I've created a custom content-type called "Books."

I need to create another content type named "Catalogs" which may contain one/many "Books" as its fields.

How would I achieve that? I'd prefer some GUI tool to construct my custom content type, from admin panel, or doing some coding, if necessary.

PS: I found this question asked here but the solution did not help. Can someone provide a detailed answer, please?

EDIT:

MohammadAliAkbari's answer works perfectly :) One problem - When adding "Books" a user can add Books not created by him - he can add any Book to his "Catalog" - How can I add constraints such that a user can add Books only created by him to his Catalog?

Solution:

Using Tenken's answer, I figured out that I can write this code in my module to solve the scenario just mentioned above:

function myModule_form_alter(&$form, &$form_state, $form_id) {
//    dsm($form_id); // Use this line to find YOUR-DESIRED-FORM-ID
    switch ($form_id) {    
        case 'YOUR-DESIRED-FORM-ID':
            $form['#validate'][] = 'stylesku_add_sku_form_validate';
//            dsm($form); // Use this to find out form's elements
            global $user;
            $currentUser = $user->uid;
            $fieldSku = $form['FIELD-ID-OF-BOOK'];
            $lang = $fieldSku['#language'];
            $fieldOptions = $fieldSku[$lang]['#options'];
            foreach($fieldOptions as $nid=>$nodeTitle){
                if(!is_int($nid))
                    continue; // Needed as the first option in select box is not really any book
                $nid = (int) $nid;
                $n = node_load($nid);
                if($n->uid != $currentUser){
                    // Remove this BOOK, this book was not created by current user
                    unset($form['FIELD-ID-OF-BOOK'][$lang]['#options'][$nid]);
                }
            }
            break;
    }
}
3

Ok, you should be familiar with

  1. entity
  2. view mode
  3. entityreference

after install entityreference create a reference to books in your catelogs content-type, then go to catelogs > manage display and for books reference select Rendered entity formatter and in its options set something like teaser

after this go to books > manage display and configure teaser as you need.

also you can add more view modes by Display Suite or via simple module:

function mymodule_entity_info_alter(&$entity_info) {
  $entity_info['node']['view modes']['render_in_catelogs'] = array(
      'label' => t('render in catelogs'),
      'custom settings' => FALSE,
  );
}
  • Thanks @MohammadAliAkbari that works perfectly :) One problem - When adding Books a user can add Books not created by him - he can add any Book to his Catelog - How can I add constraints such that a user can add Books only created by him to his Catelog? Thanks in advance for helping... – Shafiul Mar 25 '12 at 10:05
  • some hacks near protected function buildEntityFieldQuery(... is needed in entityreference/handler/base.inc – Mohammad Ali Akbari Mar 25 '12 at 10:37
  • Hacking will ruin it, being unable to update the module later. Is there any other elegant solution? Thanks – Shafiul Mar 25 '12 at 10:42
  • entityreference not allow other solution (I think), so you can add this feature and commit it in drupal.org, you should add some setting in widget form and some conditions in buildEntityFieldQuery based on field instance setting – Mohammad Ali Akbari Mar 26 '12 at 3:57
  • I've created an issue at EntityReference's page... I'm waiting for their response, then I'll try! – Shafiul Mar 26 '12 at 4:17
2

I can see 2 options to build upon @Akbari's advice ...

  1. the easy way hook_form_alter to change the select options to be limited to entityreference node values owned by the end-user. Alter the node submit validate function to assure its one the user owns. So this attempt would just edit the $form item using FAPI tweaks ... you can use FAPI '#element_validate' option to set a validate function for the selected $book.
  2. the really hard way ... which might work as @Akbari suggested ... you need to alter EntityReference_SelectionHandler_Generic::buildEntityFieldQuery() somehow. I recommend using hook_field_info_alter() to supply your own $info['entityreference']['handler'] key in the field info that extends the base class with your own and overrides the buildentityinfo logic with "ownership" logic. You will probably need to make the entityreference ctools plugins aware of your custom handler (somehow) ... an example using hook_field_info_alter can be found in this blog post (not mine) ...
  • Thanks Tenken! I'd really like to go with option 1 - I'll try and ask again here if I'm in trouble! – Shafiul Mar 26 '12 at 4:14
  • Thanks @Tenken, option 1 works perfectly, I added my code in my question. I tried to manipulate the form using malicious data - and it seems that Drupal can figure out if any user is trying to change form's select box's information. So do I really need to add a validate handler? – Shafiul Apr 2 '12 at 13:00
1

You can use the Multifield or Field Collection module.

0

You can use node reference cck field. Node reference is a CCK field by which you can create some relationship between the two content types. At the time of creation a catalog you can assign book nodes to the catalog and make it multivalued so you can assign one or more book nodes to the catalog content type.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.