node_example.module

  1. examples
    1. 6 node_example/node_example.module
    2. 7 node_example/node_example.module
    3. 8 node_example/node_example.module
  2. drupal
    1. 4.6 developer/examples/node_example.module
    2. 4.7 developer/examples/node_example.module
    3. 5 developer/examples/node_example.module

This is an example outlining how a module can be used to define a new node type.

Our example node type will allow users to specify a "color" and a "quantity" for their nodes; some kind of rudimentary inventory-tracking system, perhaps? To store this extra information, we need an auxiliary database table.

Database definition:

  CREATE TABLE node_example (
    vid int(10) unsigned NOT NULL default '0',
    nid int(10) unsigned NOT NULL default '0',
    color varchar(255) NOT NULL default '',
    quantity int(10) unsigned NOT NULL default '0',
    PRIMARY KEY (vid, nid),
    KEY `node_example_nid` (nid)
  )

Functions & methods

NameDescription
node_example_accessImplementation of hook_access().
node_example_deleteImplementation of hook_delete().
node_example_formImplementation of hook_form().
node_example_insertImplementation of hook_insert().
node_example_loadImplementation of hook_load().
node_example_nodeapiImplementation of hook_nodeapi().
node_example_node_infoImplementation of hook_node_info(). This function replaces hook_node_name() and hook_node_types() from 4.6. Drupal 5 expands this hook significantly.
node_example_permImplementation of hook_perm().
node_example_updateImplementation of hook_update().
node_example_validateImplementation of hook_validate().
node_example_viewImplementation of hook_view().
theme_node_example_order_infoA custom theme function.

File

