LightnCandy option: safestring

Use safestring option to provide your own SafeString implementation or change the default LS classname when FLAG_STANDALONEPHP is enabled.

MySafeString

You should provide __toString(). If you use \LightnCandy\SafeString in your custom helper, it will be replaced by your safestring automatically.

Source Code
require_once('./vendor/autoload.php');
use LightnCandy\LightnCandy;

class MySafeString {
    public function __toString() {
        return 'Yes! You&me!';
    }
}

$template = "{{foo}}, {{bar}}";

$phpStr = LightnCandy::compile($template, array(
    'flags' => LightnCandy::FLAG_HANDLEBARS | LightnCandy::FLAG_STANDALONEPHP,
    'helpers' => array(
        'foo' => function () {
            return new MySafeString();
        },
        'bar' => function () {
            return new \LightnCandy\SafeString('He&She!');
        }
    ),
    'safestring' => 'MySafeString'
));

$renderer = LightnCandy::prepare($phpStr);
echo $renderer();

Output

Yes! You&me!, Yes! You&me!

Rename LS class

If you specify the safestring option but the class is existing, then the \LightnCandy\SafeString class will be used.

Source Code
require_once('./vendor/autoload.php');
use LightnCandy\LightnCandy;

$template = "{{foo}}, {{bar}}";

$phpStr = LightnCandy::compile($template, array(
    'flags' => LightnCandy::FLAG_HANDLEBARS | LightnCandy::FLAG_STANDALONEPHP,
    'helpers' => array(
        'foo' => function () {
            return new MySafeString('You&Me!');
        },
        'bar' => function () {
            return new \LightnCandy\SafeString('He&She!');
        }
    ),
    'safestring' => 'MySafeString'
));

$renderer = LightnCandy::prepare($phpStr);
echo "The Code:\n$phpStr\n\n";
echo "===========================\nThe Output:\n" . $renderer();

Output

The Code:
 function lcr62387a1957f7bhbch(&$cx, $ch, $vars, $op, &$_this)
 {
  if (isset($cx['blparam'][0][$ch])) {
   return $cx['blparam'][0][$ch];
  }

  $options = array(
   'name' => $ch,
   'hash' => $vars[1],
   'contexts' => count($cx['scopes']) ? $cx['scopes'] : array(null),
   'fn.blockParams' => 0,
   '_this' => &$_this
  );

  if ($cx['flags']['spvar']) {
   $options['data'] = &$cx['sp_vars'];
  }

  return lcr62387a1957f7bexch($cx, $ch, $vars, $options);
 }

 function lcr62387a1957f7bencq($cx, $var)
 {
  // Use full namespace classname for more specific code export/match in Exporter.php replaceSafeString.
  if ($var instanceof MySafeString) {
   return (string)$var;
  }

  return str_replace(array('=', '`', '''), array('=', '`', '''), htmlspecialchars(lcr62387a1957f7braw($cx, $var), ENT_QUOTES, 'UTF-8'));
 }

 function lcr62387a1957f7bexch($cx, $ch, $vars, &$options)
 {
  $args = $vars[0];
  $args[] = &$options;
  $r = true;

  try {
   $r = call_user_func_array($cx['helpers'][$ch], $args);
  } catch (\Throwable $E) {
   lcr62387a1957f7berr($cx, "Runtime: call custom helper '$ch' error: " . $E->getMessage());
  }

  return $r;
 }

 function lcr62387a1957f7braw($cx, $v, $ex = 0)
 {
  if ($ex) {
   return $v;
  }

  if ($v === true) {
   if ($cx['flags']['jstrue']) {
    return 'true';
   }
  }

  if (($v === false)) {
   if ($cx['flags']['jstrue']) {
    return 'false';
   }
  }

  if (is_array($v)) {
   if ($cx['flags']['jsobj']) {
    if (count(array_diff_key($v, array_keys(array_keys($v)))) > 0) {
     return '[object Object]';
    } else {
     $ret = array();
     foreach ($v as $k => $vv) {
      $ret[] = lcr62387a1957f7braw($cx, $vv);
     }
     return join(',', $ret);
    }
   } else {
    return 'Array';
   }
  }

  return "$v";
 }

 function lcr62387a1957f7berr($cx, $err)
 {
  if ($cx['flags']['debug'] & $cx['constants']['DEBUG_ERROR_LOG']) {
   error_log($err);
   return;
  }
  if ($cx['flags']['debug'] & $cx['constants']['DEBUG_ERROR_EXCEPTION']) {
   throw new \Exception($err);
  }
 }

