Библиотека для cis, online, cms1

This commit is contained in:
Фёдор Подлеснов 2016-06-29 18:51:32 +03:00
commit 3c2e614d87
269 changed files with 39854 additions and 0 deletions

View file

@ -0,0 +1,107 @@
<?php
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// i18n:attributes
//
// This attribute will allow us to translate attributes of HTML tags, such
// as the alt attribute in the img tag. The i18n:attributes attribute
// specifies a list of attributes to be translated with optional message
// IDs? for each; if multiple attribute names are given, they must be
// separated by semi-colons. Message IDs? used in this context must not
// include whitespace.
//
// Note that the value of the particular attributes come either from the
// HTML attribute value itself or from the data inserted by tal:attributes.
//
// If an attibute is to be both computed using tal:attributes and translated,
// the translation service is passed the result of the TALES expression for
// that attribute.
//
// An example:
//
// <img src="http://foo.com/logo" alt="Visit us"
// tal:attributes="alt here/greeting"
// i18n:attributes="alt"
// />
//
//
// In this example, let tal:attributes set the value of the alt attribute to
// the text "Stop by for a visit!". This text will be passed to the
// translation service, which uses the result of language negotiation to
// translate "Stop by for a visit!" into the requested language. The example
// text in the template, "Visit us", will simply be discarded.
//
// Another example, with explicit message IDs:
//
// <img src="../icons/uparrow.png" alt="Up"
// i18n:attributes="src up-arrow-icon; alt up-arrow-alttext"
// >
//
// Here, the message ID up-arrow-icon will be used to generate the link to
// an icon image file, and the message ID up-arrow-alttext will be used for
// the "alt" text.
//
/**
* @package phptal.php.attribute
*/
class PHPTAL_Php_Attribute_I18N_Attributes extends PHPTAL_Php_Attribute
{
public function start()
{
// split attributes to translate
$expressions = $this->tag->generator->splitExpression($this->expression);
// foreach attribute
foreach ($expressions as $exp){
list($attribute, $key) = $this->parseSetExpression($exp);
// if the translation key is specified
if ($key != null){
// we use it and replace the tag attribute with the result of
// the translation
$key = str_replace('\'', '\\\'', $key);
$this->tag->attributes[$attribute] = $this->_getTranslationCode("'$key'");
}
else if ($this->tag->isOverwrittenAttribute($attribute)){
$varn = $this->tag->getOverwrittenAttributeVarName($attribute);
$this->tag->attributes[$attribute] = $this->_getTranslationCode($varn);
}
// else if the attribute has a default value
else if ($this->tag->hasAttribute($attribute)){
// we use this default value as the translation key
$key = $this->tag->getAttribute($attribute);
$key = str_replace('\'', '\\\'', $key);
$this->tag->attributes[$attribute] = $this->_getTranslationCode("'$key'");
}
else {
// unable to translate the attribute
throw new PHPTAL_Exception("Unable to translate attribute $attribute");
}
}
}
public function end()
{
}
private function _getTranslationCode($key)
{
$code = '<?php ';
if (preg_match_all('/\$\{(.*?)\}/', $key, $m)){
array_shift($m);
$m = array_shift($m);
foreach ($m as $name){
$code .= "\n".'$_translator->setVar(\''.$name.'\','.phptal_tale($name).');'; // allow more complex TAL expressions
}
$code .= "\n";
}
// notice the false boolean which indicate that the html is escaped
// elsewhere looks like an hack doesn't it ? :)
$result = $this->tag->generator->escapeCode(sprintf('$_translator->translate(%s, false)', $key));
$code .= 'echo '.$result.'?>';
return $code;
}
}
?>

View file

@ -0,0 +1,24 @@
<?php
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// i18n:data
//
// Since TAL always returns strings, we need a way in ZPT to translate
// objects, the most obvious case being DateTime objects. The data attribute
// will allow us to specify such an object, and i18n:translate will provide
// us with a legal format string for that object. If data is used,
// i18n:translate must be used to give an explicit message ID, rather than
// relying on a message ID computed from the content.
//
/**
* @package phptal.php.attribute.i18n
*/
class PHPTAL_Php_Attribute_I18N_Data extends PHPTAL_Php_Attribute
{
public function start(){}
public function end(){}
}
?>

View file

@ -0,0 +1,41 @@
<?php
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// i18n:domain
//
// The i18n:domain attribute is used to specify the domain to be used to get
// the translation. If not specified, the translation services will use a
// default domain. The value of the attribute is used directly; it is not
// a TALES expression.
//
/**
* @package phptal.php.attribute.i18n
*/
class PHPTAL_Php_Attribute_I18N_Domain extends PHPTAL_Php_Attribute
{
public function start()
{
// ensure a domain stack exists or create it
$this->tag->generator->doIf('!isset($__i18n_domains)');
$this->tag->generator->pushCode('$__i18n_domains = array()');
$this->tag->generator->doEnd();
//\''.str_replace(array('\\',"'"),array('\\\\',"\\'"),$expression).'\'
$expression = $this->tag->generator->interpolateTalesVarsInString($this->expression);
// push current domain and use new domain
$code = '$__i18n_domains[] = $_translator->useDomain('.$expression.')';
$this->tag->generator->pushCode($code);
}
public function end()
{
// restore domain
$code = '$_translator->useDomain(array_pop($__i18n_domains))';
$this->tag->generator->pushCode($code);
}
}
?>

View file

@ -0,0 +1,40 @@
<?php
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// i18n:name
//
// Name the content of the current element for use in interpolation within
// translated content. This allows a replaceable component in content to be
// re-ordered by translation. For example:
//
// <span i18n:translate=''>
// <span tal:replace='here/name' i18n:name='name' /> was born in
// <span tal:replace='here/country_of_birth' i18n:name='country' />.
// </span>
//
// would cause this text to be passed to the translation service:
//
// "${name} was born in ${country}."
//
/**
* @package phptal.php.attribute.i18n
*/
class PHPTAL_Php_Attribute_I18N_Name extends PHPTAL_Php_Attribute
{
public function start()
{
$this->tag->generator->pushCode('ob_start()');
}
public function end()
{
$code = '$_translator->setVar(\'%s\', ob_get_contents())';
$code = sprintf($code, $this->expression);
$this->tag->generator->pushCode($code);
$this->tag->generator->pushCode('ob_end_clean()');
}
}
?>

