|
1 <?php |
|
2 |
|
3 /** |
|
4 * @file |
|
5 * Hooks provided by the Node module. |
|
6 */ |
|
7 |
|
8 /** |
|
9 * @defgroup node_api_hooks Node API Hooks |
|
10 * @{ |
|
11 * Functions to define and modify content types. |
|
12 * |
|
13 * Each content type is maintained by a primary module, which is either |
|
14 * node.module (for content types created in the user interface) or the module |
|
15 * that implements hook_node_info() to define the content type. |
|
16 * |
|
17 * During node operations (create, update, view, delete, etc.), there are |
|
18 * several sets of hooks that get invoked to allow modules to modify the base |
|
19 * node operation: |
|
20 * - Node-type-specific hooks: When defining a node type, hook_node_info() |
|
21 * returns a 'base' component. Node-type-specific hooks are named |
|
22 * base_hookname() instead of mymodule_hookname() (in a module called |
|
23 * 'mymodule' for example). Only the node type's corresponding implementation |
|
24 * is invoked. For example, poll_node_info() in poll.module defines the base |
|
25 * for the 'poll' node type as 'poll'. So when a poll node is created, |
|
26 * hook_insert() is invoked on poll_insert() only. |
|
27 * Hooks that are node-type-specific are noted below. |
|
28 * - All-module hooks: This set of hooks is invoked on all implementing modules, |
|
29 * to allow other modules to modify what the primary node module is doing. For |
|
30 * example, hook_node_insert() is invoked on all modules when creating a poll |
|
31 * node. |
|
32 * - Field hooks: Hooks related to the fields attached to the node. These are |
|
33 * invoked from the field operations functions described below, and can be |
|
34 * either field-type-specific or all-module hooks. |
|
35 * - Entity hooks: Generic hooks for "entity" operations. These are always |
|
36 * invoked on all modules. |
|
37 * |
|
38 * Here is a list of the node and entity hooks that are invoked, field |
|
39 * operations, and other steps that take place during node operations: |
|
40 * - Creating a new node (calling node_save() on a new node): |
|
41 * - field_attach_presave() |
|
42 * - hook_node_presave() (all) |
|
43 * - hook_entity_presave() (all) |
|
44 * - Node and revision records are written to the database |
|
45 * - hook_insert() (node-type-specific) |
|
46 * - field_attach_insert() |
|
47 * - hook_node_insert() (all) |
|
48 * - hook_entity_insert() (all) |
|
49 * - hook_node_access_records() (all) |
|
50 * - hook_node_access_records_alter() (all) |
|
51 * - Updating an existing node (calling node_save() on an existing node): |
|
52 * - field_attach_presave() |
|
53 * - hook_node_presave() (all) |
|
54 * - hook_entity_presave() (all) |
|
55 * - Node and revision records are written to the database |
|
56 * - hook_update() (node-type-specific) |
|
57 * - field_attach_update() |
|
58 * - hook_node_update() (all) |
|
59 * - hook_entity_update() (all) |
|
60 * - hook_node_access_records() (all) |
|
61 * - hook_node_access_records_alter() (all) |
|
62 * - Loading a node (calling node_load(), node_load_multiple() or entity_load() |
|
63 * with $entity_type of 'node'): |
|
64 * - Node and revision information is read from database. |
|
65 * - hook_load() (node-type-specific) |
|
66 * - field_attach_load_revision() and field_attach_load() |
|
67 * - hook_entity_load() (all) |
|
68 * - hook_node_load() (all) |
|
69 * - Viewing a single node (calling node_view() - note that the input to |
|
70 * node_view() is a loaded node, so the Loading steps above are already done): |
|
71 * - hook_view() (node-type-specific) |
|
72 * - field_attach_prepare_view() |
|
73 * - hook_entity_prepare_view() (all) |
|
74 * - field_attach_view() |
|
75 * - hook_node_view() (all) |
|
76 * - hook_entity_view() (all) |
|
77 * - hook_node_view_alter() (all) |
|
78 * - hook_entity_view_alter() (all) |
|
79 * - Viewing multiple nodes (calling node_view_multiple() - note that the input |
|
80 * to node_view_multiple() is a set of loaded nodes, so the Loading steps |
|
81 * above are already done): |
|
82 * - field_attach_prepare_view() |
|
83 * - hook_entity_prepare_view() (all) |
|
84 * - hook_view() (node-type-specific) |
|
85 * - field_attach_view() |
|
86 * - hook_node_view() (all) |
|
87 * - hook_entity_view() (all) |
|
88 * - hook_node_view_alter() (all) |
|
89 * - hook_entity_view_alter() (all) |
|
90 * - Deleting a node (calling node_delete() or node_delete_multiple()): |
|
91 * - Node is loaded (see Loading section above) |
|
92 * - hook_delete() (node-type-specific) |
|
93 * - hook_node_delete() (all) |
|
94 * - hook_entity_delete() (all) |
|
95 * - field_attach_delete() |
|
96 * - Node and revision information are deleted from database |
|
97 * - Deleting a node revision (calling node_revision_delete()): |
|
98 * - Node is loaded (see Loading section above) |
|
99 * - Revision information is deleted from database |
|
100 * - hook_node_revision_delete() (all) |
|
101 * - field_attach_delete_revision() |
|
102 * - Preparing a node for editing (calling node_form() - note that if it is an |
|
103 * existing node, it will already be loaded; see the Loading section above): |
|
104 * - hook_prepare() (node-type-specific) |
|
105 * - hook_node_prepare() (all) |
|
106 * - hook_form() (node-type-specific) |
|
107 * - field_attach_form() |
|
108 * - Validating a node during editing form submit (calling |
|
109 * node_form_validate()): |
|
110 * - hook_validate() (node-type-specific) |
|
111 * - hook_node_validate() (all) |
|
112 * - field_attach_form_validate() |
|
113 * - Searching (calling node_search_execute()): |
|
114 * - hook_ranking() (all) |
|
115 * - Query is executed to find matching nodes |
|
116 * - Resulting node is loaded (see Loading section above) |
|
117 * - Resulting node is prepared for viewing (see Viewing a single node above) |
|
118 * - comment_node_update_index() is called. |
|
119 * - hook_node_search_result() (all) |
|
120 * - Search indexing (calling node_update_index()): |
|
121 * - Node is loaded (see Loading section above) |
|
122 * - Node is prepared for viewing (see Viewing a single node above) |
|
123 * - hook_node_update_index() (all) |
|
124 * @} |
|
125 */ |
|
126 |
|
127 /** |
|
128 * @addtogroup hooks |
|
129 * @{ |
|
130 */ |
|
131 |
|
132 /** |
|
133 * Inform the node access system what permissions the user has. |
|
134 * |
|
135 * This hook is for implementation by node access modules. In this hook, |
|
136 * the module grants a user different "grant IDs" within one or more |
|
137 * "realms". In hook_node_access_records(), the realms and grant IDs are |
|
138 * associated with permission to view, edit, and delete individual nodes. |
|
139 * |
|
140 * The realms and grant IDs can be arbitrarily defined by your node access |
|
141 * module; it is common to use role IDs as grant IDs, but that is not required. |
|
142 * Your module could instead maintain its own list of users, where each list has |
|
143 * an ID. In that case, the return value of this hook would be an array of the |
|
144 * list IDs that this user is a member of. |
|
145 * |
|
146 * A node access module may implement as many realms as necessary to properly |
|
147 * define the access privileges for the nodes. Note that the system makes no |
|
148 * distinction between published and unpublished nodes. It is the module's |
|
149 * responsibility to provide appropriate realms to limit access to unpublished |
|
150 * content. |
|
151 * |
|
152 * Node access records are stored in the {node_access} table and define which |
|
153 * grants are required to access a node. There is a special case for the view |
|
154 * operation -- a record with node ID 0 corresponds to a "view all" grant for |
|
155 * the realm and grant ID of that record. If there are no node access modules |
|
156 * enabled, the core node module adds a node ID 0 record for realm 'all'. Node |
|
157 * access modules can also grant "view all" permission on their custom realms; |
|
158 * for example, a module could create a record in {node_access} with: |
|
159 * @code |
|
160 * $record = array( |
|
161 * 'nid' => 0, |
|
162 * 'gid' => 888, |
|
163 * 'realm' => 'example_realm', |
|
164 * 'grant_view' => 1, |
|
165 * 'grant_update' => 0, |
|
166 * 'grant_delete' => 0, |
|
167 * ); |
|
168 * drupal_write_record('node_access', $record); |
|
169 * @endcode |
|
170 * And then in its hook_node_grants() implementation, it would need to return: |
|
171 * @code |
|
172 * if ($op == 'view') { |
|
173 * $grants['example_realm'] = array(888); |
|
174 * } |
|
175 * @endcode |
|
176 * If you decide to do this, be aware that the node_access_rebuild() function |
|
177 * will erase any node ID 0 entry when it is called, so you will need to make |
|
178 * sure to restore your {node_access} record after node_access_rebuild() is |
|
179 * called. |
|
180 * |
|
181 * @see node_access_view_all_nodes() |
|
182 * @see node_access_rebuild() |
|
183 * |
|
184 * @param $account |
|
185 * The user object whose grants are requested. |
|
186 * @param $op |
|
187 * The node operation to be performed, such as 'view', 'update', or 'delete'. |
|
188 * |
|
189 * @return |
|
190 * An array whose keys are "realms" of grants, and whose values are arrays of |
|
191 * the grant IDs within this realm that this user is being granted. |
|
192 * |
|
193 * For a detailed example, see node_access_example.module. |
|
194 * |
|
195 * @ingroup node_access |
|
196 */ |
|
197 function hook_node_grants($account, $op) { |
|
198 if (user_access('access private content', $account)) { |
|
199 $grants['example'] = array(1); |
|
200 } |
|
201 $grants['example_author'] = array($account->uid); |
|
202 return $grants; |
|
203 } |
|
204 |
|
205 /** |
|
206 * Set permissions for a node to be written to the database. |
|
207 * |
|
208 * When a node is saved, a module implementing hook_node_access_records() will |
|
209 * be asked if it is interested in the access permissions for a node. If it is |
|
210 * interested, it must respond with an array of permissions arrays for that |
|
211 * node. |
|
212 * |
|
213 * Node access grants apply regardless of the published or unpublished status |
|
214 * of the node. Implementations must make sure not to grant access to |
|
215 * unpublished nodes if they don't want to change the standard access control |
|
216 * behavior. Your module may need to create a separate access realm to handle |
|
217 * access to unpublished nodes. |
|
218 * |
|
219 * Note that the grant values in the return value from your hook must be |
|
220 * integers and not boolean TRUE and FALSE. |
|
221 * |
|
222 * Each permissions item in the array is an array with the following elements: |
|
223 * - 'realm': The name of a realm that the module has defined in |
|
224 * hook_node_grants(). |
|
225 * - 'gid': A 'grant ID' from hook_node_grants(). |
|
226 * - 'grant_view': If set to 1 a user that has been identified as a member |
|
227 * of this gid within this realm can view this node. This should usually be |
|
228 * set to $node->status. Failure to do so may expose unpublished content |
|
229 * to some users. |
|
230 * - 'grant_update': If set to 1 a user that has been identified as a member |
|
231 * of this gid within this realm can edit this node. |
|
232 * - 'grant_delete': If set to 1 a user that has been identified as a member |
|
233 * of this gid within this realm can delete this node. |
|
234 * - 'priority': If multiple modules seek to set permissions on a node, the |
|
235 * realms that have the highest priority will win out, and realms with a lower |
|
236 * priority will not be written. If there is any doubt, it is best to |
|
237 * leave this 0. |
|
238 * |
|
239 * |
|
240 * When an implementation is interested in a node but want to deny access to |
|
241 * everyone, it may return a "deny all" grant: |
|
242 * |
|
243 * @code |
|
244 * $grants[] = array( |
|
245 * 'realm' => 'all', |
|
246 * 'gid' => 0, |
|
247 * 'grant_view' => 0, |
|
248 * 'grant_update' => 0, |
|
249 * 'grant_delete' => 0, |
|
250 * 'priority' => 1, |
|
251 * ); |
|
252 * @endcode |
|
253 * |
|
254 * Setting the priority should cancel out other grants. In the case of a |
|
255 * conflict between modules, it is safer to use hook_node_access_records_alter() |
|
256 * to return only the deny grant. |
|
257 * |
|
258 * Note: a deny all grant is not written to the database; denies are implicit. |
|
259 * |
|
260 * @see node_access_write_grants() |
|
261 * |
|
262 * @param $node |
|
263 * The node that has just been saved. |
|
264 * |
|
265 * @return |
|
266 * An array of grants as defined above. |
|
267 * |
|
268 * @see hook_node_access_records_alter() |
|
269 * @ingroup node_access |
|
270 */ |
|
271 function hook_node_access_records($node) { |
|
272 // We only care about the node if it has been marked private. If not, it is |
|
273 // treated just like any other node and we completely ignore it. |
|
274 if ($node->private) { |
|
275 $grants = array(); |
|
276 // Only published nodes should be viewable to all users. If we allow access |
|
277 // blindly here, then all users could view an unpublished node. |
|
278 if ($node->status) { |
|
279 $grants[] = array( |
|
280 'realm' => 'example', |
|
281 'gid' => 1, |
|
282 'grant_view' => 1, |
|
283 'grant_update' => 0, |
|
284 'grant_delete' => 0, |
|
285 'priority' => 0, |
|
286 ); |
|
287 } |
|
288 // For the example_author array, the GID is equivalent to a UID, which |
|
289 // means there are many groups of just 1 user. |
|
290 // Note that an author can always view his or her nodes, even if they |
|
291 // have status unpublished. |
|
292 $grants[] = array( |
|
293 'realm' => 'example_author', |
|
294 'gid' => $node->uid, |
|
295 'grant_view' => 1, |
|
296 'grant_update' => 1, |
|
297 'grant_delete' => 1, |
|
298 'priority' => 0, |
|
299 ); |
|
300 |
|
301 return $grants; |
|
302 } |
|
303 } |
|
304 |
|
305 /** |
|
306 * Alter permissions for a node before it is written to the database. |
|
307 * |
|
308 * Node access modules establish rules for user access to content. Node access |
|
309 * records are stored in the {node_access} table and define which permissions |
|
310 * are required to access a node. This hook is invoked after node access modules |
|
311 * returned their requirements via hook_node_access_records(); doing so allows |
|
312 * modules to modify the $grants array by reference before it is stored, so |
|
313 * custom or advanced business logic can be applied. |
|
314 * |
|
315 * @see hook_node_access_records() |
|
316 * |
|
317 * Upon viewing, editing or deleting a node, hook_node_grants() builds a |
|
318 * permissions array that is compared against the stored access records. The |
|
319 * user must have one or more matching permissions in order to complete the |
|
320 * requested operation. |
|
321 * |
|
322 * A module may deny all access to a node by setting $grants to an empty array. |
|
323 * |
|
324 * @see hook_node_grants() |
|
325 * @see hook_node_grants_alter() |
|
326 * |
|
327 * @param $grants |
|
328 * The $grants array returned by hook_node_access_records(). |
|
329 * @param $node |
|
330 * The node for which the grants were acquired. |
|
331 * |
|
332 * The preferred use of this hook is in a module that bridges multiple node |
|
333 * access modules with a configurable behavior, as shown in the example with the |
|
334 * 'is_preview' field. |
|
335 * |
|
336 * @ingroup node_access |
|
337 */ |
|
338 function hook_node_access_records_alter(&$grants, $node) { |
|
339 // Our module allows editors to mark specific articles with the 'is_preview' |
|
340 // field. If the node being saved has a TRUE value for that field, then only |
|
341 // our grants are retained, and other grants are removed. Doing so ensures |
|
342 // that our rules are enforced no matter what priority other grants are given. |
|
343 if ($node->is_preview) { |
|
344 // Our module grants are set in $grants['example']. |
|
345 $temp = $grants['example']; |
|
346 // Now remove all module grants but our own. |
|
347 $grants = array('example' => $temp); |
|
348 } |
|
349 } |
|
350 |
|
351 /** |
|
352 * Alter user access rules when trying to view, edit or delete a node. |
|
353 * |
|
354 * Node access modules establish rules for user access to content. |
|
355 * hook_node_grants() defines permissions for a user to view, edit or delete |
|
356 * nodes by building a $grants array that indicates the permissions assigned to |
|
357 * the user by each node access module. This hook is called to allow modules to |
|
358 * modify the $grants array by reference, so the interaction of multiple node |
|
359 * access modules can be altered or advanced business logic can be applied. |
|
360 * |
|
361 * @see hook_node_grants() |
|
362 * |
|
363 * The resulting grants are then checked against the records stored in the |
|
364 * {node_access} table to determine if the operation may be completed. |
|
365 * |
|
366 * A module may deny all access to a user by setting $grants to an empty array. |
|
367 * |
|
368 * @see hook_node_access_records() |
|
369 * @see hook_node_access_records_alter() |
|
370 * |
|
371 * @param $grants |
|
372 * The $grants array returned by hook_node_grants(). |
|
373 * @param $account |
|
374 * The user account requesting access to content. |
|
375 * @param $op |
|
376 * The operation being performed, 'view', 'update' or 'delete'. |
|
377 * |
|
378 * Developers may use this hook to either add additional grants to a user or to |
|
379 * remove existing grants. These rules are typically based on either the |
|
380 * permissions assigned to a user role, or specific attributes of a user |
|
381 * account. |
|
382 * |
|
383 * @ingroup node_access |
|
384 */ |
|
385 function hook_node_grants_alter(&$grants, $account, $op) { |
|
386 // Our sample module never allows certain roles to edit or delete |
|
387 // content. Since some other node access modules might allow this |
|
388 // permission, we expressly remove it by returning an empty $grants |
|
389 // array for roles specified in our variable setting. |
|
390 |
|
391 // Get our list of banned roles. |
|
392 $restricted = variable_get('example_restricted_roles', array()); |
|
393 |
|
394 if ($op != 'view' && !empty($restricted)) { |
|
395 // Now check the roles for this account against the restrictions. |
|
396 foreach ($restricted as $role_id) { |
|
397 if (isset($account->roles[$role_id])) { |
|
398 $grants = array(); |
|
399 } |
|
400 } |
|
401 } |
|
402 } |
|
403 |
|
404 /** |
|
405 * Add mass node operations. |
|
406 * |
|
407 * This hook enables modules to inject custom operations into the mass |
|
408 * operations dropdown found at admin/content, by associating a callback |
|
409 * function with the operation, which is called when the form is submitted. The |
|
410 * callback function receives one initial argument, which is an array of the |
|
411 * checked nodes. |
|
412 * |
|
413 * @return |
|
414 * An array of operations. Each operation is an associative array that may |
|
415 * contain the following key-value pairs: |
|
416 * - label: (required) The label for the operation, displayed in the dropdown |
|
417 * menu. |
|
418 * - callback: (required) The function to call for the operation. |
|
419 * - callback arguments: (optional) An array of additional arguments to pass |
|
420 * to the callback function. |
|
421 */ |
|
422 function hook_node_operations() { |
|
423 $operations = array( |
|
424 'publish' => array( |
|
425 'label' => t('Publish selected content'), |
|
426 'callback' => 'node_mass_update', |
|
427 'callback arguments' => array('updates' => array('status' => NODE_PUBLISHED)), |
|
428 ), |
|
429 'unpublish' => array( |
|
430 'label' => t('Unpublish selected content'), |
|
431 'callback' => 'node_mass_update', |
|
432 'callback arguments' => array('updates' => array('status' => NODE_NOT_PUBLISHED)), |
|
433 ), |
|
434 'promote' => array( |
|
435 'label' => t('Promote selected content to front page'), |
|
436 'callback' => 'node_mass_update', |
|
437 'callback arguments' => array('updates' => array('status' => NODE_PUBLISHED, 'promote' => NODE_PROMOTED)), |
|
438 ), |
|
439 'demote' => array( |
|
440 'label' => t('Demote selected content from front page'), |
|
441 'callback' => 'node_mass_update', |
|
442 'callback arguments' => array('updates' => array('promote' => NODE_NOT_PROMOTED)), |
|
443 ), |
|
444 'sticky' => array( |
|
445 'label' => t('Make selected content sticky'), |
|
446 'callback' => 'node_mass_update', |
|
447 'callback arguments' => array('updates' => array('status' => NODE_PUBLISHED, 'sticky' => NODE_STICKY)), |
|
448 ), |
|
449 'unsticky' => array( |
|
450 'label' => t('Make selected content not sticky'), |
|
451 'callback' => 'node_mass_update', |
|
452 'callback arguments' => array('updates' => array('sticky' => NODE_NOT_STICKY)), |
|
453 ), |
|
454 'delete' => array( |
|
455 'label' => t('Delete selected content'), |
|
456 'callback' => NULL, |
|
457 ), |
|
458 ); |
|
459 return $operations; |
|
460 } |
|
461 |
|
462 /** |
|
463 * Respond to node deletion. |
|
464 * |
|
465 * This hook is invoked from node_delete_multiple() after the type-specific |
|
466 * hook_delete() has been invoked, but before hook_entity_delete and |
|
467 * field_attach_delete() are called, and before the node is removed from the |
|
468 * node table in the database. |
|
469 * |
|
470 * @param $node |
|
471 * The node that is being deleted. |
|
472 * |
|
473 * @ingroup node_api_hooks |
|
474 */ |
|
475 function hook_node_delete($node) { |
|
476 db_delete('mytable') |
|
477 ->condition('nid', $node->nid) |
|
478 ->execute(); |
|
479 } |
|
480 |
|
481 /** |
|
482 * Respond to deletion of a node revision. |
|
483 * |
|
484 * This hook is invoked from node_revision_delete() after the revision has been |
|
485 * removed from the node_revision table, and before |
|
486 * field_attach_delete_revision() is called. |
|
487 * |
|
488 * @param $node |
|
489 * The node revision (node object) that is being deleted. |
|
490 * |
|
491 * @ingroup node_api_hooks |
|
492 */ |
|
493 function hook_node_revision_delete($node) { |
|
494 db_delete('mytable') |
|
495 ->condition('vid', $node->vid) |
|
496 ->execute(); |
|
497 } |
|
498 |
|
499 /** |
|
500 * Respond to creation of a new node. |
|
501 * |
|
502 * This hook is invoked from node_save() after the database query that will |
|
503 * insert the node into the node table is scheduled for execution, after the |
|
504 * type-specific hook_insert() is invoked, and after field_attach_insert() is |
|
505 * called. |
|
506 * |
|
507 * Note that when this hook is invoked, the changes have not yet been written to |
|
508 * the database, because a database transaction is still in progress. The |
|
509 * transaction is not finalized until the save operation is entirely completed |
|
510 * and node_save() goes out of scope. You should not rely on data in the |
|
511 * database at this time as it is not updated yet. You should also note that any |
|
512 * write/update database queries executed from this hook are also not committed |
|
513 * immediately. Check node_save() and db_transaction() for more info. |
|
514 * |
|
515 * @param $node |
|
516 * The node that is being created. |
|
517 * |
|
518 * @ingroup node_api_hooks |
|
519 */ |
|
520 function hook_node_insert($node) { |
|
521 db_insert('mytable') |
|
522 ->fields(array( |
|
523 'nid' => $node->nid, |
|
524 'extra' => $node->extra, |
|
525 )) |
|
526 ->execute(); |
|
527 } |
|
528 |
|
529 /** |
|
530 * Act on arbitrary nodes being loaded from the database. |
|
531 * |
|
532 * This hook should be used to add information that is not in the node or node |
|
533 * revisions table, not to replace information that is in these tables (which |
|
534 * could interfere with the entity cache). For performance reasons, information |
|
535 * for all available nodes should be loaded in a single query where possible. |
|
536 * |
|
537 * This hook is invoked during node loading, which is handled by entity_load(), |
|
538 * via classes NodeController and DrupalDefaultEntityController. After the node |
|
539 * information is read from the database or the entity cache, hook_load() is |
|
540 * invoked on the node's content type module, then field_attach_load_revision() |
|
541 * or field_attach_load() is called, then hook_entity_load() is invoked on all |
|
542 * implementing modules, and finally hook_node_load() is invoked on all |
|
543 * implementing modules. |
|
544 * |
|
545 * @param $nodes |
|
546 * An array of the nodes being loaded, keyed by nid. |
|
547 * @param $types |
|
548 * An array containing the node types present in $nodes. Allows for an early |
|
549 * return for modules that only support certain node types. However, if your |
|
550 * module defines a content type, you can use hook_load() to respond to |
|
551 * loading of just that content type. |
|
552 * |
|
553 * For a detailed usage example, see nodeapi_example.module. |
|
554 * |
|
555 * @ingroup node_api_hooks |
|
556 */ |
|
557 function hook_node_load($nodes, $types) { |
|
558 // Decide whether any of $types are relevant to our purposes. |
|
559 if (count(array_intersect($types_we_want_to_process, $types))) { |
|
560 // Gather our extra data for each of these nodes. |
|
561 $result = db_query('SELECT nid, foo FROM {mytable} WHERE nid IN(:nids)', array(':nids' => array_keys($nodes))); |
|
562 // Add our extra data to the node objects. |
|
563 foreach ($result as $record) { |
|
564 $nodes[$record->nid]->foo = $record->foo; |
|
565 } |
|
566 } |
|
567 } |
|
568 |
|
569 /** |
|
570 * Control access to a node. |
|
571 * |
|
572 * Modules may implement this hook if they want to have a say in whether or not |
|
573 * a given user has access to perform a given operation on a node. |
|
574 * |
|
575 * The administrative account (user ID #1) always passes any access check, so |
|
576 * this hook is not called in that case. Users with the "bypass node access" |
|
577 * permission may always view and edit content through the administrative |
|
578 * interface. |
|
579 * |
|
580 * Note that not all modules will want to influence access on all node types. If |
|
581 * your module does not want to actively grant or block access, return |
|
582 * NODE_ACCESS_IGNORE or simply return nothing. Blindly returning FALSE will |
|
583 * break other node access modules. |
|
584 * |
|
585 * Also note that this function isn't called for node listings (e.g., RSS feeds, |
|
586 * the default home page at path 'node', a recent content block, etc.) See |
|
587 * @link node_access Node access rights @endlink for a full explanation. |
|
588 * |
|
589 * @param $node |
|
590 * Either a node object or the machine name of the content type on which to |
|
591 * perform the access check. |
|
592 * @param $op |
|
593 * The operation to be performed. Possible values: |
|
594 * - "create" |
|
595 * - "delete" |
|
596 * - "update" |
|
597 * - "view" |
|
598 * @param $account |
|
599 * The user object to perform the access check operation on. |
|
600 * |
|
601 * @return |
|
602 * - NODE_ACCESS_ALLOW: if the operation is to be allowed. |
|
603 * - NODE_ACCESS_DENY: if the operation is to be denied. |
|
604 * - NODE_ACCESS_IGNORE: to not affect this operation at all. |
|
605 * |
|
606 * @ingroup node_access |
|
607 */ |
|
608 function hook_node_access($node, $op, $account) { |
|
609 $type = is_string($node) ? $node : $node->type; |
|
610 |
|
611 if (in_array($type, node_permissions_get_configured_types())) { |
|
612 if ($op == 'create' && user_access('create ' . $type . ' content', $account)) { |
|
613 return NODE_ACCESS_ALLOW; |
|
614 } |
|
615 |
|
616 if ($op == 'update') { |
|
617 if (user_access('edit any ' . $type . ' content', $account) || (user_access('edit own ' . $type . ' content', $account) && ($account->uid == $node->uid))) { |
|
618 return NODE_ACCESS_ALLOW; |
|
619 } |
|
620 } |
|
621 |
|
622 if ($op == 'delete') { |
|
623 if (user_access('delete any ' . $type . ' content', $account) || (user_access('delete own ' . $type . ' content', $account) && ($account->uid == $node->uid))) { |
|
624 return NODE_ACCESS_ALLOW; |
|
625 } |
|
626 } |
|
627 } |
|
628 |
|
629 // Returning nothing from this function would have the same effect. |
|
630 return NODE_ACCESS_IGNORE; |
|
631 } |
|
632 |
|
633 |
|
634 /** |
|
635 * Act on a node object about to be shown on the add/edit form. |
|
636 * |
|
637 * This hook is invoked from node_object_prepare() after the type-specific |
|
638 * hook_prepare() is invoked. |
|
639 * |
|
640 * @param $node |
|
641 * The node that is about to be shown on the add/edit form. |
|
642 * |
|
643 * @ingroup node_api_hooks |
|
644 */ |
|
645 function hook_node_prepare($node) { |
|
646 if (!isset($node->comment)) { |
|
647 $node->comment = variable_get("comment_$node->type", COMMENT_NODE_OPEN); |
|
648 } |
|
649 } |
|
650 |
|
651 /** |
|
652 * Act on a node being displayed as a search result. |
|
653 * |
|
654 * This hook is invoked from node_search_execute(), after node_load() and |
|
655 * node_view() have been called. |
|
656 * |
|
657 * @param $node |
|
658 * The node being displayed in a search result. |
|
659 * |
|
660 * @return array |
|
661 * Extra information to be displayed with search result. This information |
|
662 * should be presented as an associative array. It will be concatenated with |
|
663 * the post information (last updated, author) in the default search result |
|
664 * theming. |
|
665 * |
|
666 * @see template_preprocess_search_result() |
|
667 * @see search-result.tpl.php |
|
668 * |
|
669 * @ingroup node_api_hooks |
|
670 */ |
|
671 function hook_node_search_result($node) { |
|
672 $comments = db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = :nid', array('nid' => $node->nid))->fetchField(); |
|
673 return array('comment' => format_plural($comments, '1 comment', '@count comments')); |
|
674 } |
|
675 |
|
676 /** |
|
677 * Act on a node being inserted or updated. |
|
678 * |
|
679 * This hook is invoked from node_save() before the node is saved to the |
|
680 * database. |
|
681 * |
|
682 * @param $node |
|
683 * The node that is being inserted or updated. |
|
684 * |
|
685 * @ingroup node_api_hooks |
|
686 */ |
|
687 function hook_node_presave($node) { |
|
688 if ($node->nid && $node->moderate) { |
|
689 // Reset votes when node is updated: |
|
690 $node->score = 0; |
|
691 $node->users = ''; |
|
692 $node->votes = 0; |
|
693 } |
|
694 } |
|
695 |
|
696 /** |
|
697 * Respond to updates to a node. |
|
698 * |
|
699 * This hook is invoked from node_save() after the database query that will |
|
700 * update node in the node table is scheduled for execution, after the |
|
701 * type-specific hook_update() is invoked, and after field_attach_update() is |
|
702 * called. |
|
703 * |
|
704 * Note that when this hook is invoked, the changes have not yet been written to |
|
705 * the database, because a database transaction is still in progress. The |
|
706 * transaction is not finalized until the save operation is entirely completed |
|
707 * and node_save() goes out of scope. You should not rely on data in the |
|
708 * database at this time as it is not updated yet. You should also note that any |
|
709 * write/update database queries executed from this hook are also not committed |
|
710 * immediately. Check node_save() and db_transaction() for more info. |
|
711 * |
|
712 * @param $node |
|
713 * The node that is being updated. |
|
714 * |
|
715 * @ingroup node_api_hooks |
|
716 */ |
|
717 function hook_node_update($node) { |
|
718 db_update('mytable') |
|
719 ->fields(array('extra' => $node->extra)) |
|
720 ->condition('nid', $node->nid) |
|
721 ->execute(); |
|
722 } |
|
723 |
|
724 /** |
|
725 * Act on a node being indexed for searching. |
|
726 * |
|
727 * This hook is invoked during search indexing, after node_load(), and after the |
|
728 * result of node_view() is added as $node->rendered to the node object. |
|
729 * |
|
730 * @param $node |
|
731 * The node being indexed. |
|
732 * |
|
733 * @return string |
|
734 * Additional node information to be indexed. |
|
735 * |
|
736 * @ingroup node_api_hooks |
|
737 */ |
|
738 function hook_node_update_index($node) { |
|
739 $text = ''; |
|
740 $comments = db_query('SELECT subject, comment, format FROM {comment} WHERE nid = :nid AND status = :status', array(':nid' => $node->nid, ':status' => COMMENT_PUBLISHED)); |
|
741 foreach ($comments as $comment) { |
|
742 $text .= '<h2>' . check_plain($comment->subject) . '</h2>' . check_markup($comment->comment, $comment->format, '', TRUE); |
|
743 } |
|
744 return $text; |
|
745 } |
|
746 |
|
747 /** |
|
748 * Perform node validation before a node is created or updated. |
|
749 * |
|
750 * This hook is invoked from node_validate(), after a user has has finished |
|
751 * editing the node and is previewing or submitting it. It is invoked at the |
|
752 * end of all the standard validation steps, and after the type-specific |
|
753 * hook_validate() is invoked. |
|
754 * |
|
755 * To indicate a validation error, use form_set_error(). |
|
756 * |
|
757 * Note: Changes made to the $node object within your hook implementation will |
|
758 * have no effect. The preferred method to change a node's content is to use |
|
759 * hook_node_presave() instead. If it is really necessary to change the node at |
|
760 * the validate stage, you can use form_set_value(). |
|
761 * |
|
762 * @param $node |
|
763 * The node being validated. |
|
764 * @param $form |
|
765 * The form being used to edit the node. |
|
766 * @param $form_state |
|
767 * The form state array. |
|
768 * |
|
769 * @ingroup node_api_hooks |
|
770 */ |
|
771 function hook_node_validate($node, $form, &$form_state) { |
|
772 if (isset($node->end) && isset($node->start)) { |
|
773 if ($node->start > $node->end) { |
|
774 form_set_error('time', t('An event may not end before it starts.')); |
|
775 } |
|
776 } |
|
777 } |
|
778 |
|
779 /** |
|
780 * Act on a node after validated form values have been copied to it. |
|
781 * |
|
782 * This hook is invoked when a node form is submitted with either the "Save" or |
|
783 * "Preview" button, after form values have been copied to the form state's node |
|
784 * object, but before the node is saved or previewed. It is a chance for modules |
|
785 * to adjust the node's properties from what they are simply after a copy from |
|
786 * $form_state['values']. This hook is intended for adjusting non-field-related |
|
787 * properties. See hook_field_attach_submit() for customizing field-related |
|
788 * properties. |
|
789 * |
|
790 * @param $node |
|
791 * The node object being updated in response to a form submission. |
|
792 * @param $form |
|
793 * The form being used to edit the node. |
|
794 * @param $form_state |
|
795 * The form state array. |
|
796 * |
|
797 * @ingroup node_api_hooks |
|
798 */ |
|
799 function hook_node_submit($node, $form, &$form_state) { |
|
800 // Decompose the selected menu parent option into 'menu_name' and 'plid', if |
|
801 // the form used the default parent selection widget. |
|
802 if (!empty($form_state['values']['menu']['parent'])) { |
|
803 list($node->menu['menu_name'], $node->menu['plid']) = explode(':', $form_state['values']['menu']['parent']); |
|
804 } |
|
805 } |
|
806 |
|
807 /** |
|
808 * Act on a node that is being assembled before rendering. |
|
809 * |
|
810 * The module may add elements to $node->content prior to rendering. This hook |
|
811 * will be called after hook_view(). The structure of $node->content is a |
|
812 * renderable array as expected by drupal_render(). |
|
813 * |
|
814 * When $view_mode is 'rss', modules can also add extra RSS elements and |
|
815 * namespaces to $node->rss_elements and $node->rss_namespaces respectively for |
|
816 * the RSS item generated for this node. |
|
817 * For details on how this is used, see node_feed(). |
|
818 * |
|
819 * @see blog_node_view() |
|
820 * @see forum_node_view() |
|
821 * @see comment_node_view() |
|
822 * |
|
823 * @param $node |
|
824 * The node that is being assembled for rendering. |
|
825 * @param $view_mode |
|
826 * The $view_mode parameter from node_view(). |
|
827 * @param $langcode |
|
828 * The language code used for rendering. |
|
829 * |
|
830 * @see hook_entity_view() |
|
831 * |
|
832 * @ingroup node_api_hooks |
|
833 */ |
|
834 function hook_node_view($node, $view_mode, $langcode) { |
|
835 $node->content['my_additional_field'] = array( |
|
836 '#markup' => $additional_field, |
|
837 '#weight' => 10, |
|
838 '#theme' => 'mymodule_my_additional_field', |
|
839 ); |
|
840 } |
|
841 |
|
842 /** |
|
843 * Alter the results of node_view(). |
|
844 * |
|
845 * This hook is called after the content has been assembled in a structured |
|
846 * array and may be used for doing processing which requires that the complete |
|
847 * node content structure has been built. |
|
848 * |
|
849 * If the module wishes to act on the rendered HTML of the node rather than the |
|
850 * structured content array, it may use this hook to add a #post_render |
|
851 * callback. Alternatively, it could also implement hook_preprocess_node(). See |
|
852 * drupal_render() and theme() documentation respectively for details. |
|
853 * |
|
854 * @param $build |
|
855 * A renderable array representing the node content. |
|
856 * |
|
857 * @see node_view() |
|
858 * @see hook_entity_view_alter() |
|
859 * |
|
860 * @ingroup node_api_hooks |
|
861 */ |
|
862 function hook_node_view_alter(&$build) { |
|
863 if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) { |
|
864 // Change its weight. |
|
865 $build['an_additional_field']['#weight'] = -10; |
|
866 } |
|
867 |
|
868 // Add a #post_render callback to act on the rendered HTML of the node. |
|
869 $build['#post_render'][] = 'my_module_node_post_render'; |
|
870 } |
|
871 |
|
872 /** |
|
873 * Define module-provided node types. |
|
874 * |
|
875 * This hook allows a module to define one or more of its own node types. For |
|
876 * example, the blog module uses it to define a blog node-type named "Blog |
|
877 * entry." The name and attributes of each desired node type are specified in an |
|
878 * array returned by the hook. |
|
879 * |
|
880 * Only module-provided node types should be defined through this hook. User- |
|
881 * provided (or 'custom') node types should be defined only in the 'node_type' |
|
882 * database table, and should be maintained by using the node_type_save() and |
|
883 * node_type_delete() functions. |
|
884 * |
|
885 * @return |
|
886 * An array of information defining the module's node types. The array |
|
887 * contains a sub-array for each node type, with the machine-readable type |
|
888 * name as the key. Each sub-array has up to 10 attributes. Possible |
|
889 * attributes: |
|
890 * - name: (required) The human-readable name of the node type. |
|
891 * - base: (required) The base name for implementations of node-type-specific |
|
892 * hooks that respond to this node type. Base is usually the name of the |
|
893 * module or 'node_content', but not always. See |
|
894 * @link node_api_hooks Node API hooks @endlink for more information. |
|
895 * - description: (required) A brief description of the node type. |
|
896 * - help: (optional) Help information shown to the user when creating a node |
|
897 * of this type. |
|
898 * - has_title: (optional) A Boolean indicating whether or not this node type |
|
899 * has a title field. |
|
900 * - title_label: (optional) The label for the title field of this content |
|
901 * type. |
|
902 * - locked: (optional) A Boolean indicating whether the administrator can |
|
903 * change the machine name of this type. FALSE = changeable (not locked), |
|
904 * TRUE = unchangeable (locked). |
|
905 * |
|
906 * The machine name of a node type should contain only letters, numbers, and |
|
907 * underscores. Underscores will be converted into hyphens for the purpose of |
|
908 * constructing URLs. |
|
909 * |
|
910 * All attributes of a node type that are defined through this hook (except for |
|
911 * 'locked') can be edited by a site administrator. This includes the |
|
912 * machine-readable name of a node type, if 'locked' is set to FALSE. |
|
913 * |
|
914 * @ingroup node_api_hooks |
|
915 */ |
|
916 function hook_node_info() { |
|
917 return array( |
|
918 'blog' => array( |
|
919 'name' => t('Blog entry'), |
|
920 'base' => 'blog', |
|
921 'description' => t('Use for multi-user blogs. Every user gets a personal blog.'), |
|
922 ) |
|
923 ); |
|
924 } |
|
925 |
|
926 /** |
|
927 * Provide additional methods of scoring for core search results for nodes. |
|
928 * |
|
929 * A node's search score is used to rank it among other nodes matched by the |
|
930 * search, with the highest-ranked nodes appearing first in the search listing. |
|
931 * |
|
932 * For example, a module allowing users to vote on content could expose an |
|
933 * option to allow search results' rankings to be influenced by the average |
|
934 * voting score of a node. |
|
935 * |
|
936 * All scoring mechanisms are provided as options to site administrators, and |
|
937 * may be tweaked based on individual sites or disabled altogether if they do |
|
938 * not make sense. Individual scoring mechanisms, if enabled, are assigned a |
|
939 * weight from 1 to 10. The weight represents the factor of magnification of |
|
940 * the ranking mechanism, with higher-weighted ranking mechanisms having more |
|
941 * influence. In order for the weight system to work, each scoring mechanism |
|
942 * must return a value between 0 and 1 for every node. That value is then |
|
943 * multiplied by the administrator-assigned weight for the ranking mechanism, |
|
944 * and then the weighted scores from all ranking mechanisms are added, which |
|
945 * brings about the same result as a weighted average. |
|
946 * |
|
947 * @return |
|
948 * An associative array of ranking data. The keys should be strings, |
|
949 * corresponding to the internal name of the ranking mechanism, such as |
|
950 * 'recent', or 'comments'. The values should be arrays themselves, with the |
|
951 * following keys available: |
|
952 * - title: (required) The human readable name of the ranking mechanism. |
|
953 * - join: (optional) An array with information to join any additional |
|
954 * necessary table. This is not necessary if the table required is already |
|
955 * joined to by the base query, such as for the {node} table. Other tables |
|
956 * should use the full table name as an alias to avoid naming collisions. |
|
957 * - score: (required) The part of a query string to calculate the score for |
|
958 * the ranking mechanism based on values in the database. This does not need |
|
959 * to be wrapped in parentheses, as it will be done automatically; it also |
|
960 * does not need to take the weighted system into account, as it will be |
|
961 * done automatically. It does, however, need to calculate a decimal between |
|
962 * 0 and 1; be careful not to cast the entire score to an integer by |
|
963 * inadvertently introducing a variable argument. |
|
964 * - arguments: (optional) If any arguments are required for the score, they |
|
965 * can be specified in an array here. |
|
966 * |
|
967 * @ingroup node_api_hooks |
|
968 */ |
|
969 function hook_ranking() { |
|
970 // If voting is disabled, we can avoid returning the array, no hard feelings. |
|
971 if (variable_get('vote_node_enabled', TRUE)) { |
|
972 return array( |
|
973 'vote_average' => array( |
|
974 'title' => t('Average vote'), |
|
975 // Note that we use i.sid, the search index's search item id, rather than |
|
976 // n.nid. |
|
977 'join' => array( |
|
978 'type' => 'LEFT', |
|
979 'table' => 'vote_node_data', |
|
980 'alias' => 'vote_node_data', |
|
981 'on' => 'vote_node_data.nid = i.sid', |
|
982 ), |
|
983 // The highest possible score should be 1, and the lowest possible score, |
|
984 // always 0, should be 0. |
|
985 'score' => 'vote_node_data.average / CAST(%f AS DECIMAL)', |
|
986 // Pass in the highest possible voting score as a decimal argument. |
|
987 'arguments' => array(variable_get('vote_score_max', 5)), |
|
988 ), |
|
989 ); |
|
990 } |
|
991 } |
|
992 |
|
993 |
|
994 /** |
|
995 * Respond to node type creation. |
|
996 * |
|
997 * This hook is invoked from node_type_save() after the node type is added to |
|
998 * the database. |
|
999 * |
|
1000 * @param $info |
|
1001 * The node type object that is being created. |
|
1002 */ |
|
1003 function hook_node_type_insert($info) { |
|
1004 drupal_set_message(t('You have just created a content type with a machine name %type.', array('%type' => $info->type))); |
|
1005 } |
|
1006 |
|
1007 /** |
|
1008 * Respond to node type updates. |
|
1009 * |
|
1010 * This hook is invoked from node_type_save() after the node type is updated in |
|
1011 * the database. |
|
1012 * |
|
1013 * @param $info |
|
1014 * The node type object that is being updated. |
|
1015 */ |
|
1016 function hook_node_type_update($info) { |
|
1017 if (!empty($info->old_type) && $info->old_type != $info->type) { |
|
1018 $setting = variable_get('comment_' . $info->old_type, COMMENT_NODE_OPEN); |
|
1019 variable_del('comment_' . $info->old_type); |
|
1020 variable_set('comment_' . $info->type, $setting); |
|
1021 } |
|
1022 } |
|
1023 |
|
1024 /** |
|
1025 * Respond to node type deletion. |
|
1026 * |
|
1027 * This hook is invoked from node_type_delete() after the node type is removed |
|
1028 * from the database. |
|
1029 * |
|
1030 * @param $info |
|
1031 * The node type object that is being deleted. |
|
1032 */ |
|
1033 function hook_node_type_delete($info) { |
|
1034 variable_del('comment_' . $info->type); |
|
1035 } |
|
1036 |
|
1037 /** |
|
1038 * Respond to node deletion. |
|
1039 * |
|
1040 * This is a node-type-specific hook, which is invoked only for the node type |
|
1041 * being affected. See |
|
1042 * @link node_api_hooks Node API hooks @endlink for more information. |
|
1043 * |
|
1044 * Use hook_node_delete() to respond to node deletion of all node types. |
|
1045 * |
|
1046 * This hook is invoked from node_delete_multiple() before hook_node_delete() |
|
1047 * is invoked and before field_attach_delete() is called. |
|
1048 * |
|
1049 * Note that when this hook is invoked, the changes have not yet been written |
|
1050 * to the database, because a database transaction is still in progress. The |
|
1051 * transaction is not finalized until the delete operation is entirely |
|
1052 * completed and node_delete_multiple() goes out of scope. You should not rely |
|
1053 * on data in the database at this time as it is not updated yet. You should |
|
1054 * also note that any write/update database queries executed from this hook are |
|
1055 * also not committed immediately. Check node_delete_multiple() and |
|
1056 * db_transaction() for more info. |
|
1057 * |
|
1058 * @param $node |
|
1059 * The node that is being deleted. |
|
1060 * |
|
1061 * @ingroup node_api_hooks |
|
1062 */ |
|
1063 function hook_delete($node) { |
|
1064 db_delete('mytable') |
|
1065 ->condition('nid', $node->nid) |
|
1066 ->execute(); |
|
1067 } |
|
1068 |
|
1069 /** |
|
1070 * Act on a node object about to be shown on the add/edit form. |
|
1071 * |
|
1072 * This is a node-type-specific hook, which is invoked only for the node type |
|
1073 * being affected. See |
|
1074 * @link node_api_hooks Node API hooks @endlink for more information. |
|
1075 * |
|
1076 * Use hook_node_prepare() to respond to node preparation of all node types. |
|
1077 * |
|
1078 * This hook is invoked from node_object_prepare() before the general |
|
1079 * hook_node_prepare() is invoked. |
|
1080 * |
|
1081 * @param $node |
|
1082 * The node that is about to be shown on the add/edit form. |
|
1083 * |
|
1084 * @ingroup node_api_hooks |
|
1085 */ |
|
1086 function hook_prepare($node) { |
|
1087 if (!isset($node->mymodule_value)) { |
|
1088 $node->mymodule_value = 'foo'; |
|
1089 } |
|
1090 } |
|
1091 |
|
1092 /** |
|
1093 * Display a node editing form. |
|
1094 * |
|
1095 * This is a node-type-specific hook, which is invoked only for the node type |
|
1096 * being affected. See |
|
1097 * @link node_api_hooks Node API hooks @endlink for more information. |
|
1098 * |
|
1099 * Use hook_form_BASE_FORM_ID_alter(), with base form ID 'node_form', to alter |
|
1100 * node forms for all node types. |
|
1101 * |
|
1102 * This hook, implemented by node modules, is called to retrieve the form |
|
1103 * that is displayed to create or edit a node. This form is displayed at path |
|
1104 * node/add/[node type] or node/[node ID]/edit. |
|
1105 * |
|
1106 * The submit and preview buttons, administrative and display controls, and |
|
1107 * sections added by other modules (such as path settings, menu settings, |
|
1108 * comment settings, and fields managed by the Field UI module) are |
|
1109 * displayed automatically by the node module. This hook just needs to |
|
1110 * return the node title and form editing fields specific to the node type. |
|
1111 * |
|
1112 * @param $node |
|
1113 * The node being added or edited. |
|
1114 * @param $form_state |
|
1115 * The form state array. |
|
1116 * |
|
1117 * @return |
|
1118 * An array containing the title and any custom form elements to be displayed |
|
1119 * in the node editing form. |
|
1120 * |
|
1121 * @ingroup node_api_hooks |
|
1122 */ |
|
1123 function hook_form($node, &$form_state) { |
|
1124 $type = node_type_get_type($node); |
|
1125 |
|
1126 $form['title'] = array( |
|
1127 '#type' => 'textfield', |
|
1128 '#title' => check_plain($type->title_label), |
|
1129 '#default_value' => !empty($node->title) ? $node->title : '', |
|
1130 '#required' => TRUE, '#weight' => -5 |
|
1131 ); |
|
1132 |
|
1133 $form['field1'] = array( |
|
1134 '#type' => 'textfield', |
|
1135 '#title' => t('Custom field'), |
|
1136 '#default_value' => $node->field1, |
|
1137 '#maxlength' => 127, |
|
1138 ); |
|
1139 $form['selectbox'] = array( |
|
1140 '#type' => 'select', |
|
1141 '#title' => t('Select box'), |
|
1142 '#default_value' => $node->selectbox, |
|
1143 '#options' => array( |
|
1144 1 => 'Option A', |
|
1145 2 => 'Option B', |
|
1146 3 => 'Option C', |
|
1147 ), |
|
1148 '#description' => t('Choose an option.'), |
|
1149 ); |
|
1150 |
|
1151 return $form; |
|
1152 } |
|
1153 |
|
1154 /** |
|
1155 * Respond to creation of a new node. |
|
1156 * |
|
1157 * This is a node-type-specific hook, which is invoked only for the node type |
|
1158 * being affected. See |
|
1159 * @link node_api_hooks Node API hooks @endlink for more information. |
|
1160 * |
|
1161 * Use hook_node_insert() to respond to node insertion of all node types. |
|
1162 * |
|
1163 * This hook is invoked from node_save() after the node is inserted into the |
|
1164 * node table in the database, before field_attach_insert() is called, and |
|
1165 * before hook_node_insert() is invoked. |
|
1166 * |
|
1167 * @param $node |
|
1168 * The node that is being created. |
|
1169 * |
|
1170 * @ingroup node_api_hooks |
|
1171 */ |
|
1172 function hook_insert($node) { |
|
1173 db_insert('mytable') |
|
1174 ->fields(array( |
|
1175 'nid' => $node->nid, |
|
1176 'extra' => $node->extra, |
|
1177 )) |
|
1178 ->execute(); |
|
1179 } |
|
1180 |
|
1181 /** |
|
1182 * Act on nodes being loaded from the database. |
|
1183 * |
|
1184 * This is a node-type-specific hook, which is invoked only for the node type |
|
1185 * being affected. See |
|
1186 * @link node_api_hooks Node API hooks @endlink for more information. |
|
1187 * |
|
1188 * Use hook_node_load() to respond to node load of all node types. |
|
1189 * |
|
1190 * This hook is invoked during node loading, which is handled by entity_load(), |
|
1191 * via classes NodeController and DrupalDefaultEntityController. After the node |
|
1192 * information is read from the database or the entity cache, hook_load() is |
|
1193 * invoked on the node's content type module, then field_attach_node_revision() |
|
1194 * or field_attach_load() is called, then hook_entity_load() is invoked on all |
|
1195 * implementing modules, and finally hook_node_load() is invoked on all |
|
1196 * implementing modules. |
|
1197 * |
|
1198 * This hook should only be used to add information that is not in the node or |
|
1199 * node revisions table, not to replace information that is in these tables |
|
1200 * (which could interfere with the entity cache). For performance reasons, |
|
1201 * information for all available nodes should be loaded in a single query where |
|
1202 * possible. |
|
1203 * |
|
1204 * @param $nodes |
|
1205 * An array of the nodes being loaded, keyed by nid. |
|
1206 * |
|
1207 * For a detailed usage example, see node_example.module. |
|
1208 * |
|
1209 * @ingroup node_api_hooks |
|
1210 */ |
|
1211 function hook_load($nodes) { |
|
1212 $result = db_query('SELECT nid, foo FROM {mytable} WHERE nid IN (:nids)', array(':nids' => array_keys($nodes))); |
|
1213 foreach ($result as $record) { |
|
1214 $nodes[$record->nid]->foo = $record->foo; |
|
1215 } |
|
1216 } |
|
1217 |
|
1218 /** |
|
1219 * Respond to updates to a node. |
|
1220 * |
|
1221 * This is a node-type-specific hook, which is invoked only for the node type |
|
1222 * being affected. See |
|
1223 * @link node_api_hooks Node API hooks @endlink for more information. |
|
1224 * |
|
1225 * Use hook_node_update() to respond to node update of all node types. |
|
1226 * |
|
1227 * This hook is invoked from node_save() after the node is updated in the |
|
1228 * node table in the database, before field_attach_update() is called, and |
|
1229 * before hook_node_update() is invoked. |
|
1230 * |
|
1231 * @param $node |
|
1232 * The node that is being updated. |
|
1233 * |
|
1234 * @ingroup node_api_hooks |
|
1235 */ |
|
1236 function hook_update($node) { |
|
1237 db_update('mytable') |
|
1238 ->fields(array('extra' => $node->extra)) |
|
1239 ->condition('nid', $node->nid) |
|
1240 ->execute(); |
|
1241 } |
|
1242 |
|
1243 /** |
|
1244 * Perform node validation before a node is created or updated. |
|
1245 * |
|
1246 * This is a node-type-specific hook, which is invoked only for the node type |
|
1247 * being affected. See |
|
1248 * @link node_api_hooks Node API hooks @endlink for more information. |
|
1249 * |
|
1250 * Use hook_node_validate() to respond to node validation of all node types. |
|
1251 * |
|
1252 * This hook is invoked from node_validate(), after a user has finished |
|
1253 * editing the node and is previewing or submitting it. It is invoked at the end |
|
1254 * of all the standard validation steps, and before hook_node_validate() is |
|
1255 * invoked. |
|
1256 * |
|
1257 * To indicate a validation error, use form_set_error(). |
|
1258 * |
|
1259 * Note: Changes made to the $node object within your hook implementation will |
|
1260 * have no effect. The preferred method to change a node's content is to use |
|
1261 * hook_node_presave() instead. |
|
1262 * |
|
1263 * @param $node |
|
1264 * The node being validated. |
|
1265 * @param $form |
|
1266 * The form being used to edit the node. |
|
1267 * @param $form_state |
|
1268 * The form state array. |
|
1269 * |
|
1270 * @ingroup node_api_hooks |
|
1271 */ |
|
1272 function hook_validate($node, $form, &$form_state) { |
|
1273 if (isset($node->end) && isset($node->start)) { |
|
1274 if ($node->start > $node->end) { |
|
1275 form_set_error('time', t('An event may not end before it starts.')); |
|
1276 } |
|
1277 } |
|
1278 } |
|
1279 |
|
1280 /** |
|
1281 * Display a node. |
|
1282 * |
|
1283 * This is a node-type-specific hook, which is invoked only for the node type |
|
1284 * being affected. See |
|
1285 * @link node_api_hooks Node API hooks @endlink for more information. |
|
1286 * |
|
1287 * Use hook_node_view() to respond to node view of all node types. |
|
1288 * |
|
1289 * This hook is invoked during node viewing after the node is fully loaded, so |
|
1290 * that the node type module can define a custom method for display, or add to |
|
1291 * the default display. |
|
1292 * |
|
1293 * @param $node |
|
1294 * The node to be displayed, as returned by node_load(). |
|
1295 * @param $view_mode |
|
1296 * View mode, e.g. 'full', 'teaser', ... |
|
1297 * @param $langcode |
|
1298 * (optional) A language code to use for rendering. Defaults to the global |
|
1299 * content language of the current request. |
|
1300 * |
|
1301 * @return |
|
1302 * The passed $node parameter should be modified as necessary and returned so |
|
1303 * it can be properly presented. Nodes are prepared for display by assembling |
|
1304 * a structured array, formatted as in the Form API, in $node->content. As |
|
1305 * with Form API arrays, the #weight property can be used to control the |
|
1306 * relative positions of added elements. After this hook is invoked, |
|
1307 * node_view() calls field_attach_view() to add field views to $node->content, |
|
1308 * and then invokes hook_node_view() and hook_node_view_alter(), so if you |
|
1309 * want to affect the final view of the node, you might consider implementing |
|
1310 * one of these hooks instead. |
|
1311 * |
|
1312 * @ingroup node_api_hooks |
|
1313 */ |
|
1314 function hook_view($node, $view_mode, $langcode = NULL) { |
|
1315 if ($view_mode == 'full' && node_is_page($node)) { |
|
1316 $breadcrumb = array(); |
|
1317 $breadcrumb[] = l(t('Home'), NULL); |
|
1318 $breadcrumb[] = l(t('Example'), 'example'); |
|
1319 $breadcrumb[] = l($node->field1, 'example/' . $node->field1); |
|
1320 drupal_set_breadcrumb($breadcrumb); |
|
1321 } |
|
1322 |
|
1323 $node->content['myfield'] = array( |
|
1324 '#markup' => theme('mymodule_myfield', $node->myfield), |
|
1325 '#weight' => 1, |
|
1326 ); |
|
1327 |
|
1328 return $node; |
|
1329 } |
|
1330 |
|
1331 /** |
|
1332 * @} End of "addtogroup hooks". |
|
1333 */ |