Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
100.00% |
1 / 1 |
|
100.00% |
2 / 2 |
CRAP | |
100.00% |
58 / 58 |
convertNegativeTo | |
100.00% |
1 / 1 |
0 | |
100.00% |
8 / 8 |
|||
from | |
100.00% |
1 / 1 |
0 | |
100.00% |
3 / 3 |
|||
convertFromPositive | |
100.00% |
1 / 1 |
0 | |
100.00% |
21 / 21 |
|||
convertFromNegative | |
100.00% |
1 / 1 |
0 | |
100.00% |
8 / 8 |
|||
RFC2550 | |
100.00% |
1 / 1 |
|
100.00% |
2 / 2 |
7 | |
100.00% |
58 / 58 |
to | |
100.00% |
1 / 1 |
3 | |
100.00% |
4 / 4 |
|||
convertPositiveTo | |
100.00% |
1 / 1 |
4 | |
100.00% |
14 / 14 |
<?php | |
namespace Popy\Calendar\Formatter\NumberConverter; | |
use Popy\Calendar\Formatter\NumberConverterInterface; | |
/** | |
* Converts years for RFC2550 Implementation. | |
* | |
* @link https://tools.ietf.org/html/rfc2550 | |
*/ | |
class RFC2550 implements NumberConverterInterface | |
{ | |
const ORD_START = 65; | |
const POSITIVE_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^'; | |
const NEGATIVE_CHARS = '9876543210ZYXWVUTSRQPONMLKJIHGFEDCBA!'; | |
/** | |
* @inheritDoc | |
*/ | |
public function to($input) | |
{ | |
$input = (string)$input; | |
if ($input[0] === '-' || preg_match('/^0+$/', $input)) { | |
return $this->convertNegativeTo($input); | |
} | |
return $this->convertPositiveTo($input); | |
} | |
/** | |
* Convert a positive value into its RFC2550 representation. | |
* | |
* @param string $input Value (as a string) | |
* | |
* @return string | |
*/ | |
protected function convertPositiveTo($input) | |
{ | |
$extraLen = strlen($input) - 5; | |
if ($extraLen < 0) { | |
return str_pad($input, 4, '0', STR_PAD_LEFT); | |
} | |
if ($extraLen < 26) { | |
return chr(static::ORD_START + $extraLen) . $input; | |
} | |
$extraLen -= 25; | |
$prefix = ''; | |
$carets = ''; | |
do { | |
$carets .= '^'; | |
$extraLen--; | |
$prefix = chr(static::ORD_START + $extraLen % 26) . $prefix; | |
$extraLen = intval($extraLen / 26); | |
} while ($extraLen); | |
return "${carets}${prefix}${input}"; | |
} | |
/** | |
* Converts a negative value into its RFC2550 representation. | |
* | |
* @param string $input Value (as a string) | |
* | |
* @return string | |
*/ | |
protected function convertNegativeTo($input) | |
{ | |
$res = $this->convertPositiveTo(substr($input, 1)); | |
$res = strtr($res, static::POSITIVE_CHARS, static::NEGATIVE_CHARS); | |
if (strlen($res) < 5) { | |
$res = '/' . $res; | |
} elseif ($res[0] !== '!') { | |
$res = '*' . $res; | |
} | |
return $res; | |
} | |
/** | |
* @inheritDoc | |
*/ | |
public function from($input) | |
{ | |
if (strpos('!/*', $input[0]) !== false) { | |
return $this->convertFromNegative($input); | |
} | |
return $this->convertFromPositive($input); | |
} | |
/** | |
* Convert a positive representation. | |
* | |
* @param string $input | |
* | |
* @return string | |
*/ | |
public function convertFromPositive($input) | |
{ | |
$matches = []; | |
if ( | |
!preg_match( | |
' | |
/^0*(?<carets>\\^*)(?<alpha>[A-Z]*)(?<year>\d+)$/', | |
$input, | |
$matches | |
) | |
) { | |
return; | |
} | |
if ($matches['alpha'] === '') { | |
return $matches['year']; | |
} | |
if ($matches['carets'] === '') { | |
$expectedLength = ord($matches['alpha']) - static::ORD_START + 5; | |
} else { | |
$len = strlen($matches['carets']); | |
$expectedLength = 0; | |
for ($i=0; $i < $len; $i++) { | |
$expectedLength = $expectedLength * 26; | |
$expectedLength += ord($matches['alpha'][$i]) - static::ORD_START; | |
$expectedLength++; | |
} | |
$expectedLength += 30; | |
} | |
return str_pad($matches['year'], $expectedLength, '0', STR_PAD_RIGHT); | |
} | |
/** | |
* Convert a negative representation. | |
* | |
* @param string $input | |
* | |
* @return string | |
*/ | |
public function convertFromNegative($input) | |
{ | |
if (strpos('/*', $input[0]) !== false) { | |
$input = substr($input, 1); | |
} | |
$input = strtr($input, static::NEGATIVE_CHARS, static::POSITIVE_CHARS); | |
$res = $this->convertFromPositive($input); | |
if (preg_match('/^0+$/', $res)) { | |
return $res; | |
} | |
return '-' . $res; | |
} | |
} |