You are here

sheetnode.module in Sheetnode 5

Same filename and directory in other branches
  1. 6 sheetnode.module
  2. 7.2 sheetnode.module
  3. 7 sheetnode.module

File

sheetnode.module
View source
<?php

/**
 * Implementation of hook_node_info().
 */
function sheetnode_node_info() {
  return array(
    'sheetnode' => array(
      'name' => t('Sheetnode'),
      'module' => 'sheetnode',
      'description' => t('A spreadsheet node.'),
    ),
  );
}

/**
 * Implementation of hook_perm().
 */
function sheetnode_perm() {
  return array(
    'create sheetnode',
    'edit own sheetnode',
    'edit any sheetnode',
    'delete own sheetnode',
    'delete any sheetnode',
    'create sheet template',
    'edit sheet settings',
  );
}

/**
 * Implementation of hook_access().
 */
function sheetnode_access($op, $node, $account = NULL) {
  global $user;
  if (empty($account)) {
    $account = $user;
  }
  if ($op == 'create') {
    return user_access('create sheetnode', $account) ? TRUE : NULL;
  }
  if ($op == 'update') {
    return user_access('edit any sheetnode', $account) || user_access('edit own sheetnode', $account) && $account->uid == $node->uid ? TRUE : NULL;
  }
  if ($op == 'delete') {
    return user_access('delete any sheetnode', $account) || user_access('delete own sheetnode', $account) && $account->uid == $node->uid ? TRUE : NULL;
  }
}

/**
 * Implementation of hook_delete().
 */
function sheetnode_delete(&$node) {
  db_query('DELETE FROM {sheetnode} WHERE nid=%d', $node->nid);
}

/**
 * Implementation of hook_form().
 */
function sheetnode_form(&$node) {
  $type = node_get_types('type', $node);

  // Generate the default title and body.
  $form = node_content_form($node, NULL);

  // SocialCalc sheet.
  $nid = $node->nid;
  if (isset($_POST['sheetsave'])) {
    $value = $_POST['sheetsave'];
  }
  else {
    if (!empty($node->nid)) {
      $value = _sheetnode_load($node->nid, $node->vid);
    }
    else {
      if ($node->clone_from_original_nid) {

        // support node_clone.module
        $original_node = node_load($node->clone_from_original_nid);
        $value = _sheetnode_load($original_node->nid, $original_node->vid);
        $nid = $node->clone_from_original_nid;
      }
      else {
        $value = '';
      }
    }
  }
  $output = _sheetnode_inject($value, 'edit-sheetsave', array(
    'entity-name' => 'node',
    'oid' => $nid,
  ));
  $form['sheet']['sheetview'] = array(
    '#value' => $output,
    '#weight' => -1,
  );
  $form['sheet']['sheetsave'] = array(
    '#type' => 'hidden',
  );

  // Template.
  if (user_access('create sheet template')) {
    $form['template'] = array(
      '#type' => 'textfield',
      '#title' => t('Save as template'),
      '#description' => t('When saving this sheet, also keep a copy under the name you specify here. Later, this copy can be used as a template for other sheets.'),
      '#required' => FALSE,
    );
  }
  return $form;
}

/**
 * Implementation of hook_form_alter().
 */
