add exceptions for better error handling

This commit is contained in:
Daniel Seifert 2021-04-20 09:50:49 +02:00
parent e052d44e59
commit 2c8ef877cc
Signed by: DanielS
GPG Key ID: 8A7C4C6ED1915C6F
14 changed files with 265 additions and 43 deletions

View File

@ -25,6 +25,7 @@
"proprietary"
],
"require": {
"php": ">=7.1",
"oxid-esales/oxideshop-ce": "~6.3",
"league/csv": "^9.0",
"mathieuviossat/arraytotexttable": "^1.0"

View File

@ -16,10 +16,14 @@
namespace D3\DataWizard\Application\Controller\Admin;
use D3\DataWizard\Application\Model\Configuration;
use D3\DataWizard\Application\Model\Exceptions\DataWizardException;
use D3\DataWizard\Application\Model\Exceptions\DebugException;
use D3\ModCfg\Application\Model\Exception\d3_cfg_mod_exception;
use D3\ModCfg\Application\Model\Exception\d3ShopCompatibilityAdapterException;
use Doctrine\DBAL\DBALException;
use League\Csv\CannotInsertRecord;
use League\Csv\Exception;
use OxidEsales\Eshop\Application\Controller\Admin\AdminDetailsController;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Exception\DatabaseErrorException;
use OxidEsales\Eshop\Core\Exception\StandardException;
use OxidEsales\Eshop\Core\Registry;
@ -48,9 +52,10 @@ class d3ExportWizard extends AdminDetailsController
}
/**
* @throws CannotInsertRecord
* @throws DBALException
* @throws Exception
* @throws DatabaseConnectionException
* @throws StandardException
* @throws d3ShopCompatibilityAdapterException
* @throws d3_cfg_mod_exception
*/
public function doExport()
{
@ -60,13 +65,13 @@ class d3ExportWizard extends AdminDetailsController
if (Registry::getConfig()->getConfigParam('d3datawizard_debug')) {
throw oxNew(
StandardException::class,
DebugException::class,
$export->getQuery()
);
}
$export->run(Registry::getRequest()->getRequestEscapedParameter('exportformat'));
} catch (StandardException $e) {
} catch (DataWizardException|DBALException|DatabaseErrorException $e) {
Registry::getUtilsView()->addErrorToDisplay($e);
}
}

View File

@ -35,17 +35,27 @@ class Configuration
}
/**
* @param $group
* @param ExportBase $export
*/
public function registerExport($group, ExportBase $export)
{
$this->exports[$group][md5(serialize($export))] = $export;
}
public function getGroupedExports()
/**
* @return array
*/
public function getGroupedExports(): array
{
return $this->exports;
}
public function getGroups()
/**
* @return array
*/
public function getGroups(): array
{
return array_keys($this->exports);
}

View File

@ -0,0 +1,20 @@
<?php
/**
* This Software is the property of Data Development and is protected
* by copyright law - it is NOT Freeware.
* Any unauthorized use of this software without a valid license
* is a violation of the license agreement and will be prosecuted by
* civil and criminal law.
* http://www.shopmodule.com
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
* @link http://www.oxidmodule.com
*/
namespace D3\DataWizard\Application\Model\Exceptions;
interface DataWizardException
{
}

View File

@ -0,0 +1,33 @@
<?php
/**
* This Software is the property of Data Development and is protected
* by copyright law - it is NOT Freeware.
* Any unauthorized use of this software without a valid license
* is a violation of the license agreement and will be prosecuted by
* civil and criminal law.
* http://www.shopmodule.com
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
* @link http://www.oxidmodule.com
*/
namespace D3\DataWizard\Application\Model\Exceptions;
use Exception;
use OxidEsales\Eshop\Core\Exception\StandardException;
use OxidEsales\Eshop\Core\Registry;
class DebugException extends StandardException implements DataWizardException
{
public function __construct($sMessage = "not set", $iCode = 0, Exception $previous = null )
{
$sMessage = sprintf(
Registry::getLang()->translateString('D3_DATAWIZARD_DEBUG'),
$sMessage
);
parent::__construct($sMessage, $iCode, $previous );
}
}

View File

@ -0,0 +1,33 @@
<?php
/**
* This Software is the property of Data Development and is protected
* by copyright law - it is NOT Freeware.
* Any unauthorized use of this software without a valid license
* is a violation of the license agreement and will be prosecuted by
* civil and criminal law.
* http://www.shopmodule.com
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
* @link http://www.oxidmodule.com
*/
namespace D3\DataWizard\Application\Model\Exceptions;
use Exception;
use OxidEsales\Eshop\Core\Exception\StandardException;
use OxidEsales\Eshop\Core\Registry;
class NoSuitableRendererException extends StandardException implements DataWizardException
{
public function __construct($sMessage = "not set", $iCode = 0, Exception $previous = null )
{
$sMessage = sprintf(
Registry::getLang()->translateString('D3_DATAWIZARD_ERR_NOSUITABLERENDERER'),
$sMessage
);
parent::__construct($sMessage, $iCode, $previous );
}
}

