summaryrefslogtreecommitdiff
path: root/include/call.h
blob: 53030d2646f3dc140333da98e5f721908f13e7b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/**
 *  Call.h
 *
 *  This file holds a function to call a PHP function
 *
 *  @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
 *  @copyright 2014 Copernica BV
 */

/**
 *  Set up namespace
 */
namespace Php {

/**
 *  List of functions that are available for use in PHP
 */
extern bool  class_exists(const char *classname, size_t size, bool autoload = true);
inline bool  class_exists(const char *classname, bool autoload = true) { return class_exists(classname, strlen(classname), autoload); }
inline bool  class_exists(const std::string &classname, bool autoload = true) { return class_exists(classname.c_str(), classname.size(), autoload); }
extern Value constant(const char *constant);
extern Value constant(const char *constant, size_t size);
extern Value constant(const std::string &constant);
extern bool  define(const char *name, size_t size, const Value &value);
extern bool  define(const char *name, const Value &value);
extern bool  define(const std::string &name, const Value &value);
extern bool  defined(const char *constant);
extern bool  defined(const char *constant, size_t size);
extern bool  defined(const std::string &constant);
extern bool  dl(const char *filename);
inline bool  dl(const std::string &filename) { return dl(filename.c_str()); }
inline bool  dl(const Value &filename) { return dl(filename.rawValue()); }
extern Value eval(const char *phpCode);
inline Value eval(const std::string &phpCode) { return eval(phpCode.c_str()); }
extern Value include(const char *filename);
inline Value include(const std::string &filename) { return include(filename.c_str()); }
extern Value include_once(const char *filename);
inline Value include_once(const std::string &filename) { return include_once(filename.c_str()); }
inline bool  is_a(const Value &obj, const char *classname, size_t size, bool allow_string = false) { return obj.instanceOf(classname, size, allow_string); }
inline bool  is_a(const Value &obj, const char *classname, bool allow_string = false) { return is_a(obj, classname, strlen(classname), allow_string); }
inline bool  is_a(const Value &obj, const std::string &classname, bool allow_string = false) { return is_a(obj, classname.c_str(), classname.size(), allow_string); }
inline bool  is_subclass_of(const Value &obj, const char *classname, size_t size, bool allow_string = true) { return obj.derivedFrom(classname, size, allow_string); }
inline bool  is_subclass_of(const Value &obj, const char *classname, bool allow_string = true) { return is_subclass_of(obj, classname, strlen(classname), allow_string); }
inline bool  is_subclass_of(const Value &obj, const std::string &classname, bool allow_string = true) { return is_subclass_of(obj, classname.c_str(), classname.size(), allow_string); }
extern Value require(const char *filename);
inline Value require(const std::string &filename) { return require(filename.c_str()); }
extern Value require_once(const char *filename);
inline Value require_once(const std::string &filename) { return require_once(filename.c_str()); }

/**
 *  Call a function in PHP
 *  @param  name        Name of the function to call
 *  @param  params      Variable number of parameters
 *  @return Value
 */
template <typename ...Params>
Value call(const char *name, Params&&... params)
{
    // the name can be turned into a Php::Value object, which implements
    // the operator () method to call it
    Value function(name);
    
    // invoke the operator ()
    return function(std::forward<Params>(params)...);
}

/**
 *  Long list of simply-forwarded function calls
 * 
 *  Most functions in this list are forwarded to the call() method described
 *  above, which of course is slower than necessary, because they will have to 
 *  pass the entire zend engine to look up the actual implementation, while a
 *  direct call the C implementation was possible too. The reason for this is 
 *  that we are lazy - if you feel like looking up the actual implementation for
 *  each function in the PHP source, your support is more than welcome.
 * 
 *  But since it is a stupid idea to call a PHP function from your extension
 *  anyway (that's what people write extension for: to get away from PHP and
 *  make the code run on the highway), it is not expected that these functions
 *  are going to be used very often anyway.
 */
inline Value array_key_exists(const Value &key, const Value &array) { return array.contains(key); }
inline Value array_key_exists(int key, const Value &array) { return array.contains(key); }
inline Value array_key_exists(const char *key, const Value &array) { return array.contains(key); }
inline Value array_key_exists(const std::string &key, const Value &array) { return array.contains(key); }
inline Value array_keys(const Value &value) { return call("array_keys", value); }
inline Value array_push(const Value &array, const Value &value) { return call("array_push", array, value); }
inline Value array_values(const Value &value) { return call("array_values", value); }
inline Value count(const Value &value) { return call("count", value); }
inline Value echo(const char *input) { out << input; return nullptr; }
inline Value echo(const std::string &input) { out << input; return nullptr; }
inline Value empty(const Value &value) { return value.isNull() || !value.boolValue(); }
inline Value empty(const HashMember<std::string> &member) { return !member.exists() || empty(member.value()); }
inline Value empty(const HashMember<int> &member) { return !member.exists() || empty(member.value()); }
inline Value is_array(const Value &value) { return value.isArray(); }
inline Value strlen(const Value &value) { return call("strlen", value); }
inline void  unset(const HashMember<std::string> &member) { member.unset(); }
inline void  unset(const HashMember<int> &member) { member.unset(); }
inline void  unset(const HashMember<Value> &member) { member.unset(); }

/**
 *  The 'ini_get' function returns an IniValue, so that it can also be used
 *  before the PHP engine is started.
 */
inline IniValue ini_get(const char* name) { return IniValue(name, false); }
inline IniValue ini_get_orig(const char* name) { return IniValue(name, true); }


/**
 *  The isset function conflicts with the 'isset' macro defined by the Zend engine
 */
#pragma push_macro("isset")
#undef isset

/**
 *  Define the isset function
 */
inline Value isset(const Value &value) { return call("isset", value); }
inline Value isset(const HashMember<std::string> &member) { return member.exists() && isset(member.value()); }
inline Value isset(const HashMember<int> &member) { return member.exists() && isset(member.value()); }
inline Value isset(const HashMember<Value> &member) { return member.exists() && isset(member.value()); }

/**
 *  Re-install the ISSET macro
 */
#pragma pop_macro("isset")

/**
 *  End of namespace
 */
}