Skip to content

Commit 801c01d

Browse files
Merge pull request #364 from sjinks/issue-359
Add support for PHP 7.2
2 parents 1b67997 + 0e5924a commit 801c01d

File tree

2 files changed

+68
-2
lines changed

2 files changed

+68
-2
lines changed

zend/callable.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,19 @@ void Callable::invoke(INTERNAL_FUNCTION_PARAMETERS)
2727
uint32_t argc = EX(func)->common.num_args;
2828
zend_arg_info* info = EX(func)->common.arg_info;
2929

30+
#if PHP_VERSION_ID < 70200
3031
// Sanity check
3132
assert(info[argc].class_name != nullptr && info[argc].name == nullptr);
3233

3334
// the callable we are retrieving
3435
Callable *callable = reinterpret_cast<Callable*>(info[argc].class_name);
36+
#else
37+
// Sanity check
38+
assert(info[argc].type != 0 && info[argc].name == nullptr);
39+
40+
// the callable we are retrieving
41+
Callable *callable = reinterpret_cast<Callable*>(info[argc].type);
42+
#endif
3543

3644
// check if sufficient parameters were passed (for some reason this check
3745
// is not done by Zend, so we do it here ourselves)
@@ -87,7 +95,11 @@ void Callable::initialize(zend_function_entry *entry, const char *classname, int
8795
else
8896
{
8997
// install ourselves in the extra argument
98+
#if PHP_VERSION_ID < 70200
9099
_argv[_argc + 1].class_name = reinterpret_cast<const char*>(this);
100+
#else
101+
_argv[_argc + 1].type = reinterpret_cast<zend_type>(this);
102+
#endif
91103

92104
// we use our own invoke method, which does a lookup
93105
// in the map we just installed ourselves in
@@ -111,6 +123,7 @@ void Callable::initialize(zend_function_entry *entry, const char *classname, int
111123
*/
112124
void Callable::initialize(zend_internal_function_info *info, const char *classname) const
113125
{
126+
#if PHP_VERSION_ID < 70200
114127
// store the classname
115128
info->class_name = classname;
116129

@@ -126,6 +139,18 @@ void Callable::initialize(zend_internal_function_info *info, const char *classna
126139
// them to false
127140
info->allow_null = false;
128141
info->_is_variadic = false;
142+
#else
143+
info->required_num_args = _required;
144+
info->return_reference = false;
145+
info->_is_variadic = false;
146+
147+
if (_return == Type::Object) {
148+
info->type = reinterpret_cast<zend_type>(classname);
149+
}
150+
else {
151+
info->type = ZEND_TYPE_ENCODE(static_cast<unsigned char>(_return), 0);
152+
}
153+
#endif
129154
}
130155

131156
/**

zend/callable.h

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,12 @@ class Callable
5252
}
5353

5454
// initialize the extra argument
55+
#if PHP_VERSION_ID < 70200
5556
_argv[i].class_name = nullptr;
5657
_argv[i].name = nullptr;
58+
#else
59+
_argv[i].type = 0;
60+
#endif
5761
}
5862

5963
/**
@@ -167,13 +171,18 @@ class Callable
167171
// fill members
168172
info->name = arg.name();
169173

174+
#if PHP_VERSION_ID < 70200
170175
// are we filling an object
171176
if (arg.type() == Type::Object) info->class_name = arg.classname();
172177
else info->class_name = nullptr;
173178

179+
info->allow_null = arg.allowNull();
180+
#endif
181+
174182
// set the correct type-hint
175183
switch (arg.type())
176184
{
185+
#if PHP_VERSION_ID < 70200
177186
case Type::Undefined: info->type_hint = IS_UNDEF; break; // undefined means we'll accept any type
178187
case Type::Null: info->type_hint = IS_UNDEF; break; // this is likely an error, what good would accepting NULL be? accept anything
179188
case Type::False: info->type_hint = _IS_BOOL; break; // accept true as well ;)
@@ -186,7 +195,41 @@ class Callable
186195
case Type::Object: info->type_hint = IS_OBJECT; break; // must be an object of the given classname
187196
case Type::Callable: info->type_hint = IS_CALLABLE; break; // anything that can be invoked
188197
default: info->type_hint = IS_UNDEF; break; // if not specified we allow anything
198+
#else
199+
case Type::Undefined: info->type = ZEND_TYPE_ENCODE(IS_UNDEF, arg.allowNull()); break; // undefined means we'll accept any type
200+
case Type::Null: info->type = ZEND_TYPE_ENCODE(IS_UNDEF, arg.allowNull()); break; // this is likely an error, what good would accepting NULL be? accept anything
201+
case Type::False: info->type = ZEND_TYPE_ENCODE(_IS_BOOL, arg.allowNull()); break; // accept true as well ;)
202+
case Type::True: info->type = ZEND_TYPE_ENCODE(_IS_BOOL, arg.allowNull()); break; // accept false as well
203+
case Type::Bool: info->type = ZEND_TYPE_ENCODE(_IS_BOOL, arg.allowNull()); break; // any bool will do, true, false, the options are limitless
204+
case Type::Numeric: info->type = ZEND_TYPE_ENCODE(IS_LONG, arg.allowNull()); break; // accept integers here
205+
case Type::Float: info->type = ZEND_TYPE_ENCODE(IS_DOUBLE, arg.allowNull()); break; // floating-point values welcome too
206+
case Type::String: info->type = ZEND_TYPE_ENCODE(IS_STRING, arg.allowNull()); break; // accept strings, should auto-cast objects with __toString as well
207+
case Type::Array: info->type = ZEND_TYPE_ENCODE(IS_ARRAY, arg.allowNull()); break; // array of anything (individual members cannot be restricted)
208+
case Type::Object: // must be an object of the given classname
209+
if (arg.classname()) {
210+
if (!arg.allowNull()) {
211+
info->type = reinterpret_cast<zend_type>(arg.classname());
212+
}
213+
else {
214+
/// FIXME this leaks, although this happens only once during startup / MINIT
215+
/// Probably not critical
216+
217+
const char* orig = arg.classname();
218+
std::size_t len = std::strlen(orig);
219+
char* newname = new char[len + 2]; // trailing NUL and heading ?
220+
newname[0] = '?';
221+
std::memcpy(newname + 1, orig, len + 1 /* Trailing NUL */);
222+
}
223+
}
224+
else {
225+
info->type = ZEND_TYPE_ENCODE(IS_OBJECT, arg.allowNull());
226+
}
189227

228+
break;
229+
230+
case Type::Callable: info->type = ZEND_TYPE_ENCODE(IS_CALLABLE, arg.allowNull()); break; // anything that can be invoked
231+
default: info->type = ZEND_TYPE_ENCODE(IS_UNDEF, arg.allowNull()); break; // if not specified we allow anything
232+
#endif
190233
}
191234

192235
// from PHP 5.6 and onwards, an is_variadic property can be set, this
@@ -195,8 +238,6 @@ class Callable
195238
// support methods and functions with a fixed number of arguments.
196239
info->is_variadic = false;
197240

198-
// this parameter is a regular type
199-
info->allow_null = arg.allowNull();
200241
info->pass_by_reference = arg.byReference();
201242
}
202243

0 commit comments

Comments
 (0)