Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

{cache} {/cache}
Goto page Previous  1, 2, 3, 4  Next
 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Feature Requests
View previous topic :: View next topic  
Author Message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Mon Nov 10, 2003 9:05 pm    Post subject: Reply with quote

I updated the code again to reflect messju's suggestion regarding an early bailout. I realize why I switched away from this originally: Smarty ignores what you pass back to it during the first iteration of the block--it is only concerned if it should continue processing the block. Thus, to get output for that case, I had to use echo which I typically wouldn't want to do in a plugin function. Still, this works and it is probably easier to see what is happening now.

Still looking into atu's issue regarding sub-template regeneration.

EDIT: This really isn't the greatest solution because it doesn't capture the sub-template code -- just the results. Is there a way to efficiently get the source code at runtime? Alternatively, is there a way to convert this block function into a compile time function?
Back to top
View user's profile Send private message
andre
Smarty Pro


Joined: 23 Apr 2003
Posts: 164
Location: Karlsruhe, Germany

PostPosted: Tue Nov 11, 2003 12:51 pm    Post subject: Reply with quote

Mhmm... this is really a nice solution, boots Shocked
This is possibly very helpful for a problem I'm just investigation in my own application. Thanks Wink
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Tue Nov 11, 2003 3:36 pm    Post subject: Reply with quote

@andre: really it reminds me of this post (and your follow-up) from the nice discussion that came out of your original cache modification ideas for Smarty. I can't find it now, but I seem to recall that somewhere in the discussion the topic of using cache id identifiers within the template (much as atu suggests) was brought up and that this was seen as a bad thing as it forces the designer to consider what should properly be developer issues.

I see the idea of subtemplates as useful--but the cache grouping info should be settable outside of the template itself. The first thing is that the caching and the subtemplate concepts ought be separate ideas and the second thing is that the developer should have a way to define cache categories that the designer could then refer to but whose settings were solely in control of the developer. I think this could lead to some interesting opportunities. For example, I would more easily be able to determine regeneration of a subtemplate because I would essentially have a lookup table I could refer to before I open the template. I could also store the separate cache_ids used in a cached template in the cache_info header of the cache image so as to satisfy regeneration of subtemplate portions.

Further, I really think my code needs to be updated to write actual subtemplate code (not results) or that someone should have a stab at messju's idea (which should work that way) or perhaps suggest an alternative.


Last edited by boots on Wed Nov 12, 2003 2:51 am; edited 1 time in total
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Wed Nov 12, 2003 1:01 am    Post subject: Reply with quote

As a quick follow-up, messju made a brilliant suggestion on IRC--register the plugin as non-cacheable. That way it will work like insert (with associated performance cost) but would actually still cache since the plugin explicitly caches its data. I don't think it gets simpler than that Smile
EDIT: I haven't tested this hypothesis yet, though I am starting to wonder if it will indeed work as a consequence of the fact that I store results and not template source in the subtemplates. If anyone tests this, please post your findings.
EDIT2: messju believes this will work. I'm going to let others continue this for now Smile


On-the-other-hand, I think that if you didn't cache the outer template at all, you would get similar results.

Further, in the end, I don't think this is a caching issue as much as I see it as introducing sub-templates. I belieive atu rightly pointed out in his original post that the existing caching scheme would work fine if only he used separate templates.

On a more trivial note, I've had second thoughts about the name for the plugin. I chose "sec" to be short for "section" which is obviously already taken. I think it is better called "sub" or "subtpl" or "subcache" or something like that.

Cheers!
Back to top
View user's profile Send private message
messju
Administrator


Joined: 16 Apr 2003
Posts: 3336
Location: Oldenburg, Germany

PostPosted: Mon Nov 17, 2003 10:31 am    Post subject: Reply with quote

boots wrote:
EDIT: I haven't tested this hypothesis yet, though I am starting to wonder if it will indeed work as a consequence of the fact that I store results and not template source in the subtemplates. If anyone tests this, please post your findings.
EDIT2: messju believes this will work. I'm going to let others continue this for now Smile


