Skip to content

Commit

Permalink
PES-2068 CR fixes
Browse files Browse the repository at this point in the history
PES-2068 CR refactor - introduce constants
PES-2068 CR fix - unused getters removed
PES-2068 CR fix - format table using css
PES-2068 CR fix - typehints & annotations
PES-2068 CR fix - introduce updateZasilkovnaConfig
PES-2068 CR fix - introduce configuration defaults
PES-2068 final minor CR fixes
PES-2068 CS fixes and minor improvement
PES-2068 Use ConfigValidator::KEY_PAYMENT_METHOD_PREFIX in template
PES-2068 CR - final fix for strange VM null handling
  • Loading branch information
Mrakor committed May 3, 2024
1 parent a0a8095 commit 9b8f1d3
Show file tree
Hide file tree
Showing 12 changed files with 341 additions and 165 deletions.
6 changes: 3 additions & 3 deletions install.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ CREATE TABLE IF NOT EXISTS `#__virtuemart_shipment_plg_zasilkovna` (
`zasilkovna_packet_id` decimal(10,0),
`zasilkovna_packet_price` decimal(15,2),
`weight` decimal(10,4),
`length` smallint unsigned DEFAULT '0',
`width` smallint unsigned DEFAULT '0',
`height` smallint unsigned DEFAULT '0',
`length` smallint unsigned,
`width` smallint unsigned,
`height` smallint unsigned,
`branch_id` decimal(10,0),
`branch_currency` char(5),
`branch_name_street` varchar(500),
Expand Down
13 changes: 10 additions & 3 deletions install.zasilkovna.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

use Joomla\CMS\Installer\Adapter\PluginAdapter;
use VirtueMartModelZasilkovna\ConfigurationValidator;

// No direct access to this file
defined('_JEXEC') or die('Restricted access');
Expand Down Expand Up @@ -203,7 +204,7 @@ public function postflight($route, $adapter)
require_once VMPATH_ROOT . '/plugins/vmshipment/zasilkovna/zasilkovna.php';
}

$this->createCronToken();
$this->createConfigurationDefaults();
if ($route === 'update' && $this->fromVersion && version_compare($this->fromVersion, '1.2.0', '<')) {
$this->migratePricingRules();
}
Expand Down Expand Up @@ -592,11 +593,11 @@ private function removeAdministratorFiles() {
}

