The Drupal Crud Checklist
If you are doing a custom module, there is a LOT to do just to add a content type (presuming you are not using CCK). Here's a checklist for creating a custom type. note terms in bold are generic functional placeholders for custom namespace tokens.
While there may be times when this is not a requirement, its assumed throughout that you have an nid and a vid field in your custom table. It's useful to use vid as the primary key.
This may seem like a load, but keep in mind these snippets are custom tooled to insert unique code within a larger system and as such, what might be whole files or classes in other systems are being replaced by relatively tiny functional blocks.
Create a schema
In the modue.install file create an install hook to load the content type
function module_install() {
drupal_install_schema('content_type');
}
... and the uninstall hook.
function module_uninstall() {
// Drop database tables.
drupal_uninstall_schema('content_type');
}
Create a hook to make your schema visible. note: I load mine from a YAML file so yours should look more like the stock system in the Drupal docs. note -- for drupal_get_path(), the FIRST 'module' is a LITERAL -- the word 'module' -- not the name of your module. the second module IS the name of your module.
function module_schema() {
$path = drupal_get_path('module', 'module') . '/schema.yml';
$schema = Drupal_YAML::load($path);
return $schema;
}The node schema file contains data on your desired table(s)' structure as in:
css_lead_lead:
description: A business lead
primary: vid
fields:
vid:
type: int
default: 0
not null: true
description: primary key for this table, foreign key for node
lead_uid:
type: int
default: 0
not null: true
description: the lead's user id if they are a user -- rarely true but here it is.
account_vid:
type: int
default: 0
not null: true
description: the account FK that the lead belongs to.
first_name:
type: string
length: 40
default: ''
not null: true
description: a contact's first name.
last_name:
type: string
length: 40
default: ''
not null: true
description: a contact's last name.... and so on. Multiple tables can be put in a single YAML file. Schema tables don't have to be nodes; non node tables should have their own id of type serial.
Create an info hook
the module_node_info() hook puts your content type in the standard content creation api.
function module_node_info() {
return array(
'content_type' => array(
'name' => t('Content Title'),
'module' => 'module',
'description' => t('A content type'),
'has_title' => TRUE,
'title_label' => t('Name'),
'has_body' => TRUE,
'body_label' => t('Description')
),
);
}
Create a form for the content type. Note that the specifics for the title and body fields will transport from module_node_info() above.
function content_type_form(&$node){
$form = array();
$weight = -10;
$type = node_get_types('type', $node);
if ($type->has_title) {
$form['title'] = array(
'#type' => 'textfield',
'#title' => check_plain($type->title_label),
'#required' => TRUE,
'#default_value' => $node->title,
'#weight' => $weight++
);
}
if ($type->has_body) {
$bf = node_body_field(
$node,
$type->body_label,
$type->min_word_count);
$bf['#weight'] = $weight++;
$bf['body']['#rows'] = 5;
$bf['teaser_js']['#rows'] = 2;
$form['body_field'] = $bf;
};
/**
* add any other custom fields here
*/
return $form;
}Add crud hooks for insert
You'll need to handle the insertion and updating of custom fields in a specific pair of handlers. note that _content_type_set_defaults (below) sanitizes the node, ensuring that all neeed properties have been set.
function content_type_insert($node) {
_content_type_set_defaults(&$node);
$query = <<<QUERY
INSERT INTO {custom_table} (
`custom_field_1` ,
...
`custom_field_N`
)
VALUES (
'%s',
...
'%d'
);
QUERY;
db_query($query,
$node->custom_field_1 ,
...
$node->custom_field_N
);
}
Add an update hook
Similar to the above, only for revising existing records.
function content_type_update($node) {
if ($node->revision) {
return content_type_insert($node);
}
_content_type_set_defaults(&$node);
$query = <<<QUERY
UPDATE {custom_table}
SET
`field_1` = '%s'
...
`field_n` = '%s'
WHERE
{custom_table}.`vid` = %d;
QUERY;
db_query($query,
$node->custom_field_1,
$node->empathy,
$node->vid
);
}
function _content_type_defaults(&$node){
if (!property_exists($node, 'custom_field_1')){
$node->custom_field_1 = 'default';
}
...
}
Add a delete hook
the delete button will delete the records in Drupal's node tables but you'll need to delete your custom record on your own. If there are subrecords that relate to this record they can be addressed here too. Note - by deleting the node ID related rows you delete ALL revisions.
function content_type_delete($node) {
$query = <<<QUERY
DELETE FROM {custom_table} WHERE nid = %d
QUERY;
db_query($query, $node->nid);
}
Add a load hook
This will pull all your custom tables' fields into a node stdClass object. Note: the expected return is a stdClass.
function content_type_load($node){
$query = <<<QUERY
SELECT
custom_field_1,
...
custom_field_N
FROM
{custom_table}
WHERE
vid = %d
QUERY;
$result = db_query($query, $node->vid);
$out = db_fetch_object($result);
return $out;
}
Enable node theming with a view hook
Your view field should bind in any custom theming for your object. NOTE: if you pass the teaser flag to your theme, you can use the same theme file for the teaser and full view of the node.
function content_type_view($node, $teaser = FALSE, $page) {
$node = node_prepare($node, $teaser);
$field_1 = $node->field_1;
... $field_n = $node->field_N;
$node->content['content_type_info'] = array(
'#value' => theme('content_type_info',
$teaser,
$field_1 ,
...
$field_n
),
'#weight' => 1
);
return $node;
}
Add a bridge to the theme, note that the key, content_type_info, should be the same for both the view and the theme, and should match the file 'content_type_info.tpl.php' in your module root.
function module_theme() {
return array(
'content_type_info' => array(
'template' => 'content_type_info',
'arguments' => array(
'teaser' => FALSE,
'field_1' => '',
'field_N' =>''
)
)
);
}
this should be executed in a template file called content_type_info.tpl.php
<div class="content_type_info"> <? if (!$teaser): ?> <dl> <dt>Field One</dt> <dd><?= $field_1 ?></dd> ... </dl> <? endif; ?> </div>
Note that the HTML style here used here is just an example -- you can use any HTML arrangement you want, and you're not obligated to expose all the variables.


Post new comment