Fixes #4573: mb_strtolower(null, ...) deprecation when caseSensitiveSort is false

This commit is contained in:
erwin
2025-12-03 13:19:49 +01:00
parent 5ff1fe2948
commit 077af097c2
2 changed files with 89 additions and 15 deletions

View File

@@ -20,7 +20,7 @@
* or associative arrays (e.g. query results of DAO). * or associative arrays (e.g. query results of DAO).
* Make sure to set the {@link keyField} property to the name of the field that uniquely * Make sure to set the {@link keyField} property to the name of the field that uniquely
* identifies a data record or false if you do not have such a field. * identifies a data record or false if you do not have such a field.
* *
* CArrayDataProvider may be used in the following way: * CArrayDataProvider may be used in the following way:
* <pre> * <pre>
* $rawData=Yii::app()->db->createCommand('SELECT * FROM tbl_user')->queryAll(); * $rawData=Yii::app()->db->createCommand('SELECT * FROM tbl_user')->queryAll();
@@ -164,20 +164,26 @@ class CArrayDataProvider extends CDataProvider
* @param array $fields sorting fields in $data * @param array $fields sorting fields in $data
* @return mixed $data sorting field value * @return mixed $data sorting field value
*/ */
protected function getSortingFieldValue($data, $fields) protected function getSortingFieldValue($data, $fields)
{ {
if(is_object($data)) if(is_object($data))
{ {
foreach($fields as $field) foreach($fields as $field)
$data=isset($data->$field) ? $data->$field : null; $data = isset($data->$field) ? $data->$field : null;
} }
else else
{ {
foreach($fields as $field) foreach($fields as $field)
$data=isset($data[$field]) ? $data[$field] : null; $data = isset($data[$field]) ? $data[$field] : null;
} }
return $this->caseSensitiveSort ? $data : mb_strtolower($data,Yii::app()->charset);
} // PHP 8.1+: avoid mb_strtolower(null, ...) deprecation when sort key is missing
if ($this->caseSensitiveSort || $data === null) {
return $data;
}
return mb_strtolower((string)$data, Yii::app()->charset);
}
/** /**
* Converts the "ORDER BY" clause into an array representing the sorting directions. * Converts the "ORDER BY" clause into an array representing the sorting directions.

View File

@@ -235,4 +235,72 @@ class CArrayDataProviderTest extends CTestCase
$sortedArray = array($obj2, $obj3, $obj1); $sortedArray = array($obj2, $obj3, $obj1);
$this->assertEquals($sortedArray, $dataProvider->getData()); $this->assertEquals($sortedArray, $dataProvider->getData());
} }
public function testCaseInsensitiveSortWithNullValue()
{
// This deprecation occurs only on PHP 8.1+
if (version_compare(PHP_VERSION, '8.1', '<')) {
$this->markTestSkipped('mb_strtolower(null, ...) deprecation only occurs on PHP 8.1+');
}
$previousErrorReporting = error_reporting(E_ALL);
$previousHandler = set_error_handler(function ($errno, $errstr) {
if (($errno & (E_DEPRECATED | E_USER_DEPRECATED)) !== 0
&& strpos($errstr, 'mb_strtolower') !== false
) {
throw new ErrorException($errstr, 0, $errno);
}
return false;
});
try {
$data = array(
array('id' => 1, 'name' => 'Alpha'),
array('id' => 2, 'name' => null),
array('id' => 3, 'name' => 'beta'),
);
$dataProvider = new CArrayDataProvider($data, array(
'keyField' => 'id',
'sort' => array(
'attributes' => array(
'name' => array(
'asc' => 'name ASC',
'desc' => 'name DESC',
'label' => 'Name',
'default' => 'asc',
),
),
'defaultOrder' => array(
'name' => CSort::SORT_ASC,
),
),
));
$dataProvider->caseSensitiveSort = false;
// Before the fix this call triggered a deprecation in PHP 8.1+ via mb_strtolower(null, ...)
$items = $dataProvider->getData();
$this->assertCount(3, $items);
$ids = array();
foreach ($items as $item) {
$ids[] = $item['id'];
}
$this->assertContains(2, $ids);
foreach ($items as $item) {
if ($item['id'] === 2) {
$this->assertArrayHasKey('name', $item);
$this->assertNull($item['name']);
}
}
} finally {
set_error_handler($previousHandler);
error_reporting($previousErrorReporting);
}
}
} }