Initial commit

This commit is contained in:
Nathan Adams
2013-07-20 17:41:56 -05:00
commit 3b1e713fc4
606 changed files with 136001 additions and 0 deletions

View File

@@ -0,0 +1,679 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Class to compile a template file into the corresponding PHP script
* to be run by the Template class.
*
* Compiler dataflow
*
* The important elements of the compiler are the include extends
* block and superblock directives. They cannot be handled in a linear
* way like the rest of the elements, they are more like nodes.
*
*
* @credit Copyright (C) 2006 Laurent Jouanneau.
*/
class Pluf_Template_Compiler
{
/**
* Store the literal blocks.
**/
protected $_literals;
/**
* Variables.
*/
protected $_vartype = array(T_CHARACTER, T_CONSTANT_ENCAPSED_STRING,
T_DNUMBER, T_ENCAPSED_AND_WHITESPACE,
T_LNUMBER, T_OBJECT_OPERATOR, T_STRING,
T_WHITESPACE, T_ARRAY, T_CLASS, T_PRIVATE, T_LIST);
/**
* Assignation operators.
*/
protected $_assignOp = array(T_AND_EQUAL, T_DIV_EQUAL, T_MINUS_EQUAL,
T_MOD_EQUAL, T_MUL_EQUAL, T_OR_EQUAL,
T_PLUS_EQUAL, T_PLUS_EQUAL, T_SL_EQUAL,
T_SR_EQUAL, T_XOR_EQUAL);
/**
* Operators.
*/
protected $_op = array(T_BOOLEAN_AND, T_BOOLEAN_OR, T_EMPTY, T_INC,
T_ISSET, T_IS_EQUAL, T_IS_GREATER_OR_EQUAL,
T_IS_IDENTICAL, T_IS_NOT_EQUAL, T_IS_NOT_IDENTICAL,
T_IS_SMALLER_OR_EQUAL, T_LOGICAL_AND, T_LOGICAL_OR,
T_LOGICAL_XOR, T_SR, T_SL, T_DOUBLE_ARROW);
/**
* Authorized elements in variables.
*/
protected $_allowedInVar;
/**
* Authorized elements in expression.
*/
protected $_allowedInExpr;
/**
* Authorized elements in assignation.
*/
protected $_allowedAssign;
/**
* Output filters.
*/
protected $_modifier = array('upper' => 'strtoupper',
'lower' => 'strtolower',
'count' => 'count',
'md5' => 'md5',
'sha1' => 'sha1',
'escxml' => 'htmlspecialchars',
'escape' => 'Pluf_Template_htmlspecialchars',
'strip_tags' => 'strip_tags',
'escurl' => 'rawurlencode',
'capitalize' => 'ucwords',
// Not var_export because of recursive issues.
'debug' => 'print_r',
'dump' => 'Pluf_Template_varExport',
'fulldebug' => 'var_export',
'nl2br' => 'Pluf_Template_nl2br',
'trim' => 'trim',
'ltrim' => 'ltrim',
'rtrim' => 'rtrim',
'unsafe' => 'Pluf_Template_unsafe',
'safe' => 'Pluf_Template_unsafe',
'date' => 'Pluf_Template_dateFormat',
'time' => 'Pluf_Template_timeFormat',
'dateago' => 'Pluf_Template_dateAgo',
'timeago' => 'Pluf_Template_timeAgo',
'email' => 'Pluf_Template_safeEmail',
'first' => 'Pluf_Template_first',
'last' => 'Pluf_Template_last',
);
/**
* After the compilation is completed, this contains the list of
* modifiers used in the template. The GetCompiledTemplate method
* will add a series of Pluf::loadFunction at the top to preload
* these modifiers.
*/
public $_usedModifiers = array();
/**
* Default allowed extra tags/functions.
*
* These default tags are merged with the 'template_tags' defined
* in the configuration of the application.
*/
protected $_allowedTags = array(
'url' => 'Pluf_Template_Tag_Url',
'aurl' => 'Pluf_Template_Tag_Rurl',
'media' => 'Pluf_Template_Tag_MediaUrl',
'amedia' => 'Pluf_Template_Tag_RmediaUrl',
'aperm' => 'Pluf_Template_Tag_APerm',
'getmsgs' => 'Pluf_Template_Tag_Messages',
);
/**
* During compilation, all the tags are created once so to query
* their interface easily.
*/
protected $_extraTags = array();
/**
* The block stack to see if the blocks are correctly closed.
*/
protected $_blockStack = array();
/**
* Special stack for the translation handling in blocktrans.
*/
protected $_transStack = array();
protected $_transPlural = false;
/**
* Current template source file.
*/
protected $_sourceFile;
/**
* Current tag.
*/
protected $_currentTag;
/**
* Template folders.
*/
public $templateFolders = array();
/**
* Template content. It can be set directly from a string.
*/
public $templateContent = '';
/**
* The extend blocks.
*/
public $_extendBlocks = array();
/**
* The extended template.
*/
public $_extendedTemplate = '';
/**
* Construct the compiler.
*
* @param string Basename of the template file.
* @param array Base folders in which the templates files
* should be found. (array())
* @param bool Load directly the template content. (true)
*/
function __construct($template_file, $folders=array(), $load=true)
{
/**
* [signal]
*
* Pluf_Template_Compiler::construct_template_tags_modifiers
*
* [sender]
*
* Pluf_Template_Compiler
*
* [description]
*
* This signal allows an application to dynamically modify the
* allowed template tags. The order of the merge with the ones
* configured in the configuration files and the default one
* is: default -> signal -> configuration file.
* That is, the configuration file is the highest authority.
*
* [parameters]
*
* array('tags' => array(),
* 'modifiers' => array());
*
*/
$params = array('tags' => array(),
'modifiers' => array());
Pluf_Signal::send('Pluf_Template_Compiler::construct_template_tags_modifiers',
'Pluf_Template_Compiler', $params);
$this->_allowedTags = array_merge($this->_allowedTags,
$params['tags'],
Pluf::f('template_tags', array()));
$this->_modifier = array_merge($this->_modifier,
$params['modifiers'],
Pluf::f('template_modifiers', array()));
foreach ($this->_allowedTags as $name=>$model) {
$this->_extraTags[$name] = new $model();
}
$this->_sourceFile = $template_file;
$this->_allowedInVar = array_merge($this->_vartype, $this->_op);
$this->_allowedInExpr = array_merge($this->_vartype, $this->_op);
$this->_allowedAssign = array_merge($this->_vartype, $this->_assignOp,
$this->_op);
$this->templateFolders = $folders;
if ($load) {
$this->loadTemplateFile($template_file);
}
}
/**
* Compile the template into a PHP code.
*
* @return string PHP code of the compiled template.
*/
function compile()
{
$this->compileBlocks();
$tplcontent = $this->templateContent;
// Remove the template comments
$tplcontent = preg_replace('!{\*(.*?)\*}!s', '', $tplcontent);
// Remove PHP code
$tplcontent = preg_replace('!<\?php(.*?)\?>!s', '', $tplcontent);
// Catch the litteral blocks and put them in the
// $this->_literals stack
preg_match_all('!{literal}(.*?){/literal}!s', $tplcontent, $_match);
$this->_literals = $_match[1];
$tplcontent = preg_replace("!{literal}(.*?){/literal}!s", '{literal}', $tplcontent);
// Core regex to parse the template
$result = preg_replace_callback('/{((.).*?)}/s',
array($this, '_callback'),
$tplcontent);
if (count($this->_blockStack)) {
trigger_error(sprintf(__('End tag of a block missing: %s'), end($this->_blockStack)), E_USER_ERROR);
}
return $result;
}
/**
* Get a cleaned compile template.
*
*/
function getCompiledTemplate()
{
$result = $this->compile();
if (count($this->_usedModifiers)) {
$code = array();
foreach ($this->_usedModifiers as $modifier) {
$code[] = 'Pluf::loadFunction(\''.$modifier.'\'); ';
}
$result = '<?php '.implode("\n", $code).'?>'.$result;
}
// Clean the output
$result = str_replace(array('?><?php', '<?php ?>', '<?php ?>'), '', $result);
// To avoid the triming of the \n after a php closing tag.
$result = str_replace("?>\n", "?>\n\n", $result);
return $result;
}
/**
* Parse the extend blocks.
*
* If the current template extends another, it finds the extended
* template and grabs the defined blocks and compile them.
*/
function compileBlocks()
{
$tplcontent = $this->templateContent;
$this->_extendedTemplate = '';
// Match extends on the first line of the template
if (preg_match("!{extends\s['\"](.*?)['\"]}!", $tplcontent, $_match)) {
$this->_extendedTemplate = $_match[1];
}
// Get the blocks in the current template
$cnt = preg_match_all("!{block\s(\S+?)}(.*?){/block}!s", $tplcontent, $_match);
// Compile the blocks
for ($i=0; $i<$cnt; $i++) {
if (!isset($this->_extendBlocks[$_match[1][$i]])
or false !== strpos($this->_extendBlocks[$_match[1][$i]], '~~{~~superblock~~}~~')) {
$compiler = clone($this);
$compiler->templateContent = $_match[2][$i];
$_tmp = $compiler->compile();
$this->updateModifierStack($compiler);
if (!isset($this->_extendBlocks[$_match[1][$i]])) {
$this->_extendBlocks[$_match[1][$i]] = $_tmp;
} else {
$this->_extendBlocks[$_match[1][$i]] = str_replace('~~{~~superblock~~}~~', $_tmp, $this->_extendBlocks[$_match[1][$i]]);
}
}
}
if (strlen($this->_extendedTemplate) > 0) {
// The template of interest is now the extended template
// as we are not in a base template
$this->loadTemplateFile($this->_extendedTemplate);
$this->_sourceFile = $this->_extendedTemplate;
$this->compileBlocks(); //It will recurse to the base template.
} else {
// Replace the current blocks by a place holder
if ($cnt) {
$this->templateContent = preg_replace("!{block\s(\S+?)}(.*?){/block}!s", "{block $1}", $tplcontent, -1);
}
}
}
/**
* Load a template file.
*
* The path to the file to load is relative and the file is found
* in one of the $templateFolders array of folders.
*
* @param string Relative path of the file to load.
*/
function loadTemplateFile($file)
{
// FIXME: Very small security check, could be better.
if (strpos($file, '..') !== false) {
throw new Exception(sprintf(__('Template file contains invalid characters: %s'), $file));
}
foreach ($this->templateFolders as $folder) {
if (file_exists($folder.'/'.$file)) {
$this->templateContent = file_get_contents($folder.'/'.$file);
return;
}
}
// File not found in all the folders.
throw new Exception(sprintf(__('Template file not found: %s'), $file));
}
function _callback($matches)
{
list(,$tag, $firstcar) = $matches;
if (!preg_match('/^\$|[\'"]|[a-zA-Z\/]$/', $firstcar)) {
trigger_error(sprintf(__('Invalid tag syntax: %s'), $tag), E_USER_ERROR);
return '';
}
$this->_currentTag = $tag;
if (in_array($firstcar, array('$', '\'', '"'))) {
if ('blocktrans' !== end($this->_blockStack)) {
return '<?php Pluf_Template_safeEcho('.$this->_parseVariable($tag).'); ?>';
} else {
$tok = explode('|', $tag);
$this->_transStack[substr($tok[0], 1)] = $this->_parseVariable($tag);
return '%%'.substr($tok[0], 1).'%%';
}
} else {
if (!preg_match('/^(\/?[a-zA-Z0-9_]+)(?:(?:\s+(.*))|(?:\((.*)\)))?$/', $tag, $m)) {
trigger_error(sprintf(__('Invalid function syntax: %s'), $tag), E_USER_ERROR);
return '';
}
if (count($m) == 4){
$m[2] = $m[3];
}
if (!isset($m[2])) $m[2] = '';
if($m[1] == 'ldelim') return '{';
if($m[1] == 'rdelim') return '}';
if ($m[1] != 'include') {
return '<?php '.$this->_parseFunction($m[1], $m[2]).'?>';
} else {
return $this->_parseFunction($m[1], $m[2]);
}
}
}
function _parseVariable($expr)
{
$tok = explode('|', $expr);
$res = $this->_parseFinal(array_shift($tok), $this->_allowedInVar);
foreach ($tok as $modifier) {
if (!preg_match('/^(\w+)(?:\:(.*))?$/', $modifier, $m)) {
trigger_error(sprintf(__('Invalid modifier syntax: (%s) %s'), $this->_currentTag, $modifier), E_USER_ERROR);
return '';
}
$targs = array($res);
if(isset($m[2])){
$res = $this->_modifier[$m[1]].'('.$res.','.$m[2].')';
}
else if (isset($this->_modifier[$m[1]])) {
$res = $this->_modifier[$m[1]].'('.$res.')';
} else {
trigger_error(sprintf(__('Unknown modifier: (%s) %s'), $this->_currentTag, $m[1]), E_USER_ERROR);
return '';
}
if (!in_array($this->_modifier[$m[1]], $this->_usedModifiers)) {
$this->_usedModifiers[] = $this->_modifier[$m[1]];
}
}
return $res;
}
function _parseFunction($name, $args)
{
switch ($name) {
case 'if':
$res = 'if ('.$this->_parseFinal($args, $this->_allowedInExpr).'): ';
array_push($this->_blockStack, 'if');
break;
case 'else':
if (end($this->_blockStack) != 'if') {
trigger_error(sprintf(__('End tag of a block missing: %s'), end($this->_blockStack)), E_USER_ERROR);
}
$res = 'else: ';
break;
case 'elseif':
if (end($this->_blockStack) != 'if') {
trigger_error(sprintf(__('End tag of a block missing: %s'), end($this->_blockStack)), E_USER_ERROR);
}
$res = 'elseif('.$this->_parseFinal($args, $this->_allowedInExpr).'):';
break;
case 'foreach':
$res = 'foreach ('.$this->_parseFinal($args, array_merge(array(T_AS, T_DOUBLE_ARROW, T_STRING, T_OBJECT_OPERATOR, T_LIST, $this->_allowedAssign, '[', ']')), array(';','!')).'): ';
array_push($this->_blockStack, 'foreach');
break;
case 'while':
$res = 'while('.$this->_parseFinal($args,$this->_allowedInExpr).'):';
array_push($this->_blockStack, 'while');
break;
case '/foreach':
case '/if':
case '/while':
$short = substr($name,1);
if(end($this->_blockStack) != $short){
trigger_error(sprintf(__('End tag of a block missing: %s'), end($this->_blockStack)), E_USER_ERROR);
}
array_pop($this->_blockStack);
$res = 'end'.$short.'; ';
break;
case 'assign':
$res = $this->_parseFinal($args, $this->_allowedAssign).'; ';
break;
case 'literal':
if(count($this->_literals)){
$res = '?>'.array_shift($this->_literals).'<?php ';
}else{
trigger_error(__('End tag of a block missing: literal'), E_USER_ERROR);
}
break;
case '/literal':
trigger_error(__('Start tag of a block missing: literal'), E_USER_ERROR);
break;
case 'block':
$res = '?>'.$this->_extendBlocks[$args].'<?php ';
break;
case 'superblock':
$res = '?>~~{~~superblock~~}~~<?php ';
break;
case 'trans':
$argfct = $this->_parseFinal($args, $this->_allowedAssign);
$res = 'echo(__('.$argfct.'));';
break;
case 'blocktrans':
array_push($this->_blockStack, 'blocktrans');
$res = '';
$this->_transStack = array();
if ($args) {
$this->_transPlural = true;
$_args = $this->_parseFinal($args, $this->_allowedAssign,
array(';', '[', ']'), true);
$res .= '$_b_t_c='.trim(array_shift($_args)).'; ';
}
$res .= 'ob_start(); ';
break;
case '/blocktrans':
$short = substr($name,1);
if(end($this->_blockStack) != $short){
trigger_error(sprintf(__('End tag of a block missing: %s'), end($this->_blockStack)), E_USER_ERROR);
}
$res = '';
if ($this->_transPlural) {
$res .= '$_b_t_p=ob_get_contents(); ob_end_clean(); echo(';
$res .= 'Pluf_Translation::sprintf(_n($_b_t_s, $_b_t_p, $_b_t_c), array(';
$_tmp = array();
foreach ($this->_transStack as $key=>$_trans) {
$_tmp[] = '\''.addslashes($key).'\' => Pluf_Template_safeEcho('.$_trans.', false)';
}
$res .= implode(', ', $_tmp);
unset($_trans, $_tmp);
$res .= ')));';
$this->_transStack = array();
} else {
$res .= '$_b_t_s=ob_get_contents(); ob_end_clean(); ';
if (count($this->_transStack) == 0) {
$res .= 'echo(__($_b_t_s)); ';
} else {
$res .= 'echo(Pluf_Translation::sprintf(__($_b_t_s), array(';
$_tmp = array();
foreach ($this->_transStack as $key=>$_trans) {
$_tmp[] = '\''.addslashes($key).'\' => Pluf_Template_safeEcho('.$_trans.', false)';
}
$res .= implode(', ', $_tmp);
unset($_trans, $_tmp);
$res .= '))); ';
$this->_transStack = array();
}
}
$this->_transPlural = false;
array_pop($this->_blockStack);
break;
case 'plural':
$res = '$_b_t_s=ob_get_contents(); ob_end_clean(); ob_start(); ';
break;
case 'include':
// XXX fixme: Will need some security check, when online editing.
$argfct = preg_replace('!^[\'"](.*)[\'"]$!', '$1', $args);
$_comp = new Pluf_Template_Compiler($argfct, $this->templateFolders);
$res = $_comp->compile();
$this->updateModifierStack($_comp);
break;
default:
$_end = false;
$oname = $name;
if (substr($name, 0, 1) == '/') {
$_end = true;
$name = substr($name, 1);
}
// Here we should allow custom blocks.
// Here we start the template tag calls at the template tag
// {tag ...} is not a block, so it must be a function.
if (!isset($this->_allowedTags[$name])) {
trigger_error(sprintf(__('The function tag "%s" is not allowed.'), $name), E_USER_ERROR);
}
$argfct = $this->_parseFinal($args, $this->_allowedAssign);
// $argfct is a string that can be copy/pasted in the PHP code
// but we need the array of args.
$res = '';
if (isset($this->_extraTags[$name])) {
if (false == $_end) {
if (method_exists($this->_extraTags[$name], 'start')) {
$res .= '$_extra_tag = Pluf::factory(\''.$this->_allowedTags[$name].'\', $t); $_extra_tag->start('.$argfct.'); ';
}
if (method_exists($this->_extraTags[$name], 'genStart')) {
$res .= $this->_extraTags[$name]->genStart();
}
} else {
if (method_exists($this->_extraTags[$name], 'end')) {
$res .= '$_extra_tag = Pluf::factory(\''.$this->_allowedTags[$name].'\', $t); $_extra_tag->end('.$argfct.'); ';
}
if (method_exists($this->_extraTags[$name], 'genEnd')) {
$res .= $this->_extraTags[$name]->genEnd();
}
}
}
if ($res == '') {
trigger_error(sprintf(__('The function tag "{%s ...}" is not supported.'), $oname), E_USER_ERROR);
}
}
return $res;
}
/*
-------
if: op, autre, var
foreach: T_AS, T_DOUBLE_ARROW, T_VARIABLE, @locale@
for: autre, fin_instruction
while: op, autre, var
assign: T_VARIABLE puis assign puis autre, ponctuation, T_STRING
echo: T_VARIABLE/@locale@ puis autre + ponctuation
modificateur: serie de autre séparé par une virgule
tous : T_VARIABLE, @locale@
*/
function _parseFinal($string, $allowed=array(),
$exceptchar=array(';'), $getAsArray=false)
{
$tokens = token_get_all('<?php '.$string.'?>');
$result = '';
$first = true;
$inDot = false;
$firstok = array_shift($tokens);
$afterAs = false;
$f_key = '';
$f_val = '';
$results = array();
// il y a un bug, parfois le premier token n'est pas T_OPEN_TAG...
if ($firstok == '<' && $tokens[0] == '?' && is_array($tokens[1])
&& $tokens[1][0] == T_STRING && $tokens[1][1] == 'php') {
array_shift($tokens);
array_shift($tokens);
}
foreach ($tokens as $tok) {
if (is_array($tok)) {
list($type, $str) = $tok;
$first = false;
if($type == T_CLOSE_TAG){
continue;
}
if ($type == T_AS) {
$afterAs = true;
}
if ($type == T_STRING && $inDot) {
$result .= $str;
} elseif ($type == T_VARIABLE) {
//$result .= '$t->_vars[\''.substr($str, 1).'\']';
$result .= '$t->_vars->'.substr($str, 1);
} elseif ($type == T_WHITESPACE || in_array($type, $allowed)) {
$result .= $str;
} else {
trigger_error(sprintf(__('Invalid syntax: (%s) %s.'), $this->_currentTag, $str.' tokens'.var_export($tokens, true)), E_USER_ERROR);
return '';
}
} else {
if (in_array($tok, $exceptchar)) {
trigger_error(sprintf(__('Invalid character: (%s) %s.'), $this->_currentTag, $tok), E_USER_ERROR);
} elseif ($tok == '.') {
$inDot = true;
$result .= '->';
} elseif ($tok == '~') {
$result .= '.';
} elseif ($tok =='[') {
$result.=$tok;
} elseif ($tok ==']') {
$result.=$tok;
} elseif ($getAsArray && $tok == ',') {
$results[]=$result;
$result='';
} else {
$result .= $tok;
}
$first = false;
}
}
if (!$getAsArray) {
return $result;
} else {
if ($result != '') {
$results[] = $result;
}
return $results;
}
}
/**
* Update the current stack of modifiers from another compiler.
*/
protected function updateModifierStack($compiler)
{
foreach ($compiler->_usedModifiers as $_um) {
if (!in_array($_um, $this->_usedModifiers)) {
$this->_usedModifiers[] = $_um;
}
}
}
}

