root / drupal7 / modules / node / node.api.php @ 76597ebf
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) The part of a query string to join to 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' => 'LEFT JOIN {vote_node_data} vote_node_data ON vote_node_data.nid = i.sid', |
978 |
// The highest possible score should be 1, and the lowest possible score,
|
979 |
// always 0, should be 0.
|
980 |
'score' => 'vote_node_data.average / CAST(%f AS DECIMAL)', |
981 |
// Pass in the highest possible voting score as a decimal argument.
|
982 |
'arguments' => array(variable_get('vote_score_max', 5)), |
983 |
), |
984 |
); |
985 |
} |
986 |
} |
987 |
|
988 |
|
989 |
/**
|
990 |
* Respond to node type creation.
|
991 |
*
|
992 |
* This hook is invoked from node_type_save() after the node type is added to
|
993 |
* the database.
|
994 |
*
|
995 |
* @param $info
|
996 |
* The node type object that is being created.
|
997 |
*/
|
998 |
function hook_node_type_insert($info) { |
999 |
drupal_set_message(t('You have just created a content type with a machine name %type.', array('%type' => $info->type))); |
1000 |
} |
1001 |
|
1002 |
/**
|
1003 |
* Respond to node type updates.
|
1004 |
*
|
1005 |
* This hook is invoked from node_type_save() after the node type is updated in
|
1006 |
* the database.
|
1007 |
*
|
1008 |
* @param $info
|
1009 |
* The node type object that is being updated.
|
1010 |
*/
|
1011 |
function hook_node_type_update($info) { |
1012 |
if (!empty($info->old_type) && $info->old_type != $info->type) { |
1013 |
$setting = variable_get('comment_' . $info->old_type, COMMENT_NODE_OPEN); |
1014 |
variable_del('comment_' . $info->old_type); |
1015 |
variable_set('comment_' . $info->type, $setting); |
1016 |
} |
1017 |
} |
1018 |
|
1019 |
/**
|
1020 |
* Respond to node type deletion.
|
1021 |
*
|
1022 |
* This hook is invoked from node_type_delete() after the node type is removed
|
1023 |
* from the database.
|
1024 |
*
|
1025 |
* @param $info
|
1026 |
* The node type object that is being deleted.
|
1027 |
*/
|
1028 |
function hook_node_type_delete($info) { |
1029 |
variable_del('comment_' . $info->type); |
1030 |
} |
1031 |
|
1032 |
/**
|
1033 |
* Respond to node deletion.
|
1034 |
*
|
1035 |
* This is a node-type-specific hook, which is invoked only for the node type
|
1036 |
* being affected. See
|
1037 |
* @link node_api_hooks Node API hooks @endlink for more information.
|
1038 |
*
|
1039 |
* Use hook_node_delete() to respond to node deletion of all node types.
|
1040 |
*
|
1041 |
* This hook is invoked from node_delete_multiple() before hook_node_delete()
|
1042 |
* is invoked and before field_attach_delete() is called.
|
1043 |
*
|
1044 |
* Note that when this hook is invoked, the changes have not yet been written
|
1045 |
* to the database, because a database transaction is still in progress. The
|
1046 |
* transaction is not finalized until the delete operation is entirely
|
1047 |
* completed and node_delete_multiple() goes out of scope. You should not rely
|
1048 |
* on data in the database at this time as it is not updated yet. You should
|
1049 |
* also note that any write/update database queries executed from this hook are
|
1050 |
* also not committed immediately. Check node_delete_multiple() and
|
1051 |
* db_transaction() for more info.
|
1052 |
*
|
1053 |
* @param $node
|
1054 |
* The node that is being deleted.
|
1055 |
*
|
1056 |
* @ingroup node_api_hooks
|
1057 |
*/
|
1058 |
function hook_delete($node) { |
1059 |
db_delete('mytable')
|
1060 |
->condition('nid', $node->nid) |
1061 |
->execute(); |
1062 |
} |
1063 |
|
1064 |
/**
|
1065 |
* Act on a node object about to be shown on the add/edit form.
|
1066 |
*
|
1067 |
* This is a node-type-specific hook, which is invoked only for the node type
|
1068 |
* being affected. See
|
1069 |
* @link node_api_hooks Node API hooks @endlink for more information.
|
1070 |
*
|
1071 |
* Use hook_node_prepare() to respond to node preparation of all node types.
|
1072 |
*
|
1073 |
* This hook is invoked from node_object_prepare() before the general
|
1074 |
* hook_node_prepare() is invoked.
|
1075 |
*
|
1076 |
* @param $node
|
1077 |
* The node that is about to be shown on the add/edit form.
|
1078 |
*
|
1079 |
* @ingroup node_api_hooks
|
1080 |
*/
|
1081 |
function hook_prepare($node) { |
1082 |
$file = file_save_upload($field_name, _image_filename($file->filename, NULL, TRUE)); |
1083 |
if ($file) { |
1084 |
if (!image_get_info($file->uri)) { |
1085 |
form_set_error($field_name, t('Uploaded file is not a valid image')); |
1086 |
return;
|
1087 |
} |
1088 |
} |
1089 |
else {
|
1090 |
return;
|
1091 |
} |
1092 |
$node->images['_original'] = $file->uri; |
1093 |
_image_build_derivatives($node, TRUE); |
1094 |
$node->new_file = TRUE; |
1095 |
} |
1096 |
|
1097 |
/**
|
1098 |
* Display a node editing form.
|
1099 |
*
|
1100 |
* This is a node-type-specific hook, which is invoked only for the node type
|
1101 |
* being affected. See
|
1102 |
* @link node_api_hooks Node API hooks @endlink for more information.
|
1103 |
*
|
1104 |
* Use hook_form_BASE_FORM_ID_alter(), with base form ID 'node_form', to alter
|
1105 |
* node forms for all node types.
|
1106 |
*
|
1107 |
* This hook, implemented by node modules, is called to retrieve the form
|
1108 |
* that is displayed to create or edit a node. This form is displayed at path
|
1109 |
* node/add/[node type] or node/[node ID]/edit.
|
1110 |
*
|
1111 |
* The submit and preview buttons, administrative and display controls, and
|
1112 |
* sections added by other modules (such as path settings, menu settings,
|
1113 |
* comment settings, and fields managed by the Field UI module) are
|
1114 |
* displayed automatically by the node module. This hook just needs to
|
1115 |
* return the node title and form editing fields specific to the node type.
|
1116 |
*
|
1117 |
* @param $node
|
1118 |
* The node being added or edited.
|
1119 |
* @param $form_state
|
1120 |
* The form state array.
|
1121 |
*
|
1122 |
* @return
|
1123 |
* An array containing the title and any custom form elements to be displayed
|
1124 |
* in the node editing form.
|
1125 |
*
|
1126 |
* @ingroup node_api_hooks
|
1127 |
*/
|
1128 |
function hook_form($node, &$form_state) { |
1129 |
$type = node_type_get_type($node); |
1130 |
|
1131 |
$form['title'] = array( |
1132 |
'#type' => 'textfield', |
1133 |
'#title' => check_plain($type->title_label), |
1134 |
'#default_value' => !empty($node->title) ? $node->title : '', |
1135 |
'#required' => TRUE, '#weight' => -5 |
1136 |
); |
1137 |
|
1138 |
$form['field1'] = array( |
1139 |
'#type' => 'textfield', |
1140 |
'#title' => t('Custom field'), |
1141 |
'#default_value' => $node->field1, |
1142 |
'#maxlength' => 127, |
1143 |
); |
1144 |
$form['selectbox'] = array( |
1145 |
'#type' => 'select', |
1146 |
'#title' => t('Select box'), |
1147 |
'#default_value' => $node->selectbox, |
1148 |
'#options' => array( |
1149 |
1 => 'Option A', |
1150 |
2 => 'Option B', |
1151 |
3 => 'Option C', |
1152 |
), |
1153 |
'#description' => t('Choose an option.'), |
1154 |
); |
1155 |
|
1156 |
return $form; |
1157 |
} |
1158 |
|
1159 |
/**
|
1160 |
* Respond to creation of a new node.
|
1161 |
*
|
1162 |
* This is a node-type-specific hook, which is invoked only for the node type
|
1163 |
* being affected. See
|
1164 |
* @link node_api_hooks Node API hooks @endlink for more information.
|
1165 |
*
|
1166 |
* Use hook_node_insert() to respond to node insertion of all node types.
|
1167 |
*
|
1168 |
* This hook is invoked from node_save() after the node is inserted into the
|
1169 |
* node table in the database, before field_attach_insert() is called, and
|
1170 |
* before hook_node_insert() is invoked.
|
1171 |
*
|
1172 |
* @param $node
|
1173 |
* The node that is being created.
|
1174 |
*
|
1175 |
* @ingroup node_api_hooks
|
1176 |
*/
|
1177 |
function hook_insert($node) { |
1178 |
db_insert('mytable')
|
1179 |
->fields(array(
|
1180 |
'nid' => $node->nid, |
1181 |
'extra' => $node->extra, |
1182 |
)) |
1183 |
->execute(); |
1184 |
} |
1185 |
|
1186 |
/**
|
1187 |
* Act on nodes being loaded from the database.
|
1188 |
*
|
1189 |
* This is a node-type-specific hook, which is invoked only for the node type
|
1190 |
* being affected. See
|
1191 |
* @link node_api_hooks Node API hooks @endlink for more information.
|
1192 |
*
|
1193 |
* Use hook_node_load() to respond to node load of all node types.
|
1194 |
*
|
1195 |
* This hook is invoked during node loading, which is handled by entity_load(),
|
1196 |
* via classes NodeController and DrupalDefaultEntityController. After the node
|
1197 |
* information is read from the database or the entity cache, hook_load() is
|
1198 |
* invoked on the node's content type module, then field_attach_node_revision()
|
1199 |
* or field_attach_load() is called, then hook_entity_load() is invoked on all
|
1200 |
* implementing modules, and finally hook_node_load() is invoked on all
|
1201 |
* implementing modules.
|
1202 |
*
|
1203 |
* This hook should only be used to add information that is not in the node or
|
1204 |
* node revisions table, not to replace information that is in these tables
|
1205 |
* (which could interfere with the entity cache). For performance reasons,
|
1206 |
* information for all available nodes should be loaded in a single query where
|
1207 |
* possible.
|
1208 |
*
|
1209 |
* @param $nodes
|
1210 |
* An array of the nodes being loaded, keyed by nid.
|
1211 |
*
|
1212 |
* For a detailed usage example, see node_example.module.
|
1213 |
*
|
1214 |
* @ingroup node_api_hooks
|
1215 |
*/
|
1216 |
function hook_load($nodes) { |
1217 |
$result = db_query('SELECT nid, foo FROM {mytable} WHERE nid IN (:nids)', array(':nids' => array_keys($nodes))); |
1218 |
foreach ($result as $record) { |
1219 |
$nodes[$record->nid]->foo = $record->foo; |
1220 |
} |
1221 |
} |
1222 |
|
1223 |
/**
|
1224 |
* Respond to updates to a node.
|
1225 |
*
|
1226 |
* This is a node-type-specific hook, which is invoked only for the node type
|
1227 |
* being affected. See
|
1228 |
* @link node_api_hooks Node API hooks @endlink for more information.
|
1229 |
*
|
1230 |
* Use hook_node_update() to respond to node update of all node types.
|
1231 |
*
|
1232 |
* This hook is invoked from node_save() after the node is updated in the
|
1233 |
* node table in the database, before field_attach_update() is called, and
|
1234 |
* before hook_node_update() is invoked.
|
1235 |
*
|
1236 |
* @param $node
|
1237 |
* The node that is being updated.
|
1238 |
*
|
1239 |
* @ingroup node_api_hooks
|
1240 |
*/
|
1241 |
function hook_update($node) { |
1242 |
db_update('mytable')
|
1243 |
->fields(array('extra' => $node->extra)) |
1244 |
->condition('nid', $node->nid) |
1245 |
->execute(); |
1246 |
} |
1247 |
|
1248 |
/**
|
1249 |
* Perform node validation before a node is created or updated.
|
1250 |
*
|
1251 |
* This is a node-type-specific hook, which is invoked only for the node type
|
1252 |
* being affected. See
|
1253 |
* @link node_api_hooks Node API hooks @endlink for more information.
|
1254 |
*
|
1255 |
* Use hook_node_validate() to respond to node validation of all node types.
|
1256 |
*
|
1257 |
* This hook is invoked from node_validate(), after a user has finished
|
1258 |
* editing the node and is previewing or submitting it. It is invoked at the end
|
1259 |
* of all the standard validation steps, and before hook_node_validate() is
|
1260 |
* invoked.
|
1261 |
*
|
1262 |
* To indicate a validation error, use form_set_error().
|
1263 |
*
|
1264 |
* Note: Changes made to the $node object within your hook implementation will
|
1265 |
* have no effect. The preferred method to change a node's content is to use
|
1266 |
* hook_node_presave() instead.
|
1267 |
*
|
1268 |
* @param $node
|
1269 |
* The node being validated.
|
1270 |
* @param $form
|
1271 |
* The form being used to edit the node.
|
1272 |
* @param $form_state
|
1273 |
* The form state array.
|
1274 |
*
|
1275 |
* @ingroup node_api_hooks
|
1276 |
*/
|
1277 |
function hook_validate($node, $form, &$form_state) { |
1278 |
if (isset($node->end) && isset($node->start)) { |
1279 |
if ($node->start > $node->end) { |
1280 |
form_set_error('time', t('An event may not end before it starts.')); |
1281 |
} |
1282 |
} |
1283 |
} |
1284 |
|
1285 |
/**
|
1286 |
* Display a node.
|
1287 |
*
|
1288 |
* This is a node-type-specific hook, which is invoked only for the node type
|
1289 |
* being affected. See
|
1290 |
* @link node_api_hooks Node API hooks @endlink for more information.
|
1291 |
*
|
1292 |
* Use hook_node_view() to respond to node view of all node types.
|
1293 |
*
|
1294 |
* This hook is invoked during node viewing after the node is fully loaded, so
|
1295 |
* that the node type module can define a custom method for display, or add to
|
1296 |
* the default display.
|
1297 |
*
|
1298 |
* @param $node
|
1299 |
* The node to be displayed, as returned by node_load().
|
1300 |
* @param $view_mode
|
1301 |
* View mode, e.g. 'full', 'teaser', ...
|
1302 |
* @return
|
1303 |
* The passed $node parameter should be modified as necessary and returned so
|
1304 |
* it can be properly presented. Nodes are prepared for display by assembling
|
1305 |
* a structured array, formatted as in the Form API, in $node->content. As
|
1306 |
* with Form API arrays, the #weight property can be used to control the
|
1307 |
* relative positions of added elements. After this hook is invoked,
|
1308 |
* node_view() calls field_attach_view() to add field views to $node->content,
|
1309 |
* and then invokes hook_node_view() and hook_node_view_alter(), so if you
|
1310 |
* want to affect the final view of the node, you might consider implementing
|
1311 |
* one of these hooks instead.
|
1312 |
*
|
1313 |
* @ingroup node_api_hooks
|
1314 |
*/
|
1315 |
function hook_view($node, $view_mode) { |
1316 |
if ($view_mode == 'full' && node_is_page($node)) { |
1317 |
$breadcrumb = array(); |
1318 |
$breadcrumb[] = l(t('Home'), NULL); |
1319 |
$breadcrumb[] = l(t('Example'), 'example'); |
1320 |
$breadcrumb[] = l($node->field1, 'example/' . $node->field1); |
1321 |
drupal_set_breadcrumb($breadcrumb);
|
1322 |
} |
1323 |
|
1324 |
$node->content['myfield'] = array( |
1325 |
'#markup' => theme('mymodule_myfield', $node->myfield), |
1326 |
'#weight' => 1, |
1327 |
); |
1328 |
|
1329 |
return $node; |
1330 |
} |
1331 |
|
1332 |
/**
|
1333 |
* @} End of "addtogroup hooks".
|
1334 |
*/
|