function sheetnode_form_alter($form_id, &$form) {
  if (isset($form['type']) && isset($form['type']['#value']) && $form['type']['#value'] == 'sheetnode') {
    unset($form['preview']);
  }
}
function _sheetnode_inject($value, $save_element, $context) {
  drupal_add_js(drupal_get_path('module', 'sheetnode') . '/socialcalc/socialcalcconstants.js');
  drupal_add_js(drupal_get_path('module', 'sheetnode') . '/socialcalc/socialcalc-3.js');
  drupal_add_js(drupal_get_path('module', 'sheetnode') . '/socialcalc/socialcalctableeditor.js');
  drupal_add_js(drupal_get_path('module', 'sheetnode') . '/socialcalc/formatnumber2.js');
  drupal_add_js(drupal_get_path('module', 'sheetnode') . '/socialcalc/formula1.js');
  drupal_add_js(drupal_get_path('module', 'sheetnode') . '/socialcalc/socialcalcpopup.js');
  drupal_add_js(drupal_get_path('module', 'sheetnode') . '/socialcalc/socialcalcspreadsheetcontrol.js');
  drupal_add_js(drupal_get_path('module', 'sheetnode') . '/socialcalc/socialcalcviewer.js');
  drupal_add_js(drupal_get_path('module', 'sheetnode') . '/sheetnode.js');
  drupal_add_css(drupal_get_path('module', 'sheetnode') . '/socialcalc/socialcalc.css');
  drupal_add_css(drupal_get_path('module', 'sheetnode') . '/sheetnode.css');
  module_invoke_all('sheetnode_plugins', $value, $save_element, $context);
  static $once = FALSE;
  if (!$once) {
    $once = TRUE;
    drupal_add_js(array(
      'sheetnode' => array(
        'basePath' => url(),
        'value' => $value,
        'imagePrefix' => url(drupal_get_path('module', 'sheetnode') . '/socialcalc/images/sc-'),
        'containerElement' => 'sheetview',
        'saveElement' => $save_element,
        'viewMode' => variable_get('sheetnode_view_mode', SHEETNODE_VIEW_FIDDLE),
        'showToolbar' => variable_get('sheetnode_view_toolbar', FALSE),
        'permissions' => array(
          'edit sheet settings' => user_access('edit sheet settings'),
        ),
        'context' => $context,
      ),
    ), 'setting');
    drupal_add_js('$(document).ready(function() { Drupal.sheetnode.start("body"); });', 'inline');
  }
  return '<div class="sheetview" id="sheetview"></div>';
}
function _sheetnode_sanitize_js($value) {
  $chars = array(
    chr(0xe2) . chr(0x80) . chr(0xa8),
  );
  return str_replace($chars, '', $value);
}

/**
 * Implementation of hook_insert().
 */
function sheetnode_insert($node) {
  if ($node->sheetsave) {
    _sheetnode_save($node->nid, $node->vid, $node->sheetsave);
  }
  if ($node->template && user_access('create sheet template')) {
    _sheetnode_template_save($node->vid, $node->template, $node->sheetsave);
  }
}

/**
 * Implementation of hook_update().
 */
function sheetnode_update($node) {
  if (!empty($node->sheetsave)) {
    _sheetnode_save($node->nid, $node->vid, $node->sheetsave);
  }
  else {
    if (!empty($node->revision)) {

      // reverting a revision
      db_query('INSERT INTO {sheetnode} (nid,vid,value) SELECT old.nid,%d,old.value FROM sheetnode AS old WHERE old.vid=%d', array(
        $node->vid,
        $node->old_vid,
      ));
    }
  }
  if (!empty($node->template) && user_access('create sheet template')) {
    _sheetnode_template_save($node->vid, $node->template, $node->sheetsave);
  }
}

/**
 * Implementation of hook_view().
 */
function sheetnode_view($node, $teaser = FALSE, $page = FALSE) {
  $node = node_prepare($node, $teaser);

  // SocialCalc sheet.
  if (!$teaser) {
    $value = _sheetnode_load($node->nid, $node->vid);
    $output = _sheetnode_inject($value, FALSE, array(
      'entity-name' => 'node',
      'oid' => $node->nid,
    ));
    $node->content['sheet'] = array(
      '#value' => $output,
      '#weight' => -1,
    );
  }
  return $node;
}

/**
 * Implementation of hook_nodeapi().
 */
function sheetnode_nodeapi($node, $op) {
  if ($node->type != 'sheetnode') {
    return;
  }
  switch ($op) {
    case 'update index':
      require_once drupal_get_path('module', 'sheetnode') . '/socialcalc.inc';
      $output = '<table>';
      $socialcalc = socialcalc_parse(_sheetnode_load($node->nid, $node->vid));
      $sc = $socialcalc['sheet'];
      $row = -1;
      if (!empty($sc['cells'])) {
        foreach ($sc['cells'] as $c) {
          if ($c['pos'][1] > $row) {

            // new row?
            if ($row != -1) {
              $output .= '</tr>';
            }
            $row = $c['pos'][1];
            $output .= '<tr>';
          }
          $output .= '<td>' . (isset($c['datavalue']) ? $c['datavalue'] : '&nbsp;') . (isset($c['comment']) ? ' (' . check_plain($c['comment']) . ')' : '') . '</td>';
        }
      }
      if ($row != -1) {
        $output .= '</tr>';
      }
      $output .= '</table>';
      return $output;
  }
}

/**
 * Implementation of hook_menu().
 */
