diff options
| -rw-r--r-- | HISTORY | 4 | ||||
| -rw-r--r-- | UPGRADE | 5 | ||||
| -rwxr-xr-x | bin/prado-cli.php | 2 | ||||
| -rw-r--r-- | build.xml | 12 | ||||
| -rw-r--r-- | buildscripts/classtree/build.php | 1 | ||||
| -rw-r--r-- | buildscripts/phing/tasks/PradoVersionTask.php | 15 | ||||
| -rw-r--r-- | buildscripts/texbuilder/quickstart/quickstart.tex | 2 | ||||
| -rw-r--r-- | composer.json | 19 | ||||
| -rw-r--r-- | composer.lock | 133 | ||||
| -rwxr-xr-x | demos/quickstart/protected/pages/Controls/Samples/TConditional/Home.page | 4 | ||||
| -rwxr-xr-x | demos/quickstart/protected/pages/Fundamentals/Components.page | 211 | ||||
| -rwxr-xr-x | demos/quickstart/protected/pages/GettingStarted/HelloWorld.page | 1 | ||||
| -rwxr-xr-x | demos/quickstart/protected/pages/GettingStarted/NewFeatures.page | 2 | ||||
| -rw-r--r-- | framework/PradoBase.php | 2 | ||||
| -rw-r--r-- | framework/Web/Javascripts/source/prado/prado.js | 2 | ||||
| -rw-r--r-- | framework/pradolite.php | 698 | ||||
| -rw-r--r-- | index.html | 2 | 
17 files changed, 983 insertions, 132 deletions
@@ -1,4 +1,4 @@ -Version 3.2.3 to be released +Version 3.2.3 Nov 26, 2013  BUG: Issue #467 - TSafeHtml error on php 5.5 (ctrlaltca)  BUG: Issue #470 - Problem escaping characters in TActiveDropDownList (ctrlaltca) @@ -18,7 +18,7 @@ EHN: Issue #260 - TComponent Update: Behaviors, Class Behaviors, fx global event  EHN: Issue #292 - Events should have priorities to allow event handler order to be specified (javalizard)  BUG: TDatePicker can't render css attributes class "datepicker_year_options" (m_rizki_r)  ENH: Added THtmlArea4 based on TinyMCE4 (ctrlaltca) - +BUG: TDatePicker renders a spurious TTextBox (ctrlaltca)  Version 3.2.2 Jul 20, 2013 @@ -1,5 +1,5 @@ -         Upgrading Instructions for PRADO Framework v3.2.2 +         Upgrading Instructions for PRADO Framework v3.2.3           =================================================  !!!IMPORTANT!!! @@ -9,6 +9,9 @@ if you want to upgrade from version A to version C and there is  version B between A and C, you need to following the instructions  for both A and B. +Upgrading from v3.2.2 +--------------------- +  Upgrading from v3.2.1  ---------------------  - TEmailAddressValidator's CheckMXRecord property now defaults to false. diff --git a/bin/prado-cli.php b/bin/prado-cli.php index 4fa70c08..b4b43062 100755 --- a/bin/prado-cli.php +++ b/bin/prado-cli.php @@ -569,7 +569,7 @@ class PradoCommandLineUnitTest extends PradoCommandLineAction  				if($match==null||($match!=null && $this->hasMatch($match,$entry)))  					$test->addTestFile($path.'/'.$entry);  			} -			if($entry!=='.' && $entry!=='..' && $entry!=='.svn' && is_dir($path.'/'.$entry) && $recursive) +			if($entry!=='.' && $entry!=='..' && is_dir($path.'/'.$entry) && $recursive)  				$this->addTests($test,$path.'/'.$entry,$recursive,$match);  		}  		closedir($dir); @@ -37,7 +37,6 @@        All Source Files in framework    -->    <fileset dir="." id="framework"> -    <exclude name="**/.svn"/>      <exclude name="**/*.bak"/>      <exclude name="**/*~"/>      <exclude name="**/pradolite.php"/><!-- will be generated --> @@ -58,7 +57,6 @@        Surrounding files    -->    <fileset dir="." id="misc"> -    <exclude name="**/.svn"/>      <exclude name="**/*.bak"/>      <exclude name="**/*~"/>      <include name="COPYRIGHT"/> @@ -72,7 +70,6 @@        Documentation    -->    <fileset dir="." id="docs"> -    <exclude name="**/.svn"/>      <exclude name="**/*.bak"/>      <exclude name="**/*~"/>      <exclude name="**/latex"/> @@ -85,7 +82,6 @@        Demos    -->    <fileset dir="." id="demos"> -    <exclude name="**/.svn"/>      <exclude name="**/*.bak"/>      <exclude name="**/*~"/>      <exclude name="**/runtime/*"/> @@ -201,8 +197,6 @@        php="false"        templateconfig="buildscripts/apigen/pradosoft/config.neon"      /> -    <echo>Cleaning svn directories from API manuals...</echo> -    <delete dir="${build.doc.dir}/manual/resources/.svn" includeemptydirs="true" failonerror="true" />      <echo>Indexing API manuals...</echo>      <prado-api-index docdir="${build.doc.dir}/manual" todir="${build.doc.dir}/manual"/> @@ -335,7 +329,6 @@      <echo>Checking php files..</echo>      <phplint deprecatedAsError="true">        <fileset dir="framework"> -        <exclude name="**/.svn"/>          <exclude name="**/*.bak"/>          <exclude name="**/*~"/>          <include name="**/*.php"/> @@ -345,7 +338,6 @@      <echo>Checking js files..</echo>      <jsllint>        <fileset dir="framework"> -        <exclude name="**/.svn"/>          <exclude name="**/*.bak"/>          <exclude name="**/*~"/>          <include name="**/*.js"/> @@ -355,7 +347,6 @@      <echo>Checking xml files..</echo>      <xmllint>        <fileset dir="framework"> -        <exclude name="**/.svn"/>          <exclude name="**/*.bak"/>          <exclude name="**/*~"/>          <include name="**/*.xml"/> @@ -367,7 +358,6 @@      <echo>Checking php files..</echo>      <phplint deprecatedAsError="true">        <fileset dir="demos"> -        <exclude name="**/.svn"/>          <exclude name="**/*.bak"/>          <exclude name="**/*~"/>          <include name="**/*.php"/> @@ -377,7 +367,6 @@      <echo>Checking js files..</echo>      <jsllint>        <fileset dir="demos"> -        <exclude name="**/.svn"/>          <exclude name="**/*.bak"/>          <exclude name="**/*~"/>          <include name="**/*.js"/> @@ -387,7 +376,6 @@      <echo>Checking xml files..</echo>      <xmllint>        <fileset dir="demos"> -        <exclude name="**/.svn"/>          <exclude name="**/*.bak"/>          <exclude name="**/*~"/>          <include name="**/*.xml"/> diff --git a/buildscripts/classtree/build.php b/buildscripts/classtree/build.php index 44700be4..f7b8d7e7 100644 --- a/buildscripts/classtree/build.php +++ b/buildscripts/classtree/build.php @@ -12,7 +12,6 @@ $exclusions=array(  	'pradolite.php',  	'prado-cli.php',  	'JSMin.php', -	'.svn',  	'/I18N/core',  	'/3rdParty',  	'/Testing', diff --git a/buildscripts/phing/tasks/PradoVersionTask.php b/buildscripts/phing/tasks/PradoVersionTask.php index 4310cf60..15c73efd 100644 --- a/buildscripts/phing/tasks/PradoVersionTask.php +++ b/buildscripts/phing/tasks/PradoVersionTask.php @@ -38,17 +38,8 @@ class PradoVersionTask extends PropertyTask  	 */  	private function getPradoRevision()  	{ -		$svnPath=dirname(__FILE__).'/../../../.svn'; -		if(is_file($svnPath.'/all-wcprops')) -			$propFile=$svnPath.'/all-wcprops'; -		else if(is_file($svnPath.'/dir-wcprops')) -			$propFile=$svnPath.'/dir-wcprops'; -		else -			return 'unknown'; -		$contents=file_get_contents($propFile); -		if(preg_match('/\\/svn\\/\\!svn\\/ver\\/(\d+)\\//ms',$contents,$matches)>0) -			return $matches[1]; -		else -			return 'unknown'; +		$rev=shell_exec("git log -1 --pretty=format:'%h'"); +		if($rev===null) $rev='unknown'; +		return $rev;  	}  } diff --git a/buildscripts/texbuilder/quickstart/quickstart.tex b/buildscripts/texbuilder/quickstart/quickstart.tex index deaba73c..41258800 100644 --- a/buildscripts/texbuilder/quickstart/quickstart.tex +++ b/buildscripts/texbuilder/quickstart/quickstart.tex @@ -52,7 +52,7 @@  %----------------- TITLE -------------- -\title{\Huge \bfseries PRADO v3.2.2 Quickstart Tutorial +\title{\Huge \bfseries PRADO v3.2.3 Quickstart Tutorial      \thanks{Copyright 2004-2013. All Rights Reserved.}  }  \author{Qiang Xue and Wei Zhuo} diff --git a/composer.json b/composer.json index 81573d01..26c41985 100644 --- a/composer.json +++ b/composer.json @@ -64,25 +64,6 @@  		"ext-zlib" : "*"  	},  	"include-path": ["framework"], -	"autoload": { -		"psr-0" : { -			"Prado"              : "framework", -			"Prado\\Caching"     : "framework", -			"Prado\\Collections" : "framework", -			"Prado\\Exceptions"  : "framework", -			"Prado\\I18N"        : "framework", -			"Prado\\IO"          : "framework", -			"Prado\\Security"    : "framework", -			"Prado\\Util"        : "framework", -			"Prado\\Web"         : "framework", -			"Prado\\Web\\Javascripts"        : "framework", -			"Prado\\Web\\Services"           : "framework", -			"Prado\\Web\\UI"                 : "framework", -			"Prado\\Web\\UI\\ActiveControls" : "framework", -			"Prado\\Web\\UI\\WebControls"    : "framework", -			"Prado\\Xml"                     : "framework" -		} -	},  	"support" : {  		"forum" : "http://www.pradosoft.com/forum",  		"source" : "https://github.com/pradosoft/prado" diff --git a/composer.lock b/composer.lock index 4a907065..e9fd8533 100644 --- a/composer.lock +++ b/composer.lock @@ -3,7 +3,7 @@          "This file locks the dependencies of your project to a known state",          "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"      ], -    "hash": "5d13e6a7e5d1c16086fabc64d066f227", +    "hash": "16bb0dc37f5f9efa8c30a4538c6d3fba",      "packages": [      ], @@ -180,21 +180,21 @@          },          {              "name": "guzzle/guzzle", -            "version": "v3.7.3", +            "version": "v3.7.4",              "source": {                  "type": "git",                  "url": "https://github.com/guzzle/guzzle.git", -                "reference": "0f16aad385528b5cf790392cb4a4d16cf600e944" +                "reference": "b170b028c6bb5799640e46c8803015b0f9a45ed9"              },              "dist": {                  "type": "zip", -                "url": "https://api.github.com/repos/guzzle/guzzle/zipball/0f16aad385528b5cf790392cb4a4d16cf600e944", -                "reference": "0f16aad385528b5cf790392cb4a4d16cf600e944", +                "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b170b028c6bb5799640e46c8803015b0f9a45ed9", +                "reference": "b170b028c6bb5799640e46c8803015b0f9a45ed9",                  "shasum": ""              },              "require": {                  "ext-curl": "*", -                "php": ">=5.3.2", +                "php": ">=5.3.3",                  "symfony/event-dispatcher": ">=2.1"              },              "replace": { @@ -268,7 +268,7 @@                  "rest",                  "web service"              ], -            "time": "2013-09-08 21:09:18" +            "time": "2013-10-02 20:47:00"          },          {              "name": "kukulich/fshl", @@ -314,16 +314,16 @@          },          {              "name": "nette/nette", -            "version": "v2.0.12", +            "version": "v2.0.13",              "source": {                  "type": "git",                  "url": "https://github.com/nette/nette.git", -                "reference": "80a7e460badc3d71b1469bb23810ebf235b06b11" +                "reference": "695f643c26c2326f08424fee138515fa286a0e07"              },              "dist": {                  "type": "zip", -                "url": "https://api.github.com/repos/nette/nette/zipball/80a7e460badc3d71b1469bb23810ebf235b06b11", -                "reference": "80a7e460badc3d71b1469bb23810ebf235b06b11", +                "url": "https://api.github.com/repos/nette/nette/zipball/695f643c26c2326f08424fee138515fa286a0e07", +                "reference": "695f643c26c2326f08424fee138515fa286a0e07",                  "shasum": ""              },              "require": { @@ -384,7 +384,7 @@                  "neon",                  "templating"              ], -            "time": "2013-08-07 23:14:19" +            "time": "2013-11-05 18:47:49"          },          {              "name": "phing/phing", @@ -440,31 +440,32 @@          },          {              "name": "phpunit/dbunit", -            "version": "1.2.3", +            "version": "1.3.0",              "source": {                  "type": "git",                  "url": "https://github.com/sebastianbergmann/dbunit.git", -                "reference": "8386782a2d55153e44a06eb1a9d13d6ed35d9c2d" +                "reference": "9d8a28bdb41fbd3c0dc16fa32fc00862d06abace"              },              "dist": {                  "type": "zip", -                "url": "https://api.github.com/repos/sebastianbergmann/dbunit/zipball/8386782a2d55153e44a06eb1a9d13d6ed35d9c2d", -                "reference": "8386782a2d55153e44a06eb1a9d13d6ed35d9c2d", +                "url": "https://api.github.com/repos/sebastianbergmann/dbunit/zipball/9d8a28bdb41fbd3c0dc16fa32fc00862d06abace", +                "reference": "9d8a28bdb41fbd3c0dc16fa32fc00862d06abace",                  "shasum": ""              },              "require": {                  "ext-pdo": "*",                  "ext-simplexml": "*",                  "php": ">=5.3.3", -                "phpunit/phpunit": ">=3.7.0@stable" +                "phpunit/phpunit": ">=3.7.0@stable", +                "symfony/yaml": ">=2.1.0"              },              "bin": [ -                "dbunit.php" +                "composer/bin/dbunit"              ],              "type": "library",              "extra": {                  "branch-alias": { -                    "dev-master": "1.2.x-dev" +                    "dev-master": "1.3.x-dev"                  }              },              "autoload": { @@ -494,7 +495,7 @@                  "testing",                  "xunit"              ], -            "time": "2013-03-01 11:50:46" +            "time": "2013-11-04 08:33:33"          },          {              "name": "phpunit/php-code-coverage", @@ -559,16 +560,16 @@          },          {              "name": "phpunit/php-file-iterator", -            "version": "1.3.3", +            "version": "1.3.4",              "source": {                  "type": "git",                  "url": "https://github.com/sebastianbergmann/php-file-iterator.git", -                "reference": "16a78140ed2fc01b945cfa539665fadc6a038029" +                "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb"              },              "dist": {                  "type": "zip", -                "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/16a78140ed2fc01b945cfa539665fadc6a038029", -                "reference": "16a78140ed2fc01b945cfa539665fadc6a038029", +                "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", +                "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb",                  "shasum": ""              },              "require": { @@ -595,12 +596,12 @@                  }              ],              "description": "FilterIterator implementation that filters files based on a list of suffixes.", -            "homepage": "http://www.phpunit.de/", +            "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",              "keywords": [                  "filesystem",                  "iterator"              ], -            "time": "2012-10-11 11:44:38" +            "time": "2013-10-10 15:34:57"          },          {              "name": "phpunit/php-invoker", @@ -788,16 +789,16 @@          },          {              "name": "phpunit/phpunit", -            "version": "3.7.27", +            "version": "3.7.28",              "source": {                  "type": "git",                  "url": "https://github.com/sebastianbergmann/phpunit.git", -                "reference": "4b024e753e3421837afbcca962c8724c58b39376" +                "reference": "3b97c8492bcafbabe6b6fbd2ab35f2f04d932a8d"              },              "dist": {                  "type": "zip", -                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4b024e753e3421837afbcca962c8724c58b39376", -                "reference": "4b024e753e3421837afbcca962c8724c58b39376", +                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3b97c8492bcafbabe6b6fbd2ab35f2f04d932a8d", +                "reference": "3b97c8492bcafbabe6b6fbd2ab35f2f04d932a8d",                  "shasum": ""              },              "require": { @@ -858,7 +859,7 @@                  "testing",                  "xunit"              ], -            "time": "2013-09-16 03:09:52" +            "time": "2013-10-17 07:27:40"          },          {              "name": "phpunit/phpunit-mock-objects", @@ -911,16 +912,16 @@          },          {              "name": "phpunit/phpunit-selenium", -            "version": "1.3.2", +            "version": "1.3.3",              "source": {                  "type": "git",                  "url": "https://github.com/sebastianbergmann/phpunit-selenium.git", -                "reference": "ba8ab98699dc07ede1b9e80a0523238cb5cec3d5" +                "reference": "e89bfa1080dce9617c9b3e7760d50752974bfbd2"              },              "dist": {                  "type": "zip", -                "url": "https://api.github.com/repos/sebastianbergmann/phpunit-selenium/zipball/ba8ab98699dc07ede1b9e80a0523238cb5cec3d5", -                "reference": "ba8ab98699dc07ede1b9e80a0523238cb5cec3d5", +                "url": "https://api.github.com/repos/sebastianbergmann/phpunit-selenium/zipball/e89bfa1080dce9617c9b3e7760d50752974bfbd2", +                "reference": "e89bfa1080dce9617c9b3e7760d50752974bfbd2",                  "shasum": ""              },              "require": { @@ -961,7 +962,7 @@                  "testing",                  "xunit"              ], -            "time": "2013-08-25 12:29:25" +            "time": "2013-11-22 08:54:11"          },          {              "name": "phpunit/phpunit-story", @@ -1121,17 +1122,17 @@          },          {              "name": "symfony/config", -            "version": "v2.3.4", +            "version": "v2.3.7",              "target-dir": "Symfony/Component/Config",              "source": {                  "type": "git",                  "url": "https://github.com/symfony/Config.git", -                "reference": "65a927c15ca5a911ba2fa277a5457fa8129505b0" +                "reference": "1ced3d6c88b22df8cd1fe5209dbd6a89df362a29"              },              "dist": {                  "type": "zip", -                "url": "https://api.github.com/repos/symfony/Config/zipball/65a927c15ca5a911ba2fa277a5457fa8129505b0", -                "reference": "65a927c15ca5a911ba2fa277a5457fa8129505b0", +                "url": "https://api.github.com/repos/symfony/Config/zipball/1ced3d6c88b22df8cd1fe5209dbd6a89df362a29", +                "reference": "1ced3d6c88b22df8cd1fe5209dbd6a89df362a29",                  "shasum": ""              },              "require": { @@ -1165,21 +1166,21 @@              ],              "description": "Symfony Config Component",              "homepage": "http://symfony.com", -            "time": "2013-08-06 05:49:23" +            "time": "2013-09-19 09:45:20"          },          {              "name": "symfony/console", -            "version": "v2.3.4", +            "version": "v2.3.7",              "target-dir": "Symfony/Component/Console",              "source": {                  "type": "git",                  "url": "https://github.com/symfony/Console.git", -                "reference": "db78f8ff7fc9e28d25ff9a0bf6ddf9f0e35fbbe3" +                "reference": "00848d3e13cf512e77c7498c2b3b0192f61f4b18"              },              "dist": {                  "type": "zip", -                "url": "https://api.github.com/repos/symfony/Console/zipball/db78f8ff7fc9e28d25ff9a0bf6ddf9f0e35fbbe3", -                "reference": "db78f8ff7fc9e28d25ff9a0bf6ddf9f0e35fbbe3", +                "url": "https://api.github.com/repos/symfony/Console/zipball/00848d3e13cf512e77c7498c2b3b0192f61f4b18", +                "reference": "00848d3e13cf512e77c7498c2b3b0192f61f4b18",                  "shasum": ""              },              "require": { @@ -1218,21 +1219,21 @@              ],              "description": "Symfony Console Component",              "homepage": "http://symfony.com", -            "time": "2013-08-17 16:34:49" +            "time": "2013-11-13 21:27:40"          },          {              "name": "symfony/event-dispatcher", -            "version": "v2.3.4", +            "version": "v2.3.7",              "target-dir": "Symfony/Component/EventDispatcher",              "source": {                  "type": "git",                  "url": "https://github.com/symfony/EventDispatcher.git", -                "reference": "41c9826457c65fa3cf746f214985b7ca9cba42f8" +                "reference": "2d8ece3c610726a73d0c95c885134efea182610e"              },              "dist": {                  "type": "zip", -                "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/41c9826457c65fa3cf746f214985b7ca9cba42f8", -                "reference": "41c9826457c65fa3cf746f214985b7ca9cba42f8", +                "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/2d8ece3c610726a73d0c95c885134efea182610e", +                "reference": "2d8ece3c610726a73d0c95c885134efea182610e",                  "shasum": ""              },              "require": { @@ -1272,21 +1273,21 @@              ],              "description": "Symfony EventDispatcher Component",              "homepage": "http://symfony.com", -            "time": "2013-07-21 12:12:18" +            "time": "2013-10-13 06:32:10"          },          {              "name": "symfony/filesystem", -            "version": "v2.3.4", +            "version": "v2.3.7",              "target-dir": "Symfony/Component/Filesystem",              "source": {                  "type": "git",                  "url": "https://github.com/symfony/Filesystem.git", -                "reference": "87acbbef6d35ba649f96f09cc572c45119b360c3" +                "reference": "2b8995042086c5552c94d33b5553c492e9cfc00e"              },              "dist": {                  "type": "zip", -                "url": "https://api.github.com/repos/symfony/Filesystem/zipball/87acbbef6d35ba649f96f09cc572c45119b360c3", -                "reference": "87acbbef6d35ba649f96f09cc572c45119b360c3", +                "url": "https://api.github.com/repos/symfony/Filesystem/zipball/2b8995042086c5552c94d33b5553c492e9cfc00e", +                "reference": "2b8995042086c5552c94d33b5553c492e9cfc00e",                  "shasum": ""              },              "require": { @@ -1319,21 +1320,21 @@              ],              "description": "Symfony Filesystem Component",              "homepage": "http://symfony.com", -            "time": "2013-07-21 12:12:18" +            "time": "2013-09-19 09:45:20"          },          {              "name": "symfony/stopwatch", -            "version": "v2.3.4", +            "version": "v2.3.7",              "target-dir": "Symfony/Component/Stopwatch",              "source": {                  "type": "git",                  "url": "https://github.com/symfony/Stopwatch.git", -                "reference": "23333342d7edd461f576b246c6fa7b30b4d9bebe" +                "reference": "2d3491564a1413ea98074c557491b73ae46294ac"              },              "dist": {                  "type": "zip", -                "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/23333342d7edd461f576b246c6fa7b30b4d9bebe", -                "reference": "23333342d7edd461f576b246c6fa7b30b4d9bebe", +                "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/2d3491564a1413ea98074c557491b73ae46294ac", +                "reference": "2d3491564a1413ea98074c557491b73ae46294ac",                  "shasum": ""              },              "require": { @@ -1366,21 +1367,21 @@              ],              "description": "Symfony Stopwatch Component",              "homepage": "http://symfony.com", -            "time": "2013-07-21 12:12:18" +            "time": "2013-10-17 11:48:01"          },          {              "name": "symfony/yaml", -            "version": "v2.3.4", +            "version": "v2.3.7",              "target-dir": "Symfony/Component/Yaml",              "source": {                  "type": "git",                  "url": "https://github.com/symfony/Yaml.git", -                "reference": "5a279f1b5f5e1045a6c432354d9ea727ff3a9847" +                "reference": "c1bda5b459d792cb253de12c65beba3040163b2b"              },              "dist": {                  "type": "zip", -                "url": "https://api.github.com/repos/symfony/Yaml/zipball/5a279f1b5f5e1045a6c432354d9ea727ff3a9847", -                "reference": "5a279f1b5f5e1045a6c432354d9ea727ff3a9847", +                "url": "https://api.github.com/repos/symfony/Yaml/zipball/c1bda5b459d792cb253de12c65beba3040163b2b", +                "reference": "c1bda5b459d792cb253de12c65beba3040163b2b",                  "shasum": ""              },              "require": { @@ -1413,7 +1414,7 @@              ],              "description": "Symfony Yaml Component",              "homepage": "http://symfony.com", -            "time": "2013-08-24 15:26:22" +            "time": "2013-10-17 11:48:01"          }      ],      "aliases": [ diff --git a/demos/quickstart/protected/pages/Controls/Samples/TConditional/Home.page b/demos/quickstart/protected/pages/Controls/Samples/TConditional/Home.page index 9e37b675..5702970a 100755 --- a/demos/quickstart/protected/pages/Controls/Samples/TConditional/Home.page +++ b/demos/quickstart/protected/pages/Controls/Samples/TConditional/Home.page @@ -1,9 +1,9 @@  <com:TContent ID="body">
  <h1>TConditional Samples</h1>
 -<com:TConditional Condition="Prado::getVersion()==='3.2.2'">
 +<com:TConditional Condition="Prado::getVersion()==='3.2.3'">
  <prop:TrueTemplate>
 -  <com:TLabel Text="You are using PRADO 3.2.2" />
 +  <com:TLabel Text="You are using PRADO 3.2.3" />
  </prop:TrueTemplate>
  <prop:FalseTemplate>
    <com:TLabel Text="You are using PRADO <%= Prado::getVersion() %>" />
 diff --git a/demos/quickstart/protected/pages/Fundamentals/Components.page b/demos/quickstart/protected/pages/Fundamentals/Components.page index 9326d89c..11235b56 100755 --- a/demos/quickstart/protected/pages/Fundamentals/Components.page +++ b/demos/quickstart/protected/pages/Fundamentals/Components.page @@ -96,7 +96,216 @@ $button->OnClick->add( $callback );  $button->OnClick[] = $callback;
  $button->attachEventHandler( 'OnClick' , $callback );
  </com:TTextHighlighter>
 -where <tt>$callback</tt> refers to a valid PHP callback (e.g. a function name, a class method <tt>array($object,'method')</tt>, etc.)
 +</p>
 + The variable <tt>$callback</tt> contains the definition of the event handler that can be either a string referring to a global function name, or an array whose first element refers to an object and second element a method name/path that is reachable by the object, e.g.
 + </p>
 +<ul>
 +<li>'buttonClicked' : buttonClicked($sender,$param);</li>
 +<li>array($object,'buttonClicked') : $object->buttonClicked($sender,$param);</li>
 +<li>array($object,'MainContent.SubmitButton.buttonClicked') : $object->MainContent->SubmitButton->buttonClicked($sender,$param);</li>
 +</ul>
 +<com:SinceVersion Version="3.2.3" />
 +<h2 id="26001">Global events</h2>
 +<p id="130001" class="block-content">
 +With the addition of behaviors, a more expansive event model is needed.  There 
 +are two new event types (global and dynamic events) as well as a more comprehensive 
 +behavior model that includes class wide behaviors.
 +</p>
 +<p id="130002" class="block-content">
 +A global event is defined by all events whose name starts with 'fx'.
 +The event name is potentially a method name and is thus case-insensitive. All 'fx' events 
 +are valid as the whole 'fx' event/method space is global in nature. Any object may patch into
 +any global event by defining that event as a method. Global events have priorities 
 +just like 'on' events; so as to be able to order the event execution. Due to the 
 +nature of all events which start with 'fx' being valid, in effect, every object 
 +has every 'fx' global event. It is simply an issue of tapping into the desired 
 +global event.
 +</p>
 +<p id="130003" class="block-content">
 +A global event that starts with 'fx' can be called even if the object does not
 +implement the method of the global event.  A call to a non-existing 'fx' method
 +will, at minimal, function and return null.  If a method argument list has a first 
 +parameter, it will be returned instead of null.  This allows filtering and chaining.
 +'fx' methods do not automatically install and uninstall. To install and uninstall an
 +object's global event listeners, call the object's <tt>listen</tt> and 
 +<tt>unlisten</tt> methods, respectively.  An object may auto-install its global event
 +during <tt>__construct</tt> by overriding <tt>getAutoGlobalListen</tt> and returning true.
 +</p>
 +<p id="130004" class="block-content">
 +As of PHP version 5.3, nulled objects without code references will still continue to persist
 +in the global event queue because <tt>__destruct</tt> is not automatically called.  In the common
 +__destruct method, if an object is listening to global events, then <tt>unlisten</tt> is called.
 +<tt>unlisten</tt> is required to be manually called before an object is
 +left without references if it is currently listening to any global events. This includes 
 +class wide behaviors.
 +</p>
 +<p id="130005" class="block-content">
 +An object that contains a method that starts with 'fx' will have those functions 
 +automatically receive those events of the same name after <tt>listen</tt> is called on the object.
 +</p>
 +<p id="130006" class="block-content">
 +An object may listen to a global event without defining an 'fx' method of the same name by 
 +adding an object method to the global event list.  For example
 +</p>
 +<com:TTextHighlighter CssClass="source block-content">
 +$component->fxGlobalCheck=$callback;  // or $component->OnClick->add($callback);
 +$component->attachEventHandler('fxGlobalCheck',array($object, 'someMethod'));
 +</com:TTextHighlighter>
 +<h2 id="26002">Events between Objects and their behaviors, Dynamic Events</h2>
 +<p id="130007" class="block-content">
 +An intra-object/behavior event is defined by methods that start with 'dy'.  Just as with 
 +'fx' global events, every object has every dynamic event.  Any call to a method that
 +starts with 'dy' will be handled, regardless of whether it is implemented.  These 
 +events are for communicating with attached behaviors.
 +</p>
 +<p id="130008" class="block-content">
 +Dynamic events can be used in a variety of ways.  They can be used to tell behaviors
 +when a non-behavior method is called.  Dynamic events could be used as data filters.
 +They could also be used to specify when a piece of code is to be run, eg. should the 
 +loop process be performed on a particular piece of data.  In this way, some control
 +is handed to the behaviors over the process and/or data.
 +</p>
 +<p id="130009" class="block-content">
 +If there are no handlers for an 'fx' or 'dy' event, it will return the first
 +parameter of the argument list.  If there are no arguments, these events
 +will return null.  If there are handlers an 'fx' method will be called directly
 +within the object.  Global 'fx' events are triggered by calling <tt>raiseEvent</tt>.
 +For dynamic events where there are behaviors that respond to the dynamic events, a 
 +<tt>TCallChain</tt> is developed.  A call chain allows the behavior dynamic event
 +implementations to call further implementing behaviors within a chain.
 +</p>
 +<p id="130010" class="block-content">
 +If an object implements <tt>IDynamicMethods</tt>, all global and object dynamic 
 +events will be sent to <tt>__dycall</tt>.  In the case of global events, all 
 +global events will trigger this method.  In the case of behaviors, all undefined
 +dynamic events  which are called will be passed through to this method.
 +</p>
 +<p id="130011" class="block-content">
 +<h2 id="26003">Behaviors</h2>
 +<p id="130012" class="block-content">
 +There are two types of behaviors.  There are individual object behaviors and
 +there are class wide behaviors.  Class behaviors depend upon object behaviors.
 +</p>
 +<p id="130013" class="block-content">
 +When a new class implements <tt>IBehavior</tt> or <tt>IClassBehavior</tt> or
 +extends <tt>TBehavior</tt> or <tt>TClassBehavior</tt>, it may be added to an 
 +object by calling the object's <tt>attachBehavior</tt>.  The behaviors associated
 +name can then be used to <tt>enableBehavior</tt> or <tt>disableBehavior</tt> 
 +the specific behavior.
 +</p>
 +<p id="130014" class="block-content">
 +All behaviors may be turned on and off via <tt>enableBehaviors</tt> and 
 +<tt>disableBehaviors</tt>, respectively.  To check if behaviors are on or off
 +a call to <tt>getBehaviorsEnabled</tt> will provide the variable.
 +</p>
 +<p id="130015" class="block-content">
 +Attaching and detaching whole sets of behaviors is done using 
 +<tt>attachBehaviors</tt> and <tt>detachBehaviors</tt>.  <tt>clearBehaviors</tt>
 +removes all of an object's behaviors.
 +</p>
 +<p id="130016" class="block-content">
 +<tt>asa</tt> returns a behavior of a specific name.  <tt>isa</tt> is the
 +behavior inclusive function that acts as the PHP operator <tt>instanceof</tt>.
 +A behavior could provide the functionality of a specific class thus causing
 +the host object to act similarly to a completely different class.  A behavior 
 +would then implement <tt>IInstanceCheck</tt> to provide the identity of the 
 +different class.
 +</p>
 +<p id="130017" class="block-content">
 +Class behaviors are similar to object behaviors except that the class behavior 
 +is the implementation for all instances of the class.  A class behavior
 +will have the object upon which is being called be prepended to the parameter
 +list.  This way the object is known across the class behavior implementation.
 +</p>
 +<p id="130018" class="block-content">
 +Class behaviors are attached using <tt>attachClassBehavior</tt> and detached
 +using <tt>detachClassBehavior</tt>.  Class behaviors are important in that
 +they will be applied to all new instances of a particular class.  In this way
 +class behaviors become default behaviors to a new instances of a class in
 +<tt>__construct</tt>.  Detaching a class behavior will remove the behavior 
 +from the default set of behaviors created for an object when the object
 +is instanced.
 +</p>
 +<p id="130019" class="block-content">
 +Class behaviors are also added to all existing instances via the global 'fx' 
 +event mechanism.  When a new class behavior is added, the event 
 +<tt>fxAttachClassBehavior</tt> is raised and all existing instances that are
 +listening to this global event (primarily after <tt>listen</tt> is called)
 +will have this new behavior attached.  A similar process is used when
 +detaching class behaviors.  Any objects listening to the global 'fx' event
 +<tt>fxDetachClassBehavior</tt> will have a class behavior removed.
 +</p>
 +<h2 id="26004">Dynamic Intra-Object Events</h2>
 +<p id="130020" class="block-content">
 +Dynamic events start with 'dy'.  This mechanism is used to allow objects
 +to communicate with their behaviors directly.  The entire 'dy' event space
 +is valid.  All attached, enabled behaviors that implement a dynamic event 
 +are called when the host object calls the dynamic event.  If there is no 
 +implementation or behaviors, this returns null when no parameters are
 +supplied and will return the first parameter when there is at least one
 +parameter in the dynamic event.
 +</p>
 +<com:TTextHighlighter CssClass="source block-content">
 +	null == $this->dyBehaviorEvent();
 +	5 == $this->dyBehaviorEvent(5); //when no behaviors implement this dynamic event
 +</com:TTextHighlighter>
 +<p id="130021" class="block-content">
 +Dynamic events can be chained together within behaviors to allow for data 
 +filtering. Dynamic events are implemented within behaviors by defining the
 +event as a method.
 +</p>
 +<com:TTextHighlighter CssClass="source block-content">
 +class TObjectBehavior extends TBehavior {
 +    public function dyBehaviorEvent($param1, $callchain) {
 +			//Do something, eg:  $param1 += 13;
 +			return $callchain->dyBehaviorEvent($param1);
 +    }
 +}
 +</com:TTextHighlighter>
 +<p id="130022" class="block-content">
 +This implementation of a behavior and dynamic event will flow through to the 
 +next behavior implementing the dynamic event.  The first parameter is always 
 +return when it is supplied.  Otherwise a dynamic event returns null.
 +</p>
 +<p id="130023" class="block-content">
 +In the case of a class behavior, the object is also prepended to the dynamic
 +event.
 +</p>
 +<com:TTextHighlighter CssClass="source block-content">
 +class TObjectClassBehavior extends TClassBehavior {
 +    public function dyBehaviorEvent($hostobject, $param1, $callchain) {
 +			//Do something, eg:  $param1 += $hostobject->getNumber();
 +			return $callchain->dyBehaviorEvent($param1);
 +    }
 +}
 +</com:TTextHighlighter>
 +</p>
 +<p id="130024" class="block-content">
 +When calling a dynamic event, only the parameters are passed.  The host object
 +and the call chain are built into the framework.
 +</p>
 +
 +<h2 id="26005">Global Event and Dynamic event catching</h2>
 +
 +<p id="130025" class="block-content">
 +Given that all global 'fx' events and dynamic 'dy' events are valid and 
 +operational, there is a mechanism for catching events called that are not
 +implemented (similar to the built-in PHP method <tt>__call</tt>).  When
 +a dynamic or global event is called but a behavior does not implement it, 
 +yet desires to know when an undefined dynamic event is run, the behavior 
 +implements the interface <tt>IDynamicMethods</tt> and method <tt>__dycall</tt>.
 +</p>
 +<p id="130026" class="block-content">
 +In the case of dynamic events, <tt>__dycall</tt> is supplied with the method 
 +name and its parameters.  When a global event is raised, via <tt>raiseEvent</tt>,
 +the method is the event name and the parameters are supplied.
 +</p>
 +<p id="130027" class="block-content">
 +When implemented, this catch-all mechanism is called for event global event event
 +when implemented outside of a behavior.  Within a behavior, it will also be called
 +when the object to which the behavior is attached calls any unimplemented dynamic 
 +event.  This is the fall-back mechanism for informing a class and/or behavior 
 +of when an global and/or undefined dynamic event is executed.
  </p>
  <h2 id="704">Namespaces</h2>
 diff --git a/demos/quickstart/protected/pages/GettingStarted/HelloWorld.page b/demos/quickstart/protected/pages/GettingStarted/HelloWorld.page index c69921f8..557aa46d 100755 --- a/demos/quickstart/protected/pages/GettingStarted/HelloWorld.page +++ b/demos/quickstart/protected/pages/GettingStarted/HelloWorld.page @@ -60,6 +60,7 @@ $application->run();                // run the application  </li>
  <li><tt>Home.php</tt> - page class for the <tt>Home</tt> page. It mainly contains the method responding to the <tt>OnClick</tt> event of the button.
  <com:TTextHighlighter CssClass="source block-content" id="code_50005">
 +<?php
  class Home extends TPage
  {
      public function buttonClicked($sender,$param)
 diff --git a/demos/quickstart/protected/pages/GettingStarted/NewFeatures.page b/demos/quickstart/protected/pages/GettingStarted/NewFeatures.page index 897b45f0..95bcc57f 100755 --- a/demos/quickstart/protected/pages/GettingStarted/NewFeatures.page +++ b/demos/quickstart/protected/pages/GettingStarted/NewFeatures.page @@ -9,6 +9,8 @@ This page summarizes the main new features that are introduced in each PRADO rel  <h2 id="8001">Version 3.2.3</h2>  <ul>  <li>Added <a href="?page=Controls.HtmlArea4">THtmlArea4 control</a> based on TinyMCE4</li> +<li>Added support for Behaviors, Class Behaviors, fx global events, and dy one to one events</li> +<li>Added the ability to set a priority (order) to event handlers</li>  </ul>  <h2 id="8001">Version 3.2.2</h2> diff --git a/framework/PradoBase.php b/framework/PradoBase.php index 2da331c9..0722d0fd 100644 --- a/framework/PradoBase.php +++ b/framework/PradoBase.php @@ -71,7 +71,7 @@ class PradoBase  	 */  	public static function getVersion()  	{ -		return '3.2.2'; +		return '3.2.3';  	}  	/** diff --git a/framework/Web/Javascripts/source/prado/prado.js b/framework/Web/Javascripts/source/prado/prado.js index 59bf433b..2e3ffbaa 100644 --- a/framework/Web/Javascripts/source/prado/prado.js +++ b/framework/Web/Javascripts/source/prado/prado.js @@ -240,7 +240,7 @@ var Prado =  	 * Version of Prado clientscripts  	 * @var Version  	 */ -	Version: '3.2.2', +	Version: '3.2.3',  	/**  	 * Registry for Prado components diff --git a/framework/pradolite.php b/framework/pradolite.php index cc4bbb79..d9627d13 100644 --- a/framework/pradolite.php +++ b/framework/pradolite.php @@ -1,7 +1,7 @@  <?php  /**   * File Name: pradolite.php - * Last Update: 2013/09/13 14:14:15 + * Last Update: 2013/11/26 10:04:34   * Generated By: buildscripts/phpbuilder/build.php   *   * This file is used in lieu of prado.php to boost PRADO application performance. @@ -25,7 +25,7 @@ class PradoBase  	protected static $classExists = array();  	public static function getVersion()  	{ -		return '3.2.2'; +		return '3.2.3';  	}  	public static function initErrorHandlers()  	{ @@ -475,9 +475,9 @@ class TApplicationComponent extends TComponent  		$fullPath=dirname($class->getFileName()).DIRECTORY_SEPARATOR.$assetPath;  		return $this->publishFilePath($fullPath);  	} -	public function publishFilePath($fullPath) +	public function publishFilePath($fullPath, $checkTimestamp=false)  	{ -		return Prado::getApplication()->getAssetManager()->publishFilePath($fullPath); +		return Prado::getApplication()->getAssetManager()->publishFilePath($fullPath, $checkTimestamp);  	}  }  abstract class TModule extends TApplicationComponent implements IModule @@ -1248,6 +1248,377 @@ class TTextWriter extends TComponent implements ITextWriter  		$this->write($str."\n");  	}  } +class TPriorityList extends TList  +{ +	private $_d=array(); +	private $_o=false; +	private $_fd=null; +	private $_c=0; +	private $_dp=10; +	private $_p=8; +	public function __construct($data=null,$readOnly=false,$defaultPriority=10,$precision=8) +	{ +		parent::__construct(); +		if($data!==null) +			$this->copyFrom($data); +		$this->setReadOnly($readOnly); +		$this->setPrecision($precision); +		$this->setDefaultPriority($defaultPriority); +	} +	public function count() +	{ +		return $this->getCount(); +	} +	public function getCount() +	{ +		return $this->_c; +	} +	public function getPriorityCount($priority=null) +	{ +		if($priority===null) +			$priority=$this->getDefaultPriority(); +		$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); +		if(!isset($this->_d[$priority]) || !is_array($this->_d[$priority])) +			return false; +		return count($this->_d[$priority]); +	} +	public function getDefaultPriority() +	{ +		return $this->_dp; +	} +	protected function setDefaultPriority($value) +	{ +		$this->_dp=(string)round(TPropertyValue::ensureFloat($value),$this->_p); +	} +	public function getPrecision() +	{ +		return $this->_p; +	} +	protected function setPrecision($value) +	{ +		$this->_p=TPropertyValue::ensureInteger($value); +	} +	public function getIterator() +	{ +		return new ArrayIterator($this->flattenPriorities()); +	} +	public function getPriorities() +	{ +		$this->sortPriorities(); +		return array_keys($this->_d); +	} +	protected function sortPriorities() { +		if(!$this->_o) { +			ksort($this->_d,SORT_NUMERIC); +			$this->_o=true; +		} +	} +	protected function flattenPriorities() { +		if(is_array($this->_fd)) +			return $this->_fd; +		$this->sortPriorities(); +		$this->_fd=array(); +		foreach($this->_d as $priority => $itemsatpriority) +			$this->_fd=array_merge($this->_fd,$itemsatpriority); +		return $this->_fd; +	} +	public function itemAt($index) +	{ +		if($index>=0&&$index<$this->getCount()) { +			$arr=$this->flattenPriorities(); +			return $arr[$index]; +		} else +			throw new TInvalidDataValueException('list_index_invalid',$index); +	} +	public function itemsAtPriority($priority=null) +	{ +		if($priority===null) +			$priority=$this->getDefaultPriority(); +		$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); +		return isset($this->_d[$priority])?$this->_d[$priority]:null; +	} +	public function itemAtIndexInPriority($index,$priority=null) +	{ +		if($priority===null) +			$priority=$this->getDefaultPriority(); +		$priority=(string)round(TPropertyValue::ensureFloat($priority), $this->_p); +		return !isset($this->_d[$priority])?false:( +				isset($this->_d[$priority][$index])?$this->_d[$priority][$index]:false +			); +	} +	public function add($item,$priority=null) +	{ +		if($this->getReadOnly()) +			throw new TInvalidOperationException('list_readonly',get_class($this)); +		return $this->insertAtIndexInPriority($item,false,$priority,true); +	} +	public function insertAt($index,$item) +	{ +		if($this->getReadOnly()) +			throw new TInvalidOperationException('list_readonly',get_class($this)); +		if(($priority=$this->priorityAt($index,true))!==false) +			$this->insertAtIndexInPriority($item,$priority[1],$priority[0]); +		else +			throw new TInvalidDataValueException('list_index_invalid',$index); +	} +	public function insertAtIndexInPriority($item,$index=false,$priority=null,$preserveCache=false) +	{ +		if($this->getReadOnly()) +			throw new TInvalidOperationException('list_readonly',get_class($this)); +		if($priority===null) +			$priority=$this->getDefaultPriority(); +		$priority=(string)round(TPropertyValue::ensureFloat($priority), $this->_p); +		if($preserveCache) { +			$this->sortPriorities(); +			$cc=0; +			foreach($this->_d as $prioritykey=>$items) +				if($prioritykey>=$priority) +					break; +				else +					$cc+=count($items); +			if($index===false&&isset($this->_d[$priority])) { +				$c=count($this->_d[$priority]); +				$c+=$cc; +				$this->_d[$priority][]=$item; +			} else if(isset($this->_d[$priority])) { +				$c=$index+$cc; +				array_splice($this->_d[$priority],$index,0,array($item)); +			} else { +				$c = $cc; +				$this->_o = false; +				$this->_d[$priority]=array($item); +			} +			if($this->_fd&&is_array($this->_fd)) 				array_splice($this->_fd,$c,0,array($item)); +		} else { +			$c=null; +			if($index===false&&isset($this->_d[$priority])) { +				$cc=count($this->_d[$priority]); +				$this->_d[$priority][]=$item; +			} else if(isset($this->_d[$priority])) { +				$cc=$index; +				array_splice($this->_d[$priority],$index,0,array($item)); +			} else { +				$cc=0; +				$this->_o=false; +				$this->_d[$priority]=array($item); +			} +			if($this->_fd&&is_array($this->_fd)&&count($this->_d)==1) +				array_splice($this->_fd,$cc,0,array($item)); +			else +				$this->_fd=null; +		} +		$this->_c++; +		return $c; +	} +	public function remove($item,$priority=false) +	{ +		if($this->getReadOnly()) +			throw new TInvalidOperationException('list_readonly',get_class($this)); +		if(($p=$this->priorityOf($item,true))!==false) +		{ +			if($priority!==false) { +				if($priority===null) +					$priority=$this->getDefaultPriority(); +				$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); +				if($p[0]!=$priority) +					throw new TInvalidDataValueException('list_item_inexistent'); +			} +			$this->removeAtIndexInPriority($p[1],$p[0]); +			return $p[2]; +		} +		else +			throw new TInvalidDataValueException('list_item_inexistent'); +	} +	public function removeAt($index) +	{ +		if($this->getReadOnly()) +			throw new TInvalidOperationException('list_readonly',get_class($this)); +		if(($priority=$this->priorityAt($index, true))!==false) +			return $this->removeAtIndexInPriority($priority[1],$priority[0]); +		throw new TInvalidDataValueException('list_index_invalid',$index); +	} +	public function removeAtIndexInPriority($index, $priority=null) +	{ +		if($this->getReadOnly()) +			throw new TInvalidOperationException('list_readonly',get_class($this)); +		if($priority===null) +			$priority=$this->getDefaultPriority(); +		$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); +		if(!isset($this->_d[$priority])||$index<0||$index>=count($this->_d[$priority])) +			throw new TInvalidDataValueException('list_item_inexistent'); +				$value=array_splice($this->_d[$priority],$index,1); +		$value=$value[0]; +		if(!count($this->_d[$priority])) +			unset($this->_d[$priority]); +		$this->_c--; +		$this->_fd=null; +		return $value; +	} +	public function clear() +	{ +		if($this->getReadOnly()) +			throw new TInvalidOperationException('list_readonly',get_class($this)); +		$d=array_reverse($this->_d,true); +		foreach($this->_d as $priority=>$items) { +			for($index=count($items)-1;$index>=0;$index--) +				$this->removeAtIndexInPriority($index,$priority); +			unset($this->_d[$priority]); +		} +	} +	public function contains($item) +	{ +		return $this->indexOf($item)>=0; +	} +	public function indexOf($item) +	{ +		if(($index=array_search($item,$this->flattenPriorities(),true))===false) +			return -1; +		else +			return $index; +	} +	public function priorityOf($item,$withindex = false) +	{ +		$this->sortPriorities(); +		$absindex = 0; +		foreach($this->_d as $priority=>$items) { +			if(($index=array_search($item,$items,true))!==false) { +				$absindex+=$index; +				return $withindex?array($priority,$index,$absindex,  +						'priority'=>$priority,'index'=>$index,'absindex'=>$absindex):$priority; +			} else +				$absindex+=count($items); +		} +		return false; +	} +	public function priorityAt($index,$withindex = false) +	{ +		if($index<0||$index>=$this->getCount()) +			throw new TInvalidDataValueException('list_index_invalid',$index); +		$absindex=$index; +		$this->sortPriorities(); +		foreach($this->_d as $priority=>$items) { +			if($index>=($c=count($items))) +				$index-=$c; +			else +				return $withindex?array($priority,$index,$absindex,  +						'priority'=>$priority,'index'=>$index,'absindex'=>$absindex):$priority; +		} +		return false; +	} +	public function insertBefore($indexitem, $item) +	{ +		if($this->getReadOnly()) +			throw new TInvalidOperationException('list_readonly',get_class($this)); +		if(($priority=$this->priorityOf($indexitem,true))===false) +			throw new TInvalidDataValueException('list_item_inexistent'); +		$this->insertAtIndexInPriority($item,$priority[1],$priority[0]); +		return $priority[2]; +	} +	public function insertAfter($indexitem, $item) +	{ +		if($this->getReadOnly()) +			throw new TInvalidOperationException('list_readonly',get_class($this)); +		if(($priority=$this->priorityOf($indexitem,true))===false) +			throw new TInvalidDataValueException('list_item_inexistent'); +		$this->insertAtIndexInPriority($item,$priority[1]+1,$priority[0]); +		return $priority[2]+1; +	} +	public function toArray() +	{ +		return $this->flattenPriorities(); +	} +	public function toPriorityArray() +	{ +		$this->sortPriorities(); +		return $this->_d; +	} +	public function toArrayBelowPriority($priority,$inclusive=false) +	{ +		$this->sortPriorities(); +		$items=array(); +		foreach($this->_d as $itemspriority=>$itemsatpriority) +		{ +			if((!$inclusive&&$itemspriority>=$priority)||$itemspriority>$priority) +				break; +			$items=array_merge($items,$itemsatpriority); +		} +		return $items; +	} +	public function toArrayAbovePriority($priority,$inclusive=true) +	{ +		$this->sortPriorities(); +		$items=array(); +		foreach($this->_d as $itemspriority=>$itemsatpriority) +		{ +			if((!$inclusive&&$itemspriority<=$priority)||$itemspriority<$priority) +				continue; +			$items=array_merge($items,$itemsatpriority); +		} +		return $items; +	} +	public function copyFrom($data) +	{ +		if($data instanceof TPriorityList) +		{ +			if($this->getCount()>0) +				$this->clear(); +			foreach($data->getPriorities() as $priority) +			{ +				foreach($data->itemsAtPriority($priority) as $index=>$item) +					$this->insertAtIndexInPriority($item,$index,$priority); +			} +		} else if(is_array($data)||$data instanceof Traversable) { +			if($this->getCount()>0) +				$this->clear(); +			foreach($data as $key=>$item) +				$this->add($item); +		} else if($data!==null) +			throw new TInvalidDataTypeException('map_data_not_iterable'); +	} +	public function mergeWith($data) +	{ +		if($data instanceof TPriorityList) +		{ +			foreach($data->getPriorities() as $priority) +			{ +				foreach($data->itemsAtPriority($priority) as $index=>$item) +					$this->insertAtIndexInPriority($item,false,$priority); +			} +		} +		else if(is_array($data)||$data instanceof Traversable) +		{ +			foreach($data as $priority=>$item) +				$this->add($item); +		} +		else if($data!==null) +			throw new TInvalidDataTypeException('map_data_not_iterable'); +	} +	public function offsetExists($offset) +	{ +		return ($offset>=0&&$offset<$this->getCount()); +	} +	public function offsetGet($offset) +	{ +		return $this->itemAt($offset); +	} +	public function offsetSet($offset,$item) +	{ +		if($offset===null) +			return $this->add($item); +		if($offset===$this->getCount()) { +			$priority=$this->priorityAt($offset-1,true); +			$priority[1]++; +		} else { +			$priority=$this->priorityAt($offset,true); +			$this->removeAtIndexInPriority($priority[1],$priority[0]); +		} +		$this->insertAtIndexInPriority($item,$priority[1],$priority[0]); +	} +	public function offsetUnset($offset) +	{ +		$this->removeAt($offset); +	} +}  class TMap extends TComponent implements IteratorAggregate,ArrayAccess,Countable  {  	private $_d=array(); @@ -1392,6 +1763,310 @@ class TMapIterator implements Iterator  		return $this->_key!==false;  	}  } +class TPriorityMap extends TMap +{ +	private $_d=array(); +	private $_r=false; +	private $_o=false; +	private $_fd=null; +	private $_c=0; +	private $_dp=10; +	private $_p=8; +	public function __construct($data=null,$readOnly=false,$defaultPriority=10,$precision=8) +	{ +		if($data!==null) +			$this->copyFrom($data); +		$this->setReadOnly($readOnly); +		$this->setPrecision($precision); +		$this->setDefaultPriority($defaultPriority); +	} +	public function getReadOnly() +	{ +		return $this->_r; +	} +	protected function setReadOnly($value) +	{ +		$this->_r=TPropertyValue::ensureBoolean($value); +	} +	public function getDefaultPriority() +	{ +		return $this->_dp; +	} +	protected function setDefaultPriority($value) +	{ +		$this->_dp = (string)round(TPropertyValue::ensureFloat($value), $this->_p); +	} +	public function getPrecision() +	{ +		return $this->_p; +	} +	protected function setPrecision($value) +	{ +		$this->_p=TPropertyValue::ensureInteger($value); +	} +	public function getIterator() +	{ +		return new ArrayIterator($this->flattenPriorities()); +	} +	protected function sortPriorities() { +		if(!$this->_o) { +			ksort($this->_d, SORT_NUMERIC); +			$this->_o=true; +		} +	} +	protected function flattenPriorities() { +		if(is_array($this->_fd)) +			return $this->_fd; +		$this->sortPriorities(); +		$this->_fd = array(); +		foreach($this->_d as $priority => $itemsatpriority) +			$this->_fd = array_merge($this->_fd, $itemsatpriority); +		return $this->_fd; +	} +	public function count() +	{ +		return $this->getCount(); +	} +	public function getCount() +	{ +		return $this->_c; +	} +	public function getPriorityCount($priority=null) +	{ +		if($priority===null) +			$priority=$this->getDefaultPriority(); +		$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); +		if(!isset($this->_d[$priority])||!is_array($this->_d[$priority])) +			return false; +		return count($this->_d[$priority]); +	} +	public function getPriorities() +	{ +		$this->sortPriorities(); +		return array_keys($this->_d); +	} +	public function getKeys() +	{ +		return array_keys($this->flattenPriorities()); +	} +	public function itemAt($key,$priority=false) +	{ +		if($priority===false){ +			$map=$this->flattenPriorities(); +			return isset($map[$key])?$map[$key]:null; +		} else { +			if($priority===null) +				$priority=$this->getDefaultPriority(); +			$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); +			return (isset($this->_d[$priority])&&isset($this->_d[$priority][$key]))?$this->_d[$priority][$key]:null; +		} +	} +	public function setPriorityAt($key,$priority=null) +	{ +		if($priority===null) +			$priority=$this->getDefaultPriority(); +		$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); +		$oldpriority=$this->priorityAt($key); +		if($oldpriority!==false&&$oldpriority!=$priority) { +			$value=$this->remove($key,$oldpriority); +			$this->add($key,$value,$priority); +		} +		return $oldpriority; +	} +	public function itemsAtPriority($priority=null) +	{ +		if($priority===null) +			$priority=$this->getDefaultPriority(); +		$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); +		return isset($this->_d[$priority])?$this->_d[$priority]:null; +	} +	public function priorityOf($item) +	{ +		$this->sortPriorities(); +		foreach($this->_d as $priority=>$items) +			if(($index=array_search($item,$items,true))!==false) +				return $priority; +		return false; +	} +	public function priorityAt($key) +	{ +		$this->sortPriorities(); +		foreach($this->_d as $priority=>$items) +			if(array_key_exists($key,$items)) +				return $priority; +		return false; +	} +	public function add($key,$value,$priority=null) +	{ +		if($priority===null) +			$priority=$this->getDefaultPriority(); +		$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); +		if(!$this->_r) +		{ +			foreach($this->_d as $innerpriority=>$items) +				if(array_key_exists($key,$items)) +				{ +					unset($this->_d[$innerpriority][$key]); +					$this->_c--; +					if(count($this->_d[$innerpriority])===0) +						unset($this->_d[$innerpriority]); +				} +			if(!isset($this->_d[$priority])) { +				$this->_d[$priority]=array($key=>$value); +				$this->_o=false; +			} +			else +				$this->_d[$priority][$key]=$value; +			$this->_c++; +			$this->_fd=null; +		} +		else +			throw new TInvalidOperationException('map_readonly',get_class($this)); +		return $priority; +	} +	public function remove($key,$priority=false) +	{ +		if(!$this->_r) +		{ +			if($priority===null) +				$priority=$this->getDefaultPriority(); +			if($priority===false) +			{ +				$this->sortPriorities(); +				foreach($this->_d as $priority=>$items) +					if(array_key_exists($key,$items)) +					{ +						$value=$this->_d[$priority][$key]; +						unset($this->_d[$priority][$key]); +						$this->_c--; +						if(count($this->_d[$priority])===0) +						{ +							unset($this->_d[$priority]); +							$this->_o=false; +						} +						$this->_fd=null; +						return $value; +					} +				return null; +			} +			else +			{ +				$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); +				if(isset($this->_d[$priority])&&(isset($this->_d[$priority][$key])||array_key_exists($key,$this->_d[$priority]))) +				{ +					$value=$this->_d[$priority][$key]; +					unset($this->_d[$priority][$key]); +					$this->_c--; +					if(count($this->_d[$priority])===0) { +						unset($this->_d[$priority]); +						$this->_o=false; +					} +					$this->_fd=null; +					return $value; +				} +				else +					return null; +			} +		} +		else +			throw new TInvalidOperationException('map_readonly',get_class($this)); +	} +	public function clear() +	{ +		foreach($this->_d as $priority=>$items) +			foreach(array_keys($items) as $key) +				$this->remove($key); +	} +	public function contains($key) +	{ +		$map=$this->flattenPriorities(); +		return isset($map[$key])||array_key_exists($key,$map); +	} +	public function toArray() +	{ +		return $this->flattenPriorities(); +	} +	public function toArrayBelowPriority($priority,$inclusive=false) +	{ +		$this->sortPriorities(); +		$items=array(); +		foreach($this->_d as $itemspriority=>$itemsatpriority) +		{ +			if((!$inclusive&&$itemspriority>=$priority)||$itemspriority>$priority) +				break; +			$items=array_merge($items,$itemsatpriority); +		} +		return $items; +	} +	public function toArrayAbovePriority($priority,$inclusive=true) +	{ +		$this->sortPriorities(); +		$items=array(); +		foreach($this->_d as $itemspriority=>$itemsatpriority) +		{ +			if((!$inclusive&&$itemspriority<=$priority)||$itemspriority<$priority) +				continue; +			$items=array_merge($items,$itemsatpriority); +		} +		return $items; +	} +	public function copyFrom($data) +	{ +		if($data instanceof TPriorityMap) +		{ +			if($this->getCount()>0) +				$this->clear(); +			foreach($data->getPriorities() as $priority) { +				foreach($data->itemsAtPriority($priority) as $key => $value) { +					$this->add($key,$value,$priority); +				} +			} +		} +		else if(is_array($data)||$data instanceof Traversable) +		{ +			if($this->getCount()>0) +				$this->clear(); +			foreach($data as $key=>$value) +				$this->add($key,$value); +		} +		else if($data!==null) +			throw new TInvalidDataTypeException('map_data_not_iterable'); +	} +	public function mergeWith($data) +	{ +		if($data instanceof TPriorityMap) +		{ +			foreach($data->getPriorities() as $priority) +			{ +				foreach($data->itemsAtPriority($priority) as $key => $value) +					$this->add($key,$value,$priority); +			} +		} +		else if(is_array($data)||$data instanceof Traversable) +		{ +			foreach($data as $key=>$value) +				$this->add($key,$value); +		} +		else if($data!==null) +			throw new TInvalidDataTypeException('map_data_not_iterable'); +	} +	public function offsetExists($offset) +	{ +		return $this->contains($offset); +	} +	public function offsetGet($offset) +	{ +		return $this->itemAt($offset); +	} +	public function offsetSet($offset,$item) +	{ +		$this->add($offset,$item); +	} +	public function offsetUnset($offset) +	{ +		$this->remove($offset); +	} +}  class TStack extends TComponent implements IteratorAggregate,Countable  {  	private $_d=array(); @@ -3767,7 +4442,7 @@ class TAttributeCollection extends TMap  	}  	public function hasProperty($name)  	{ -		return $this->contains($name) || parent::hasProperty($name); +		return $this->contains($name) || parent::canGetProperty($name) || parent::canSetProperty($name);  	}  	public function canGetProperty($name)  	{ @@ -6436,12 +7111,9 @@ class TClientScriptManager extends TApplicationComponent  	public function getStyleSheetUrls()  	{  		$stylesheets = array_values( -			array_merge( -				array_map( -					create_function('$e', 'return is_array($e) ? $e[0] : $e;'), -					$this->_styleSheetFiles), -				$this->_styleSheets -			) +			array_map( +				create_function('$e', 'return is_array($e) ? $e[0] : $e;'), +				$this->_styleSheetFiles)  		);  		foreach(Prado::getApplication()->getAssetManager()->getPublished() as $path=>$url)  			if (substr($url,strlen($url)-4)=='.css') @@ -6449,6 +7121,10 @@ class TClientScriptManager extends TApplicationComponent  		$stylesheets = array_unique($stylesheets);  		return $stylesheets;  	} +	public function getStyleSheetCodes() +	{ +		return array_unique(array_values($this->_styleSheets)); +	}  	public function registerHeadScriptFile($key,$url)  	{  		$this->checkIfNotInRender(); @@ -8,7 +8,7 @@  <body>  <h1>PRADO Framework for PHP 5 </h1> -<p>Version 3.2.2<br> +<p>Version 3.2.3<br>  Copyright© 2004-2013 by <a href="http://www.pradosoft.com/">Prado Software</a><br>  All Rights Reserved.  </p>  | 
