/[drupal]/contributions/modules/cck/nodereference.module
ViewVC logotype

Contents of /contributions/modules/cck/nodereference.module

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


Revision 1.121 - (hide annotations) (download) (as text)
Tue Mar 25 13:12:41 2008 UTC (20 months ago) by karens
Branch: MAIN
Changes since 1.120: +7 -14 lines
File MIME type: text/x-php
Re-name fields to use Views 1 naming like field_text_value instead of field_text to make updates easier, and alter content.views_convert.inc to match.

Add default filters for all fields, and update fields to switch from string or numeric filters to 'in' operators if there are lists of allowed values.

Add helper function to return Views table name to make it easier to change the tablename in the future, like if we find a way to avoid the need to alias each field as its own table.
1 JonBob 1.1 <?php
2 karens 1.121 // $Id: nodereference.module,v 1.120 2008/03/24 01:59:03 yched Exp $
3 JonBob 1.1
4     /**
5     * @file
6 JonBob 1.2 * Defines a field type for referencing one node from another.
7 JonBob 1.1 */
8    
9     /**
10 JonBob 1.2 * Implementation of hook_menu().
11     */
12 yched 1.57 function nodereference_menu() {
13 JonBob 1.2 $items = array();
14 yched 1.57 $items['nodereference/autocomplete'] = array(
15     'title' => t('Nodereference autocomplete'),
16     'page callback' => 'nodereference_autocomplete',
17     'access arguments' => array('access content'),
18     'type' => MENU_CALLBACK
19     );
20 JonBob 1.2 return $items;
21     }
22    
23     /**
24 karens 1.66 * Implementation of hook_theme().
25     */
26     function nodereference_theme() {
27     return array(
28 karens 1.69 'nodereference_item_simple' => array(
29 yched 1.70 'arguments' => array('item' => NULL),
30     ),
31 karens 1.69 'nodereference_item_advanced' => array(
32 yched 1.70 'arguments' => array('item' => NULL, 'view' => NULL),
33     ),
34 karens 1.88 'nodereference_select' => array(
35     'arguments' => array('element' => NULL),
36     ),
37     'nodereference_autocomplete' => array(
38     'arguments' => array('element' => NULL),
39     ),
40 yched 1.106 'nodereference_formatter_default' => array(
41     'arguments' => array('element'),
42     ),
43     'nodereference_formatter_full' => array(
44     'arguments' => array('element'),
45     'function' => 'theme_nodereference_formatter_full_teaser',
46     ),
47     'nodereference_formatter_teaser' => array(
48     'arguments' => array('element'),
49     'function' => 'theme_nodereference_formatter_full_teaser',
50     ),
51 karens 1.66 );
52     }
53    
54     /**
55 JonBob 1.1 * Implementation of hook_field_info().
56 karens 1.75 *
57     * Here we indicate that the content module will use its default
58     * handling for the view of this field.
59     *
60     * Callbacks can be omitted if default handing is used.
61     * They're included here just so this module can be used
62     * as an example for custom modules that might do things
63     * differently.
64 JonBob 1.1 */
65     function nodereference_field_info() {
66     return array(
67 karens 1.75 'nodereference' => array(
68 yched 1.117 'label' => t('Node Reference'),
69 karens 1.91 'description' => t('Store the id of a related node as an integer value.'),
70 karens 1.75 'callbacks' => array(
71     'tables' => CONTENT_CALLBACK_DEFAULT,
72     'arguments' => CONTENT_CALLBACK_DEFAULT,
73     ),
74     ),
75 JonBob 1.1 );
76     }
77    
78     /**
79     * Implementation of hook_field_settings().
80     */
81 JonBob 1.8 function nodereference_field_settings($op, $field) {
82 JonBob 1.1 switch ($op) {
83     case 'form':
84     $form = array();
85 JonBob 1.7 $form['referenceable_types'] = array(
86     '#type' => 'checkboxes',
87     '#title' => t('Content types that can be referenced'),
88     '#multiple' => TRUE,
89 karens 1.92 '#default_value' => is_array($field['referenceable_types']) ? $field['referenceable_types'] : array(),
90 karens 1.37 '#options' => node_get_types('names'),
91 JonBob 1.7 );
92 karens 1.115 if (module_exists('views')) {
93     $views = array('--' => '--');
94     $all_views = views_get_all_views();
95     foreach ($all_views as $view) {
96     $views[t('Existing Views')][$view->name] = $view->name;
97     }
98    
99     if (count($views) > 1) {
100     $form['advanced'] = array(
101     '#type' => 'fieldset',
102     '#title' => t('Advanced - Nodes that can be referenced (View)'),
103     '#collapsible' => TRUE,
104     '#collapsed' => !isset($field['advanced_view']) || $field['advanced_view'] == '--',
105     );
106     $form['advanced']['advanced_view'] = array(
107     '#type' => 'select',
108     '#title' => t('View'),
109     '#options' => $views,
110     '#default_value' => isset($field['advanced_view']) ? $field['advanced_view'] : '--',
111     '#description' => t('Choose the "Views module" view that selects the nodes that can be referenced.<br>Note :<ul><li>This will discard the "Content types" settings above. Use the view\'s "filters" section instead.</li><li>Use the view\'s "fields" section to display additional informations about candidate nodes on node creation/edition form.</li><li>Use the view\'s "sort criteria" section to determine the order in which candidate nodes will be displayed.</li></ul>'),
112     );
113     $form['advanced']['advanced_view_args'] = array(
114     '#type' => 'textfield',
115     '#title' => t('View arguments'),
116     '#default_value' => isset($field['advanced_view_args']) ? $field['advanced_view_args'] : '',
117     '#required' => FALSE,
118     '#description' => t('Provide a comma separated list of arguments to pass to the view.'),
119     );
120     }
121     }
122 JonBob 1.1 return $form;
123    
124     case 'save':
125 karens 1.35 $settings = array('referenceable_types');
126 karens 1.115 if (module_exists('views')) {
127     $settings[] = 'advanced_view';
128     $settings[] = 'advanced_view_args';
129     }
130 karens 1.35 return $settings;
131 JonBob 1.17
132 JonBob 1.14 case 'database columns':
133     $columns = array(
134 karens 1.83 'nid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => FALSE),
135 yched 1.72 );
136     return $columns;
137    
138 yched 1.113 case 'views data':
139     $data = content_views_field_views_data($field);
140     $db_info = content_database_info($field);
141 karens 1.121 $table_alias = content_views_tablename($field);
142    
143     // Swap the filter handler to the 'in' operator.
144     $data[$table_alias][$field['field_name'] .'_nid']['filter']['handler'] = 'views_handler_filter_in_operator_content';
145 yched 1.113
146 karens 1.121 // Add a relationship for related node.
147     $data[$table_alias][$field['field_name'] .'_nid']['relationship'] = array(
148 karens 1.118 'base' => 'node',
149 yched 1.113 'field' => $db_info['columns']['nid']['column'],
150     'handler' => 'views_handler_relationship',
151     );
152     return $data;
153 JonBob 1.1 }
154     }
155    
156     /**
157     * Implementation of hook_field().
158     */
159 karens 1.45 function nodereference_field($op, &$node, $field, &$items, $teaser, $page) {
160     switch ($op) {
161     case 'validate':
162 yched 1.48 $refs = _nodereference_potential_references($field, TRUE);
163 karens 1.96 foreach ($items as $delta => $item) {
164 karens 1.69 if (is_array($item) && !empty($item['error_field'])) {
165     $error_field = $item['error_field'];
166     unset($item['error_field']);
167     if (!empty($item['nid'])) {
168     if (!in_array($item['nid'], array_keys($refs))) {
169     form_set_error($error_field, t('%name : This post can\'t be referenced.', array('%name' => t($field['widget']['label']))));
170     }
171 yched 1.49 }
172 karens 1.45 }
173     }
174 karens 1.95 return $items;
175 karens 1.81 }
176     }
177 karens 1.75
178 karens 1.81 /**
179     * Implementation of hook_content_is_empty().
180     */
181 yched 1.84 function nodereference_content_is_empty($item, $field) {
182 karens 1.81 if (empty($item['nid'])) {
183     return TRUE;
184 karens 1.45 }
185 karens 1.81 return FALSE;
186 karens 1.45 }
187 JonBob 1.1
188 JonBob 1.23 /**
189 karens 1.34 * Implementation of hook_field_formatter_info().
190 JonBob 1.23 */
191 karens 1.34 function nodereference_field_formatter_info() {
192     return array(
193     'default' => array(
194 yched 1.117 'label' => t('Title (link)'),
195 karens 1.34 'field types' => array('nodereference'),
196 karens 1.109 'multiple values' => CONTENT_HANDLE_CORE,
197 karens 1.34 ),
198     'plain' => array(
199 yched 1.117 'label' => t('Title (no link)'),
200 karens 1.34 'field types' => array('nodereference'),
201 karens 1.109 'multiple values' => CONTENT_HANDLE_CORE,
202 karens 1.34 ),
203 yched 1.62 'full' => array(
204 yched 1.117 'label' => t('Full node'),
205 yched 1.62 'field types' => array('nodereference'),
206 karens 1.109 'multiple values' => CONTENT_HANDLE_CORE,
207 yched 1.62 ),
208     'teaser' => array(
209 yched 1.117 'label' => t('Teaser'),
210 yched 1.62 'field types' => array('nodereference'),
211 karens 1.109 'multiple values' => CONTENT_HANDLE_CORE,
212 yched 1.62 ),
213 karens 1.34 );
214     }
215    
216     /**
217 yched 1.106 * Theme function for 'default' nodereference field formatter.
218 karens 1.34 */
219 yched 1.106 function theme_nodereference_formatter_default($element) {
220     $output = '';
221 yched 1.120 if (!empty($element['#item']['nid']) && is_numeric($element['#item']['nid']) && ($title = _nodereference_titles($element['#item']['nid']))) {
222     $output = l($title, 'node/'. $element['#item']['nid']);
223 yched 1.106 }
224     return $output;
225     }
226 yched 1.58
227 yched 1.106 /**
228     * Theme function for 'plain' nodereference field formatter.
229     */
230     function theme_nodereference_formatter_plain($element) {
231     $output = '';
232 yched 1.120 if (!empty($element['#item']['nid']) && is_numeric($element['#item']['nid']) && ($title = _nodereference_titles($element['#item']['nid']))) {
233     $output = check_plain($title);
234 JonBob 1.25 }
235 yched 1.106 return $output;
236     }
237 karens 1.34
238 yched 1.106 /**
239     * Proxy theme function for 'full' and 'teaser' nodereference field formatters.
240     */
241     function theme_nodereference_formatter_full_teaser($element) {
242     static $recursion_queue = array();
243     $output = '';
244     if (!empty($element['#item']['nid']) && is_numeric($element['#item']['nid'])) {
245 yched 1.67 // If no 'referencing node' is set, we are starting a new 'reference thread'
246     if (!isset($node->referencing_node)) {
247     $recursion_queue = array();
248     }
249     $recursion_queue[] = $node->nid;
250 yched 1.106 if (in_array($element['#item']['nid'], $recursion_queue)) {
251 yched 1.67 // Prevent infinite recursion caused by reference cycles :
252     // if the node has already been rendered earlier in this 'thread',
253     // we fall back to 'default' (node title) formatter.
254 yched 1.106 return theme('nodereference_formatter_default', $element);
255 yched 1.67 }
256 yched 1.119 if ($referenced_node = node_load($element['#item']['nid'])) {
257     $referenced_node->referencing_node = $node;
258     $referenced_node->referencing_field = $field;
259     _nodereference_titles($element['#item']['nid'], $referenced_node->title);
260     $output = node_view($referenced_node, $element['#formatter'] == 'teaser');
261     }
262 yched 1.62 }
263 yched 1.106 return $output;
264     }
265 yched 1.62
266 yched 1.106 /**
267     * Helper function for formatters.
268     *
269     * Store node titles collected in the curent request.
270     */
271     function _nodereference_titles($nid, $known_title = NULL) {
272     static $titles = array();
273     if (!isset($titles[$nid])) {
274     $title = $known_title ? $known_title : db_result(db_query("SELECT title FROM {node} WHERE nid=%d", $nid));
275     $titles[$nid] = $title ? $title : '';
276 JonBob 1.7 }
277 yched 1.106 return $titles[$nid];
278 JonBob 1.7 }
279    
280     /**
281     * Implementation of hook_widget_info().
282 karens 1.75 *
283     * We need custom handling of multiple values for the nodereference_select
284     * widget because we need to combine them into a options list rather
285     * than display multiple elements.
286     *
287     * We will use the content module's default handling for default value.
288     *
289     * Callbacks can be omitted if default handing is used.
290     * They're included here just so this module can be used
291     * as an example for custom modules that might do things
292     * differently.
293 JonBob 1.7 */
294     function nodereference_widget_info() {
295     return array(
296     'nodereference_select' => array(
297 yched 1.117 'label' => t('Select List'),
298 JonBob 1.7 'field types' => array('nodereference'),
299 karens 1.78 'multiple values' => CONTENT_HANDLE_MODULE,
300 karens 1.75 'callbacks' => array(
301     'default value' => CONTENT_CALLBACK_DEFAULT,
302 yched 1.117 ),
303 JonBob 1.7 ),
304     'nodereference_autocomplete' => array(
305 yched 1.117 'label' => t('Autocomplete Text Field'),
306 JonBob 1.7 'field types' => array('nodereference'),
307 karens 1.78 'multiple values' => CONTENT_HANDLE_CORE,
308 karens 1.75 'callbacks' => array(
309     'default value' => CONTENT_CALLBACK_DEFAULT,
310 yched 1.117 ),
311 JonBob 1.7 ),
312     );
313     }
314    
315     /**
316 karens 1.88 * Implementation of FAPI hook_elements().
317     *
318     * Any FAPI callbacks needed for individual widgets can be declared here,
319     * and the element will be passed to those callbacks for processing.
320     *
321     * Drupal will automatically theme the element using a theme with
322     * the same name as the hook_elements key.
323     *
324     * Autocomplete_path is not used by text_widget but other widgets can use it
325     * (see nodereference and userreference).
326     */
327     function nodereference_elements() {
328     return array(
329     'nodereference_select' => array(
330     '#input' => TRUE,
331     '#columns' => array('uid'), '#delta' => 0,
332     '#process' => array('nodereference_select_process'),
333     ),
334     'nodereference_autocomplete' => array(
335     '#input' => TRUE,
336     '#columns' => array('name'), '#delta' => 0,
337     '#process' => array('nodereference_autocomplete_process'),
338     '#autocomplete_path' => FALSE,
339     ),
340     );
341     }
342    
343     /**
344 JonBob 1.7 * Implementation of hook_widget().
345 karens 1.75 *
346     * Attach a single form element to the form. It will be built out and
347     * validated in the callback(s) listed in hook_elements. We build it
348     * out in the callbacks rather than here in hook_widget so it can be
349     * plugged into any module that can provide it with valid
350     * $field information.
351     *
352     * Content module will set the weight, field name and delta values
353     * for each form element. This is a change from earlier CCK versions
354     * where the widget managed its own multiple values.
355     *
356     * If there are multiple values for this field, the content module will
357     * call this function as many times as needed.
358     *
359     * @param $form
360     * the entire form array, $form['#node'] holds node information
361     * @param $form_state
362     * the form_state, $form_state['values'][$field['field_name']]
363     * holds the field's form values.
364     * @param $field
365     * the field array
366     * @param $items
367     * array of default values for this field
368     * @param $delta
369     * the order of this item in the array of subelements (0, 1, 2, etc)
370     *
371     * @return
372     * the form item for a single element for this field
373     */
374     function nodereference_widget(&$form, &$form_state, $field, $items, $delta = 0) {
375     switch ($field['widget']['type']) {
376     case 'nodereference_select':
377     $element = array(
378 karens 1.88 '#type' => 'nodereference_select',
379 karens 1.75 '#default_value' => $items,
380     );
381     break;
382 karens 1.34
383 karens 1.75 case 'nodereference_autocomplete':
384     $element = array(
385 karens 1.88 '#type' => 'nodereference_autocomplete',
386 karens 1.75 '#default_value' => isset($items[$delta]) ? $items[$delta] : NULL,
387     '#value_callback' => 'nodereference_autocomplete_value',
388     );
389     break;
390     }
391     return $element;
392     }
393 yched 1.40
394 karens 1.75 /**
395     * Value for a nodereference autocomplete element.
396     *
397     * Substitute in the node title for the node nid.
398     */
399     function nodereference_autocomplete_value($element, $edit = FALSE) {
400 karens 1.100 $field_key = $element['#columns'][0];
401     if (!empty($element['#default_value'][$field_key])) {
402     $nid = $element['#default_value'][$field_key];
403     $value = db_result(db_query(db_rewrite_sql('SELECT n.title FROM {node} n WHERE n.nid = %d'), $nid));
404     $value .= ' [nid:'. $nid .']';
405     return array($field_key => $value);
406 JonBob 1.14 }
407 karens 1.100 return array($field_key => NULL);
408 karens 1.75 }
409 JonBob 1.18
410 karens 1.88 /**
411     * Process an individual element.
412     *
413     * Build the form element. When creating a form using FAPI #process,
414     * note that $element['#value'] is already set.
415     *
416 karens 1.90 * The $fields array is in $form['#field_info'][$element['#field_name']].
417 karens 1.88 */
418     function nodereference_select_process($element, $edit, $form_state, $form) {
419     // The nodereference_select widget doesn't need to create its own
420     // element, it can wrap around the optionwidgets_select element.
421     // Add a validation step where the value can be unwrapped.
422     $field_key = $element['#columns'][0];
423     $element[$field_key] = array(
424     '#type' => 'optionwidgets_select',
425 karens 1.97 '#default_value' => isset($element['#value']) ? $element['#value'] : '',
426 karens 1.114 '#element_validate' => array('optionwidgets_validate', 'nodereference_select_validate'),
427 karens 1.94
428     // The following values were set by the content module and need
429     // to be passed down to the nested element.
430 karens 1.88 '#field_name' => $element['#field_name'],
431     '#delta' => $element['#delta'],
432     '#columns' => $element['#columns'],
433 karens 1.94 '#title' => $element['#title'],
434 yched 1.110 '#required' => $element['#required'],
435 yched 1.107 '#description' => $element['#description'],
436 karens 1.88 );
437     return $element;
438     }
439    
440     /**
441     * Process an individual element.
442     *
443     * Build the form element. When creating a form using FAPI #process,
444     * note that $element['#value'] is already set.
445     *
446     */
447     function nodereference_autocomplete_process($element, $edit, $form_state, $form) {
448     // The nodereference autocomplete widget doesn't need to create its own
449     // element, it can wrap around the text_textfield element and add an autocomplete
450     // path and some extra processing to it.
451     // Add a validation step where the value can be unwrapped.
452     $field_key = $element['#columns'][0];
453    
454     $element[$field_key] = array(
455     '#type' => 'text_textfield',
456 karens 1.98 '#default_value' => isset($element['#value']) ? $element['#value'] : '',
457 karens 1.101 '#autocomplete_path' => 'nodereference/autocomplete/'. $element['#field_name'],
458 karens 1.88 '#element_validate' => array('nodereference_autocomplete_validate'),
459 karens 1.94
460     // The following values were set by the content module and need
461     // to be passed down to the nested element.
462 karens 1.88 '#field_name' => $element['#field_name'],
463     '#delta' => $element['#delta'],
464     '#columns' => $element['#columns'],
465 karens 1.94 '#title' => $element['#title'],
466 yched 1.110 '#required' => $element['#required'],
467 yched 1.107 '#description' => $element['#description'],
468 karens 1.88 );
469     return $element;
470     }
471    
472     /**
473 karens 1.100 * Validate an select element.
474 karens 1.88 *
475     * Remove the wrapper layer and set the right element's value.
476 karens 1.100 */
477     function nodereference_select_validate($element, &$form_state) {
478 karens 1.103 $field_key = $element['#columns'][0];
479 karens 1.114 array_pop($element['#parents']);
480     form_set_value($element, $form_state['values'][$element['#field_name']][$field_key], $form_state);
481 karens 1.88 }
482    
483     /**
484     * Validate an autocomplete element.
485     *
486     * Remove the wrapper layer and set the right element's value.
487     */
488     function nodereference_autocomplete_validate($element, &$form_state) {
489 karens 1.87 $field_name = $element['#field_name'];
490 karens 1.93 $field = content_fields($field_name);
491 karens 1.75 $field_key = $element['#columns'][0];
492 karens 1.93 $delta = $element['#delta'];
493 karens 1.75 $value = $element['#value'][$field_key];
494 karens 1.99 $nid = NULL;
495 karens 1.75 if (!empty($value)) {
496     preg_match('/^(?:\s*|(.*) )?\[\s*nid\s*:\s*(\d+)\s*\]$/', $value, $matches);
497     if (!empty($matches)) {
498     // explicit nid
499     list(, $title, $nid) = $matches;
500     if (!empty($title) && ($n = node_load($nid)) && $title != $n->title) {
501 karens 1.88 form_set_error($element[$field_key], t('%name : Title mismatch. Please check your selection.'), array('%name' => t($element[$field_key]['#title'])));
502 karens 1.75 }
503     }
504     else {
505     // no explicit nid
506     // TODO :
507     // the best thing would be to present the user with an additional form,
508     // allowing the user to choose between valid candidates with the same title
509     // ATM, we pick the first matching candidate...
510     $nids = _nodereference_potential_references($field, FALSE, $value, TRUE);
511     $nid = (!empty($nids)) ? array_shift(array_keys($nids)) : 0;
512     }
513 JonBob 1.1 }
514 karens 1.99 form_set_value($element, $nid, $form_state);
515 karens 1.75 return $element;
516     }
517    
518     /**
519     * Implementation of hook_allowed_values().
520     */
521     function nodereference_allowed_values($field) {
522     $options = _nodereference_potential_references($field, TRUE);
523     foreach ($options as $key => $value) {
524     $options[$key] = _nodereference_item($field, $value);
525     }
526     if (!$field['required']) {
527 yched 1.102 $options = array(0 => '<'. t('none') .'>') + $options;
528 karens 1.75 }
529     return $options;
530 JonBob 1.1 }
531    
532     /**
533 yched 1.102 * Fetch an array of all candidate referenced nodes,
534     * for use in presenting the selection form to the user.
535 JonBob 1.1 */
536 karens 1.35 function _nodereference_potential_references($field, $return_full_nodes = FALSE, $string = '', $exact_string = false) {
537 karens 1.116 // TODO Once filtering by title is working, get rid of "empty($string)" constraint to use this with autocomplete.
538     if (empty($string) && module_exists('views') && isset($field['advanced_view']) && $field['advanced_view'] != '--' && ($view = views_get_view($field['advanced_view']))) {
539 karens 1.115 // advanced field : referenceable nodes defined by a view
540     // let views.module build the query
541    
542 karens 1.116 $view->init();
543    
544     // TODO is this the right way to do this?
545     // make sure the fields get included in the query
546     $view->set_display('page');
547     $view->display['page']->style_plugin = 'list';
548 karens 1.115
549     // arguments for the view
550 karens 1.116 if (isset($field['advanced_view_args'])) {
551 karens 1.115 // TODO: Support Tokens using token.module ?
552 karens 1.116 $view_args = array();
553     $view_args = array_map('trim', explode(',', $field['advanced_view_args']));
554     $view->set_arguments($view_args);
555     }
556 karens 1.115
557 karens 1.116 // TODO Filtering by title is not yet working in Views 2, can't do this yet??
558 karens 1.115 //if (isset($string)) {
559 karens 1.116 // views_view_add_filter($view, 'node', 'title', $exact_string ? '=' : 'contains', $string, null);
560 karens 1.115 //}
561    
562     // we do need title field, so add it if not present (unlikely, but...)
563     //$has_title = array_reduce($view->field, create_function('$a, $b', 'return ($b["field"] == "title") || $a;'), false);
564     //if (!$has_title) {
565     // views_view_add_field($view, 'node', 'title', '');
566     //}
567     //views_load_cache();
568     //views_sanitize_view($view);
569    
570     // make sure the query is not cached
571     $view->is_cacheable = FALSE;
572 karens 1.116
573 karens 1.115 $view->execute();
574     $options = array();
575     foreach ($view->result as $row) {
576     foreach ($view->field as $field) {
577     if (!empty($field['handler']) && is_object($field['handler'])) {
578     $options[$row->nid][] = theme('views_view_field', $view, $field, $row);
579     }
580     }
581     }
582     return $options;
583     }
584     else {
585 karens 1.35 // standard field : referenceable nodes defined by content types
586     // build the appropriate query
587     $related_types = array();
588     $args = array();
589    
590 karens 1.92 if (is_array($field['referenceable_types'])) {
591 karens 1.35 foreach ($field['referenceable_types'] as $related_type) {
592     if ($related_type) {
593 yched 1.64 $related_types[] = " n.type = '%s'";
594 karens 1.35 $args[] = $related_type;
595     }
596 JonBob 1.33 }
597 JonBob 1.1 }
598    
599 karens 1.35 $related_clause = implode(' OR ', $related_types);
600    
601     if (!count($related_types)) {
602     return array();
603     }
604    
605     if (isset($string)) {
606 yched 1.64 $string_clause = $exact_string ? " AND n.title = '%s'" : " AND n.title LIKE '%%%s%'";
607 karens 1.35 $related_clause = "(". $related_clause .")". $string_clause;
608     $args[] = $string;
609     }
610 JonBob 1.1
611 karens 1.35 $result = db_query(db_rewrite_sql("SELECT n.nid, n.title AS node_title, n.type AS node_type FROM {node} n WHERE ". $related_clause ." ORDER BY n.title, n.type"), $args);
612 karens 1.115 }
613 JonBob 1.1
614     $rows = array();
615    
616     while ($node = db_fetch_object($result)) {
617 JonBob 1.6 if ($return_full_nodes) {
618 JonBob 1.3 $rows[$node->nid] = $node;
619 JonBob 1.6 }
620     else {
621 karens 1.35 $rows[$node->nid] = $node->node_title;
622 JonBob 1.3 }
623 karens 1.105 }
624 JonBob 1.1
625     return $rows;
626     }
627 JonBob 1.2
628     /**
629     * Retrieve a pipe delimited string of autocomplete suggestions
630     */
631     function nodereference_autocomplete($field_name, $string = '') {
632 JonBob 1.28 $fields = content_fields();
633 JonBob 1.2 $field = $fields[$field_name];
634 unconed 1.15 $matches = array();
635 JonBob 1.2
636 karens 1.35 foreach (_nodereference_potential_references($field, TRUE, $string) as $row) {
637 karens 1.37 $matches[$row->node_title .' [nid:'. $row->nid .']'] = _nodereference_item($field, $row, TRUE);
638 karens 1.35 }
639 karens 1.77 drupal_json($matches);
640 karens 1.35 }
641    
642 yched 1.112 function _nodereference_item($field, $item, $html = FALSE) {
643 karens 1.115 if (module_exists('views') && isset($field['advanced_view']) && $field['advanced_view'] != '--' && ($view = views_get_view($field['advanced_view']))) {
644     $field_names = array();
645     foreach ($view->field as $name => $viewfield) {
646     $field_names[] = $name;
647     }
648     $output = theme('nodereference_item_advanced', $item, $field_names, $view);
649     if (!$html) {
650     // Views theming runs check_plain (htmlentities) on the values.
651     // We reverse that with html_entity_decode.
652     $output = html_entity_decode(strip_tags($output), ENT_QUOTES);
653     }
654     }
655     else {
656 karens 1.35 $output = theme('nodereference_item_simple', $item);
657 yched 1.112 $output = $html ? check_plain($output) : $output;
658 karens 1.115 }
659 karens 1.35 return $output;
660     }
661    
662 karens 1.115 function theme_nodereference_item_advanced($item, $field_names, $view) {
663 karens 1.35 $item_fields = array();
664 karens 1.115 foreach ($item as $delta => $value) {
665 karens 1.35 // remove link tags (ex : for node titles)
666     $value = preg_replace('/<a[^>]*>(.*)<\/a>/iU', '$1', $value);
667     if (!empty($value)) {
668 karens 1.115 $item_fields[] = "<span class='view-field view-data-$field_names[$delta]'>$value</span>";;
669 karens 1.35 }
670     }
671     $output = implode(' - ', $item_fields);
672     $output = "<span class='view-item view-item-$view->name'>$output</span>";
673     return $output;
674     }
675 JonBob 1.2
676 karens 1.35 function theme_nodereference_item_simple($item) {
677 karens 1.111 return $item->node_title;
678 JonBob 1.32 }
679 karens 1.34
680     /**
681     * Provide a list of users to filter on.
682     */
683     function _nodereference_filter_handler($op, $filterinfo) {
684 yched 1.40 $options = array(0 => t('<empty>'));
685 karens 1.34 $options = $options + _nodereference_potential_references($filterinfo['extra']['field']);
686     return $options;
687 karens 1.88 }
688    
689     /**
690     * FAPI theme for an individual elements.
691     *
692     * The textfield or select is already rendered by the
693     * textfield or select themes and the html output
694     * lives in $element['#children']. Override this theme to
695     * make custom changes to the output.
696     *
697     * $element['#field_name'] contains the field name
698     * $element['#delta] is the position of this element in the group
699     */
700     function theme_nodereference_select($element) {
701     return $element['#children'];
702     }
703    
704     function theme_nodereference_autocomplete($element) {
705     return $element['#children'];
706 karens 1.35 }

  ViewVC Help
Powered by ViewVC 1.1.2