View file

@ -0,0 +1,38 @@
<?php
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// i18n:source
//
// The i18n:source attribute specifies the language of the text to be
// translated. The default is "nothing", which means we don't provide
// this information to the translation services.
//
/**
* @package phptal.php.attribute.i18n
*/
class PHPTAL_Php_Attribute_I18N_Source extends PHPTAL_Php_Attribute
{
public function start()
{
// ensure that a sources stack exists or create it
$this->tag->generator->doIf('!isset($__i18n_sources)');
$this->tag->generator->pushCode('$__i18n_sources = array()');
$this->tag->generator->end();
// push current source and use new one
$code = '$__i18n_sources[] = $_translator->setSource(\'%s\')';
$code = sprintf($code, $this->expression);
$this->tag->generator->pushCode($code);
}
public function end()
{
// restore source
$code = '$_translator->setSource(array_pop($__i18n_sources))';
$this->tag->generator->pushCode($code);
}
}
?>

View file

@ -0,0 +1,32 @@
<?php
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// i18n:target
//
// The i18n:target attribute specifies the language of the translation we
// want to get. If the value is "default", the language negotiation services
// will be used to choose the destination language. If the value is
// "nothing", no translation will be performed; this can be used to suppress
// translation within a larger translated unit. Any other value must be a
// language code.
//
// The attribute value is a TALES expression; the result of evaluating the
// expression is the language code or one of the reserved values.
//
// Note that i18n:target is primarily used for hints to text extraction
// tools and translation teams. If you had some text that should only be
// translated to e.g. German, then it probably shouldn't be wrapped in an
// i18n:translate span.
//
/**
* @package phptal.php.attribute.i18n
*/
class PHPTAL_Php_Attribute_I18N_Target extends PHPTAL_Php_Attribute
{
public function start(){}
public function end(){}
}
?>

View file

@ -0,0 +1,97 @@
<?php
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// ZPTInternationalizationSupport
//
// i18n:translate
//
// This attribute is used to mark units of text for translation. If this
// attribute is specified with an empty string as the value, the message ID
// is computed from the content of the element bearing this attribute.
// Otherwise, the value of the element gives the message ID.
//
/**
* @package phptal.php.attribute.i18n
*/
class PHPTAL_Php_Attribute_I18N_Translate extends PHPTAL_Php_Attribute
{
public function start()
{
$escape = true;
if (preg_match('/^(text|structure)(?:\s+(.*)|\s*$)/',$this->expression,$m))
{
if ($m[1]=='structure') $escape=false;
$this->expression = isset($m[2])?$m[2]:'';
}
// if no expression is given, the content of the node is used as
// a translation key
if (strlen(trim($this->expression)) == 0){
$key = $this->_getTranslationKey($this->tag, !$escape);
$key = trim(preg_replace('/\s+/sm'.($this->tag->generator->getEncoding()=='UTF-8'?'u':''), ' ', $key));
$code = '\'' . str_replace('\'', '\\\'', $key) . '\'';
}
else {
$code = $this->tag->generator->evaluateExpression($this->expression);
}
$this->_prepareNames($this->tag);
$php = sprintf('echo $_translator->translate(%s,%s);', $code, $escape ? 'true':'false');
$this->tag->generator->pushCode($php);
}
public function end()
{
}
private function _getTranslationKey($tag, $preserve_tags)
{
$result = '';
foreach ($tag->children as $child){
if ($child instanceOf PHPTAL_Php_Text){
$result .= $child->node->getValue();
}
else if ($child instanceOf PHPTAL_Php_Element){
if ($child->hasAttribute('i18n:name')){
$value = $child->getAttribute('i18n:name');
$result .= '${' . $value . '}';
}
else {
if ($preserve_tags)
{
$result .= '<'.$child->name;
foreach($child->attributes as $k => $v)
{
$result .= ' '.$k.'="'.$v.'"';
}
$result .= '>'.$this->_getTranslationKey($child, $preserve_tags).'</'.$child->name.'>';
}
else
{
$result .= $this->_getTranslationKey($child, $preserve_tags);
}
}
}
}
return $result;
}
private function _prepareNames($tag)
{
foreach ($tag->children as $child){
if ($child instanceOf PHPTAL_Php_Element){
if ($child->hasAttribute('i18n:name')){
$child->generate();
}
else {
$this->_prepareNames($child);
}
}
}
}
}
?>

View file

@ -0,0 +1,71 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Laurent Bedubourg <lbedubourg@motion-twin.com>
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// METAL Specification 1.0
//
// argument ::= Name
//
// Example:
//
// <p metal:define-macro="copyright">
// Copyright 2001, <em>Foobar</em> Inc.
// </p>
//
// PHPTAL:
//
// <?php function XXX_macro_copyright( $tpl ) { ? >
// <p>
// Copyright 2001, <em>Foobar</em> Inc.
// </p>
// <?php } ? >
//
/**
* @package phptal.php.attribute.metal
* @author Laurent Bedubourg <lbedubourg@motion-twin.com>
*/
class PHPTAL_Php_Attribute_METAL_DefineMacro extends PHPTAL_Php_Attribute
{
public function start()
{
$macroname = strtr(trim($this->expression),'-','_');
if (!preg_match('/^[a-z0-9_]+$/i', $macroname)){
throw new PHPTAL_Exception('Bad macro name "'.$macroname.'"', $this->tag->getSourceFile(), $this->tag->getSourceLine());
}
$this->tag->generator->doFunction($macroname, '$tpl, $ctx');
$this->tag->generator->doXmlDeclaration();
$this->tag->generator->doDoctype();
$this->tag->generator->doSetVar('$tpl', 'clone $tpl');
$this->tag->generator->doSetVar('$ctx', '$tpl->getContext()');
$this->tag->generator->doSetVar('$glb', '$tpl->getGlobalContext()');
$this->tag->generator->doSetVar('$_translator', '$tpl->getTranslator()');
}
public function end()
{
$this->tag->generator->doEnd();
}
}

