]> granicus.if.org Git - php/commitdiff
- Make class_parentS() and class_implements() accepts class names as well
authorMarcus Boerger <helly@php.net>
Wed, 6 Apr 2005 15:16:45 +0000 (15:16 +0000)
committerMarcus Boerger <helly@php.net>
Wed, 6 Apr 2005 15:16:45 +0000 (15:16 +0000)
ext/spl/php_spl.c
ext/spl/tests/spl_003.phpt [new file with mode: 0755]

index 3da6593f328ceff9f72a31b67066f4ea82848159..ae60b246f01321c508b7a53d52c9c8b51142a330 100755 (executable)
@@ -59,18 +59,56 @@ static void spl_init_globals(zend_spl_globals *spl_globals)
 }
 /* }}} */
 
+static zend_class_entry * spl_find_ce_by_name(char *name, int len, zend_bool autoload TSRMLS_DC)
+{
+       zend_class_entry **ce;
+       int found;
+       if (!autoload) {
+               char *lc_name;
+
+               lc_name = do_alloca(len + 1);
+               zend_str_tolower_copy(lc_name, name, len);
+
+               found = zend_hash_find(EG(class_table), lc_name, len +1, (void **) &ce);
+               free_alloca(lc_name);
+       } else {
+               found = zend_lookup_class(name, len, &ce TSRMLS_CC);
+       }
+       if (found != SUCCESS) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Class %s does not exist%s", name, autoload ? " and could not be loaded" : "");
+               return NULL;
+       }
+       
+       return *ce;
+}
+
 /* {{{ array class_parents(object instance)
  Return an array containing the names of all parent classes */
 PHP_FUNCTION(class_parents)
 {
        zval *obj;
-       zend_class_entry *parent_class;
+       zend_class_entry *parent_class, *ce;
+       zend_bool autoload = 1;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &obj, &autoload) == FAILURE) {
+               RETURN_FALSE;
+       }
+       
+       if (Z_TYPE_P(obj) != IS_OBJECT && Z_TYPE_P(obj) != IS_STRING) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "object or string expected");
                RETURN_FALSE;
        }
+       
+       if (Z_TYPE_P(obj) == IS_STRING) {
+               if (NULL == (ce = spl_find_ce_by_name(Z_STRVAL_P(obj), Z_STRLEN_P(obj), autoload TSRMLS_CC))) {
+                       RETURN_FALSE;
+               }
+       } else {
+               ce = Z_OBJCE_P(obj);
+       }
+       
        array_init(return_value);
-       parent_class = Z_OBJCE_P(obj)->parent;
+       parent_class = ce->parent;
        while (parent_class) {
                spl_add_class_name(return_value, parent_class, 0, 0 TSRMLS_CC);
                parent_class = parent_class->parent;
@@ -78,17 +116,32 @@ PHP_FUNCTION(class_parents)
 }
 /* }}} */
 
-/* {{{ proto array class_implements()
+/* {{{ proto array class_implements(mixed what [, bool autoload ])
  Return all classes and interfaces implemented by SPL */
 PHP_FUNCTION(class_implements)
 {
        zval *obj;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
+       zend_bool autoload = 1;
+       zend_class_entry *ce;
+       
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &obj, &autoload) == FAILURE) {
                RETURN_FALSE;
        }
+       if (Z_TYPE_P(obj) != IS_OBJECT && Z_TYPE_P(obj) != IS_STRING) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "object or string expected");
+               RETURN_FALSE;
+       }
+       
+       if (Z_TYPE_P(obj) == IS_STRING) {
+               if (NULL == (ce = spl_find_ce_by_name(Z_STRVAL_P(obj), Z_STRLEN_P(obj), autoload TSRMLS_CC))) {
+                       RETURN_FALSE;
+               }
+       } else {
+               ce = Z_OBJCE_P(obj);
+       }
+       
        array_init(return_value);
-       spl_add_interfaces(return_value, Z_OBJCE_P(obj), 1, ZEND_ACC_INTERFACE TSRMLS_CC);
+       spl_add_interfaces(return_value, ce, 1, ZEND_ACC_INTERFACE TSRMLS_CC);
 }
 /* }}} */
 
diff --git a/ext/spl/tests/spl_003.phpt b/ext/spl/tests/spl_003.phpt
new file mode 100755 (executable)
index 0000000..cadf3b5
--- /dev/null
@@ -0,0 +1,76 @@
+--TEST--
+SPL: class_parents() and class_implements()
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+class a{}
+class b extends a{}
+class c extends b{}
+class d{}
+var_dump(class_parents(new c),
+         class_parents("c"),
+         class_parents(new b),
+         class_parents("b"),
+         class_parents("d"),
+         class_parents("foo", 0),
+         class_parents("foo", 1)
+);
+
+interface iface1{}
+interface iface2{}
+class f implements iface1, iface2{}
+var_dump(class_implements(new a),
+         class_implements("a"),
+         class_implements("aaa"),
+         class_implements("bbb", 0)
+);
+
+function __autoload($cname) {
+    var_dump($cname);
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Warning: class_parents(): Class foo does not exist in %sspl_003.php on line %d
+string(3) "foo"
+
+Warning: class_parents(): Class foo does not exist and could not be loaded in %sspl_003.php on line %d
+array(2) {
+  ["b"]=>
+  string(1) "b"
+  ["a"]=>
+  string(1) "a"
+}
+array(2) {
+  ["b"]=>
+  string(1) "b"
+  ["a"]=>
+  string(1) "a"
+}
+array(1) {
+  ["a"]=>
+  string(1) "a"
+}
+array(1) {
+  ["a"]=>
+  string(1) "a"
+}
+array(0) {
+}
+bool(false)
+bool(false)
+string(3) "aaa"
+
+Warning: class_implements(): Class aaa does not exist and could not be loaded in %sspl_003.php on line %d
+
+Warning: class_implements(): Class bbb does not exist in %sspl_003.php on line %d
+array(0) {
+}
+array(0) {
+}
+bool(false)
+bool(false)
+===DONE===
\ No newline at end of file