View File

@ -0,0 +1,22 @@
<?php
/**
* This Software is the property of Data Development and is protected
* by copyright law - it is NOT Freeware.
* Any unauthorized use of this software without a valid license
* is a violation of the license agreement and will be prosecuted by
* civil and criminal law.
* http://www.shopmodule.com
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
* @link http://www.oxidmodule.com
*/
namespace D3\DataWizard\Application\Model\Exceptions;
use OxidEsales\Eshop\Core\Exception\StandardException;
class RenderException extends StandardException implements DataWizardException
{
}

View File

@ -0,0 +1,40 @@
<?php
/**
* This Software is the property of Data Development and is protected
* by copyright law - it is NOT Freeware.
* Any unauthorized use of this software without a valid license
* is a violation of the license agreement and will be prosecuted by
* civil and criminal law.
* http://www.shopmodule.com
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
* @link http://www.oxidmodule.com
*/
namespace D3\DataWizard\Application\Model\Exceptions;
use D3\DataWizard\Application\Model\QueryBase;
use Exception;
use OxidEsales\Eshop\Core\Exception\StandardException;
class TaskException extends StandardException implements DataWizardException
{
/** @var QueryBase */
public $task;
public function __construct( QueryBase $task, $sMessage = "not set", $iCode = 0, Exception $previous = null )
{
$sMessage = implode(
' - ',
[
$task->getTitle(),
$sMessage
]
);
parent::__construct( $sMessage, $iCode, $previous );
$this->task = $task;
}
}

View File

