FeedsExcelParser.inc in Feeds Excel 7.2
Contains FeedsExcelParser.
File
FeedsExcelParser.incView source
<?php
/**
* @file
* Contains FeedsExcelParser.
*/
/**
* Provides feeds parser class for Excel files.
*/
class FeedsExcelParser extends FeedsParser {
private $file_path;
private $library;
private $reader;
/**
* Init file path.
*/
private function initFilePath(FeedsFetcherResult $fetcher_result) {
if (!isset($this->file_path)) {
$this->file_path = drupal_realpath($fetcher_result
->getFilePath());
}
}
/**
* Init PHPExcel library.
*/
private function initLibrary() {
if (!isset($this->library)) {
$this->library = libraries_load('PHPExcel');
if (empty($this->library['loaded'])) {
throw new Exception(t('PHPExcel missed.'));
}
}
}
/**
* Init PHPExcel reader.
*/
private function initReader() {
if (!isset($this->reader)) {
$this->reader = PHPExcel_IOFactory::createReaderForFile($this->file_path);
$this->reader
->setReadDataOnly(TRUE);
}
}
/**
* Get total rows.
*/
private function getTotal() {
$this->reader
->setReadFilter(new FeedsExcelParserIReadFilter());
$this->reader
->load($this->file_path);
return drupal_static('feeds_excel_parser_row_counter');
}
/**
* Parse first row as headers.
*/
private function getHeaders() {
$headers = array();
$this->reader
->setReadFilter(new FeedsExcelParserIReadFilter(1, 1));
foreach ($this->reader
->load($this->file_path)
->getSheet()
->getRowIterator() as $row) {
foreach ($row
->getCellIterator() as $cell_index => $cell) {
$headers[$cell_index] = filter_xss($cell
->getValue());
}
}
return $headers;
}
/**
* {@inheritdoc}
*/
public function parse(FeedsSource $source, FeedsFetcherResult $fetcher_result) {
// Init vars.
$this
->initFilePath($fetcher_result);
$this
->initLibrary();
$this
->initReader();
// Init state. Use two pointers: global and by sheet.
$state = $source
->state(FEEDS_PARSE);
$state->total = !empty($state->total) ? $state->total : $this
->getTotal();
$state->pointer = !empty($state->pointer) ? $state->pointer : array(
'sheet_pointer' => 1,
'processed_rows' => array(),
);
// Prepare to parsing.
$items = array();
$filter = new FeedsExcelParserIReadFilter($state->pointer['sheet_pointer'], $this->config['chunk_size']);
$this->reader
->setReadFilter($filter);
$excel = $this->reader
->load($this->file_path);
// Setup parse type.
switch ($this->config['sheets']['parse_type']) {
case 'first':
$sheets = array(
$excel
->getSheet(),
);
break;
case 'title':
$sheets = array(
$excel
->getSheetByName($this->config['sheets']['parse_value']),
);
break;
case 'index':
$sheets = array(
$excel
->getSheet($this->config['sheets']['parse_value']),
);
break;
default:
$sheets = $excel
->getWorksheetIterator();
}
// Check for errors.
if (is_array($sheets) && in_array(NULL, $sheets)) {
throw new Exception(t('Wrong sheet !type: !value.', array(
'!type' => $this->config['sheets']['parse_type'],
'!value' => $this->config['sheets']['parse_value'],
)));
}
// Parse values.
foreach ($sheets as $sheet) {
foreach ($sheet
->getRowIterator() as $row_index => $row) {
// Generate row key.
$row_key = implode('__', array(
$sheet
->getTitle(),
$row_index,
));
// Iterate cells.
foreach ($row
->getCellIterator() as $cell_index => $cell) {
// Detect headers row.
if (!$this->config['no_headers'] && $row_index === 1 && !is_null($header = $cell
->getCalculatedValue())) {
$state->pointer['headers'][$cell_index] = $header;
continue;
}
// Detect cell index and put values if not empty.
$cell_key = !$this->config['no_headers'] && !empty($state->pointer['headers'][$cell_index]) ? $state->pointer['headers'][$cell_index] : $cell_index;
$value = $this->config['calculate'] ? $cell
->getCalculatedValue() : $cell
->getValue();
if (!is_null($value)) {
$items[$row_key][$cell_key] = $value;
}
}
// Add sheet title to values.
if (isset($items[$row_key]) && !empty($this->config['sheets']['map_title'])) {
$items[$row_key][$this->config['sheets']['map_title']] = $sheet
->getTitle();
}
// Increment row pointer.
$state->pointer['sheet_pointer'] = $row_index + 1;
// Save row as processed.
$state->pointer['processed_rows'][$row_key] = $row_key;
}
}
$state
->progress($state->total, count($state->pointer['processed_rows']));
return new FeedsParserResult(array_values($items));
}
/**
* {@inheritdoc}
*/
public function clear(FeedsSource $source) {
}
/**
* {@inheritdoc}
*/
public function getMappingSources() {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function configDefaults() {
return array(
'chunk_size' => 10,
'no_headers' => 0,
'calculate' => 0,
'sheets' => array(
'parse_type' => 'all',
'parse_value' => '',
'map_title' => '',
),
);
}
/**
* {@inheritdoc}
*/
public function configForm(&$form_state) {
$form = array();
$form['chunk_size'] = array(
'#type' => 'select',
'#title' => t('Chunk size'),
'#options' => drupal_map_assoc(array(
1,
5,
10,
20,
50,
100,
200,
)),
'#description' => t("Select quantity of rows which will be parsed per ounce. <b>Notice: selected quantity will be multiplied on sheets' quantity.</b>"),
'#default_value' => $this->config['chunk_size'],
);
$form['no_headers'] = array(
'#type' => 'checkbox',
'#title' => t('No headers'),
'#description' => t("Check if the imported Excel file does not start with a header row. If checked, mapping sources must be named '0', '1', '2' etc."),
'#default_value' => $this->config['no_headers'],
);
$form['calculate'] = array(
'#type' => 'checkbox',
'#title' => t('Calculate'),
'#description' => t('Check if need to calculate cells data via getCalculatedValue()'),
'#default_value' => $this->config['calculate'],
);
$form['sheets'] = array(
'#type' => 'fieldset',
'#title' => t('Sheets settings'),
'#tree' => TRUE,
);
$form['sheets']['parse_type'] = array(
'#type' => 'select',
'#title' => t('How to parse?'),
'#default_value' => $this->config['sheets']['parse_type'],
'#options' => array(
'all' => t('All sheets'),
'first' => t('First sheet'),
'title' => t('By title'),
'index' => t('By index'),
),
);
$form['sheets']['parse_value'] = array(
'#type' => 'textfield',
'#default_value' => $this->config['sheets']['parse_value'],
'#states' => array(
'visible' => array(
array(
array(
'select[name="sheets[parse_type]"]' => array(
'value' => 'title',
),
),
'or',
array(
'select[name="sheets[parse_type]"]' => array(
'value' => 'index',
),
),
),
),
),
);
$form['sheets']['map_title'] = array(
'#type' => 'textfield',
'#title' => t('Source key of sheet title'),
'#description' => t('If filled, sheet title will be available in mapping.'),
'#default_value' => $this->config['sheets']['map_title'],
);
return $form;
}
}
Classes
Name | Description |
---|---|
FeedsExcelParser | Provides feeds parser class for Excel files. |