Skip to content

Commit c25efef

Browse files
the Value::isCallable() did not work, it has been refactored based on the "method_exists" implementation
1 parent 94003aa commit c25efef

File tree

3 files changed

+113
-8
lines changed

3 files changed

+113
-8
lines changed

zend/includes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <zend_exceptions.h>
4343
#include <zend_interfaces.h>
4444
#include <zend_ini.h>
45+
#include <zend_closures.h>
4546
#include <SAPI.h>
4647

4748
/**

zend/lowercase.h

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/**
2+
* LowerCase.h
3+
*
4+
* Class to temporary convert a name to lowercase
5+
*
6+
* @author Emiel Bruijntjes <[email protected]>
7+
* @copyright 2016 Copernica BV
8+
*/
9+
10+
/**
11+
* Include guard
12+
*/
13+
#pragma once
14+
15+
/**
16+
* Begin of namespace
17+
*/
18+
namespace Php {
19+
20+
/**
21+
* Class definition
22+
*/
23+
class LowerCase
24+
{
25+
private:
26+
/**
27+
* The lowercase name
28+
* @var zend_string
29+
*/
30+
zend_string *_name;
31+
32+
public:
33+
/**
34+
* Constructor
35+
* @param name the original name
36+
*/
37+
LowerCase(zend_string *name) :
38+
_name(zend_string_tolower(name)) {}
39+
40+
/**
41+
* No copy'ing or moving
42+
* @param that
43+
*/
44+
LowerCase(const LowerCase &that) = delete;
45+
LowerCase(LowerCase &&that) = delete;
46+
47+
/**
48+
* Destructor
49+
*/
50+
virtual ~LowerCase()
51+
{
52+
// release the data
53+
zend_string_release(_name);
54+
}
55+
56+
/**
57+
* Expose internal value
58+
* @return zend_string*
59+
*/
60+
zend_string *value()
61+
{
62+
// expose member
63+
return _name;
64+
}
65+
66+
/**
67+
* Cast to a zend_string
68+
* @return zend_string*
69+
*/
70+
operator zend_string* ()
71+
{
72+
// expose member
73+
return _name;
74+
}
75+
};
76+
77+
/**
78+
* End of namespace
79+
*/
80+
}

zend/value.cpp

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
*/
2727
#include "includes.h"
2828
#include "string.h"
29+
#include "lowercase.h"
2930

3031
/**
3132
* Set up namespace
@@ -800,15 +801,38 @@ bool Value::isCallable(const char *name)
800801
{
801802
// this only makes sense if we are an object
802803
if (!isObject()) return false;
804+
805+
// get the class properties
806+
zend_class_entry *ce = Z_OBJCE_P(_val);
803807

804-
// wrap the name in a Php::Value object to get a zval
805-
Value method(name);
806-
807-
// we need the tsrm_ls variable
808-
TSRMLS_FETCH();
809-
810-
// ask zend nicely whether the function is callable
811-
return zend_is_callable_ex(method._val, Z_OBJ_P(_val), IS_CALLABLE_CHECK_NO_ACCESS, nullptr, nullptr, nullptr TSRMLS_CC);
808+
// convert the name to lowercase
809+
LowerCase methodname{String(name)};
810+
811+
// check if the function indeed exists
812+
if (zend_hash_exists(&ce->function_table, methodname)) return true;
813+
814+
// can we dynamically fetch the method?
815+
if (Z_OBJ_HT_P(_val)->get_method == nullptr) return false;
816+
817+
// get the function
818+
union _zend_function *func = Z_OBJ_HT_P(_val)->get_method(&Z_OBJ_P(_val), methodname, nullptr);
819+
820+
// if function does not exist, we do not have to check further
821+
if (func == nullptr) return false;
822+
823+
// i dont get this code, it is copied from the method_exists() function (but the code has
824+
// of course been prettified because the php guys dont know how to write good looking code)
825+
if (!(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) return true;
826+
827+
// check the result ("Returns true to the fake Closure's __invoke")
828+
bool result = func->common.scope == zend_ce_closure && zend_string_equals_literal(methodname.value(), ZEND_INVOKE_FUNC_NAME);
829+
830+
// free resources (still don't get this code, copied from zend_builtin_functions.c)
831+
zend_string_release(func->common.function_name);
832+
zend_free_trampoline(func);
833+
834+
// done
835+
return result;
812836
}
813837

814838
/**

0 commit comments

Comments
 (0)