View file

@ -0,0 +1,75 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Laurent Bedubourg <lbedubourg@motion-twin.com>
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// METAL Specification 1.0
//
// argument ::= Name
//
// Example:
//
// <table metal:define-macro="sidebar">
// <tr><th>Links</th></tr>
// <tr><td metal:define-slot="links">
// <a href="/">A Link</a>
// </td></tr>
// </table>
//
// PHPTAL: (access to slots may be renamed)
//
// <?php function XXXX_macro_sidebar( $tpl ) { ? >
// <table>
// <tr><th>Links</th></tr>
// <tr>
// <?php if (isset($tpl->slots->links)): ? >
// <?php echo $tpl->slots->links ? >
// <?php else: ? >
// <td>
// <a href="/">A Link</a>
// </td></tr>
// </table>
// <?php } ? >
//
/**
* @package phptal.php.attribute.metal
* @author Laurent Bedubourg <lbedubourg@motion-twin.com>
*/
class PHPTAL_Php_Attribute_METAL_DefineSlot extends PHPTAL_Php_Attribute
{
public function start()
{
$cond = sprintf('$ctx->hasSlot("%s")', $this->expression);
$this->tag->generator->doIf($cond);
$code = sprintf('<?php echo $ctx->getSlot("%s") ?>', $this->expression);
$this->tag->generator->pushHtml($code);
$this->tag->generator->doElse();
}
public function end()
{
$this->tag->generator->doEnd();
}
}
?>

View file

@ -0,0 +1,75 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Laurent Bedubourg <lbedubourg@motion-twin.com>
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// METAL Specification 1.0
//
// argument ::= Name
//
// Example:
//
// <table metal:use-macro="here/doc1/macros/sidebar">
// <tr><th>Links</th></tr>
// <tr><td metal:fill-slot="links">
// <a href="http://www.goodplace.com">Good Place</a><br>
// <a href="http://www.badplace.com">Bad Place</a><br>
// <a href="http://www.otherplace.com">Other Place</a>
// </td></tr>
// </table>
//
// PHPTAL:
//
// 1. evaluate slots
//
// <?php ob_start(); ? >
// <td>
// <a href="http://www.goodplace.com">Good Place</a><br>
// <a href="http://www.badplace.com">Bad Place</a><br>
// <a href="http://www.otherplace.com">Other Place</a>
// </td>
// <?php $tpl->slots->links = ob_get_contents(); ob_end_clean(); ? >
//
// 2. call the macro (here not supported)
//
// <?php echo phptal_macro($tpl, 'master_page.html/macros/sidebar'); ? >
//
/**
* @package phptal.php.attribute.metal
* @author Laurent Bedubourg <lbedubourg@motion-twin.com>
*/
class PHPTAL_Php_Attribute_METAL_FillSlot extends PHPTAL_Php_Attribute
{
public function start()
{
$this->tag->generator->pushCode('ob_start()');
}
public function end()
{
$code = '$ctx->fillSlot("'.$this->expression.'", ob_get_clean())';
$this->tag->generator->pushCode($code);
}
}

View file

@ -0,0 +1,131 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Laurent Bedubourg <lbedubourg@motion-twin.com>
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// METAL Specification 1.0
//
// argument ::= expression
//
// Example:
//
// <hr />
// <p metal:use-macro="here/master_page/macros/copyright">
// <hr />
//
// PHPTAL: (here not supported)
//
// <?php echo phptal_macro( $tpl, 'master_page.html/macros/copyright'); ? >
//
/**
* @package phptal.php.attribute.metal
* @author Laurent Bedubourg <lbedubourg@motion-twin.com>
*/
class PHPTAL_Php_Attribute_METAL_UseMacro extends PHPTAL_Php_Attribute
{
static $ALLOWED_ATTRIBUTES = array(
'metal:fill-slot',
'metal:define-macro',
'tal:define',
);
public function start()
{
$this->pushSlots();
foreach ($this->tag->children as $child){
$this->generateFillSlots($child);
}
$macroname = strtr($this->expression,'-','_');
// local macro (no filename specified) and non dynamic macro name
if (preg_match('/^[a-z0-9_]+$/i', $macroname)) {
$code = sprintf(
'%s%s($tpl, $ctx)',
$this->tag->generator->getFunctionPrefix(),
$macroname
);
$this->tag->generator->pushCode($code);
}
// external macro or ${macroname}, use PHPTAL at runtime to resolve it
else {
$code = $this->tag->generator->interpolateTalesVarsInString($this->expression);
$code = sprintf('<?php $tpl->executeMacro(%s); ?>', $code);
$this->tag->generator->pushHtml($code);
}
$this->popSlots();
}
public function end()
{
}
private function pushSlots()
{
// reset template slots on each macro call ?
//
// NOTE: defining a macro and using another macro on the same tag
// means inheriting from the used macro, thus slots are shared, it
// is a little tricky to understand but very natural to use.
//
// For example, we may have a main design.html containing our main
// website presentation with some slots (menu, content, etc...) then
// we may define a member.html macro which use the design.html macro
// for the general layout, fill the menu slot and let caller templates
// fill the parent content slot without interfering.
if (!$this->tag->hasAttribute('metal:define-macro')){
$this->tag->generator->pushCode('$ctx->pushSlots()');
}
}
private function popSlots()
{
// restore slots if not inherited macro
if (!$this->tag->hasAttribute('metal:define-macro')){
$this->tag->generator->pushCode('$ctx->popSlots()');
}
}
private function generateFillSlots($tag)
{
if (false == ($tag instanceOf PHPTAL_Php_Tree))
return;
// if the tag contains one of the allowed attribute, we generate it
foreach (self::$ALLOWED_ATTRIBUTES as $attribute){
if ($tag->hasAttribute($attribute)){
$tag->generate();
return;
}
}
// recurse
foreach ($tag->children as $child){
$this->generateFillSlots($child);
}
}
}
?>