function sheetnode_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'node/add/sheetnode',
      'title' => t('Sheetnode'),
      'access' => user_access('create sheetnode'),
    );
    $items[] = array(
      'path' => 'sheetnode/load',
      'type' => MENU_CALLBACK,
      'callback' => '_sheetnode_ajax_load',
      'access' => user_access('access content'),
    );
    $items[] = array(
      'path' => 'sheetnode/field',
      'type' => MENU_CALLBACK,
      'callback' => '_sheetnode_ajax_field',
      'access' => user_access('access content'),
    );
    $items[] = array(
      'path' => 'node/add/sheetnode_template',
      'title' => t('Sheetnode import from template'),
      'access' => user_access('create sheetnode'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'sheetnode_import_template',
      ),
    );
    $items[] = array(
      'path' => 'admin/settings/sheetnode',
      'title' => t('Sheetnode'),
      'access' => user_access('administer site configuration'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'sheetnode_admin_settings',
      ),
    );
    $items[] = array(
      'path' => 'admin/settings/sheetnode/general',
      'title' => t('General'),
      'access' => user_access('administer site configuration'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'sheetnode_admin_settings',
      ),
      'type' => MENU_DEFAULT_LOCAL_TASK,
      'weight' => -10,
    );
  }
  return $items;
}
define('SHEETNODE_VIEW_READONLY', 0);
define('SHEETNODE_VIEW_FIDDLE', 1);
define('SHEETNODE_VIEW_HTML', 2);
function sheetnode_admin_settings() {
  $form['sheetnode_view_mode'] = array(
    '#type' => 'radios',
    '#title' => t('View mode'),
    '#description' => t('Select the way sheetnodes should be displayed in view mode.'),
    '#options' => array(
      SHEETNODE_VIEW_READONLY => t('Read-only spreadsheet'),
      SHEETNODE_VIEW_FIDDLE => t('Fiddle mode (interactive spreadsheet without save functionality)'),
      SHEETNODE_VIEW_HTML => t('HTML table'),
    ),
    '#default_value' => variable_get('sheetnode_view_mode', SHEETNODE_VIEW_FIDDLE),
  );
  $form['sheetnode_view_toolbar'] = array(
    '#type' => 'checkbox',
    '#title' => t('Show toolbar in view mode'),
    '#default_value' => variable_get('sheetnode_view_toolbar', FALSE),
  );
  return system_settings_form($form);
}
function sheetnode_import_template() {
  $options[0] = t('- Please choose a template -');
  $result = db_query("SELECT tid, name FROM {sheetnode_template}");
  while ($template = db_fetch_object($result)) {
    $options[$template->tid] = $template->name;
  }
  $form['template'] = array(
    '#type' => 'select',
    '#title' => t('Template'),
    '#description' => t('Please select the template to load into your new sheetnode.'),
    '#options' => $options,
    '#default_value' => 0,
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
  );
  return $form;
}
function sheetnode_import_template_validate($form, $form_values) {
  if (!$form_values['template']) {
    form_set_error('template', t('Please select a template.'));
  }
}
function sheetnode_import_template_submit($form, $form_values) {
  global $user;
  $template = db_fetch_object(db_query("SELECT * FROM {sheetnode_template} WHERE tid=%d", $form_values['template']));
  $node = array(
    'type' => 'sheetnode',
    'name' => $user->name,
  );
  $form_state_node = array();
  $form_state_node['title'] = $template->name;
  $form_state_node['body'] = '';
  $form_state_node['name'] = $user->name;
  $form_state_node['sheetsave'] = unserialize($template->value);

  // Allow other modules to modify the new node's creation parameters.
  // Hook signature: hook_sheetnode_alter(&$form_state_node, $form, $form_state);

  //drupal_alter('sheetnode', $form_state_node, $form, $form_state);
  $result = drupal_execute('sheetnode_node_form', $form_state_node, (object) $node);
  return $result . '/edit';
}

/**
 * Implementation of hook_views_api().
 */
function sheetnode_views_api() {
  return array(
    'api' => 2.0,
  );
}

/**
 * Implementation of hook_theme().
 */
