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).
* 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.
*
*
* CArrayDataProvider may be used in the following way:
* <pre>
* $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
* @return mixed $data sorting field value
*/
protected function getSortingFieldValue($data, $fields)
{
if(is_object($data))
{
foreach($fields as $field)
$data=isset($data->$field) ? $data->$field : null;
}
else
{
foreach($fields as $field)
$data=isset($data[$field]) ? $data[$field] : null;
}
return $this->caseSensitiveSort ? $data : mb_strtolower($data,Yii::app()->charset);
}
protected function getSortingFieldValue($data, $fields)
{
if(is_object($data))
{
foreach($fields as $field)
$data = isset($data->$field) ? $data->$field : null;
}
else
{
foreach($fields as $field)
$data = isset($data[$field]) ? $data[$field] : null;
}
// 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.

View File

@@ -235,4 +235,72 @@ class CArrayDataProviderTest extends CTestCase
$sortedArray = array($obj2, $obj3, $obj1);
$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);
}
}
}