View file

@ -0,0 +1,92 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Kornel Lesiński <kornel@aardvarkmedia.co.uk>
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
/** phptal:cache (note that's not tal:cache) caches element's HTML for a given time. Time is a number with 'd', 'h', 'm' or 's' suffix.
There's optional parameter that defines how cache should be shared. By default cache is not sensitive to template's context at all
- it's shared between all pages that use that template.
You can add per url to have separate copy of given element for every URL.
You can add per expression to have different cache copy for every different value of an expression (which MUST evaluate to a string).
Expression cannot refer to variables defined using tal:define on the same element.
NB:
* phptal:cache blocks can be nested, but outmost block will cache other blocks regardless of their freshness.
* you cannot use metal:fill-slot inside elements with phptal:cache
Examples:
<div phptal:cache="3h">...</div> <!-- <div> to be evaluated at most once per 3 hours. -->
<ul phptal:cache="1d per object/id">...</ul> <!-- <ul> be cached for one day, separately for each object. -->
*/
class PHPTAL_Php_Attribute_PHPTAL_Cache extends PHPTAL_Php_Attribute
{
private $cache_tag;
public function start()
{
if (!preg_match('/^\s*([0-9]+\s*|[a-zA-Z][a-zA-Z0-9_]*\s+)([dhms])\s*(?:\;?\s*per\s+([^;]+)|)\s*$/',$this->expression, $matches))
throw new PHPTAL_Exception("Cache attribute syntax error: ".$this->expression);
$cache_len = $matches[1];
if (!is_numeric($cache_len)) $cache_len = '$ctx->'.$cache_len;
switch($matches[2])
{
case 'd': $cache_len .= '*24'; /* no break */
case 'h': $cache_len .= '*60'; /* no break */
case 'm': $cache_len .= '*60'; /* no break */
}
$this->cache_tag = '"'.addslashes( $this->tag->node->getName() . ':' . $this->tag->node->getSourceLine()).'"';
$cache_per_expression = isset($matches[3])?trim($matches[3]):NULL;
if ($cache_per_expression == 'url')
{
$this->cache_tag .= '.$_SERVER["REQUEST_URI"]';
}
else if ($cache_per_expression == 'nothing') { }
else if ($cache_per_expression)
{
$code = $this->tag->generator->evaluateExpression($cache_per_expression);
if (is_array($code)) { throw new PHPTAL_Exception("Chained expressions in per-cache directive are not supported"); }
$old_cache_tag = $this->cache_tag;
$this->cache_tag = '$ctx->cache_tag_';
$this->tag->generator->doSetVar($this->cache_tag, '('.$code.')."@".' . $old_cache_tag );
}
$cond = '!file_exists(__FILE__.md5('.$this->cache_tag.')) || time() - '.$cache_len.' >= @filemtime(__FILE__.md5('.$this->cache_tag.'))';
$this->tag->generator->doIf($cond);
$this->tag->generator->doEval('ob_start()');
}
public function end()
{
$this->tag->generator->doEval('file_put_contents(__FILE__.md5('.$this->cache_tag.'), ob_get_flush())');
$this->tag->generator->doElse();
$this->tag->generator->doEval('readfile(__FILE__.md5('.$this->cache_tag.'))');
$this->tag->generator->doEnd();
}
}

View file

@ -0,0 +1,44 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Laurent Bedubourg <lbedubourg@motion-twin.com>
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
/**
* @package phptal.php.attribute.phptal
* @author Laurent Bedubourg <lbedubourg@motion-twin.com>
*/
class PHPTAL_Php_Attribute_PHPTAL_DEBUG extends PHPTAL_Php_Attribute
{
public function start()
{
$this->_oldMode = $this->tag->generator->setDebug(true);
}
public function end()
{
$this->tag->generator->setDebug( $this->_oldMode );
}
private $_oldMode;
}
?>

View file

@ -0,0 +1,66 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Laurent Bedubourg <lbedubourg@motion-twin.com>
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
/**
* @package phptal.php.attribute.phptal
* @author Laurent Bedubourg <lbedubourg@motion-twin.com>
*/
class PHPTAL_Php_Attribute_PHPTAL_ID extends PHPTAL_Php_Attribute
{
private $id;
public function start()
{
$this->id = str_replace('"', '\\\"', $this->expression);
// retrieve trigger
$this->tag->generator->doSetVar(
'$trigger',
'$tpl->getTrigger("'.$this->id.'")'
);
// if trigger found and trigger tells to proceed, we execute
// the node content
$cond = '$trigger && '
. '$trigger->start("%s", $tpl) == PHPTAL_Trigger::PROCEED';
$cond = sprintf($cond, $this->id);
$this->tag->generator->doIf($cond);
}
public function end()
{
// end of if PROCEED
$this->tag->generator->doEnd();
// if trigger found, notify the end of the node
$this->tag->generator->doIf('$trigger');
$this->tag->generator->pushCode(
'$trigger->end("'.$this->id.'", $tpl)'
);
$this->tag->generator->doEnd();
}
}
?>

View file

