You are missing some Flash content that should appear here! Perhaps your browser cannot display it, or maybe it did not initialize correctly.

CCK Export for node modules

 
 

So I spent yesterday learning some new things about Drupal.  As always there's too much for any one person, so I'm going to share what I learned in the hopes that it will help other out, and maybe let us refine a process toward getting these sorts of modules fast-tracked toward being the "Drupal-Way".

In this blog I'm going to cover a number of different concepts including the ability to package your own pre-built designs via views, packaging content types via cck, and just some all around niceties that Drupal 6 makes so easy.

First, let's discuss the Views module for a bit. Views2 is one of the greatest additions to Drupal since... well...Views1 or CCK.  Views2 takes a number of jobs and makes them generally easier, and more straight forward.  Views2 can connect to non-node tables, even custom table structures, and importantly for this tutorial it can provide default views for you module.  Seeing as how Drupal is going to provide us with 90% of all the code we need for this module, we need to understand how those components all come together.

I'm going to gloss over the most of the views setup, but for those of you who are interested, Merlinofchaos (Earl Miles) has a great tutorial you can check out here.  I specifically followed this portion of his documentation pretty closely.  It specifies both how to package your own views with a module as well as how to build custom themes for those views.  Very powerful stuff.  As a side note, the docs, while great, don't immediately make it clear what your "displayid" is.  So for those of you following this method please refer to the provided theme information that each view has as part of the views2 admin.  You'll see at "Theme: Information" toward the bottom of each view display's administration and this particular button can save you MANY headaches and hours of time.  Generally speaking the first theme  mentioned in any group you're over-riding is your "original hook", and the furthest one down that same list will be the actual template you're over-riding.  Also, Merlin's docs make it pretty clear that you should make template hook names all underscores (regardless of what the view or displayid names are) and your template name should be all dashes (again, regardless of what you've named things).

With that all out of the way, let's dive into the meat of this article which is how we add CCK exported code to a module and have that module install the content type for us.  For those of you who are not familiar with CCK export, CCK essentially has the ability to provide you with code so that it's portable from one site to the next (especially good for dev/live scenarios).  However, unlike Views2, which provide actual hooks that it will go looking for to install its own exported code, CCK provides this only as an administrative nicety.  As such we actually have to hook into CCK's import forms and tell drupal to execute them properly.  This is where drupal_execute comes in.  Chances are you've seen some ugly implementations of this sort of thing in the past, but this is actually pretty clean, so stick with me.

First things first: We only want to do this on install, so we need a module.install file and a hook_install as well.  Now for clenliness sake I've put the cck exported code into its own file: module.cck.inc.  Again, it'd be nice if CCK just looked for a file of a naming convention similar to this, and just imported the content type on install (the way views does).  However... you could potentially screw a view up really badly, and have almost no ill-effects as you can always revert to whatever the module provided for you.  CCK is dealing with live tables, and as such, more thought needs to go into such an implementation.  My use-case here is pretty narrow (intentionally) and so it works great for this.  Within our hook_install we're going to add the following lines:

<?php
db_query
("UPDATE {system} SET weight = 11 WHERE name = 'modulename'");
module_load_include('inc', 'modulename', 'module.cck');
$form_state['values']['type_name'] = '&lt;create&gt;';
$form_state['values']['macro'] = module_cck_export();
drupal_execute('content_copy_import_form', $form_state);
?>

This code does a couple things. The db_query is required by views, since we're custom theming these views. It's mentioned in Merlin's documentation.

Next, we load up our cck include container.  This file contains one function, I named mine module_cck_export.  You could name it anything.  Then we start to build up our form_state variable.  By setting the type_name to  <create> cck will create a content type as specified by the macro portion of the form_state (your cck export code). Finally we'll execute the same form function that CCK uses for the import and pass our own built up version of the form_state to it.

Hopefully that's all made sense up to this point.  Our next challenge is to properly add the cck export into our module's code.  CCK treats this code as though its a string.  This code (at first glance) is an array, and indeed CCK ultimately treats it as such, but we're handling this via the import form and so we need to give CCK what it expects.  My module was used to create testimonials.  The following code is what CCK gave me with the caveat that since we want to handle this all as a string, we've escaped CCK's provided single quotes.

