summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes7
-rw-r--r--HISTORY8
-rw-r--r--UPGRADE3
-rw-r--r--buildscripts/phing/tasks/BuildPradoPEARPackageTask.php30
-rw-r--r--demos/quickstart/protected/pages/Controls/ImageButton.page2
-rw-r--r--demos/quickstart/protected/pages/Fundamentals/Pages.page2
-rw-r--r--framework/Collections/TDummyDataSource.php12
-rw-r--r--framework/Collections/TList.php15
-rw-r--r--framework/Collections/TMap.php15
-rw-r--r--framework/Collections/TPagedDataSource.php12
-rw-r--r--framework/Collections/TStack.php12
-rw-r--r--framework/Exceptions/messages.txt2
-rw-r--r--framework/I18N/core/MessageFormat.php4
-rw-r--r--framework/I18N/core/NumberFormat.php13
-rw-r--r--framework/PradoBase.php86
-rw-r--r--framework/Security/TAuthManager.php8
-rw-r--r--framework/Util/TSimpleDateFormatter.php5
-rw-r--r--framework/Web/THttpRequest.php53
-rw-r--r--framework/Web/THttpSession.php15
-rw-r--r--framework/Web/UI/TTemplateControl.php2
-rw-r--r--framework/Web/UI/WebControls/TDatePicker.php33
-rw-r--r--index.html2
-rw-r--r--requirements/index.php7
-rw-r--r--requirements/messages-bg.txt3
-rw-r--r--requirements/messages-zh.txt3
-rw-r--r--requirements/messages.txt3
-rw-r--r--tests/FunctionalTests/tickets/protected/messages/en/messages.xml17
-rw-r--r--tests/FunctionalTests/tickets/protected/pages/Ticket220.page2
-rw-r--r--tests/FunctionalTests/tickets/protected/pages/Ticket269.page10
-rw-r--r--tests/FunctionalTests/tickets/protected/pages/Ticket285.page7
-rw-r--r--tests/FunctionalTests/tickets/protected/pages/Ticket306.page12
-rw-r--r--tests/FunctionalTests/tickets/protected/pages/Ticket311.page18
-rw-r--r--tests/FunctionalTests/tickets/protected/pages/Ticket312.page11
-rw-r--r--tests/FunctionalTests/tickets/protected/pages/config.xml8
-rw-r--r--tests/FunctionalTests/tickets/tests/Ticket285TestCase.php12
-rw-r--r--tests/unit/I18N/core/NumberFormatTest.php25
36 files changed, 324 insertions, 155 deletions
diff --git a/.gitattributes b/.gitattributes
index f51ec8f0..140bf48d 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1923,6 +1923,7 @@ tests/FunctionalTests/quickstart/Controls/Wizard5TestCase.php -text
tests/FunctionalTests/quickstart/Fundamentals/HangmanTestCase.php -text
tests/FunctionalTests/tickets.php -text
tests/FunctionalTests/tickets/index.php -text
+tests/FunctionalTests/tickets/protected/messages/en/messages.xml -text
tests/FunctionalTests/tickets/protected/pages/Layout.php -text
tests/FunctionalTests/tickets/protected/pages/Layout.tpl -text
tests/FunctionalTests/tickets/protected/pages/TestHtmlArea.php -text
@@ -1936,6 +1937,7 @@ tests/FunctionalTests/tickets/protected/pages/Ticket21.page -text
tests/FunctionalTests/tickets/protected/pages/Ticket21.php -text
tests/FunctionalTests/tickets/protected/pages/Ticket239.page -text
tests/FunctionalTests/tickets/protected/pages/Ticket239.php -text
+tests/FunctionalTests/tickets/protected/pages/Ticket269.page -text
tests/FunctionalTests/tickets/protected/pages/Ticket27.page -text
tests/FunctionalTests/tickets/protected/pages/Ticket28.page -text
tests/FunctionalTests/tickets/protected/pages/Ticket28.php -text
@@ -1943,6 +1945,10 @@ tests/FunctionalTests/tickets/protected/pages/Ticket284.page -text
tests/FunctionalTests/tickets/protected/pages/Ticket284.php -text
tests/FunctionalTests/tickets/protected/pages/Ticket284Component.php -text
tests/FunctionalTests/tickets/protected/pages/Ticket284Component.tpl -text
+tests/FunctionalTests/tickets/protected/pages/Ticket285.page -text
+tests/FunctionalTests/tickets/protected/pages/Ticket306.page -text
+tests/FunctionalTests/tickets/protected/pages/Ticket311.page -text
+tests/FunctionalTests/tickets/protected/pages/Ticket312.page -text
tests/FunctionalTests/tickets/protected/pages/Ticket54.page -text
tests/FunctionalTests/tickets/protected/pages/Ticket54Master.php -text
tests/FunctionalTests/tickets/protected/pages/Ticket54Master.tpl -text
@@ -1961,6 +1967,7 @@ tests/FunctionalTests/tickets/tests/Ticket21TestCase.php -text
tests/FunctionalTests/tickets/tests/Ticket239TestCase.php -text
tests/FunctionalTests/tickets/tests/Ticket27TestCase.php -text
tests/FunctionalTests/tickets/tests/Ticket284TestCase.php -text
+tests/FunctionalTests/tickets/tests/Ticket285TestCase.php -text
tests/FunctionalTests/tickets/tests/Ticket28TestCase.php -text
tests/FunctionalTests/tickets/tests/Ticket54TestCase.php -text
tests/FunctionalTests/tickets/tests/Ticket72TestCase.php -text
diff --git a/HISTORY b/HISTORY
index b11a10bc..43d8764b 100644
--- a/HISTORY
+++ b/HISTORY
@@ -14,10 +14,16 @@ Version 3.0.3 August 6, 2006
============================
BUG: Ticket#264 - Typos in some exception throw statements (Knut)
BUG: Ticket#268 - THttpResponse.redirect() may fail for some browsers (Qiang)
+BUG: Ticket#285 - NumberFormat Rounding Bug (Wei)
BUG: Ticket#297 - THttpRequest::constructUrl() encoding bug about array GET parameters (Qiang)
BUG: TDataGrid may complain getting ItemType on a non-object if the grid is not data-bound (Qiang)
BUG: TCheckBox.Value should be converted to string (Qiang)
+BUG: Ticket#302 - TDatePicker's bug with AutoPostBack set to "true" (Wei)
+BUG: Ticket#306 - Prado::localize function may fail when localized string passed as parameter (Wei)
+BUG: Ticket#311 - Several bugs in TDatePicker (Wei)
+BUG: Ticket#312 - TDatePicker's ReadOnly property bug (Wei)
CHG: Ticket#206 - TBaseValidator.OnValidate is raised only when the validator is visible (Qiang)
+CHG: Raised PHP version requirement to 5.1 and above (Qiang)
ENH: Ticket#178 - Added TRadioButton.UniqueGroupName property (Qiang)
ENH: Ticket#220 - TClientScripts method to import custom javascript files (Wei)
ENH: Ticket#225 - TRadioButton::getRadioButtonsInGroup() added (Wei)
@@ -27,7 +33,7 @@ ENH: Ticket#263 - TListBox and TDropDownList support optgroup now (Qiang)
ENH: Ticket#277 - Added TControl.CustomData property (Qiang)
ENH: Ticket#287 - TControl::broadcastEvent() may raise events now (Qiang)
ENH: Ticket#292 - Added THttpRequest::parseUrl() so that it is easier to be extended (Qiang)
-ENH: Better URL 'Path' format (Qiang)
+ENH: Ticket#309 - Added THttpRequest.UrlParamSeparator property (Qiang)
NEW: Added TStyleSheet (Wei)
diff --git a/UPGRADE b/UPGRADE
index 077b859b..4796b22b 100644
--- a/UPGRADE
+++ b/UPGRADE
@@ -16,6 +16,9 @@ for both A and B.
Upgrading from v3.0.2
---------------------
+- The minimum PHP version required is raised to 5.1.0 and above.
+ If your server is installed with a lower version of PHP, you will
+ have to upgrade it in order to run PRADO applications.
- The signature of TControl::broadcastEvent() is changed from
broadcastEvent($sender,TBroadCastEventParameter $param) to
broadcastEvent($name,$sender,$param).
diff --git a/buildscripts/phing/tasks/BuildPradoPEARPackageTask.php b/buildscripts/phing/tasks/BuildPradoPEARPackageTask.php
index 72ad8798..a8128d12 100644
--- a/buildscripts/phing/tasks/BuildPradoPEARPackageTask.php
+++ b/buildscripts/phing/tasks/BuildPradoPEARPackageTask.php
@@ -8,12 +8,12 @@ require_once 'PEAR/PackageFileManager/File.php';
/**
* Task for creating a PEAR package definition file package.xml to be used with
* the PEAR distribution of PRADO.
- *
+ *
* @author Knut Urdalen <knut.urdalen@gmail.com>
* @package phing.tasks.ext
*/
class BuildPradoPEARPackageTask extends MatchingTask {
-
+
/* Base directory for reading files. */
private $dir;
@@ -24,7 +24,7 @@ class BuildPradoPEARPackageTask extends MatchingTask {
private $state = 'stable';
private $notes;
private $filesets = array();
-
+
/* Package file */
private $packageFile;
@@ -43,21 +43,21 @@ class BuildPradoPEARPackageTask extends MatchingTask {
*
* @param PEAR_PackageFileManager2 $pkg
*/
- private function setOptions($pkg) {
+ private function setOptions($pkg) {
$options['baseinstalldir'] = 'prado3';
$options['packagedirectory'] = $this->dir->getAbsolutePath();
-
+
if(empty($this->filesets)) {
throw new BuildException("You must use a <fileset> tag to specify the files to include in the package.xml");
}
-
+
// Use PEAR_PackageFileManager_Fileset from phing as file list generator
$options['filelistgenerator'] = 'Fileset';
-
+
// Some Phing-specific options needed by our Fileset reader
$options['phing_project'] = $this->getProject();
$options['phing_filesets'] = $this->filesets;
-
+
if($this->packageFile !== null) {
// Create one with full path
$f = new PhingFile($this->packageFile->getAbsolutePath());
@@ -81,7 +81,7 @@ class BuildPradoPEARPackageTask extends MatchingTask {
if($this->dir === null) {
throw new BuildException("You must specify the \"dir\" attribute for PEAR package task.");
}
-
+
if($this->version === null) {
throw new BuildException("You must specify the \"version\" attribute for PEAR package task.");
}
@@ -110,21 +110,21 @@ o Team Integration - PRADO enables separation of content and presentation. Compo
$package->setReleaseVersion($this->version);
$package->setAPIVersion($this->version);
-
+
$package->setReleaseStability($this->state);
$package->setAPIStability($this->state);
-
+
$package->setNotes($this->notes);
-
+
$package->setLicense('BSD', 'http://www.opensource.org/licenses/bsd-license.php');
-
+
// Add package maintainers
$package->addMaintainer('lead', 'qxue', 'Qiang Xue', 'qiang.xue@gmail.com');
$package->addMaintainer('lead', 'jrags', 'Jason Ragsdale', 'jrags@jasrags.net');
$package->addMaintainer('lead', 'knut', 'Knut Urdalen', 'knut.urdalen@gmail.com');
// "core" dependencies
- $package->setPhpDep('5.0.4');
+ $package->setPhpDep('5.1.0');
$package->setPearinstallerDep('1.4.7');
$package->generateContents();
@@ -175,7 +175,7 @@ o Team Integration - PRADO enables separation of content and presentation. Compo
public function setState($v) {
$this->state = $v;
}
-
+
/**
* Sets release notes field.
* @param string $v
diff --git a/demos/quickstart/protected/pages/Controls/ImageButton.page b/demos/quickstart/protected/pages/Controls/ImageButton.page
index a79ecb6a..a4f8d30f 100644
--- a/demos/quickstart/protected/pages/Controls/ImageButton.page
+++ b/demos/quickstart/protected/pages/Controls/ImageButton.page
@@ -4,7 +4,7 @@
<com:DocLink ClassPath="System.Web.UI.WebControls.TImageButton" />
<p>
-<tt>TImageButton</tt> is also similar to <tt>TButton</tt>, except that <tt>TImageButton</tt> displays the button as an image. The image is specified via <tt>ImageUrl</tt>, and the alternate text is specified by <tt>Text</tt>. In addition, it is possible to obtain the coordinate of the point where the image is clicked. The coordinate information is contained in the event parameter of the <tt>Click</tt> event (not <tt>Command</tt>).
+<tt>TImageButton</tt> is also similar to <tt>TButton</tt>, except that <tt>TImageButton</tt> displays the button as an image. The image is specified via <tt>ImageUrl</tt>, and the alternate text is specified by <tt>Text</tt>. In addition, it is possible to obtain the coordinate of the point where the image is clicked. The coordinate information is contained in the event parameter of the <tt>OnClick</tt> event (not <tt>OnCommand</tt>).
</p>
<com:RunBar PagePath="Controls.Samples.TImageButton.Home" />
diff --git a/demos/quickstart/protected/pages/Fundamentals/Pages.page b/demos/quickstart/protected/pages/Fundamentals/Pages.page
index 1e91801c..3403bddc 100644
--- a/demos/quickstart/protected/pages/Fundamentals/Pages.page
+++ b/demos/quickstart/protected/pages/Fundamentals/Pages.page
@@ -10,7 +10,7 @@ Each page must have a <a href="?page=Configurations.Templates1">template</a> fil
<h2 id="902">PostBack</h2>
<p>
-A form submission is called <i>postback</i> if the submission is made to the page containing the form. Postback can be considered an event happened on the client side, raised by the user. PRADO will try to identify which control on the server side is responsible for a postback event. If one is determined, for example, a <tt>TButton</tt>, we call it the postback event sender which will translate the postback event into some specific server-side event (e.g. <tt>Click</tt> and <tt>Command</tt> events for <tt>TButton</tt>).
+A form submission is called <i>postback</i> if the submission is made to the page containing the form. Postback can be considered an event happened on the client side, raised by the user. PRADO will try to identify which control on the server side is responsible for a postback event. If one is determined, for example, a <tt>TButton</tt>, we call it the postback event sender which will translate the postback event into some specific server-side event (e.g. <tt>OnClick</tt> and <tt>OnCommand</tt> events for <tt>TButton</tt>).
</p>
diff --git a/framework/Collections/TDummyDataSource.php b/framework/Collections/TDummyDataSource.php
index 46e625ab..d7fee4a9 100644
--- a/framework/Collections/TDummyDataSource.php
+++ b/framework/Collections/TDummyDataSource.php
@@ -26,7 +26,7 @@
* @package System.Collections
* @since 3.0
*/
-class TDummyDataSource extends TComponent implements IteratorAggregate
+class TDummyDataSource extends TComponent implements IteratorAggregate, Countable
{
private $_count;
@@ -54,6 +54,16 @@ class TDummyDataSource extends TComponent implements IteratorAggregate
{
return new TDummyDataSourceIterator($this->_count);
}
+
+ /**
+ * Returns the number of (virtual) items in the data source.
+ * This method is required by Countable interface.
+ * @return integer number of (virtual) items in the data source.
+ */
+ public function count()
+ {
+ return $this->getCount();
+ }
}
/**
diff --git a/framework/Collections/TList.php b/framework/Collections/TList.php
index 015781cb..1104ec47 100644
--- a/framework/Collections/TList.php
+++ b/framework/Collections/TList.php
@@ -25,9 +25,8 @@
* unset($list[$index]); // remove the item at $index
* if(isset($list[$index])) // if the list has an item at $index
* foreach($list as $index=>$item) // traverse each item in the list
+ * $n=count($list); // returns the number of items in the list
* </code>
- * Note, count($list) will always return 1. You should use {@link getCount()}
- * to determine the number of items in the list.
*
* To extend TList by doing additional operations with each addition or removal
* operation, override {@link insertAt()}, and {@link removeAt()}.
@@ -37,7 +36,7 @@
* @package System.Collections
* @since 3.0
*/
-class TList extends TComponent implements IteratorAggregate,ArrayAccess
+class TList extends TComponent implements IteratorAggregate,ArrayAccess,Countable
{
/**
* internal data storage
@@ -95,6 +94,16 @@ class TList extends TComponent implements IteratorAggregate,ArrayAccess
}
/**
+ * Returns the number of items in the list.
+ * This method is required by Countable interface.
+ * @return integer number of items in the list.
+ */
+ public function count()
+ {
+ return $this->getCount();
+ }
+
+ /**
* @return integer the number of items in the list
*/
public function getCount()
diff --git a/framework/Collections/TMap.php b/framework/Collections/TMap.php
index e3a26e5f..ef393866 100644
--- a/framework/Collections/TMap.php
+++ b/framework/Collections/TMap.php
@@ -24,16 +24,15 @@
* unset($map[$key]); // remove the value with the specified key
* if(isset($map[$key])) // if the map contains the key
* foreach($map as $key=>$value) // traverse the items in the map
+ * $n=count($map); // returns the number of items in the map
* </code>
- * Note, count($map) will always return 1. You should use {@link getCount()}
- * to determine the number of items in the map.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Revision: $ $Date: $
* @package System.Collections
* @since 3.0
*/
-class TMap extends TComponent implements IteratorAggregate,ArrayAccess
+class TMap extends TComponent implements IteratorAggregate,ArrayAccess,Countable
{
/**
* @var array internal data storage
@@ -85,6 +84,16 @@ class TMap extends TComponent implements IteratorAggregate,ArrayAccess
}
/**
+ * Returns the number of items in the map.
+ * This method is required by Countable interface.
+ * @return integer number of items in the map.
+ */
+ public function count()
+ {
+ return $this->getCount();
+ }
+
+ /**
* @return integer the number of items in the map
*/
public function getCount()
diff --git a/framework/Collections/TPagedDataSource.php b/framework/Collections/TPagedDataSource.php
index 6192b1f7..a2bce9e3 100644
--- a/framework/Collections/TPagedDataSource.php
+++ b/framework/Collections/TPagedDataSource.php
@@ -28,7 +28,7 @@
* @package System.Collections
* @since 3.0
*/
-class TPagedDataSource extends TComponent implements IteratorAggregate
+class TPagedDataSource extends TComponent implements IteratorAggregate,Countable
{
/**
* @var mixed original data source
@@ -183,6 +183,16 @@ class TPagedDataSource extends TComponent implements IteratorAggregate
}
/**
+ * Returns the number of items in the current page.
+ * This method is required by Countable interface.
+ * @return integer number of items in the current page.
+ */
+ public function count()
+ {
+ return $this->getCount();
+ }
+
+ /**
* @return integer number of pages
*/
public function getPageCount()
diff --git a/framework/Collections/TStack.php b/framework/Collections/TStack.php
index 79d17902..f1118d90 100644
--- a/framework/Collections/TStack.php
+++ b/framework/Collections/TStack.php
@@ -31,7 +31,7 @@
* @package System.Collections
* @since 3.0
*/
-class TStack extends TComponent implements IteratorAggregate
+class TStack extends TComponent implements IteratorAggregate,Countable
{
/**
* internal data storage
@@ -160,6 +160,16 @@ class TStack extends TComponent implements IteratorAggregate
{
return $this->_c;
}
+
+ /**
+ * Returns the number of items in the stack.
+ * This method is required by Countable interface.
+ * @return integer number of items in the stack.
+ */
+ public function count()
+ {
+ return $this->getCount();
+ }
}
/**
diff --git a/framework/Exceptions/messages.txt b/framework/Exceptions/messages.txt
index ff9ab1f3..630f7b50 100644
--- a/framework/Exceptions/messages.txt
+++ b/framework/Exceptions/messages.txt
@@ -322,6 +322,8 @@ databoundcontrol_datamember_invalid = databoundcontrol_datamember_invalid
clientscript_invalid_file_position = Invalid file position '{1}' for TClientScript control '{0}', must be 'Head', 'Here' or 'Begin'.
+tdatepicker_autopostback_unsupported = '{0}' does not support AutoPostBack.
+
callback_not_support_no_priority_state_update = Callback request does not support unprioritized pagestate update.
callback_invalid_callback_options = '{1}' is not a valid TCallbackOptions control for Callback control '{0}'.
callback_invalid_clientside_options = Callback ClientSide property must be either a string that is the ID of a TCallbackOptions control or an instance of TCallbackClientSideOptions.=======
diff --git a/framework/I18N/core/MessageFormat.php b/framework/I18N/core/MessageFormat.php
index dab7434c..3faa663d 100644
--- a/framework/I18N/core/MessageFormat.php
+++ b/framework/I18N/core/MessageFormat.php
@@ -161,6 +161,10 @@ class MessageFormat
public function format($string,$args=array(), $catalogue=null, $charset=null)
{
if(empty($charset)) $charset = $this->getCharset();
+
+ //force args as UTF-8
+ foreach($args as $k => $v)
+ $args[$k] = I18N_toUTF8($v, $charset);
$s = $this->formatString(I18N_toUTF8($string, $charset),$args,$catalogue);
return I18N_toEncoding($s, $charset);
}
diff --git a/framework/I18N/core/NumberFormat.php b/framework/I18N/core/NumberFormat.php
index 8e715f15..b30e615b 100644
--- a/framework/I18N/core/NumberFormat.php
+++ b/framework/I18N/core/NumberFormat.php
@@ -161,9 +161,14 @@ class NumberFormat
$string = (string)$string;
$dp = strpos($string, '.');
+ $decimalDigits = $this->formatInfo->DecimalDigits;
+// var_dump($decimalDigits);
+ //if not decimal digits, assume 0 decimal points.
+ if(is_int($decimalDigits) && $decimalDigits > 0)
+ $string = (string)round(floatval($string),$decimalDigits);
if(is_int($dp))
- $string = substr($string, 0, $dp);
-
+ $string = substr($string, 0, $dp);
+
$integer = '';
$digitSize = $this->formatInfo->getDigitSize();
@@ -233,7 +238,9 @@ class NumberFormat
$decimalDigits = $this->formatInfo->DecimalDigits;
$decimalSeparator = $this->formatInfo->DecimalSeparator;
-
+
+ //do the correct rounding here
+ //$string = round(floatval($string), $decimalDigits);
if(is_int($dp))
{
if($decimalDigits == -1)
diff --git a/framework/PradoBase.php b/framework/PradoBase.php
index 608784e9..50e4ac82 100644
--- a/framework/PradoBase.php
+++ b/framework/PradoBase.php
@@ -563,86 +563,16 @@ class PradoBase
}
/**
- * The following code is meant to fill the gaps between different PHP versions.
+ * TReflectionClass class.
+ * This class was originally written to cope with the incompatibility between different PHP versions.
+ * It is equivalent to ReflectionClass for PHP version >= 5.1.0
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $ $Date: $
+ * @package System
+ * @since 3.0
*/
-if(version_compare(phpversion(),'5.1.0','>='))
+class TReflectionClass extends ReflectionClass
{
- /**
- * TReflectionClass class.
- * This class is written to cope with the incompatibility between different PHP versions.
- * It is equivalent to ReflectionClass if PHP version >= 5.1.0
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $ $Date: $
- * @package System
- * @since 3.0
- */
- class TReflectionClass extends ReflectionClass
- {
- }
-}
-else // PHP < 5.1.0
-{
- /**
- * TReflectionClass class.
- * This class is written to cope with the incompatibility between different PHP versions.
- * It mainly provides a way to detect if a method exists for a given class name.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $ $Date: $
- * @package System
- * @since 3.0
- */
- class TReflectionClass extends ReflectionClass
- {
- /**
- * @param string method name
- * @return boolean whether the method exists
- */
- public function hasMethod($method)
- {
- try
- {
- return $this->getMethod($method)!==null;
- }
- catch(Exception $e)
- {
- return false;
- }
- }
-
- /**
- * @param string property name
- * @return boolean whether the property exists
- */
- public function hasProperty($property)
- {
- try
- {
- return $this->getProperty($property)!==null;
- }
- catch(Exception $e)
- {
- return false;
- }
- }
- }
-
- if(!function_exists('property_exists'))
- {
- /**
- * Detects whether an object contains the specified member variable.
- * @param object
- * @param string member variable (property) name
- * @return boolean
- */
- function property_exists($object, $property)
- {
- if(is_object($object))
- return array_key_exists($property, get_object_vars($object));
- else
- return false;
- }
- }
}
?>
diff --git a/framework/Security/TAuthManager.php b/framework/Security/TAuthManager.php
index ee01d5f3..e378b51e 100644
--- a/framework/Security/TAuthManager.php
+++ b/framework/Security/TAuthManager.php
@@ -195,10 +195,6 @@ class TAuthManager extends TModule
public function onAuthenticate($param)
{
$application=$this->getApplication();
- if($this->hasEventHandler('OnAuthenticate'))
- $this->raiseEvent('OnAuthenticate',$this,$application);
- if($application->getUser()!==null)
- return;
if(($session=$application->getSession())===null)
throw new TConfigurationException('authmanager_session_required');
@@ -206,6 +202,10 @@ class TAuthManager extends TModule
$sessionInfo=$session->itemAt($this->generateUserSessionKey());
$user=$this->_userManager->getUser(null)->loadFromString($sessionInfo);
$application->setUser($user);
+
+ // event handler gets a chance to do further auth work
+ if($this->hasEventHandler('OnAuthenticate'))
+ $this->raiseEvent('OnAuthenticate',$this,$application);
}
/**
diff --git a/framework/Util/TSimpleDateFormatter.php b/framework/Util/TSimpleDateFormatter.php
index 2a3da63a..971225b5 100644
--- a/framework/Util/TSimpleDateFormatter.php
+++ b/framework/Util/TSimpleDateFormatter.php
@@ -294,11 +294,14 @@ class TSimpleDateFormatter
}
if ($i_val != $this->length($value))
throw new TInvalidDataValueException("Pattern '{$this->pattern}' mismatch", $value);
-
+ //var_dump('month is '.$month);
if(!$defaultToCurrentTime && (is_null($month) || is_null($day) || is_null($year)))
return null;
else
+ {
+ $day = intval($day) <= 0 ? 1 : intval($day);
return @mktime(0, 0, 0, $month, $day, $year);
+ }
}
/**
diff --git a/framework/Web/THttpRequest.php b/framework/Web/THttpRequest.php
index 01827f33..130dc3cf 100644
--- a/framework/Web/THttpRequest.php
+++ b/framework/Web/THttpRequest.php
@@ -57,13 +57,12 @@
* @package System.Web
* @since 3.0
*/
-class THttpRequest extends TApplicationComponent implements IteratorAggregate,ArrayAccess,IModule
+class THttpRequest extends TApplicationComponent implements IteratorAggregate,ArrayAccess,Countable,IModule
{
/**
* Separator used to separate GET variable name and value when URL format is Path.
*/
- const URL_PARAM_SEPARATOR=',';
-
+ private $_separator=',';
/**
* @var boolean whether the module is initialized
*/
@@ -227,6 +226,26 @@ class THttpRequest extends TApplicationComponent implements IteratorAggregate,Ar
}
/**
+ * @return string separator used to separate GET variable name and value when URL format is Path. Defaults to comma ','.
+ */
+ public function getUrlParamSeparator()
+ {
+ return $this->_separator;
+ }
+
+ /**
+ * @param string separator used to separate GET variable name and value when URL format is Path.
+ * @throws TInvalidDataValueException if the separator is not a single character
+ */
+ public function setUrlParamSeparator($value)
+ {
+ if(strlen($value)===1)
+ $this->_separator=$value;
+ else
+ throw new TInvalidDataValueException('httprequest_separator_invalid');
+ }
+
+ /**
* @return string request type, can be GET, POST, HEAD, or PUT
*/
public function getRequestType()
@@ -460,10 +479,7 @@ class THttpRequest extends TApplicationComponent implements IteratorAggregate,Ar
*/
public function constructUrl($serviceID,$serviceParam,$getItems=null,$encodeAmpersand=false,$encodeGetItems=true)
{
- if($this->getUrlFormat()==='Path')
- $url=$serviceID.'/'.$serviceParam;
- else
- $url=$serviceID.'='.$serviceParam;
+ $url=$serviceID.'='.$serviceParam;
$amp=$encodeAmpersand?'&amp;':'&';
if(is_array($getItems) || $getItems instanceof Traversable)
{
@@ -497,7 +513,7 @@ class THttpRequest extends TApplicationComponent implements IteratorAggregate,Ar
}
if($this->getUrlFormat()==='Path')
{
- $url=strtr($url,array($amp=>'/','?'=>'/','='=>self::URL_PARAM_SEPARATOR));
+ $url=strtr($url,array($amp=>'/','?'=>'/','='=>$this->_separator));
if(defined('SID') && SID != '' && !((int)ini_get('session.use_cookies')===1 && ((int)ini_get('session.use_only_cookies')===1)))
$url.='?'.SID;
return $this->getApplicationUrl().'/'.$url;
@@ -523,13 +539,12 @@ class THttpRequest extends TApplicationComponent implements IteratorAggregate,Ar
{
$paths=explode('/',$this->_pathInfo);
$getVariables=$_GET;
- $index=0;
$serviceID=null;
foreach($paths as $path)
{
if(($path=trim($path))!=='')
{
- if(($pos=strpos($path,','))!==false)
+ if(($pos=strpos($path,$this->_separator))!==false)
{
$name=substr($path,0,$pos);
$value=substr($path,$pos+1);
@@ -538,16 +553,8 @@ class THttpRequest extends TApplicationComponent implements IteratorAggregate,Ar
else
$getVariables[$name]=$value;
}
- else if($index===0)
- {
- $serviceID=$path;
- $getVariables[$serviceID]='';
- }
- else if($index===1 && $serviceID!==null)
- $getVariables[$serviceID]=$path;
else
$getVariables[$path]='';
- $index++;
}
}
return $getVariables;
@@ -654,6 +661,16 @@ class THttpRequest extends TApplicationComponent implements IteratorAggregate,Ar
}
/**
+ * Returns the number of items in the request.
+ * This method is required by Countable interface.
+ * @return integer number of items in the request.
+ */
+ public function count()
+ {
+ return $this->getCount();
+ }
+
+ /**
* @return array the key list
*/
public function getKeys()
diff --git a/framework/Web/THttpSession.php b/framework/Web/THttpSession.php
index 4439cf57..19473cda 100644
--- a/framework/Web/THttpSession.php
+++ b/framework/Web/THttpSession.php
@@ -61,7 +61,7 @@
* @package System.Web
* @since 3.0
*/
-class THttpSession extends TApplicationComponent implements IteratorAggregate,ArrayAccess,IModule
+class THttpSession extends TApplicationComponent implements IteratorAggregate,ArrayAccess,Countable,IModule
{
/**
* @var boolean whether this module has been initialized
@@ -139,7 +139,8 @@ class THttpSession extends TApplicationComponent implements IteratorAggregate,Ar
session_set_save_handler(array($this,'_open'),array($this,'_close'),array($this,'_read'),array($this,'_write'),array($this,'_destroy'),array($this,'_gc'));
if($this->_cookie!==null)
session_set_cookie_params($this->_cookie->getExpire(),$this->_cookie->getPath(),$this->_cookie->getDomain(),$this->_cookie->getSecure());
- session_start();
+ if(ini_get('session.auto_start')!=='1')
+ session_start();
$this->_started=true;
}
}
@@ -487,6 +488,16 @@ class THttpSession extends TApplicationComponent implements IteratorAggregate,Ar
}
/**
+ * Returns the number of items in the session.
+ * This method is required by Countable interface.
+ * @return integer number of items in the session.
+ */
+ public function count()
+ {
+ return $this->getCount();
+ }
+
+ /**
* @return array the list of session variable names
*/
public function getKeys()
diff --git a/framework/Web/UI/TTemplateControl.php b/framework/Web/UI/TTemplateControl.php
index c7364d4b..3bbe52c5 100644
--- a/framework/Web/UI/TTemplateControl.php
+++ b/framework/Web/UI/TTemplateControl.php
@@ -129,7 +129,7 @@ class TTemplateControl extends TCompositeControl
*/
public function createChildControls()
{
- if($tpl=$this->getTemplate(true))
+ if($tpl=$this->getTemplate())
{
foreach($tpl->getDirective() as $name=>$value)
{
diff --git a/framework/Web/UI/WebControls/TDatePicker.php b/framework/Web/UI/WebControls/TDatePicker.php
index 27d080c6..42cb305e 100644
--- a/framework/Web/UI/WebControls/TDatePicker.php
+++ b/framework/Web/UI/WebControls/TDatePicker.php
@@ -69,6 +69,15 @@ Prado::using('System.Web.UI.WebControls.TTextBox');
class TDatePicker extends TTextBox
{
/**
+ * AutoPostBack is not supported.
+ */
+ public function setAutoPostBack($value)
+ {
+ throw new TNotSupportedException('tdatepicker_autopostback_unsupported',
+ get_class($this));
+ }
+
+ /**
* @return string the format of the date string
*/
public function getDateFormat()
@@ -328,7 +337,7 @@ class TDatePicker extends TTextBox
*/
protected function renderDatePickerButtons($writer)
{
- if($this->getShowCalendar())
+ if($this->getShowCalendar() && $this->getEnabled(true))
{
switch ($this->getMode())
{
@@ -384,7 +393,9 @@ class TDatePicker extends TTextBox
$year = intval($values[$key.'$year']);
else
$year = $date['year'];
+
$date = @mktime(0, 0, 0, $month, $day, $year);
+
$pattern = $this->getDateFormat();
$pattern = str_replace(array('MMMM', 'MMM'), array('MM','MM'), $pattern);
$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter', $pattern);
@@ -497,12 +508,13 @@ class TDatePicker extends TTextBox
{
$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter',
$this->getDateFormat());
+
foreach($formatter->getDayMonthYearOrdering() as $type)
{
if($type == 'day')
$this->renderCalendarDayOptions($writer,$date['mday']);
elseif($type == 'month')
- $this->renderCalendarMonthOptions($writer,$date['mon']-1);
+ $this->renderCalendarMonthOptions($writer,$date['mon']);
elseif($type == 'year')
$this->renderCalendarYearOptions($writer,$date['year']);
}
@@ -550,6 +562,8 @@ class TDatePicker extends TTextBox
$writer->addAttribute('id', $this->getClientID().'_day');
$writer->addAttribute('name', $this->getUniqueID().'$day');
$writer->addAttribute('class', 'datepicker_day_options');
+ if($this->getReadOnly() || !$this->getEnabled(true))
+ $writer->addAttribute('disabled', 'disabled');
$writer->renderBeginTag('select');
$this->renderDropDownListOptions($writer, $days, $selected);
$writer->renderEndTag();
@@ -562,13 +576,16 @@ class TDatePicker extends TTextBox
*/
protected function renderCalendarMonthOptions($writer, $selected=null)
{
+
$info = $this->getLocalizedCalendarInfo();
$writer->addAttribute('id', $this->getClientID().'_month');
$writer->addAttribute('name', $this->getUniqueID().'$month');
$writer->addAttribute('class', 'datepicker_month_options');
+ if($this->getReadOnly() || !$this->getEnabled(true))
+ $writer->addAttribute('disabled', 'disabled');
$writer->renderBeginTag('select');
$this->renderDropDownListOptions($writer,
- $this->getLocalizedMonthNames($info), $selected);
+ $this->getLocalizedMonthNames($info), $selected-1);
$writer->renderEndTag();
}
@@ -585,8 +602,12 @@ class TDatePicker extends TTextBox
$this->getDateFormat());
switch($formatter->getMonthPattern())
{
- case 'MMM':
- case 'MM': return $info->getAbbreviatedMonthNames();
+ case 'MMM': return $info->getAbbreviatedMonthNames();
+ case 'MM':
+ $array = array();
+ for($i=1;$i<=12;$i++)
+ $array[$i-1] = $i < 10 ? '0'.$i : $i;
+ return $array;
case 'M':
$array = array(); for($i=1;$i<=12;$i++) $array[$i-1] = $i;
return $array;
@@ -606,6 +627,8 @@ class TDatePicker extends TTextBox
$years[$i] = $i;
$writer->addAttribute('id', $this->getClientID().'_year');
$writer->addAttribute('name', $this->getUniqueID().'$year');
+ if($this->getReadOnly() || !$this->getEnabled(true))
+ $writer->addAttribute('disabled', 'disabled');
$writer->renderBeginTag('select');
$writer->addAttribute('class', 'datepicker_year_options');
$this->renderDropDownListOptions($writer, $years, $selected);
diff --git a/index.html b/index.html
index dd2f8582..8b2446ca 100644
--- a/index.html
+++ b/index.html
@@ -28,7 +28,7 @@ All Rights Reserved.
<h2>Requirements</h2>
<p>
-The sole requirement for PRADO is PHP 5.0.4 or higher.
+The sole requirement for PRADO is PHP 5.1.0 or higher.
Please run <a href="requirements/index.php">requirement checker</a> to obtain
more detailed requirement information.
</p>
diff --git a/requirements/index.php b/requirements/index.php
index a94c92cf..fb58dfce 100644
--- a/requirements/index.php
+++ b/requirements/index.php
@@ -32,13 +32,8 @@
$requirements = array(
array(
true,
- version_compare(PHP_VERSION,"5.0.4",">="),
- 'PHP version check',
- 'PHP 5.0.4 or higher required'),
- array(
- false,
version_compare(PHP_VERSION,"5.1.0",">="),
- 'PHP version check','PHP 5.1.0 or higher preferred'),
+ 'PHP version check','PHP 5.1.0 or higher required'),
array(
true,
isset($_SERVER["HTTP_ACCEPT"]),
diff --git a/requirements/messages-bg.txt b/requirements/messages-bg.txt
index ea54f02c..e1be6b5d 100644
--- a/requirements/messages-bg.txt
+++ b/requirements/messages-bg.txt
@@ -2,8 +2,7 @@
passed with warnings = Конфигурацията на вашия сървър удовлетворява минималните изисквания на PRADO. Моля, обърнете внимание на предупрежденията по-долу.
failed = За съжаление, вашият сървър не удовлетворява изискванията на PRADO.
PHP version check = Проверка за версията на PHP
-PHP 5.0.4 or higher required = Изисква се PHP 5.0.4 или по-висока версия.
-PHP 5.1.0 or higher preferred = Препоръчва се PHP 5.1.0 или по-висока версия. Това ще предотврати грешката предизвикана от рекурсивните __get/__set извиквания.
+PHP 5.1.0 or higher required = Изисква се PHP 5.1.0 или по-висока версия.
SQLite extension check = Проверка за SQLite
SQLite extension optional = SQLite разширението е незадължително. Ако не е заредено, няма да можете да ползвате TSqliteCache.
Memcache extension check = Проверка за Memcache
diff --git a/requirements/messages-zh.txt b/requirements/messages-zh.txt
index b86d96cf..6ee6e2c4 100644
--- a/requirements/messages-zh.txt
+++ b/requirements/messages-zh.txt
@@ -2,8 +2,7 @@
passed with warnings = 您的服务器配置符合PRADO的最低要求。请关注以下的警告信息。
failed = 对不起,您的服务器配置不符合PRADO的要求。
PHP version check = PHP版本检查
-PHP 5.0.4 or higher required = PRADO需要PHP 5.0.4或更高版本。
-PHP 5.1.0 or higher preferred = PRADO推荐使用PHP 5.1.0或更高版本。它将避免由于递归调用__get/__call引起的错误。
+PHP 5.1.0 or higher required = PRADO需要PHP 5.1.0或更高版本。
SQLite extension check = SQLite模块检查
SQLite extension optional = SQLite模块是可选的。如果它不存在,您将无法使用TSQLiteCache。
Memcache extension check = Memcache模块检查
diff --git a/requirements/messages.txt b/requirements/messages.txt
index ccda04b2..5c1a1364 100644
--- a/requirements/messages.txt
+++ b/requirements/messages.txt
@@ -2,8 +2,7 @@ all passed = Congratulations! Your server configuration satisfies all requ
passed with warnings = Your server configuration satisfies minimum requirements by PRADO. Please pay attention to the warnings listed below.
failed = Sorry, your server configuration does not satisfy the requirements by PRADO.
PHP version check = PHP version check
-PHP 5.0.4 or higher required = PHP version 5.0.4 or higher is required by PRADO.
-PHP 5.1.0 or higher preferred = PHP version 5.1.0 or higher is preferred by PRADO. It eliminates the error caused by recursive __get/__set calls.
+PHP 5.1.0 or higher required = PHP version 5.1.0 or higher is required by PRADO.
SQLite extension check = SQLite extension check
SQLite extension optional = SQLite extension is optional. If it is absent, you will not be able to use TSqliteCache.
Memcache extension check = Memcache extension check
diff --git a/tests/FunctionalTests/tickets/protected/messages/en/messages.xml b/tests/FunctionalTests/tickets/protected/messages/en/messages.xml
new file mode 100644
index 00000000..9b04d076
--- /dev/null
+++ b/tests/FunctionalTests/tickets/protected/messages/en/messages.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<xliff version="1.0">
+ <file source-language="EN" target-language="en" datatype="plaintext" original="messages" date="2006-08-01T12:08:27Z" product-name="messages">
+ <body>
+
+<trans-unit id="1">
+<source>{field} is required.</source>
+<target>Lütfen '{field}' alanını doldurunuz.</target>
+</trans-unit>
+
+<trans-unit id="2">
+<source>city</source>
+<target>Şehir</target>
+</trans-unit>
+</body>
+ </file>
+</xliff>
diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket220.page b/tests/FunctionalTests/tickets/protected/pages/Ticket220.page
index d5b6e182..e4c8fa95 100644
--- a/tests/FunctionalTests/tickets/protected/pages/Ticket220.page
+++ b/tests/FunctionalTests/tickets/protected/pages/Ticket220.page
@@ -16,7 +16,7 @@
<com:TLabel ID="label1" Text="Label 1" />
<input type="button" id="button1" value="update" />
- <com:TClientScript UsingPradoScripts="prado">
+ <com:TClientScript PradoScripts="prado">
Event.observe("button1", "click", function()
{
element = $("<%= $this->label1->ClientID %>");
diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket269.page b/tests/FunctionalTests/tickets/protected/pages/Ticket269.page
new file mode 100644
index 00000000..fe5721e3
--- /dev/null
+++ b/tests/FunctionalTests/tickets/protected/pages/Ticket269.page
@@ -0,0 +1,10 @@
+<com:TContent ID="Content">
+
+ <com:System.I18N.TDateFormat
+ Value="2006-07-05"
+ Culture="de_DE"
+ Pattern="dd.MMMM.yyyy" />
+ <br />
+ <com:TLabel Text="Zurück" />
+
+</com:TContent> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket285.page b/tests/FunctionalTests/tickets/protected/pages/Ticket285.page
new file mode 100644
index 00000000..9aeb37e9
--- /dev/null
+++ b/tests/FunctionalTests/tickets/protected/pages/Ticket285.page
@@ -0,0 +1,7 @@
+<com:TContent ID="Content">
+
+<com:System.I18N.TNumberFormat Value="349.999" Pattern="#.00" />
+
+<com:System.I18N.TNumberFormat Value="349.99" Pattern="#.00" />
+
+</com:TContent> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket306.page b/tests/FunctionalTests/tickets/protected/pages/Ticket306.page
new file mode 100644
index 00000000..6a202cc6
--- /dev/null
+++ b/tests/FunctionalTests/tickets/protected/pages/Ticket306.page
@@ -0,0 +1,12 @@
+<com:TContent ID="Content">
+
+<com:TTranslate>
+ {field} is required.
+ <com:TTranslateParameter Key="field">
+ <com:TTranslate>
+ city
+ </com:TTranslate>
+ </com:TTranslateParameter>
+</com:TTranslate>
+
+</com:TContent> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket311.page b/tests/FunctionalTests/tickets/protected/pages/Ticket311.page
new file mode 100644
index 00000000..45b41b7d
--- /dev/null
+++ b/tests/FunctionalTests/tickets/protected/pages/Ticket311.page
@@ -0,0 +1,18 @@
+<com:TContent ID="Content">
+<com:TButton Text="Click me" />
+<com:TDatePicker
+ InputMode="DropDownList"
+ DateFormat="M/yyyy" />
+
+<com:TDatePicker
+ InputMode="DropDownList"
+ DateFormat="MM/yyyy" />
+
+ <com:TDatePicker
+ InputMode="DropDownList"
+ DateFormat="MMM/yyyy" />
+
+ <com:TDatePicker
+ InputMode="DropDownList"
+ DateFormat="MMMM/yyyy" />
+</com:TContent> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket312.page b/tests/FunctionalTests/tickets/protected/pages/Ticket312.page
new file mode 100644
index 00000000..f6c550c5
--- /dev/null
+++ b/tests/FunctionalTests/tickets/protected/pages/Ticket312.page
@@ -0,0 +1,11 @@
+<com:TContent ID="Content">
+<com:TButton Text="Click me" />
+<com:TDatePicker
+ ReadOnly="true"
+ InputMode="DropDownList"
+ DateFormat="M/yyyy" />
+
+<com:TDatePicker
+ DateFormat="d/M/yyyy" />
+
+</com:TContent> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/protected/pages/config.xml b/tests/FunctionalTests/tickets/protected/pages/config.xml
index 48a0114c..9404e969 100644
--- a/tests/FunctionalTests/tickets/protected/pages/config.xml
+++ b/tests/FunctionalTests/tickets/protected/pages/config.xml
@@ -4,5 +4,13 @@
<paths>
<using namespace="System.I18N.*" />
</paths>
+ <modules>
+ <module id="globalization" class="TGlobalization">
+ <translation type="XLIFF"
+ source="Application.messages"
+ autosave="true"/>
+ </module>
+ </modules>
+
<pages MasterClass="Application.pages.Layout" />
</configuration> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/tests/Ticket285TestCase.php b/tests/FunctionalTests/tickets/tests/Ticket285TestCase.php
new file mode 100644
index 00000000..cd681c58
--- /dev/null
+++ b/tests/FunctionalTests/tickets/tests/Ticket285TestCase.php
@@ -0,0 +1,12 @@
+<?php
+
+class Ticket285TestCase extends SeleniumTestCase
+{
+ function test()
+ {
+ $this->open('tickets/index.php?page=Ticket285');
+ $this->assertTextPresent('350.00');
+ $this->assertTextPresent('349.99');
+ }
+}
+?> \ No newline at end of file
diff --git a/tests/unit/I18N/core/NumberFormatTest.php b/tests/unit/I18N/core/NumberFormatTest.php
index af6a06ca..e136058e 100644
--- a/tests/unit/I18N/core/NumberFormatTest.php
+++ b/tests/unit/I18N/core/NumberFormatTest.php
@@ -12,6 +12,7 @@ class NumberFormatTest extends PHPUnit2_Framework_TestCase {
$formatter = new NumberFormat();
$number = '123456789.125156';
$wanted = '123,456,789.125156';
+
$this->assertEquals($wanted, $formatter->format($number));
//currency
@@ -87,8 +88,7 @@ class NumberFormatTest extends PHPUnit2_Framework_TestCase {
$pattern = '0000';
$wanted = '0005';
- //this should fail!!!
- $this->assertNotEquals($wanted, $formatter->format($number, $pattern));
+ $this->assertEquals($wanted, $formatter->format($number, $pattern));
}
function testFormatWithANegativeValue() {
@@ -105,7 +105,28 @@ class NumberFormatTest extends PHPUnit2_Framework_TestCase {
$expected = "10E";
$this->assertEquals('10E', $formatter->format($number, 'e'));
}
+
+ function testRounding()
+ {
+ $formatter = new NumberFormat();
+
+ $number = 349.999;
+ $pattern = '#.00';
+ $expected = '350.00';
+
+ $this->assertEquals($expected, $formatter->format($number, $pattern));
+ }
+ function testRounding2()
+ {
+ $formatter = new NumberFormat();
+
+ $number = 349.99;
+ $pattern = '#.00';
+ $expected = '349.99';
+
+ $this->assertEquals($expected, $formatter->format($number, $pattern));
+ }
}
?> \ No newline at end of file