if (!class_exists("MySafeString")) {
class MySafeString {
 public static $jsContext = array (
  'flags' => 
  array (
    'jstrue' => 1,
    'jsobj' => 1,
  ),
);
    public function __construct($str, $escape = false)
    {
        $this->string = $escape ? (($escape === 'encq') ? static::encq(static::$jsContext, $str) : static::enc(static::$jsContext, $str)) : $str;
    }
    public function __toString()
    {
        return $this->string;
    }
    public static function stripExtendedComments($template)
    {
        return preg_replace(static::EXTENDED_COMMENT_SEARCH, '{{! }}', $template);
    }
    public static function escapeTemplate($template)
    {
        return addcslashes(addcslashes($template, '\\'), "'");
    }
    public static function raw($cx, $v, $ex = 0)
    {
        if ($ex) {
            return $v;
        }

        if ($v === true) {
            if ($cx['flags']['jstrue']) {
                return 'true';
            }
        }

        if (($v === false)) {
            if ($cx['flags']['jstrue']) {
                return 'false';
            }
        }

        if (is_array($v)) {
            if ($cx['flags']['jsobj']) {
                if (count(array_diff_key($v, array_keys(array_keys($v)))) > 0) {
                    return '[object Object]';
                } else {
                    $ret = array();
                    foreach ($v as $k => $vv) {
                        $ret[] = static::raw($cx, $vv);
                    }
                    return join(',', $ret);
                }
            } else {
                return 'Array';
            }
        }

        return "$v";
    }
    public static function enc($cx, $var)
    {
        return htmlspecialchars(static::raw($cx, $var), ENT_QUOTES, 'UTF-8');
    }
    public static function encq($cx, $var)
    {
        return str_replace(array('=', '`', '''), array('=', '`', '''), htmlspecialchars(static::raw($cx, $var), ENT_QUOTES, 'UTF-8'));
    }
}
}
return function ($in = null, $options = null) {
    $helpers = array(            'foo' => function() {
            return new MySafeString('You&Me!');
        },
            'bar' => function() {
            return new MySafeString('He&She!');
        },
);
    $partials = array();
    $cx = array(
        'flags' => array(
            'jstrue' => false,
            'jsobj' => false,
            'jslen' => false,
            'spvar' => true,
            'prop' => false,
            'method' => false,
            'lambda' => false,
            'mustlok' => false,
            'mustlam' => false,
            'mustsec' => false,
            'echo' => false,
            'partnc' => false,
            'knohlp' => false,
            'debug' => isset($options['debug']) ? $options['debug'] : 1,
        ),
        'constants' =>  array(
            'DEBUG_ERROR_LOG' => 1,
            'DEBUG_ERROR_EXCEPTION' => 2,
            'DEBUG_TAGS' => 4,
            'DEBUG_TAGS_ANSI' => 12,
            'DEBUG_TAGS_HTML' => 20,
        ),
        'helpers' => isset($options['helpers']) ? array_merge($helpers, $options['helpers']) : $helpers,
        'partials' => isset($options['partials']) ? array_merge($partials, $options['partials']) : $partials,
        'scopes' => array(),
        'sp_vars' => isset($options['data']) ? array_merge(array('root' => $in), $options['data']) : array('root' => $in),
        'blparam' => array(),
        'partialid' => 0,
        'runtime' => '\LightnCandy\Runtime',
    );
    
    $inary=is_array($in);
    return ''.lcr62387a1957f7bencq($cx, lcr62387a1957f7bhbch($cx, 'foo', array(array(),array()), 'encq', $in)).', '.lcr62387a1957f7bencq($cx, lcr62387a1957f7bhbch($cx, 'bar', array(array(),array()), 'encq', $in)).'';
};

===========================
The Output:
You&Me!, He&She!

See Also...