/**
* Creates update carriers token.
* Creates update carriers token and other plugin configuration defaults.
*
* @return void
*/
private function createCronToken() {
private function createConfigurationDefaults(): void {
/** @var \VirtueMartModelZasilkovna $model */
$model = VmModel::getModel('zasilkovna');
$config = $model->loadConfig();
Expand All @@ -605,6 +606,12 @@ private function createCronToken() {
$config['cron_token'] = substr(sha1(rand()), 0, 16);
}

foreach (ConfigurationValidator::CONFIG_DEFAULTS as $key => $value) {
if (!isset($config[$key])) {
$config[$key] = $value;
}
}

$model->updateConfig($config);
}

Expand Down
88 changes: 36 additions & 52 deletions media/admin/com_virtuemart/controllers/zasilkovna.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
class VirtuemartControllerZasilkovna extends VmController
{
const ZASILKOVNA_LIMITATIONS_REMOVED_NOTICE_DISMISSED = 'zasilkovna_limitations_removed_notice_dismissed';
public const FROM_POST = 'fromPost';
public const FORM_VALUES = 'formValues';

/** @var \VirtueMartModelZasilkovna\Order\Detail */
private $orderDetail;
Expand Down Expand Up @@ -80,23 +82,7 @@ public function save($data = 0): void
$data = vRequest::getPost();
}

/** @var VirtueMartModelZasilkovna $model */
$model = VmModel::getModel('zasilkovna');
$currentData = $model->loadConfig();

$errors = [];
if (strlen($data['zasilkovna_api_pass']) !== 32) {
$errors['zasilkovna_api_pass'] = JText::_('PLG_VMSHIPMENT_PACKETERY_API_PASS_INVALID');
}

$validData = $this->getValidatedDimensionsData($data, $errors);
$model->updateConfig(array_replace_recursive($currentData, $validData));

if ($errors === []) {
$message = new FlashMessage(JText::_('PLG_VMSHIPMENT_PACKETERY_CONFIG_SAVED'), FlashMessage::TYPE_MESSAGE);
} else {
$message = new FlashMessage(implode("<br>", $errors), FlashMessage::TYPE_ERROR);
}
$message = $this->updateZasilkovnaConfig($data);

$redir = 'index.php?option=com_virtuemart';
$app = JFactory::getApplication();
Expand Down Expand Up @@ -307,48 +293,46 @@ private function getExportOrders()

/**
* @param array<string, mixed> $data
* @param array<string,string> $errors
* @return array<string, mixed>
* @return FlashMessage
*/
private function getValidatedDimensionsData(array $data, array &$errors = []): array
private function updateZasilkovnaConfig(array $data): FlashMessage
{
if (!isset($data['zasilkovna_use_default_weight']) || $data['zasilkovna_use_default_weight'] === '0') {
$data['zasilkovna_use_default_weight'] = false;
$data['zasilkovna_default_weight'] = null;
} else {
if (!isset($data['zasilkovna_default_weight']) || (float) $data['zasilkovna_default_weight'] < 0.001) {
$errors['zasilkovna_default_weight'] = sprintf(
JText::_('PLG_VMPSHIPMENT_PACKETERY_DEFAULT_FIELD_MUST_BE_POSITIVE'),
JText::_('PLG_VMSHIPMENT_PACKETERY_DEFAULT_WEIGHT')
);
} else {
$data['zasilkovna_default_weight'] = round((float) $data['zasilkovna_default_weight'], 3);
}
}
$configStorage = new VirtueMartModelZasilkovna\SessionStorage(JFactory::getSession(), 'packeteryConfig');
$configStorage->set(self::FROM_POST, self::FORM_VALUES, $data);

$fields = [
'zasilkovna_default_length' => 'PLG_VMSHIPMENT_PACKETERY_DEFAULT_DIMENSIONS_LENGTH',
'zasilkovna_default_width' => 'PLG_VMSHIPMENT_PACKETERY_DEFAULT_DIMENSIONS_WIDTH',
'zasilkovna_default_height' => 'PLG_VMSHIPMENT_PACKETERY_DEFAULT_DIMENSIONS_HEIGHT',
];
if (!isset($data['zasilkovna_use_default_dimensions']) || $data['zasilkovna_use_default_dimensions'] === '0') {
$data['zasilkovna_use_default_dimensions'] = false;
foreach(array_keys($fields) as $field) {
$data[$field] = null;
}
} else {
foreach ($fields as $field => $label) {
if (!isset($data[$field]) || (int)$data[$field] < 1) {
$errors[$field] = sprintf(
JText::_('PLG_VMPSHIPMENT_PACKETERY_DEFAULT_FIELD_MUST_BE_POSITIVE'),
JText::_($label)
);
/** @var VirtueMartModelZasilkovna $model */
$model = VmModel::getModel('zasilkovna');
$currentData = $model->loadConfig();

$formValidator = new VirtueMartModelZasilkovna\ConfigurationValidator($data);
$formValidator->validate();

if (!$formValidator->isValid()) {
$errors = $formValidator->getErrors();
$messages = [];

//$error is either error string translation key, or array where 1st element is sprintf template and others are sprintf arguments (all untranslated)
foreach ($errors as $formField => $error) {
if (!is_array($error)) {
$messages[] = JText::_($error);
} else {
$data[$field] = (int)$data[$field];
$messages[] = sprintf(
JText::_($error[0]),
...array_map(
static function ($item) {
return JText::_($item);
},
array_slice($error, 1))
);
}
}

return new FlashMessage(implode("<br>", $messages), FlashMessage::TYPE_ERROR);
}

return $data;
$model->updateConfig(array_replace_recursive($currentData, $formValidator->getValidData()));
$configStorage->clear(self::FROM_POST, self::FORM_VALUES);

return new FlashMessage(JText::_('PLG_VMSHIPMENT_PACKETERY_CONFIG_SAVED'), FlashMessage::TYPE_MESSAGE);
}
}
25 changes: 12 additions & 13 deletions media/admin/com_virtuemart/models/zasilkovna_orders.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,11 @@ public function printCarrierLabels(array $packetIds, Label\Format $format, $offs
}

/**
* @param $orders_id_arr
* @param string[] $orders_id_arr
* @return array<string,array<string,mixed>>
* @throws Exception
*/
public function submitToZasilkovna($orders_id_arr): array
public function submitToZasilkovna(array $orders_id_arr): array
{

$db = JFactory::getDBO();
Expand Down Expand Up @@ -198,11 +198,10 @@ public function submitToZasilkovna($orders_id_arr): array
$dimensions = ['length', 'width', 'height'];
$size = [];
foreach ($dimensions as $dimension) {
if (isset($order[$dimension]) && $order[$dimension] > 0) {
$size[$dimension] = $order[$dimension];
}
}
if (count($size) === 3) {

if ($order['length']) {
$attributes['size'] = $size;
}

Expand Down Expand Up @@ -351,9 +350,9 @@ public function exportToCSV($orders_id_arr) {
$row['recipient_city'],
$row['recipient_zip'],
$row['carrier_point'],
$row['width'],
$row['height'],
$row['depth'],
$row['width'] ?? '',
$row['height'] ?? '',
$row['length'] ?? '',
);

echo "," . implode(',', $order) . PHP_EOL;
Expand Down Expand Up @@ -448,11 +447,11 @@ private function createConvertInstance() {
}

/**
* @param $orders_arr
* @param string[] $orders_arr
* @return array<array<string,mixed>>
* @throws Exception
*/
protected function prepareForExport($orders_arr): array
protected function prepareForExport(array $orders_arr): array
{
if (!$orders_arr)
{
Expand Down Expand Up @@ -539,9 +538,9 @@ protected function prepareForExport($orders_arr): array
$orderForExport['recipient_zip'] = $row['zip_code'];
$orderForExport['carrier_point'] = $row['carrier_pickup_point'];
$orderForExport['is_carrier'] = $row['is_carrier'];
$orderForExport['width'] = $row['width'] > 0 ? $row['width'] : "";
$orderForExport['height'] = $row['height'] > 0 ? $row['height'] : "";
$orderForExport['length'] = $row['length'] > 0 ? $row['length'] : "";
$orderForExport['width'] = $row['width'];
$orderForExport['height'] = $row['height'];
$orderForExport['length'] = $row['length'];
$orderForExport['zasilkovna_packet_id'] = $row['zasilkovna_packet_id'];

$ordersForExport[] = $orderForExport;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<?php
namespace VirtueMartModelZasilkovna;

class ConfigurationValidator
{
public const KEY_USE_DEFAULT_WEIGHT = 'zasilkovna_use_default_weight';
public const KEY_DEFAULT_WEIGHT = 'zasilkovna_default_weight';
public const KEY_USE_DEFAULT_DIMENSIONS = 'zasilkovna_use_default_dimensions';
public const KEY_API_PASS = 'zasilkovna_api_pass';
public const KEY_ESHOP_LABEL = 'zasilkovna_eshop_label';
public const KEY_DEFAULT_LENGTH = 'zasilkovna_default_length';
public const KEY_DEFAULT_WIDTH = 'zasilkovna_default_width';
public const KEY_DEFAULT_HEIGHT = 'zasilkovna_default_height';
public const KEY_PAYMENT_METHOD_PREFIX = 'zasilkovna_payment_method_';
public const CONFIG_DEFAULTS = [
self::KEY_USE_DEFAULT_WEIGHT => false,
self::KEY_DEFAULT_WEIGHT => 0,
self::KEY_USE_DEFAULT_DIMENSIONS => false,
self::KEY_DEFAULT_LENGTH => 0,
self::KEY_DEFAULT_WIDTH => 0,
self::KEY_DEFAULT_HEIGHT => 0,
self::KEY_API_PASS => '',
self::KEY_ESHOP_LABEL => '',
];


/**
* @var array<string, mixed>
*/
private array $configuration;

/**
* @var array <string, string>|array<string, array<string>>
*/
private array $errors = [];

/**
* @var array<string, mixed>
*/
private array $validData = [];

/**
* @param array<string, mixed> $configuration
*/
public function __construct(array $configuration)
{
$this->configuration = $configuration;
}

public function validate(): void {
$this->validateApiPassword();
$this->validateWeight();
$this->validateDimensions();
$this->setValidDataForNotValidatedFields();
}

private function validateWeight(): void {
if ($this->configuration[self::KEY_USE_DEFAULT_WEIGHT] === '1') {
if (empty($this->configuration[self::KEY_DEFAULT_WEIGHT])
|| (float)$this->configuration[self::KEY_DEFAULT_WEIGHT] < 0.001) {
$this->errors[self::KEY_DEFAULT_WEIGHT] = [
'PLG_VMPSHIPMENT_PACKETERY_DEFAULT_FIELD_MUST_BE_POSITIVE',
'PLG_VMSHIPMENT_PACKETERY_DEFAULT_WEIGHT',
];
return;
}
$this->validData[self::KEY_DEFAULT_WEIGHT] = round((float)$this->configuration[self::KEY_DEFAULT_WEIGHT], 3);
$this->validData[self::KEY_USE_DEFAULT_WEIGHT] = true;
return;
}
$this->validData[self::KEY_USE_DEFAULT_WEIGHT] = false;
$this->validData[self::KEY_DEFAULT_WEIGHT] = self::CONFIG_DEFAULTS[self::KEY_DEFAULT_WEIGHT];
}

private function validateDimensions(): void {
$fields = [
self::KEY_DEFAULT_LENGTH => 'PLG_VMSHIPMENT_PACKETERY_DEFAULT_DIMENSIONS_LENGTH',
self::KEY_DEFAULT_WIDTH => 'PLG_VMSHIPMENT_PACKETERY_DEFAULT_DIMENSIONS_WIDTH',
self::KEY_DEFAULT_HEIGHT => 'PLG_VMSHIPMENT_PACKETERY_DEFAULT_DIMENSIONS_HEIGHT',
];

if (!isset($this->configuration[self::KEY_USE_DEFAULT_DIMENSIONS])
|| $this->configuration[self::KEY_USE_DEFAULT_DIMENSIONS] === '0'
) {
$this->validData[self::KEY_USE_DEFAULT_DIMENSIONS] = false;
foreach (array_keys($fields) as $field) {
$this->validData[$field] = self::CONFIG_DEFAULTS[$field];
}
return;
}

$validDimensions = [];
foreach ($fields as $field => $label) {
if (!isset($this->configuration[$field]) || (int)$this->configuration[$field] < 1) {
$this->errors[$field] = ['PLG_VMPSHIPMENT_PACKETERY_DEFAULT_FIELD_MUST_BE_POSITIVE', $label];
} else {
$validDimensions[$field] = (int)$this->configuration[$field];
}
}
if (count($validDimensions) === count($fields)) {
$this->validData[self::KEY_USE_DEFAULT_DIMENSIONS] = true;
$this->validData = array_merge($this->validData, $validDimensions);
}
}

private function validateApiPassword(): void {
if ($this->configuration[self::KEY_API_PASS] === '') {
$this->errors[self::KEY_API_PASS] = 'PLG_VMSHIPMENT_PACKETERY_API_PASS_NOT_SET';
return;
}
if (strlen($this->configuration[self::KEY_API_PASS]) !== 32) {
$this->errors[self::KEY_API_PASS] = 'PLG_VMSHIPMENT_PACKETERY_API_PASS_INVALID';
return;
}

$this->validData[self::KEY_API_PASS] = $this->configuration[self::KEY_API_PASS];
}

public function isValid(): bool {
return empty($this->errors);
}

/**
* @return array<string, string>|array<string, array<string>>
*/
public function getErrors(): array {
return $this->errors;
}

/**
* @return array<string, mixed>
*/
public function getValidData(): array {
return $this->validData;
}

private function setValidDataForNotValidatedFields(): void {
$this->validData[self::KEY_ESHOP_LABEL] = $this->configuration[self::KEY_ESHOP_LABEL] ?? self::CONFIG_DEFAULTS[self::KEY_ESHOP_LABEL];

$paymentMethods = array_filter(
$this->configuration,
static function ($key) {
return str_starts_with($key, self::KEY_PAYMENT_METHOD_PREFIX);
},
ARRAY_FILTER_USE_KEY
);
$this->validData = array_merge($this->validData, $paymentMethods);
}
}
Loading

0 comments on commit 9b8f1d3

Please sign in to comment.