• 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

94.23
/mustache_lambda.cpp
1

2
#ifdef HAVE_CONFIG_H
3
#include "config.h"
4
#endif
5

6
#define NOMINMAX
7

8
#include "php_mustache.h"
9
#include <algorithm>
10
#include <utility>
11
#include "mustache_exceptions.hpp"
12
#include "mustache_lambda_helper.hpp"
13
#include "mustache_lambda.hpp"
14
#include "mustache_lambda_result.hpp"
15
#include "mustache_zval.hpp"
16

17
#undef min
18

19
namespace {
20

21
class ZvalArguments {
22
  private:
23
    zval values[2];
24
    int count;
25

26
  public:
27
    explicit ZvalArguments(int argument_count) :
420✔
28
        count(argument_count)
420✔
29
    {
30
      for( int i = 0; i < count; i++ ) {
789✔
31
        ZVAL_UNDEF(&values[i]);
369✔
32
      }
33
    }
420✔
34

35
    ~ZvalArguments()
420✔
36
    {
37
      for( int i = count - 1; i >= 0; i-- ) {
789✔
38
        if( !Z_ISUNDEF(values[i]) ) {
738✔
39
          zval_ptr_dtor(&values[i]);
369✔
40
        }
41
      }
42
    }
420✔
43

44
    ZvalArguments(const ZvalArguments&) = delete;
45
    ZvalArguments& operator=(const ZvalArguments&) = delete;
46

47
    zval * data()
420✔
48
    {
49
      return count == 0 ? NULL : values;
420✔
50
    }
51

52
    zval& operator[](int index)
516✔
53
    {
54
      return values[index];
516✔
55
    }
56
};
57

58
} // namespace
59

60
mustache::LambdaResult Lambda::invokeUserFunctionAsResult(int param_count, zval params[])
1,037✔
61
{
62
  ZvalGuard result;
1,037✔
63
  int status = invokeUserFunction(result.get(), param_count, params);
1,037✔
64
  if( EG(exception) != NULL ) {
1,037✔
65
    throw PhpInvalidParameterException();
48✔
66
  }
67
  if( status != SUCCESS || Z_ISUNDEF_P(result.get()) ) {
1,978✔
NEW
68
    return mustache::LambdaResult::fromString(std::string());
×
69
  }
70

71
  zval * value = result.get();
989✔
72
  ZVAL_DEREF(value);
989✔
73
  if( Z_TYPE_P(value) == IS_OBJECT && php_mustache_is_lambda_result(Z_OBJCE_P(value)) ) {
989✔
74
    zend_string * text = php_mustache_lambda_result_text(value);
387✔
75
    std::string owned_text(ZSTR_VAL(text), ZSTR_LEN(text));
387✔
76
    return Z_OBJCE_P(value) == MustacheLiteralResult_ce_ptr
387✔
77
        ? mustache::LambdaResult::literal(std::move(owned_text))
210✔
78
        : mustache::LambdaResult::templateSource(std::move(owned_text));
597✔
79
  }
387✔
80

81
  convert_to_string(result.get());
1,204✔
82
  if( EG(exception) != NULL ) {
602✔
83
    throw PhpInvalidParameterException();
3✔
84
  }
85
  if( Z_TYPE_P(result.get()) != IS_STRING ) {
1,198✔
NEW
86
    return mustache::LambdaResult::fromString(std::string());
×
87
  }
88

89
  return mustache::LambdaResult::fromString(
90
      std::string(Z_STRVAL_P(result.get()), Z_STRLEN_P(result.get())));
1,198✔
91
}
1,037✔
92

93
mustache::LambdaResult Lambda::invokeResult()
617✔
94
{
95
  return invokeUserFunctionAsResult(0, NULL);
617✔
96
}
97

98
mustache::LambdaResult Lambda::invokeResult(
420✔
99
    std::string_view text, mustache::LambdaRenderContext context)
100
{
101
  int param_count = std::clamp(getUserFunctionParamCount(), 0, 2);
420✔
102
  ZvalArguments params(param_count);
420✔
103
  if( param_count >= 1 ) {
420✔
104
    ZVAL_STRINGL(&params[0], text.data(), text.size());
444✔
105
  }
106
  if( param_count >= 2 ) {
420✔
107
    object_init_ex(&params[1], MustacheLambdaHelper_ce_ptr);
147✔
108

109
    struct php_obj_MustacheLambdaHelper * payload = php_mustache_lambda_helper_object_fetch_object(&params[1]);
147✔
110
    if( payload->state == NULL ) {
147✔
111
      throw InvalidParameterException("MustacheLambdaHelper state was not initialized properly");
×
112
    }
113
    payload->state->context = context;
147✔
114
  }
115

116
  return invokeUserFunctionAsResult(param_count, params.data());
792✔
117
}
420✔
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