@ -20,8 +20,6 @@ use D3\ModCfg\Application\Model\d3filesystem;
use D3\ModCfg\Application\Model\Exception\d3_cfg_mod_exception;
use D3\ModCfg\Application\Model\Exception\d3ShopCompatibilityAdapterException;
use Doctrine\DBAL\DBALException;
use League\Csv\CannotInsertRecord;
use League\Csv\Exception;
use OxidEsales\Eshop\Core\DatabaseProvider;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Exception\DatabaseErrorException;
@ -36,6 +34,8 @@ abstract class ExportBase implements QueryBase
* @throws DBALException
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
* @throws Exceptions\NoSuitableRendererException
* @throws Exceptions\TaskException
* @throws StandardException
* @throws d3ShopCompatibilityAdapterException
* @throws d3_cfg_mod_exception
@ -44,24 +44,7 @@ abstract class ExportBase implements QueryBase
{
$query = trim($this->getQuery());
if (strtolower(substr($query, 0, 6)) !== 'select') {
/** @var StandardException $e */
throw oxNew(
StandardException::class,
$this->getTitle().' - '.Registry::getLang()->translateString('D3_DATAWIZARD_EXPORT_NOSELECT')
);
}
$rows = DatabaseProvider::getDb(DatabaseProvider::FETCH_MODE_ASSOC)->getAll($query);
if (count($rows) <= 0) {
throw oxNew(
StandardException::class,
Registry::getLang()->translateString('D3_DATAWIZARD_ERR_NOEXPORTCONTENT')
);
}
$fieldNames = array_keys($rows[0]);
list( $rows, $fieldNames ) = $this->executeQuery( $query );
$content = $this->renderContent($rows, $fieldNames, $format);
@ -73,6 +56,9 @@ abstract class ExportBase implements QueryBase
);
}
/**
* @return string
*/
public function getButtonText() : string
{
return "D3_DATAWIZARD_EXPORT_SUBMIT";
@ -82,13 +68,20 @@ abstract class ExportBase implements QueryBase
* @param $format
*
* @return ExportRenderer\RendererInterface
* @throws Exceptions\NoSuitableRendererException
*/
public function getRenderer($format): ExportRenderer\RendererInterface
{
return oxNew(RendererBridge::class)->getRenderer($format);
}
public function getFileExtension($format)
/**
* @param $format
*
* @return string
* @throws Exceptions\NoSuitableRendererException
*/
public function getFileExtension($format): string
{
return $this->getRenderer($format)->getFileExtension();
}
@ -98,9 +91,10 @@ abstract class ExportBase implements QueryBase
* @param $fieldnames
* @param $format
*
* @return mixed
* @return string
* @throws Exceptions\NoSuitableRendererException
*/
public function renderContent($rows, $fieldnames, $format)
public function renderContent($rows, $fieldnames, $format): string
{
$renderer = $this->getRenderer($format);
return $renderer->getContent($rows, $fieldnames);
@ -110,9 +104,42 @@ abstract class ExportBase implements QueryBase
* @param $format
*
* @return string
* @throws Exceptions\NoSuitableRendererException
*/
public function getExportFileName($format) : string
{
return $this->getExportFilenameBase().'_'.date('Y-m-d_H-i-s').'.'.$this->getFileExtension($format);
}
/**
* @param string $query
*
* @return array
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
*/
protected function executeQuery( string $query ): array
{
if ( strtolower( substr( $query, 0, 6 ) ) !== 'select' ) {
throw oxNew(
Exceptions\TaskException::class,
$this,
Registry::getLang()->translateString( 'D3_DATAWIZARD_ERR_NOEXPORTSELECT' )
);
}
$rows = DatabaseProvider::getDb( DatabaseProvider::FETCH_MODE_ASSOC )->getAll( $query );
if ( count( $rows ) <= 0 ) {
throw oxNew(
Exceptions\TaskException::class,
$this,
Registry::getLang()->translateString( 'D3_DATAWIZARD_ERR_NOEXPORTCONTENT' )
);
}
$fieldNames = array_keys( $rows[0] );
return [ $rows, $fieldNames ];
}
}

View File

@ -15,7 +15,7 @@
namespace D3\DataWizard\Application\Model\ExportRenderer;
use League\Csv\CannotInsertRecord;
use D3\DataWizard\Application\Model\Exceptions\RenderException;
use League\Csv\EncloseField;
use League\Csv\Exception;
use League\Csv\Writer;
@ -28,14 +28,19 @@ class Csv implements RendererInterface
* @param $fieldNames
*
* @return string
* @throws Exception
* @throws CannotInsertRecord
* @throws RenderException
*/
public function getContent($rows, $fieldNames): string
{
$csv = $this->getCsv();
$csv->insertOne($fieldNames);
$csv->insertAll($rows);
try {
$csv = $this->getCsv();
$csv->insertOne( $fieldNames );
$csv->insertAll( $rows );
} catch (Exception $e) {
/** @var RenderException $newException */
$newException = oxNew(RenderException::class, $e->getMessage(), $e->getCode(), $e );
throw $newException;
}
return $csv->getContent();
}

View File

@ -19,12 +19,21 @@ use MathieuViossat\Util\ArrayToTextTable;
class Pretty implements RendererInterface
{
/**
* @param $rows
* @param $fieldNames
*
* @return string
*/
public function getContent($rows, $fieldNames) : string
{
$renderer = oxNew(ArrayToTextTable::class, $rows);
return $renderer->getTable();
}
/**
* @return string
*/
public function getFileExtension(): string
{
return 'txt';

View File

@ -15,6 +15,8 @@
namespace D3\DataWizard\Application\Model\ExportRenderer;
use D3\DataWizard\Application\Model\Exceptions\NoSuitableRendererException;
class RendererBridge
{
const FORMAT_CSV = 'CSV';
@ -23,16 +25,20 @@ class RendererBridge
/**
* @param string $format
*
* @throws NoSuitableRendererException
* @return RendererInterface
*/
public function getRenderer($format = self::FORMAT_CSV): RendererInterface
{
switch ($format) {
case self::FORMAT_CSV:
return oxNew(Csv::class);
case self::FORMAT_PRETTY:
return oxNew(Pretty::class);
case self::FORMAT_CSV:
default:
return oxNew(Csv::class);
}
/** @var NoSuitableRendererException $e */
$e = oxNew(NoSuitableRendererException::class, $format);
throw $e;
}
}

View File

@ -17,7 +17,16 @@ namespace D3\DataWizard\Application\Model\ExportRenderer;
interface RendererInterface
{
/**
* @param $rows
* @param $fieldNames
*
* @return string
*/
public function getContent($rows, $fieldNames) : string;
/**
* @return string
*/
public function getFileExtension() : string;
}

View File

@ -39,10 +39,12 @@ $aLang = array(
'D3_DATAWIZARD_EXPORT_FORMAT_CSV' => 'CSV-Format',
'D3_DATAWIZARD_EXPORT_FORMAT_PRETTY' => 'Pretty-Format',
'D3_DATAWIZARD_EXPORT_NOSELECT' => 'Export kann nicht ausgeführt werden. Exporte erfordern SELECT Query.',
'D3_DATAWIZARD_DEBUG' => 'Debug: %1$s',
'D3_DATAWIZARD_ERR_NOEXPORTSELECT' => 'Export kann nicht ausgeführt werden. Exporte erfordern SELECT Query.',
'D3_DATAWIZARD_ERR_NOEXPORT_INSTALLED' => 'Es sind keine Exporte installiert oder aktiviert.',
'D3_DATAWIZARD_ERR_NOEXPORTCONTENT' => 'Export ist leer, kein Inhalt zum Download verfügbar'
'D3_DATAWIZARD_ERR_NOEXPORTCONTENT' => 'Export ist leer, kein Inhalt zum Download verfügbar',
'D3_DATAWIZARD_ERR_NOSUITABLERENDERER' => 'kein Renderer für Format "%1$s" registriert'
// Abracadata
// Harry Potter