%PDF- %PDF-
Direktori : /home/lightco1/upgrade.lightco.com.au/administrator/components/com_csvi/helper/file/import/ |
Current File : /home/lightco1/upgrade.lightco.com.au/administrator/components/com_csvi/helper/file/import/xml.php |
<?php /** * @package CSVI * @subpackage File * * @author Roland Dalmulder <contact@csvimproved.com> * @copyright Copyright (C) 2006 - 2016 RolandD Cyber Produksi. All rights reserved. * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html * @link http://www.csvimproved.com */ defined('_JEXEC') or die; /** * XML file importer. * * @package CSVI * @subpackage File * @since 6.0 */ class CsviHelperFileImportXml extends CsviHelperFile { /** * Contains the data that is read from file * * @var XMLReader * @since 3.0 */ protected $data; /** * Contains the record name to read from the XML * * @var string * @since 3.0 */ private $recordName = ''; /** * Internal line pointer * * @var int * @since 3.0 */ public $linepointer = 0; /** * Holds the CSVI fields helper * * @var CsviHelperImportFields * @since 6.0 */ protected $fields; /** * Load the column headers from a file. * * @return mixed array when column headers are found | false if column headers cannot be read. * * @since 3.0 */ public function loadColumnHeaders() { $columnheaders = array(); $continue = true; $line = 0; // Make sure the file is loaded $this->openFile(); // Start reading the XML file while ($this->data->read()) { // Only read the chosen records if ($this->data->nodeType == XMLREADER::ELEMENT && $this->data->name == $this->recordName && $continue ) { // Start reading the record while ($this->data->read() && $continue) { switch ($this->data->nodeType) { case (XMLREADER::ELEMENT): // Check if it has attributes if ($this->data->hasAttributes) { $parent[] = $this->data->name; // Get the attributes while ($this->data->moveToNextAttribute()) { // The attribute name if (empty($parent)) { $field_name = $this->data->name; } else { $field_name = implode('/', $parent) . '/' . $this->data->name; } $columnheaders[] = $field_name; } } elseif (!$this->data->isEmptyElement) { $parent[] = $this->data->name; } break; case (XMLREADER::END_ELEMENT): $line++; array_pop($parent); if ($this->data->name == $this->recordName) { $continue = false; } break; case XMLReader::TEXT: case XMLReader::CDATA: // The field name if (empty($parent)) { $field_name = $this->data->name; } else { $field_name = implode('/', $parent); } $columnheaders[] = $field_name; break; } } } elseif (!$continue) { break; } } // Reset the internal pointer $this->rewind(); return $columnheaders; } /** * Get the file position. * * @return int Current position in the file. * * @since 3.0 */ public function getFilePos() { return $this->linepointer; } /** * Set the file position * * To be able to set the file position correctly, the XML reader needs to be at the start of the file. * * @param int $pos The position to move to. * * @return int Current position in the file. * * @since 3.0 */ public function setFilePos($pos) { // Close the XML reader $this->closeFile(false); // Open a new XML reader $this->processFile(); // Move the pointer to the specified position return $this->skipXmlRecords($pos); } /** * Close the file. * * @param bool $removeFolder Set if the folder should be removed. * * @return void. * * @since 3.0 */ public function closeFile($removeFolder = true) { if ($this->data->close()) { $this->fp = false; } $this->closed = true; parent::closeFile($removeFolder); } /** * Read the next line in the file. * * @return array with the line of data read | false if data cannot be read. * * @since 3.0 */ public function readNextLine() { $parent = array(); $counters = array(); // Start reading the XML file while ($this->data->read()) { // Only read the chosen records if ($this->data->nodeType == XMLREADER::ELEMENT && $this->data->name == $this->recordName) { // Check if it has attributes if ($this->data->hasAttributes) { if (!$this->data->isEmptyElement) { $parent[] = $this->data->name; } // Get the attributes while ($this->data->moveToNextAttribute()) { // The attribute name if (empty($parent)) { $field_name = $this->data->name; } else { $field_name = implode('/', $parent) . '/' . $this->data->name; } // The attribute value $field_value = $this->data->value; // Add the field to the list of data if ($this->fields->valid($field_name)) { if (!isset($counters[$field_name])) { $counters[$field_name] = 0; } $counters[$field_name]++; $this->fields->set($field_name, $field_value, $counters[$field_name]); } } // Empty the parent as we are done $parent = array(); } // Start reading the record while ($this->data->read()) { switch ($this->data->nodeType) { case (XMLREADER::ELEMENT): // Check if it has attributes if ($this->data->hasAttributes) { $clearParent = false; if ($this->data->isEmptyElement) { $clearParent = true; } $parent[] = $this->data->name; // Get the attributes while ($this->data->moveToNextAttribute()) { // The attribute name if (empty($parent)) { $field_name = $this->data->name; } else { $field_name = implode('/', $parent) . '/' . $this->data->name; } // The attribute value $field_value = $this->data->value; // Add the field to the list of data if ($this->fields->valid($field_name)) { if (!isset($counters[$field_name])) { $counters[$field_name] = 0; } $counters[$field_name]++; $this->fields->set($field_name, $field_value, $counters[$field_name]); } } if ($clearParent) { array_pop($parent); } } else { if (!$this->data->isEmptyElement) { $parent[] = $this->data->name; } } break; case (XMLREADER::END_ELEMENT) : array_pop($parent); if ($this->data->name === $this->recordName) { $this->linepointer++; return true; } break; case XMLReader::TEXT: case XMLReader::CDATA: // The field name if (empty($parent)) { $field_name = $this->data->name; } else { $field_name = implode('/', $parent); } // The field value $field_value = $this->data->value; // Add the field to the list of data if ($this->fields->valid($field_name)) { if (!isset($counters[$field_name])) { $counters[$field_name] = 0; } $counters[$field_name]++; $this->fields->set($field_name, $field_value, $counters[$field_name]); } break; } } } } return false; } /** * Open the file to read. * * @return bool Returns true. * * @since 3.0 */ public function openFile() { if (!$this->fp) { // Use a streaming approach to support large files $this->data = new XMLReader; $this->fp = $this->data->open($this->filename); if ($this->fp == false) { $this->log->addStats('incorrect', JText::_('COM_CSVI_ERROR_XML_READING_FILE')); $app = JFactory::getApplication(); $app->enqueueMessage(JText::_('COM_CSVI_ERROR_XML_READING_FILE'), 'error'); return false; } } return true; } /** * Process the file to import. * * @return bool Always returns true. * * @since 3.0 */ public function processFile() { // Open the file if ($this->openFile()) { // Set the record name $this->recordName = $this->template->get('xml_record_name', 'general'); return true; } else { return false; } } /** * Sets the file pointer back to beginning. * * @return void. * * @since 3.0 */ public function rewind() { $this->linepointer = 0; // Close the file, so we can start reading from the beginning if ($this->data->close()) { $this->fp = false; } $this->processFile(); } /** * Advances the file pointer 1 forward. * * @param bool $preview True if called from preview. * * @return void. * * @since 3.0 */ public function next($preview = false) { if (!$preview) { // Read one line and discard it $this->readNextLine(); } } /** * Skips through the XML file until the the required number 'record' nodes has been read * Assume the file pointer is at the start of file. * * @param int $pos The number of records to skip. * * @return bool True if records are skipped | false if records are not skipped. * * @since 3.0 */ private function skipXmlRecords($pos) { $this->log->add('Forwarding to position: ' . $pos, false); // Check whether the pointer needs to be moved if ($pos <= 0) { return true; } $count = 0; while ($this->data->read()) { // Searching for a valid record - must be the start of a node and in the list of valid record types if ($this->data->nodeType == XMLREADER::ELEMENT && $this->data->name == $this->recordName) { // Found a valid record while ($this->data->nodeType == XMLREADER::ELEMENT && $this->data->name == $this->recordName) { // Node is a valid record type - skip to the end of the record $this->data->next(); $count++; if ($count == $pos) { $this->linepointer = $pos; return true; } } } else { // Not found - try again continue; } } // Hit EOF before skipping the required number of records return false; } /** * Returns the number of lines. * * @return int Returns the number of lines in the file. * * @since 6.0 */ public function linecount() { // Set number of lines $linecount = 0; if ($this->fp) { // Get the current position $currentPosition = $this->getFilePos(); // Rewind the file $this->rewind(); // Read the next line until it reached the end while ($this->readNextLine()) { $linecount++; } // Set the file back to the position it was $this->setFilePos($currentPosition); } return $linecount; } }