Repository: yiisoft/yii (language: php)

Issue:
Argument 2 in number_format does not accept null
<!--
Note that only PHP 7 and PHP 8 compatibility issues are accepted. For security issues contact maintainers privately.
-->

### What steps will reproduce the problem?
Call CFormatted::formatNumber($value) will call number_format($value) where the three next default arguments are gotten from CFormat::$numberFormat. The decimals argument will be set to null, which is deprecated, thus giving the error message given below.

The fix is to change  CFormatter::$numberFormat['deciamls'] from null to 0.

### What is the expected result?
No error message

### What do you get instead?
Error message: number_format(): Passing null to parameter #2 ($decimals) of type int is deprecated


### Additional info

| Q                | A
| ---------------- | ---
| Yii version      | 1.1.27
| PHP version      | 8.1.13
| Operating system | Linux Mint 21.1



Discussion / hints:

Fix patch:
diff --git a/CHANGELOG b/CHANGELOG
index b3a675541c..4a0d528a10 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -4,6 +4,7 @@
 Version 1.1.28 under development
 --------------------------------
 
+- Enh #4503: Update tests and code for PHP 8.1 compatibility, stop suppressing deprecation warnings in tests (wtommyw)
 - Bug #4491: Fixed limit and Offset not working correctly with MSSQL version 11 (2012) and newer (shnoulle, wtommyw)
 - Bug #4497: PHP 8.1 compatibility: Fix unserialize null in CRedisCache (kenguest, wtommyw)
 - Bug #4500: PHP 8.1 compatibility: Fix deprecation warnings in CMysql classes (csears123)
