| Current Path : /srv/web/sites/trentinoplant.it/httpdocs/vendor/magento/framework/Measure/ |
| Current File : /srv/web/sites/trentinoplant.it/httpdocs/vendor/magento/framework/Measure/AbstractMeasure.php |
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* https://framework.zend.com/license
* If you did not receive a copy of the license and are unable to obtain it
* through the world-wide-web, please send an email to license@zend.com
* so we can send you a copy immediately.
*
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (https://www.zend.com/)
* @license https://framework.zend.com/license New BSD License
*/
declare(strict_types=1);
namespace Magento\Framework\Measure;
use Exception;
use Laminas\I18n\Filter\NumberParse;
use Locale;
use Magento\Framework\Measure\Exception\MeasureException;
use NumberFormatter;
/**
* Base for Measure
*/
abstract class AbstractMeasure
{
/**
* @var string
*/
protected $value;
/**
* @var string
*/
protected string $type;
/**
* @var string|null
*/
protected ?string $locale = null;
/**
* @var array
*/
protected array $units = [];
/**
* @param float|int $value
* @param string|null $type
* @param string|null $locale
* @throws MeasureException
*/
public function __construct($value, $type = null, $locale = null)
{
$this->setLocale($locale);
$type = $type ?? $this->units['STANDARD'];
if (empty($this->units[$type])) {
throw new MeasureException(__(
'Type (%1) is unknown',
$type
));
}
$this->setValue($value, $type, $this->locale);
}
/**
* Returns the conversion list.
*
* @return array
*/
public function getConversionList(): array
{
return $this->units;
}
/**
* Sets a new locale for the value representation.
*
* @param string|null $locale
* @return AbstractMeasure
*/
public function setLocale(string $locale = null): AbstractMeasure
{
$this->locale = $locale ?? Locale::getDefault();
return $this;
}
/**
* Sets a new locale for the value representation.
*
* @param int|string $value
* @param string $type
* @param string $locale
* @return AbstractMeasure
* @throws MeasureException
*/
public function setValue($value, string $type, string $locale): AbstractMeasure
{
try {
$numberParse = new NumberParse($locale, NumberFormatter::TYPE_DEFAULT);
$this->value = (string) $numberParse->filter($value);
$this->setType($type);
} catch (Exception $exception) {
throw new MeasureException(
__($exception->getMessage()),
$exception->getCode(),
$exception
);
}
return $this;
}
/**
* Returns the internal value.
*
* @param int $round
* @param string|null $locale
* @return float|string
*/
public function getValue(int $round = -1, string $locale = null)
{
$result = $round < 0 ? $this->value : round((float) $this->value, $round);
if ($locale !== null) {
$numberParse = new NumberParse($locale, NumberFormatter::TYPE_DEFAULT);
return (string) $numberParse->filter($result);
}
return $result;
}
/**
* Set a new type, and convert the value.
*
* @param string $type
* @return AbstractMeasure
* @throws MeasureException
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
* phpcs:disable Generic.Metrics.NestingLevel
*/
public function setType(string $type): AbstractMeasure
{
if (empty($this->units[$type])) {
throw new MeasureException(__(
'Type (%1) is unknown',
$type
));
}
if (!empty($this->type)) {
$value = $this->value;
if (is_array($this->units[$this->getType()][0])) {
foreach ($this->units[$this->getType()][0] as $key => $found) {
switch ($key) {
case "/":
if ($found != 0) {
$value = $this->div($value, $found, 25);
}
break;
case "+":
$value = $this->add($value, $found, 25);
break;
case "-":
$value = $this->sub($value, $found, 25);
break;
default:
$value = $this->mul($value, $found, 25);
break;
}
}
} else {
$value = $this->mul($value, $this->units[$this->getType()][0], 25);
}
if (is_array($this->units[$type][0])) {
foreach (array_reverse($this->units[$type][0]) as $key => $found) {
switch ($key) {
case "/":
$value = $this->mul($value, $found, 25);
break;
case "+":
$value = $this->sub($value, $found, 25);
break;
case "-":
$value = $this->add($value, $found, 25);
break;
default:
if ($found != 0) {
$value = $this->div($value, $found, 25);
}
break;
}
}
} else {
$value = $this->div($value, $this->units[$type][0], 25);
}
$valueLength = strlen($value);
for ($i = 1; $i <= $valueLength; ++$i) {
if ($value[$valueLength - $i] != '0') {
$length = 26 - $i;
break;
}
}
$this->value = round((float) $value, $length ?? 0);
}
$this->type = $type;
return $this;
}
/**
* Returns the original type.
*
* @return string
*/
public function getType(): string
{
return $this->type;
}
/**
* Returns a string representation.
*
* @param int $round
* @param string|null $locale
* @return string
*/
public function toString(int $round = -1, ?string $locale = null): string
{
if ($locale === null) {
$locale = $this->locale;
}
return $this->getValue($round, $locale) . ' ' . $this->units[$this->getType()][1];
}
/**
* Returns a string representation.
*
* @return string
*/
public function __toString()
{
return $this->toString();
}
/**
* BCAdd - fixes a problem of BCMath and exponential numbers.
*
* @param string $firstOption
* @param string $secondOption
* @param int|null $scale
* @return string
*/
private function add(string $firstOption, string $secondOption, int $scale = null): string
{
$firstOption = $this->exponent($firstOption, $scale);
$secondOption = $this->exponent($secondOption, $scale);
return bcadd($firstOption, $secondOption, $scale);
}
/**
* BCSub - fixes a problem of BCMath and exponential numbers.
*
* @param string $firstOption
* @param string $secondOption
* @param int|null $scale
* @return string
*/
private function sub(string $firstOption, string $secondOption, int $scale = null): string
{
$firstOption = $this->exponent($firstOption, $scale);
$secondOption = $this->exponent($secondOption, $scale);
return bcsub($firstOption, $secondOption, $scale);
}
/**
* BCDiv - fixes a problem of BCMath and exponential numbers.
*
* @param string $firstOption
* @param string $secondOption
* @param int|null $scale
* @return string
*/
private function div(string $firstOption, string $secondOption, int $scale = null): string
{
$firstOption = $this->exponent($firstOption, $scale);
$secondOption = $this->exponent($secondOption, $scale);
return bcdiv($firstOption, $secondOption, $scale);
}
/**
* BCMul - fixes a problem of BCMath and exponential numbers.
*
* @param string $firstOption
* @param string $secondOption
* @param int|null $scale
* @return string
*/
private function mul(string $firstOption, string $secondOption, int $scale = null): string
{
$firstOption = $this->exponent($firstOption, $scale);
$secondOption = $this->exponent($secondOption, $scale);
return bcmul($firstOption, $secondOption, $scale);
}
/**
* Changes exponential numbers to plain string numbers.
*
* @param string $value
* @param int|null $scale
* @return string
*/
private function exponent(string $value, int $scale = null): string
{
if (!extension_loaded('bcmath')) {
return $value;
}
$split = explode('e', $value);
if (count($split) === 1) {
$split = explode('E', $value);
}
if (count($split) > 1) {
$value = bcmul($split[0], bcpow('10', $split[1], $scale), $scale);
}
return $value;
}
}