• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jbboehr / php-mustache / 34081562661

07 Sep 2026 04:00AM UTC coverage: 85.646% (+0.3%) from 85.352%
34081562661

push

github

jbboehr
Add explicit PHP lambda result classes

Allow callbacks to choose literal text or template evaluation independently of the engine's string mode, preserving HTML escaping and legacy return conversion.

Keep both result types final and immutable, with owned text, value cloning, and rejection of ordinary-data use. Refs #68.

85 of 98 new or added lines in 5 files covered. (86.73%)

1259 of 1470 relevant lines covered (85.65%)

15776.15 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.67
/mustache_lambda_result.cpp
1
#ifdef HAVE_CONFIG_H
2
#include "config.h"
3
#endif
4

5
#include "php_mustache.h"
6
#include "mustache_arginfo.h"
7
#include "mustache_exceptions.hpp"
8
#include "mustache_lambda_result.hpp"
9
#if PHP_VERSION_ID < 80100
10
#include <Zend/zend_exceptions.h>
11
#include <Zend/zend_interfaces.h>
12
#endif
13

14
zend_class_entry * MustacheLiteralResult_ce_ptr;
15
zend_class_entry * MustacheTemplateResult_ce_ptr;
16
static zend_object_handlers MustacheLambdaResult_obj_handlers;
17

18
struct php_obj_MustacheLambdaResult {
19
  zend_string * text;
20
  zend_object std;
21
};
22

23
static php_obj_MustacheLambdaResult * mustache_lambda_result_fetch(zend_object * object)
852✔
24
{
25
  return (php_obj_MustacheLambdaResult *)((char *) object - XtOffsetOf(php_obj_MustacheLambdaResult, std));
852✔
26
}
27

28
zend_string * php_mustache_lambda_result_text(zval * value)
426✔
29
{
30
  zend_string * text = mustache_lambda_result_fetch(Z_OBJ_P(value))->text;
426✔
31
  if( text == NULL ) {
426✔
NEW
32
    zend_throw_error(NULL, "%s is not initialized", ZSTR_VAL(Z_OBJCE_P(value)->name));
×
NEW
33
    throw PhpInvalidParameterException();
×
34
  }
35
  return text;
426✔
36
}
37

38
static zend_object * MustacheLambdaResult_obj_create(zend_class_entry * ce)
183✔
39
{
40
  php_obj_MustacheLambdaResult * payload =
41
      (php_obj_MustacheLambdaResult *) zend_object_alloc(sizeof(php_obj_MustacheLambdaResult), ce);
183✔
42
  payload->text = NULL;
183✔
43
  zend_object_std_init(&payload->std, ce);
183✔
44
  object_properties_init(&payload->std, ce);
183✔
45
  payload->std.handlers = &MustacheLambdaResult_obj_handlers;
183✔
46
  return &payload->std;
183✔
47
}
48

49
static void MustacheLambdaResult_obj_free(zend_object * object)
183✔
50
{
51
  php_obj_MustacheLambdaResult * payload = mustache_lambda_result_fetch(object);
183✔
52
  if( payload->text != NULL ) {
183✔
53
    zend_string_release(payload->text);
171✔
54
  }
55
  zend_object_std_dtor(object);
183✔
56
}
183✔
57

58
static zend_object * MustacheLambdaResult_obj_clone(zend_object * object)
6✔
59
{
60
  zend_string * text = mustache_lambda_result_fetch(object)->text;
6✔
61
  if( text == NULL ) {
6✔
NEW
62
    zend_throw_error(NULL, "%s is not initialized", ZSTR_VAL(object->ce->name));
×
NEW
63
    return NULL;
×
64
  }
65
  zend_object * copy = MustacheLambdaResult_obj_create(object->ce);
6✔
66
  mustache_lambda_result_fetch(copy)->text = zend_string_copy(text);
6✔
67
  zend_objects_clone_members(copy, object);
6✔
68
  return copy;
6✔
69
}
70

71
static int MustacheLambdaResult_obj_compare(zval * left, zval * right)
36✔
72
{
73
  ZEND_COMPARE_OBJECTS_FALLBACK(left, right);
72✔
74
  if( Z_OBJCE_P(left) != Z_OBJCE_P(right) ) {
36✔
75
    return ZEND_UNCOMPARABLE;
6✔
76
  }
77
  if( Z_OBJ_P(left) == Z_OBJ_P(right) ) {
30✔
NEW
78
    return 0;
×
79
  }
80
  zend_string * left_text = mustache_lambda_result_fetch(Z_OBJ_P(left))->text;
30✔
81
  zend_string * right_text = mustache_lambda_result_fetch(Z_OBJ_P(right))->text;
30✔
82
  if( left_text == NULL || right_text == NULL ) {
30✔
NEW
83
    zend_throw_error(NULL, "%s is not initialized", ZSTR_VAL(Z_OBJCE_P(left)->name));
×
NEW
84
    return ZEND_UNCOMPARABLE;
×
85
  }
86
  return zend_binary_strcmp(ZSTR_VAL(left_text), ZSTR_LEN(left_text),
60✔
87
      ZSTR_VAL(right_text), ZSTR_LEN(right_text));
30✔
88
}
89