function sheetnode_theme($existing, $type, $theme, $path) {
  return array(
    'sheetnode_range' => array(
      'arguments' => array(
        'range' => NULL,
      ),
    ),
    'sheetfield_spreadsheet' => array(
      'arguments' => array(
        'element' => NULL,
      ),
    ),
    'sheetnode_formatter_default' => array(
      'arguments' => array(
        'element' => NULL,
      ),
    ),
    'sheetnode_formatter_socialcalc_date' => array(
      'arguments' => array(
        'element' => NULL,
      ),
    ),
  );
}
function theme_sheetnode_range($range) {
  if (empty($range)) {
    return '';
  }
  require_once drupal_get_path('module', 'sheetnode') . '/socialcalc.inc';
  list($c, $r) = socialcalc_coord_to_cr(key($range));
  $row = array();
  $row[] = array(
    'data' => $r,
    'header' => TRUE,
  );
  $header = array();
  $header[] = array();
  $rows = array();
  foreach ($range as $coord => $value) {
    $pos = socialcalc_coord_to_cr($coord);
    if ($pos[1] > $r) {
      $rows[] = $row;
      $r = $pos[1];
      $row = array();
      $row[] = array(
        'data' => $r,
        'header' => TRUE,
      );
    }
    $row[] = $value;
    if (empty($rows)) {
      $coord = socialcalc_cr_to_coord($pos[0], $pos[1], TRUE);
      $header[] = $coord[0];
    }
  }
  $rows[] = $row;
  return theme('table', $header, $rows);
}

/**
 * Implementation of hook_init().
 */
function sheetnode_init() {

  // TODO: This is here for the view admin page. Find another way to include them or at least restrict the path.
  drupal_add_css(drupal_get_path('module', 'sheetnode') . '/socialcalc/socialcalc.css');
  drupal_add_css(drupal_get_path('module', 'sheetnode') . '/sheetnode.css');
}

/**
 * Implementation of hook_content_extra_fields().
 */
function sheetnode_content_extra_fields($type_name) {
  $extra = array();
  if ($type_name == 'sheetnode') {
    $extra['sheet'] = array(
      'label' => t('Sheetview'),
      'description' => t('Sheetnode module form.'),
      'weight' => -1,
    );
  }
  return $extra;
}

/**
 * Implementation of hook_field_info().
 */
function sheetnode_field_info() {
  return array(
    'sheetfield' => array(
      'label' => t('Sheet'),
      'description' => t('Store a spreadsheet in the database.'),
    ),
  );
}

/**
 * Implementation of hook_field_settings().
 */
function sheetnode_field_settings($op, $field) {
  switch ($op) {
    case 'form':
      break;
    case 'save':
      break;
    case 'database columns':
      require_once drupal_get_path('module', 'sheetnode') . '/sheetnode.install';
      $schema = sheetnode_schema();
      $columns['value'] = $schema['sheetnode']['fields']['value'];
      return $columns;
    case 'views data':
      break;
  }
}

/**
 * Implementation of hook_field().
 */
function sheetnode_field($op, &$node, $field, &$items, $teaser, $page) {
  switch ($op) {
    case 'insert':
    case 'update':
      break;
  }
}

/**
 * Implementation of hook_content_is_empty().
 */
function sheetnode_content_is_empty($item, $field) {

  // TODO
  return FALSE;
}

/**
 * Implementation of hook_field_formatter_info().
 */
function sheetnode_field_formatter_info() {
  return array(
    'default' => array(
      'label' => t('Default'),
      'field types' => array(
        'sheetfield',
      ),
      'multiple values' => CONTENT_HANDLE_CORE,
    ),
    'socialcalc_date' => array(
      'label' => t('SocialCalc'),
      'field types' => array(
        'date',
        'datetime',
        'datestamp',
      ),
      'multiple values' => CONTENT_HANDLE_CORE,
    ),
  );
}

/**
 * Implementation of hook_widget_info().
 */
function sheetnode_widget_info() {
  return array(
    'sheetfield_spreadsheet' => array(
      'label' => t('Spreadsheet'),
      'field types' => array(
        'sheetfield',
      ),
      'multiple values' => CONTENT_HANDLE_CORE,
      'callbacks' => array(
        'default value' => CONTENT_CALLBACK_DEFAULT,
      ),
    ),
  );
}

/**
 * Implementation of hook_widget_settings().
 */
function sheetnode_widget_settings($op, $widget) {
  switch ($op) {
    case 'form':
      break;
    case 'save':
      break;
  }
}

/**
 * Implementation of hook_widget().
 */
function sheetnode_widget(&$form, &$form_state, $field, $items, $delta = 0) {
  $element = array(
    '#type' => $field['widget']['type'],
    '#default_value' => isset($items[$delta]) ? $items[$delta] : '',
  );
  return $element;
}

/**
 * Implementation of FAPI hook_elements().
 */
