summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxue <>2006-02-16 22:48:18 +0000
committerxue <>2006-02-16 22:48:18 +0000
commite9bfba959b6d655ed2eba71e4f2a618237d68698 (patch)
tree7e9160367d627a13d177c104802dc343f2f32e33
parenta2cf28f9759c9a1b385914ad64b4f74470f8703b (diff)
Modified asset manipulation APIs.
-rw-r--r--.gitattributes1
-rw-r--r--buildscripts/phpbuilder/files.txt2
-rw-r--r--framework/TApplication.php29
-rw-r--r--framework/TComponent.php25
-rw-r--r--framework/Web/Javascripts/TJSON.php160
-rw-r--r--framework/Web/Services/TPageService.php42
-rw-r--r--framework/Web/UI/TAssetManager.php239
-rw-r--r--framework/Web/UI/TClientScriptManager.php306
-rw-r--r--framework/Web/UI/TControl.php15
-rw-r--r--framework/Web/UI/TTemplateManager.php9
-rw-r--r--framework/Web/UI/WebControls/TColorPicker.php4
-rw-r--r--framework/Web/UI/WebControls/TDatePicker.php4
-rw-r--r--framework/Web/UI/WebControls/TRatingList.php12
-rw-r--r--framework/Web/UI/WebControls/TTextHighlighter.php2
14 files changed, 365 insertions, 485 deletions
diff --git a/.gitattributes b/.gitattributes
index ccea88bc..2799bff9 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -663,7 +663,6 @@ framework/Web/THttpRequest.php -text
framework/Web/THttpResponse.php -text
framework/Web/THttpSession.php -text
framework/Web/THttpUtility.php -text
-framework/Web/UI/TAssetManager.php -text
framework/Web/UI/TClientScriptManager.php -text
framework/Web/UI/TControl.php -text
framework/Web/UI/TControlAdapter.php -text
diff --git a/buildscripts/phpbuilder/files.txt b/buildscripts/phpbuilder/files.txt
index 0bb29bfb..c9a9d14d 100644
--- a/buildscripts/phpbuilder/files.txt
+++ b/buildscripts/phpbuilder/files.txt
@@ -21,13 +21,13 @@ Exceptions/TErrorHandler.php
Web/THttpRequest.php
Web/THttpResponse.php
Web/THttpSession.php
+Web/TAssetManager.php
Security/TAuthorizationRule.php
Security/TSecurityManager.php
Web/Services/TPageService.php
Web/UI/THtmlWriter.php
Web/UI/TTemplateManager.php
Web/UI/TThemeManager.php
-Web/UI/TAssetManager.php
Web/UI/TControlAdapter.php
Web/UI/TControl.php
Web/UI/TTemplateControl.php
diff --git a/framework/TApplication.php b/framework/TApplication.php
index 8c4f65f0..b61fa30d 100644
--- a/framework/TApplication.php
+++ b/framework/TApplication.php
@@ -38,6 +38,10 @@ require_once(PRADO_DIR.'/Security/TSecurityManager.php');
* Includes TPageService class (default service)
*/
require_once(PRADO_DIR.'/Web/Services/TPageService.php');
+/**
+ * Includes TAssetManager class
+ */
+require_once(PRADO_DIR.'/Web/TAssetManager.php');
/**
@@ -253,6 +257,10 @@ class TApplication extends TComponent
*/
private $_security=null;
/**
+ * @var TAssetManager asset manager module
+ */
+ private $_assetManager=null;
+ /**
* @var TAuthorizationRuleCollection collection of authorization rules
*/
private $_authRules=null;
@@ -678,6 +686,27 @@ class TApplication extends TComponent
}
/**
+ * @return TAssetManager asset manager
+ */
+ public function getAssetManager()
+ {
+ if(!$this->_assetManager)
+ {
+ $this->_assetManager=new TAssetManager;
+ $this->_assetManager->init(null);
+ }
+ return $this->_assetManager;
+ }
+
+ /**
+ * @param TAssetManager asset manager
+ */
+ public function setAssetManager(TAssetManager $value)
+ {
+ $this->_assetManager=$value;
+ }
+
+ /**
* @return IStatePersister application state persister
*/
public function getApplicationStatePersister()
diff --git a/framework/TComponent.php b/framework/TComponent.php
index 6641fd1a..8d6be46e 100644
--- a/framework/TComponent.php
+++ b/framework/TComponent.php
@@ -474,6 +474,31 @@ class TComponent
{
return Prado::getApplication()->getUser();
}
+
+ /**
+ * Publishes a private asset and gets its URL.
+ * This method will publish a private asset (file or directory)
+ * and gets the URL to the asset. Note, if the asset refers to
+ * a directory, all contents under that directory will be published.
+ * @param string path of the asset that is relative to the directory containing the control class file.
+ * @return string URL to the asset path.
+ */
+ public function publishAsset($assetPath)
+ {
+ $class=new ReflectionClass(get_class($this));
+ $fullPath=dirname($class->getFileName()).'/'.$assetPath;
+ return $this->publishFilePath($fullPath);
+ }
+
+ /**
+ * Publishes a file or directory and returns its URL.
+ * @param string absolute path of the file or directory to be published
+ * @return string URL to the published file or directory
+ */
+ public function publishFilePath($fullPath)
+ {
+ return $this->getApplication()->getAssetManager()->publishFilePath($fullPath);
+ }
}
/**
diff --git a/framework/Web/Javascripts/TJSON.php b/framework/Web/Javascripts/TJSON.php
index 76a19d27..e653264b 100644
--- a/framework/Web/Javascripts/TJSON.php
+++ b/framework/Web/Javascripts/TJSON.php
@@ -1,6 +1,4 @@
<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
/**
* Converts to and from JSON format.
*
@@ -47,8 +45,8 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
-* @category
-* @package System.Web.Services.AJAX
+* @category
+* @package System.Web.Javascripts
* @author Michal Migurski <mike-json@teczno.com>
* @author Matt Knapp <mdknapp[at]gmail[dot]com>
* @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
@@ -60,7 +58,7 @@
/**
* Converts to and from JSON format.
*
-* @package System.Web.Services.AJAX
+* @package System.Web.Javascripts
* @author Michal Migurski <mike-json@teczno.com>
* @author Matt Knapp <mdknapp[at]gmail[dot]com>
* @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
@@ -76,9 +74,9 @@ class TJSON
/**
* Marker constant for JSON::decode(), used to flag stack state
- */
+ */
const JSON_IN_STR = 2;
-
+
/**
* Marker constant for JSON::decode(), used to flag stack state
*/
@@ -91,17 +89,17 @@ class TJSON
/**
* Marker constant for JSON::decode(), used to flag stack state
- */
+ */
const JSON_IN_CMT = 16;
/**
* Behavior switch for JSON::decode()
*/
const JSON_LOOSE_TYPE = 10;
-
+
/**
* Behavior switch for JSON::decode()
- */
+ */
const JSON_STRICT_TYPE = 11;
/**
@@ -137,17 +135,17 @@ class TJSON
switch (gettype($var)) {
case 'boolean':
return $var ? 'true' : 'false';
-
+
case 'NULL':
return 'null';
-
+
case 'integer':
return (int) $var;
-
+
case 'double':
case 'float':
return (float) $var;
-
+
case 'string':
// STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
$ascii = '';
@@ -158,9 +156,9 @@ class TJSON
* escaping with a slash or encoding to UTF-8 where necessary
*/
for ($c = 0; $c < $strlen_var; ++$c) {
-
+
$ord_var_c = ord($var{$c});
-
+
switch (true) {
case $ord_var_c == 0x08:
$ascii .= '\b';
@@ -184,12 +182,12 @@ class TJSON
// double quote, slash, slosh
$ascii .= '\\'.$var{$c};
break;
-
+
case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
// characters U-00000000 - U-0000007F (same as ASCII)
$ascii .= $var{$c};
break;
-
+
case (($ord_var_c & 0xE0) == 0xC0):
// characters U-00000080 - U-000007FF, mask 110XXXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
@@ -198,7 +196,7 @@ class TJSON
$utf16 = $this->utf8_to_utf16be($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
-
+
case (($ord_var_c & 0xF0) == 0xE0):
// characters U-00000800 - U-0000FFFF, mask 1110XXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
@@ -209,7 +207,7 @@ class TJSON
$utf16 = $this->utf8_to_utf16be($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
-
+
case (($ord_var_c & 0xF8) == 0xF0):
// characters U-00010000 - U-001FFFFF, mask 11110XXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
@@ -221,7 +219,7 @@ class TJSON
$utf16 = $this->utf8_to_utf16be($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
-
+
case (($ord_var_c & 0xFC) == 0xF8):
// characters U-00200000 - U-03FFFFFF, mask 111110XX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
@@ -234,7 +232,7 @@ class TJSON
$utf16 = $this->utf8_to_utf16be($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
-
+
case (($ord_var_c & 0xFE) == 0xFC):
// characters U-04000000 - U-7FFFFFFF, mask 1111110X
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
@@ -250,9 +248,9 @@ class TJSON
break;
}
}
-
+
return '"'.$ascii.'"';
-
+
case 'array':
/*
* As per JSON spec if any array key is not an integer
@@ -271,8 +269,8 @@ class TJSON
* parameter is only accessible using ECMAScript's
* bracket notation.
*/
-
- // treat as a JSON object
+
+ // treat as a JSON object
if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
return '{' .
join(',', array_map(array($this, 'name_value'),
@@ -283,7 +281,7 @@ class TJSON
// treat it like a regular array
return '[' . join(',', array_map(array($this, 'encode'), $var)) . ']';
-
+
case 'object':
$vars = get_object_vars($var);
return '{' .
@@ -296,7 +294,7 @@ class TJSON
return '';
}
}
-
+
/**
* encodes an arbitrary variable into JSON format, alias for encode()
* @see JSON::encode()
@@ -313,7 +311,7 @@ class TJSON
{
return $this->encode($var);
}
-
+
/** function name_value
* array-walking function for use in generating JSON-formatted name-value pairs
*
@@ -326,7 +324,7 @@ class TJSON
protected function name_value($name, $value)
{
return $this->encode(strval($name)) . ':' . $this->encode($value);
- }
+ }
/**
* reduce a string by removing leading and trailing comments and whitespace
@@ -339,18 +337,18 @@ class TJSON
protected function reduce_string($str)
{
$str = preg_replace(array(
-
+
// eliminate single line comments in '// ...' form
'#^\s*//(.+)$#m',
-
+
// eliminate multi-line comments in '/* ... */' form, at start of string
'#^\s*/\*(.+)\*/#Us',
-
+
// eliminate multi-line comments in '/* ... */' form, at end of string
'#/\*(.+)\*/\s*$#Us'
-
+
), '', $str);
-
+
// eliminate extraneous space
return trim($str);
}
@@ -370,17 +368,17 @@ class TJSON
public function decode($str)
{
$str = $this->reduce_string($str);
-
+
switch (strtolower($str)) {
case 'true':
return true;
case 'false':
return false;
-
+
case 'null':
return null;
-
+
default:
if (is_numeric($str)) {
// Lookie-loo, it's a number
@@ -393,19 +391,19 @@ class TJSON
return ((float)$str == (integer)$str)
? (integer)$str
: (float)$str;
-
+
} elseif (preg_match('/^("|\').+(\1)$/s', $str, $m) && $m[1] == $m[2]) {
// STRINGS RETURNED IN UTF-8 FORMAT
$delim = substr($str, 0, 1);
$chrs = substr($str, 1, -1);
$utf8 = '';
$strlen_chrs = strlen($chrs);
-
+
for ($c = 0; $c < $strlen_chrs; ++$c) {
-
+
$substr_chrs_c_2 = substr($chrs, $c, 2);
$ord_chrs_c = ord($chrs{$c});
-
+
switch (true) {
case $substr_chrs_c_2 == '\b':
$utf8 .= chr(0x08);
@@ -437,7 +435,7 @@ class TJSON
$utf8 .= $chrs{++$c};
}
break;
-
+
case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
// single, escaped unicode character
$utf16 = chr(hexdec(substr($chrs, ($c+2), 2)))
@@ -445,39 +443,39 @@ class TJSON
$utf8 .= $this->utf16be_to_utf8($utf16);
$c+=5;
break;
-
+
case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
$utf8 .= $chrs{$c};
break;
-
+
case ($ord_chrs_c & 0xE0) == 0xC0:
// characters U-00000080 - U-000007FF, mask 110XXXXX
//see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 2);
++$c;
break;
-
+
case ($ord_chrs_c & 0xF0) == 0xE0:
// characters U-00000800 - U-0000FFFF, mask 1110XXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 3);
$c += 2;
break;
-
+
case ($ord_chrs_c & 0xF8) == 0xF0:
// characters U-00010000 - U-001FFFFF, mask 11110XXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 4);
$c += 3;
break;
-
+
case ($ord_chrs_c & 0xFC) == 0xF8:
// characters U-00200000 - U-03FFFFFF, mask 111110XX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 5);
$c += 4;
break;
-
+
case ($ord_chrs_c & 0xFE) == 0xFC:
// characters U-04000000 - U-7FFFFFFF, mask 1111110X
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
@@ -488,9 +486,9 @@ class TJSON
}
}
-
+
return $utf8;
-
+
} elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
// array, or object notation
@@ -506,14 +504,14 @@ class TJSON
$obj = new stdClass();
}
}
-
+
array_push($stk, array('what' => self::JSON_SLICE,
'where' => 0,
'delim' => false));
$chrs = substr($str, 1, -1);
$chrs = $this->reduce_string($chrs);
-
+
if ($chrs == '') {
if (reset($stk) == self::JSON_IN_ARR) {
return $arr;
@@ -525,14 +523,14 @@ class TJSON
}
//print("\nparsing {$chrs}\n");
-
+
$strlen_chrs = strlen($chrs);
-
+
for ($c = 0; $c <= $strlen_chrs; ++$c) {
-
+
$top = end($stk);
$substr_chrs_c_2 = substr($chrs, $c, 2);
-
+
if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == self::JSON_SLICE))) {
// found a comma that is not inside a string, array, etc.,
// OR we've reached the end of the character list
@@ -619,16 +617,16 @@ class TJSON
// found a comment end, and we're in one now
array_pop($stk);
$c++;
-
+
for ($i = $top['where']; $i <= $c; ++$i)
$chrs = substr_replace($chrs, ' ', $i, 1);
-
+
//print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
}
-
+
}
-
+
if (reset($stk) == self::JSON_IN_ARR) {
return $arr;
@@ -636,11 +634,11 @@ class TJSON
return $obj;
}
-
+
}
}
}
-
+
/**
* decodes a JSON string into appropriate variable; alias for decode()
* @see JSON::decode()
@@ -657,7 +655,7 @@ class TJSON
{
return $this->decode($var);
}
-
+
/**
* This function returns any UTF-8 encoded text as a list of
@@ -667,23 +665,23 @@ class TJSON
* @link http://www.randomchaos.com/document.php?source=php_and_unicode
* @see unicode_to_utf8()
*/
- protected function utf8_to_unicode( &$str )
+ protected function utf8_to_unicode( &$str )
{
- $unicode = array();
+ $unicode = array();
$values = array();
$lookingFor = 1;
- for ($i = 0; $i < strlen( $str ); $i++ )
+ for ($i = 0; $i < strlen( $str ); $i++ )
{
$thisValue = ord( $str[ $i ] );
- if ( $thisValue < 128 )
+ if ( $thisValue < 128 )
$unicode[] = $thisValue;
- else
+ else
{
- if ( count( $values ) == 0 )
+ if ( count( $values ) == 0 )
$lookingFor = ( $thisValue < 224 ) ? 2 : 3;
$values[] = $thisValue;
- if ( count( $values ) == $lookingFor )
+ if ( count( $values ) == $lookingFor )
{
$number = ( $lookingFor == 3 ) ?
( ( $values[0] % 16 ) * 4096 ) + ( ( $values[1] % 64 ) * 64 ) + ( $values[2] % 64 ):
@@ -704,21 +702,21 @@ class TJSON
* @link http://www.randomchaos.com/document.php?source=php_and_unicode
* @see utf8_to_unicode()
*/
- protected function unicode_to_utf8( &$str )
+ protected function unicode_to_utf8( &$str )
{
$utf8 = '';
- foreach( $str as $unicode )
+ foreach( $str as $unicode )
{
- if ( $unicode < 128 )
+ if ( $unicode < 128 )
{
$utf8.= chr( $unicode );
- }
- elseif ( $unicode < 2048 )
+ }
+ elseif ( $unicode < 2048 )
{
$utf8.= chr( 192 + ( ( $unicode - ( $unicode % 64 ) ) / 64 ) );
$utf8.= chr( 128 + ( $unicode % 64 ) );
- }
- else
+ }
+ else
{
$utf8.= chr( 224 + ( ( $unicode - ( $unicode % 4096 ) ) / 4096 ) );
$utf8.= chr( 128 + ( ( ( $unicode % 4096 ) - ( $unicode % 64 ) ) / 64 ) );
@@ -733,7 +731,7 @@ class TJSON
*
* Maybe really UCS-2 without mb_string due to utf8_to_unicode limits
*/
- protected function utf8_to_utf16be(&$str, $bom = false)
+ protected function utf8_to_utf16be(&$str, $bom = false)
{
$out = $bom ? "\xFE\xFF" : '';
if(function_exists('mb_convert_encoding'))
@@ -750,12 +748,12 @@ class TJSON
*
* Maybe really UCS-2 without mb_string due to utf8_to_unicode limits
*/
- protected function utf16be_to_utf8(&$str)
+ protected function utf16be_to_utf8(&$str)
{
$uni = unpack('n*',$str);
return unicode_to_utf8($uni);
}
}
-
+
?> \ No newline at end of file
diff --git a/framework/Web/Services/TPageService.php b/framework/Web/Services/TPageService.php
index 32f7514c..bb80b902 100644
--- a/framework/Web/Services/TPageService.php
+++ b/framework/Web/Services/TPageService.php
@@ -16,7 +16,6 @@
Prado::using('System.Web.UI.TPage');
Prado::using('System.Web.UI.TTemplateManager');
Prado::using('System.Web.UI.TThemeManager');
-Prado::using('System.Web.UI.TAssetManager');
/**
* TPageService class.
@@ -47,10 +46,9 @@ Prado::using('System.Web.UI.TAssetManager');
* Configuration of a module in a subdirectory will overwrite its parent
* directory's configuration, if both configurations refer to the same module.
*
- * By default, TPageService will automatically load three modules:
+ * By default, TPageService will automatically load two modules:
* - {@link TTemplateManager} : manages page and control templates
* - {@link TThemeManager} : manages themes used in a Prado application
- * - {@link TAssetManager} : manages assets used in a Prado application.
*
* In page directory configurations, static authorization rules can also be specified,
* which governs who and which roles can access particular pages.
@@ -122,10 +120,6 @@ class TPageService extends TService
*/
private $_initialized=false;
/**
- * @var TAssetManager asset manager
- */
- private $_assetManager=null;
- /**
* @var TThemeManager theme manager
*/
private $_themeManager=null;
@@ -323,27 +317,6 @@ class TPageService extends TService
}
/**
- * @return TAssetManager asset manager
- */
- public function getAssetManager()
- {
- if(!$this->_assetManager)
- {
- $this->_assetManager=new TAssetManager;
- $this->_assetManager->init(null);
- }
- return $this->_assetManager;
- }
-
- /**
- * @param TAssetManager asset manager
- */
- public function setAssetManager(TAssetManager $value)
- {
- $this->_assetManager=$value;
- }
-
- /**
* @return TThemeManager theme manager
*/
public function getThemeManager()
@@ -482,19 +455,6 @@ class TPageService extends TService
{
return $this->getRequest()->constructUrl($this->_id,$pagePath,$getParams,$encodeAmpersand);
}
-
- /**
- * Publishes a private asset and returns its URL.
- * This method will publish a private asset (file or directory)
- * and returns the URL to the asset. Note, if the asset refers to
- * a directory, all contents under that directory will be published.
- * @param string path of the asset that is either absolute or relative to the directory containing the current running script.
- * @return string URL to the asset path.
- */
- public function getAsset($path)
- {
- return $this->getAssetManager()->publishFilePath($path);
- }
}
diff --git a/framework/Web/UI/TAssetManager.php b/framework/Web/UI/TAssetManager.php
deleted file mode 100644
index 3e341a5e..00000000
--- a/framework/Web/UI/TAssetManager.php
+++ /dev/null
@@ -1,239 +0,0 @@
-<?php
-/**
- * TAssetManager class
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Revision: $ $Date: $
- * @package System.Web.UI
- */
-
-/**
- * TAssetManager class
- *
- * TAssetManager provides a scheme to allow web clients visiting
- * private files that are normally web-inaccessible.
- *
- * TAssetManager will copy the file to be published into a web-accessible
- * directory. The default base directory for storing the file is "assets", which
- * should be under the application directory. This can be changed by setting
- * the {@link setBasePath BasePath} property together with the
- * {@link setBaseUrl BaseUrl} property that refers to the URL for accessing the base path.
- *
- * By default, TAssetManager will not publish a file or directory if it already
- * exists in the publishing directory and has an older modification time.
- * If the application mode is set as 'Performance', the modification time check
- * will be skipped. You can explicitly require a modification time check
- * with the function {@link publishFilePath}. This is usually
- * very useful during development.
- *
- * TAssetManager may be configured in application configuration file within
- * page service element as follows,
- * <module id="asset" BasePath="Application.assets" BaseUrl="/assets" />
- * where {@link getBasePath BasePath} and {@link getBaseUrl BaseUrl} are
- * configurable properties of TAssetManager. Make sure that BasePath is a namespace
- * pointing to a valid directory writable by the Web server process.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $ $Date: $
- * @package System.Web.UI
- * @since 3.0
- */
-class TAssetManager extends TModule
-{
- /**
- * Default web accessible base path for storing private files
- */
- const DEFAULT_BASEPATH='assets';
- /**
- * @var string base web accessible path for storing private files
- */
- private $_basePath=null;
- /**
- * @var string base URL for accessing the publishing directory.
- */
- private $_baseUrl=null;
- /**
- * @var boolean whether to use timestamp checking to ensure files are published with up-to-date versions.
- */
- private $_checkTimestamp=false;
- /**
- * @var TApplication application instance
- */
- private $_application;
- /**
- * @var array published assets
- */
- private $_published=array();
- /**
- * @var boolean whether the module is initialized
- */
- private $_initialized=false;
-
- /**
- * Initializes the module.
- * This method is required by IModule and is invoked by application.
- * @param TXmlElement module configuration
- */
- public function init($config)
- {
- $application=$this->getApplication();
- if($this->_basePath===null)
- $this->_basePath=dirname($application->getRequest()->getPhysicalApplicationPath()).'/'.self::DEFAULT_BASEPATH;
- if(!is_writable($this->_basePath) || !is_dir($this->_basePath))
- throw new TConfigurationException('assetmanager_basepath_invalid',$this->_basePath);
- if($this->_baseUrl===null)
- $this->_baseUrl=rtrim(dirname($application->getRequest()->getApplicationPath()),'/\\').'/'.self::DEFAULT_BASEPATH;
- $application->getService()->setAssetManager($this);
- $this->_initialized=true;
- }
-
- /**
- * @return string the root directory storing published asset files
- */
- public function getBasePath()
- {
- return $this->_basePath;
- }
-
- /**
- * Sets the root directory storing published asset files.
- * The directory must be in namespace format.
- * @param string the root directory storing published asset files
- * @throws TInvalidOperationException if the service is initialized already
- */
- public function setBasePath($value)
- {
- if($this->_initialized)
- throw new TInvalidOperationException('assetmanager_basepath_unchangeable');
- else
- {
- $this->_basePath=Prado::getPathOfAlias($value);
- if($this->_basePath===null || !is_dir($this->_basePath) || !is_writable($this->_basePath))
- throw new TInvalidDataValueException('assetmanage_basepath_invalid',$value);
- }
- }
-
- /**
- * @return string the base url that the published asset files can be accessed
- */
- public function getBaseUrl()
- {
- return $this->_baseUrl;
- }
-
- /**
- * @param string the base url that the published asset files can be accessed
- * @throws TInvalidOperationException if the service is initialized already
- */
- public function setBaseUrl($value)
- {
- if($this->_initialized)
- throw new TInvalidOperationException('assetmanager_baseurl_unchangeable');
- else
- $this->_baseUrl=rtrim($value,'/');
- }
-
- public function getPublishedUrl($path)
- {
- if(($fullpath=realpath($path))!==false)
- {
- $dir=$this->hash(dirname($fullpath));
- $file=$this->_basePath.'/'.$dir.'/'.basename($fullpath);
- if(is_file($file) || is_dir($file))
- return $this->_baseUrl.'/'.$dir.'/'.basename($fullpath);
- }
- return null;
- }
-
- public function isPublished($path)
- {
- return $this->getPublishedUrl($path) !== null;
- }
-
- /**
- * Publishes a file or a directory (recursively).
- * This method will copy the content in a directory (recursively) to
- * a web accessible directory and returns the URL for the directory.
- * @param string the path to be published
- * @param boolean whether to use file modify time to ensure every published file is latest
- * @return string an absolute URL to the published directory
- */
- public function publishFilePath($path,$checkTimestamp=false)
- {
- if(isset($this->_published[$path]))
- return $this->_published[$path];
- else if(($fullpath=realpath($path))===false)
- return '';
- else if(is_file($fullpath))
- {
- $dir=$this->hash(dirname($fullpath));
- $file=$this->_basePath.'/'.$dir.'/'.basename($fullpath);
- if(!is_file($file) || $checkTimestamp || $this->getApplication()->getMode()!==TApplication::STATE_PERFORMANCE)
- {
- if(!is_dir($this->_basePath.'/'.$dir))
- @mkdir($this->_basePath.'/'.$dir);
- if(!is_file($file) || @filemtime($file)<@filemtime($fullpath))
- {
- Prado::trace("Publishing file $fullpath",'System.Web.UI.TAssetManager');
- @copy($fullpath,$file);
- }
- }
- $this->_published[$path]=$this->_baseUrl.'/'.$dir.'/'.basename($fullpath);
- return $this->_published[$path];
- }
- else
- {
- $dir=$this->hash($fullpath);
- if(!is_dir($this->_basePath.'/'.$dir) || $checkTimestamp || $this->getApplication()->getMode()!==TApplication::STATE_PERFORMANCE)
- {
- Prado::trace("Publishing directory $fullpath",'System.Web.UI.TAssetManager');
- $this->copyDirectory($fullpath,$this->_basePath.'/'.$dir);
- }
- $this->_published[$path]=$this->_baseUrl.'/'.$dir;
- return $this->_published[$path];
- }
- }
-
- /**
- * Generate a CRC32 hash for the directory path. Collisions are higher
- * than MD5 but generates a much smaller hash string.
- * @param string string to be hashed.
- * @return string hashed string.
- */
- protected function hash($dir)
- {
- return sprintf('%x',crc32($dir));
- }
-
- /**
- * Copies a directory recursively as another.
- * If the destination directory does not exist, it will be created.
- * File modification time is used to ensure the copied files are latest.
- * @param string the source directory
- * @param string the destination directory
- */
- protected function copyDirectory($src,$dst)
- {
- if(!is_dir($dst))
- @mkdir($dst);
- $folder=@opendir($src);
- while($file=@readdir($folder))
- {
- if($file==='.' || $file==='..')
- continue;
- else if(is_file($src.'/'.$file))
- {
- if(@filemtime($dst.'/'.$file)<@filemtime($src.'/'.$file))
- @copy($src.'/'.$file,$dst.'/'.$file);
- }
- else
- $this->copyDirectory($src.'/'.$file,$dst.'/'.$file);
- }
- closedir($folder);
- }
-}
-
-?> \ No newline at end of file
diff --git a/framework/Web/UI/TClientScriptManager.php b/framework/Web/UI/TClientScriptManager.php
index 0ff99aa2..1ea4175d 100644
--- a/framework/Web/UI/TClientScriptManager.php
+++ b/framework/Web/UI/TClientScriptManager.php
@@ -10,76 +10,6 @@
* @package System.Web.UI
*/
-/*class TPostBackOptions extends TComponent
-{
- public $_actionUrl='';
- public $_autoPostBack=false;
- public $_clientSubmit=true;
- public $_performValidation=false;
- public $_validationGroup='';
- public $_trackFocus=false;
-
- public function getActionUrl()
- {
- return $this->_actionUrl;
- }
-
- public function setActionUrl($value)
- {
- $this->_actionUrl=THttpUtility::quoteJavaScriptString($value);
- }
-
- public function getAutoPostBack()
- {
- return $this->_autoPostBack;
- }
-
- public function setAutoPostBack($value)
- {
- $this->_autoPostBack=$value;
- }
-
- public function getClientSubmit()
- {
- return $this->_clientSubmit;
- }
-
- public function setClientSubmit($value)
- {
- $this->_clientSubmit=$value;
- }
-
- public function getPerformValidation()
- {
- return $this->_performValidation;
- }
-
- public function setPerformValidation($value)
- {
- $this->_performValidation=$value;
- }
-
- public function getValidationGroup()
- {
- return $this->_validationGroup;
- }
-
- public function setValidationGroup($value)
- {
- $this->_validationGroup=$value;
- }
-
- public function getTrackFocus()
- {
- return $this->_trackFocus;
- }
-
- public function setTrackFocus($value)
- {
- $this->_trackFocus=$value;
- }
-}
-*/
Prado::using('System.Web.Javascripts.*');
/**
@@ -94,21 +24,21 @@ class TClientScriptManager extends TComponent
{
const SCRIPT_DIR='Web/Javascripts/js';
//const POSTBACK_FUNC='Prado.doPostBack';
-
+
private $_page;
private $_hiddenFields=array();
private $_beginScripts=array();
private $_endScripts=array();
private $_scriptFiles=array();
-
+
//private $_headScriptFiles=array();
//private $_headScripts=array();
-
+
private $_styleSheetFiles=array();
private $_styleSheets=array();
-
+
private $_client;
-
+
/*private $_onSubmitStatements=array();
private $_arrayDeclares=array();
private $_expandoAttributes=array();
@@ -116,17 +46,17 @@ class TClientScriptManager extends TComponent
private $_focusScriptRegistered=false;
private $_scrollScriptRegistered=false;
*/
-
+
private $_publishedScriptFiles=array();
-
+
public function __construct(TPage $owner)
{
$this->_page=$owner;
$this->_client = new TClientScript($this);
}
-
-
+
+
public function registerPostBackControl($control,$namespace='Prado.WebUI')
{
$options = $this->getPostBackOptions($control);
@@ -134,7 +64,7 @@ class TClientScriptManager extends TComponent
$namespace = empty($namespace) ? "window" : $namespace;
$code = "new {$namespace}.{$type}($options);";
$this->registerEndScript(sprintf('%08X', crc32($code)), $code);
-
+
$this->registerHiddenField(TPage::FIELD_POSTBACK_TARGET,'');
$this->registerHiddenField(TPage::FIELD_POSTBACK_PARAMETER,'');
$this->registerClientScript('prado');
@@ -143,7 +73,7 @@ class TClientScriptManager extends TComponent
protected function getPostBackOptions($control)
{
$postback = $control->getPostBackOptions();
- if(!isset($postback['ID']))
+ if(!isset($postback['ID']))
$postback['ID'] = $control->getClientID();
if(!isset($postback['FormID']))
$postback['FormID'] = $this->_page->getForm()->getClientID();
@@ -152,7 +82,7 @@ class TClientScriptManager extends TComponent
}
/**
- * Register a default button to panel. When the $panel is in focus and
+ * Register a default button to panel. When the $panel is in focus and
* the 'enter' key is pressed, the $button will be clicked.
* @param TControl panel to register the default button action
* @param TControl button to trigger a postback
@@ -180,12 +110,12 @@ class TClientScriptManager extends TComponent
/**
- * Register client scripts.
+ * Register client scripts.
*/
public function registerClientScript($script)
{
static $scripts = array();
- $scripts = array_unique(array_merge($scripts,
+ $scripts = array_unique(array_merge($scripts,
TClientScript::getScripts($script)));
$this->publishClientScriptAssets($scripts);
@@ -209,9 +139,8 @@ class TClientScriptManager extends TComponent
{
$base = Prado::getFrameworkPath();
$clientScripts = self::SCRIPT_DIR;
- $assetManager = $this->_page->getService()->getAssetManager();
$file = "{$base}/{$clientScripts}/{$lib}.js";
- $assetManager->publishFilePath($file);
+ $this->publishFilePath($file);
$this->_publishedScriptFiles[$lib] = true;
}
}
@@ -229,9 +158,8 @@ class TClientScriptManager extends TComponent
{
$base = Prado::getFrameworkPath();
$clientScripts = self::SCRIPT_DIR;
- $assetManager = $this->_page->getService()->getAssetManager();
$file = "{$base}/{$clientScripts}/{$scriptFile}";
- $url= $assetManager->publishFilePath($file);
+ $url= $this->publishFilePath($file);
$this->_publishedScriptFiles[$scriptFile] = $url;
return $url;
}
@@ -485,7 +413,7 @@ class TClientScriptManager extends TComponent
{
return "<script type=\"text/javascript\">\n/*<![CDATA[*/\n{$code}\n/*]]>*/\n</script>";
}
-
+
public function renderStyleSheetFiles($writer)
{
$str='';
@@ -535,4 +463,204 @@ class TClientScriptManager extends TComponent
*/
}
+/**
+ * PradoClientScript class.
+ *
+ * Resolves Prado client script dependencies. e.g. TPradoClientScript::getScripts("dom");
+ *
+ * - <b>base</b> basic javascript utilities, e.g. $()
+ * - <b>dom</b> DOM and Form functions, e.g. $F(inputID) to retrive form input values.
+ * - <b>effects</b> Effects such as fade, shake, move
+ * - <b>controls</b> Prado client-side components, e.g. Slider, AJAX components
+ * - <b>validator</b> Prado client-side validators.
+ * - <b>ajax</b> Prado AJAX library including Prototype's AJAX and JSON.
+ *
+ * Dependencies for each library are automatically resolved.
+ *
+ * Namespace: System.Web.UI
+ *
+ * @author Wei Zhuo<weizhuo[at]gmail[dot]com>
+ * @version $Revision: 1.1 $ $Date: 2005/11/06 23:02:33 $
+ * @package System.Web.UI
+ */
+class TPradoClientScript
+{
+ /**
+ * Client-side javascript library dependencies
+ * @var array
+ */
+ protected static $_dependencies = array(
+ 'prado' => array('prado'),
+ 'effects' => array('prado', 'effects'),
+ 'ajax' => array('prado', 'effects', 'ajax'),
+ 'validator' => array('prado', 'validator'),
+ 'logger' => array('prado', 'logger'),
+ 'datepicker' => array('prado', 'datepicker'),
+ 'rico' => array('prado', 'effects', 'ajax', 'rico'),
+ 'colorpicker' => array('prado', 'colorpicker')
+ );
+
+ /**
+ * Resolve dependencies for the given library name(s).
+ * @param string|array name(s) of the library to be loaded.
+ * @return array list of library file names (w/o extension) for the specified library name(s).
+ */
+ public function getScripts($scripts)
+ {
+ $files = array();
+ if(!is_array($scripts)) $scripts = array($scripts);
+ foreach($scripts as $script)
+ {
+ if(isset(self::$_dependencies[$script]))
+ $files = array_merge($files, self::$_dependencies[$script]);
+ $files[] = $script;
+ }
+ $files = array_unique($files);
+ return $files;
+ }
+
+
+ /**
+ * TODO: clean up
+ *
+ public function getPostBackEventReference($control,$parameter='',$options=null,$javascriptPrefix=true)
+ {
+ if(!$options || (!$options->getPerformValidation() && !$options->getTrackFocus() && $options->getClientSubmit() && $options->getActionUrl()==''))
+ {
+ $this->registerPostBackScript();
+ if(($form=$this->_page->getForm())!==null)
+ $formID=$form->getClientID();
+ else
+ throw new TConfigurationException('clientscriptmanager_form_required');
+ $postback=self::POSTBACK_FUNC.'(\''.$formID.'\',\''.$control->getUniqueID().'\',\''.THttpUtility::quoteJavaScriptString($parameter).'\')';
+ if($options && $options->getAutoPostBack())
+ $postback='setTimeout(\''.THttpUtility::quoteJavaScriptString($postback).'\',0)';
+ return $javascriptPrefix?'javascript:'.$postback:$postback;
+ }
+ $opt='';
+ $flag=false;
+ if($options->getPerformValidation())
+ {
+ $flag=true;
+ $this->registerValidationScript();
+ $opt.=',true,';
+ }
+ else
+ $opt.=',false,';
+ if($options->getValidationGroup()!=='')
+ {
+ $flag=true;
+ $opt.='"'.$options->getValidationGroup().'",';
+ }
+ else
+ $opt.='\'\',';
+ if($options->getActionUrl()!=='')
+ {
+ $flag=true;
+ $this->_page->setCrossPagePostBack(true);
+ $opt.='"'.$options->getActionUrl().'",';
+ }
+ else
+ $opt.='null,';
+ if($options->getTrackFocus())
+ {
+ $flag=true;
+ $this->registerFocusScript();
+ $opt.='true,';
+ }
+ else
+ $opt.='false,';
+ if($options->getClientSubmit())
+ {
+ $flag=true;
+ $opt.='true';
+ }
+ else
+ $opt.='false';
+ if(!$flag)
+ return '';
+ $this->registerPostBackScript();
+ if(($form=$this->_page->getForm())!==null)
+ $formID=$form->getClientID();
+ else
+ throw new TConfigurationException('clientscriptmanager_form_required');
+ $postback=self::POSTBACK_FUNC.'(\''.$formID.'\',\''.$control->getUniqueID().'\',\''.THttpUtility::quoteJavaScriptString($parameter).'\''.$opt.')';
+ if($options && $options->getAutoPostBack())
+ $postback='setTimeout(\''.THttpUtility::quoteJavaScriptString($postback).'\',0)';
+ return $javascriptPrefix?'javascript:'.$postback:$postback;
+ }*/
+
+}
+
+/*class TPostBackOptions extends TComponent
+{
+ public $_actionUrl='';
+ public $_autoPostBack=false;
+ public $_clientSubmit=true;
+ public $_performValidation=false;
+ public $_validationGroup='';
+ public $_trackFocus=false;
+
+ public function getActionUrl()
+ {
+ return $this->_actionUrl;
+ }
+
+ public function setActionUrl($value)
+ {
+ $this->_actionUrl=THttpUtility::quoteJavaScriptString($value);
+ }
+
+ public function getAutoPostBack()
+ {
+ return $this->_autoPostBack;
+ }
+
+ public function setAutoPostBack($value)
+ {
+ $this->_autoPostBack=$value;
+ }
+
+ public function getClientSubmit()
+ {
+ return $this->_clientSubmit;
+ }
+
+ public function setClientSubmit($value)
+ {
+ $this->_clientSubmit=$value;
+ }
+
+ public function getPerformValidation()
+ {
+ return $this->_performValidation;
+ }
+
+ public function setPerformValidation($value)
+ {
+ $this->_performValidation=$value;
+ }
+
+ public function getValidationGroup()
+ {
+ return $this->_validationGroup;
+ }
+
+ public function setValidationGroup($value)
+ {
+ $this->_validationGroup=$value;
+ }
+
+ public function getTrackFocus()
+ {
+ return $this->_trackFocus;
+ }
+
+ public function setTrackFocus($value)
+ {
+ $this->_trackFocus=$value;
+ }
+}
+*/
+
?> \ No newline at end of file
diff --git a/framework/Web/UI/TControl.php b/framework/Web/UI/TControl.php
index 49ba629f..4f905a1a 100644
--- a/framework/Web/UI/TControl.php
+++ b/framework/Web/UI/TControl.php
@@ -297,21 +297,6 @@ class TControl extends TComponent
}
/**
- * Publishes a private asset and gets its URL.
- * This method will publish a private asset (file or directory)
- * and gets the URL to the asset. Note, if the asset refers to
- * a directory, all contents under that directory will be published.
- * @param string path of the asset that is relative to the directory containing the control class file.
- * @return string URL to the asset path.
- */
- public function getAsset($assetPath)
- {
- $class=new ReflectionClass(get_class($this));
- $assetPath=dirname($class->getFileName()).'/'.$assetPath;
- return $this->getService()->getAsset($assetPath);
- }
-
- /**
* Returns the id of the control.
* Control ID can be either manually set or automatically generated.
* If $hideAutoID is true, automatically generated ID will be returned as an empty string.
diff --git a/framework/Web/UI/TTemplateManager.php b/framework/Web/UI/TTemplateManager.php
index 4c71de51..67bda1b2 100644
--- a/framework/Web/UI/TTemplateManager.php
+++ b/framework/Web/UI/TTemplateManager.php
@@ -183,10 +183,6 @@ class TTemplate extends TComponent implements ITemplate
*/
private $_tplFile=null;
/**
- * @var TAssetManager asset manager
- */
- private $_assetManager;
- /**
* @var integer the line number that parsing starts from (internal use)
*/
private $_startingLine=0;
@@ -264,7 +260,6 @@ class TTemplate extends TComponent implements ITemplate
{
if(($page=$tplControl->getPage())===null)
$page=$this->getService()->getRequestedPage();
- $this->_assetManager=$this->getService()->getAssetManager();
$controls=array();
foreach($this->_tpl as $key=>$object)
{
@@ -376,7 +371,7 @@ class TTemplate extends TComponent implements ITemplate
$component->$setter($value[1]);
break;
case self::CONFIG_ASSET: // asset URL
- $url=$this->_assetManager->publishFilePath($this->_contextPath.'/'.$value[1]);
+ $url=$this->publishFilePath($this->_contextPath.'/'.$value[1]);
$component->$setter($url);
break;
case self::CONFIG_PARAMETER: // application parameter
@@ -416,7 +411,7 @@ class TTemplate extends TComponent implements ITemplate
$component->setSubProperty($name,$value[1]);
break;
case self::CONFIG_ASSET: // asset URL
- $url=$this->_assetManager->publishFilePath($this->_contextPath.'/'.$value[1]);
+ $url=$this->publishFilePath($this->_contextPath.'/'.$value[1]);
$component->setSubProperty($name,$url);
break;
case self::CONFIG_PARAMETER: // application parameter
diff --git a/framework/Web/UI/WebControls/TColorPicker.php b/framework/Web/UI/WebControls/TColorPicker.php
index f168aa5f..2a19125b 100644
--- a/framework/Web/UI/WebControls/TColorPicker.php
+++ b/framework/Web/UI/WebControls/TColorPicker.php
@@ -133,7 +133,7 @@ class TColorPicker extends TTextBox
$cs = $this->getPage()->getClientScript();
$style = 'System.Web.Javascripts.colorpicker.'.$this->getColorPickerStyle();
$cssFile=Prado::getPathOfNamespace($style,'.css');
- $url = $this->getService()->getAsset($cssFile);
+ $url = $this->publishFilePath($cssFile);
if(!$cs->isStyleSheetFileRegistered($style))
$cs->registerStyleSheetFile($style, $url);
return $url;
@@ -158,7 +158,7 @@ class TColorPicker extends TTextBox
{
$image = 'System.Web.Javascripts.colorpicker.'.$filename;
$file = Prado::getPathOfNamespace($image, $ext);
- $list[$filename.$ext] = $this->getService()->getAsset($file);
+ $list[$filename.$ext] = $this->publishFilePath($file);
}
$imgs['button.gif'] = $list['button.gif'];
$imgs['background.png'] = $list['background.png'];
diff --git a/framework/Web/UI/WebControls/TDatePicker.php b/framework/Web/UI/WebControls/TDatePicker.php
index e7e68f6f..6f5eaffb 100644
--- a/framework/Web/UI/WebControls/TDatePicker.php
+++ b/framework/Web/UI/WebControls/TDatePicker.php
@@ -330,7 +330,7 @@ class TDatePicker extends TTextBox
$cs = $this->getPage()->getClientScript();
$image = 'System.Web.Javascripts.datepicker.calendar';
$file = Prado::getPathOfNamespace($image, '.png');
- return $this->getService()->getAsset($file);
+ return $this->publishFilePath($file);
}
/**
@@ -342,7 +342,7 @@ class TDatePicker extends TTextBox
$cs = $this->getPage()->getClientScript();
$style = 'System.Web.Javascripts.datepicker.'.$this->getCalendarStyle();
$cssFile=Prado::getPathOfNamespace($style,'.css');
- $url = $this->getService()->getAsset($cssFile);
+ $url = $this->publishFilePath($cssFile);
if(!$cs->isStyleSheetFileRegistered($style))
$cs->registerStyleSheetFile($style, $url);
return $url;
diff --git a/framework/Web/UI/WebControls/TRatingList.php b/framework/Web/UI/WebControls/TRatingList.php
index 6613c08b..3c5a9279 100644
--- a/framework/Web/UI/WebControls/TRatingList.php
+++ b/framework/Web/UI/WebControls/TRatingList.php
@@ -80,22 +80,22 @@ class TRatingList extends TRadioButtonList
{
$cs = $this->getPage()->getClientScript();
$style = $this->getRatingStyle()->getStyleSheet();
- $url = $this->getService()->getAsset($style);
+ $url = $this->publishFilePath($style);
if(!$cs->isStyleSheetFileRegistered($style))
- $cs->registerStyleSheetFile($style, $url);
+ $cs->registerStyleSheetFile($style, $url);
return $url;
}
-
+
protected function publishRatingListAssets()
{
$cs = $this->getPage()->getClientScript();
$assets = $this->getRatingStyle()->getAssets();
$list = array();
foreach($assets as $file)
- $list[] = $this->getService()->getAsset($file);
+ $list[] = $this->publishFilePath($file);
return $list;
}
-
+
/**
* @param THtmlWriter writer
*/
@@ -146,7 +146,7 @@ abstract class TRatingListStyle
}
class TRatingListDefaultStyle extends TRatingListStyle
-{
+{
public function __construct()
{
parent::__construct();
diff --git a/framework/Web/UI/WebControls/TTextHighlighter.php b/framework/Web/UI/WebControls/TTextHighlighter.php
index 80358ff6..281f131e 100644
--- a/framework/Web/UI/WebControls/TTextHighlighter.php
+++ b/framework/Web/UI/WebControls/TTextHighlighter.php
@@ -123,7 +123,7 @@ class TTextHighlighter extends TWebControl
if(!$cs->isStyleSheetFileRegistered($cssKey))
{
$cssFile=Prado::getPathOfNamespace('System.3rdParty.geshi.highlight','.css');
- $styleSheet = $this->getService()->getAsset($cssFile);
+ $styleSheet = $this->publishFilePath($cssFile);
$cs->registerStyleSheetFile($cssKey, $styleSheet);
}
}