<?php
function testimonial_cck_export() {
$output = '$content[type]  = array (
\'name\' =&gt; \'Testimonial\',
\'type\' =&gt; \'testimonial\',
\'description\' =&gt; \'This content type is used to create testimonial entries.  These entries can be sorted through a variety of provided views or you may create your own view.\',
\'title_label\' =&gt; \'Client Name\',
\'body_label\' =&gt; \'Testimonial\',
\'min_word_count\' =&gt; \'0\',
\'help\' =&gt; \'\',
\'node_options\' =&gt;
array (
\'status\' =&gt; true,
\'promote\' =&gt; false,
\'sticky\' =&gt; false,
\'revision\' =&gt; false,
),
\'language_content_type\' =&gt; \'0\',
\'i18n_node\' =&gt; \'1\',
\'i18nsync_nodeapi\' =&gt;
array (
\'author\' =&gt; false,
\'status\' =&gt; false,
\'promote\' =&gt; false,
\'moderate\' =&gt; false,
\'sticky\' =&gt; false,
\'revision\' =&gt; false,
\'parent\' =&gt; false,
\'taxonomy\' =&gt; false,
\'comment\' =&gt; false,
\'field_testimonial_link\' =&gt; false,
),
\'old_type\' =&gt; \'testimonial\',
\'orig_type\' =&gt; \'\',
\'module\' =&gt; \'node\',
\'custom\' =&gt; \'1\',
\'modified\' =&gt; \'1\',
\'locked\' =&gt; \'0\',
\'comment\' =&gt; \'0\',
\'comment_default_mode\' =&gt; \'4\',
\'comment_default_order\' =&gt; \'1\',
\'comment_default_per_page\' =&gt; \'50\',
\'comment_controls\' =&gt; \'3\',
\'comment_anonymous\' =&gt; 0,
\'comment_subject_field\' =&gt; \'1\',
\'comment_preview\' =&gt; \'1\',
\'comment_form_location\' =&gt; \'0\',
);
$content[fields]  = array (
0 =&gt;
array (
\'label\' =&gt; \'Client Link\',
\'field_name\' =&gt; \'field_testimonial_link\',
\'type\' =&gt; \'link\',
\'widget_type\' =&gt; \'link\',
\'change\' =&gt; \'Change basic information\',
\'weight\' =&gt; \'-3\',
\'description\' =&gt; \'\',
\'default_value\' =&gt;
array (
0 =&gt;
array (
\'title\' =&gt; \'\',
\'url\' =&gt; \'\',
),
),
\'default_value_php\' =&gt; \'\',
\'default_value_widget\' =&gt; NULL,
\'group\' =&gt; false,
\'required\' =&gt; 1,
\'multiple\' =&gt; \'0\',
\'url\' =&gt; 0,
\'title\' =&gt; \'required\',
\'title_value\' =&gt; \'\',
\'enable_tokens\' =&gt; 0,
\'display\' =&gt;
array (
\'url_cutoff\' =&gt; \'80\',
),
\'attributes\' =&gt;
array (
\'target\' =&gt; \'_blank\',
\'rel\' =&gt; \'\',
\'class\' =&gt; \'testimonial_link\',
),
\'op\' =&gt; \'Save field settings\',
\'module\' =&gt; \'link\',
\'widget_module\' =&gt; \'link\',
\'columns\' =&gt;
array (
\'url\' =&gt;
array (
\'type\' =&gt; \'varchar\',
\'length\' =&gt; 255,
\'not null\' =&gt; false,
\'sortable\' =&gt; true,
),
\'title\' =&gt;
array (
\'type\' =&gt; \'varchar\',
\'length\' =&gt; 255,
\'not null\' =&gt; false,
\'sortable\' =&gt; true,
),
\'attributes\' =&gt;
array (
\'type\' =&gt; \'text\',
\'size\' =&gt; \'medium\',
\'not null\' =&gt; false,
),
),
\'display_settings\' =&gt;
array (
\'label\' =&gt;
array (
\'format\' =&gt; \'above\',
\'exclude\' =&gt; 0,
),
\'teaser\' =&gt;
array (
\'format\' =&gt; \'default\',
\'exclude\' =&gt; 0,
),
\'full\' =&gt;
array (
\'format\' =&gt; \'default\',
\'exclude\' =&gt; 0,
),
4 =&gt;
array (
\'format\' =&gt; \'default\',
\'exclude\' =&gt; 0,
),
2 =&gt;
array (
\'format\' =&gt; \'default\',
\'exclude\' =&gt; 0,
),
3 =&gt;
array (
\'format\' =&gt; \'default\',
\'exclude\' =&gt; 0,
),
\'token\' =&gt;
array (
\'format\' =&gt; \'default\',
\'exclude\' =&gt; 0,
),
),
),
);
$content[extra]  = array (
\'title\' =&gt; \'-5\',
\'body_field\' =&gt; \'-4\',
\'menu\' =&gt; \'-2\',
);'
;
return
$output;
}
?>

