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'] = '<create>';
$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\' => \'Testimonial\',
\'type\' => \'testimonial\',
\'description\' => \'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\' => \'Client Name\',
\'body_label\' => \'Testimonial\',
\'min_word_count\' => \'0\',
\'help\' => \'\',
\'node_options\' =>
array (
\'status\' => true,
\'promote\' => false,
\'sticky\' => false,
\'revision\' => false,
),
\'language_content_type\' => \'0\',
\'i18n_node\' => \'1\',
\'i18nsync_nodeapi\' =>
array (
\'author\' => false,
\'status\' => false,
\'promote\' => false,
\'moderate\' => false,
\'sticky\' => false,
\'revision\' => false,
\'parent\' => false,
\'taxonomy\' => false,
\'comment\' => false,
\'field_testimonial_link\' => false,
),
\'old_type\' => \'testimonial\',
\'orig_type\' => \'\',
\'module\' => \'node\',
\'custom\' => \'1\',
\'modified\' => \'1\',
\'locked\' => \'0\',
\'comment\' => \'0\',
\'comment_default_mode\' => \'4\',
\'comment_default_order\' => \'1\',
\'comment_default_per_page\' => \'50\',
\'comment_controls\' => \'3\',
\'comment_anonymous\' => 0,
\'comment_subject_field\' => \'1\',
\'comment_preview\' => \'1\',
\'comment_form_location\' => \'0\',
);
$content[fields] = array (
0 =>
array (
\'label\' => \'Client Link\',
\'field_name\' => \'field_testimonial_link\',
\'type\' => \'link\',
\'widget_type\' => \'link\',
\'change\' => \'Change basic information\',
\'weight\' => \'-3\',
\'description\' => \'\',
\'default_value\' =>
array (
0 =>
array (
\'title\' => \'\',
\'url\' => \'\',
),
),
\'default_value_php\' => \'\',
\'default_value_widget\' => NULL,
\'group\' => false,
\'required\' => 1,
\'multiple\' => \'0\',
\'url\' => 0,
\'title\' => \'required\',
\'title_value\' => \'\',
\'enable_tokens\' => 0,
\'display\' =>
array (
\'url_cutoff\' => \'80\',
),
\'attributes\' =>
array (
\'target\' => \'_blank\',
\'rel\' => \'\',
\'class\' => \'testimonial_link\',
),
\'op\' => \'Save field settings\',
\'module\' => \'link\',
\'widget_module\' => \'link\',
\'columns\' =>
array (
\'url\' =>
array (
\'type\' => \'varchar\',
\'length\' => 255,
\'not null\' => false,
\'sortable\' => true,
),
\'title\' =>
array (
\'type\' => \'varchar\',
\'length\' => 255,
\'not null\' => false,
\'sortable\' => true,
),
\'attributes\' =>
array (
\'type\' => \'text\',
\'size\' => \'medium\',
\'not null\' => false,
),
),
\'display_settings\' =>
array (
\'label\' =>
array (
\'format\' => \'above\',
\'exclude\' => 0,
),
\'teaser\' =>
array (
\'format\' => \'default\',
\'exclude\' => 0,
),
\'full\' =>
array (
\'format\' => \'default\',
\'exclude\' => 0,
),
4 =>
array (
\'format\' => \'default\',
\'exclude\' => 0,
),
2 =>
array (
\'format\' => \'default\',
\'exclude\' => 0,
),
3 =>
array (
\'format\' => \'default\',
\'exclude\' => 0,
),
\'token\' =>
array (
\'format\' => \'default\',
\'exclude\' => 0,
),
),
),
);
$content[extra] = array (
\'title\' => \'-5\',
\'body_field\' => \'-4\',
\'menu\' => \'-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' => 2,
);
}
function testimonial_theme($existing, $type, $theme, $path) {
return array(
'views_view__testimonials_page__page_1' => array (
'arguments' => array('view' => NULL),
'template' => 'views-view--testimonials-page--page-1',
'original hook' => 'views_view',
),
'views_view_unformatted__testimonials_page__page_1' => array(
'arguments' => array('view' => NULL, 'options' => NULL, 'rows' => NULL, 'title' => NULL),
'template' => 'views-view-unformatted--testimonials-page--page-1',
'original hook' => 'views-view-unformatted',
),
);
}
function testimonial_preprocess_views_view__testimonials_page__page_1(&$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.
Good stuff, but too long and
Good stuff, but too long and hard to read.
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> <br>
ob_start();<br> require ('m29_blank.definition');<br> ob_end_clean();<br><br>
$form_state['values']['type_name'] = '<create>';<br>
$form_state['values']['macro'] = '$content = '. var_export($content, 1)
.';';<br> $form_state['values']['op'] = t('Import');<br> <br>
drupal_execute('content_copy_import_form', $form_state); <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
www.medyum-cenaphoca.info
awesome
Drupalcon DC Sponsorship
A proud sponsor of Drupalcon DC!

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