franck@0
|
1 <?php |
franck@0
|
2 // vim: set ts=2 sw=2 expandtab syntax=php: |
franck@0
|
3 |
franck@0
|
4 /** |
franck@0
|
5 * @file |
franck@0
|
6 * Fichier principale du module noderef_view |
franck@0
|
7 * |
franck@0
|
8 * Ce module permet d'ajouter à tous les champs de type "Node Reference" |
franck@1
|
9 * pour lesquels une vue définissant les nodes autorisés a été définie |
franck@1
|
10 * un lien 'Search' affichant la vue dans une popup (via le module Popups API), |
franck@0
|
11 * permettant de choisir les nodes à mettre dans le champ en disposant de la |
franck@1
|
12 * puissance de Views pour la recherche (Exposed Filters notamment). |
franck@0
|
13 */ |
franck@0
|
14 |
franck@0
|
15 /** |
franck@0
|
16 * Implémentation de hook_view_action_info(). |
franck@0
|
17 * |
franck@0
|
18 * On crée une nouvelle action, nommée Select, et qui sera utilisée pour marquer |
franck@0
|
19 * les nodes comme données à utiliser. L'utilisation concrète qui en est faite |
franck@0
|
20 * dans ce module consiste à utiliser ces nœuds selectionés pour les ajouter |
franck@0
|
21 * dans le champ Node Reference étant à l'origine de la recherche. |
franck@0
|
22 */ |
franck@0
|
23 function noderef_view_action_info() { |
franck@0
|
24 return array( |
franck@0
|
25 'noderef_view_select' => array( |
franck@9
|
26 'description' => t('Add selected values to field'), |
franck@0
|
27 'type' => 'node', |
franck@0
|
28 'configurable' => FALSE, |
franck@0
|
29 'hooks' => array( |
franck@0
|
30 'nodeapi' => array() |
franck@0
|
31 ) |
franck@0
|
32 ) |
franck@0
|
33 ); |
franck@0
|
34 } |
franck@0
|
35 |
franck@0
|
36 /** |
franck@0
|
37 * Implémentation concrète de l'action de selection. |
franck@0
|
38 * |
franck@0
|
39 * On vide toute eventuelle selection précédente, puis on passe dans le cookie |
franck@0
|
40 * les informations sur la selection qui a été faite. |
franck@0
|
41 */ |
franck@0
|
42 function noderef_view_select($node, $context) { |
franck@0
|
43 static $count = 0; |
franck@0
|
44 if ($count == 0 && is_array($_COOKIE['noderef'])) { |
franck@0
|
45 // Reset the cookies |
franck@0
|
46 $before = time() - 300; |
franck@0
|
47 foreach($_COOKIE['noderef'] as $id => $val) { |
franck@0
|
48 setcookie('noderef['. $id .']', 0, $before, '/'); |
franck@0
|
49 } |
franck@0
|
50 } |
franck@0
|
51 $count++; |
franck@0
|
52 $five = time() + 300; |
franck@0
|
53 setrawcookie('noderef['. $node->nid .']', rawurlencode($node->title), $five, '/'); |
franck@11
|
54 drupal_set_message(t('!title added to selection', |
franck@11
|
55 array('!title' => $node->title))); |
franck@0
|
56 } |
franck@0
|
57 |
franck@0
|
58 /** |
franck@0
|
59 * Implémentation de hook_form_alter(). |
franck@0
|
60 * |
franck@0
|
61 * On parcoure tous les formulaires à la recherche d'éventuels champs |
franck@0
|
62 * de type "Node Reference" sur lesquels appliqués nos transformations. |
franck@0
|
63 */ |
franck@0
|
64 function noderef_view_form_alter(&$form, $form_state, $form_id) { |
franck@0
|
65 if (isset($form['type']) && $form_id == $form['type']['#value'] .'_node_form') { |
franck@0
|
66 // That's a node form, get the fields and alter the form if needed |
franck@0
|
67 $fields = content_fields(); |
franck@11
|
68 $alter = _noderef_view_walk_form($form, $fields, $form); |
franck@0
|
69 if ($alter) { |
franck@0
|
70 // We've changed the form, add the JS-behavior and Views CSS |
franck@0
|
71 // (the latter to deal with exposed filters in the popup) |
franck@6
|
72 $path = drupal_get_path('module', 'noderef_view'); |
franck@6
|
73 drupal_add_js($path .'/noderef_view.js'); |
franck@6
|
74 drupal_add_css($path .'/noderef_view.css'); |
franck@0
|
75 drupal_add_css(drupal_get_path('module', 'views') .'/css/views.css'); |
franck@0
|
76 } |
franck@0
|
77 } |
franck@0
|
78 elseif ($form_id == 'views_exposed_form' && isset($_GET['destination'])) { |
franck@0
|
79 // Views "Exposed Filter" forms doesn't preserve destination by default. |
franck@0
|
80 $form['destination'] = array( |
franck@0
|
81 '#type' => 'hidden', |
franck@0
|
82 '#value' => $_GET['destination'] |
franck@0
|
83 ); |
franck@0
|
84 } |
franck@0
|
85 } |
franck@0
|
86 |
franck@0
|
87 /** |
franck@0
|
88 * Parcoure le tableau contenant le formulaire à la recherche |
franck@0
|
89 * d'élement à modifier. |
franck@0
|
90 * @return |
franck@0
|
91 * TRUE si un élement a été modifié, FALSE sinon |
franck@0
|
92 */ |
franck@11
|
93 function _noderef_view_walk_form(&$form, $fields, $items) { |
franck@0
|
94 $alter = FALSE; |
franck@11
|
95 foreach($items as $key => $item) { |
franck@0
|
96 if (is_array($item)) { |
franck@0
|
97 if (isset($fields[$key])) { |
franck@0
|
98 $alter |= noderef_view_alter_item($form, $key, $fields[$key]); |
franck@0
|
99 } |
franck@0
|
100 else { |
franck@11
|
101 $alter |= _noderef_view_walk_form($form, $fields, $item); |
franck@0
|
102 } |
franck@0
|
103 } |
franck@0
|
104 } |
franck@0
|
105 return $alter; |
franck@0
|
106 } |
franck@0
|
107 |
franck@0
|
108 /** |
franck@0
|
109 * Modification d'un élement en particulier du formulaire. |
franck@0
|
110 * |
franck@0
|
111 * @return |
franck@0
|
112 * TRUE si l'element a été modifié, FALSE sinon. |
franck@0
|
113 */ |
franck@0
|
114 function noderef_view_alter_item(&$form, $key, $field) { |
franck@0
|
115 if (is_array($field) && $field['type'] == 'nodereference') { |
franck@2
|
116 $link = _noderef_view_get_link($field); |
franck@0
|
117 if (!empty($link)) { |
franck@0
|
118 return TRUE; |
franck@0
|
119 } |
franck@0
|
120 } |
franck@0
|
121 return FALSE; |
franck@0
|
122 } |
franck@0
|
123 |
franck@0
|
124 /** |
franck@0
|
125 * Création d'un lien vers une éventuelle vue associé au champ. |
franck@0
|
126 * |
franck@0
|
127 * @return |
franck@0
|
128 * - Un lien vers la vue si une vue est associée |
franck@0
|
129 * - Une chaine vide sinon |
franck@11
|
130 */ |
franck@0
|
131 function _noderef_view_get_link($field) { |
franck@0
|
132 $path = ''; |
franck@0
|
133 // Check if there's a view associated with this field |
franck@0
|
134 if (isset($field['advanced_view']) && $field['advanced_view'] !== '--') { |
franck@0
|
135 $view = views_get_view($field['advanced_view']); |
franck@0
|
136 // Try to find a path for this view, looking at the displays |
franck@0
|
137 $path = ''; |
franck@0
|
138 foreach($view->display as $display) { |
franck@0
|
139 if (is_array($display->display_options) |
franck@0
|
140 && isset($display->display_options['path'])) { |
franck@0
|
141 $path = $display->display_options['path']; |
franck@2
|
142 break; |
franck@0
|
143 } |
franck@0
|
144 } |
franck@0
|
145 } |
franck@0
|
146 // If we found a view with a suitable display, then link to it |
franck@0
|
147 if (!empty($path)) { |
franck@0
|
148 popups_add_popups(); |
franck@0
|
149 $options = array( |
franck@12
|
150 'attributes' => array('class' => 'popups-form-noupdate noderef_view_link'), |
franck@0
|
151 'query' => array('destination' => 'node') |
franck@0
|
152 ); |
franck@0
|
153 $path = l(t('Search'), $path, $options); |
franck@0
|
154 } |
franck@2
|
155 return $path; |
franck@0
|
156 } |
franck@0
|
157 |
franck@11
|
158 function noderef_view_theme() { |
franck@11
|
159 return array( |
franck@11
|
160 'noderef_view_autocomplete' => array( |
franck@11
|
161 'arguments' => array('element' => NULL) |
franck@11
|
162 ) |
franck@11
|
163 ); |
franck@11
|
164 } |
franck@11
|
165 |
franck@11
|
166 function noderef_view_widget_info() { |
franck@11
|
167 return array( |
franck@11
|
168 'noderef_view_autocomplete' => array( |
franck@11
|
169 'label' => t('Autocomplete text field with View'), |
franck@11
|
170 'field types' => array('nodereference'), |
franck@11
|
171 'multiple values' => CONTENT_HANDLE_CORE, |
franck@11
|
172 'callbacks' => array( |
franck@11
|
173 'default value' => CONTENT_CALLBACK_DEFAULT, |
franck@11
|
174 ), |
franck@11
|
175 ), |
franck@11
|
176 ); |
franck@11
|
177 } |
franck@11
|
178 |
franck@11
|
179 function noderef_view_elements() { |
franck@11
|
180 return array( |
franck@11
|
181 'noderef_view_autocomplete' => array( |
franck@11
|
182 '#input' => TRUE, |
franck@11
|
183 '#columns' => array('name'), '#delta' => 0, |
franck@11
|
184 '#process' => array('noderef_view_autocomplete_process'), |
franck@11
|
185 '#autocomplete_path' => FALSE, |
franck@11
|
186 ), |
franck@11
|
187 ); |
franck@11
|
188 } |
franck@11
|
189 |
franck@11
|
190 function noderef_view_widget(&$form, &$form_state, $field, $items, $delta = 0) { |
franck@11
|
191 switch ($field['widget']['type']) { |
franck@11
|
192 case 'noderef_view_autocomplete': |
franck@11
|
193 $element = array( |
franck@11
|
194 '#type' => 'noderef_view_autocomplete', |
franck@11
|
195 '#default_value' => isset($items[$delta]) ? $items[$delta] : NULL, |
franck@11
|
196 '#value_callback' => 'nodereference_autocomplete_value', |
franck@11
|
197 ); |
franck@11
|
198 break; |
franck@11
|
199 } |
franck@11
|
200 return $element; |
franck@11
|
201 } |
franck@11
|
202 |
franck@11
|
203 /** |
franck@11
|
204 * Process an individual element. |
franck@11
|
205 * |
franck@11
|
206 * Build the form element. When creating a form using FAPI #process, |
franck@11
|
207 * note that $element['#value'] is already set. |
franck@11
|
208 * |
franck@11
|
209 */ |
franck@11
|
210 function noderef_view_autocomplete_process($element, $edit, $form_state, $form) { |
franck@11
|
211 // The nodereference autocomplete widget doesn't need to create its own |
franck@11
|
212 // element, it can wrap around the text_textfield element and add an autocomplete |
franck@11
|
213 // path and some extra processing to it. |
franck@11
|
214 // Add a validation step where the value can be unwrapped. |
franck@11
|
215 $fields = content_fields(); |
franck@11
|
216 $link = _noderef_view_get_link($fields[$element['#field_name']]); |
franck@11
|
217 $field_key = $element['#columns'][0]; |
franck@11
|
218 $element[$field_key] = array( |
franck@11
|
219 '#type' => 'text_textfield', |
franck@11
|
220 '#default_value' => isset($element['#value']) ? $element['#value'] : '', |
franck@11
|
221 '#autocomplete_path' => 'nodereference/autocomplete/'. $element['#field_name'], |
franck@11
|
222 // The following values were set by the content module and need |
franck@11
|
223 // to be passed down to the nested element. |
franck@11
|
224 '#title' => $element['#title'], |
franck@11
|
225 '#required' => $element['#required'], |
franck@11
|
226 '#description' => $element['#description'], |
franck@11
|
227 '#field_name' => $element['#field_name'], |
franck@11
|
228 '#type_name' => $element['#type_name'], |
franck@11
|
229 '#delta' => $element['#delta'], |
franck@11
|
230 '#columns' => $element['#columns'], |
franck@11
|
231 ); |
franck@11
|
232 if ($link) { |
franck@11
|
233 $element[$field_key]['#noderef_view_link'] = $link; |
franck@11
|
234 $element[$field_key]['#prefix'] = "<div class='noderef-view-wrapper'>"; |
franck@11
|
235 $element[$field_key]['#suffix'] = $link ."</div>"; |
franck@11
|
236 } |
franck@11
|
237 if (empty($element[$field_key]['#element_validate'])) { |
franck@11
|
238 $element[$field_key]['#element_validate'] = array(); |
franck@11
|
239 } |
franck@11
|
240 array_unshift($element[$field_key]['#element_validate'], 'nodereference_autocomplete_validate'); |
franck@11
|
241 |
franck@11
|
242 // Used so that hook_field('validate') knows where to flag an error. |
franck@11
|
243 $element['_error_element'] = array( |
franck@11
|
244 '#type' => 'value', |
franck@11
|
245 // Wrapping the element around a text_textfield element creates a |
franck@11
|
246 // nested element, so the final id will look like 'field-name-0-nid-nid'. |
franck@11
|
247 '#value' => implode('][', array_merge($element['#parents'], array($field_key, $field_key))), |
franck@11
|
248 ); |
franck@11
|
249 return $element; |
franck@11
|
250 } |
franck@11
|
251 |
franck@11
|
252 function theme_noderef_view_autocomplete($element) { |
franck@11
|
253 return <<<EOT |
franck@11
|
254 <div class='noderef-view-wrapper'> |
franck@11
|
255 {$element['#children']} |
franck@11
|
256 {$element['#noderef_view_link']} |
franck@11
|
257 <span class='clear-block'></span> |
franck@11
|
258 </div> |
franck@11
|
259 EOT; |
franck@11
|
260 } |