eads@0: array( eads@0: 'arguments' => array('element' => NULL), eads@0: ), eads@0: 'mee_formatter_default' => array( eads@0: 'arguments' => array('element' => NULL), eads@0: ), eads@0: ); tom@2: tom@2: $scald_config = variable_get('scald_config', 0); tom@2: foreach ($scald_config->contexts as $context => $details) { tom@2: $theme['mee_formatter_'. $context] = array( tom@2: 'arguments' => array('element' => NULL), tom@2: 'function' => 'theme_mee_context_formatter', tom@2: ); tom@2: } eads@0: return $theme; eads@0: } eads@0: eads@0: /** eads@0: * Implementation of hook_field_info(). eads@0: */ eads@0: function mee_field_info() { eads@0: return array( eads@0: 'multimedia_editorial_element' => array( eads@0: 'label' => t('Multimedia Editorial Element (MEE)'), eads@0: 'description' => t('MEE combines Scald, WYSIWYG, and DnD to create a multimedia enabled text field.'), eads@0: ), eads@0: ); eads@0: } eads@0: eads@0: /** eads@0: * Implementation of hook_field_settings(). eads@0: */ eads@0: function mee_field_settings($op, $field) { eads@0: switch ($op) { eads@0: case 'form': eads@0: $form = array(); eads@0: $options = array(0 => t('Plain text'), 1 => t('Filtered text (user selects input format)')); eads@0: $form['mee_processing'] = array( eads@0: '#type' => 'radios', eads@0: '#title' => t('Text processing'), eads@0: '#default_value' => is_numeric($field['mee_processing']) ? $field['mee_processing'] : 1, eads@0: '#options' => $options, eads@0: '#description' => t('Filtered text, with a WYSIWYG editor defined on one or more input formats, is strongly recommended.'), eads@0: ); eads@0: // @TODO Ask Drupal about available libraries eads@0: $form['mee_dnd_callback_url'] = array( eads@0: '#type' => 'textfield', eads@0: '#title' => t('Library callback URL'), eads@0: '#default_value' => url($field['mee_dnd_callback_url']) ? $field['mee_dnd_callback_url'] : '', eads@0: '#description' => t('The absolute URL or relative path of a callback URL that provides proper JSON to the drag and drop library.'), eads@0: ); tom@4: // @@@TODO: Add an "Editor Context" option on a per-field basis tom@4: // @@@TODO: Add a "Display Context" option on a per-field basis (this is an override) eads@0: return $form; eads@0: eads@0: case 'save': tom@4: return array('mee_processing', 'mee_dnd_callback_url', 'mee_scald_editor_context'); eads@0: eads@0: case 'database columns': eads@0: $columns['value'] = array('type' => 'text', 'size' => 'big', 'not null' => FALSE, 'sortable' => TRUE); eads@0: $columns['dnd_callback_url'] = array('type' => 'text', 'size' => 'small', 'not null' => FALSE); eads@0: if (!empty($field['mee_processing'])) { eads@0: $columns['format'] = array('type' => 'int', 'unsigned' => TRUE, 'not null' => FALSE); eads@0: } eads@0: return $columns; eads@0: eads@0: case 'views data': eads@0: return content_views_field_views_data($field); eads@0: } eads@0: } eads@0: eads@0: /** eads@0: * Implementation of hook_field(). eads@0: */ eads@0: function mee_field($op, &$node, $field, &$items, $teaser, $page) { eads@0: switch ($op) { tom@2: case 'presave': tom@2: // @@@TODO: parse the field & replace editor reps with SAS tom@2: break; // end 'submit' tom@2: tom@2: case 'insert': tom@2: foreach ($items as $delta => $item) { tom@3: $scald_included = scald_included($item); tom@3: tom@3: $temp_atom = new stdClass; tom@3: $temp_atom->type = 'composite'; tom@3: $temp_atom->provider = 'mee'; tom@3: $temp_atom->base_id = $node->nid . ':' . $delta; tom@3: $temp_atom->publisher = $node->uid; tom@3: $temp_atom->title = $node->title; tom@3: $temp_atom->authors = array(scald_uid_to_aid($node->uid)); tom@2: $temp_atom->relationships = empty($scald_included) ? array() : array('includes' => $scald_included); tom@3: tom@2: $sid = scald_register_atom($temp_atom); tom@2: } tom@2: break; // end 'insert' tom@2: tom@2: case 'update': tom@2: foreach ($items as $delta => $item) { tom@3: $scald_included = scald_included($item); tom@2: tom@3: // @@@TODO: Handle failure of fetch tom@3: $atom = scald_fetch(scald_search(array('base_id' => $node->nid . ':' . $delta), FALSE, TRUE)); tom@3: $atom->publisher = $node->uid; tom@3: $atom->title = $node->title; tom@3: $atom->authors = array( tom@3: $temp_atom->relationships = empty($scald_included) ? array() : array('includes' => $scald_included); tom@3: tom@3: scald_update_atom($atom); tom@2: } tom@2: break; // end 'update' tom@2: tom@2: case 'delete': tom@3: foreach ($items as $delta => $item) { tom@3: scald_unregister_atom(scald_search(array('base_id' => $node->nid . ':' . $delta), FALSE, TRUE)); tom@3: } tom@2: break; // end 'delete' tom@2: eads@0: case 'sanitize': eads@0: foreach ($items as $delta => $item) { eads@0: if (!empty($field['mee_processing'])) { eads@0: $check = is_null($node) || (isset($node->build_mode) && $node->build_mode == NODE_BUILD_PREVIEW); eads@0: $text = isset($item['value']) ? check_markup($item['value'], $item['format'], $check) : ''; eads@0: } eads@0: else { eads@0: $text = check_plain($item['value']); eads@0: } eads@0: $items[$delta]['safe'] = $text; eads@0: } tom@2: break; // end 'sanitize' eads@0: } eads@0: } eads@0: eads@0: /** eads@0: * Implementation of hook_content_is_empty(). eads@0: */ eads@0: function mee_content_is_empty($item, $field) { eads@0: if (empty($item['value']) && (string)$item['value'] !== '0') { eads@0: return TRUE; eads@0: } eads@0: return FALSE; eads@0: } eads@0: eads@0: /** eads@0: * Implementation of hook_field_formatter_info(). eads@0: */ eads@0: function mee_field_formatter_info() { eads@0: $formatters = array( eads@0: 'default' => array( eads@0: 'label' => t('Filtered text'), eads@0: 'field types' => array('multimedia_editorial_element'), eads@0: 'multiple values' => CONTENT_HANDLE_CORE, eads@0: ), eads@0: 'plain' => array( eads@0: 'label' => t('Plain text'), eads@0: 'field types' => array('multimedia_editorial_element'), eads@0: 'multiple values' => CONTENT_HANDLE_CORE, eads@0: ), eads@0: ); eads@0: //@TODO generate context processor based field formatters eads@0: //foreach (scald_contexts() as $context) { eads@0: // $formatters[$context] = array( eads@0: // 'label' => t('Scald context processor: @context', array('@context' => $context), eads@0: // 'field types' => 'mee', eads@0: // ); eads@0: //} eads@0: return $formatters; eads@0: } eads@0: eads@0: function theme_mee_formatter_default($element) { tom@4: return scald_sas_to_rendered($element['#item']['safe']); eads@0: } eads@0: eads@0: /** eads@0: * Theme function for 'plain' text field formatter. eads@0: */ eads@0: function theme_mee_formatter_plain($element) { tom@4: return strip_tags(scald_sas_to_rendered($element['#item']['safe'], 'title', TRUE)); eads@0: } eads@0: tom@4: //function theme_mee_context_formatter($element) { tom@4: // return 'foo'; tom@4: //} eads@0: eads@0: /** eads@0: * Implementation of hook_widget_info(). eads@0: */ eads@0: function mee_widget_info() { eads@0: return array( eads@0: 'mee_textarea' => array( eads@0: 'label' => t('MEE Textarea'), eads@0: 'field types' => array('multimedia_editorial_element'), eads@0: 'multiple values' => CONTENT_HANDLE_CORE, eads@0: ), eads@0: ); eads@0: } eads@0: eads@0: /** eads@0: * Implementation of FAPI hook_elements(). eads@0: * eads@0: * Any FAPI callbacks needed for individual widgets can be declared here, eads@0: * and the element will be passed to those callbacks for processing. eads@0: * eads@0: * Drupal will automatically theme the element using a theme with eads@0: * the same name as the hook_elements key. eads@0: */ eads@0: function mee_elements() { eads@0: return array( eads@0: 'mee_textarea' => array( eads@0: '#input' => TRUE, eads@0: '#columns' => array('value', 'format'), '#delta' => 0, eads@0: '#process' => array('mee_textarea_process', 'dnd_process_textarea'), eads@0: '#filter_value' => FILTER_FORMAT_DEFAULT, eads@0: ), eads@0: ); eads@0: } eads@0: eads@0: /** eads@0: * Implementation of hook_widget_settings(). eads@0: */ eads@0: function mee_widget_settings($op, $widget) { eads@0: switch ($op) { eads@0: case 'form': eads@0: $form = array(); eads@0: $rows = (isset($widget['rows']) && is_numeric($widget['rows'])) ? $widget['rows'] : 5; eads@0: $size = (isset($widget['size']) && is_numeric($widget['size'])) ? $widget['size'] : 60; eads@0: $form['rows'] = array( eads@0: '#type' => 'textfield', eads@0: '#title' => t('Rows'), eads@0: '#default_value' => $rows, eads@0: '#element_validate' => array('_mee_widget_settings_row_validate'), eads@0: '#required' => TRUE, eads@0: ); eads@0: $form['size'] = array('#type' => 'hidden', '#value' => $size); eads@0: return $form; eads@0: eads@0: case 'save': eads@0: return array('rows', 'size'); eads@0: } eads@0: } eads@0: eads@0: function _mee_widget_settings_row_validate($element, &$form_state) { eads@0: $value = $form_state['values']['rows']; eads@0: if (!is_numeric($value) || intval($value) != $value || $value <= 0) { eads@0: form_error($element, t('"Rows" must be a positive integer.')); eads@0: } eads@0: } eads@0: eads@0: function _mee_widget_settings_size_validate($element, &$form_state) { eads@0: $value = $form_state['values']['size']; eads@0: if (!is_numeric($value) || intval($value) != $value || $value <= 0) { eads@0: form_error($element, t('"Size" must be a positive integer.')); eads@0: } eads@0: } eads@0: eads@0: /** eads@0: * Implementation of hook_widget(). eads@0: * eads@0: * Attach a single form element to the form. It will be built out and eads@0: * validated in the callback(s) listed in hook_elements. We build it eads@0: * out in the callbacks rather than here in hook_widget so it can be eads@0: * plugged into any module that can provide it with valid eads@0: * $field information. eads@0: * eads@0: * Content module will set the weight, field name and delta values eads@0: * for each form element. This is a change from earlier CCK versions eads@0: * where the widget managed its own multiple values. eads@0: * eads@0: * If there are multiple values for this field, the content module will eads@0: * call this function as many times as needed. eads@0: * eads@0: * @param $form eads@0: * the entire form array, $form['#node'] holds node information eads@0: * @param $form_state eads@0: * the form_state, $form_state['values'][$field['field_name']] eads@0: * holds the field's form values. eads@0: * @param $field eads@0: * the field array eads@0: * @param $items eads@0: * array of default values for this field eads@0: * @param $delta eads@0: * the order of this item in the array of subelements (0, 1, 2, etc) eads@0: * eads@0: * @return eads@0: * the form item for a single element for this field eads@0: */ eads@0: function mee_widget(&$form, &$form_state, $field, $items, $delta = 0) { eads@0: $element = array( eads@0: '#type' => $field['widget']['type'], tom@4: '#default_value' => isset($items[$delta]) ? scald_sas_to_rendered($items[$delta], $field['mee_scald_editor_context'], TRUE) : '', eads@0: ); eads@0: return $element; eads@0: } eads@0: eads@0: /** eads@0: * Process an individual element. eads@0: * eads@0: * Build the form element. When creating a form using FAPI #process, eads@0: * note that $element['#value'] is already set. eads@0: * eads@0: * The $fields array is in $form['#field_info'][$element['#field_name']]. eads@0: */ eads@0: function mee_textarea_process($element, $edit, $form_state, $form) { eads@0: drupal_add_css(drupal_get_path('module', 'mee') .'/css/mee.css'); eads@0: eads@0: $field = $form['#field_info'][$element['#field_name']]; eads@0: $field_key = $element['#columns'][0]; eads@0: $element[$field_key] = array( eads@0: '#type' => 'textarea', eads@0: '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL, eads@0: '#rows' => !empty($field['widget']['rows']) ? $field['widget']['rows'] : 10, eads@0: '#weight' => 0, eads@0: // The following values were set by the content module and need eads@0: // to be passed down to the nested element. eads@0: '#title' => $element['#title'], eads@0: '#description' => $element['#description'], eads@0: '#required' => $element['#required'], eads@0: '#field_name' => $element['#field_name'], eads@0: '#type_name' => $element['#type_name'], eads@0: '#delta' => $element['#delta'], eads@0: '#columns' => $element['#columns'], eads@0: '#prefix' => '