@ -0,0 +1,60 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Laurent Bedubourg <lbedubourg@motion-twin.com>
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
/**
* @package phptal.php.attribute.phptal
* @author Laurent Bedubourg <lbedubourg@motion-twin.com>
*/
class PHPTAL_Php_Attribute_PHPTAL_TALES extends PHPTAL_Php_Attribute
{
public function start()
{
$mode = trim($this->expression);
$mode = strtolower($mode);
if ($mode == '' || $mode == 'default')
$mode = 'tales';
if ($mode != 'php' && $mode != 'tales') {
$err = "Unsupported TALES mode '%s'";
$err = sprintf($err, $mode);
throw new PHPTAL_Exception(
$err,
$this->tag->getSourceFile(),
$this->tag->getSourceLine()
);
}
$this->_oldMode = $this->tag->generator->setTalesMode( $mode );
}
public function end()
{
$this->tag->generator->setTalesMode( $this->_oldMode );
}
private $_oldMode;
}
?>

View file

@ -0,0 +1,168 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Laurent Bedubourg <lbedubourg@motion-twin.com>
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// TAL Specifications 1.4
//
// argument ::= attribute_statement [';' attribute_statement]*
// attribute_statement ::= attribute_name expression
// attribute_name ::= [namespace ':'] Name
// namespace ::= Name
//
// examples:
//
// <a href="/sample/link.html"
// tal:attributes="href here/sub/absolute_url">
// <textarea rows="80" cols="20"
// tal:attributes="rows request/rows;cols request/cols">
//
// IN PHPTAL: attributes will not work on structured replace.
//
require_once PHPTAL_DIR.'PHPTAL/Php/TalesChainExecutor.php';
/**
* @package phptal.php.attribute.tal
* @author Laurent Bedubourg <lbedubourg@motion-twin.com>
*/
class PHPTAL_Php_Attribute_TAL_Attributes
extends PHPTAL_Php_Attribute
implements PHPTAL_Php_TalesChainReader
{
const ATT_FULL_REPLACE = '$__ATT_';
const ATT_VALUE_REPLACE = '$__att_';
// this regex is used to determine if an attribute is entirely replaced
// by a php variable or if only its value is replaced.
const REGEX_FULL_REPLACE = '/<?php echo \$__ATT_.*? ?>/';
public function start()
{
// split attributes using ; delimiter
$attrs = $this->tag->generator->splitExpression($this->expression);
foreach ($attrs as $exp) {
list($attribute, $expression) = $this->parseSetExpression($exp);
if ($expression) {
$this->prepareAttribute($attribute, $expression);
}
}
}
public function end()
{
}
private function prepareAttribute($attribute, $expression)
{
$code = $this->extractEchoType(trim($expression));
$code = $this->tag->generator->evaluateExpression($code);
// if $code is an array then the attribute value is decided by a
// tales chained expression
if (is_array($code)) {
return $this->prepareChainedAttribute2($attribute, $code);
}
// XHTML boolean attribute does not appear when empty of false
if (PHPTAL_Dom_Defs::getInstance()->isBooleanAttribute($attribute)) {
return $this->prepareBooleanAttribute($attribute, $code);
}
// regular attribute which value is the evaluation of $code
$attkey = self::ATT_VALUE_REPLACE . $this->getVarName($attribute);
if ($this->_echoType == PHPTAL_Php_Attribute::ECHO_STRUCTURE)
$value = $code;
else
$value = $this->tag->generator->escapeCode($code);
$this->tag->generator->doSetVar($attkey, $value);
$this->tag->overwriteAttributeWithPhpValue($attribute, $attkey);
}
private function prepareChainedAttribute2($attribute, $chain)
{
$this->_default = false;
$this->_attribute = $attribute;
if (array_key_exists($attribute, $this->tag->attributes)) {
$this->_default = $this->tag->attributes[$attribute];
}
$this->_attkey = self::ATT_FULL_REPLACE.$this->getVarName($attribute);
$executor = new PHPTAL_Php_TalesChainExecutor($this->tag->generator, $chain, $this);
$this->tag->overwriteAttributeWithPhpValue($attribute, $this->_attkey);
}
private function prepareBooleanAttribute($attribute, $code)
{
$attkey = self::ATT_FULL_REPLACE.$this->getVarName($attribute);
$value = "' $attribute=\"$attribute\"'";
$this->tag->generator->doIf($code);
$this->tag->generator->doSetVar($attkey, $value);
$this->tag->generator->doElse();
$this->tag->generator->doSetVar($attkey, '\'\'');
$this->tag->generator->doEnd();
$this->tag->overwriteAttributeWithPhpValue($attribute, $attkey);
}
private function getVarName($attribute)
{
return strtr($attribute,':-', '__');
}
public function talesChainNothingKeyword(PHPTAL_Php_TalesChainExecutor $executor)
{
$executor->doElse();
$this->tag->generator->doSetVar(
$this->_attkey,
"''"
);
$executor->breakChain();
}
public function talesChainDefaultKeyword(PHPTAL_Php_TalesChainExecutor $executor)
{
$executor->doElse();
$code = ($this->_default !== false)
? "' $this->_attribute=\"".str_replace("'",'\\\'',$this->_default)."\"'" // default value
: '\'\''; // do not print attribute
$this->tag->generator->doSetVar($this->_attkey, $code);
$executor->breakChain();
}
public function talesChainPart(PHPTAL_Php_TalesChainExecutor $executor, $exp, $islast)
{
if (!$islast) {
$condition = "!phptal_isempty($this->_attkey = $exp)";
}
else {
$condition = "NULL !== ($this->_attkey = $exp)";
}
$executor->doIf($condition);
if ($this->_echoType == PHPTAL_Php_Attribute::ECHO_STRUCTURE)
$value = $this->_attkey;
else
$value = $this->tag->generator->escapeCode($this->_attkey);
$this->tag->generator->doSetVar($this->_attkey, "' $this->_attribute=\"'.$value.'\"'");
}
}
?>

View file

@ -0,0 +1,40 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Laurent Bedubourg <lbedubourg@motion-twin.com>
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
/**
* @package phptal.php.attribute.tal
*/
class PHPTAL_Php_Attribute_TAL_Comment extends PHPTAL_Php_Attribute
{
public function start()
{
$this->tag->generator->doComment($this->expression);
}
public function end()
{
}
}
?>

