Files
grzanieplus.pl/plugins/stImportExportPlugin/lib/stPropelExporter.class.php
2025-03-12 17:06:23 +01:00

517 lines
13 KiB
PHP

<?php
/**
* SOTESHOP/stImportExportPlugin
*
* Ten plik należy do aplikacji stImportExportPlugin opartej na licencji (Open License SOTE) Otwarta Licencja SOTE.
* Nie zmieniaj tego pliku, jeśli chcesz korzystać z automatycznych aktualizacji oprogramowania.
* Jeśli chcesz wprowadzać swoje modyfikacje do programu, zapoznaj się z dokumentacją, jak zmieniać
* oprogramowanie bez zmiany kodu bazowego http://www.sote.pl/modifications
*
* @package stImportExportPlugin
* @subpackage libs
* @copyright SOTE (www.sote.pl)
* @license http://www.sote.pl/license/open (Open License SOTE) Otwarta Licencja SOTE
* @version $Id: stPropelExporter.class.php 13384 2011-06-02 11:30:57Z piotr $
* @author Piotr Halas <piotr.halas@sote.pl>
*/
/**
* Definicje bledow
*/
define( "EXPORT_NO_CONFIG", "Plik konfiguracyjny exportu nie istnieje." );
/**
* Klasa obslugi eksportu danych
*
* @package stImportExportPlugin
* @subpackage libs
*/
class stPropelExporter implements stPropelImportExportInterface
{
const FIELD_EXCEEDS_32K_MSG = 'Pole <b>%field%</b> posiada więcej niż 32 000 znaków.';
const FIELD_INCORRECT_ENCODING = 'Pole <b>%field%</b> zawiera znaki z poza zakresu kodowania <b>%encoding%</b>.';
const FIELD_NA_REPLAGE_MSG = 'Eksport pola zostaje pominięty i jego wartość zostaje zastąpiona w pliku eksportu przez <b>[N/A]</b>. Proszę nie edytować zawartości kolumn z wartością <b>[N/A]</b>, w innym wypadku (przy ponownym imporcie) wartość tego pola zostanie nadpisana.';
/**
* Naglowe pliku
* @var string
*/
var $header = '';
/**
* stopka pliku
* @var string
*/
var $footer = '';
/**
* nazwa modelu
* @var string
*/
var $model = '';
/**
* Unikatowa
* @var string
*/
var $converter = '';
/**
* Konfiguracja modulu
* @var array()
*/
var $config = array();
/**
* nazwa pliku eksprotu
* @var string
*/
var $output_file_extension = '';
/**
* Limit jednoczesnie eksportowanych elementow
* @var integer
*/
var $limit = 20;
var $hard_limit = null;
protected $filepath = null;
/**
* Uchwyt pliku
*
* @var mixed
*/
protected $fh = null;
protected $md5hash = array();
protected $logger = null;
protected $customParameters = array();
protected $i18nCatalogue = null;
/**
* konstruktor klasy, nalezy podac nazwe modelu oraz tablice
* eksportowanych pol
*
* @param string $model
* @param array $fields
*/
public function __construct($model = '', $fields = array(), $filepath = null)
{
$dir = sfConfig::get('sf_data_dir').'/export';
if (!is_dir($dir))
{
mkdir($dir, 0755);
}
$this->model = $model;
$this->config = $fields;
$this->filepath = $filepath;
$this->logger = new stImportExportLog(sfConfig::get('sf_log_dir').DIRECTORY_SEPARATOR.'export_'.$model.'.log');
$this->criteria = $this->getCriteria();
stEventDispatcher::getInstance()->notify(new sfEvent($this->criteria, 'st'.sfContext::getInstance()->getModuleName().'Export.'.$this->model.'Criteria'));
}
public function getFilePath()
{
return $this->filepath;
}
public function setI18nCatalogue($i18nCatalogue)
{
$this->i18nCatalogue = $i18nCatalogue;
}
public function setCustomParameters(array $parameters)
{
$this->customParameters = $parameters;
}
/**
* Zwraca liczbe rekordow do eksportu
*
* @return integer
*/
public function getDataCount()
{
return call_user_func($this->model.'Peer::doCount', $this->criteria);
}
/**
* Zwraca konfiguracja eksportu
*
* @return array
*/
public function getConfig()
{
return $this->config;
}
public function validateFile(array &$errors = null)
{
return false;
}
/**
* Glowna petla eksportu, pobiera offset danych do eksportu.
* Zwraca offset koljego kroku
*
* @param integer $offset
* @return integer
*/
public function doProcess($offset=0)
{
// jezeli jest to pierwszy krok zapisuje naglowek i naglowek tabeli
if ($offset==0)
{
$this->writeHeader();
$this->writeHeaderRow();
$this->clearMd5Hash();
}
// pobiera dane z tabeli
$data = $this->getData($offset);
// oblicza liczbe pobranych danych oraz liczbe calkowita danych w bazie
$data_items_count = count($data);
$data_all_count = $this->getDataCount();
// zapisuje dane do pliku
$this->writeConvertedData($data);
$this->writeMd5Hash();
// sprawdza czy zakonczono eksport, jezeli tak to zapisuje stopke
if ( $data_items_count > 0 && $data_all_count<=( $data_items_count + $offset))
{
$this->writeFooterRow();
$this->writeFooter();
$this->moveOutputFile();
}
return $offset+$data_items_count;
}
protected function doSelect(Criteria $c)
{
return call_user_func($this->model.'Peer::doSelect',$c);
}
/**
* Pobiera dane z bazy danych poczawszy od offsetu, zwraca pobrane
* dane w postaci tablicy
*
* @param integer $offset
* @return array
*/
protected function getData($offset = 0)
{
//tworzy nowe zapytanie uwzgledniajac offset i limit
$c = clone $this->criteria;
$c->setOffset($offset);
$c->setLimit($this->limit);
// wykonuje zaputanie do bazy danych
$data = $this->doSelect($c);
$this->md5hash = array();
$return_data = array();
// dla kazdego zwrocengo wyniku zapisuje dane do tablicy
foreach($data as $row)
{
$return_row = array();
// eksport jest wykonywany tylko do pol zapisanych w konfiguracji
foreach ($this->config['fields'] as $func_name=>$args)
{
$type = $args['type'];
$primaryKey = $row->getPrimaryKey();
$isCompositePrimaryKey = is_array($primaryKey);
if ($isCompositePrimaryKey)
{
$logKey = implode("_", $primaryKey);
}
else
{
$logKey = $primaryKey;
}
$this->logger->setCurrentKey($logKey);
// ustala rzeczywista nazwe funkcji do pobrania danych
$real_func_name = 'get'. sfInflector::camelize($func_name);
if (isset($args['method'])) $real_func_name = $args['method'];
// pobiera dane z modelu glownego lub zaleznych, jezeli podana funkcja nie wystepuje wstawia watosc null
if (!isset($args['class']))
{
try
{
$v = $row->$real_func_name($this->logger);
$return_row[$func_name] = $this->formatValue($v, $type);
}
catch (Exception $e)
{
$this->logger->add(null, $e->getMessage(), stImportExportLog::$FATAL);
$return_row[$func_name] = null;
}
}
elseif (isset($args['class']) && is_callable($args['class'].'::'.$real_func_name))
{
try
{
$v = call_user_func($args['class'].'::'.$real_func_name,$row,$this->logger, $this->customParameters);
$return_row[$func_name] = $this->formatValue($v, $type);
}
catch (Exception $e)
{
$this->logger->add(null, $e->getMessage(), stImportExportLog::$FATAL);
$return_row[$func_name] = null;
}
}
else
{
$return_row[$func_name] = null;
}
if (isset($args['md5hash']) && $args['md5hash'] && $return_row[$func_name] !== null)
{
$this->md5hash[$row->getId()][$func_name] = md5($return_row[$func_name]);
}
}
// dodaje dane to glownej tablicy danych
$return_data[] = $return_row;
}
return $return_data;
}
public function formatValue($v, $type = null)
{
switch($type)
{
case "double":
case "float":
return stPrice::round($v, 2);
case "int":
case "integer":
case "bool":
case "boolean":
return intval($v);
default:
return strval($v);
}
}
/**
* Zwraca nowa instancje obiektu Criteria
*/
protected function getCriteria(Criteria $criteria = null)
{
if (null === $criteria)
{
$criteria = new Criteria();
}
return $criteria;
}
/**
* Funkcja zamienia dane w postaci tablicy na okreslony format,
* funkcja ta definiowana jest w eksporterze okreslonego formatu
*
* @param array $data
* @return mixed
*/
protected function getConvertedData($data = null)
{
return '';
}
/**
* Zapisuje dane do pliku
*
* @param string $data
*/
protected function writeConvertedData($data = null)
{
file_put_contents($this->filepath,$this->getConvertedData($data),FILE_APPEND);
}
protected function writeMd5Hash()
{
foreach ($this->md5hash as $id => $values)
{
$md5hash = ExportMd5HashPeer::retrieveByModelId($id, $this->model);
if (null === $md5hash)
{
$md5hash = new ExportMd5Hash();
$md5hash->setId($id);
$md5hash->setModel($this->model);
}
$md5hash->setMd5Hash($values);
$md5hash->save();
}
}
protected function clearMd5Hash()
{
$con = Propel::getConnection();
$con->executeQuery(sprintf('TRUNCATE %s', ExportMd5HashPeer::TABLE_NAME));
}
/**
* Zwraca tresc naglowka, w funkcji tej moga zostac wykonane dodatkowe opercj na naglowku
*
* @return string
*/
protected function getHeader()
{
return $this->header;
}
/**
* Zapisuje naglowek do pliku
*/
protected function writeHeader()
{
file_put_contents($this->filepath,$this->getHeader());
}
/**
* Zwraca wiersz naglowka, funkcja defioniowana w pliku eksportera
*
* @return string
*/
protected function getHeaderRow()
{
return '';
}
/**
* Zapisuje wiersz naglowkowy do pliku
*/
protected function writeHeaderRow()
{
file_put_contents($this->filepath,$this->getHeaderRow(),FILE_APPEND);
}
/**
* Zwraca zawartosc stopki
*
* @return string
*/
protected function getFooter()
{
return $this->footer;
}
/**
* Zapisuje zawartosc stopki do pliku
*/
protected function writeFooter()
{
file_put_contents($this->filepath,$this->getFooter(),FILE_APPEND);
}
/**
* Zwraca wiersz stopki
*
* @return string
*/
protected function getFooterRow()
{
return '';
}
/**
* Zapisuje wiersz stopki do pliku
*/
protected function writeFooterRow()
{
file_put_contents($this->filepath,$this->getFooterRow(),FILE_APPEND);
}
/**
* Umozliwia przeniesienie piku wynikowego po wykonaniu eksportu
* Zwraca nazwe pliku.
*
* @return string
*/
protected function moveOutputFile()
{
return '';
}
public function setLimit($limit = 20)
{
if (is_integer($limit) && $limit>0)
{
$this->limit = $limit;
if ($this->hard_limit && $this->limit > $this->hard_limit)
{
$this->limit = $this->hard_limit;
}
}
}
public function getUserName($name)
{
if (is_array($name))
{
return implode("_", array_map(function($name) {
return $this->translateFieldName($name);
}, $name));
}
return $this->translateFieldName($name);
}
protected function translateFieldName($name)
{
if (isset($this->config['fields'][$name]['name']))
{
$field = $this->config['fields'][$name];
$i18nCatalogue = $this->i18nCatalogue;
if (isset($field['i18n']))
{
$i18nCatalogue = $field['i18n'];
}
elseif (isset($field['i18n_file']))
{
$i18nCatalogue = $field['i18n_file'];
}
return sfContext::getInstance()->getI18N()->__($field['name'], array(), $i18nCatalogue).'::'.$name;
}
return $name;
}
public function getLogger()
{
return $this->logger;
}
}