i didn't look that close at the code. imho it does not work as it is now. i didn't notice you write a template and fetch it afterwards. you are correct: now the output would be parsed a second time in the fetch()-call. that's not desirable and sometimes even dangerous. instead of writing to the templates-dir and fetch()-ing one should use write_cache_file() to write the contents. but that may cause average to major headaches regardings inserts and non-cached-plugins.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Mon Nov 17, 2003 5:44 pm    Post subject: Reply with quote

messju wrote:
instead of writing to the templates-dir and fetch()-ing one should use write_cache_file() to write the contents. but that may cause average to major headaches regardings inserts and non-cached-plugins.

ha ha -- "average to major headaches" -- hilarious! True, though. Without the source template being available, there is no way to independantly regenerate the cache for the generously named "subtemplates". The only way I can see around this is to chop the template into source bits. I've hinted that I don't see that as trivial--but something that may be possble using the approach messju suggested at the start of this thread.

I'm glad that this came out because the last time I discussed this on IRC with messju, I was completely confused as I felt the code was faulty from the start but messju somehow convinced me that it would work as-is Wink

I do think that there are certain cases where there may be merit for the solution I proposed but I will let others decide its fate. FWIW, below is a code update that incorporates changes I received from messju to meet the concerns in his last post. I am posting it here instead of in my original post since it no longer operates in the same way. Indeed, in some ways this plugin is utterly superfluous; however, if you intend to cache a static content piece (or "clip") it may have some merit for you. I have changed the name for this plugin to {clipcache} both to differentiate it from {sec} and to better reflect its purpose.
[php:1:e6d2330acc]/**
* block.clipcache.php
*
* Create a cache image for a "clip" from a template.
*
* @author boots, messju
* @version 0.1.5 2003-NOV-17
* @since 2003-NOV-10
* @see http://www.phpinsider.com/smarty-forum/viewtopic.php?p=5902#5902
*
* ----------------------------------------------------------------------------
* @param group required specify cache build group
* @param id required id within the cache build group
* @param ttl required time to live for template part/group
* @param template required expects $smarty.template
*/
function smarty_block_clipcache($params, $content, &$smarty, &$repeat)
{
// validation
extract ($params);
foreach (array('id', 'group', 'template', 'ttl') as $required) {
if (!isset($$required)) {
$smarty->trigger_error("clipcache block: $$required param missing. Aborted.");
return;
}
}

$name = "$template.$id"; // clip cache target name

if (!isset($content)) {
// first iteration through block, so no content was processed
// try and read from the cache (if succeeds, do not re-enter block)
$_params = array(
'tpl_file' => $name
, 'cache_id' => $group
, 'compile_id' => $smarty->compile_id
);
require_once SMARTY_DIR.'core'.DIRECTORY_SEPARATOR.'core.read_cache_file.php';
$_caching = $smarty->caching;
$smarty->caching = 2; // cache by individual lifetime
if (@smarty_core_read_cache_file($_params, $smarty)) {
$repeat = false;
echo $_params['results']; // we do this since we can not use return here
}
$smarty->caching = $_caching;

} else {
// cache-miss: cache the clip

// save smarty environment as proposed by calling template
$_ttl = $smarty->cache_lifetime;
$smarty->cache_lifetime = $ttl;
$_caching = $smarty->caching;
$smarty->caching = 2;
$_id = $smarty->cache_id; /* note: cache_id needs to be saved as it can differ from id used for outer template */

// write the cache image
$_params = array(
'tpl_file' => $name
, 'cache_id' => $group
, 'compile_id' => $smarty->compile_id
, 'results' => $content
);
require_once SMARTY_DIR.'core'.DIRECTORY_SEPARATOR.'core.write_cache_file.php';
@smarty_core_write_cache_file($_params, $smarty);

// restore smarty environment as proposed by calling template
$smarty->caching = $_caching;
$smarty->cache_lifetime = $_ttl;
$smarty->cache_id = $_id;

return $content;
}
}[/php:1:e6d2330acc]
This is completely untested by me. Thanks once again to messju for his suggestions and efforts Smile
Back to top
View user's profile Send private message
messju
Administrator