diff --git a/framework/i18n/CLocale.php b/framework/i18n/CLocale.php
index 09af68af5e..8495cf582f 100644
--- a/framework/i18n/CLocale.php
+++ b/framework/i18n/CLocale.php
@@ -417,7 +417,7 @@ public function getTerritoryID($id)
 	 */
 	public function getLocaleDisplayName($id=null, $category='languages')
 	{
-		$id = $this->getCanonicalID($id);
+		$id = $this->getCanonicalID((string)$id);
 		if (($category == 'languages') && (isset($this->_data[$category][$id])))
 		{
 			return $this->_data[$category][$id];
diff --git a/framework/utils/CFormatter.php b/framework/utils/CFormatter.php
index 132137c7b1..ed95375203 100644
--- a/framework/utils/CFormatter.php
+++ b/framework/utils/CFormatter.php
@@ -73,7 +73,7 @@ class CFormatter extends CApplicationComponent
 	 * They correspond to the number of digits after the decimal point, the character displayed as the decimal point
 	 * and the thousands separator character.
 	 */
-	public $numberFormat=array('decimals'=>null, 'decimalSeparator'=>null, 'thousandSeparator'=>null);
+	public $numberFormat=array('decimals'=>0, 'decimalSeparator'=>null, 'thousandSeparator'=>null);
 	/**
 	 * @var array the text to be displayed when formatting a boolean value. The first element corresponds
 	 * to the text display for false, the second element for true. Defaults to <code>array('No', 'Yes')</code>.
diff --git a/framework/validators/CDateValidator.php b/framework/validators/CDateValidator.php
index 89287a32aa..2a875d9cc3 100644
--- a/framework/validators/CDateValidator.php
+++ b/framework/validators/CDateValidator.php
@@ -55,7 +55,8 @@ protected function validateAttribute($object,$attribute)
 		$valid=false;
 
 		// reason of array checking is explained here: https://github.com/yiisoft/yii/issues/1955
-		if(!is_array($value))
+		// checking for `null` as passing `null` to CDateTimeParser::parse will throw a deprecation error in PHP >= 8.1
+		if(!is_array($value) && $value !== null)
 		{
 			$formats=is_string($this->format) ? array($this->format) : $this->format;
 			foreach($formats as $format)
diff --git a/framework/validators/CStringValidator.php b/framework/validators/CStringValidator.php
index 98a94544b4..42af241914 100644
--- a/framework/validators/CStringValidator.php
+++ b/framework/validators/CStringValidator.php
@@ -88,9 +88,9 @@ protected function validateAttribute($object,$attribute)
 		}
 
 		if(function_exists('mb_strlen') && $this->encoding!==false)
-			$length=mb_strlen($value, $this->encoding ? $this->encoding : Yii::app()->charset);
+			$length=mb_strlen((string)$value, $this->encoding ? $this->encoding : Yii::app()->charset);
 		else
-			$length=strlen($value);
+			$length=strlen((string)$value);
 
 		if($this->min!==null && $length<$this->min)
 		{
diff --git a/framework/web/helpers/CHtml.php b/framework/web/helpers/CHtml.php
index d20a11eb1f..927b23b279 100644
--- a/framework/web/helpers/CHtml.php
+++ b/framework/web/helpers/CHtml.php
@@ -2370,7 +2370,7 @@ public static function listData($models,$valueField,$textField,$groupField='')
 	public static function value($model,$attribute,$defaultValue=null)
 	{
 		if(is_scalar($attribute) || $attribute===null)
-			foreach(explode('.',$attribute) as $name)
+			foreach(explode('.',(string)$attribute) as $name)
 			{
 				if(is_object($model))
 				{
diff --git a/framework/web/widgets/CStarRating.php b/framework/web/widgets/CStarRating.php
index 071fe0835b..de2f736bdc 100644
--- a/framework/web/widgets/CStarRating.php
+++ b/framework/web/widgets/CStarRating.php
@@ -170,7 +170,7 @@ protected function renderStars($id,$name)
 				$options['title']=$this->titles[$value];
 			else
 				unset($options['title']);
-			echo CHtml::radioButton($name,!strcmp($value,$selection),$options) . "\n";
+			echo CHtml::radioButton($name,!strcmp($value,(string)$selection),$options) . "\n";
 		}
 	}
 
@@ -202,4 +202,4 @@ protected function getClientOptions()
 		}
 		return $options;
 	}
-}
\ No newline at end of file
+}


Test patch:
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 16ba5f1429..18ea5772e3 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -1,10 +1,5 @@
 <?php
 
-if (PHP_MAJOR_VERSION>=7 && PHP_MINOR_VERSION>=1) {
-	// skip deprecation errors in PHP 7.1 and above
-	error_reporting(E_ALL & ~E_DEPRECATED);
-}
-
 defined('YII_ENABLE_EXCEPTION_HANDLER') or define('YII_ENABLE_EXCEPTION_HANDLER',false);
 defined('YII_ENABLE_ERROR_HANDLER') or define('YII_ENABLE_ERROR_HANDLER',false);
 defined('YII_DEBUG') or define('YII_DEBUG',true);
diff --git a/tests/framework/base/CSecurityManagerTest.php b/tests/framework/base/CSecurityManagerTest.php
index 15cdae66c9..8cc386ffcd 100644
--- a/tests/framework/base/CSecurityManagerTest.php
+++ b/tests/framework/base/CSecurityManagerTest.php
@@ -246,7 +246,7 @@ public function dataProviderCompareStrings()
 	public function testCompareStrings($expected, $actual)
 	{
 		$sm=new CSecurityManager;
-		$this->assertEquals(strcmp($expected,$actual)===0,$sm->compareString($expected,$actual));
+		$this->assertEquals(strcmp((string)$expected,(string)$actual)===0,$sm->compareString((string)$expected,(string)$actual));
 	}
 
 	/**
diff --git a/tests/framework/i18n/CLocaleTest.php b/tests/framework/i18n/CLocaleTest.php
index 4fe3af9b8a..f9a10a9923 100644
--- a/tests/framework/i18n/CLocaleTest.php
+++ b/tests/framework/i18n/CLocaleTest.php
@@ -123,7 +123,7 @@ public function providerGetLocaleDisplayName()
 	public function testGetLocaleDisplayName($ctorLocale,$methodLocale,$assertion)
 	{
 		$locale=CLocale::getInstance($ctorLocale);
-		$this->assertEquals(mb_strtolower($assertion),mb_strtolower($locale->getLocaleDisplayName($methodLocale)));
+		$this->assertEquals(mb_strtolower((string)$assertion),mb_strtolower((string)$locale->getLocaleDisplayName((string)$methodLocale)));
 	}
 
 	public function providerGetLanguage()
@@ -176,7 +176,7 @@ public function providerGetLanguage()
 	public function testGetLanguage($ctorLocale,$methodLocale,$assertion)
 	{
 		$locale=CLocale::getInstance($ctorLocale);
-		$this->assertEquals(mb_strtolower($assertion),mb_strtolower($locale->getLanguage($methodLocale)));
+		$this->assertEquals(mb_strtolower((string)$assertion),mb_strtolower((string)$locale->getLanguage((string)$methodLocale)));
 	}
 
 	public function providerGetScript()
@@ -217,7 +217,7 @@ public function providerGetScript()
 	public function testGetScript($ctorLocale,$methodLocale,$assertion)
 	{
 		$locale=CLocale::getInstance($ctorLocale);
-		$this->assertEquals($assertion,$locale->getScript($methodLocale));
+		$this->assertEquals((string)$assertion,$locale->getScript((string)$methodLocale));
 	}
 
 	public function providerGetTerritory()
@@ -264,6 +264,6 @@ public function providerGetTerritory()
 	public function testGetTerritory($ctorLocale,$methodLocale,$assertion)
 	{
 		$locale=CLocale::getInstance($ctorLocale);
-		$this->assertEquals($assertion,$locale->getTerritory($methodLocale));
+		$this->assertEquals((string)$assertion,$locale->getTerritory((string)$methodLocale));
 	}
 }
diff --git a/tests/framework/utils/CDateTimeParserTest.php b/tests/framework/utils/CDateTimeParserTest.php
index 7c364ff149..eb18a2e85d 100644
--- a/tests/framework/utils/CDateTimeParserTest.php
+++ b/tests/framework/utils/CDateTimeParserTest.php
@@ -193,8 +193,6 @@ public function testFailing()
 	{
 		// empty parsed string
 		$this->assertFalse(CDateTimeParser::parse('', 'dd MMMM, yyyy, HH:mm'));
-		$this->assertFalse(CDateTimeParser::parse(false, 'dd MMMM, yyyy, HH:mm'));
-		$this->assertFalse(CDateTimeParser::parse(null, 'dd MMMM, yyyy, HH:mm'));
 
 		// accidently mixed up arguments
 		$this->assertFalse(CDateTimeParser::parse('dd/MM/yyyy, ???, hh:m:s', '02/08/2010, yyy, 05:9:7'));
diff --git a/tests/framework/utils/CFormatterTest.php b/tests/framework/utils/CFormatterTest.php
index e9dd35d34e..97b0ea905f 100644
--- a/tests/framework/utils/CFormatterTest.php
+++ b/tests/framework/utils/CFormatterTest.php
@@ -123,4 +123,57 @@ public function testFormatNtext($value, $paragraphs, $removeEmptyParagraphs, $as
 		$formatter = new CFormatter();
 		$this->assertEquals($assertion, $formatter->formatNtext($value, $paragraphs, $removeEmptyParagraphs));
 	}
+
+	/**
+	 * @dataProvider providerFormatNumber()
+	 * @param string $value
+	 * @param string $decimals
+	 * @param string $decimalSeparator
+	 * @param string $thousandSeparator
+	 * @param string $assertion
+	 */
+	public function testFormatNumber($value,$decimals,$decimalSeparator,$thousandSeparator,$assertion)
+	{
+		$formatter = new CFormatter();
+
+		if ($decimals!==null)
+			$formatter->numberFormat['decimals']=$decimals;
+
+		if ($decimalSeparator!==null)
+			$formatter->numberFormat['decimalSeparator']=$decimalSeparator;
+
+		if ($thousandSeparator!==null)
+			$formatter->numberFormat['thousandSeparator']=$thousandSeparator;
+
+		$this->assertEquals($assertion,$formatter->formatNumber($value));
+	}
+
+	public function providerFormatNumber()
+	{
+		return array(
+			// Tests decimals
+			array('1.5',null,null,null,'2'),
+			array('1.5',1,null,null,'1.5'),
+			array('1.55',1,null,null,'1.6'),
+			array('1.44',1,null,null,'1.4'),
+			array('1.01',2,null,null,'1.01'),
+
+			// Test decimal separator
+			array('1.5',null, ',', null,'2'),
+			array('1.5',1,',',null,'1,5'),
+			array('1.55',1,',',null,'1,6'),
+			array('1.44',1,',',null,'1,4'),
+			array('1.01',2,',',null,'1,01'),
+
+			// Test thousands seperator
+			array('1000',null,null,'.','1.000'),
+			array('10000',null,null,'.','10.000'),
+			array('100000',null,null,'.','100.000'),
+			array('1000000',null,null,'.','1.000.000'),
+
+			// Test all at once
+			array('1000.05',2,'D','T','1T000D05'),
+			array('10000.005',2,'D','T','10T000D01'),
+		);
+	}
 }
diff --git a/tests/framework/validators/CFileValidatorTest.php b/tests/framework/validators/CFileValidatorTest.php
index aa84f5ab04..54a43d31f1 100644
--- a/tests/framework/validators/CFileValidatorTest.php
+++ b/tests/framework/validators/CFileValidatorTest.php
@@ -20,8 +20,8 @@ public function providerSizeToBytes()
 			array('1.2G', 1*1024*1024*1024),
 			array('100500', 100500),
 			array('9000', 9000),
-			array(null, null),
-			array('', null),
+			array(null, 0),
+			array('', 0),
 		);
 	}
 
@@ -34,7 +34,7 @@ public function providerSizeToBytes()
 	public function testSizeToBytes($sizeString, $assertion)
 	{
 		$fileValidator=new CFileValidator();
-		$this->assertEquals($assertion, $fileValidator->sizeToBytes($sizeString));
+		$this->assertSame($assertion, $fileValidator->sizeToBytes((string)$sizeString));
 	}
 
 	public function testValidate()
diff --git a/tests/framework/web/helpers/CHtmlTest.php b/tests/framework/web/helpers/CHtmlTest.php
index 228c14e5b1..5b9f455007 100644
--- a/tests/framework/web/helpers/CHtmlTest.php
+++ b/tests/framework/web/helpers/CHtmlTest.php
@@ -178,7 +178,7 @@ public static function providerCloseTag()
 		);
 	}
 
-    /**
+	/**
 	 * @dataProvider providerCloseTag
 	 *
 	 * @param string $tag
@@ -402,11 +402,11 @@ public static function providerScriptWithHtmlOptions()
 				array('async'=>true),
 				"<script type=\"text/javascript\" async=\"async\">\n/*<![CDATA[*/\nvar a = 10;\n/*]]>*/\n</script>"
 			),
-            array(
-                'var a = 10;',
-                array('async'=>false),
-                "<script type=\"text/javascript\" async=\"false\">\n/*<![CDATA[*/\nvar a = 10;\n/*]]>*/\n</script>"
-            ),
+			array(
+				'var a = 10;',
+				array('async'=>false),
+				"<script type=\"text/javascript\" async=\"false\">\n/*<![CDATA[*/\nvar a = 10;\n/*]]>*/\n</script>"
+			),
 		);
 	}
 
@@ -643,6 +643,13 @@ public function providerValue()
 			array(array('v1'),"0",'defaultValue','v1'),
 			array(array('v1'),0,'defaultValue','v1'),
 			array(array('v1'),0.0,'defaultValue','v1'),
+
+			// Test $model as an array, with null as a key, see: https://github.com/yiisoft/yii/pull/4503#discussion_r1054516859
+			array(array(null=>'v1','k2'=>'v2'),null,'defaultValue','v1'),
+			array(array(null=>'v1','k2'=>'v2'),'','defaultValue','v1'),
+			array(array(''=>'v1','k2'=>'v2'),null,'defaultValue','v1'),
+			array(array(''=>'v1','k2'=>'v2'),'','defaultValue','v1'),
+			array(array(null=>'v1','k2'=>'v2'),'k2','defaultValue','v2'),
 		);
 
 		// create_function is not supported by CHtml::value(), we're just testing this feature/property
@@ -671,7 +678,7 @@ public function providerValue()
 	 */
 	public function testValue($model, $attribute, $defaultValue, $assertion)
 	{
-		$this->assertEquals($assertion, CHtml::value($model, $attribute, $defaultValue));
+		$this->assertEquals($assertion, CHtml::value($model, $attribute, (string)$defaultValue));
 	}
 
 	/**
@@ -1128,17 +1135,17 @@ public function testAjaxCallbacks()
 		$out=CHtml::ajax(array(
 			'success'=>'js:function() { /* callback */ }',
 		));
-		$this->assertTrue(mb_strpos($out,"'success':function() { /* callback */ }", null, Yii::app()->charset)!==false, "Unexpected JavaScript: ".$out);
+		$this->assertTrue(mb_strpos($out,"'success':function() { /* callback */ }", 0, Yii::app()->charset)!==false, "Unexpected JavaScript: ".$out);
 
 		$out=CHtml::ajax(array(
 			'success'=>'function() { /* callback */ }',
 		));
-		$this->assertTrue(mb_strpos($out,"'success':function() { /* callback */ }", null, Yii::app()->charset)!==false, "Unexpected JavaScript: ".$out);
+		$this->assertTrue(mb_strpos($out,"'success':function() { /* callback */ }", 0, Yii::app()->charset)!==false, "Unexpected JavaScript: ".$out);
 
 		$out=CHtml::ajax(array(
 			'success'=>new CJavaScriptExpression('function() { /* callback */ }'),
 		));
-		$this->assertTrue(mb_strpos($out,"'success':function() { /* callback */ }", null, Yii::app()->charset)!==false, "Unexpected JavaScript: ".$out);
+		$this->assertTrue(mb_strpos($out,"'success':function() { /* callback */ }", 0, Yii::app()->charset)!==false, "Unexpected JavaScript: ".$out);
 	}
 }
 
@@ -1168,7 +1175,7 @@ class CHtmlTestModel extends CModel
 	 */
 	public $attr4;
 
-    /**
+	/**
 	 * Returns the list of attribute names.
 	 * @return array list of attribute names. Defaults to all public properties of the class.
 	 */
diff --git a/tests/framework/web/widgets/CAutoCompleteTest.php b/tests/framework/web/widgets/CAutoCompleteTest.php
index cb3b566f6b..effabcbbe2 100644
--- a/tests/framework/web/widgets/CAutoCompleteTest.php
+++ b/tests/framework/web/widgets/CAutoCompleteTest.php
@@ -9,13 +9,13 @@ public function testCallbackEncoding()
 		$expected = "'highlight':function() { /* callback */ }";
 
 		$out=$this->getWidgetScript('js:function() { /* callback */ }');
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out);
 
 		$out=$this->getWidgetScript('function() { /* callback */ }');
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out);
 
 		$out=$this->getWidgetScript(new CJavaScriptExpression('function() { /* callback */ }'));
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out);
 	}
 
 	private function getWidgetScript($callback)
@@ -28,6 +28,7 @@ private function getWidgetScript($callback)
 		$widget->data = array(1, 2, 3);
 		$widget->init();
 		$widget->run();
+		$out = '';
 		Yii::app()->clientScript->render($out);
 		ob_end_clean();
 		return $out;
diff --git a/tests/framework/web/widgets/CMaskedTextFieldTest.php b/tests/framework/web/widgets/CMaskedTextFieldTest.php
index 898e102264..dc5d8c9ddd 100644
--- a/tests/framework/web/widgets/CMaskedTextFieldTest.php
+++ b/tests/framework/web/widgets/CMaskedTextFieldTest.php
@@ -9,13 +9,13 @@ public function testCallbackEncoding()
 		$expected = "'completed':function() { /* callback */ }";
 
 		$out=$this->getWidgetScript('js:function() { /* callback */ }');
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out);
 
 		$out=$this->getWidgetScript('function() { /* callback */ }');
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out);
 
 		$out=$this->getWidgetScript(new CJavaScriptExpression('function() { /* callback */ }'));
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out);
 	}
 
 	private function getWidgetScript($callback)
@@ -28,6 +28,7 @@ private function getWidgetScript($callback)
 		$widget->mask = '99/99/9999';
 		$widget->init();
 		$widget->run();
+		$out = '';
 		Yii::app()->clientScript->render($out);
 		ob_end_clean();
 		return $out;
diff --git a/tests/framework/web/widgets/CMultiFileUploadTest.php b/tests/framework/web/widgets/CMultiFileUploadTest.php
index c5217593ef..3ce50c8d4e 100644
--- a/tests/framework/web/widgets/CMultiFileUploadTest.php
+++ b/tests/framework/web/widgets/CMultiFileUploadTest.php
@@ -9,13 +9,13 @@ public function testCallbackEncoding()
 		$expected = "'onFileSelect':function() { /* callback */ }";
 
 		$out=$this->getWidgetScript('js:function() { /* callback */ }');
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out);
 
 		$out=$this->getWidgetScript('function() { /* callback */ }');
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out);
 
 		$out=$this->getWidgetScript(new CJavaScriptExpression('function() { /* callback */ }'));
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out);
 	}
 
 	private function getWidgetScript($callback)
@@ -27,6 +27,7 @@ private function getWidgetScript($callback)
 		$widget->options['onFileSelect'] = $callback;
 		$widget->init();
 		$widget->run();
+		$out = '';
 		Yii::app()->clientScript->render($out);
 		ob_end_clean();
 		return $out;
diff --git a/tests/framework/web/widgets/CStarRatingTest.php b/tests/framework/web/widgets/CStarRatingTest.php
index 91e94da71c..bc181b464d 100644
--- a/tests/framework/web/widgets/CStarRatingTest.php
+++ b/tests/framework/web/widgets/CStarRatingTest.php
@@ -9,13 +9,13 @@ public function testCallbackEncoding()
 		$expected = "'callback':function() { /* callback */ }";
 
 		$out=$this->getWidgetScript('js:function() { /* callback */ }');
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out);
 
 		$out=$this->getWidgetScript('function() { /* callback */ }');
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out);
 
 		$out=$this->getWidgetScript(new CJavaScriptExpression('function() { /* callback */ }'));
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out);
 	}
 
 	private function getWidgetScript($callback)
@@ -27,6 +27,7 @@ private function getWidgetScript($callback)
 		$widget->callback = $callback;
 		$widget->init();
 		$widget->run();
+		$out = '';
 		Yii::app()->clientScript->render($out);
 		ob_end_clean();
 		return $out;
diff --git a/tests/framework/zii/widgets/CGridViewTest.php b/tests/framework/zii/widgets/CGridViewTest.php
index abcc4923f1..2dc057b184 100644
--- a/tests/framework/zii/widgets/CGridViewTest.php
+++ b/tests/framework/zii/widgets/CGridViewTest.php
@@ -14,7 +14,7 @@ public function testCallbackEncoding()
 			'js:function() { /* callback3 */ }',
 			'js:function() { /* callback4 */ }'
 		);
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out);
 
 		$out=$this->getWidgetScript(
 			'function() { /* callback1 */ }',
@@ -22,7 +22,7 @@ public function testCallbackEncoding()
 			'function() { /* callback3 */ }',
 			'function() { /* callback4 */ }'
 		);
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out);
 
 		$out=$this->getWidgetScript(
 			new CJavaScriptExpression('function() { /* callback1 */ }'),
@@ -30,7 +30,7 @@ public function testCallbackEncoding()
 			new CJavaScriptExpression('function() { /* callback3 */ }'),
 			new CJavaScriptExpression('function() { /* callback4 */ }')
 		);
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out);
 	}
 
 	private function getWidgetScript($callback1, $callback2, $callback3, $callback4)
@@ -46,8 +46,9 @@ private function getWidgetScript($callback1, $callback2, $callback3, $callback4)
 		$widget->dataProvider = new CArrayDataProvider(array(1, 2, 3));
 		$widget->init();
 		$widget->registerClientScript();
+		$out = '';
 		Yii::app()->clientScript->render($out);
 		ob_end_clean();
 		return $out;
 	}
-}
\ No newline at end of file
+}
diff --git a/tests/framework/zii/widgets/CListViewTest.php b/tests/framework/zii/widgets/CListViewTest.php
index 9ceddd5956..1b2b4b65fe 100644
--- a/tests/framework/zii/widgets/CListViewTest.php
+++ b/tests/framework/zii/widgets/CListViewTest.php
@@ -9,13 +9,13 @@ public function testCallbackEncoding()
 		$expected = "'beforeAjaxUpdate':function() { /* callback1 */ },'afterAjaxUpdate':function() { /* callback2 */ }";
 
 		$out=$this->getWidgetScript('js:function() { /* callback1 */ }', 'js:function() { /* callback2 */ }');
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out);
 
 		$out=$this->getWidgetScript('function() { /* callback1 */ }', 'function() { /* callback2 */ }');
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out);
 
 		$out=$this->getWidgetScript(new CJavaScriptExpression('function() { /* callback1 */ }'), new CJavaScriptExpression('function() { /* callback2 */ }'));
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out);
 	}
 
 	private function getWidgetScript($callback1, $callback2)
@@ -30,8 +30,9 @@ private function getWidgetScript($callback1, $callback2)
 		$widget->dataProvider = new CArrayDataProvider(array(1, 2, 3));
 		$widget->init();
 		$widget->registerClientScript();
+		$out = '';
 		Yii::app()->clientScript->render($out);
 		ob_end_clean();
 		return $out;
 	}
-}
\ No newline at end of file
+}
diff --git a/tests/framework/zii/widgets/grid/CButtonColumnTest.php b/tests/framework/zii/widgets/grid/CButtonColumnTest.php
index 218b059876..7ec7c913dc 100644
--- a/tests/framework/zii/widgets/grid/CButtonColumnTest.php
+++ b/tests/framework/zii/widgets/grid/CButtonColumnTest.php
@@ -9,13 +9,13 @@ public function testCallbackEncoding()
 		$expected = "jQuery(document).on('click','#grid1 a.view',function() { /* callback */ });";
 
 		$out=$this->getWidgetScript('js:function() { /* callback */ }');
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out);
 
 		$out=$this->getWidgetScript('function() { /* callback */ }');
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out);
 
 		$out=$this->getWidgetScript(new CJavaScriptExpression('function() { /* callback */ }'));
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out);
 	}
 
 	private function getWidgetScript($callback)
@@ -32,6 +32,7 @@ private function getWidgetScript($callback)
 			),
 		);
 		$widget->init();
+		$out = '';
 		Yii::app()->clientScript->render($out);
 		ob_end_clean();
 		return $out;
diff --git a/tests/framework/zii/widgets/jui/CJuiButtonTest.php b/tests/framework/zii/widgets/jui/CJuiButtonTest.php
index 0b7e4aa1d0..73450db9c4 100644
--- a/tests/framework/zii/widgets/jui/CJuiButtonTest.php
+++ b/tests/framework/zii/widgets/jui/CJuiButtonTest.php
@@ -9,13 +9,13 @@ public function testCallbackEncoding()
 		$expected = ".click(function() { /* callback */ });";
 
 		$out=$this->getWidgetScript('js:function() { /* callback */ }');
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out);
 
 		$out=$this->getWidgetScript('function() { /* callback */ }');
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out);
 
 		$out=$this->getWidgetScript(new CJavaScriptExpression('function() { /* callback */ }'));
-		$this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out);
+		$this->assertTrue(mb_strpos($out,$expected, 0, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out);
 	}
 
 	private function getWidgetScript($callback)
@@ -28,6 +28,7 @@ private function getWidgetScript($callback)
 		$widget->onclick = $callback;
 		$widget->init();
 		$widget->run();
+		$out = '';
 		Yii::app()->clientScript->render($out);
 		ob_end_clean();
 		return $out;