]> granicus.if.org Git - php/commitdiff
Add a prepend param to spl_autoload_register
authorEtienne Kneuss <colder@php.net>
Sun, 25 May 2008 12:17:27 +0000 (12:17 +0000)
committerEtienne Kneuss <colder@php.net>
Sun, 25 May 2008 12:17:27 +0000 (12:17 +0000)
ext/spl/php_spl.c
ext/spl/tests/spl_autoload_010.phpt [new file with mode: 0644]
ext/spl/tests/spl_autoload_011.phpt [new file with mode: 0644]

index 8212f5f84fda13c997581ea01efe60b31fd16db0..485c0ba2b56f038eef342f67faeccfad7a44aef9 100755 (executable)
@@ -393,7 +393,14 @@ PHP_FUNCTION(spl_autoload_call)
        zval_ptr_dtor(&zclass_name);
 } /* }}} */
 
-/* {{{ proto bool spl_autoload_register([mixed autoload_function = "spl_autoload" [, throw = true]]) U
+#define HT_MOVE_TAIL_TO_HEAD(ht)                                               \
+       (ht)->pListTail->pListNext = (ht)->pListHead;                   \
+       (ht)->pListHead = (ht)->pListTail;                                              \
+       (ht)->pListTail = (ht)->pListHead->pListLast;                   \
+       (ht)->pListTail->pListNext = NULL;                                      \
+       (ht)->pListHead->pListLast = NULL;
+
+/* {{{ proto bool spl_autoload_register([mixed autoload_function = "spl_autoload" [, throw = true [, prepend = false]]]) U
  Register given function as __autoload() implementation */
 PHP_FUNCTION(spl_autoload_register)
 {
@@ -401,11 +408,12 @@ PHP_FUNCTION(spl_autoload_register)
        zval zfunc_name, ztmp;
        zval *zcallable = NULL;
        zend_bool do_throw = 1;
+       zend_bool prepend = 0;
        zend_function *spl_func_ptr;
        autoload_func_info alfi;
        zval **obj_ptr;
 
-       if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "|zb", &zcallable, &do_throw) == FAILURE) {
+       if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "|zbb", &zcallable, &do_throw, &prepend) == FAILURE) {
                return;
        }
 
@@ -517,9 +525,17 @@ PHP_FUNCTION(spl_autoload_register)
                        spl_alfi.obj = NULL;
                        spl_alfi.ce = NULL;
                        zend_hash_add(SPL_G(autoload_functions), "spl_autoload", sizeof("spl_autoload"), &spl_alfi, sizeof(autoload_func_info), NULL);
+                       if (prepend && SPL_G(autoload_functions)->nNumOfElements > 1) {
+                               /* Move the newly created element to the head of the hashtable */
+                               HT_MOVE_TAIL_TO_HEAD(SPL_G(autoload_functions));
+                       }
                }
 
                zend_u_hash_add(SPL_G(autoload_functions), Z_TYPE(zfunc_name), Z_UNIVAL(zfunc_name), Z_UNILEN(zfunc_name)+1, &alfi, sizeof(autoload_func_info), NULL);
+               if (prepend && SPL_G(autoload_functions)->nNumOfElements > 1) {
+                       /* Move the newly created element to the head of the hashtable */
+                       HT_MOVE_TAIL_TO_HEAD(SPL_G(autoload_functions));
+               }
 skip:
                zval_dtor(&zfunc_name);
        }
diff --git a/ext/spl/tests/spl_autoload_010.phpt b/ext/spl/tests/spl_autoload_010.phpt
new file mode 100644 (file)
index 0000000..cd70bdc
--- /dev/null
@@ -0,0 +1,30 @@
+--TEST--
+SPL: spl_autoload() and prepend
+--INI--
+include_path=.
+--FILE--
+<?php
+function autoloadA($name) {
+    echo "A -> $name\n";
+}
+function autoloadB($name) {
+    echo "B -> $name\n";
+}
+function autoloadC($name) {
+    echo "C -> $name\n";
+    class C{}
+}
+
+spl_autoload_register('autoloadA');
+spl_autoload_register('autoloadB', true, true);
+spl_autoload_register('autoloadC');
+
+new C;
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+B -> C
+A -> C
+C -> C
+===DONE===
diff --git a/ext/spl/tests/spl_autoload_011.phpt b/ext/spl/tests/spl_autoload_011.phpt
new file mode 100644 (file)
index 0000000..5a99255
--- /dev/null
@@ -0,0 +1,31 @@
+--TEST--
+SPL: spl_autoload() and object freed
+--INI--
+include_path=.
+--FILE--
+<?php
+class A {
+    public $var = 1;
+    public function autoload() {
+        echo "var:".$this->var."\n";
+    }
+    public function __destruct() {
+        echo "__destruct__\n";
+    }
+}
+
+$a = new A;
+$a->var = 2;
+
+spl_autoload_register(array($a, 'autoload'));
+unset($a);
+
+var_dump(class_exists("C", true));
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+var:2
+bool(false)
+===DONE===
+__destruct__