comparison mee.module @ 0:548f63d8a41b

Blam, simple MEE cck field type.
author David Eads <eads@chicagotech.org>
date Tue, 10 Mar 2009 13:44:50 -0500
parents
children 3d3d533f9eff
comparison
equal deleted inserted replaced
-1:000000000000 0:548f63d8a41b
1 <?php
2 // $Id;
3 /**
4 * @file
5 * Defines a special textarea, with drag and drop media driven by Scald and
6 * dnd.module when rich text editing is enabled on the textarea via the
7 * WYSIWYG API.
8 */
9
10 /**
11 * Implementation of hook_theme().
12 */
13 function mee_theme() {
14 $theme = array(
15 'mee_textarea' => array(
16 'arguments' => array('element' => NULL),
17 ),
18 'mee_formatter_default' => array(
19 'arguments' => array('element' => NULL),
20 ),
21 );
22 // @TODO enable!
23 //foreach (scald_contexts() as $context) {
24 // $theme['mee_formatter_'. $context] = array(
25 // 'arguments' => array('element' => NULL),
26 // 'function' => 'theme_mee_context_formatter',
27 // );
28 //}
29 return $theme;
30 }
31
32 /**
33 * Implementation of hook_field_info().
34 */
35 function mee_field_info() {
36 return array(
37 'multimedia_editorial_element' => array(
38 'label' => t('Multimedia Editorial Element (MEE)'),
39 'description' => t('MEE combines Scald, WYSIWYG, and DnD to create a multimedia enabled text field.'),
40 ),
41 );
42 }
43
44 /**
45 * Implementation of hook_field_settings().
46 */
47 function mee_field_settings($op, $field) {
48 switch ($op) {
49 case 'form':
50 $form = array();
51 $options = array(0 => t('Plain text'), 1 => t('Filtered text (user selects input format)'));
52 $form['mee_processing'] = array(
53 '#type' => 'radios',
54 '#title' => t('Text processing'),
55 '#default_value' => is_numeric($field['mee_processing']) ? $field['mee_processing'] : 1,
56 '#options' => $options,
57 '#description' => t('Filtered text, with a WYSIWYG editor defined on one or more input formats, is strongly recommended.'),
58 );
59 // @TODO Ask Drupal about available libraries
60 $form['mee_dnd_callback_url'] = array(
61 '#type' => 'textfield',
62 '#title' => t('Library callback URL'),
63 '#default_value' => url($field['mee_dnd_callback_url']) ? $field['mee_dnd_callback_url'] : '',
64 '#description' => t('The absolute URL or relative path of a callback URL that provides proper JSON to the drag and drop library.'),
65 );
66 return $form;
67
68 case 'save':
69 return array('mee_processing', 'mee_dnd_callback_url');
70
71 case 'database columns':
72 $columns['value'] = array('type' => 'text', 'size' => 'big', 'not null' => FALSE, 'sortable' => TRUE);
73 $columns['dnd_callback_url'] = array('type' => 'text', 'size' => 'small', 'not null' => FALSE);
74 if (!empty($field['mee_processing'])) {
75 $columns['format'] = array('type' => 'int', 'unsigned' => TRUE, 'not null' => FALSE);
76 }
77 return $columns;
78
79 case 'views data':
80 return content_views_field_views_data($field);
81 }
82 }
83
84 /**
85 * Implementation of hook_field().
86 */
87 function mee_field($op, &$node, $field, &$items, $teaser, $page) {
88 switch ($op) {
89 case 'sanitize':
90 foreach ($items as $delta => $item) {
91 if (!empty($field['mee_processing'])) {
92 $check = is_null($node) || (isset($node->build_mode) && $node->build_mode == NODE_BUILD_PREVIEW);
93 $text = isset($item['value']) ? check_markup($item['value'], $item['format'], $check) : '';
94 }
95 else {
96 $text = check_plain($item['value']);
97 }
98 $items[$delta]['safe'] = $text;
99 }
100 }
101 }
102
103 /**
104 * Implementation of hook_content_is_empty().
105 */
106 function mee_content_is_empty($item, $field) {
107 if (empty($item['value']) && (string)$item['value'] !== '0') {
108 return TRUE;
109 }
110 return FALSE;
111 }
112
113 /**
114 * Implementation of hook_field_formatter_info().
115 */
116 function mee_field_formatter_info() {
117 $formatters = array(
118 'default' => array(
119 'label' => t('Filtered text'),
120 'field types' => array('multimedia_editorial_element'),
121 'multiple values' => CONTENT_HANDLE_CORE,
122 ),
123 'plain' => array(
124 'label' => t('Plain text'),
125 'field types' => array('multimedia_editorial_element'),
126 'multiple values' => CONTENT_HANDLE_CORE,
127 ),
128 );
129 //@TODO generate context processor based field formatters
130 //foreach (scald_contexts() as $context) {
131 // $formatters[$context] = array(
132 // 'label' => t('Scald context processor: @context', array('@context' => $context),
133 // 'field types' => 'mee',
134 // );
135 //}
136 return $formatters;
137 }
138
139 function theme_mee_formatter_default($element) {
140 return $element['#item']['safe'];
141 }
142
143 /**
144 * Theme function for 'plain' text field formatter.
145 */
146 function theme_mee_formatter_plain($element) {
147 return strip_tags($element['#item']['safe']);
148 }
149
150 function theme_mee_context_formatter($element) {
151 return 'foo';
152 }
153
154 /**
155 * Implementation of hook_widget_info().
156 */
157 function mee_widget_info() {
158 return array(
159 'mee_textarea' => array(
160 'label' => t('MEE Textarea'),
161 'field types' => array('multimedia_editorial_element'),
162 'multiple values' => CONTENT_HANDLE_CORE,
163 ),
164 );
165 }
166
167 /**
168 * Implementation of FAPI hook_elements().
169 *
170 * Any FAPI callbacks needed for individual widgets can be declared here,
171 * and the element will be passed to those callbacks for processing.
172 *
173 * Drupal will automatically theme the element using a theme with
174 * the same name as the hook_elements key.
175 */
176 function mee_elements() {
177 return array(
178 'mee_textarea' => array(
179 '#input' => TRUE,
180 '#columns' => array('value', 'format'), '#delta' => 0,
181 '#process' => array('mee_textarea_process', 'dnd_process_textarea'),
182 '#filter_value' => FILTER_FORMAT_DEFAULT,
183 ),
184 );
185 }
186
187 /**
188 * Implementation of hook_widget_settings().
189 */
190 function mee_widget_settings($op, $widget) {
191 switch ($op) {
192 case 'form':
193 $form = array();
194 $rows = (isset($widget['rows']) && is_numeric($widget['rows'])) ? $widget['rows'] : 5;
195 $size = (isset($widget['size']) && is_numeric($widget['size'])) ? $widget['size'] : 60;
196 $form['rows'] = array(
197 '#type' => 'textfield',
198 '#title' => t('Rows'),
199 '#default_value' => $rows,
200 '#element_validate' => array('_mee_widget_settings_row_validate'),
201 '#required' => TRUE,
202 );
203 $form['size'] = array('#type' => 'hidden', '#value' => $size);
204 return $form;
205
206 case 'save':
207 return array('rows', 'size');
208 }
209 }
210
211 function _mee_widget_settings_row_validate($element, &$form_state) {
212 $value = $form_state['values']['rows'];
213 if (!is_numeric($value) || intval($value) != $value || $value <= 0) {
214 form_error($element, t('"Rows" must be a positive integer.'));
215 }
216 }
217
218 function _mee_widget_settings_size_validate($element, &$form_state) {
219 $value = $form_state['values']['size'];
220 if (!is_numeric($value) || intval($value) != $value || $value <= 0) {
221 form_error($element, t('"Size" must be a positive integer.'));
222 }
223 }
224
225 /**
226 * Implementation of hook_widget().
227 *
228 * Attach a single form element to the form. It will be built out and
229 * validated in the callback(s) listed in hook_elements. We build it
230 * out in the callbacks rather than here in hook_widget so it can be
231 * plugged into any module that can provide it with valid
232 * $field information.
233 *
234 * Content module will set the weight, field name and delta values
235 * for each form element. This is a change from earlier CCK versions
236 * where the widget managed its own multiple values.
237 *
238 * If there are multiple values for this field, the content module will
239 * call this function as many times as needed.
240 *
241 * @param $form
242 * the entire form array, $form['#node'] holds node information
243 * @param $form_state
244 * the form_state, $form_state['values'][$field['field_name']]
245 * holds the field's form values.
246 * @param $field
247 * the field array
248 * @param $items
249 * array of default values for this field
250 * @param $delta
251 * the order of this item in the array of subelements (0, 1, 2, etc)
252 *
253 * @return
254 * the form item for a single element for this field
255 */
256 function mee_widget(&$form, &$form_state, $field, $items, $delta = 0) {
257 $element = array(
258 '#type' => $field['widget']['type'],
259 '#default_value' => isset($items[$delta]) ? $items[$delta] : '',
260 );
261 return $element;
262 }
263
264 /**
265 * Process an individual element.
266 *
267 * Build the form element. When creating a form using FAPI #process,
268 * note that $element['#value'] is already set.
269 *
270 * The $fields array is in $form['#field_info'][$element['#field_name']].
271 */
272 function mee_textarea_process($element, $edit, $form_state, $form) {
273 drupal_add_css(drupal_get_path('module', 'mee') .'/css/mee.css');
274
275 $field = $form['#field_info'][$element['#field_name']];
276 $field_key = $element['#columns'][0];
277 $element[$field_key] = array(
278 '#type' => 'textarea',
279 '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
280 '#rows' => !empty($field['widget']['rows']) ? $field['widget']['rows'] : 10,
281 '#weight' => 0,
282 // The following values were set by the content module and need
283 // to be passed down to the nested element.
284 '#title' => $element['#title'],
285 '#description' => $element['#description'],
286 '#required' => $element['#required'],
287 '#field_name' => $element['#field_name'],
288 '#type_name' => $element['#type_name'],
289 '#delta' => $element['#delta'],
290 '#columns' => $element['#columns'],
291 '#prefix' => '<div class="mee-wrap-editor-library">',
292 '#suffix' => '</div>',
293 '#dnd-enabled' => TRUE,
294 '#dnd-settings' => array(
295 'drop_selector' => '#'. $element['#id'] .' .drop',
296 'url' => $field['mee_dnd_callback_url'],
297 ),
298 );
299
300 if (!empty($field['mee_processing'])) {
301 $filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format';
302 $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT;
303 $parents = array_merge($element['#parents'] , array($filter_key));
304 $element[$filter_key] = filter_form($format, 1, $parents);
305 }
306
307 // Used so that hook_field('validate') knows where to flag an error.
308 $element['_error_element'] = array(
309 '#type' => 'value',
310 '#value' => implode('][', array_merge($element['#parents'], array($field_key))),
311 );
312
313
314 return $element;
315 }
316
317 /**
318 * FAPI theme for an individual text elements.
319 *
320 * The textfield or textarea is already rendered by the
321 * textfield or textarea themes and the html output
322 * lives in $element['#children']. Override this theme to
323 * make custom changes to the output.
324 *
325 * $element['#field_name'] contains the field name
326 * $element['#delta] is the position of this element in the group
327 */
328 function theme_mee_textarea($element) {
329 return $element['#children'];
330 }