Skip to content

Commit cfb24b5

Browse files
committed
Fix registering object handlers on PHP 8.3
1 parent 6106253 commit cfb24b5

3 files changed

Lines changed: 152 additions & 1 deletion

File tree

php_decimal.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,9 @@ static php_decimal_t *php_decimal_alloc()
358358
php_decimal_t *obj = ecalloc(1, sizeof(php_decimal_t));
359359

360360
if (obj) {
361+
#if PHP_VERSION_ID < 80300
361362
obj->std.handlers = &php_decimal_handlers;
363+
#endif
362364
zend_object_std_init((zend_object *) obj, php_decimal_ce);
363365
} else {
364366
php_decimal_memory_error();
@@ -2746,6 +2748,10 @@ static void php_decimal_register_class_entry()
27462748
php_decimal_ce->serialize = php_decimal_serialize;
27472749
php_decimal_ce->unserialize = php_decimal_unserialize;
27482750

2751+
#if PHP_VERSION_ID >= 80300
2752+
php_decimal_ce->default_object_handlers = &php_decimal_handlers;
2753+
#endif
2754+
27492755
zend_class_implements(php_decimal_ce, 1, php_json_serializable_ce);
27502756

27512757
PHP_DECIMAL_LONG_CONSTANT("ROUND_UP", PHP_DECIMAL_ROUND_UP);
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
--TEST--
2+
Decimal::__construct
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("decimal") || PHP_VERSION_ID < 81000) echo "skip";
6+
?>
7+
--FILE--
8+
<?php
9+
use Decimal\Decimal;
10+
11+
$tests = [
12+
13+
/**
14+
* Constructor args, expected precision, expected value
15+
*
16+
* Decimal::__construct(value [, precision])
17+
*/
18+
[[], 28, "0"],
19+
20+
[[123, /* 28 */ ], 28, "123"],
21+
[["0.2000", /* 28 */ ], 28, "0.2000"],
22+
[["1E+900", /* 28 */ ], 28, "1E+900"],
23+
[[new Decimal("0.1"), /* 28 */ ], 28, "0.1"],
24+
25+
[[123, 10], 10, "123"],
26+
[["0.2000", 10], 10, "0.2000"],
27+
[["1E+900", 10], 10, "1E+900"],
28+
[[new Decimal("0.1"), 10], 28, "0.1"],
29+
30+
[[150, 1], 1, "2E+2"], // Warning
31+
[["0.2000", 1], 1, "0.2"], // No warning, result is exact
32+
[["0.20001", 1], 1, "0.2"], // Warning, data lost
33+
[["1E+900", 1], 1, "1E+900"],
34+
[[new Decimal("0.1"), 1], 28, "0.1"],
35+
36+
/* Precision is considered a minimum, to preserve precision of decimals. */
37+
[[new Decimal("0.12345", 5), 1], 5, "0.12345"],
38+
39+
/* Use given decimal precision if greater than default. */
40+
[[new Decimal("0.1234", 50), /* 28 */], 50, "0.1234"],
41+
42+
[[ "nan"], 28, "NAN"],
43+
[[ "inf"], 28, "INF"],
44+
[["-inf"], 28, "-INF"],
45+
46+
/* While float is not actually supported, these constants are an exception
47+
for the sake of developer sanity and convenience. */
48+
[[ NAN], 28, "NAN"],
49+
[[ INF], 28, "INF"],
50+
[[-INF], 28, "-INF"],
51+
52+
/* Check precision bounds */
53+
[[0, Decimal::MAX_PRECISION], Decimal::MAX_PRECISION, "0"],
54+
[[0, Decimal::MIN_PRECISION], Decimal::MIN_PRECISION, "0"],
55+
];
56+
57+
foreach ($tests as $index => $test) {
58+
list($args, $precision, $expect) = $test;
59+
60+
$result = new Decimal(...$args);
61+
62+
if ($result->precision() !== $precision || (string) $result !== $expect) {
63+
var_dump(compact("index", "args", "result", "precision", "expect"));
64+
}
65+
}
66+
67+
68+
try {
69+
new Decimal(" 1");
70+
} catch (DomainException $e) {
71+
printf("A %s\n", $e->getMessage());
72+
}
73+
74+
try {
75+
new Decimal("1 ");
76+
} catch (DomainException $e) {
77+
printf("B %s\n", $e->getMessage());
78+
}
79+
80+
try {
81+
new Decimal(1.5);
82+
} catch (TypeError $e) {
83+
printf("C %s\n", $e->getMessage());
84+
}
85+
86+
try {
87+
new Decimal(null);
88+
} catch (TypeError $e) {
89+
printf("D %s\n", $e->getMessage());
90+
}
91+
92+
try {
93+
new Decimal(0, "b");
94+
} catch (TypeError $e) {
95+
printf("E %s\n", $e->getMessage());
96+
}
97+
98+
try {
99+
new Decimal(0, null);
100+
} catch (OutOfRangeException $e) {
101+
printf("F %s\n", $e->getMessage());
102+
}
103+
104+
try {
105+
new Decimal(0, 0);
106+
} catch (OutOfRangeException $e) {
107+
printf("G %s\n", $e->getMessage());
108+
}
109+
110+
try {
111+
new Decimal(0, -1);
112+
} catch (OutOfRangeException $e) {
113+
printf("H %s\n", $e->getMessage());
114+
}
115+
116+
/* Check max precision */
117+
try {
118+
new Decimal(0, Decimal::MAX_PRECISION + 1);
119+
} catch (OutOfRangeException $e) {
120+
printf("I %s\n", $e->getMessage());
121+
}
122+
123+
try {
124+
(new Decimal())->__construct();
125+
} catch (BadMethodCallException $e) {
126+
printf("J %s\n", $e->getMessage());
127+
}
128+
129+
?>
130+
--EXPECTF--
131+
Warning: Loss of data on integer conversion in %s on line %d
132+
133+
Warning: Loss of data on string conversion in %s on line %d
134+
A Failed to parse string as decimal: " 1"
135+
B Failed to parse string as decimal: "1 "
136+
C Decimal\Decimal::__construct() expected parameter 1 to be a string, integer, or decimal, float given
137+
D Decimal\Decimal::__construct() expected parameter 1 to be a string, integer, or decimal, null given
138+
E Decimal\Decimal::__construct(): Argument #2 ($precision) must be of type int, string given
139+
140+
Deprecated: Decimal\Decimal::__construct(): Passing null to parameter #2 ($precision) of type int is deprecated in /work/php-decimal/ext-decimal/tests/php8/methods/__construct.php on line 92
141+
F Decimal precision out of range
142+
G Decimal precision out of range
143+
H Decimal precision out of range
144+
I Decimal precision out of range
145+
J Decimal objects are immutable

tests/php8/methods/__construct.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Decimal::__construct
33
--SKIPIF--
44
<?php
5-
if (!extension_loaded("decimal") || PHP_VERSION_ID < 80000) echo "skip";
5+
if (!extension_loaded("decimal") || PHP_VERSION_ID < 80000 || PHP_VERSION_ID >= 80100) echo "skip";
66
?>
77
--FILE--
88
<?php

0 commit comments

Comments
 (0)