View file

@ -0,0 +1,101 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Laurent Bedubourg <lbedubourg@motion-twin.com>
//
// TAL Specifications 1.4
//
// argument ::= expression
//
// Example:
//
// <p tal:condition="here/copyright"
// tal:content="here/copyright">(c) 2000</p>
//
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
require_once PHPTAL_DIR.'PHPTAL/Php/TalesChainExecutor.php';
/**
* @package phptal.php.attribute.tal
* @author Laurent Bedubourg <lbedubourg@motion-twin.com>
*/
class PHPTAL_Php_Attribute_TAL_Condition
extends PHPTAL_Php_Attribute
implements PHPTAL_Php_TalesChainReader
{
private $expressions = array();
public function start()
{
$code = $this->tag->generator->evaluateExpression($this->expression);
// If it's a chained expression build a new code path
if (is_array($code)) {
$this->expressions = array();
$executor = new PHPTAL_Php_TalesChainExecutor( $this->tag->generator, $code, $this );
return;
}
// Force a falsy condition if the nothing keyword is active
if ($code == PHPTAL_TALES_NOTHING_KEYWORD) {
$code = 'false';
}
$this->tag->generator->doIf($code);
}
public function end()
{
$this->tag->generator->doEnd();
}
public function talesChainPart(PHPTAL_Php_TalesChainExecutor $executor, $exp, $islast)
{
// check if the expression is empty
if ( $exp !== 'false' ) {
$this->expressions[] = '!phptal_isempty($__content__ = ' . $exp . ')';
}
if ( $islast ) {
// for the last one in the chain build a ORed condition
$this->tag->generator->doIf( implode(' || ', $this->expressions ) );
// The executor will always end an if so we output a dummy if
$executor->doIf('false');
}
}
public function talesChainNothingKeyword(PHPTAL_Php_TalesChainExecutor $executor)
{
// end the chain
$this->talesChainPart( $executor, 'false', true );
$executor->breakChain();
}
public function talesChainDefaultKeyword(PHPTAL_Php_TalesChainExecutor $executor)
{
throw new PHPTAL_Exception('\'default\' keyword not allowed on condition expressions');
}
}

View file

@ -0,0 +1,98 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Laurent Bedubourg <lbedubourg@motion-twin.com>
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// TAL Specifications 1.4
//
// argument ::= (['text'] | 'structure') expression
//
// Example:
//
// <p tal:content="user/name">Fred Farkas</p>
//
//
require_once PHPTAL_DIR.'PHPTAL/Php/TalesChainExecutor.php';
/**
* @package phptal.php.attribute.tal
* @author Laurent Bedubourg <lbedubourg@motion-twin.com>
*/
class PHPTAL_Php_Attribute_TAL_Content
extends PHPTAL_Php_Attribute
implements PHPTAL_Php_TalesChainReader
{
public function start()
{
$expression = $this->extractEchoType($this->expression);
$code = $this->tag->generator->evaluateExpression($expression);
if (is_array($code)) {
return $this->generateChainedContent($code);
}
if ($code == PHPTAL_TALES_NOTHING_KEYWORD) {
return;
}
if ($code == PHPTAL_TALES_DEFAULT_KEYWORD) {
return $this->generateDefault();
}
$this->doEcho($code);
}
public function end()
{
}
private function generateDefault()
{
$this->tag->generateContent(true);
}
private function generateChainedContent($code)
{
$executor = new PHPTAL_Php_TalesChainExecutor($this->tag->generator, $code, $this);
}
public function talesChainPart(PHPTAL_Php_TalesChainExecutor $executor, $exp, $islast)
{
$executor->doIf('!phptal_isempty($__content__ = '.$exp.')');
$this->doEcho('$__content__');
}
public function talesChainNothingKeyword(PHPTAL_Php_TalesChainExecutor $executor)
{
$executor->breakChain();
}
public function talesChainDefaultKeyword(PHPTAL_Php_TalesChainExecutor $executor)
{
$executor->doElse();
$this->generateDefault();
$executor->breakChain();
}
}
?>

View file