function sheetnode_elements() {
  return array(
    'sheetfield_spreadsheet' => array(
      '#input' => TRUE,
      '#columns' => array(
        'value',
      ),
      '#delta' => 0,
      '#process' => array(
        'sheetfield_spreadsheet_process',
      ),
      '#autocomplete_path' => FALSE,
    ),
  );
}
function sheetfield_spreadsheet_process($element, $edit, $form_state, $form) {
  $field_key = $element['#columns'][0];
  $delta = $element['#delta'];
  $value = isset($element['#default_value']) ? is_array($element['#default_value']) ? $element['#default_value']['value'] : $element['#default_value'] : (isset($element['#value'][$field_key]) && is_string($element['#value'][$field_key]) ? $element['#value'][$field_key] : '');
  $output = _sheetnode_inject($value, $element['#id'] . '-' . $field_key, isset($form['#node']) ? array(
    'entity-name' => 'node',
    'oid' => $form['#node']->nid,
  ) : NULL);
  $element['sheetview'] = array(
    '#value' => $output,
    '#weight' => -1,
  );
  $element[$field_key] = array(
    '#type' => 'hidden',
  );
  $element['#tree'] = TRUE;
  return $element;
}
function theme_sheetfield_spreadsheet($element) {
  return theme('form_element', $element, $element['#children']);
}
function theme_sheetnode_formatter_default($element) {
  $value = $element['#item']['value'];
  $output = _sheetnode_inject($value, FALSE, isset($element['#node']) ? array(
    'entity-name' => 'node',
    'oid' => $element['#node']->nid,
  ) : NULL);
  return $output;
}
function theme_sheetnode_formatter_socialcalc_date($element) {
  require_once drupal_get_path('module', 'sheetnode') . '/socialcalc.inc';
  $field_name = $element['#field_name'];
  $fields = content_fields();
  $field = $fields[$field_name];
  $item = $element['#item'];
  $value = $item['value'];
  if ($field['type'] == DATE_ISO) {
    $value = str_replace(' ', 'T', date_fuzzy_datetime($value));
  }
  $date = date_make_date($value, NULL, $field['type'], $field['granularity']);
  return socialcalc_import_date($date);
}
function _sheetnode_ajax_load($sheetname = NULL, $vid = NULL) {
  require_once drupal_get_path('module', 'sheetnode') . '/socialcalc.inc';

  // Try to find a sheetnode.
  if (empty($sheetname)) {
    $sheetname = $_REQUEST['sheetname'];
  }
  if (is_numeric($sheetname)) {
    $value = db_result(db_query("SELECT value FROM {sheetnode} WHERE nid=%d ORDER BY vid DESC LIMIT 1", intval($sheetname)));
  }
  else {
    $value = db_result(db_query("SELECT value FROM {sheetnode} s INNER JOIN {node} n ON s.nid=n.nid WHERE UCASE(n.title)='%s' ORDER BY s.vid DESC LIMIT 1", db_escape_string(strtoupper($sheetname))));
  }

  // Try to find a sheetfield.
  if (!$value && module_exists('content')) {
    if (is_numeric($sheetname)) {
      $node = node_load(intval($sheetname));
      if ($node) {
        $type = content_types($node->type);
        foreach ($type['fields'] as $field_name => $field_info) {
          if ($field_info['type'] == 'sheetfield' && isset($node->{$field_name})) {
            $value = $node->{$field_name}[0]['value'];
          }
        }
      }
    }
  }

  // Try to find a sheetview.
  if (!$value && module_exists('views')) {

    // Try a view feed with our SocialCalc output plugin style
    $view = views_get_view($sheetname);
    if ($view) {
      foreach (array_keys($view->display) as $display_name) {
        $display = $view->display[$display_name];
        if (isset($display->display_options['style_plugin']) && $display->display_options['style_plugin'] == 'sheet_raw') {
          $value = $view
            ->render($display->id);
          header('Content-type: text/html');

          // Our style plugin sets this to text/plain
        }
      }
    }
  }

  // Found a spreadsheet: return it.
  if ($value) {
    $parts = socialcalc_parse_parts($value);
    if (isset($parts['sheet'])) {
      echo $parts['sheet'];
    }
  }
  exit;
}
function _sheetnode_ajax_field($oid = NULL, $entity = NULL, $field = NULL) {
  if (!$oid) {
    $oid = $_REQUEST['oid'];
  }
  if (!$entity) {
    $entity = $_REQUEST['entity'];
  }
  if (!$field) {
    $field = $_REQUEST['field'];
  }
  if (function_exists($entity . '_load')) {
    $object = call_user_func($entity . '_load', $oid);
    $value = NULL;
    if ($object) {

      // Try CCK field.
      if ($entity == 'node' && module_exists('content')) {
        $field_info = content_fields($field, $object->type);
        if ($field_info) {
          $field_info['display_settings']['label']['format'] = 'hidden';
          $value = content_view_field($field_info, $object, FALSE, TRUE);
        }
      }

      // Try rendered node field.
      if (!$value && $entity == 'node') {
        $node = drupal_clone($object);
        $node = node_build_content($node);
        if (isset($node->content[$field])) {
          $value = drupal_render($node->content[$field]);
        }
      }

      // Try raw object field.
      if (!$value && isset($object->{$field})) {
        if (is_object($object->{$field}) || is_array($object->{$field})) {
          $value = print_r($object->{$field}, TRUE);
        }
        else {
          $value = $object->{$field};
        }
      }

      // If found, send it back.
      if ($value) {
        _sheetnode_json(array(
          'type' => is_numeric($value) ? 'n' : 'th',
          'value' => $value,
        ));
        exit;
      }
    }
  }
  _sheetnode_json(array(
    'value' => '',
    'type' => 'e#NAME?',
  ));
  exit;
}
function _sheetnode_json($var = NULL) {

  // We are returning JavaScript, so tell the browser.
  drupal_set_header('Content-Type: text/javascript; charset=utf-8');
  if (isset($var)) {
    echo drupal_to_js($var);
  }
}
function _sheetnode_load($nid, $vid) {
  $value = db_result(db_query("SELECT value FROM {sheetnode} WHERE nid=%d AND vid=%d", $nid, $vid));
  return $value ? unserialize($value) : '';
}
function _sheetnode_save($nid, $vid, $value) {
  db_query("DELETE FROM {sheetnode} WHERE vid=%d", $vid);
  db_query("INSERT INTO {sheetnode} (nid, vid, value) VALUES (%d, %d, '%s')", $nid, $vid, serialize(_sheetnode_sanitize_js($value)));
}
function _sheetnode_template_save($vid, $name, $value) {
  db_query("DELETE FROM {sheetnode_template} WHERE vid=%d", $vid);
  db_query("INSERT INTO {sheetnode_template} (vid, name, value) VALUES (%d, '%s', '%s')", $vid, db_escape_string($name), serialize(_sheetnode_sanitize_js($value)));
}
function _sheetnode_sanitize_filename($filename, $extension) {
  $filename = preg_replace('/[^a-zA-Z0-9-_.]/', '-', $filename);
  $filename .= '.' . $extension;
  return $filename;
}