90
PHP_METHOD(MustacheLiteralResult, __construct)
183✔
91
{
92
  zend_string * text;
93
  ZEND_PARSE_PARAMETERS_START(1, 1)
183✔
94
    Z_PARAM_STR(text)
354✔
95
  ZEND_PARSE_PARAMETERS_END();
189✔
96

97
  php_obj_MustacheLambdaResult * payload = mustache_lambda_result_fetch(Z_OBJ_P(getThis()));
342✔
98
  if( payload->text != NULL ) {
171✔
99
    zend_throw_error(NULL, "%s is already initialized", ZSTR_VAL(Z_OBJCE_P(getThis())->name));
12✔
100
    RETURN_THROWS();
6✔
101
  }
102
  payload->text = zend_string_copy(text);
330✔
103
}
104

105
PHP_METHOD(MustacheLiteralResult, getText)
39✔
106
{
107
  ZEND_PARSE_PARAMETERS_NONE();
39✔
108
  try {
109
    RETURN_STR_COPY(php_mustache_lambda_result_text(getThis()));
120✔
NEW
110
  } catch(...) {
×
NEW
111
    mustache_exception_handler();
×
NEW
112
  }
×
113
}
114

115
#if PHP_VERSION_ID < 80100
116
PHP_METHOD(MustacheLiteralResult, __serialize)
117
{
118
  zend_throw_exception_ex(zend_ce_exception, 0,
119
      "Serialization of '%s' is not allowed", ZSTR_VAL(Z_OBJCE_P(getThis())->name));
120
  RETURN_THROWS();
121
}
122

123
PHP_METHOD(MustacheLiteralResult, __unserialize)
124
{
125
  zend_throw_exception_ex(zend_ce_exception, 0,
126
      "Serialization of '%s' is not allowed", ZSTR_VAL(Z_OBJCE_P(getThis())->name));
127
  RETURN_THROWS();
128
}
129
#endif
130

131
static zend_function_entry MustacheLiteralResult_methods[] = {
132
  PHP_ME(MustacheLiteralResult, __construct, arginfo_class_MustacheLiteralResult___construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
133
  PHP_ME(MustacheLiteralResult, getText, arginfo_class_MustacheLiteralResult_getText, ZEND_ACC_PUBLIC)
134
#if PHP_VERSION_ID < 80100
135
  PHP_ME(MustacheLiteralResult, __serialize, arginfo_class_MustacheLiteralResult___serialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
136
  PHP_ME(MustacheLiteralResult, __unserialize, arginfo_class_MustacheLiteralResult___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
137
#endif
138
  { NULL, NULL, NULL }
139
};
140

141
// The classes have identical methods and storage; their class selects interpretation.
142
static zend_function_entry MustacheTemplateResult_methods[] = {
143
  PHP_MALIAS(MustacheLiteralResult, __construct, __construct, arginfo_class_MustacheTemplateResult___construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
144
  PHP_MALIAS(MustacheLiteralResult, getText, getText, arginfo_class_MustacheTemplateResult_getText, ZEND_ACC_PUBLIC)
145
#if PHP_VERSION_ID < 80100
146
  PHP_MALIAS(MustacheLiteralResult, __serialize, __serialize, arginfo_class_MustacheTemplateResult___serialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
147
  PHP_MALIAS(MustacheLiteralResult, __unserialize, __unserialize, arginfo_class_MustacheTemplateResult___unserialize, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
148
#endif
149
  { NULL, NULL, NULL }
150
};
151

152
PHP_MINIT_FUNCTION(mustache_lambda_result)
994✔
153
{
154
  memcpy(&MustacheLambdaResult_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
994✔
155
  MustacheLambdaResult_obj_handlers.offset = XtOffsetOf(php_obj_MustacheLambdaResult, std);
994✔
156
  MustacheLambdaResult_obj_handlers.free_obj = MustacheLambdaResult_obj_free;
994✔
157
  MustacheLambdaResult_obj_handlers.clone_obj = MustacheLambdaResult_obj_clone;
994✔
158
  MustacheLambdaResult_obj_handlers.compare = MustacheLambdaResult_obj_compare;
994✔
159

160
  zend_class_entry ce;
161
  INIT_CLASS_ENTRY(ce, "MustacheLiteralResult", MustacheLiteralResult_methods);
994✔
162
  ce.ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NO_DYNAMIC_PROPERTIES;
994✔
163
  ce.create_object = MustacheLambdaResult_obj_create;
994✔
164
#if PHP_VERSION_ID < 80100
165
  ce.serialize = zend_class_serialize_deny;
166
  ce.unserialize = zend_class_unserialize_deny;
167
#else
168
  ce.ce_flags |= ZEND_ACC_NOT_SERIALIZABLE;
994✔
169
#endif
170
  MustacheLiteralResult_ce_ptr = zend_register_internal_class(&ce);
994✔
171

172
  INIT_CLASS_ENTRY(ce, "MustacheTemplateResult", MustacheTemplateResult_methods);
994✔
173
  ce.ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NO_DYNAMIC_PROPERTIES;
994✔
174
  ce.create_object = MustacheLambdaResult_obj_create;
994✔
175
#if PHP_VERSION_ID < 80100
176
  ce.serialize = zend_class_serialize_deny;
177
  ce.unserialize = zend_class_unserialize_deny;
178
#else
179
  ce.ce_flags |= ZEND_ACC_NOT_SERIALIZABLE;
994✔
180
#endif
181
  MustacheTemplateResult_ce_ptr = zend_register_internal_class(&ce);
994✔
182
  return SUCCESS;
994✔
183
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc