Index: bible_field.install
===================================================================
RCS file: bible_field.install
diff -N bible_field.install
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bible_field.install	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,38 @@
+<?php
+// $Id$
+
+/**
+ * Implementation of hook_install().
+ */
+function bible_field_install() {
+  drupal_load('module', 'content');
+  content_notify('install', 'bible_field');
+}
+
+/**
+ * Implementation of hook_uninstall().
+ */
+function bible_field_uninstall() {
+  drupal_load('module', 'content');
+  content_notify('uninstall', 'bible_field');
+}
+
+/**
+ * Implementation of hook_enable().
+ *
+ * Notify content module when this module is enabled.
+ */
+function bible_field_enable() {
+  drupal_load('module', 'content');
+  content_notify('enable', 'bible_field');
+}
+
+/**
+ * Implementation of hook_disable().
+ *
+ * Notify content module when this module is disabled.
+ */
+function bible_field_disable() {
+  drupal_load('module', 'content');
+  content_notify('disable', 'bible_field');
+}
Index: bible_field.module
===================================================================
RCS file: bible_field.module
diff -N bible_field.module
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bible_field.module	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,484 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Provides CCK and Views integration to the Bible module.
+ */
+
+/**
+ * Implementation of hook_theme().
+ */
+function bible_field_theme() {
+  return array(
+    'bible_field_bibleref' => array(
+      'arguments' => array('element' => NULL),
+    ),
+    'bible_field_formatter_default' => array(
+      'arguments' => array('element' => NULL),
+    ),
+    'bible_field_formatter_plain' => array(
+      'arguments' => array('element' => NULL),
+    ),
+    'bible_field_formatter_full' => array(
+      'arguments' => array('element' => NULL),
+    ),
+  );
+}
+
+/**
+ * Implementation of hook_field_info().
+ */
+function bible_field_field_info() {
+  return array(
+    'bible_field' => array(
+      'label' => t('Bible Reference'),
+      'description' => t('Provides a link or reference to a scripture verse.'),
+      ),
+    );
+}
+
+/**
+ * Implementation of hook_field_settings().
+ */
+function bible_field_field_settings($op, $field) {
+  switch ($op) {
+    case 'form':
+      $form = array();
+      // Set no options because we know what kind of data we want to enter.
+      return $form;
+
+    case 'save':
+      return array();
+
+    case 'database columns':
+      $columns['book']    = array('type' => 'int', 'length' => 5, 'not null' => FALSE, 'sortable' => TRUE, 'views' => TRUE);
+      $columns['chapter'] = array('type' => 'int', 'length' => 5, 'not null' => FALSE, 'sortable' => TRUE, 'views' => TRUE);
+      $columns['verses']  = array('type' => 'varchar', 'length' => 25, 'not null' => FALSE, 'sortable' => TRUE, 'views' => TRUE);
+      return $columns;
+  }
+}
+
+/**
+ * Implementation of hook_field().
+ *
+ * Define the behavior of a field type.
+ *
+ * @param $op
+ *   What kind of action is being performed. Possible values:
+ *   - "load": The node is about to be loaded from the database. This hook
+ *     should be used to load the field.
+ *   - "validate": The user has just finished editing the node and is
+ *     trying to preview or submit it. This hook can be used to check or
+ *     even modify the node. Errors should be set with form_set_error().
+ *   - "presave": The user has just finished editing the node and the node has
+ *     passed validation. This hook can be used to modify the node.
+ *   - "insert": The node is being created (inserted in the database).
+ *   - "update": The node is being updated.
+ *   - "delete": The node is being deleted.
+ * @param &$node
+ *   The node the action is being performed on. This argument is passed by
+ *   reference for performance only; do not modify it.
+ * @param $field
+ *   The field the action is being performed on.
+ * @param &$node_field
+ *   The contents of the field in this node. Changes to this variable will
+ *   be saved back to the node object.
+ * @return
+ *   This varies depending on the operation.
+ *   - The "load" operation should return an object containing extra values
+ *     to be merged into the node object.
+ *   - The "insert", "update", "delete", "validate", and "presave" operations
+ *     have no return value.
+ *
+ * In most cases, only "validate" operations is relevant ; the rest
+ * have default implementations in content_field() that usually suffice.
+ */
+function bible_field_field($op, &$node, $field, &$items, $teaser, $page) {
+  switch ($op) {
+    case 'validate':
+      global $book_list, $book_namelist;
+      $book_regex = $book_list .'|'. str_replace(';', '|', $book_namelist);
+      $pattern_regex = '/('. $book_regex .')[:. ]+(\d{1,3}):(\d{1,3}(?:-\d{1,3})?)((#.*)?)/e';
+      if (is_array($items)) {
+        foreach ($items as $delta => $item) {
+          $error_element = isset($item['_error_element']) ? $item['_error_element'] : '';
+          if (is_array($item) && isset($item['_error_element'])) unset($item['_error_element']);
+          if (!empty($item['value'])) {
+            if (preg_match($pattern_regex, $item['value'])) {
+              form_set_error($error_element, t('%name: does not match BLS syntax.', array('%name' => t($field['widget']['label']))));
+            }
+          }
+        }
+      }
+      return $items;
+
+    case 'presave':
+	  global $book_list, $book_namelist;
+      $book_regex = $book_list .'|'. str_replace(';', '|', $book_namelist);
+      $pattern_regex = '/('. $book_regex .')[:. ]+(\d{1,3}):(\d{1,3}(?:-\d{1,3})?)((#.*)?)/e';
+      
+      // Need array of all the book abbrevs and their order.
+      $book_array = explode('|', $book_list);
+      
+      // Also need array of all the book names and their order.
+      $namelist_array = explode(';', $book_namelist);
+      foreach ($namelist_array as $key => $name) {
+        $namelist_array[$key] = substr($name, strpos($name, '|') + 1);
+      }
+      
+      foreach ($items as $delta => $item) {
+        $matches = array();
+        $match = array();
+        preg_match($pattern_regex, $item, $matches);
+        
+        // Get the order number of that book.
+        $book_num = array_search($matches[1], $book_array);
+        if ($book_num === FALSE) $book_num = array_search($matches[1], $namelist_array);
+        
+        $match['book']    = $book_num;
+        $match['chapter'] = $matches[2];
+        $match['verses']  = $matches[3] . (!empty($matches[4]) ? '-' . $matches[4] : '');
+        $items[$delta] = $match;
+      }
+      break;
+    
+    case 'load':
+	  global $book_list, $book_namelist;
+      $object = array();
+	  
+      // Need array of all the book abbrevs and their order.
+      $book_array = explode('|', $book_list);
+      
+      if (isset($node->{$field['field_name']})) {
+        foreach ($node->{$field['field_name']} as $delta => $item) {
+          $object[$field['field_name']][$delta]['book']    = $item['book']; 
+          $object[$field['field_name']][$delta]['chapter'] = $item['chapter'];
+          $object[$field['field_name']][$delta]['verses']  = $item['verses']; 
+          $object[$field['field_name']][$delta]['value']   = $book_array[$item['book']] . ' '; 
+          $object[$field['field_name']][$delta]['value']  .= $item['chapter'] . ':' . $item['verses'];
+        }
+      }
+      
+      return $object;
+  }
+}
+
+/**
+ * Implementation of hook_content_is_empty().
+ */
+function bible_field_content_is_empty($item, $field) {
+  if (empty($item['value']) && (!isset($item['book']) || empty($item['chapter']) || empty($item['verses']))) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * Implementation of hook_field_formatter_info().
+ *
+ * The default behavior of formatters is that they will create
+ * a theme for a single field value.
+ *
+ * Setting 'multiple values' to CONTENT_HANDLE_FIELD will create
+ * a formatter that will receive all the values of a field so you
+ * can, for instance, plot all the values on a map or in a graph.
+ *
+ * The 'view' operation (handled by the Content module) constructs the
+ * $node in a way that you can use drupal_render() to display the
+ * formatted output for an individual field.
+ *
+ * i.e. print drupal_render($node->field_foo);
+ *
+ * The code now supports both single value formatters, which theme an
+ * individual item value as has been done in previous version of CCK,
+ * and multiple value formatters, which theme all values for the field
+ * in a single theme. The multiple value formatters could be used, for
+ * instance, to plot field values on a single map or display them
+ * in a graph. Single value formatters are the default, multiple value
+ * formatters can be designated as such in formatter_info().
+ *
+ * The node array will look like:
+ *
+ *  'Single value' formatter:
+ *   $node->content['field_foo'] = array(
+ *     '#type' => 'content_field',
+ *     '#title' => 'label'
+ *     '#field_name' => 'field_name',
+ *     '#node' => $node,
+ *     'items' =>
+ *       0 => array(
+ *         '#theme' => $theme,
+ *         '#field_name' => 'field_name',
+ *         '#type_name' => $node->type,
+ *         '#formatter' => $formatter_name,
+ *         '#item' => $items[0],
+ *       ),
+ *       1 => array(
+ *         '#theme' => $theme,
+ *         '#field_name' => 'field_name',
+ *         '#type_name' => $node->type,
+ *         '#formatter' => $formatter_name,
+ *         '#item' => $items[1],
+ *       ),
+ *     ),
+ *   );
+ *  'Multiple value' formatter:
+ *   $node->content['field_foo'] = array(
+ *     '#type' => 'content_field',
+ *     '#title' => 'label'
+ *     '#field_name' => 'field_name',
+ *     '#node' => $node,
+ *     'items' => array(
+ *       '#theme' => $theme,
+ *       '#field_name' => 'field_name',
+ *       '#type_name' => $node->type,
+ *       '#formatter' => $formatter_name,
+ *       0 => array(
+ *         '#item' => $items[0],
+ *       ),
+ *       1 => array(
+ *         '#item' => $items[1],
+ *       ),
+ *     ),
+ *   );
+ */
+function bible_field_field_formatter_info() {
+  return array(
+    'default' => array(
+      'label' => t('Default'),
+      'field types' => array('bible_field'),
+      'multiple values' => CONTENT_HANDLE_CORE,
+    ),
+    'plain' => array(
+      'label' => t('Plain text'),
+      'field types' => array('bible_field'),
+      'multiple values' => CONTENT_HANDLE_CORE,
+    ),
+    'full' => array(
+      'label' => t('Full Reference'),
+      'field types' => array('bible_field'),
+      'multiple values' => CONTENT_HANDLE_CORE,
+    ),
+  );
+}
+
+/**
+ * Theme function for 'default' text field formatter.
+ */
+function theme_bible_field_formatter_plain($element) {
+  return $element['#item']['value'];
+}
+
+/**
+ * Theme function for 'plain' text field formatter.
+ */
+function theme_bible_field_formatter_full($element) {
+  $verses = explode('-', $element['#item']['verses']);
+  $text = _bible_field_load_ref($element['#item']['book'], $element['#item']['chapter'], $verses[0], $verses[1]);
+  return $text;
+}
+
+/**
+ * Theme function for 'trimmed' text field formatter.
+ */
+function theme_bible_field_formatter_default($element) {
+  return _bible_blsanchorize($element['#item']['value']);
+}
+
+function _bible_field_load_ref($book, $chapter, $verse_start, $verse_end = NULL) {
+  global $book_list;
+  // Need array of all the book abbrevs and their order.
+  $book_array = explode('|', $book_list);
+      
+  $ref_value  = $book_array[$book] . ':'; 
+  $ref_value .= $chapter . ':' . $verse_start;
+  if (!empty($verse_end)) $ref_value .= '-' . $verse_end;
+  
+  $text = $ref_value . ' - ' . _bible_get_verse_content($ref_value);
+  return $text;
+}
+
+/**
+ * Implementation of hook_widget_info().
+ *
+ * Here we indicate that the content module will handle
+ * the default value and multiple values for these widgets.
+ *
+ * Callbacks can be omitted if default handing is used.
+ * They're included here just so this module can be used
+ * as an example for custom modules that might do things
+ * differently.
+ *
+ * IMPORTANT! - field and widget names will be truncated to 32 characters in
+ * the database and in internal arrays, like content_fields().
+ */
+function bible_field_widget_info() {
+  return array(
+    'bible_field_bibleref' => array(
+      'label' => t('Bible Reference'),
+      'field types' => array('bible_field'),
+      'multiple values' => CONTENT_HANDLE_CORE,
+      'callbacks' => array(
+        'default value' => CONTENT_CALLBACK_DEFAULT,
+        ),
+    ),
+  );
+}
+
+/**
+ * Implementation of FAPI hook_elements().
+ *
+ * Any FAPI callbacks needed for individual widgets can be declared here,
+ * and the element will be passed to those callbacks for processing.
+ *
+ * Drupal will automatically theme the element using a theme with
+ * the same name as the hook_elements key.
+ *
+ * Autocomplete_path is not used by text_widget but other widgets can use it
+ * (see nodereference and userreference).
+ */
+function bible_field_elements() {
+  return array(
+    'bible_field_bibleref' => array(
+      '#input' => TRUE,
+      '#columns' => array('value'), '#delta' => 0,
+      '#process' => array('bible_field_bibleref_process'),
+      '#autocomplete_path' => FALSE,
+      ),
+    );
+}
+
+/**
+ * Implementation of hook_widget_settings().
+ *
+ * Handle the parameters for a widget.
+ *
+ * @param $op
+ *   The operation to be performed. Possible values:
+ *   - "form": Display the widget settings form.
+ *   - "validate": Check the widget settings form for errors.
+ *   - "save": Declare which pieces of information to save back to the database.
+ * @param $widget
+ *   The widget on which the operation is to be performed.
+ * @return
+ *   This varies depending on the operation.
+ *   - "form": an array of form elements to add to the settings page.
+ *   - "validate": no return value. Use form_set_error().
+ *   - "save": an array of names of form elements to be saved in the database.
+ */
+function bible_field_widget_settings($op, $widget) {
+  switch ($op) {
+    case 'form':
+      $form = array();
+      return $form;
+
+    case 'validate':
+      break;
+
+    case 'save':
+      return array();
+  }
+}
+
+/**
+ * Implementation of hook_widget().
+ *
+ * Attach a single form element to the form. It will be built out and
+ * validated in the callback(s) listed in hook_elements. We build it
+ * out in the callbacks rather than here in hook_widget so it can be
+ * plugged into any module that can provide it with valid
+ * $field information.
+ *
+ * Content module will set the weight, field name and delta values
+ * for each form element. This is a change from earlier CCK versions
+ * where the widget managed its own multiple values.
+ *
+ * If there are multiple values for this field, the content module will
+ * call this function as many times as needed.
+ *
+ * @param $form
+ *   the entire form array, $form['#node'] holds node information
+ * @param $form_state
+ *   the form_state, $form_state['values'][$field['field_name']]
+ *   holds the field's form values.
+ * @param $field
+ *   the field array
+ * @param $items
+ *   array of default values for this field
+ * @param $delta
+ *   the order of this item in the array of subelements (0, 1, 2, etc)
+ *
+ * @return
+ *   the form item for a single element for this field
+ */
+function bible_field_widget(&$form, &$form_state, $field, $items, $delta = 0) {
+  global $book_list;
+  // Need array of all the book abbrevs and their order.
+  $book_array = explode('|', $book_list);
+      
+  $ref_value  = $book_array[$items[$delta]['book']] . ' '; 
+  $ref_value .= $items[$delta]['chapter'] . ':' . $items[$delta]['verses'];
+  $items[$delta]['value'] = $ref_value;
+  
+  $element = array(
+    '#type' => 'textfield',
+    '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : '',
+  );
+  return $element;
+}
+
+/**
+ * Process an individual element.
+ *
+ * Build the form element. When creating a form using FAPI #process,
+ * note that $element['#value'] is already set.
+ *
+ * The $fields array is in $form['#field_info'][$element['#field_name']].
+ */
+function bible_field_bibleref_process($element, $edit, $form_state, $form) {
+  global $book_list;
+  // Need array of all the book abbrevs and their order.
+  $book_array = explode('|', $book_list);
+      
+  $field = $form['#field_info'][$element['#field_name']];
+  $field_key = $element['#columns'][0];
+  $delta = $element['#delta'];
+
+  $ref_value  = $book_array[$element['#value'][$field_key]['book']] . ' '; 
+  $ref_value .= $element['#value'][$field_key]['chapter'] . ':' . $element['#value'][$field_key]['verses'];
+  $element['#value'][$field_key]['value'] = $ref_value;
+  
+  $element[$field_key] = array(
+    '#type' => 'textfield',
+    '#default_value' => isset($element['#value'][$field_key]['value']) ? $element['#value'][$field_key]['value'] : NULL,
+    '#size' => 30,
+    '#attributes' => array('class' => 'bible-reference'),
+    // The following values were set by the content module and need
+    // to be passed down to the nested element.
+    '#title' => $element['#title'],
+    '#description' => $element['#description'],
+    '#required' => $element['#required'],
+    '#field_name' => $element['#field_name'],
+    '#type_name' => $element['#type_name'],
+    '#delta' => $element['#delta'],
+    '#columns' => $element['#columns'],
+  );
+
+  return $element;
+}
+
+/**
+ * FAPI theme for an individual text elements.
+ *
+ * The textfield or textarea is already rendered by the
+ * textfield or textarea themes and the html output
+ * lives in $element['#children']. Override this theme to
+ * make custom changes to the output.
+ *
+ * $element['#field_name'] contains the field name
+ * $element['#delta]  is the position of this element in the group
+ */
+function theme_bible_field_bibleref($element) {
+  return print_r($element, true);
+}
Index: bible_field.info
===================================================================
RCS file: bible_field.info
diff -N bible_field.info
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bible_field.info	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,8 @@
+;$Id$
+name = Bible Field
+description = Provides CCK and Views integration with the Bible Module
+version = "6.x-1.x-dev"
+package = Church
+core = 6.x
+dependencies[] = content
+dependencies[] = bible
