mirror of
https://github.com/smarty-php/smarty.git
synced 2025-07-29 15:37:14 +02:00
Added licence file and demo folder
This commit is contained in:
165
COPYING.lib
Normal file
165
COPYING.lib
Normal file
@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
5
demo/configs/test.conf
Normal file
5
demo/configs/test.conf
Normal file
@ -0,0 +1,5 @@
|
||||
title = Welcome to Smarty!
|
||||
cutoff_size = 40
|
||||
|
||||
[setup]
|
||||
bold = true
|
30
demo/index.php
Normal file
30
demo/index.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* Example Application
|
||||
*
|
||||
* @package Example-application
|
||||
*/
|
||||
|
||||
require '../libs/Smarty.class.php';
|
||||
|
||||
$smarty = new Smarty;
|
||||
|
||||
//$smarty->force_compile = true;
|
||||
$smarty->debugging = true;
|
||||
$smarty->caching = true;
|
||||
$smarty->cache_lifetime = 120;
|
||||
|
||||
$smarty->assign("Name", "Fred Irving Johnathan Bradley Peppergill", true);
|
||||
$smarty->assign("FirstName", array("John", "Mary", "James", "Henry"));
|
||||
$smarty->assign("LastName", array("Doe", "Smith", "Johnson", "Case"));
|
||||
$smarty->assign("Class", array(array("A", "B", "C", "D"), array("E", "F", "G", "H"),
|
||||
array("I", "J", "K", "L"), array("M", "N", "O", "P")));
|
||||
|
||||
$smarty->assign("contacts", array(array("phone" => "1", "fax" => "2", "cell" => "3"),
|
||||
array("phone" => "555-4444", "fax" => "555-3333", "cell" => "760-1234")));
|
||||
|
||||
$smarty->assign("option_values", array("NY", "NE", "KS", "IA", "OK", "TX"));
|
||||
$smarty->assign("option_output", array("New York", "Nebraska", "Kansas", "Iowa", "Oklahoma", "Texas"));
|
||||
$smarty->assign("option_selected", "NE");
|
||||
|
||||
$smarty->display('index.tpl');
|
83
demo/plugins/cacheresource.apc.php
Normal file
83
demo/plugins/cacheresource.apc.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* APC CacheResource
|
||||
* CacheResource Implementation based on the KeyValueStore API to use
|
||||
* memcache as the storage resource for Smarty's output caching.
|
||||
* *
|
||||
*
|
||||
* @package CacheResource-examples
|
||||
* @author Uwe Tews
|
||||
*/
|
||||
class Smarty_CacheResource_Apc extends Smarty_CacheResource_KeyValueStore
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
// test if APC is present
|
||||
if (!function_exists('apc_cache_info')) {
|
||||
throw new Exception('APC Template Caching Error: APC is not installed');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read values for a set of keys from cache
|
||||
*
|
||||
* @param array $keys list of keys to fetch
|
||||
*
|
||||
* @return array list of values with the given keys used as indexes
|
||||
* @return boolean true on success, false on failure
|
||||
*/
|
||||
protected function read(array $keys)
|
||||
{
|
||||
$_res = array();
|
||||
$res = apc_fetch($keys);
|
||||
foreach ($res as $k => $v) {
|
||||
$_res[$k] = $v;
|
||||
}
|
||||
|
||||
return $_res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save values for a set of keys to cache
|
||||
*
|
||||
* @param array $keys list of values to save
|
||||
* @param int $expire expiration time
|
||||
*
|
||||
* @return boolean true on success, false on failure
|
||||
*/
|
||||
protected function write(array $keys, $expire = null)
|
||||
{
|
||||
foreach ($keys as $k => $v) {
|
||||
apc_store($k, $v, $expire);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove values from cache
|
||||
*
|
||||
* @param array $keys list of keys to delete
|
||||
*
|
||||
* @return boolean true on success, false on failure
|
||||
*/
|
||||
protected function delete(array $keys)
|
||||
{
|
||||
foreach ($keys as $k) {
|
||||
apc_delete($k);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove *all* values from cache
|
||||
*
|
||||
* @return boolean true on success, false on failure
|
||||
*/
|
||||
protected function purge()
|
||||
{
|
||||
return apc_clear_cache('user');
|
||||
}
|
||||
}
|
97
demo/plugins/cacheresource.memcache.php
Normal file
97
demo/plugins/cacheresource.memcache.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Memcache CacheResource
|
||||
* CacheResource Implementation based on the KeyValueStore API to use
|
||||
* memcache as the storage resource for Smarty's output caching.
|
||||
* Note that memcache has a limitation of 256 characters per cache-key.
|
||||
* To avoid complications all cache-keys are translated to a sha1 hash.
|
||||
*
|
||||
* @package CacheResource-examples
|
||||
* @author Rodney Rehm
|
||||
*/
|
||||
class Smarty_CacheResource_Memcache extends Smarty_CacheResource_KeyValueStore
|
||||
{
|
||||
/**
|
||||
* memcache instance
|
||||
*
|
||||
* @var Memcache
|
||||
*/
|
||||
protected $memcache = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->memcache = new Memcache();
|
||||
$this->memcache->addServer('127.0.0.1', 11211);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read values for a set of keys from cache
|
||||
*
|
||||
* @param array $keys list of keys to fetch
|
||||
*
|
||||
* @return array list of values with the given keys used as indexes
|
||||
* @return boolean true on success, false on failure
|
||||
*/
|
||||
protected function read(array $keys)
|
||||
{
|
||||
$_keys = $lookup = array();
|
||||
foreach ($keys as $k) {
|
||||
$_k = sha1($k);
|
||||
$_keys[] = $_k;
|
||||
$lookup[$_k] = $k;
|
||||
}
|
||||
$_res = array();
|
||||
$res = $this->memcache->get($_keys);
|
||||
foreach ($res as $k => $v) {
|
||||
$_res[$lookup[$k]] = $v;
|
||||
}
|
||||
|
||||
return $_res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save values for a set of keys to cache
|
||||
*
|
||||
* @param array $keys list of values to save
|
||||
* @param int $expire expiration time
|
||||
*
|
||||
* @return boolean true on success, false on failure
|
||||
*/
|
||||
protected function write(array $keys, $expire = null)
|
||||
{
|
||||
foreach ($keys as $k => $v) {
|
||||
$k = sha1($k);
|
||||
$this->memcache->set($k, $v, 0, $expire);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove values from cache
|
||||
*
|
||||
* @param array $keys list of keys to delete
|
||||
*
|
||||
* @return boolean true on success, false on failure
|
||||
*/
|
||||
protected function delete(array $keys)
|
||||
{
|
||||
foreach ($keys as $k) {
|
||||
$k = sha1($k);
|
||||
$this->memcache->delete($k);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove *all* values from cache
|
||||
*
|
||||
* @return boolean true on success, false on failure
|
||||
*/
|
||||
protected function purge()
|
||||
{
|
||||
$this->memcache->flush();
|
||||
}
|
||||
}
|
162
demo/plugins/cacheresource.mysql.php
Normal file
162
demo/plugins/cacheresource.mysql.php
Normal file
@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* MySQL CacheResource
|
||||
* CacheResource Implementation based on the Custom API to use
|
||||
* MySQL as the storage resource for Smarty's output caching.
|
||||
* Table definition:
|
||||
* <pre>CREATE TABLE IF NOT EXISTS `output_cache` (
|
||||
* `id` CHAR(40) NOT NULL COMMENT 'sha1 hash',
|
||||
* `name` VARCHAR(250) NOT NULL,
|
||||
* `cache_id` VARCHAR(250) NULL DEFAULT NULL,
|
||||
* `compile_id` VARCHAR(250) NULL DEFAULT NULL,
|
||||
* `modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
* `content` LONGTEXT NOT NULL,
|
||||
* PRIMARY KEY (`id`),
|
||||
* INDEX(`name`),
|
||||
* INDEX(`cache_id`),
|
||||
* INDEX(`compile_id`),
|
||||
* INDEX(`modified`)
|
||||
* ) ENGINE = InnoDB;</pre>
|
||||
*
|
||||
* @package CacheResource-examples
|
||||
* @author Rodney Rehm
|
||||
*/
|
||||
class Smarty_CacheResource_Mysql extends Smarty_CacheResource_Custom
|
||||
{
|
||||
// PDO instance
|
||||
protected $db;
|
||||
protected $fetch;
|
||||
protected $fetchTimestamp;
|
||||
protected $save;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
try {
|
||||
$this->db = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty");
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
throw new SmartyException('Mysql Resource failed: ' . $e->getMessage());
|
||||
}
|
||||
$this->fetch = $this->db->prepare('SELECT modified, content FROM output_cache WHERE id = :id');
|
||||
$this->fetchTimestamp = $this->db->prepare('SELECT modified FROM output_cache WHERE id = :id');
|
||||
$this->save = $this->db->prepare('REPLACE INTO output_cache (id, name, cache_id, compile_id, content)
|
||||
VALUES (:id, :name, :cache_id, :compile_id, :content)');
|
||||
}
|
||||
|
||||
/**
|
||||
* fetch cached content and its modification time from data source
|
||||
*
|
||||
* @param string $id unique cache content identifier
|
||||
* @param string $name template name
|
||||
* @param string $cache_id cache id
|
||||
* @param string $compile_id compile id
|
||||
* @param string $content cached content
|
||||
* @param integer $mtime cache modification timestamp (epoch)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime)
|
||||
{
|
||||
$this->fetch->execute(array('id' => $id));
|
||||
$row = $this->fetch->fetch();
|
||||
$this->fetch->closeCursor();
|
||||
if ($row) {
|
||||
$content = $row['content'];
|
||||
$mtime = strtotime($row['modified']);
|
||||
} else {
|
||||
$content = null;
|
||||
$mtime = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch cached content's modification timestamp from data source
|
||||
*
|
||||
* @note implementing this method is optional. Only implement it if modification times can be accessed faster than loading the complete cached content.
|
||||
*
|
||||
* @param string $id unique cache content identifier
|
||||
* @param string $name template name
|
||||
* @param string $cache_id cache id
|
||||
* @param string $compile_id compile id
|
||||
*
|
||||
* @return integer|boolean timestamp (epoch) the template was modified, or false if not found
|
||||
*/
|
||||
protected function fetchTimestamp($id, $name, $cache_id, $compile_id)
|
||||
{
|
||||
$this->fetchTimestamp->execute(array('id' => $id));
|
||||
$mtime = strtotime($this->fetchTimestamp->fetchColumn());
|
||||
$this->fetchTimestamp->closeCursor();
|
||||
|
||||
return $mtime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save content to cache
|
||||
*
|
||||
* @param string $id unique cache content identifier
|
||||
* @param string $name template name
|
||||
* @param string $cache_id cache id
|
||||
* @param string $compile_id compile id
|
||||
* @param integer|null $exp_time seconds till expiration time in seconds or null
|
||||
* @param string $content content to cache
|
||||
*
|
||||
* @return boolean success
|
||||
*/
|
||||
protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content)
|
||||
{
|
||||
$this->save->execute(array(
|
||||
'id' => $id,
|
||||
'name' => $name,
|
||||
'cache_id' => $cache_id,
|
||||
'compile_id' => $compile_id,
|
||||
'content' => $content,
|
||||
));
|
||||
|
||||
return !!$this->save->rowCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete content from cache
|
||||
*
|
||||
* @param string $name template name
|
||||
* @param string $cache_id cache id
|
||||
* @param string $compile_id compile id
|
||||
* @param integer|null $exp_time seconds till expiration or null
|
||||
*
|
||||
* @return integer number of deleted caches
|
||||
*/
|
||||
protected function delete($name, $cache_id, $compile_id, $exp_time)
|
||||
{
|
||||
// delete the whole cache
|
||||
if ($name === null && $cache_id === null && $compile_id === null && $exp_time === null) {
|
||||
// returning the number of deleted caches would require a second query to count them
|
||||
$query = $this->db->query('TRUNCATE TABLE output_cache');
|
||||
|
||||
return - 1;
|
||||
}
|
||||
// build the filter
|
||||
$where = array();
|
||||
// equal test name
|
||||
if ($name !== null) {
|
||||
$where[] = 'name = ' . $this->db->quote($name);
|
||||
}
|
||||
// equal test compile_id
|
||||
if ($compile_id !== null) {
|
||||
$where[] = 'compile_id = ' . $this->db->quote($compile_id);
|
||||
}
|
||||
// range test expiration time
|
||||
if ($exp_time !== null) {
|
||||
$where[] = 'modified < DATE_SUB(NOW(), INTERVAL ' . intval($exp_time) . ' SECOND)';
|
||||
}
|
||||
// equal test cache_id and match sub-groups
|
||||
if ($cache_id !== null) {
|
||||
$where[] = '(cache_id = ' . $this->db->quote($cache_id)
|
||||
. ' OR cache_id LIKE ' . $this->db->quote($cache_id . '|%') . ')';
|
||||
}
|
||||
// run delete query
|
||||
$query = $this->db->query('DELETE FROM output_cache WHERE ' . join(' AND ', $where));
|
||||
|
||||
return $query->rowCount();
|
||||
}
|
||||
}
|
322
demo/plugins/cacheresource.pdo.php
Normal file
322
demo/plugins/cacheresource.pdo.php
Normal file
@ -0,0 +1,322 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PDO Cache Handler
|
||||
* Allows you to store Smarty Cache files into your db.
|
||||
* Example table :
|
||||
* CREATE TABLE `smarty_cache` (
|
||||
* `id` char(40) NOT NULL COMMENT 'sha1 hash',
|
||||
* `name` varchar(250) NOT NULL,
|
||||
* `cache_id` varchar(250) DEFAULT NULL,
|
||||
* `compile_id` varchar(250) DEFAULT NULL,
|
||||
* `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
* `expire` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
* `content` mediumblob NOT NULL,
|
||||
* PRIMARY KEY (`id`),
|
||||
* KEY `name` (`name`),
|
||||
* KEY `cache_id` (`cache_id`),
|
||||
* KEY `compile_id` (`compile_id`),
|
||||
* KEY `modified` (`modified`),
|
||||
* KEY `expire` (`expire`)
|
||||
* ) ENGINE=InnoDB
|
||||
* Example usage :
|
||||
* $cnx = new PDO("mysql:host=localhost;dbname=mydb", "username", "password");
|
||||
* $smarty->setCachingType('pdo');
|
||||
* $smarty->loadPlugin('Smarty_CacheResource_Pdo');
|
||||
* $smarty->registerCacheResource('pdo', new Smarty_CacheResource_Pdo($cnx, 'smarty_cache'));
|
||||
*
|
||||
* @author Beno!t POLASZEK - 2014
|
||||
*/
|
||||
class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom
|
||||
{
|
||||
|
||||
protected $fetchStatements = Array('default' => 'SELECT %2$s
|
||||
FROM %1$s
|
||||
WHERE 1
|
||||
AND id = :id
|
||||
AND cache_id IS NULL
|
||||
AND compile_id IS NULL',
|
||||
|
||||
'withCacheId' => 'SELECT %2$s
|
||||
FROM %1$s
|
||||
WHERE 1
|
||||
AND id = :id
|
||||
AND cache_id = :cache_id
|
||||
AND compile_id IS NULL',
|
||||
|
||||
'withCompileId' => 'SELECT %2$s
|
||||
FROM %1$s
|
||||
WHERE 1
|
||||
AND id = :id
|
||||
AND compile_id = :compile_id
|
||||
AND cache_id IS NULL',
|
||||
|
||||
'withCacheIdAndCompileId' => 'SELECT %2$s
|
||||
FROM %1$s
|
||||
WHERE 1
|
||||
AND id = :id
|
||||
AND cache_id = :cache_id
|
||||
AND compile_id = :compile_id');
|
||||
protected $insertStatement = 'INSERT INTO %s
|
||||
|
||||
SET id = :id,
|
||||
name = :name,
|
||||
cache_id = :cache_id,
|
||||
compile_id = :compile_id,
|
||||
modified = CURRENT_TIMESTAMP,
|
||||
expire = DATE_ADD(CURRENT_TIMESTAMP, INTERVAL :expire SECOND),
|
||||
content = :content
|
||||
|
||||
ON DUPLICATE KEY UPDATE
|
||||
name = :name,
|
||||
cache_id = :cache_id,
|
||||
compile_id = :compile_id,
|
||||
modified = CURRENT_TIMESTAMP,
|
||||
expire = DATE_ADD(CURRENT_TIMESTAMP, INTERVAL :expire SECOND),
|
||||
content = :content';
|
||||
|
||||
protected $deleteStatement = 'DELETE FROM %1$s WHERE %2$s';
|
||||
protected $truncateStatement = 'TRUNCATE TABLE %s';
|
||||
|
||||
protected $fetchColumns = 'modified, content';
|
||||
protected $fetchTimestampColumns = 'modified';
|
||||
|
||||
protected $pdo, $table, $database;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*
|
||||
* @param PDO $pdo PDO : active connection
|
||||
* @param string $table : table (or view) name
|
||||
* @param string $database : optionnal - if table is located in another db
|
||||
*/
|
||||
public function __construct(PDO $pdo, $table, $database = null)
|
||||
{
|
||||
|
||||
if (is_null($table)) {
|
||||
throw new SmartyException("Table name for caching can't be null");
|
||||
}
|
||||
|
||||
$this->pdo = $pdo;
|
||||
$this->table = $table;
|
||||
$this->database = $database;
|
||||
|
||||
$this->fillStatementsWithTableName();
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills the table name into the statements.
|
||||
*
|
||||
* @return Current Instance
|
||||
* @access protected
|
||||
*/
|
||||
protected function fillStatementsWithTableName()
|
||||
{
|
||||
|
||||
foreach ($this->fetchStatements AS &$statement) {
|
||||
$statement = sprintf($statement, $this->getTableName(), '%s');
|
||||
}
|
||||
|
||||
$this->insertStatement = sprintf($this->insertStatement, $this->getTableName());
|
||||
$this->deleteStatement = sprintf($this->deleteStatement, $this->getTableName(), '%s');
|
||||
$this->truncateStatement = sprintf($this->truncateStatement, $this->getTableName());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the fetch statement, depending on what you specify
|
||||
*
|
||||
* @param string $columns : the column(s) name(s) you want to retrieve from the database
|
||||
* @param string $id unique cache content identifier
|
||||
* @param string|null $cache_id cache id
|
||||
* @param string|null $compile_id compile id
|
||||
* @access protected
|
||||
*/
|
||||
protected function getFetchStatement($columns, $id, $cache_id = null, $compile_id = null)
|
||||
{
|
||||
|
||||
if (!is_null($cache_id) && !is_null($compile_id)) {
|
||||
$query = $this->fetchStatements['withCacheIdAndCompileId'] AND $args = Array('id' => $id, 'cache_id' => $cache_id, 'compile_id' => $compile_id);
|
||||
} elseif (is_null($cache_id) && !is_null($compile_id)) {
|
||||
$query = $this->fetchStatements['withCompileId'] AND $args = Array('id' => $id, 'compile_id' => $compile_id);
|
||||
} elseif (!is_null($cache_id) && is_null($compile_id)) {
|
||||
$query = $this->fetchStatements['withCacheId'] AND $args = Array('id' => $id, 'cache_id' => $cache_id);
|
||||
} else {
|
||||
$query = $this->fetchStatements['default'] AND $args = Array('id' => $id);
|
||||
}
|
||||
|
||||
$query = sprintf($query, $columns);
|
||||
|
||||
$stmt = $this->pdo->prepare($query);
|
||||
|
||||
foreach ($args AS $key => $value) {
|
||||
$stmt->bindValue($key, $value);
|
||||
}
|
||||
|
||||
return $stmt;
|
||||
}
|
||||
|
||||
/**
|
||||
* fetch cached content and its modification time from data source
|
||||
*
|
||||
* @param string $id unique cache content identifier
|
||||
* @param string $name template name
|
||||
* @param string|null $cache_id cache id
|
||||
* @param string|null $compile_id compile id
|
||||
* @param string $content cached content
|
||||
* @param integer $mtime cache modification timestamp (epoch)
|
||||
*
|
||||
* @return void
|
||||
* @access protected
|
||||
*/
|
||||
protected function fetch($id, $name, $cache_id = null, $compile_id = null, &$content, &$mtime)
|
||||
{
|
||||
|
||||
$stmt = $this->getFetchStatement($this->fetchColumns, $id, $cache_id, $compile_id);
|
||||
$stmt ->execute();
|
||||
$row = $stmt->fetch();
|
||||
$stmt ->closeCursor();
|
||||
|
||||
if ($row) {
|
||||
$content = $this->outputContent($row['content']);
|
||||
$mtime = strtotime($row['modified']);
|
||||
} else {
|
||||
$content = null;
|
||||
$mtime = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch cached content's modification timestamp from data source
|
||||
* {@internal implementing this method is optional.
|
||||
* Only implement it if modification times can be accessed faster than loading the complete cached content.}}
|
||||
*
|
||||
* @param string $id unique cache content identifier
|
||||
* @param string $name template name
|
||||
* @param string|null $cache_id cache id
|
||||
* @param string|null $compile_id compile id
|
||||
*
|
||||
* @return integer|boolean timestamp (epoch) the template was modified, or false if not found
|
||||
* @access protected
|
||||
*/
|
||||
// protected function fetchTimestamp($id, $name, $cache_id = null, $compile_id = null) {
|
||||
// $stmt = $this->getFetchStatement($this->fetchTimestampColumns, $id, $cache_id, $compile_id);
|
||||
// $stmt -> execute();
|
||||
// $mtime = strtotime($stmt->fetchColumn());
|
||||
// $stmt -> closeCursor();
|
||||
// return $mtime;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Save content to cache
|
||||
*
|
||||
* @param string $id unique cache content identifier
|
||||
* @param string $name template name
|
||||
* @param string|null $cache_id cache id
|
||||
* @param string|null $compile_id compile id
|
||||
* @param integer|null $exp_time seconds till expiration time in seconds or null
|
||||
* @param string $content content to cache
|
||||
*
|
||||
* @return boolean success
|
||||
* @access protected
|
||||
*/
|
||||
protected function save($id, $name, $cache_id = null, $compile_id = null, $exp_time, $content)
|
||||
{
|
||||
|
||||
$stmt = $this->pdo->prepare($this->insertStatement);
|
||||
|
||||
$stmt ->bindValue('id', $id);
|
||||
$stmt ->bindValue('name', $name);
|
||||
$stmt ->bindValue('cache_id', $cache_id, (is_null($cache_id)) ? PDO::PARAM_NULL : PDO::PARAM_STR);
|
||||
$stmt ->bindValue('compile_id', $compile_id, (is_null($compile_id)) ? PDO::PARAM_NULL : PDO::PARAM_STR);
|
||||
$stmt ->bindValue('expire', (int) $exp_time, PDO::PARAM_INT);
|
||||
$stmt ->bindValue('content', $this->inputContent($content));
|
||||
$stmt ->execute();
|
||||
|
||||
return !!$stmt->rowCount();
|
||||
}
|
||||
|
||||
/*
|
||||
* Encodes the content before saving to database
|
||||
*
|
||||
* @param string $content
|
||||
* @return string $content
|
||||
* @access protected
|
||||
*/
|
||||
protected function inputContent($content)
|
||||
{
|
||||
return $content;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decodes the content before saving to database
|
||||
*
|
||||
* @param string $content
|
||||
* @return string $content
|
||||
* @access protected
|
||||
*/
|
||||
protected function outputContent($content)
|
||||
{
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete content from cache
|
||||
*
|
||||
* @param string|null $name template name
|
||||
* @param string|null $cache_id cache id
|
||||
* @param string|null $compile_id compile id
|
||||
* @param integer|null|-1 $exp_time seconds till expiration or null
|
||||
*
|
||||
* @return integer number of deleted caches
|
||||
* @access protected
|
||||
*/
|
||||
protected function delete($name = null, $cache_id = null, $compile_id = null, $exp_time = null)
|
||||
{
|
||||
|
||||
// delete the whole cache
|
||||
if ($name === null && $cache_id === null && $compile_id === null && $exp_time === null) {
|
||||
// returning the number of deleted caches would require a second query to count them
|
||||
$this->pdo->query($this->truncateStatement);
|
||||
return - 1;
|
||||
}
|
||||
// build the filter
|
||||
$where = array();
|
||||
// equal test name
|
||||
if ($name !== null) {
|
||||
$where[] = 'name = ' . $this->pdo->quote($name);
|
||||
}
|
||||
// equal test cache_id and match sub-groups
|
||||
if ($cache_id !== null) {
|
||||
$where[] = '(cache_id = ' . $this->pdo->quote($cache_id)
|
||||
. ' OR cache_id LIKE ' . $this->pdo->quote($cache_id . '|%') . ')';
|
||||
}
|
||||
// equal test compile_id
|
||||
if ($compile_id !== null) {
|
||||
$where[] = 'compile_id = ' . $this->pdo->quote($compile_id);
|
||||
}
|
||||
// for clearing expired caches
|
||||
if ($exp_time === Smarty::CLEAR_EXPIRED) {
|
||||
$where[] = 'expire < CURRENT_TIMESTAMP';
|
||||
} // range test expiration time
|
||||
elseif ($exp_time !== null) {
|
||||
$where[] = 'modified < DATE_SUB(NOW(), INTERVAL ' . intval($exp_time) . ' SECOND)';
|
||||
}
|
||||
// run delete query
|
||||
$query = $this->pdo->query(sprintf($this->deleteStatement, join(' AND ', $where)));
|
||||
return $query->rowCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the formatted table name
|
||||
*
|
||||
* @return string
|
||||
* @access protected
|
||||
*/
|
||||
protected function getTableName()
|
||||
{
|
||||
return (is_null($this->database)) ? "`{$this->table}`" : "`{$this->database}`.`{$this->table}`";
|
||||
}
|
||||
}
|
||||
|
43
demo/plugins/cacheresource.pdo_gzip.php
Normal file
43
demo/plugins/cacheresource.pdo_gzip.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PDO Cache Handler with GZIP support
|
||||
* Example usage :
|
||||
* $cnx = new PDO("mysql:host=localhost;dbname=mydb", "username", "password");
|
||||
* $smarty->setCachingType('pdo_gzip');
|
||||
* $smarty->loadPlugin('Smarty_CacheResource_Pdo_Gzip');
|
||||
* $smarty->registerCacheResource('pdo_gzip', new Smarty_CacheResource_Pdo_Gzip($cnx, 'smarty_cache'));
|
||||
*
|
||||
* @require Smarty_CacheResource_Pdo class
|
||||
* @author Beno!t POLASZEK - 2014
|
||||
*/
|
||||
require_once 'cacheresource.pdo.php';
|
||||
|
||||
class Smarty_CacheResource_Pdo_Gzip extends Smarty_CacheResource_Pdo
|
||||
{
|
||||
|
||||
/*
|
||||
* Encodes the content before saving to database
|
||||
*
|
||||
* @param string $content
|
||||
* @return string $content
|
||||
* @access protected
|
||||
*/
|
||||
protected function inputContent($content)
|
||||
{
|
||||
return gzdeflate($content);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decodes the content before saving to database
|
||||
*
|
||||
* @param string $content
|
||||
* @return string $content
|
||||
* @access protected
|
||||
*/
|
||||
protected function outputContent($content)
|
||||
{
|
||||
return gzinflate($content);
|
||||
}
|
||||
}
|
||||
|
60
demo/plugins/resource.extendsall.php
Normal file
60
demo/plugins/resource.extendsall.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Extends All Resource
|
||||
* Resource Implementation modifying the extends-Resource to walk
|
||||
* through the template_dirs and inherit all templates of the same name
|
||||
*
|
||||
* @package Resource-examples
|
||||
* @author Rodney Rehm
|
||||
*/
|
||||
class Smarty_Resource_Extendsall extends Smarty_Internal_Resource_Extends
|
||||
{
|
||||
/**
|
||||
* populate Source Object with meta data from Resource
|
||||
*
|
||||
* @param Smarty_Template_Source $source source object
|
||||
* @param Smarty_Internal_Template $_template template object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null)
|
||||
{
|
||||
$uid = '';
|
||||
$sources = array();
|
||||
$exists = true;
|
||||
foreach ($_template->smarty->getTemplateDir() as $key => $directory) {
|
||||
try {
|
||||
$s = Smarty_Resource::source(null, $source->smarty, '[' . $key . ']' . $source->name);
|
||||
if (!$s->exists) {
|
||||
continue;
|
||||
}
|
||||
$sources[$s->uid] = $s;
|
||||
$uid .= $s->filepath;
|
||||
}
|
||||
catch (SmartyException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!$sources) {
|
||||
$source->exists = false;
|
||||
$source->template = $_template;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$sources = array_reverse($sources, true);
|
||||
reset($sources);
|
||||
$s = current($sources);
|
||||
|
||||
$source->components = $sources;
|
||||
$source->filepath = $s->filepath;
|
||||
$source->uid = sha1($uid);
|
||||
$source->exists = $exists;
|
||||
if ($_template && $_template->smarty->compile_check) {
|
||||
$source->timestamp = $s->timestamp;
|
||||
}
|
||||
// need the template at getContent()
|
||||
$source->template = $_template;
|
||||
}
|
||||
}
|
81
demo/plugins/resource.mysql.php
Normal file
81
demo/plugins/resource.mysql.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* MySQL Resource
|
||||
* Resource Implementation based on the Custom API to use
|
||||
* MySQL as the storage resource for Smarty's templates and configs.
|
||||
* Table definition:
|
||||
* <pre>CREATE TABLE IF NOT EXISTS `templates` (
|
||||
* `name` varchar(100) NOT NULL,
|
||||
* `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
* `source` text,
|
||||
* PRIMARY KEY (`name`)
|
||||
* ) ENGINE=InnoDB DEFAULT CHARSET=utf8;</pre>
|
||||
* Demo data:
|
||||
* <pre>INSERT INTO `templates` (`name`, `modified`, `source`) VALUES ('test.tpl', "2010-12-25 22:00:00", '{$x="hello world"}{$x}');</pre>
|
||||
*
|
||||
* @package Resource-examples
|
||||
* @author Rodney Rehm
|
||||
*/
|
||||
class Smarty_Resource_Mysql extends Smarty_Resource_Custom
|
||||
{
|
||||
// PDO instance
|
||||
protected $db;
|
||||
// prepared fetch() statement
|
||||
protected $fetch;
|
||||
// prepared fetchTimestamp() statement
|
||||
protected $mtime;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
try {
|
||||
$this->db = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty");
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
throw new SmartyException('Mysql Resource failed: ' . $e->getMessage());
|
||||
}
|
||||
$this->fetch = $this->db->prepare('SELECT modified, source FROM templates WHERE name = :name');
|
||||
$this->mtime = $this->db->prepare('SELECT modified FROM templates WHERE name = :name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a template and its modification time from database
|
||||
*
|
||||
* @param string $name template name
|
||||
* @param string $source template source
|
||||
* @param integer $mtime template modification timestamp (epoch)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function fetch($name, &$source, &$mtime)
|
||||
{
|
||||
$this->fetch->execute(array('name' => $name));
|
||||
$row = $this->fetch->fetch();
|
||||
$this->fetch->closeCursor();
|
||||
if ($row) {
|
||||
$source = $row['source'];
|
||||
$mtime = strtotime($row['modified']);
|
||||
} else {
|
||||
$source = null;
|
||||
$mtime = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a template's modification time from database
|
||||
*
|
||||
* @note implementing this method is optional. Only implement it if modification times can be accessed faster than loading the comple template source.
|
||||
*
|
||||
* @param string $name template name
|
||||
*
|
||||
* @return integer timestamp (epoch) the template was modified
|
||||
*/
|
||||
protected function fetchTimestamp($name)
|
||||
{
|
||||
$this->mtime->execute(array('name' => $name));
|
||||
$mtime = $this->mtime->fetchColumn();
|
||||
$this->mtime->closeCursor();
|
||||
|
||||
return strtotime($mtime);
|
||||
}
|
||||
}
|
62
demo/plugins/resource.mysqls.php
Normal file
62
demo/plugins/resource.mysqls.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* MySQL Resource
|
||||
* Resource Implementation based on the Custom API to use
|
||||
* MySQL as the storage resource for Smarty's templates and configs.
|
||||
* Note that this MySQL implementation fetches the source and timestamps in
|
||||
* a single database query, instead of two separate like resource.mysql.php does.
|
||||
* Table definition:
|
||||
* <pre>CREATE TABLE IF NOT EXISTS `templates` (
|
||||
* `name` varchar(100) NOT NULL,
|
||||
* `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
* `source` text,
|
||||
* PRIMARY KEY (`name`)
|
||||
* ) ENGINE=InnoDB DEFAULT CHARSET=utf8;</pre>
|
||||
* Demo data:
|
||||
* <pre>INSERT INTO `templates` (`name`, `modified`, `source`) VALUES ('test.tpl', "2010-12-25 22:00:00", '{$x="hello world"}{$x}');</pre>
|
||||
*
|
||||
* @package Resource-examples
|
||||
* @author Rodney Rehm
|
||||
*/
|
||||
class Smarty_Resource_Mysqls extends Smarty_Resource_Custom
|
||||
{
|
||||
// PDO instance
|
||||
protected $db;
|
||||
// prepared fetch() statement
|
||||
protected $fetch;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
try {
|
||||
$this->db = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty");
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
throw new SmartyException('Mysql Resource failed: ' . $e->getMessage());
|
||||
}
|
||||
$this->fetch = $this->db->prepare('SELECT modified, source FROM templates WHERE name = :name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a template and its modification time from database
|
||||
*
|
||||
* @param string $name template name
|
||||
* @param string $source template source
|
||||
* @param integer $mtime template modification timestamp (epoch)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function fetch($name, &$source, &$mtime)
|
||||
{
|
||||
$this->fetch->execute(array('name' => $name));
|
||||
$row = $this->fetch->fetch();
|
||||
$this->fetch->closeCursor();
|
||||
if ($row) {
|
||||
$source = $row['source'];
|
||||
$mtime = strtotime($row['modified']);
|
||||
} else {
|
||||
$source = null;
|
||||
$mtime = null;
|
||||
}
|
||||
}
|
||||
}
|
2
demo/templates/footer.tpl
Normal file
2
demo/templates/footer.tpl
Normal file
@ -0,0 +1,2 @@
|
||||
</BODY>
|
||||
</HTML>
|
5
demo/templates/header.tpl
Normal file
5
demo/templates/header.tpl
Normal file
@ -0,0 +1,5 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>{$title} - {$Name}</TITLE>
|
||||
</HEAD>
|
||||
<BODY bgcolor="#ffffff">
|
82
demo/templates/index.tpl
Normal file
82
demo/templates/index.tpl
Normal file
@ -0,0 +1,82 @@
|
||||
{config_load file="test.conf" section="setup"}
|
||||
{include file="header.tpl" title=foo}
|
||||
|
||||
<PRE>
|
||||
|
||||
{* bold and title are read from the config file *}
|
||||
{if #bold#}<b>{/if}
|
||||
{* capitalize the first letters of each word of the title *}
|
||||
Title: {#title#|capitalize}
|
||||
{if #bold#}</b>{/if}
|
||||
|
||||
The current date and time is {$smarty.now|date_format:"%Y-%m-%d %H:%M:%S"}
|
||||
|
||||
The value of global assigned variable $SCRIPT_NAME is {$SCRIPT_NAME}
|
||||
|
||||
Example of accessing server environment variable SERVER_NAME: {$smarty.server.SERVER_NAME}
|
||||
|
||||
The value of {ldelim}$Name{rdelim} is <b>{$Name}</b>
|
||||
|
||||
variable modifier example of {ldelim}$Name|upper{rdelim}
|
||||
|
||||
<b>{$Name|upper}</b>
|
||||
|
||||
|
||||
An example of a section loop:
|
||||
|
||||
{section name=outer
|
||||
loop=$FirstName}
|
||||
{if $smarty.section.outer.index is odd by 2}
|
||||
{$smarty.section.outer.rownum} . {$FirstName[outer]} {$LastName[outer]}
|
||||
{else}
|
||||
{$smarty.section.outer.rownum} * {$FirstName[outer]} {$LastName[outer]}
|
||||
{/if}
|
||||
{sectionelse}
|
||||
none
|
||||
{/section}
|
||||
|
||||
An example of section looped key values:
|
||||
|
||||
{section name=sec1 loop=$contacts}
|
||||
phone: {$contacts[sec1].phone}<br>
|
||||
fax: {$contacts[sec1].fax}<br>
|
||||
cell: {$contacts[sec1].cell}<br>
|
||||
{/section}
|
||||
<p>
|
||||
|
||||
testing strip tags
|
||||
{strip}
|
||||
<table border=0>
|
||||
<tr>
|
||||
<td>
|
||||
<A HREF="{$SCRIPT_NAME}">
|
||||
<font color="red">This is a test </font>
|
||||
</A>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
{/strip}
|
||||
|
||||
</PRE>
|
||||
|
||||
This is an example of the html_select_date function:
|
||||
|
||||
<form>
|
||||
{html_select_date start_year=1998 end_year=2010}
|
||||
</form>
|
||||
|
||||
This is an example of the html_select_time function:
|
||||
|
||||
<form>
|
||||
{html_select_time use_24_hours=false}
|
||||
</form>
|
||||
|
||||
This is an example of the html_options function:
|
||||
|
||||
<form>
|
||||
<select name=states>
|
||||
{html_options values=$option_values selected=$option_selected output=$option_output}
|
||||
</select>
|
||||
</form>
|
||||
|
||||
{include file="footer.tpl"}
|
Reference in New Issue
Block a user