/[drupal]/contributions/modules/addnode/addnode.module
ViewVC logotype

Contents of /contributions/modules/addnode/addnode.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.3 - (show annotations) (download) (as text)
Wed Jul 9 15:43:40 2008 UTC (16 months, 2 weeks ago) by panis
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +448 -257 lines
File MIME type: text/x-php
refactored addnode - uses popup window to create nodes on the fly.
1 <?php
2 // $Id $
3
4 /**
5 * @file
6 * Extension of nodereference allows user to either select existing nodes
7 * or create new nodes via a popup window. Also lets user reorder the attached
8 * nodes as they are attached.
9 */
10
11
12 /**
13 * Implementation of hook_help
14 */
15 function addnode_help($section='')
16 {
17 $output = '';
18 switch ($section)
19 {
20 case "admin/help#addnode":
21 $output = '<p>' . t("Extension of nodereference allows user to either select existing nodes or create new nodes via a popup window. Also lets user reorder the attached nodes as they are attached.") . '</p>';
22 break;
23 }
24 return $output;
25 }
26
27 /**
28 * Implementation of hook_widget_info.
29 * Specifies the label and that it is a widget for the nodereference field type
30 */
31 function addnode_widget_info()
32 {
33 return array(
34 'addnode_select' => array(
35 'label' => 'AddNode List',
36 'field types' => array('nodereference'),
37 ),
38 );
39 }
40
41 /**
42 * Implementation of hook_widget
43 */
44 function addnode_widget($op, &$node, $field, &$items)
45 {
46 //need this module for the_nodereference_potential_references function.
47 include_once(drupal_get_path('module', 'content').'/nodereference.module');
48
49 if ($field['widget']['type'] == 'addnode_select')
50 {
51 switch ($op) {
52
53 //prepare hook load the node order from the database if available
54 //rearrange the nids in that sequence and return the list.
55 case 'prepare form values':
56
57 $items_transposed = content_transpose_array_rows_cols($items);
58 $nids = $items_transposed['nid'];
59 $order = db_result(db_query("SELECT weights FROM {addnode_order} WHERE nid=%d AND fieldname='%s'", $node->nid, $field['field_name']));
60
61 //if there is a curent list of nids.
62 if (is_array($nids)) {
63
64 //find out the order - order is stored as a string of nids.
65 $order = $order? array_keys(explode(',', $order), 0):array();
66
67 //new nids not already ordered are captured in the missing array.
68 $unordered = array();
69
70 //look at each nid and if it is in the ordered list keep it in the
71 //ordered list else collect it in the unordered array to append to the
72 //ordered list.
73 foreach ($nids as $nid) {
74 if (!array_key_exists($nid, $order)) {
75 $unordered[$nid] = 1;
76 }
77 else {
78 $order[$nid] = 1;
79 }
80 }
81
82 //filter will take out all the nids that we have not used.
83 $order = array_filter($order);
84
85 //this is the final list of nids - ordered ones preceeding
86 //the unordered ones.
87 $nids = $order + $unordered;
88 //only need the keys.
89 $nids = array_keys($nids);
90 }
91 else {
92 $nids = array();
93 }
94
95 //here is the new order containing the final set of nids.
96 $order = implode(',', $nids);
97
98 //pass this along to the form call
99 $items['default nids'] = $nids;
100 $items['node_order'] = $order;
101 break;
102
103 case 'form':
104 $form = array();
105 $fieldname=$field['field_name'];
106 $title=t($field['widget']['label']);
107
108 //gets the list of all potential nodes that could be referenced
109 $options = _nodereference_potential_references($field, true);
110 foreach ($options as $key => $value) {
111 $options[$key] = _nodereference_item($field, $value);
112 }
113
114 //string describing what can be added.
115 $typedesc = "";
116 $type_count=0; //counts up how many types there are
117 $type_list=array(); //list of the types
118
119 //If referenceable_types is not an array, give up.
120 if (!is_array($field['referenceable_types'])) {
121 return $form;
122 }
123
124 //add referenceable types to the $type_list array
125 foreach ($field['referenceable_types'] as $ref_type) {
126 if ($ref_type) {
127 $typedesc = $ref_type;
128 $type_count++;
129 $type_list[] = $ref_type;
130 }
131 }
132
133 //if there are no types available, give up.
134 if ($type_count==0) {
135 //@todo Need to display something explaining the problem.
136 $form[$fieldname]['error'] = array(
137 '#type' => 'markup',
138 '#title' => $title,
139 '#value' => '<div class="error">This field does not have any content types configured to be displayed. Please contact your administrator if you think you have reached this in error</div>',
140 );
141 return $form;
142 }
143
144 //converts the type name to a human readable one
145 $typedesc = node_get_types('type', $typedesc);
146 $typedesc = $typedesc->name;
147
148 //If there's more than one type available then we use the term 'item' to describe them
149 if ($type_count>1) {
150 $typedesc = "item";
151 }
152
153 //if this field supports multiple selections then the select list
154 //stays in the "to_" list else it is stored in the select identified
155 //by the fieldname itself.
156 if($field['multiple']) {
157 $output = theme('addnode_link', $type_list,'updateNewNodes', 'to_' . $fieldname, 'icon');
158 } else {
159 $output = theme('addnode_link', $type_list,'updateNewNodes', $fieldname, 'icon');
160 }
161
162 //create the link to create new nodes.
163 $new_link= "<b>$title:</b>";
164 $new_link.= t("Select !typedesc already available", array('!typedesc'=>"$typedesc"));
165 $new_link.= ' or click here to add a new one ' . $output .'<br>';
166
167 $form[$fieldname]['#tree'] = TRUE;
168 $form[$fieldname]['newnode'] = array(
169 '#type' => 'markup',
170 '#value' => $new_link,
171 );
172
173
174 //if multiple select is enabled then allow the user to move the
175 //selected items from one select box to another and reordered the
176 //selected items.
177 if ($field['multiple']) {
178
179 //take the list of all available items and make 2 lists from it
180 //one that is of the selected items (to_list) and the other one
181 //the available (from_list) items.
182 if( is_array($items['default nids'] )) {
183 foreach ($items['default nids'] as $nid) {
184 if(in_array($nid, array_keys($options))) {
185 $to_list[$nid] = $options[$nid];
186 $options[$nid] = 0;
187 }
188 }
189 $from_list = array_filter($options);
190 }
191 else {
192 $from_list = $options;
193 $to_list = array();
194 }
195
196 //cannot have any of the lists empty so send in a "none"
197 //option if the select list is empty
198 if(count($to_list) == 0) { $to_list[0] = 'None'; }
199 if(count($from_list) == 0) { $from_list[0] = 'None'; }
200
201 //markup to wrap the fields in a table.
202 $form[$fieldname]['t1'] = array(
203 '#type' => 'markup',
204 '#value' => '<table><tr><td valign="top">',
205 );
206
207 //select lists for available references that can be added
208 //note the #DANGEROUS_SKIP_CHECK flag below - this is a hidden
209 //feature in drupal to skip checking of select lists on a submit to
210 //make sure that the list options etc have not changed. Because we
211 //will be dynamically manipulating the select lists via javascript
212 //drupal will throw errors if this check is enabled.
213 $form[$fieldname]['from_nids'] = array(
214 '#type' => 'select',
215 '#title' => t('Available References'),
216 '#multiple' => $field['multiple'],
217 '#options' => $from_list,
218 '#required' => FALSE,
219 '#description' => $field['widget']['description'],
220 '#size' => 15,
221 '#weight' => $field['weight'],
222 '#DANGEROUS_SKIP_CHECK' => true,
223 '#attributes' => array(
224 'id' => "from_$fieldname",
225 ),
226 );
227
228 $form[$fieldname]['t2'] = array(
229 '#type' => 'markup',
230 '#value' => '</td><td valign="middle">',
231 );
232
233 $form[$fieldname]['add'] = array(
234 '#type' => 'markup',
235 '#value' => '<input type="button" onclick="addnode_add_item(\'' . $fieldname . '\');" value="&rarr;" class="faq_arrow"/><br />',
236 );
237 $form[$fieldname]['remove'] = array(
238 '#type' => 'markup',
239 '#value' => '<input type="button" onclick="addnode_remove_item(\'' . $fieldname . '\');" value="&larr;" class="faq_arrow"/><br />',
240 );
241
242 $form[$fieldname]['t3'] = array(
243 '#type' => 'markup',
244 '#value' => '</td><td valign="top">',
245 );
246
247 //select list contains the selected nodes. note comment on
248 //DANGEROUS_SKIP_CHECK above in the from_nids
249 $form[$fieldname]['to_nids'] = array(
250 '#type' => 'select',
251 '#title' => t('Currently Attached References'),
252 '#options' => $to_list,
253 '#required' => $field['required'],
254 '#description' => $field['widget']['description'],
255 '#size' => 15,
256 '#multiple' => TRUE,
257 '#weight' => $field['weight'],
258 '#DANGEROUS_SKIP_CHECK' => true,
259 '#attributes' => array(
260 'id' => "to_$fieldname",
261 'class'=> 'addnode-select',
262 ),
263 );
264
265 //the order of the nodes is stored in a hidden field updated
266 //by javascript right before the submit of the form.
267 $form[$fieldname]['nids'] = array(
268 '#type' => 'hidden',
269 '#attributes' => array('class' => 'addnode-order'),
270 '#default_value' => $items['node_order'],
271 );
272
273 //control buttons - buttons to move items from one list to the
274 //other and to rearrange the existing list.
275 $form[$fieldname]['move_up'] = array(
276 '#type' => 'markup',
277 '#value' => '<input type="button" onclick="addnode_move_item_up(\'' . $fieldname . '\');" value="&uarr;" class="faq_arrow"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
278 );
279 $form[$fieldname]['move_down'] = array(
280 '#type' => 'markup',
281 '#value' => '<input type="button" onclick="addnode_move_item_down(\'' . $fieldname . '\');" value="&darr;" class="faq_arrow"/><br />',
282 );
283 $form[$fieldname]['t4'] = array(
284 '#type' => 'markup',
285 '#value' => '</td></tr></table>',
286 );
287 }
288 else {
289 //single select field just display a ordinary select list.
290 $form[$fieldname]['nids'] = array(
291 '#type' => 'select',
292 '#title' => '',
293 '#multiple' => $field['multiple'],
294 '#options' => $options,
295 '#default_value' => $items['default nids'],
296 '#required' => $field['required'],
297 '#description' => $field['widget']['description'],
298 '#size' => 15,
299 '#weight' => $field['weight'],
300 '#attributes' => array(
301 'id' => "$fieldname",
302 ),
303 );
304 }
305
306 return $form;
307
308 case 'process form values':
309
310 //process the returned results and rearrange the data fields for
311 //processing by the CCJ module.
312 if ($field['multiple']) {
313 $node_order = $items['nids'];
314 $items['nids'] = explode(',', $node_order);
315
316 if (empty($items['nids'])) {
317 $items['nids'] = array(0 => '0');
318 }
319
320 $items = array_values(content_transpose_array_rows_cols(array('nid' => $items['nids'])));
321
322 //save the order of the items - delete any existing order and
323 //replace with a new one - this dispenses the check for existing order
324 //and an update or an insert otherwise..
325 db_query("DELETE FROM {addnode_order} WHERE nid=%d AND fieldname='%s'",
326 $node->nid, $field['field_name']);
327 db_query("INSERT INTO {addnode_order} (nid,fieldname,weights) VALUES (%d,'%s', '%s')", $node->nid, $field['field_name'], $node_order);
328
329 // Remove the widget's data representation so it isn't saved.
330 unset($items['nids']);
331 unset($items['from_nids']);
332 unset($items['to_nids']);
333 unset($node_order);
334 }
335 else {
336 $items[0]['nid'] = $items['nids'];
337 // Remove the widget's data representation so it isn't saved.
338 unset($items['nids']);
339 }
340 break;
341 case 'submit':
342 break;
343 }
344 }
345 }
346
347 function addnode_menu($may_cache) {
348
349 $items = array();
350 if ($may_cache) {
351 $items[] = array(
352 'path' => 'addnode/load',
353 'title' => t('Node Assist Thumbnails'),
354 'callback' => 'addnode_load',
355 'access' => user_access('access content'),
356 'type' => MENU_CALLBACK);
357 $items[] = array(
358 'path' => 'addnode/add',
359 'title' => t('Node Assist Create New'),
360 'callback' => 'addnode_add',
361 'access' => user_access('access content'),
362 'type' => MENU_CALLBACK);
363 $items[] = array(
364 'path' => 'admin/settings/addnode',
365 'title' => t('Node assist'),
366 'description' => t('Change settings for the Node assist module.'),
367 'callback' => 'drupal_get_form',
368 'callback arguments' => 'addnode_admin_settings',
369 'access' => user_access('administer site configuration'),
370 'type' => MENU_NORMAL_ITEM); // optional
371 }
372 else {
373 //load our javascript functions.
374 $path = drupal_get_path('module','addnode');
375 drupal_add_js($path . '/addnode.js');
376 drupal_add_css($path .'/addnode.css', 'module', 'all', TRUE);
377 drupal_add_js($path . '/thickbox.js');
378 drupal_add_css($path . '/thickbox.css');
379 }
380
381 return $items;
382 }
383
384 /**
385 * Theme for adding an image link underneath textareas
386 */
387 function theme_addnode_link($node_types, $callback_fn, $callback_arg, $link) {
388 $instance = $callback_arg;
389 $_SESSION['addnode'][$instance] = array();
390 $_SESSION['addnode'][$instance]['node_types'] = $node_types;
391 $_SESSION['addnode'][$instance]['callback_fn'] = $callback_fn;
392 $_SESSION['addnode'][$instance]['callback_arg'] = $callback_arg;
393 $_SESSION['addnode'][$instance]['nids'] = array();
394
395 $output = '<div class="addnode-button"><a class="thickbox addnode-link" id="addnode-link-'. $id .'" title="'. t('Add New Content') .'" href="'. url('addnode/load/'.$instance, 'TB_iframe=true&height=350&width=600') .'">';
396 $output .= ($link == 'icon') ? '<img src="'. base_path() . drupal_get_path('module', 'addnode') .'/newdocument.gif" border="0" alt="'. t('New') .'" />' : t('New');
397 $output .= '</a></div>';
398 return $output;
399 }
400
401 /**
402 * Implementation of hook_nodeapi().
403 *
404 * - Keep track of where nids are used.
405 * - Catch nids of recently created nodes.
406 */
407 function addnode_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
408 switch ($op) {
409 case 'insert':
410 case 'update':
411 // Put nid into a global if this node is created with addnode:
412 if (arg(0) == 'addnode') {
413 $instance = arg(2);
414 $_SESSION['addnode'][$instance]['nids'][$node->nid] = $node->title;
415 }
416 break;
417 case 'delete':
418 break;
419 }
420 }
421
422
423 /**
424 * create an empty addnode form.
425 **/
426 function addnode_add($instance, $node_type='') {
427 global $user;
428
429 if($node_type == '') {
430 $output .= t('System Error: Please notify administrator');
431 }
432 else if (node_access('create',$node_type)) {
433 // Define an empty node and fetch an image node form:
434 $node = array('uid' => $user->uid,
435 'name' => $user->name,
436 'type' => $node_type,
437 'addnode_instance' => $instance);
438 $output .= drupal_get_form($node_type . '_node_form', $node);
439 }
440 else {
441 $output = t('You do not have access to create a: '). $node_type;
442 }
443 print theme('addnode_page', $output, array('id' => 'addnode_upload', 'class' => 'addnode'));
444 }
445
446 /**
447 * Implementation of hook_alter().
448 * Add a second submit callback which alters the redirect we do not want
449 * the addnode form to redirect to the newly created node.
450 */
451 function addnode_form_alter($form_id, &$form) {
452 if (arg(0) != 'addnode') return;
453 if(isset($form['type'])) {
454 if($form['type']['#value'].'_node_form' == $form_id) {
455 if (!is_array($form['#submit'])) { $form['#submit'] = array(); }
456 $form['#submit'] += array('addnode_node_form_submit' => array($form));
457 }
458 }
459 }
460
461 /**
462 * A second submit callback for node_form.
463 * Change the redirect from node/$nid to addnode/properties/$nid.
464 */
465 function addnode_node_form_submit($form_id, $form_values) {
466 $instance = arg(2);
467 // Get the nid of the newly created node (caught by addnode_nodeapi):
468 $nids = array_keys($_SESSION['addnode'][$instance]['nids']);
469 $nid = end($nids);
470 $title = $_SESSION['addnode'][$instance]['nids'][$nid];
471 drupal_goto("addnode/load/$instance/$nid/$title");
472 }
473
474 /**
475 * available node types
476 */
477 function addnode_nodereference_types() {
478 return $_SESSION['addnode']['node_types'];
479 }
480
481 /**
482 * Load the thumbnail display pane
483 *
484 * Grabs all images from image.module and loads the thumbnails.
485 */
486 function addnode_load($instance, $nid='',$title='') {
487 global $user;
488
489 $node_types = $_SESSION['addnode'][$instance]['node_types'];
490
491 if(count($node_types) > 1) {
492 /* show list of node types to create. */
493 $output = $nid? t('Add Another:'):t('Add Content:');
494 $output .= '<ul>';
495 foreach ($node_types as $n) {
496 if( node_access('create', $n) ) {
497 $output .= '<li>' . l($n, "addnode/add/$instance/$n") . '</li>';
498 }
499 }
500 $output .= '</ul>';
501 }
502 else {
503 $n = $node_types[0];
504 if($nid) {
505 $output = t('Add Another') . ' ' . l($n, "addnode/add/$instance/$n");
506 }
507 else {
508 /* go to node add form of only type. */
509 drupal_goto("addnode/add/$instance/$n");
510 }
511 }
512
513 $args[] = $_SESSION['addnode'][$instance]['callback_fn'];
514 $args[] = $_SESSION['addnode'][$instance]['callback_arg'];
515 $args[] = $nid;
516 $args[] = $title;
517
518 array_walk($args,'_quote');
519 $callbackargs = implode(',',$args);
520
521 print theme('addnode_page', $output, array('id' => 'addnode_load', 'onload' => 'addnode_callback('.$callbackargs.');', 'class' => 'addnode'));
522 }
523
524 function _quote(&$item, $key) {
525 $item = "'$item'";
526 }
527
528 // -----------------------------------------------------------------------
529 // Theme Functions
530 // -------------------------------------------------------------------------
531 function theme_addnode_page($content, $attributes = NULL) {
532 $output .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'."\n";
533 $output .= '<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">'."\n";
534 //$output = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">'."\n";
535 //$output .= "<html>\n";
536 $output .= "<head>\n";
537 $output .= " <title>$title</title>\n";
538 $output .= drupal_get_html_head();
539 $output .= drupal_get_js();
540 $output .= drupal_get_css();
541 $path = drupal_get_path('module', 'addnode') .'/addnode.css';
542 $output .= "<style type=\"text/css\" media=\"{$media}\">@import \"" . base_path() . $path ."\";</style>\n";
543
544 $output .= "</head>\n";
545 $output .= "<body" . drupal_attributes($attributes) .">\n";
546
547 $output .= theme_status_messages();
548
549 $output .= "\n<!-- begin content -->\n";
550 $output .= $content;
551 $output .= "\n<!-- end content -->\n";
552 $output .= '</body>';
553 $output .= '</html>';
554 return $output;
555 }

  ViewVC Help
Powered by ViewVC 1.1.2