@ -0,0 +1,183 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Laurent Bedubourg <lbedubourg@motion-twin.com>
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// TAL spec 1.4 for tal:define content
//
// argument ::= define_scope [';' define_scope]*
// define_scope ::= (['local'] | 'global') define_var
// define_var ::= variable_name expression
// variable_name ::= Name
//
// Note: If you want to include a semi-colon (;) in an expression, it must be escaped by doubling it (;;).*
//
// examples:
//
// tal:define="mytitle template/title; tlen python:len(mytitle)"
// tal:define="global company_name string:Digital Creations, Inc."
//
require_once PHPTAL_DIR.'PHPTAL/Php/TalesChainExecutor.php';
/**
* @package phptal.php.attribute.tal
* @author Laurent Bedubourg <lbedubourg@motion-twin.com>
*/
class PHPTAL_Php_Attribute_TAL_Define
extends PHPTAL_Php_Attribute
implements PHPTAL_Php_TalesChainReader
{
public function start()
{
$expressions = $this->tag->generator->splitExpression($this->expression);
$definesAnyNonGlobalVars = false;
foreach ($expressions as $exp){
list($defineScope, $defineVar, $expression) = $this->parseExpression($exp);
if (!$defineVar) {
continue;
}
$this->_defineScope = $defineScope;
if ($defineScope != 'global') $definesAnyNonGlobalVars = true; // <span tal:define="global foo" /> should be invisible, but <img tal:define="bar baz" /> not
if ($this->_defineScope != 'global' && !$this->_pushedContext){
$this->tag->generator->pushContext();
$this->_pushedContext = true;
}
$this->_defineVar = $defineVar;
if ($expression === null) {
// no expression give, use content of tag as value for newly defined
// var.
$this->bufferizeContent();
continue;
}
$code = $this->tag->generator->evaluateExpression($expression);
if (is_array($code)){
$this->chainedDefine($code);
}
elseif ($code == PHPTAL_TALES_NOTHING_KEYWORD) {
$this->doDefineVarWith('null');
}
else {
$this->doDefineVarWith($code);
}
}
// if the content of the tag was buffered or the tag has nothing to tell, we hide it.
if ($this->_buffered || (!$definesAnyNonGlobalVars && !$this->tag->hasRealContent() && !$this->tag->hasRealAttributes())){
$this->tag->hidden = true;
}
}
public function end()
{
if ($this->_pushedContext){
$this->tag->generator->popContext();
}
}
private function chainedDefine($parts)
{
$executor = new PHPTAL_Php_TalesChainExecutor(
$this->tag->generator, $parts, $this
);
}
public function talesChainNothingKeyword(PHPTAL_Php_TalesChainExecutor $executor)
{
$executor->doElse();
$this->doDefineVarWith('null');
$executor->breakChain();
}
public function talesChainDefaultKeyword(PHPTAL_Php_TalesChainExecutor $executor)
{
$executor->doElse();
$this->bufferizeContent();
$executor->breakChain();
}
public function talesChainPart(PHPTAL_Php_TalesChainExecutor $executor, $exp, $islast)
{
if ($this->_defineScope == 'global'){
$executor->doIf('($glb->'.$this->_defineVar.' = '.$exp.') !== null');
}
else {
$executor->doIf('($ctx->'.$this->_defineVar.' = '.$exp.') !== null');
}
}
/**
* Parse the define expression, already splitted in sub parts by ';'.
*/
public function parseExpression($exp)
{
$defineScope = false; // (local | global)
$defineVar = false; // var to define
// extract defineScope from expression
$exp = trim($exp);
if (preg_match('/^(local|global)\s+(.*?)$/ism', $exp, $m)) {
list(,$defineScope, $exp) = $m;
$exp = trim($exp);
}
// extract varname and expression from remaining of expression
list($defineVar, $exp) = $this->parseSetExpression($exp);
if ($exp !== null) $exp = trim($exp);
return array($defineScope, $defineVar, $exp);
}
private function bufferizeContent()
{
if (!$this->_buffered){
$this->tag->generator->pushCode( 'ob_start()' );
$this->tag->generateContent();
$this->tag->generator->pushCode('$__tmp_content__ = ob_get_clean()');
$this->_buffered = true;
}
$this->doDefineVarWith('$__tmp_content__');
}
private function doDefineVarWith($code)
{
if ($this->_defineScope == 'global'){
$this->tag->generator->doSetVar('$glb->'.$this->_defineVar, $code);
}
else {
$this->tag->generator->doSetVar('$ctx->'.$this->_defineVar, $code);
}
}
private $_buffered = false;
private $_defineScope = null;
private $_defineVar = null;
private $_pushedContext = false;
}
?>

View file

@ -0,0 +1,74 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Laurent Bedubourg <lbedubourg@motion-twin.com>
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// TAL Specifications 1.4
//
// argument ::= [expression]
//
// Example:
//
// <div tal:omit-tag="" comment="This tag will be removed">
// <i>...but this text will remain.</i>
// </div>
//
// <b tal:omit-tag="not:bold">I may not be bold.</b>
//
// To leave the contents of a tag in place while omitting the surrounding
// start and end tag, use the omit-tag statement.
//
// If its expression evaluates to a false value, then normal processing
// of the element continues.
//
// If the expression evaluates to a true value, or there is no
// expression, the statement tag is replaced with its contents. It is up to
// the interface between TAL and the expression engine to determine the
// value of true and false. For these purposes, the value nothing is false,
// and cancellation of the action has the same effect as returning a
// false value.
//
/**
* @package phptal.php.attribute.tal
* @author Laurent Bedubourg <lbedubourg@motion-twin.com>
*/
class PHPTAL_Php_Attribute_TAL_OmitTag extends PHPTAL_Php_Attribute
{
public function start()
{
if (trim($this->expression) == ''){
$this->tag->headFootDisabled = true;
}
else {
// print tag header/foot only if condition is false
$cond = $this->tag->generator->evaluateExpression($this->expression);
$this->tag->headFootPrintCondition = '!('.$cond.')';
}
}
public function end()
{
}
}
?>

View file

@ -0,0 +1,81 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Laurent Bedubourg <lbedubourg@motion-twin.com>
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// TAL Specifications 1.4
//
// argument ::= (['text'] | 'structure') expression
//
// Example:
//
// <p tal:on-error="string: Error! This paragraph is buggy!">
// My name is <span tal:replace="here/SlimShady" />.<br />
// (My login name is
// <b tal:on-error="string: Username is not defined!"
// tal:content="user">Unknown</b>)
// </p>
//
/**
* @package phptal.php.attribute.tal
* @author Laurent Bedubourg <lbedubourg@motion-twin.com>
*/
class PHPTAL_Php_Attribute_TAL_OnError extends PHPTAL_Php_Attribute
{
const ERR_VAR = '$__err__';
public function start()
{
$this->tag->generator->doTry();
$this->tag->generator->pushCode('ob_start()');
}
public function end()
{
$this->tag->generator->pushCode('ob_end_flush()');
$this->tag->generator->doCatch('Exception '.self::ERR_VAR);
$this->tag->generator->pushCode('$tpl->addError('.self::ERR_VAR.')');
$this->tag->generator->pushCode('ob_end_clean()');
$expression = $this->extractEchoType($this->expression);
$code = $this->tag->generator->evaluateExpression($expression);
switch ($code) {
case PHPTAL_TALES_NOTHING_KEYWORD:
break;
case PHPTAL_TALES_DEFAULT_KEYWORD:
$this->tag->generator->pushHtml('<pre class="phptalError"');
$this->tag->generator->doEcho(self::ERR_VAR);
$this->tag->generator->pushHtml('</pre>');
break;
default:
$this->doEcho($code);
break;
}
$this->tag->generator->doEnd();
}
}
?>

