Adding a related table to the FUEL module pages_model

edited April 2012 in Modules
Hi,

I'm trying to add a documents field to the pages model, such that for any CMS page, the user might "attach" documents to it. These would then be downloadable on the page view.

I've followed the example in the category->articles tutorial, and while I've had success with that method with "simple" modules, I can't quite get it to work thoroughly for the pages_model.

I've got the combo box up in the CMS admin page, and this allows me to copy "documents" left to right, and save them (ie the lookup table gets the correct document id and page id recorded using the "on_after_save" hook). What doesn't happen is that, on page refresh, the right hand combo box does not record what is already associated.

How does the multiple select underlying the combo boxes read in the "selected" (ie previously attached) data?

Here's what I have in the form_fields method for the pages_model:

function form_fields($values = array()) { $related = array('documents' => 'documents_to_pages_model'); $fields = parent::form_fields(); $fields['date_added']['type'] = 'hidden'; // ******************* NEW RELATED DOCUMENT FIELD BEGIN ******************* $CI =& get_instance(); $CI->load->model('documents_model'); $CI->load->model('documents_to_pages_model'); $document_options = $CI->documents_model->options_list('id', 'title', array('active' => 'yes'), 'title'); $document_values = (!empty($values['id'])) ? array_keys($CI->documents_to_pages_model->find_all_array_assoc('document_id', array('page_id' => $values['id']))) : array(); $fields['documents'] = array('label' => 'Documents', 'type' => 'array', 'class' => 'add_edit documents', 'options' => $document_options, 'value' => $document_values, 'mode' => 'multi'); // ******************* NEW RELATED DOCUMENT FIELD END ******************* $yes = lang('form_enum_option_yes'); $no = lang('form_enum_option_no'); $fields['cache']['options'] = array('yes' => $yes, 'no' => $no); return $fields; }

I imagine the $document_values for the select are not coming back as I expect.

The "documents_to_pages_model" table columns are: id, page_id, document_id, date_added, last_updated

Comments

  • edited 1:38AM
    Have you implemented an on_after_save hook to save the the values perhaps using the save_related method on the model?
  • edited April 2012
    Yep, the on_after_save is working fine, it's the select back that seems to be the issue. I've been debugging what "find_all_array_assoc()" might be returning, and oddly, it seems $values['id'] is empty even on edit (eg if the url in this case is '/fuel/pages/edit/11' I am expecting '11' to be the value of $values['id'].

    The primary key of the fuel_pages table is 'id' so I'm puzzled. If I hard code the value of $values['id'] in the find_all_array_assoc() then everything works as expected (eg set the value as '11' where the url is /fuel/pages/edit/11).
  • edited April 2012
    Now I'm looking into the pages_model more closely and realise it's not as familiar as I thought. The model isn't (obviously) "fuel_pages_model", and the __construct uses "pages" not "fuel_pages"?

    Also, the on_after_save function is working and that does utilise values['id']:
    function on_after_save($values) { $data = (!empty($this->normalized_save_data['documents'])) ? $this->normalized_save_data['documents'] : array(); $this->save_related('documents_to_pages_model', array('page_id' => $values['id']), array('document_id' => $data)); }

    so I'm concluding no array "$values" is passed to form_fields() - hence the default empty array argument used in the form_fields() code above is the reason there is never a 'id' to send to the "find_all_array_assoc()" ?

    For want of anything else, I can get the page id using:
    $this_id = (is_numeric($this->uri->segment($this->uri->total_segments()))) ? $this->uri->segment($this->uri->total_segments()) : NULL;

    On a related matter, if I wanted to retrieve the id of the fuel_page in a particular view or block, what would be the best method?
  • edited 1:38AM
    Yes... this is an issue if you are trying to replace the pages_model. On line 117 in the fuel/modules/fuel/controllers/pages.php controller, you can change it to:
    $fields = $this->model->form_fields($saved);
    This will be fixed in the next major release.

    For the pages_model, the "pages" actually does reference the fuel_pages table because the __construct method in base_module_model references the config parameter "tables" which is an array of aliases to tables.
  • edited April 2012
    Ok I'll try that - but on my last point - what is the page_id that can be retrieved from a view for a CMS page?
  • edited 1:38AM
    The page ID should be passed in the $values array of the form_fields method after that change is made. It is also part of the segment too which you pointed out.
  • edited 1:38AM
    Actually I meant what's the best means of getting the CMS page id from the front-end view (or block), one rendered by $this->fuel_page->render()? I took a look around the forum and a method as good as any (?) seemed to be:
    $location = uri_path(); $CI =& get_instance(); $CI->load->module_model(FUEL_FOLDER, 'pages_model'); $page = $CI->pages_model->find_by_location($location); $pid = $page['id'];

    but maybe that's a bit verbose. I think there is probably a means of doing the same but with fuel_model(), but I haven't tried yet.

    On the bright side I've achieved what I wanted to do, create a document attachment to fuel_pages. To round it off nicely I would find a way of making the combo boxes for the attachment process appear last on the admin page (eg after the layout variables), but I think that would require more tinkering with the fuel admin views - it's not something that can be shuffled around with the form_fields() configuration.
  • edited May 2012
    The find_by_location method would be the way to do it similar to what you have.

    To have the fields appear last, you can set the "order" field parameter to something over 1000. By default, published/active are set to like 999 so they will appear last:
    $fields['documents'] = array('label' => 'Documents', 'type' => 'array', 'class' => 'add_edit documents', 'options' => $document_options, 'value' => $document_values, 'mode' => 'multi', 'order' => '10000');
  • edited 1:38AM
    Wow! I'd dismissed the ordering potential as I noticed the page variables and page record fields were dealt with separately in the admin view.
  • edited May 2012
    Hmm. Actually, now I've tried this out my initial scepticism was right. Setting the order key of the "documents" field to a high value does not move it relative to all the other fields.

    I wanted to set the documents field last in the entire "edit/create" form, but it is only possible to make it last of the "page information" section, using the "order" key (I think this is what you intended with your suggestion).

    Conversely, if I set
    $fields['page_title']['order'] = 1;
    in form_fields() for pages_model.php, then the page variable field "page_title" does shift position (to the 3rd row in the form) but then causes an error
    There is an error with this layout because it contains one or more of the following reserved words: location, layout, published, cache, date_added, last_modified, last_modified_by, page_title, documents
    which breaks the "layout variables" section.

    Looks like the page variables cannot be re-ordered either. The form_fields() mustn't use keys present in page variables.
  • edited 1:38AM
    If this is for the pages module, then that is correct. There are actually to form_builder instances rendering there. One for the page information and the other for the page variable information.

    That warning appears because you still have the "documents" form field as part of the pages module and that is checked to prevent conflicts on submit between data for the pages module and data for the page variables module.
Sign In or Register to comment.