View File

@@ -0,0 +1,48 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Class storing the data that are then used in the template.
*/
class Pluf_Template_Context
{
public $_vars;
function __construct($vars=array())
{
$this->_vars = new Pluf_Template_ContextVars($vars);
}
function get($var)
{
if (isset($this->_vars[$var])) {
return $this->_vars[$var];
}
return '';
}
function set($var, $value)
{
$this->_vars[$var] = $value;
}
}

View File

@@ -0,0 +1,65 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Class storing the data that are then used in the template.
*
* This class automatically set the 'request' key with the current
* request and use and add more keys based on the processors.
*/
class Pluf_Template_Context_Request extends Pluf_Template_Context
{
function __construct($request, $vars=array())
{
$vars = array_merge(array('request' => $request), $vars);
foreach (Pluf::f('template_context_processors', array()) as $proc) {
Pluf::loadFunction($proc);
$vars = array_merge($proc($request), $vars);
}
$params = array('request' => $request,
'context' => $vars);
/**
* [signal]
*
* Pluf_Template_Context_Request::construct
*
* [sender]
*
* Pluf_Template_Context_Request
*
* [description]
*
* This signal allows an application to dynamically modify the
* context array.
*
* [parameters]
*
* array('request' => $request,
* 'context' => array());
*
*/
Pluf_Signal::send('Pluf_Template_Context_Request::construct',
'Pluf_Template_Context_Request', $params);
$this->_vars = new Pluf_Template_ContextVars($params['context']);
}
}

