CCK for Developers
Last modified: June 3, 2009 - 12:01
In addition to the material in this handbook, developers may find the Content Construction Kit Group to be a useful source of information. That is an active group of people who develop and use CCK modules, and it's a good a place to read what others are doing, or post questions and announcements about CCK development. For a good introduction to the data model used by CCK, you may want to read the introduction to CCK article on the lullabot site.

create CCK type in a module
Could someone please outline how to create a custom CCK in a module.
I've read the threads:
http://drupal.org/node/348214
also
http://civicactions.com/blog/cck_import_and_update
http://snipplr.com/view/3891/import-cck-definition-from-text-file/
http://groups.drupal.org/node/5272
http://drupal.org/node/128038#comment-921630
specifically:
* @param $module
* @param $dir
* The module which containing the CCK definitions.
* @param $ext
* Extension
*/
function cck_install_content_dir($module, $dir = 'content_types', $ext = 'content') {
$content_types = content_types();
$files = file_scan_directory(drupal_get_path('module', $module) . '/' . $dir, "\.${ext}$");
foreach ($files as $file) {
module_load_include('inc', 'install_profile_api', 'contrib/content_copy');
install_content_copy_import_from_file($file->filename);
}
}
In example:
/**
* Implementation of hook_install().
*/
function my_module_install() {
cck_install_content_dir('my_module');
}
But how to adjust this to a module and NOT in an installation profile.
Do I just put this code in the *.module file.
How does it get triggered in module setup?
The reason?
SO I don't have to reinstall drupal in order to create custom CCKs.
Thanks in advance.
cheers
Ed
That is not an installation
That is not an installation profile, it's a modules install file that run once when the module is installed and is the appropriate place to do what you are after the reason being that code is meant to only run once. One could make a setting pages that adapts that code to it keeps track of files already loaded and does not load them again.
Programmatic CCK content type creation
I found this too.
http://tinpixel.com/node/53
http://thedrupalblog.com/programmatically-create-any-node-type-using-dru...
Step 3: create a PHP function to hold your CCK definition
The template of the function will look like this, prior to pasting the contents of your copy buffer from above (containing the exported CCK content type definition code). We use a separate function just for the definition because it is must be updated with a new export from CCK if we decide to change or tweak our CCK content type later. It makes editing easier and less error prone.
function _modulename_cck_export() {
// paste code after this line.
// paste code before this line.
return $content;
}
Step 6: Write PHP code to actually create the content type
Write the install code to initiate creation of the new content type. This is where we make sure we have the necessary CCK pieces, populate a form using the now hard-coded CCK export, and then use drupal_execute() to submit the form to create the new content type. Here's an example:
function _example_install_cck_node() {
/* get the CCK node types to be created. This is where you load the
* file containing your function from above, if necessary, and then call
* that function.
*/
module_load_include('inc', 'modulename', 'modulename.ccknodedef');
$content = _modulename_cck_export(); // in modulename.ccknodedef.inc
// CCK content_copy.module may not be enabled, so make sure it is included
require_once './' . drupal_get_path('module', 'content')
. '/modules/content_copy/content_copy.module';
$form_state['values']['type_name'] = '';
$form_state['values']['macro'] = '$content = ' . var_export($content, TRUE) . ';';
// form provided by content_copy.module
drupal_execute('content_copy_import_form', $form_state);
content_clear_type_cache();
}
EDIT:
I'm happy to say the following code worked for me. ;-)
I'm also able to use node_import to import values into a newly created CCK node.
in the provider.install file
<?php
// $Id$
/***********************************************************************************************
* Implemenation of hook_install();
*/
function provider_install(){
watchdog('provider_install.');
provider_update_1();
};
/***********************************************************************************************
* Implemenation of provider_update_1();
* just so that i can force build of CCK Types without uninstalling/re-installing
*/
function provider_update_1() {
//
$ret = array();
watchdog('provider_update_1.');
//
if (!module_exists("content_copy")) {
drupal_set_message('Programmatically creating CCK fields requires the Content Copy module. Exiting.');
// CCK content_copy.module may not be enabled, so make sure it is included
require_once './' . drupal_get_path('module', 'content')
. '/modules/content_copy/content_copy.module';
}
// add CCK types
$path = drupal_get_path('module', 'provider') . "/cck_types";
$cck_types = glob($path . "/*.txt");
foreach ($cck_types as $cck_type) {
provider_install_cck_node('<create>', '', $cck_type);
}
return $ret;
}
/**
* Programmatically create CCK fields and types using the content copy module
* @param $type string
* content type to create, defaults to new type, if type exists, only fields will be added
* @param $macro array
* exported array from content types -> export. If file is not specified, macro will be used
* @param $file string
* path to file containing content copy exported macro data structure. no escaping needed.
*/
function provider_install_cck_node($type = '<create>', $macro = '', $filename = '') {
watchdog('provider_install_cck_node.');
// Get the files content
if (file_exists($filename)) {
$content = implode('', file ($filename));
}
else {
drupal_set_message('Unable to read input file for import. Exiting.');
return;
}
// Build form state
$form_state = array(
'values' => array(
'type_name' => '<create>',
'macro' => $content,
),
);
// form provided by content_copy.module
drupal_execute('content_copy_import_form', $form_state);
content_clear_type_cache();
}
/***********************************************************************************************
* Implemenation of hook_install();
*/
function provider_uninstall(){
//For hook_uninstall() you can simply do
node_type_delete('provider');
watchdog('provider_uninstall.');
}
in the provider.module file
<?php
/*****************************************************************************
* Implemenation of hook_init(); placeholder, doesn't do anything.
*/
function provider_init(){
}
file structure
module/provider/provider.install
module/provider/provider.module
module/provider/cck_types/apples.txt
where apples.txt is a CCK export of the GUI.
ie
$content['type'] = array (
'name' => 'Provider',
'type' => 'provider',
'description' => 'Provider Description',
'title_label' => 'Title',
'body_label' => 'Body',
'min_word_count' => '0',
'help' => '',
'node_options' =>
array (
'status' => true,
'promote' => true,
'sticky' => false,
'revision' => false,
),
'language_content_type' => '0',
'upload' => '1',
'old_type' => 'provider',
'orig_type' => '',
'module' => 'node',
'custom' => '1',
'modified' => '1',
'locked' => '0',
'signup_node_default_state' => 'disabled',
'content_profile_use' => false,
'fivestar' => 0,
'fivestar_stars' => 5,
'fivestar_labels_enable' => 1,
'fivestar_label_0' => 'Cancel rating',
'fivestar_label_1' => 'Poor',
'fivestar_label_2' => 'Okay',
'fivestar_label_3' => 'Good',
'fivestar_label_4' => 'Great',
'fivestar_label_5' => 'Awesome',
'fivestar_label_6' => 'Give it @star/@count',
'fivestar_label_7' => 'Give it @star/@count',
'fivestar_label_8' => 'Give it @star/@count',
'fivestar_label_9' => 'Give it @star/@count',
'fivestar_label_10' => 'Give it @star/@count',
'fivestar_style' => 'average',
'fivestar_text' => 'dual',
'fivestar_title' => 1,
'fivestar_feedback' => 1,
'fivestar_unvote' => 0,
'fivestar_position_teaser' => 'hidden',
'fivestar_position' => 'below',
'fivestar_comment' => 0,
'image_attach' => '0',
'image_attach_size_teaser' => 'thumbnail',
'image_attach_weight_teaser' => '0',
'image_attach_size_body' => 'thumbnail',
'image_attach_weight_body' => '0',
'comment' => '2',
'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',
'event_nodeapi' => 'never',
'location_addanother' => 0,
);
$content['fields'] = array (
0 =>
array (
'label' => 'Email',
'field_name' => 'field_email',
'type' => 'email',
'widget_type' => 'email_textfield',
'change' => 'Change basic information',
'weight' => '32',
'size' => '60',
'description' => '',
'default_value' =>
array (
0 =>
array (
'email' => '',
),
),
'default_value_php' => '',
'default_value_widget' => NULL,
'group' => false,
'required' => 0,
'multiple' => '0',
'op' => 'Save field settings',
'module' => 'email',
'widget_module' => 'email',
'columns' =>
array (
'email' =>
array (
'type' => 'varchar',
'length' => 255,
'not null' => false,
'sortable' => true,
),
),
'display_settings' =>
array (
'weight' => '32',
'parent' => '',
'label' =>
array (
'format' => 'inline',
),
'teaser' =>
array (
'format' => 'hidden',
'exclude' => 0,
),
'full' =>
array (
'format' => 'contact',
'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,
),
),
),
1 =>
array (
'label' => 'Website',
'field_name' => 'field_website',
'type' => 'link',
'widget_type' => 'link',
'change' => 'Change basic information',
'weight' => '33',
'description' => '',
'default_value' =>
array (
0 =>
array (
'title' => '',
'url' => '',
),
),
'default_value_php' => '',
'default_value_widget' =>
array (
'field_website' =>
array (
0 =>
array (
'title' => '',
'url' => '',
),
),
),
'group' => false,
'required' => 0,
'multiple' => '0',
'url' => 0,
'title' => 'none',
'title_value' => '',
'enable_tokens' => 0,
'display' =>
array (
'url_cutoff' => '80',
),
'attributes' =>
array (
'target' => 'default',
'rel' => '',
'class' => '',
),
'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 (
'weight' => '33',
'parent' => '',
'label' =>
array (
'format' => 'inline',
),
'teaser' =>
array (
'format' => 'hidden',
'exclude' => 0,
),
'full' =>
array (
'format' => 'url',
'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' => '0',
'menu' => '-2',
'attachments' => '30',
);
Enjoy.
cheers
Ed
extended to an module?
should this be extended in a cck add on module?
drush integration
ideally this should be part of drush.
ie.
drush [import cck type] [cck type file]
But I'm using it to create a "custom" module, while leveraging the freebies CCK gives me.
cheers
Ed