Joined: 16 Apr 2003
Posts: 3336
Location: Oldenburg, Germany

PostPosted: Mon Nov 17, 2003 6:08 pm    Post subject: Reply with quote

@boots:

boots wrote:
[php:1:56be25b47d]$_id = $smarty->cache_id; /* note: cache_id needs to be saved as it can differ from id used for outer template */ [/php:1:56be25b47d]


to my knowledge there is no property $smarty->cache_id, so there is no need to save it.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Mon Nov 17, 2003 6:53 pm    Post subject: Reply with quote

messju wrote:
to my knowledge there is no property $smarty->cache_id, so there is no need to save it.

I thought you'd catch that, messju Smile I was under the impression that cache_id worked like compile_id, but you would certainly know more about that than I.

I won't bother to update the code at this point since it is inconsequential.
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Fri Apr 08, 2005 8:57 am    Post subject: {clipcache} improved Reply with quote

May 17, 2006 EDIT: THIS POST HAS BEEN SUPERCEDED. Code is now at http://smarty.incutio.com/?page=ClipCache

May 3, 2006 EDIT: new version 0.1.6 -- minor bug fixes. Still beta Smile
Sep 22, 2005 EDIT: new version 0.1.5 -- directory writing issues should be resolved. Expects that use_sub_dirs=true. Still beta Smile
Sep 22, 2005 EDIT: new version 0.1.4 -- Much improved behviour as it now writes template fragments to a required subdirectory 'clipcache' in your compile directory. You must ensure that the directory exists and is writable. Still beta as another update is needed to support template subdirectories (eg: foo/bar.tpl)
July 9, 2005 EDIT: new version 0.1.3 -- minor updates, but still beta.

note: Requires Smarty 2.6.10 or later.

Well, its been a long time but here is an update. This version of the code is more along the lines of messju's original proposal. This particular incantination is built from a prefilter and a function plugin that is registered as non-cached.