developer/examples/node_example.module
View source
  1. /**
  2. * @file
  3. * This is an example outlining how a module can be used to define a new
  4. * node type.
  5. *
  6. * Our example node type will allow users to specify a "color" and a "quantity"
  7. * for their nodes; some kind of rudimentary inventory-tracking system, perhaps?
  8. * To store this extra information, we need an auxiliary database table.
  9. *
  10. * Database definition:
  11. * @code
  12. * CREATE TABLE node_example (
  13. * vid int(10) unsigned NOT NULL default '0',
  14. * nid int(10) unsigned NOT NULL default '0',
  15. * color varchar(255) NOT NULL default '',
  16. * quantity int(10) unsigned NOT NULL default '0',
  17. * PRIMARY KEY (vid, nid),
  18. * KEY `node_example_nid` (nid)
  19. * )
  20. * @endcode
  21. */
  22. /**
  23. * Implementation of hook_node_info(). This function replaces hook_node_name()
  24. * and hook_node_types() from 4.6. Drupal 5 expands this hook significantly.
  25. *
  26. * This is a required node hook. This function describes the nodes provided by
  27. * this module.
  28. *
  29. * The "name" value provide a human readable name for the node,
  30. * while the "module" value tells Drupal how the module's functions map to hooks
  31. * (i.e. if the module is node_example_foo then node_example_foo_insert will be
  32. * called when inserting the node). The "description" value provides a brief
  33. * description of the node type, which will show up when a user accesses the
  34. * "create content" page for that node type. Other attributes can also be
  35. * defined through this hook, but only these ones are required.
  36. */
  37. function node_example_node_info() {
  38. return array(
  39. 'node_example' => array(
  40. 'name' => t('example node'),
  41. 'module' => 'node_example',
  42. 'description' => t("This is an example node type with a few fields."),
  43. )
  44. );
  45. }
  46. /**
  47. * Implementation of hook_access().
  48. *
  49. * Node modules may implement node_access() to determine the operations
  50. * users may perform on nodes. This example uses a very common access pattern.
  51. */
  52. function node_example_access($op, $node) {
  53. global $user;
  54. if ($op == 'create') {
  55. // Only users with permission to do so may create this node type.
  56. return user_access('create example node');
  57. }
  58. // Users who create a node may edit or delete it later, assuming they have the
  59. // necessary permissions.
  60. if ($op == 'update' || $op == 'delete') {
  61. if (user_access('edit own example nodes') && ($user->uid == $node->uid)) {
  62. return TRUE;
  63. }
  64. }
  65. }
  66. /**
  67. * Implementation of hook_perm().
  68. *
  69. * Since we are limiting the ability to create new nodes to certain users,
  70. * we need to define what those permissions are here. We also define a permission
  71. * to allow users to edit the nodes they created.
  72. */
  73. function node_example_perm() {
  74. return array('create example node', 'edit own example nodes');
  75. }
  76. /**
  77. * Implementation of hook_form().
  78. *
  79. * Now it's time to describe the form for collecting the information
  80. * specific to this node type. This hook requires us to return an array with
  81. * a sub array containing information for each element in the form.
  82. */
  83. function node_example_form(&$node) {
  84. $type = node_get_types('type', $node);
  85. // We need to define form elements for the node's title and body.
  86. $form['title'] = array(
  87. '#type' => 'textfield',
  88. '#title' => check_plain($type->title_label),
  89. '#required' => TRUE,
  90. '#default_value' => $node->title,
  91. '#weight' => -5
  92. );
  93. // We want the body and filter elements to be adjacent. We could try doing
  94. // this by setting their weights, but another module might add elements to the
  95. // form with the same weights and end up between ours. By putting them into a
  96. // sub-array together, we're able force them to be rendered together.
  97. $form['body_filter']['body'] = array(
  98. '#type' => 'textarea',
  99. '#title' => check_plain($type->body_label),
  100. '#default_value' => $node->body,
  101. '#required' => FALSE
  102. );
  103. $form['body_filter']['filter'] = filter_form($node->format);
  104. // Now we define the form elements specific to our node type.
  105. $form['color'] = array(
  106. '#type' => 'textfield',
  107. '#title' => t('Color'),
  108. '#default_value' => $node->color
  109. );
  110. $form['quantity'] = array(
  111. '#type' => 'textfield',
  112. '#title' => t('Quantity'),
  113. '#default_value' => $node->quantity,
  114. '#size' => 10,
  115. '#maxlength' => 10
  116. );
  117. return $form;
  118. }
  119. /**
  120. * Implementation of hook_validate().
  121. *
  122. * Our "quantity" field requires a number to be entered. This hook lets
  123. * us ensure that the user entered an appropriate value before we try
  124. * inserting anything into the database.
  125. *
  126. * Errors should be signaled with form_set_error().
  127. */
  128. function node_example_validate(&$node) {
  129. if ($node->quantity) {
  130. if (!is_numeric($node->quantity)) {
  131. form_set_error('quantity', t('The quantity must be a number.'));
  132. }
  133. }
  134. else {
  135. // Let an empty field mean "zero."
  136. $node->quantity = 0;
  137. }
  138. }
  139. /**
  140. * Implementation of hook_insert().
  141. *
  142. * As a new node is being inserted into the database, we need to do our own
  143. * database inserts.
  144. */
  145. function node_example_insert($node) {
  146. db_query("INSERT INTO {node_example} (vid, nid, color, quantity) VALUES (%d, %d, '%s', %d)", $node->vid, $node->nid, $node->color, $node->quantity);
  147. }
  148. /**
  149. * Implementation of hook_update().
  150. *
  151. * As an existing node is being updated in the database, we need to do our own
  152. * database updates.
  153. */
  154. function node_example_update($node) {
  155. // if this is a new node or we're adding a new revision,
  156. if ($node->revision) {
  157. node_example_insert($node);
  158. }
  159. else {
  160. db_query("UPDATE {node_example} SET color = '%s', quantity = %d WHERE vid = %d", $node->color, $node->quantity, $node->vid);
  161. }
  162. }
  163. /**
  164. * Implementation of hook_nodeapi().
  165. *
  166. * When a node revision is deleted, we need to remove the corresponding record
  167. * from our table. The only way to handle revision deletion is by implementing
  168. * hook_nodeapi().
  169. */
  170. function node_example_nodeapi(&$node, $op, $teaser, $page) {
  171. switch ($op) {
  172. case 'delete revision':
  173. // Notice that we're matching a single revision based on the node's vid.
  174. db_query('DELETE FROM {node_example} WHERE vid = %d', $node->vid);
  175. break;
  176. }
  177. }
  178. /**
  179. * Implementation of hook_delete().
  180. *
  181. * When a node is deleted, we need to remove all related records from out table.
  182. */
  183. function node_example_delete($node) {
  184. // Notice that we're matching all revision, by using the node's nid.
  185. db_query('DELETE FROM {node_example} WHERE nid = %d', $node->nid);
  186. }
  187. /**
  188. * Implementation of hook_load().
  189. *
  190. * Now that we've defined how to manage the node data in the database, we
  191. * need to tell Drupal how to get the node back out. This hook is called
  192. * every time a node is loaded, and allows us to do some loading of our own.
  193. */
  194. function node_example_load($node) {
  195. $additions = db_fetch_object(db_query('SELECT color, quantity FROM {node_example} WHERE vid = %d', $node->vid));
  196. return $additions;
  197. }
  198. /**
  199. * Implementation of hook_view().
  200. *
  201. * This is a typical implementation that simply runs the node text through
  202. * the output filters.
  203. */
  204. function node_example_view($node, $teaser = FALSE, $page = FALSE) {
  205. $node = node_prepare($node, $teaser);
  206. $node->content['myfield'] = array(
  207. '#value' => theme('node_example_order_info', $node),
  208. '#weight' => 1,
  209. );
  210. return $node;
  211. }
  212. /**
  213. * A custom theme function.
  214. *
  215. * By using this function to format our node-specific information, themes
  216. * can override this presentation if they wish. We also wrap the default
  217. * presentation in a CSS class that is prefixed by the module name. This
  218. * way, style sheets can modify the output without requiring theme code.
  219. */
  220. function theme_node_example_order_info($node) {
  221. $output = '<div class="node_example_order_info">';
  222. $output .= t('The order is for %quantity %color items.', array('%quantity' => check_plain($node->quantity), '%color' => check_plain($node->color)));
  223. $output .= '</div>';
  224. return $output;
  225. }
Login or register to post comments