View file

@ -0,0 +1,115 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Laurent Bedubourg <lbedubourg@motion-twin.com>
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// TAL Specifications 1.4
//
// argument ::= variable_name expression
// variable_name ::= Name
//
// Example:
//
// <p tal:repeat="txt python:'one', 'two', 'three'">
// <span tal:replace="txt" />
// </p>
// <table>
// <tr tal:repeat="item here/cart">
// <td tal:content="repeat/item/index">1</td>
// <td tal:content="item/description">Widget</td>
// <td tal:content="item/price">$1.50</td>
// </tr>
// </table>
//
// The following information is available from an Iterator:
//
// * index - repetition number, starting from zero.
// * number - repetition number, starting from one.
// * even - true for even-indexed repetitions (0, 2, 4, ...).
// * odd - true for odd-indexed repetitions (1, 3, 5, ...).
// * start - true for the starting repetition (index 0).
// * end - true for the ending, or final, repetition.
// * length - length of the sequence, which will be the total number of repetitions.
//
// * letter - count reps with lower-case letters: "a" - "z", "aa" - "az", "ba" - "bz", ..., "za" - "zz", "aaa" - "aaz", and so forth.
// * Letter - upper-case version of letter.
// * roman - count reps with lower-case roman numerals: "i", "ii", "iii", "iv", "v", "vi" ...
// * Roman - upper-case version of roman numerals.
///
// * first - true for the first item in a group - see note below
// * lasst - true for the last item in a group - see note below
//
// Note: first and last are intended for use with sorted sequences. They try to
// divide the sequence into group of items with the same value. If you provide
// a path, then the value obtained by following that path from a sequence item
// is used for grouping, otherwise the value of the item is used. You can
// provide the path by appending it to the path from the repeat variable,
// as in "repeat/item/first/color".
//
// PHPTAL: index, number, even, etc... will be stored in the
// $ctx->repeat->'item' object. Thus $ctx->repeat->item->odd
//
/**
* @package phptal.php.attribute.tal
* @author Laurent Bedubourg <lbedubourg@motion-twin.com>
*/
class PHPTAL_Php_Attribute_TAL_Repeat extends PHPTAL_Php_Attribute
{
const REPEAT = '$__repeat__';
public function start()
{
// alias to repeats handler to avoid calling extra getters on each variable access
$this->tag->generator->doSetVar( self::REPEAT, '$ctx->repeat' );
list( $varName, $expression ) = $this->parseSetExpression( $this->expression );
$code = $this->tag->generator->evaluateExpression( $expression );
$item = '$ctx->' . $varName;
$controller = self::REPEAT . '->' . $varName;
// reset item var into template context
/* // Is this actually needed?
$this->tag->generator->doIf( '!isset('.$this->item.')' );
$this->tag->generator->doSetVar( $this->item, 'false' );
$this->tag->generator->doEnd();
*/
// instantiate controller using expression
$this->tag->generator->doSetVar( $controller, 'new PHPTAL_RepeatController('.$code.')' );
// Lets loop the iterator with a foreach construct
$this->tag->generator->doForeach( $item, $controller );
}
public function end()
{
$this->tag->generator->doEnd();
}
private $item;
private $controller;
}
?>

View file

@ -0,0 +1,117 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
// Copyright (c) 2004-2005 Laurent Bedubourg
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Authors: Laurent Bedubourg <lbedubourg@motion-twin.com>
//
require_once PHPTAL_DIR.'PHPTAL/Php/Attribute.php';
// TAL Specifications 1.4
//
// argument ::= (['text'] | 'structure') expression
//
// Default behaviour : text
//
// <span tal:replace="template/title">Title</span>
// <span tal:replace="text template/title">Title</span>
// <span tal:replace="structure table" />
// <span tal:replace="nothing">This element is a comment.</span>
//
require_once PHPTAL_DIR.'PHPTAL/Php/TalesChainExecutor.php';
/**
* @package phptal.php.attribute.tal
* @author Laurent Bedubourg <lbedubourg@motion-twin.com>
*/
class PHPTAL_Php_Attribute_TAL_Replace
extends PHPTAL_Php_Attribute
implements PHPTAL_Php_TalesChainReader
{
const REPLACE_VAR = '$__replace__';
public function start()
{
// tal:replace="" => do nothing and ignore node
if (trim($this->expression) == ""){
return;
}
$expression = $this->extractEchoType($this->expression);
$code = $this->tag->generator->evaluateExpression($expression);
// chained expression
if (is_array($code)){
return $this->replaceByChainedExpression($code);
}
// nothing do nothing
if ($code == PHPTAL_TALES_NOTHING_KEYWORD) {
return;
}
// default generate default tag content
if ($code == PHPTAL_TALES_DEFAULT_KEYWORD) {
return $this->generateDefault();
}
// replace tag with result of expression
$this->doEcho($code);
}
public function end()
{
}
private function replaceByChainedExpression($expArray)
{
$executor = new PHPTAL_Php_TalesChainExecutor(
$this->tag->generator, $expArray, $this
);
}
public function talesChainNothingKeyword(PHPTAL_Php_TalesChainExecutor $executor)
{
$executor->continueChain();
}
public function talesChainDefaultKeyword(PHPTAL_Php_TalesChainExecutor $executor)
{
$executor->doElse();
$this->generateDefault();
$executor->breakChain();
}
public function talesChainPart(PHPTAL_Php_TalesChainExecutor $executor, $exp, $islast)
{
$executor->doIf('!phptal_isempty('.self::REPLACE_VAR.' = '.$exp.')');
$this->doEcho(self::REPLACE_VAR);
}
private function generateDefault()
{
$this->tag->generateSurroundHead();
$this->tag->generateHead();
$this->tag->generateContent();
$this->tag->generateFoot();
$this->tag->generateSurroundFoot();
}
}
?>