Features, Improvements
    * Main template can be cached or not;
    * The cache_lifetime of the main template need not be less than the cache lifetimes (ttl's) of the clipcache's;
    * Writes actual template source to a separate template file (filename#id);
    * No longer need to specify the template name.
Caveats
    * Not resource safe;
    * Does not support multiple template_dirs.
The {clipcache} blocks are essentially "removed" from the original template in that the compile file for the template no longer includes the clipcache code directly but rather fetch()'s it from the clipcache's own template file which is created during the prefilter stage. This should imply that clipcache blocks can still see the scope of the original parent; unfortunately, since they are fetched, they behave like an {include}'d template and therefore have local scopes. Assignments made in a {clipcache} block aren't seen in the original template even though they both originate from the same file. Its always something Smile

Notes

You can use the {include_clipcache} function without the prefilter if you want to simply use this as a method to have private caching of your included templates (which the core {include} does not support). eg:
Code:
{include_clipcache file="template.tpl" cache_id="cache|group" cache_lifetime=$cache_lifetime}
Note that the {include_clipcache} tag uses different parameters than the prefilter {clipcache} and is more in line with the standard Smarty::display().

Some of you will recall that Andre & Freestyler combined to come up with some variations of a cache handler that works well with {clipcache} setups. I have updated that code to work with eAccelerator. The relevant thread is here.

Installation

Put the plugins in your $smarty->plugins_dir folder. The optional extended Smarty class (Smarty_ClipCache) has methods to register and unregister clipcache features.

Sample Code

example.php[php:1:c9f0d92ac8]<?php
include 'Smarty.class.php';
include 'Smarty_ClipCache.class.php';
$smarty = new Smarty_ClipCache();
// configure to suit your setup

$smarty->register_clipcache();
$smarty->caching = 1;
$smarty->cache_lifetime = 20;
$smarty->display('example.tpl');
?>[/php:1:c9f0d92ac8]example.tpl
Code:
<h2>Very Simple Example</h2>

{**
 * Plain Jane static content. As usual, this will be refreshed at the frequency
 * specified for this template. It should be noted that due to the way the caching
 * system works, refresh frequences will be approximate and typically slightly
 * greater than the specified amount. This means that template refreshes between
 * clips and the main template won't be lock-step.
 *}
<div>
Timestamp 1: {$smarty.now|date_format:"%Y-%m-%d %H:%M:%S"}

This first timestamp will refresh every 20 seconds
which is the cache_lifetime of this template.
</div>

{**
 * Create a clipcache block.
 *
 * A clipcache block has its own private refresh frequency and cache id. To
 * enable this, the block is written to a separate template file at compile time
 * which is then compiled separately.
 *
 * Note that the following parameters are required:
 * @id unique identifier for the block within this template
 * @group cache group to associate with the block
 * @ttl time-to-live for the block, in seconds
 *
 * Also note that the close tag must be a duplicate of the open tag!
 * Sorry, I'm too lazy to fix that for now.
 *}
{clipcache id=test group=foo ttl=5}
<div>
Timestamp 2: {$smarty.now|date_format:"%Y-%m-%d %H:%M:%S"}

This clipcache block timestamp is refreshed every 5 seconds.
</div>

{**
 * the following is a nested clipcache block. Tread carefully!
 *}
{clipcache id=foo group="foo|foo" ttl=10}
<div>
Timestamp 3: {$smarty.now|date_format:"%Y-%m-%d %H:%M:%S"}

This nested clipcache block timestamp is refreshed every 10 seconds.
</div>
{/clipcache id=foo group="foo|foo" ttl=10}

{/clipcache id=test group=foo ttl=5}

Extended Smarty Class[php:1:c9f0d92ac8]<?php

/**
* Smarty Addon
* @package Smarty
*/

/**
* Smarty_ClipCache (Smarty)
*
* Extended Smarty class to manage {clipache} plugin functionality.
*
* @file Smarty_ClipCache.class.php
* @version 0.1.6 2006-May-03
* @since 2005-APR-08
*
* @author boots {jayboots ~ yahoo com}
* @copyright brainpower, boots, 2004-2006
* @license LGPL 2.1
* @link http://www.phpinsider.com/smarty-forum/viewtopic.php?p=19733#19733
*/
class Smarty_ClipCache extends Smarty
{
function Smarty_ClipCache()
{
$this->Smarty();
}

function register_clipcache()
{
$this->load_filter( 'pre', 'clipcache' );
require_once $this->_get_plugin_filepath( 'function', 'include_clipcache' );
$this->register_function( 'include_clipcache', 'smarty_function_include_clipcache', false );
$write_path = rtrim( $this->compile_dir, "/\\" ) . DIRECTORY_SEPARATOR . 'clipcache' . DIRECTORY_SEPARATOR;
$this->template_dir = (array)$this->template_dir;
if ( !in_array( $write_path, $this->template_dir ) ) {
$this->template_dir[] = $write_path;
}
}

function unregister_clipcache()
{
$this->unregister_prefilter( 'clipcache' );
$this->unregister_function( 'include_clipcache' );
}
}
[/php:1:c9f0d92ac8]

The Plugins

prefilter.clipcache.php [php:1:c9f0d92ac8]<?php

/**
* Smarty plugin
* @package Smarty
* @subpackage plugins
*/

/**
* Smarty clipcache prefilter plugin
*
* Clip template source into a new file and replace with a call for isolated caching
*
* @file prefilter.clipcache.php
* @version 0.1.6 2006-May-03
* @since 2005-APR-08
*
* @author boots {jayboots ~ yahoo com}
* @copyright brainpower, boots, 2004-2006
* @license LGPL 2.1
* @link http://www.phpinsider.com/smarty-forum/viewtopic.php?p=19733#19733
*
* @param string $source
* @param Smarty_Compiler $compiler
*
* This filter grabs compiler blocks and observes the tag following attributes
*
* #param id required unique id of clipcache block within template
* #param group required specify cache build group
* #param ttl required time to live for template part/group
* #param ldelim optional specify the left delimiter to use for included content
* #param rdelim optional specify the right delimiter to use for included content
*/
function smarty_prefilter_clipcache($source, &$compiler)
{
// setup
require_once $compiler->_get_plugin_filepath( 'outputfilter', 'trimwhitespace' );
$ld = $compiler->left_delimiter;
$rd = $compiler->right_delimiter;
$search = "{$ld}\s*clipcache\s+(.*?)\s*{$rd}(.*){$ld}\s*/clipcache\s+\\1{$rd}";

// Pull out the clip blocks
preg_match_all( "!$search!is", $source, $clip_blocks );
$i=0;
$replacements = array();

foreach ( $clip_blocks[1] as $tag_attrs ) {
$params = $compiler->_parse_attrs( $tag_attrs );

foreach ( array( 'group'=>'cache_id', 'id'=>'id', 'ttl'=>'cache_lifetime' ) as $required=>$mapto ) {

if ( !array_key_exists( $required, $params ) ) {
$compiler->_syntax_error( "clipcache: '$required' param missing. Aborted.", E_USER_WARNING );

return;

} else {
$$mapto = $params[$required];

if ( substr( $$mapto, 0, 1 ) == "'" ) {
$$mapto = substr( $$mapto, 1, strlen( $$mapto ) - 2 );
}
}
}

foreach ( array( 'rdelim'=>$rd, 'ldelim'=>$ld ) as $optional=>$default ) {
${"_{$optional}"} = $default;
$$optional = ( array_key_exists( $optional, $params ) )
? substr( $params[$optional], 1, strlen( $params[$optional] ) - 2 )
: $default;
}

// write the clip block file source template
$write_path = rtrim( $compiler->compile_dir, "/\\" ) . DIRECTORY_SEPARATOR;

$file_name = $compiler->_current_file.'#' . $id;
require_once SMARTY_CORE_DIR . 'core.write_file.php';
smarty_core_write_file( array( 'filename'=>$write_path . 'clipcache' . DIRECTORY_SEPARATOR . $file_name, 'contents'=>$clip_blocks[2][$i++], 'create_dirs'=>true ), $compiler );

// prepare replacement source for the clip block
if ( $ldelim == $ld && $rdelim == $rd ) {
$replacements[] = $ld . 'include_clipcache file="' . $file_name . '" cache_id="' . $cache_id . '" cache_lifetime=' . $cache_lifetime . $rd;

} else {
$replacements[] = $ld . 'include_clipcache file="' . $file_name . '" cache_id="' . $cache_id . '" cache_lifetime=' . $cache_lifetime . ' ldelim="' . $ldelim . '" rdelim="' . $rdelim.'"' . $rd;
}
}

// replace clip blocks
$source = preg_replace( "!$search!is", '@@@SMARTY:CLIPCACHE@@@', $source );
smarty_outputfilter_trimwhitespace_replace( "@@@SMARTY:CLIPCACHE@@@", $replacements, $source );

return $source;
}
[/php:1:c9f0d92ac8]function.include_clipcache.php[php:1:c9f0d92ac8]<?php

/**
* Smarty plugin
* @package Smarty
* @subpackage plugins
*/

/**
* Smarty {include_clipcache} function plugin
*
* Includes a template using private caching parameters. Must be registered as non-caching.
*
* @file function.include_clipcache.php
* @version 0.1.6 2006-May-03
* @since 2005-APR-08
*
* @author boots {jayboots ~ yahoo com}
* @copyright brainpower, boots, 2004-2006
* @license LGPL 2.1
* @link http://www.phpinsider.com/smarty-forum/viewtopic.php?p=19733#19733
*
* @param array $params
* @param Smarty $smarty
*
* This function observes the following tag attributes (in $params):
*
* #param file required template file
* #param cache_id required specify cache build group
* #param cache_lifetime required time to live for template part/group
* #param ldelim optional specify the left delimiter to use for included content
* #param rdelim optional specify the right delimiter to use for included content
*/
function smarty_function_include_clipcache($params, &$smarty)
{
// validation
foreach ( array( 'cache_id', 'file', 'cache_lifetime' ) as $required ) {

if ( !array_key_exists( $required, $params ) ) {
$smarty->trigger_error( "include_clipcache: '$required' param missing. Aborted.", E_USER_WARNING );

return;
}
}

// handle optional delimiters
foreach ( array( 'rdelim'=>$smarty->right_delimiter, 'ldelim'=>$smarty->left_delimiter) as $optional=>$default ) {
${"_{$optional}"} = $default;
$$optional = ( array_key_exists( $optional, $params ) )
? $params[$optional]
: $default;
}

// save smarty environment as proposed by calling template
$_cache_lifetime = $smarty->cache_lifetime;
$smarty->cache_lifetime = $params['cache_lifetime'];
$_caching = $smarty->caching;
$smarty->caching = 2;
$smarty->left_delimiter = $ldelim;
$smarty->right_delimiter = $rdelim;

// run the requested clipcache template
$content = $smarty->fetch($params['file'], $params['cache_id']);

// restore smarty environment as proposed by calling template
$smarty->caching = $_caching;
$smarty->cache_lifetime = $_cache_lifetime;
$smarty->left_delimiter = $_ldelim;
$smarty->right_delimiter = $_rdelim;
return $content;
}
[/php:1:c9f0d92ac8]

There is also an experimental compiler version, but this one is slightly cleaner. EDIT (2005-SEP-22): the compiler version is now abandoned.


Last edited by boots on Thu May 18, 2006 7:25 am; edited 9 times in total
Back to top
View user's profile Send private message
micha80
Smarty Rookie


Joined: 31 Aug 2005
Posts: 7
Location: Berlin

PostPosted: Wed Sep 21, 2005 11:37 am    Post subject: Reply with quote

hello @ all,

i'am a new one to smarty but got the problem you have diskussed here. so i decided to solve the problem with the last suggestion. but i got an error now.

Code:
Fatal error: Call to undefined function: file_put_contents() in /usr/local/smarty/plugins/prefilter.clipcache.php on line 60


maybe you know this and could help me to fix it. i've searched all smarty files for this function but i wasn't lucky. Wink maybe there is a spelling error or its an own programmed function or something else but i can't get it by myself.

thx a lot, micha
Back to top
View user's profile Send private message
messju
Administrator


Joined: 16 Apr 2003
Posts: 3336
Location: Oldenburg, Germany

PostPosted: Wed Sep 21, 2005 11:40 am    Post subject: Reply with quote

file_put_contents() is only available in php 5.0 and later.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
micha80
Smarty Rookie


Joined: 31 Aug 2005
Posts: 7
Location: Berlin

PostPosted: Wed Sep 21, 2005 11:52 am    Post subject: Reply with quote

ok, thx for fast answer...

what does this function do? does it only create a file with the parameter "$file_name" and put in the contents from "$clip_blocks[2][$i++]"?

can i replace this with a PHP4 way?

are there other php5 function i have to replace for php4?

thx, micha
Back to top
View user's profile Send private message
messju
Administrator


Joined: 16 Apr 2003
Posts: 3336
Location: Oldenburg, Germany

PostPosted: Wed Sep 21, 2005 12:14 pm    Post subject: Reply with quote

it's documented @ http://php.net/file_put_contents
Back to top
View user's profile Send private message Send e-mail Visit poster's website
micha80
Smarty Rookie


Joined: 31 Aug 2005
Posts: 7
Location: Berlin

PostPosted: Wed Sep 21, 2005 12:30 pm    Post subject: Reply with quote

sorry, but i have one more question. where did you define the path for the file?
i only see that you pass the filename but how does the function know where to save the file?

thx, micha
Back to top
View user's profile Send private message
messju
Administrator


Joined: 16 Apr 2003
Posts: 3336
Location: Oldenburg, Germany

PostPosted: Wed Sep 21, 2005 1:08 pm    Post subject: Reply with quote

micha80 wrote:
where did you define the path for the file?


are you kidding? $file_name is assigned two lines above the call to file_put_contents().
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Feature Requests All times are GMT
Goto page Previous  1, 2, 3, 4  Next
Page 2 of 4

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP