From: Xinchen Hui <laruence@php.net>
Date: Tue, 21 Aug 2012 05:32:15 +0000 (+0800)
Subject: Implemented FR #62840 (Add sort flag to ArrayObject::ksort)
X-Git-Tag: php-5.4.7RC1~36^2~1
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8722173ad5d3132bfefbeb753c29e246876b0492;p=php

Implemented FR #62840 (Add sort flag to ArrayObject::ksort)
---

diff --git a/NEWS b/NEWS
index 27a34c3c68..d60f51b530 100644
--- a/NEWS
+++ b/NEWS
@@ -38,6 +38,9 @@ PHP                                                                        NEWS
   . Fixed bug (segfault due to PS(mod_user_implemented) not be reseted 
     when close handler call exit). (Laruence)
 
+- SPL:
+  . Implemented FR #62840 (Add sort flag to ArrayObject::ksort). (Laruence)
+
 - Standard:
   . Fixed bug #62836 (Seg fault or broken object references on unserialize()).
     (Laruence)
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c
index e2ea17a3fe..1e4577a3f9 100755
--- a/ext/spl/spl_array.c
+++ b/ext/spl/spl_array.c
@@ -58,6 +58,10 @@ PHPAPI zend_class_entry  *spl_ce_RecursiveArrayIterator;
 #define SPL_ARRAY_INT_MASK           0xFFFF0000
 #define SPL_ARRAY_CLONE_MASK         0x0300FFFF
 
+#define SPL_ARRAY_METHOD_NO_ARG				0
+#define SPL_ARRAY_METHOD_USE_ARG    		1
+#define SPL_ARRAY_METHOD_MAY_USER_ARG 		2
+
 typedef struct _spl_array_object {
 	zend_object       std;
 	zval              *array;
@@ -1426,26 +1430,36 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam
 {
 	spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 	HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
-	zval *tmp, *arg;
+	zval *tmp, *arg = NULL;
 	zval *retval_ptr = NULL;
 	
 	MAKE_STD_ZVAL(tmp);
 	Z_TYPE_P(tmp) = IS_ARRAY;
 	Z_ARRVAL_P(tmp) = aht;
 	
-	if (use_arg) {
-		if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) {
+	if (!use_arg) {
+		aht->nApplyCount++;
+		zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 1, tmp, NULL TSRMLS_CC);
+		aht->nApplyCount--;
+	} else if (use_arg == SPL_ARRAY_METHOD_MAY_USER_ARG) {
+		if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "|z", &arg) == FAILURE) {
 			Z_TYPE_P(tmp) = IS_NULL;
 			zval_ptr_dtor(&tmp);
-			zend_throw_exception(spl_ce_BadMethodCallException, "Function expects exactly one argument", 0 TSRMLS_CC);
+			zend_throw_exception(spl_ce_BadMethodCallException, "Function expects one argument at most", 0 TSRMLS_CC);
 			return;
 		}
 		aht->nApplyCount++;
-		zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 2, tmp, arg TSRMLS_CC);
+		zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, arg? 2 : 1, tmp, arg TSRMLS_CC);
 		aht->nApplyCount--;
 	} else {
+		if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) {
+			Z_TYPE_P(tmp) = IS_NULL;
+			zval_ptr_dtor(&tmp);
+			zend_throw_exception(spl_ce_BadMethodCallException, "Function expects exactly one argument", 0 TSRMLS_CC);
+			return;
+		}
 		aht->nApplyCount++;
-		zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 1, tmp, NULL TSRMLS_CC);
+		zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 2, tmp, arg TSRMLS_CC);
 		aht->nApplyCount--;
 	}
 	Z_TYPE_P(tmp) = IS_NULL; /* we want to destroy the zval, not the hashtable */
@@ -1461,35 +1475,35 @@ SPL_METHOD(cname, fname) \
 	spl_array_method(INTERNAL_FUNCTION_PARAM_PASSTHRU, #fname, sizeof(#fname)-1, use_arg); \
 }
 
-/* {{{ proto int ArrayObject::asort()
-       proto int ArrayIterator::asort()
+/* {{{ proto int ArrayObject::asort([int $sort_flags = SORT_REGULAR ])
+       proto int ArrayIterator::asort([int $sort_flags = SORT_REGULAR ])
    Sort the entries by values. */
-SPL_ARRAY_METHOD(Array, asort, 0) /* }}} */
+SPL_ARRAY_METHOD(Array, asort, SPL_ARRAY_METHOD_MAY_USER_ARG) /* }}} */
 
-/* {{{ proto int ArrayObject::ksort()
-       proto int ArrayIterator::ksort()
+/* {{{ proto int ArrayObject::ksort([int $sort_flags = SORT_REGULAR ])
+       proto int ArrayIterator::ksort([int $sort_flags = SORT_REGULAR ])
    Sort the entries by key. */
-SPL_ARRAY_METHOD(Array, ksort, 0) /* }}} */
+SPL_ARRAY_METHOD(Array, ksort, SPL_ARRAY_METHOD_MAY_USER_ARG) /* }}} */
 
 /* {{{ proto int ArrayObject::uasort(callback cmp_function)
        proto int ArrayIterator::uasort(callback cmp_function)
    Sort the entries by values user defined function. */