As I said this is CCK's provided export code with the caveat that we've escaped all the provided single quotes.  Via our install hook we can now install a new content type, any associated fields (mines using a link field) and if we provide default views with our module all of that can come to life with the single click of a button as well.  All of it designed to our code specifications with as little effort, and as much re-usability as possible.

It's worth noting that this is the entirety of my .module file:

<?php
function testimonial_views_api() {
return array(
'api' =&gt; 2,
);
}
function
testimonial_theme($existing, $type, $theme, $path) {
return array(
'views_view__testimonials_page__page_1' =&gt; array (
'arguments' =&gt; array('view' =&gt; NULL),
'template' =&gt; 'views-view--testimonials-page--page-1',
'original hook' =&gt; 'views_view',
),
'views_view_unformatted__testimonials_page__page_1' =&gt; array(
'arguments' =&gt; array('view' =&gt; NULL, 'options' =&gt; NULL, 'rows' =&gt; NULL, 'title' =&gt; NULL),
'template' =&gt; 'views-view-unformatted--testimonials-page--page-1',
'original hook' =&gt; 'views-view-unformatted',
),
);
}
function
testimonial_preprocess_views_view__testimonials_page__page_1(&amp;$vars) {
drupal_add_css(drupal_get_path('module', 'testimonial') .'/testimonial.css');
}
?>

Hopefully this code will help someone out.  I'd love to hear feedback on this, and if anyone has a method for making the CCK export a tad cleaner, that would be awesome as well.  Have a happy Thanksgiving all.

 
The content of this field is kept private and will not be shown publicly.
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.
  • HTML tags will be transformed to conform to HTML standards.

More information about formatting options

 

I'm having trouble with the

I'm having trouble with the code displaying properly but hopefully this is still clear to all involved.

Good stuff, but too long and

Good stuff, but too long and hard to read.

Yeah, kind of felt the same

Yeah, kind of felt the same as I wrote it, but there was an awful lot of information to convey here. I hope some people can make use of it, I'll probably put together a video about it soon.

This all jives with what

This all jives with what I've been doing this week. I have an alternate way of including the CCK export code, that makes you include file a bit easier (the whole file is just the CCK export, no modifications):

function m29_blank_install() {
 
  ob_start();
  require ('m29_blank.definition');
  ob_end_clean();

  $form_state['values']['type_name'] = '<create>';
  $form_state['values']['macro'] = '$content = '. var_export($content, 1) .';';
  $form_state['values']['op'] = t('Import');
 
  drupal_execute('content_copy_import_form', $form_state); 
}

More pertinently, I'm trying to figure out how to provide a default node template for the exported data type. You have any leads on that?

Drupal vs. Wordpress

I've been designing wordpress themes for a while now and I have been wondering if there is a demand for Drupal themes? Is there much difference between the two as far as developing template themes?

Drupal is a content

Drupal is a content management system, and can pretty easily be set up and used without any programming knowledge. There's also plenty of plugins and templates that can be added/purchased, again without the need for programming knowledge. However if you want to customise it, you will really need a solid understanding.

Good stuff, but too long and

Good stuff, but too long and hard to read.

medyum

This all jives with what I've been doing this week. I have an alternate way of including the CCK export code, that makes you include file a bit easier (the whole file is just the CCK export, no modifications):

function m29_blank_install() {<br>&nbsp; <br>&nbsp;
ob_start();<br>&nbsp; require ('m29_blank.definition');<br>&nbsp; ob_end_clean();<br><br>&nbsp;
$form_state['values']['type_name'] = '&lt;create&gt;';<br>&nbsp;
$form_state['values']['macro'] = '$content = '. var_export($content, 1)
.';';<br>&nbsp; $form_state['values']['op'] = t('Import');<br>&nbsp; <br>&nbsp;
drupal_execute('content_copy_import_form', $form_state);&nbsp; <br>}

More pertinently, I'm trying to figure out how to provide a default node template for the exported data type. You have any leads on that?

 

medyum

http://www.medyumca.com

www.medyum-cenaphoca.info

awesome

great website

 

<a href='http://www.webcada.com'>web design singapore</a>

© 2009 the Worx Company
site designed by the Worx Company · site hosted by Hosts of America