sheetnode_text.module in Sheetnode 7.2
Same filename and directory in other branches
Module file for the sheetnode_text module.
This extends sheetnodes to enable importing of text to sheetnodes.
File
modules/sheetnode_text/sheetnode_text.moduleView source
<?php
/**
* @file
* Module file for the sheetnode_text module.
*
* This extends sheetnodes to enable importing of text to sheetnodes.
*/
/**
* Implementation of hook_menu().
*/
function sheetnode_text_menu() {
$items['node/add/sheetnode_text'] = array(
'title' => 'Sheetnode import from text table',
'access arguments' => array(
'create sheetnode',
),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'sheetnode_text_import_form',
),
'description' => 'Create a new sheetnode with content from a text table.',
);
return $items;
}
/**
* Callback for import form.
*/
function sheetnode_text_import_form() {
$form['title'] = array(
'#type' => 'textfield',
'#title' => t('Title'),
'#description' => t('Spreadsheet title.'),
);
$form['text'] = array(
'#type' => 'textarea',
'#title' => t('Text'),
'#description' => t('Text representation of table to import.'),
'#required' => TRUE,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
return $form;
}
/**
* Submit handler for import form.
*/
function sheetnode_text_import_form_submit($form, &$form_state) {
module_load_include('inc', 'node', 'node.pages');
global $user;
$title = $form_state['values']['title'];
$text = $form_state['values']['text'];
$options = array(
'ignore_spans' => variable_get('sheetnode_text_ignore_spans', FALSE),
'process_dividers' => variable_get('sheetnode_text_process_dividers', TRUE),
);
$sc = sheetnode_text_import($text, $options);
$node = new StdClass();
$node->type = 'sheetnode';
node_object_prepare($node);
$node->title = $title;
$node->name = $user->name;
$node->language = LANGUAGE_NONE;
$node->sheetnode['value'] = $sc;
$node->sheetnode['template'] = NULL;
$context = array(
'text' => $text,
'options' => $options,
);
$params = array();
drupal_alter('sheetnode_import', $node, $params, $context);
// Save the sheetnode.
$node = node_submit($node);
node_save($node);
if (!empty($node->nid)) {
$form_state['redirect'] = 'node/' . $node->nid;
}
}
/**
* API function to import a URL.
*/
function sheetnode_text_import($text, $options = array()) {
module_load_include('inc', 'sheetnode', 'socialcalc');
$sheet = array();
sheetnode_text_import_table($text, $sheet, $options);
$socialcalc = array(
'sheet' => $sheet,
'edit' => socialcalc_default_edit($sheet),
'audit' => socialcalc_default_audit($sheet),
);
return socialcalc_save($socialcalc);
}
/**
* API function to import a single table.
*/
function sheetnode_text_import_table($table, &$sheet, $options = array()) {
// 1. Split text into lines->ranges.
// Consider row with maximum number of ranges = header.
$rows = array();
$maxcols = 0;
foreach (preg_split("/(\r?\n)|<br\\s*\\/>/", $table) as $line) {
$elements = preg_split("/\\s{2,}|\\|/", $line, -1, PREG_SPLIT_OFFSET_CAPTURE | PREG_SPLIT_NO_EMPTY);
$row = array();
foreach ($elements as $i => $element) {
$text = $element[0];
$start = $element[1];
$row[] = array(
'start' => $start,
'end' => isset($elements[$i + 1]) ? $elements[$i + 1][1] - 1 : mb_strlen($line) - 1,
'text' => $text,
);
}
if (count($row) > $maxcols) {
$maxcols = count($row);
$header = $row;
}
$rows[] = $row;
}
// 2. Match ranges to cells.
// col, row.
$pos = $maxpos = array(
1,
@$sheet['attribs']['lastrow'] + 1,
);
$cell = $cells = $spans = array();
foreach ($rows as $row) {
foreach ($row as $range) {
// Find column of this range.
$pos[0] = count($header) - 1;
foreach ($header as $c => $h) {
if ($range['start'] <= $h['end']) {
$pos[0] = $c + 1;
break;
}
}
// Find colspan of this range.
$colspan = 1;
for ($i = $c; $i < count($header); $i++) {
$h = $i < count($header) - 1 ? $header[$i + 1] : NULL;
if (empty($h)) {
break;
}
if ($range['end'] < $h['start']) {
break;
}
$colspan++;
}
$colspan = min($colspan, count($header));
// TODO: Find rowspan of this range.
$rowspan = 1;
// Create cell.
$value = _sheetnode_text_import_value($range['text']);
if (!empty($options['process_dividers']) && preg_match('/^-+$/', $value)) {
$value = NULL;
}
$cell = array();
$cell['pos'] = $pos;
$cell['datavalue'] = $value;
$cell['datatype'] = is_numeric($value) ? 'v' : 't';
$cell['valuetype'] = is_numeric($value) ? 'n' : 'th';
if ($colspan > 1 && empty($options['ignore_spans'])) {
$cell['colspan'] = $colspan;
}
if (!empty($value)) {
$cells[socialcalc_cr_to_coord($pos[0], $pos[1])] = $cell;
}
for ($r = $pos[1]; $r < $pos[1] + $rowspan; $r++) {
$spans[socialcalc_cr_to_coord($pos[0], $r)] = TRUE;
}
$pos[0] += $colspan;
$maxpos[0] = max($maxpos[0], $pos[0]);
}
// Advance to next row.
if ($pos[0] > 1) {
$pos[1]++;
}
$maxpos[1] = max($maxpos[1], $pos[1]);
}
$sheet['cells'] = isset($sheet['cells']) ? $sheet['cells'] + $cells : $cells;
$sheet['attribs']['lastcol'] = max(@$sheet['attribs']['lastcol'], $maxpos[0] - 1);
$sheet['attribs']['lastrow'] = max(@$sheet['attribs']['lastrow'], $maxpos[1] - 1);
}
/**
* Utility function to import a cell value.
*/
function _sheetnode_text_import_value($val) {
$val = trim($val);
$num = parse_formatted_number($val);
return $num === FALSE ? $val : $num;
}
Functions
Name | Description |
---|---|
sheetnode_text_import | API function to import a URL. |
sheetnode_text_import_form | Callback for import form. |
sheetnode_text_import_form_submit | Submit handler for import form. |
sheetnode_text_import_table | API function to import a single table. |
sheetnode_text_menu | Implementation of hook_menu(). |
_sheetnode_text_import_value | Utility function to import a cell value. |