-SPL_ARRAY_METHOD(Array, uasort, 1) /* }}} */
+SPL_ARRAY_METHOD(Array, uasort, SPL_ARRAY_METHOD_USE_ARG) /* }}} */
 
 /* {{{ proto int ArrayObject::uksort(callback cmp_function)
        proto int ArrayIterator::uksort(callback cmp_function)
    Sort the entries by key using user defined function. */
-SPL_ARRAY_METHOD(Array, uksort, 1) /* }}} */
+SPL_ARRAY_METHOD(Array, uksort, SPL_ARRAY_METHOD_USE_ARG) /* }}} */
 
 /* {{{ proto int ArrayObject::natsort()
        proto int ArrayIterator::natsort()
    Sort the entries by values using "natural order" algorithm. */
-SPL_ARRAY_METHOD(Array, natsort, 0) /* }}} */
+SPL_ARRAY_METHOD(Array, natsort, SPL_ARRAY_METHOD_NO_ARG) /* }}} */
 
 /* {{{ proto int ArrayObject::natcasesort()
        proto int ArrayIterator::natcasesort()
    Sort the entries by key using case insensitive "natural order" algorithm. */
-SPL_ARRAY_METHOD(Array, natcasesort, 0) /* }}} */
+SPL_ARRAY_METHOD(Array, natcasesort, SPL_ARRAY_METHOD_NO_ARG) /* }}} */
 
 /* {{{ proto mixed|NULL ArrayIterator::current()
    Return current array entry */
diff --git a/ext/spl/tests/arrayObject_asort_basic1.phpt b/ext/spl/tests/arrayObject_asort_basic1.phpt
index ec69049a32..53df1d502b 100644
--- a/ext/spl/tests/arrayObject_asort_basic1.phpt
+++ b/ext/spl/tests/arrayObject_asort_basic1.phpt
@@ -17,12 +17,14 @@ var_dump($ao1->asort());
 var_dump($ao1);
 var_dump($ao2->asort('blah'));
 var_dump($ao2);
+var_dump($ao2->asort(SORT_NUMERIC));
+var_dump($ao2);
 ?>
 ===DONE===
 --EXPECTF--
 *** Testing ArrayObject::asort() : basic functionality ***
 bool(true)
-object(ArrayObject)#1 (1) {
+object(ArrayObject)#%d (1) {
   ["storage":"ArrayObject":private]=>
   array(3) {
     [1]=>
@@ -33,8 +35,22 @@ object(ArrayObject)#1 (1) {
     int(4)
   }
 }
+
+Warning: asort() expects parameter 2 to be long, string given in %sarrayObject_asort_basic1.php on line %d
+bool(false)
+object(ArrayObject)#%d (1) {
+  ["storage":"ArrayObject":private]=>
+  array(3) {
+    ["a"]=>
+    int(4)
+    ["b"]=>
+    int(2)
+    ["c"]=>
+    int(3)
+  }
+}
 bool(true)
-object(ArrayObject)#2 (1) {
+object(ArrayObject)#%d (1) {
   ["storage":"ArrayObject":private]=>
   array(3) {
     ["b"]=>
diff --git a/ext/spl/tests/arrayObject_ksort_basic1.phpt b/ext/spl/tests/arrayObject_ksort_basic1.phpt
index 9c8d1e7345..8f37938126 100644
--- a/ext/spl/tests/arrayObject_ksort_basic1.phpt
+++ b/ext/spl/tests/arrayObject_ksort_basic1.phpt
@@ -16,12 +16,14 @@ var_dump($ao1->ksort());
 var_dump($ao1);
 var_dump($ao2->ksort('blah'));
 var_dump($ao2);
+var_dump($ao2->ksort(SORT_STRING));
+var_dump($ao2);
 ?>
 ===DONE===
 --EXPECTF--
 *** Testing ArrayObject::ksort() : basic functionality ***
 bool(true)
-object(ArrayObject)#1 (1) {
+object(ArrayObject)#%d (1) {
   ["storage":"ArrayObject":private]=>
   array(3) {
     [0]=>
@@ -32,18 +34,34 @@ object(ArrayObject)#1 (1) {
     int(3)
   }
 }
-bool(true)
+
+Warning: ksort() expects parameter 2 to be long, string given in %sarrayObject_ksort_basic1.php on line %d
+bool(false)
 object(ArrayObject)#2 (1) {
   ["storage":"ArrayObject":private]=>
   array(4) {
-    ["a"]=>
-    int(2)
     ["b"]=>
     int(4)
+    ["a"]=>
+    int(2)
     ["q"]=>
     int(3)
     [99]=>
     string(1) "x"
   }
 }
+bool(true)
+object(ArrayObject)#%d (1) {
+  ["storage":"ArrayObject":private]=>
+  array(4) {
+    [99]=>
+    string(1) "x"
+    ["a"]=>
+    int(2)
+    ["b"]=>
+    int(4)
+    ["q"]=>
+    int(3)
+  }
+}
 ===DONE===