public function render($context) { try { $expire_time = $this->expire_time_var->resolve($context); } catch (VariableDoesNotExist $e) { throw new TemplateSyntaxError('"cache" tag got an unknown variable: ' . $this->expire_time_var->var); } if (!is_numeric($expire_time)) { throw new TemplateSyntaxError('"cache" tag got a non-integer timeout value: ' . print_r($expire_time, true)); } $expire_time = (int) $expire_time; // Build a unicode key for this fragment and all vary-on's. $vs_ = array(); foreach ($this->vary_on as $var) { $v_ = new Variable($var); $vs_[] = urlencode($v_->resolve($context)); } $args = join(':', $vs_); unset($vs_); $cache_key = 'template.cache.' . $this->fragment_name . '.' . md5($args); $manager = Dja::getCacheManager(); $value = $manager->get($cache_key); if ($value === null) { $value = $this->nodelist->render($context); $manager->set($cache_key, $value, $expire_time); } return $value; }
public function renderFile($context, $sourceFile, $data, $return) { $result = Dja::render($sourceFile, $data); if ($return) { return $result; } echo $result; return null; }
private function getAppTemplateDirs() { if (self::$app_template_dirs === null) { foreach (Dja::getSetting('INSTALLED_APPS') as $app) { $template_dir = $app . '/templates'; // TODO Probably needs directory exists check. self::$app_template_dirs[] = $template_dir; } } return self::$app_template_dirs; }
public function getTemplateSources($template_name, $template_dirs = null) { if (!$template_dirs) { $template_dirs = Dja::getSetting('TEMPLATE_DIRS'); } $dirs_ = array(); foreach ($template_dirs as $template_dir) { try { $dirs_[] = safe_join($template_dir, $template_name); } catch (ValueError $e) { /* * The joined path was located outside of this particular * template_dir (it might be inside another one, so this isn't fatal). */ continue; } } return $dirs_; }
public function testCorrectExceptionIndex() { $debug_old_ = Dja::getSetting('TEMPLATE_DEBUG'); Dja::setSetting('TEMPLATE_DEBUG', True); $tests = array(array('{% load bad_tag %}{% for i in range %}{% badsimpletag %}{% endfor %}', array(38, 56)), array('{% load bad_tag %}{% for i in range %}{% for j in range %}{% badsimpletag %}{% endfor %}{% endfor %}', array(58, 76)), array('{% load bad_tag %}{% for i in range %}{% badsimpletag %}{% for j in range %}Hello{% endfor %}{% endfor %}', array(38, 56)), array('{% load bad_tag %}{% for i in range %}{% for j in five %}{% badsimpletag %}{% endfor %}{% endfor %}', array(38, 57)), array('{% load bad_tag %}{% for j in five %}{% badsimpletag %}{% endfor %}', array(18, 37))); // {% for j in five %} // {% badsimpletag %} $context = new Context(array('range' => array(1, 2, 3, 4, 5), 'five' => 5)); foreach ($tests as $item) { list($source, $expected_error_source_index) = $item; $template = DjaLoader::getTemplateFromString($source); try { $template->render($context); } catch (RuntimeError $e) { // TODO except (RuntimeError, TypeError), e: $error_source_index = $e->django_template_source[1]; $this->assertEquals($expected_error_source_index, $error_source_index); } } Dja::setSetting('TEMPLATE_DEBUG', $debug_old_); }
public function render($context) { try { $template_name = $this->template_name->resolve($context); $template = DjaLoader::getTemplate($template_name); return $this->renderTemplate($template, $context); } catch (Exception $e) { if (Dja::getSetting('TEMPLATE_DEBUG')) { throw $e; } return ''; } }
/** * @param Context $context * @param bool $ignore_failures * * @return mixed */ public function resolve($context, $ignore_failures = False) { if ($this->var instanceof Variable) { try { $obj = $this->var->resolve($context); } catch (VariableDoesNotExist $e) { if ($ignore_failures) { $obj = null; } else { if (Dja::getSetting('TEMPLATE_STRING_IF_INVALID')) { if (DjaBase::$invalid_var_format_string === null) { DjaBase::$invalid_var_format_string = strpos(Dja::getSetting('TEMPLATE_STRING_IF_INVALID'), '%s') !== False; } if (DjaBase::$invalid_var_format_string) { return sprintf(Dja::getSetting('TEMPLATE_STRING_IF_INVALID'), $this->var); } return Dja::getSetting('TEMPLATE_STRING_IF_INVALID'); } else { $obj = Dja::getSetting('TEMPLATE_STRING_IF_INVALID'); } } } } else { $obj = $this->var; } foreach ($this->filters as $filter) { list($func, $args, $n_) = $filter; $arg_vals = array(); foreach ($args as $arg_data) { /** @var $arg Variable|string */ list($lookup, $arg) = $arg_data; if (!$lookup) { $arg_vals[] = mark_safe($arg); } else { $arg_vals[] = $arg->resolve($context); } } if (py_getattr($func, 'expects_localtime', False)) { $obj = localtime($obj, $context->use_tz); } $func_ = $func->closure; if (py_getattr($func, 'needs_autoescape', False)) { $new_obj = call_user_func_array($func_, array_merge(array($obj, $context->autoescape), $arg_vals)); } else { $new_obj = call_user_func_array($func_, array_merge(array($obj), $arg_vals)); } if (py_getattr($func, 'is_safe', False) && $obj instanceof SafeData) { $obj = mark_safe($new_obj); } else { if ($obj instanceof EscapeData) { $obj = mark_for_escaping($new_obj); } else { $obj = $new_obj; } } } return $obj; }
private static function getTracebackData($template_file, $e) { $loader_debug_info = array(); $template_does_not_exist = False; $template_info = null; if ($e instanceof TemplateDoesNotExist) { foreach (DjaLoader::$template_source_loaders as $loader) { $template_does_not_exist = True; $template_list = array(); $tpl_sources = $loader->getTemplateSources($template_file); foreach ($tpl_sources as $t) { $template_list[] = array('name' => $t, 'exists' => file_exists($t)); } $loader_debug_info[] = array('loader' => get_class($loader), 'templates' => $template_list); } } if (isset($e->django_template_source)) { list($origin, $pos) = $e->django_template_source; list($start, $end) = $pos; $template_source = $origin->reload(); $context_lines = 10; $line = 0; $upto = 0; $source_lines = array(); $before = $during = $after = ''; $linebreak_iter = function ($source, &$last_pos) { if ($last_pos === null) { $last_pos = 0; return $last_pos; } elseif ($last_pos === false) { return -1; } $p = strpos($source, "\n", $last_pos); if ($p === false) { $last_pos = strlen($source) + 1; // TODO check unicode handling } else { $last_pos = $p + 1; } return $p; }; $num = 0; $next = null; while (($r_ = $linebreak_iter($template_source, $next)) != -1) { if ($start >= $upto && $end <= $next) { $line = $num; $before = escape(py_slice($template_source, $upto, $start)); $during = escape(py_slice($template_source, $start, $end)); $after = escape(py_slice($template_source, $end, $next)); } $source_lines[] = array($num, escape(py_slice($template_source, $upto, $next))); $upto = $next; if ($r_ === false) { $next = false; } $num++; } $total = count($source_lines); $top = max(1, $line - $context_lines); $bottom = min($total, $line + 1 + $context_lines); $template_info = array('message' => $e->getMessage(), 'source_lines' => py_slice($source_lines, $top, $bottom), 'before' => $before, 'during' => $during, 'after' => $after, 'top' => $top, 'bottom' => $bottom, 'total' => $total, 'line' => $line, 'name' => $origin->name); } return array('exception_type' => get_class($e), 'exception_value' => $e->getMessage(), 'dja_version_info' => Dja::getVersion(), 'template_info' => $template_info, 'template_does_not_exist' => $template_does_not_exist, 'loader_debug_info' => $loader_debug_info); }
<?php require_once '../dja/dja.php'; define('DJA_TESTS_DIR', dirname(__FILE__)); // Add current directory to apps, so that tests can find `templates` and `templatetags`. Dja::setSetting('INSTALLED_APPS', array(DJA_TESTS_DIR)); Dja::setSetting('TEMPLATE_DIRS', array(DJA_TESTS_DIR, 'templates'));
public static function add_truncation_text($text, $truncate = null) { if ($truncate === null) { $truncate = Dja::getI18n()->pgettext('String to return when truncating text', '%(truncated_text)s...'); } if (strpos($truncate, '%(truncated_text)s') !== False) { return str_replace('%(truncated_text)s', $text, $truncate); } /* * The truncation text didn't contain the %(truncated_text)s string * replacement argument so just append it to the text. */ if (py_str_ends_with($text, $truncate)) { // But don't append the truncation text if the current text already ends in this. return $text; } return $text . $truncate; }
/** * Simple rendering method. * * Handles Dja exceptions and renders pretty error * page if TEMPLATE_DEBUG = True. * * @static * @param string $template * @param array $context * @param bool $use_cache Use compiled template object cache. * @return string * @throws DjaException */ public static function render($template, $context, $use_cache = True) { Dja::setSetting('TEMPLATE_CACHE', $use_cache); try { $result = DjaLoader::renderToString($template, $context); } catch (DjaException $e) { if (!Dja::getSetting('TEMPLATE_DEBUG')) { throw $e; } $result = DjaDebug::getTracebackHtml($template, $e); } return (string) $result; }
/** * @param Context $context * @return SafeString|string * @throws UrlNoReverseMatch */ public function render($context) { $args = array(); foreach ($this->args as $arg) { $args[] = $arg->resolve($context); } $kwargs = array(); foreach ($this->kwargs as $k => $v) { $kwargs[$k] = $v->resolve($context); // TODO check smart_str(k, 'ascii') } $view_name = $this->view_name; if (!$this->legacy_view_name) { $view_name = $view_name->resolve($context); } /* * Try to look up the URL twice: once given the view name, and again * relative to what we guess is the "main" app. If they both fail, * re-raise the NoReverseMatch unless we're using the * {% url ... as var %} construct in which cause return nothing. */ $url = ''; try { $url_manager = Dja::getUrlDispatcher(); $url = $url_manager->reverse($view_name, null, $args, $kwargs, null, $context->current_app); } catch (UrlNoReverseMatch $e) { if ($this->asvar === null) { throw $e; } } if ($this->asvar) { $context[$this->asvar] = $url; return ''; } else { return $url; } }
public function testTemplates() { $template_tests = self::getTemplateTests(); $filter_tests = get_filter_tests(); /* * Quickly check that we aren't accidentally using a name in both * template and filter tests. */ $overlapping_names = array(); $tkeys_ = array_keys($template_tests); foreach ($filter_tests as $name => $v) { if (array_key_exists($name, $tkeys_)) { $overlapping_names[] = $name; } } if (!empty($overlapping_names)) { throw new Exception('Duplicate test name(s): ' . join(', ', $overlapping_names)); } $template_tests = array_merge($template_tests, $filter_tests); $tpls_ = array(); foreach ($template_tests as $name => $t) { $tpls_[$name] = $t[0]; } $cache_loader = setup_test_template_loader($tpls_, True); $failures = array(); $tests = $template_tests; ksort($tests); // Turn TEMPLATE_DEBUG off, because tests assume that. $old_debug = Dja::getSetting('TEMPLATE_DEBUG'); Dja::setSetting('TEMPLATE_DEBUG', True); // Set TEMPLATE_STRING_IF_INVALID to a known string. $old_invalid = Dja::getSetting('TEMPLATE_STRING_IF_INVALID'); $expected_invalid_str = 'INVALID'; // Set ALLOWED_INCLUDE_ROOTS so that ssi works. $old_allowed_include_roots = Dja::getSetting('ALLOWED_INCLUDE_ROOTS'); Dja::setSetting('ALLOWED_INCLUDE_ROOTS', array(realpath(dirname(__FILE__)))); // Warm the URL reversing cache. This ensures we don't pay the cost // warming the cache during one of the tests. Dja::getUrlDispatcher()->reverse('regressiontests.templates.views.client_action', null, array(), array('id' => 0, 'action' => "update")); foreach ($tests as $name => $vals) { if (is_array($vals[2])) { $normal_string_result = $vals[2][0]; $invalid_string_result = $vals[2][1]; if (is_array($invalid_string_result)) { $expected_invalid_str = 'INVALID %s'; $invalid_string_result = sprintf($invalid_string_result[0], $invalid_string_result[1]); DjaBase::$invalid_var_format_string = True; } if (isset($vals[2][2])) { $template_debug_result = $vals[2][2]; } else { $template_debug_result = $normal_string_result; } } else { $normal_string_result = $vals[2]; $invalid_string_result = $vals[2]; $template_debug_result = $vals[2]; } if (isset($vals[1]['LANGUAGE_CODE'])) { Dja::getI18n()->activate($vals[1]['LANGUAGE_CODE']); } else { Dja::getI18n()->activate('en-us'); } foreach (array(array('', False, $normal_string_result), array($expected_invalid_str, False, $invalid_string_result), array('', True, $template_debug_result)) as $itm) { list($invalid_str, $template_debug, $result) = $itm; Dja::setSetting('TEMPLATE_STRING_IF_INVALID', $invalid_str); Dja::setSetting('TEMPLATE_DEBUG', $template_debug); foreach (array(False, True) as $is_cached) { $fail_str_ = 'Template test (Cached=' . ($is_cached ? 'TRUE' : 'FALSE') . ', TEMPLATE_STRING_IF_INVALID=\'' . $invalid_str . '\', TEMPLATE_DEBUG=' . ($template_debug ? 'TRUE' : 'FALSE') . '): ' . $name . ' -- FAILED. '; try { try { $test_template = DjaLoader::getTemplate($name); } catch (ShouldNotExecuteException $e) { $failures[] = $fail_str_ . 'Template loading invoked method that shouldn\'t have been invoked.'; } try { $output = self::render($test_template, $vals); } catch (ShouldNotExecuteException $e) { $failures[] = $fail_str_ . 'Template loading invoked method that shouldn\'t have been invoked.'; } } catch (ContextStackException $e) { $failures[] = $fail_str_ . 'Context stack was left imbalanced'; continue; } catch (Exception $e) { $exc_type = get_class($e); $exc_value = $e->getMessage(); $exc_tb = $e->getTraceAsString(); if ($exc_type != $result) { $tb = $exc_tb; $failures[] = $fail_str_ . 'Got ' . $exc_type . ', exception: ' . $exc_value . "\n" . $tb; } continue; } if ($output != $result) { $failures[] = $fail_str_ . 'Expected [' . $result . '], got [' . $output . ']'; } } $cache_loader->reset(); } if (isset($vals[1]['LANGUAGE_CODE'])) { Dja::getI18n()->deactivate(); } if (DjaBase::$invalid_var_format_string) { $expected_invalid_str = 'INVALID'; DjaBase::$invalid_var_format_string = False; } } restore_template_loaders(); Dja::getI18n()->deactivate(); Dja::setSetting('TEMPLATE_STRING_IF_INVALID', $old_invalid); Dja::setSetting('TEMPLATE_DEBUG', $old_debug); Dja::setSetting('ALLOWED_INCLUDE_ROOTS', $old_allowed_include_roots); $sep_ = str_pad('', 70, '-'); $this->assertEquals(array(), $failures, "Tests failed:\n{$sep_}\n" . join("\n{$sep_}\n", $failures)); }
*/ $lib->filter('default', function ($value, $arg) { return $value ? $value : $arg; }, array('is_safe' => False)); $lib->filter('default_if_none', function ($value, $arg) { if ($value === null) { return $arg; } return $value; }, array('is_safe' => False)); $lib->filter('divisibleby', function ($value, $arg) { return (int) $value % (int) $arg->get() == 0; }, array('is_safe' => False)); $lib->filter('yesno', function ($value, $arg = null) { if ($arg === null) { $arg = Dja::getI18n()->ugettext('yes,no,maybe'); } $bits = explode(',', $arg); if (count($bits) < 2) { return $value; // Invalid arg. } @(list($yes, $no, $maybe) = $bits); if (!$maybe) { // Unpack list of wrong size (no "maybe" value provided). $maybe = $bits[1]; } if ($value === null) { return $maybe; } if ($value) {
/** * Returns a compiled Template object for the given template name, * handling template inheritance recursively. * * @param $template_name * * @return Template */ public static function getTemplate($template_name) { $self = get_called_class(); $get_template = function () use($template_name, $self) { list($template, $origin) = $self::findTemplate($template_name); if (!py_hasattr($template, 'render')) { // template needs to be compiled $template = $self::getTemplateFromString($template, $origin, $template_name); } return $template; }; $use_cache = Dja::getSetting('TEMPLATE_CACHE'); if (!$use_cache) { return $get_template(); } $cacher = Dja::getCacheManager(); if (!($template = $cacher->get($template_name))) { $template = $get_template(); $cacher->set($template_name, $template); } return $template; }