View File

@@ -0,0 +1,43 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Special array where the keyed indexes can be accessed as properties.
*/
class Pluf_Template_ContextVars extends ArrayObject
{
function __get($prop)
{
return (isset($this[$prop])) ? $this[$prop] : '';
}
function __set($prop, $value)
{
$this[$prop] = $value;
}
function __toString()
{
return var_export($this, true);
}
}

View File

@@ -0,0 +1,49 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* A string already escaped to display in a template.
*/
class Pluf_Template_SafeString
{
public $value = '';
function __construct($mixed, $safe=false)
{
if (is_object($mixed) and 'Pluf_Template_SafeString' == get_class($mixed)) {
$this->value = $mixed->value;
} else {
$this->value = ($safe) ? $mixed : htmlspecialchars($mixed, ENT_COMPAT, 'UTF-8');
}
}
function __toString()
{
return $this->value;
}
public static function markSafe($string)
{
return new Pluf_Template_SafeString($string, true);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
class Pluf_Template_Tag
{
protected $context;
/**
* Constructor.
*
* @param Context Context object (null)
*/
function __construct($context=null)
{
$this->context = $context;
}
}

View File

@@ -0,0 +1,49 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Assign a permission to a template variable.
*
* This template tag is available by default under the name
* aperm. Example of usage:
*
* <code>
* {aperm 'can_drive', $user, 'MyApp.can_drive'}
* {aperm 'can_drive_big_car', $user, 'MyApp.can_drive', $bigcar}
* {if $can_drive}Can drive!{/if}
* </code>
*
*/
class Pluf_Template_Tag_APerm extends Pluf_Template_Tag
{
/**
* @param string Variable to get the permission
* @param Pluf_User
* @param string Permission string
* @param mixed Optional Pluf_Model if using row level permission (null)
*/
function start($var, $user, $perm, $object=null)
{
$this->context->set($var, $user->hasPerm($perm, $object));
}
}

View File

@@ -0,0 +1,51 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Display a configuration variable.
*
* It filter to prevent some configuration variables to be displayed.
*
*/
class Pluf_Template_Tag_Cfg extends Pluf_Template_Tag
{
/**
* Display the configuration variable.
*
* @param string Configuration variable.
* @param mixed Default value to return display ('').
* @param bool Display the value (true).
* @param string Prefix to set to the variable if not displayed ('cfg_').
*/
function start($cfg, $default='', $display=true, $prefix='cfg_')
{
if ($cfg != 'secret_key'
or 0 !== strpos($cfg, 'db_')) {
if ($display) {
echo Pluf::f($cfg, $default);
} else {
$this->context->set($prefix.$cfg, Pluf::f($cfg, $default));
}
}
}
}

View File

@@ -0,0 +1,153 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2010 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Template tag <code>cycle</code>.
*
* Cycle among the given strings or variables each time this tag is
* encountered.
*
* Within a loop, cycles among the given strings each time through the loop:
*
* <code>
* {foreach $some_list as $obj}
* <tr class="{cycle 'row1', 'row2'}">
* ...
* </tr>
* {/foreach}
* </code>
*
* You can use variables, too. For example, if you have two
* template variables, $rowvalue1 and $rowvalue2, you can
* cycle between their values like this:
*
* <code>
* {foreach $some_list as $obj}
* <tr class="{cycle $rowvalue1, $rowvalue2}">
* ...
* </tr>
* {/foreach}
* </code>
*
* You can mix variables and strings:
*
* <code>
* {foreach $some_list as $obj}
* <tr class="{cycle 'row1', rowvalue2, 'row3'}">
* ...
* </tr>
* {/foreach}
* </code>
*
* In some cases you might want to refer to the next value of a cycle
* from outside of a loop. To do this, just group the arguments into
* an array and give the {cycle} tag name last, like this:
*
* <code>
* {cycle array('row1', 'row2'), 'rowcolors'}
* </code>
*
* From then on, you can insert the current value of the cycle
* wherever you'd like in your template:
*
* <code>
* <tr class="{cycle $rowcolors}">...</tr>
* <tr class="{cycle $rowcolors}">...</tr>
*
* Based on concepts from the Django cycle template tag.
*/
class Pluf_Template_Tag_Cycle extends Pluf_Template_Tag
{
/**
* @see Pluf_Template_Tag::start()
* @throws InvalidArgumentException If no argument is provided.
*/
public function start()
{
$nargs = func_num_args();
if (1 > $nargs) {
throw new InvalidArgumentException(
'`cycle` tag requires at least one argument'
);
}
$result = '';
list($key, $index) = $this->_computeIndex(func_get_args());
switch ($nargs) {
# (array or mixed) argument
case 1:
$arg = func_get_arg(0);
if (is_array($arg)) {
$result = $arg[$index % count($arg)];
} else {
$result = $arg;
}
break;
# (array) arguments, (string) assign
case 2:
$args = func_get_args();
if (is_array($args[0])) {
$last = array_pop($args);
if (is_string($last) && '' === $this->context->get($last)) {
$value = Pluf_Utils::flattenArray($args[0]);
$this->context->set($last, $value);
list($assign_key, $assign_index) = $this->_computeIndex(array($value));
$result = $value[0];
}
break;
}
# considers all the arguments as a value to use in the cycle
default:
$args = Pluf_Utils::flattenArray(func_get_args());
$result = $args[$index % count($args)];
break;
}
echo Pluf_Template::markSafe((string) $result);
}
/**
* Compute an index for the given array.
*
* @param array
* @return array A array of two elements: key and index.
*/
protected function _computeIndex($args)
{
if (!isset($this->context->__cycle_stack)) {
$this->context->__cycle_stack = array();
}
$key = serialize($args);
$this->context->__cycle_stack[$key] = (array_key_exists($key, $this->context->__cycle_stack)) ?
1 + $this->context->__cycle_stack[$key] :
0;
$index = $this->context->__cycle_stack[$key];
return array($key, $index);
}
}

View File

@@ -0,0 +1,79 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2010 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Template tag <code>firstof</code>.
*
* Outputs the first variable passed that is not false, without escaping.
* Outputs nothing if all the passed variables are false.
*
* Sample usage:
*
* <code>{firstof array($var1, $var2, $var3)}</code>
*
* This is equivalent to:
*
* <code>
* {if $var1}
* {$var1|safe}
* {elseif $var2}
* {$var2|safe}
* {elseif $var3}
* {$var3|safe}
* {/if}
* </code>
*
* You can also use a literal string as a fallback value in case all
* passed variables are false:
*
* <code>{firstof array($var1, $var2, $var3), "fallback value"}</code>
*
* Based on concepts from the Django firstof template tag.
*/
class Pluf_Template_Tag_Firstof extends Pluf_Template_Tag
{
/**
* @see Pluf_Template_Tag::start()
* @param string $token Variables to test.
* @param string $fallback Literal string to used when all passed variables are false.
* @throws InvalidArgumentException If no argument is provided.
*/
public function start($tokens = array(), $fallback = null)
{
if (!is_array($tokens) || 0 === count($tokens)) {
throw new InvalidArgumentException(
'`firstof` tag requires at least one array as argument'
);
}
$result = (string) $fallback;
foreach ($tokens as $var) {
if ($var) {
$result = Pluf_Template::markSafe((string) $var);
break;
}
}
echo $result;
}
}

View File

@@ -0,0 +1,41 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
class Pluf_Template_Tag_MediaUrl extends Pluf_Template_Tag
{
function start($file='')
{
echo Pluf_Template_Tag_MediaUrl::url($file);
}
public static function url($file='')
{
if ($file !== '' && Pluf::f('last_update_file', false) &&
false !== ($last_update = Pluf::fileExists(Pluf::f('last_update_file')))
) {
$file = $file.'?'.substr(md5(filemtime($last_update)), 0, 5);
}
return Pluf::f('url_media', Pluf::f('app_base').'/media').$file;
}
}

View File

@@ -0,0 +1,42 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Display the messages for the current user.
*/
class Pluf_Template_Tag_Messages extends Pluf_Template_Tag
{
function start($user)
{
if (is_object($user) && !$user->isAnonymous()) {
$messages = $user->getAndDeleteMessages();
if (count($messages) > 0) {
echo '<div class="user-messages">'."\n".'<ul>'."\n";
foreach ($messages as $m) {
echo '<li>'.$m.'</li>';
}
echo '</ul></div>';
}
}
}
}

View File

@@ -0,0 +1,89 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Custom tag example.
*/
class Pluf_Template_Tag_Mytag extends Pluf_Template_Tag
{
/**
* Perform some operations at the opening of the
* tag {mytag 'param1', 'param2'}.
*
* You can access the template context through
* $this->context
*/
function start($param1, $param2)
{
echo 'start of tag mytag:<br />';
echo '$this->context[mytag]: '
.$this->context->get('mytag').'<br />';
}
/**
* Generate some valid PHP code to be put in the template.
*
* The code generated by this function is included in the
* template just after the call to $this->start() if the start()
* method is implemented.
*
* You cannot access the template context but you can write
* code that is modifying it through $t
*/
function genStart()
{
return '$t->set(\'mytag\', \'hello world!\');';
}
/**
* Perform some operations at the closing of the
* tag {/mytag 'param1'}.
*
* You can access the template context through
* $this->context
*/
function end($param1)
{
echo 'end of tag mytag:<br />';
echo '$this->context[mytag]: '
.$this->context->get('mytag').'<br />';
}
/**
* Generate some valid PHP code to be put in the template.
*
* The code generated by this function is included in the
* template just after the call to $this->end() if the end()
* method is implemented.
*
* You cannot access the template context but you can write
* code that is modifying it through $t
*/
function genEnd()
{
// Cleaning :)
return '$t->set(\'mytag\', \'\');';
}
}

View File

@@ -0,0 +1,46 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2010 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Template tag <code>now</code>.
*
* Displays the date, formatted according to the given string.
*
* Sample usage:
* <code>It is {now "jS F Y H:i"}</code>
*
* Based on concepts from the Django now template tag.
*
* @link http://php.net/date for all the possible values.
*/
class Pluf_Template_Tag_Now extends Pluf_Template_Tag
{
/**
* @see Pluf_Template_Tag::start()
* @param string $token Format to be applied.
*/
public function start($token)
{
echo date($token);
}
}

View File

@@ -0,0 +1,165 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2010 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Template tag <code>regroup</code>.
*
* Regroup a list of alike objects by a common attribute.
*
* This complex tag is best illustrated by use of an example:
* say that people is a list of people represented by arrays with
* first_name, last_name, and gender keys:
*
* <code>
* $people = array(
* array('first_name' => 'George',
* 'last_name' => 'Bush',
* 'gender' => 'Male'),
* array('first_name' => 'Bill',
* 'last_name' => 'Clinton',
* 'gender' => 'Male'),
* array('first_name' => 'Margaret',
* 'last_name' => 'Thatcher',
* 'gender' => 'Female'),
* array('first_name' => 'Condoleezza',
* 'last_name' => 'Rice',
* 'gender' => 'Female'),
* array('first_name' => 'Pat',
* 'last_name' => 'Smith',
* 'gender' => 'Unknow'),
* );
* </code>
*
* ...and you'd like to display a hierarchical list that is ordered by
* gender, like this:
*
* <ul>
* <li>Male:
* <ul>
* <li>George Bush</li>
* <li>Bill Clinton</li>
* </ul>
* </li>
* <li>Female:
* <ul>
* <li>Margaret Thatcher</li>
* <li>Condoleezza Rice</li>
* </ul>
* </li>
* <li>Unknown:
* <ul>
* <li>Pat Smith</li>
* </ul>
* </li>
* </ul>
*
* You can use the {regroup} tag to group the list of people by
* gender. The following snippet of template code would accomplish this:
*
* <code>
* {regroup $people, 'gender', 'gender_list'}
* <ul>
* {foreach $gender_list as $gender}
* <li>{$gender.grouper}:
* <ul>
* {foreach $gender.list as $item}
* <li>{$item.first_name} {$item.last_name}</li>
* {/foreach}
* </ul>
* </li>
* {/foreach}
* </ul>
* </code>
*
* Let's walk through this example. {regroup} takes three arguments:
* the object (array or instance of Pluf_Model or any object)
* you want to regroup, the attribute to group by,and the name of the
* resulting object. Here, we're regrouping the people list by the
* gender attribute and calling the result gender_list. The result is
* assigned in a context varible of the same name $gender_list.
*
* {regroup} produces a instance of ArrayObject (in this case, $gender_list)
* of group objects. Each group object has two attributes:
*
* <ul>
* <li>grouper -- the item that was grouped by
* (e.g., the string "Male" or "Female").</li>
* <li>list -- an ArrayObject of all items in this group
* (e.g., an ArrayObject of all people with gender='Male').</li>
* </ul>
*
* Note that {regroup} does not order its input!
*
* Based on concepts from the Django regroup template tag.
*/
class Pluf_Template_Tag_Regroup extends Pluf_Template_Tag
{
/**
* @see Pluf_Template_Tag::start()
* @param mixed $data The object to group.
* @param string $by The attribute ti group by.
* @param string $assign The name of the resulting object.
* @throws InvalidArgumentException If no argument is provided.
*/
public function start($data, $by, $assign)
{
$grouped = array();
$tmp = array();
foreach ($data as $group) {
if (is_object($group)) {
if (is_subclass_of($group, 'Pluf_Model')) {
$raw = $group->getData();
if (!array_key_exists($by, $raw)) {
continue;
}
} else {
$ref = new ReflectionObject($group);
if (!$ref->hasProperty($by)) {
continue;
}
}
$key = $group->$by;
$list = $group;
} else {
if (!array_key_exists($by, $group)) {
continue;
}
$key = $group[$by];
$list = new ArrayObject($group, ArrayObject::ARRAY_AS_PROPS);
}
if (!array_key_exists($key, $tmp)) {
$tmp[$key] = array();
}
$tmp[$key][] = $list;
}
foreach ($tmp as $key => $list) {
$grouped[] = new ArrayObject(array('grouper' => $key,
'list' => $list),
ArrayObject::ARRAY_AS_PROPS);
}
$this->context->set(trim($assign), $grouped);
}
}

View File

@@ -0,0 +1,18 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of ConfOrganizer, a conference manager application.
# Copyright (C) 2006 Loic d'Anterroches.
#
# ***** END LICENSE BLOCK ***** */
class Pluf_Template_Tag_RmediaUrl extends Pluf_Template_Tag
{
function start($var, $file='')
{
$this->context->set($var,
Pluf_Template_Tag_MediaUrl::url($file));
}
}

View File

@@ -0,0 +1,36 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
/**
* Assign the url to a template variable.
*/
class Pluf_Template_Tag_Rurl extends Pluf_Template_Tag
{
function start($var, $view, $params=array(), $get_params=array())
{
$this->context->set($var,
Pluf_HTTP_URL_urlForView($view, $params, $get_params));
}
}

View File

@@ -0,0 +1,32 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
#
# Plume Framework 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.
#
# Plume Framework 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 program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
class Pluf_Template_Tag_Url extends Pluf_Template_Tag
{
function start($view, $params=array(), $get_params=array())
{
echo Pluf_HTTP_URL_urlForView($view, $params, $get_params);
}
}