Functions

Namesort descending Description
sheetfield_spreadsheet_process
sheetnode_access Implementation of hook_access().
sheetnode_admin_settings
sheetnode_content_extra_fields Implementation of hook_content_extra_fields().
sheetnode_content_is_empty Implementation of hook_content_is_empty().
sheetnode_delete Implementation of hook_delete().
sheetnode_elements Implementation of FAPI hook_elements().
sheetnode_field Implementation of hook_field().
sheetnode_field_formatter_info Implementation of hook_field_formatter_info().
sheetnode_field_info Implementation of hook_field_info().
sheetnode_field_settings Implementation of hook_field_settings().
sheetnode_form Implementation of hook_form().
sheetnode_form_alter Implementation of hook_form_alter().
sheetnode_import_template
sheetnode_import_template_submit
sheetnode_import_template_validate
sheetnode_init Implementation of hook_init().
sheetnode_insert Implementation of hook_insert().
sheetnode_menu Implementation of hook_menu().
sheetnode_nodeapi Implementation of hook_nodeapi().
sheetnode_node_info Implementation of hook_node_info().
sheetnode_perm Implementation of hook_perm().
sheetnode_theme Implementation of hook_theme().
sheetnode_update Implementation of hook_update().
sheetnode_view Implementation of hook_view().
sheetnode_views_api Implementation of hook_views_api().
sheetnode_widget Implementation of hook_widget().
sheetnode_widget_info Implementation of hook_widget_info().
sheetnode_widget_settings Implementation of hook_widget_settings().
theme_sheetfield_spreadsheet
theme_sheetnode_formatter_default
theme_sheetnode_formatter_socialcalc_date
theme_sheetnode_range
_sheetnode_ajax_field
_sheetnode_ajax_load
_sheetnode_inject
_sheetnode_json
_sheetnode_load
_sheetnode_sanitize_filename
_sheetnode_sanitize_js
_sheetnode_save
_sheetnode_template_save

Constants