Browse Source

fix bug #55475 - implement is_a BC solution

pull/7/head
Stanislav Malyshev 15 years ago
parent
commit
10f20585fc
  1. 19
      Zend/zend_builtin_functions.c
  2. 378
      ext/standard/tests/class_object/is_a.phpt
  3. 24
      ext/standard/tests/class_object/is_a_error_001.phpt
  4. 24
      ext/standard/tests/class_object/is_subclass_of_error_001.phpt

19
Zend/zend_builtin_functions.c

@ -839,13 +839,20 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass)
int class_name_len;
zend_class_entry *instance_ce;
zend_class_entry **ce;
zend_bool allow_string = only_subclass;
zend_bool retval;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &obj, &class_name, &class_name_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs|b", &obj, &class_name, &class_name_len, &allow_string) == FAILURE) {
return;
}
if (Z_TYPE_P(obj) == IS_STRING) {
/*
* allow_string - is_a default is no, is_subclass_of is yes.
* if it's allowed, then the autoloader will be called if the class does not exist.
* default behaviour is different, as 'is_a' used to be used to test mixed return values
* and there is no easy way to deprecate this.
*/
if (allow_string && Z_TYPE_P(obj) == IS_STRING) {
zend_class_entry **the_ce;
if (zend_lookup_class(Z_STRVAL_P(obj), Z_STRLEN_P(obj), &the_ce TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
@ -871,7 +878,7 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass)
}
/* {{{ proto bool is_subclass_of(mixed object, string class_name)
/* {{{ proto bool is_subclass_of(mixed object_or_string, string class_name [, bool allow_string=true])
Returns true if the object has this class as one of its parents */
ZEND_FUNCTION(is_subclass_of)
{
@ -880,8 +887,8 @@ ZEND_FUNCTION(is_subclass_of)
/* }}} */
/* {{{ proto bool is_a(mixed object, string class_name)
Returns true if the object is of this class or has this class as one of its parents */
/* {{{ proto bool is_a(mixed object_or_string, string class_name [, bool allow_string=false])
Returns true if the first argument is an object and is this class or has this class as one of its parents, */
ZEND_FUNCTION(is_a)
{
is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);

378
ext/standard/tests/class_object/is_a.phpt

@ -0,0 +1,378 @@
--TEST--
is_a and is_subclass_of behaviour (with and without autoload)
--SKIPIF--
<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?>
--FILE--
<?php
interface if_a {
function f_a();
}
interface if_b extends if_a {
function f_b();
}
class base {
function _is_a($sub) {
echo "\n>>> With Defined class\n";
echo str_pad('is_a( OBJECT:'.get_class($this).', '.$sub.') = ', 60) . (is_a($this, $sub) ? 'yes' : 'no')."\n";
echo str_pad('is_a( STRING:'.get_class($this).', '.$sub.') = ', 60). (is_a(get_class($this), $sub) ? 'yes' : 'no')."\n";
echo str_pad('is_a( STRING:'.get_class($this).', '.$sub.', true) = ', 60). (is_a(get_class($this), $sub, true) ? 'yes' : 'no')."\n";
echo str_pad('is_subclass_of( OBJECT:'.get_class($this).', '.$sub.') = ', 60). (is_subclass_of($this, $sub) ? 'yes' : 'no')."\n";
echo str_pad('is_subclass_of( STRING:'.get_class($this).', '.$sub.') = ', 60). (is_subclass_of(get_class($this), $sub) ? 'yes' : 'no')."\n";
echo str_pad('is_subclass_of( STRING:'.get_class($this).', '.$sub.',false) = ', 60). (is_subclass_of(get_class($this), $sub , false) ? 'yes' : 'no')."\n";
// with autoload options..
echo ">>> With Undefined\n";
echo str_pad('is_a( STRING:undefB, '.$sub.',true) = ', 60). (is_a('undefB', $sub, true) ? 'yes' : 'no')."\n";
echo str_pad('is_a( STRING:undefB, '.$sub.') = ', 60). (is_a('undefB', $sub) ? 'yes' : 'no')."\n";
echo str_pad('is_subclass_of( STRING:undefB, '.$sub.',false) = ', 60). (is_subclass_of('undefB', $sub, false) ? 'yes' : 'no')."\n";
echo str_pad('is_subclass_of( STRING:undefB, '.$sub.') = ', 60). (is_subclass_of('undefB', $sub) ? 'yes' : 'no')."\n";
}
function test() {
echo $this->_is_a('base');
echo $this->_is_a('derived_a');
echo $this->_is_a('if_a');
echo $this->_is_a('undefA');
echo "\n";
}
}
class derived_a extends base implements if_a {
function f_a() {}
}
class derived_b extends base implements if_a, if_b {
function f_a() {}
function f_b() {}
}
class derived_c extends derived_a implements if_b {
function f_b() {}
}
class derived_d extends derived_c {
}
$t = new base();
$t->test();
$t = new derived_a();
$t->test();
eval('
function __autoload($name)
{
echo ">>>> In __autoload: ";
var_dump($name);
}
');
echo "NOW WITH AUTOLOAD\n\n";
$t = new base();
$t->test();
$t = new derived_a();
$t->test();
$t = new derived_b();
$t->test();
?>
--EXPECTF--
>>> With Defined class
is_a( OBJECT:base, base) = yes
is_a( STRING:base, base) = no
is_a( STRING:base, base, true) = yes
is_subclass_of( OBJECT:base, base) = no
is_subclass_of( STRING:base, base) = no
is_subclass_of( STRING:base, base,false) = no
>>> With Undefined
is_a( STRING:undefB, base,true) = no
is_a( STRING:undefB, base) = no
is_subclass_of( STRING:undefB, base,false) = no
is_subclass_of( STRING:undefB, base) = no
>>> With Defined class
is_a( OBJECT:base, derived_a) = no
is_a( STRING:base, derived_a) = no
is_a( STRING:base, derived_a, true) = no
is_subclass_of( OBJECT:base, derived_a) = no
is_subclass_of( STRING:base, derived_a) = no
is_subclass_of( STRING:base, derived_a,false) = no
>>> With Undefined
is_a( STRING:undefB, derived_a,true) = no
is_a( STRING:undefB, derived_a) = no
is_subclass_of( STRING:undefB, derived_a,false) = no
is_subclass_of( STRING:undefB, derived_a) = no
>>> With Defined class
is_a( OBJECT:base, if_a) = no
is_a( STRING:base, if_a) = no
is_a( STRING:base, if_a, true) = no
is_subclass_of( OBJECT:base, if_a) = no
is_subclass_of( STRING:base, if_a) = no
is_subclass_of( STRING:base, if_a,false) = no
>>> With Undefined
is_a( STRING:undefB, if_a,true) = no
is_a( STRING:undefB, if_a) = no
is_subclass_of( STRING:undefB, if_a,false) = no
is_subclass_of( STRING:undefB, if_a) = no
>>> With Defined class
is_a( OBJECT:base, undefA) = no
is_a( STRING:base, undefA) = no
is_a( STRING:base, undefA, true) = no
is_subclass_of( OBJECT:base, undefA) = no
is_subclass_of( STRING:base, undefA) = no
is_subclass_of( STRING:base, undefA,false) = no
>>> With Undefined
is_a( STRING:undefB, undefA,true) = no
is_a( STRING:undefB, undefA) = no
is_subclass_of( STRING:undefB, undefA,false) = no
is_subclass_of( STRING:undefB, undefA) = no
>>> With Defined class
is_a( OBJECT:derived_a, base) = yes
is_a( STRING:derived_a, base) = no
is_a( STRING:derived_a, base, true) = yes
is_subclass_of( OBJECT:derived_a, base) = yes
is_subclass_of( STRING:derived_a, base) = yes
is_subclass_of( STRING:derived_a, base,false) = no
>>> With Undefined
is_a( STRING:undefB, base,true) = no
is_a( STRING:undefB, base) = no
is_subclass_of( STRING:undefB, base,false) = no
is_subclass_of( STRING:undefB, base) = no
>>> With Defined class
is_a( OBJECT:derived_a, derived_a) = yes
is_a( STRING:derived_a, derived_a) = no
is_a( STRING:derived_a, derived_a, true) = yes
is_subclass_of( OBJECT:derived_a, derived_a) = no
is_subclass_of( STRING:derived_a, derived_a) = no
is_subclass_of( STRING:derived_a, derived_a,false) = no
>>> With Undefined
is_a( STRING:undefB, derived_a,true) = no
is_a( STRING:undefB, derived_a) = no
is_subclass_of( STRING:undefB, derived_a,false) = no
is_subclass_of( STRING:undefB, derived_a) = no
>>> With Defined class
is_a( OBJECT:derived_a, if_a) = yes
is_a( STRING:derived_a, if_a) = no
is_a( STRING:derived_a, if_a, true) = yes
is_subclass_of( OBJECT:derived_a, if_a) = yes
is_subclass_of( STRING:derived_a, if_a) = yes
is_subclass_of( STRING:derived_a, if_a,false) = no
>>> With Undefined
is_a( STRING:undefB, if_a,true) = no
is_a( STRING:undefB, if_a) = no
is_subclass_of( STRING:undefB, if_a,false) = no
is_subclass_of( STRING:undefB, if_a) = no
>>> With Defined class
is_a( OBJECT:derived_a, undefA) = no
is_a( STRING:derived_a, undefA) = no
is_a( STRING:derived_a, undefA, true) = no
is_subclass_of( OBJECT:derived_a, undefA) = no
is_subclass_of( STRING:derived_a, undefA) = no
is_subclass_of( STRING:derived_a, undefA,false) = no
>>> With Undefined
is_a( STRING:undefB, undefA,true) = no
is_a( STRING:undefB, undefA) = no
is_subclass_of( STRING:undefB, undefA,false) = no
is_subclass_of( STRING:undefB, undefA) = no
NOW WITH AUTOLOAD
>>> With Defined class
is_a( OBJECT:base, base) = yes
is_a( STRING:base, base) = no
is_a( STRING:base, base, true) = yes
is_subclass_of( OBJECT:base, base) = no
is_subclass_of( STRING:base, base) = no
is_subclass_of( STRING:base, base,false) = no
>>> With Undefined
>>>> In __autoload: string(6) "undefB"
is_a( STRING:undefB, base,true) = no
is_a( STRING:undefB, base) = no
is_subclass_of( STRING:undefB, base,false) = no
>>>> In __autoload: string(6) "undefB"
is_subclass_of( STRING:undefB, base) = no
>>> With Defined class
is_a( OBJECT:base, derived_a) = no
is_a( STRING:base, derived_a) = no
is_a( STRING:base, derived_a, true) = no
is_subclass_of( OBJECT:base, derived_a) = no
is_subclass_of( STRING:base, derived_a) = no
is_subclass_of( STRING:base, derived_a,false) = no
>>> With Undefined
>>>> In __autoload: string(6) "undefB"
is_a( STRING:undefB, derived_a,true) = no
is_a( STRING:undefB, derived_a) = no
is_subclass_of( STRING:undefB, derived_a,false) = no
>>>> In __autoload: string(6) "undefB"
is_subclass_of( STRING:undefB, derived_a) = no
>>> With Defined class
is_a( OBJECT:base, if_a) = no
is_a( STRING:base, if_a) = no
is_a( STRING:base, if_a, true) = no
is_subclass_of( OBJECT:base, if_a) = no
is_subclass_of( STRING:base, if_a) = no
is_subclass_of( STRING:base, if_a,false) = no
>>> With Undefined
>>>> In __autoload: string(6) "undefB"
is_a( STRING:undefB, if_a,true) = no
is_a( STRING:undefB, if_a) = no
is_subclass_of( STRING:undefB, if_a,false) = no
>>>> In __autoload: string(6) "undefB"
is_subclass_of( STRING:undefB, if_a) = no
>>> With Defined class
is_a( OBJECT:base, undefA) = no
is_a( STRING:base, undefA) = no
is_a( STRING:base, undefA, true) = no
is_subclass_of( OBJECT:base, undefA) = no
is_subclass_of( STRING:base, undefA) = no
is_subclass_of( STRING:base, undefA,false) = no
>>> With Undefined
>>>> In __autoload: string(6) "undefB"
is_a( STRING:undefB, undefA,true) = no
is_a( STRING:undefB, undefA) = no
is_subclass_of( STRING:undefB, undefA,false) = no
>>>> In __autoload: string(6) "undefB"
is_subclass_of( STRING:undefB, undefA) = no
>>> With Defined class
is_a( OBJECT:derived_a, base) = yes
is_a( STRING:derived_a, base) = no
is_a( STRING:derived_a, base, true) = yes
is_subclass_of( OBJECT:derived_a, base) = yes
is_subclass_of( STRING:derived_a, base) = yes
is_subclass_of( STRING:derived_a, base,false) = no
>>> With Undefined
>>>> In __autoload: string(6) "undefB"
is_a( STRING:undefB, base,true) = no
is_a( STRING:undefB, base) = no
is_subclass_of( STRING:undefB, base,false) = no
>>>> In __autoload: string(6) "undefB"
is_subclass_of( STRING:undefB, base) = no
>>> With Defined class
is_a( OBJECT:derived_a, derived_a) = yes
is_a( STRING:derived_a, derived_a) = no
is_a( STRING:derived_a, derived_a, true) = yes
is_subclass_of( OBJECT:derived_a, derived_a) = no
is_subclass_of( STRING:derived_a, derived_a) = no
is_subclass_of( STRING:derived_a, derived_a,false) = no
>>> With Undefined
>>>> In __autoload: string(6) "undefB"
is_a( STRING:undefB, derived_a,true) = no
is_a( STRING:undefB, derived_a) = no
is_subclass_of( STRING:undefB, derived_a,false) = no
>>>> In __autoload: string(6) "undefB"
is_subclass_of( STRING:undefB, derived_a) = no
>>> With Defined class
is_a( OBJECT:derived_a, if_a) = yes
is_a( STRING:derived_a, if_a) = no
is_a( STRING:derived_a, if_a, true) = yes
is_subclass_of( OBJECT:derived_a, if_a) = yes
is_subclass_of( STRING:derived_a, if_a) = yes
is_subclass_of( STRING:derived_a, if_a,false) = no
>>> With Undefined
>>>> In __autoload: string(6) "undefB"
is_a( STRING:undefB, if_a,true) = no
is_a( STRING:undefB, if_a) = no
is_subclass_of( STRING:undefB, if_a,false) = no
>>>> In __autoload: string(6) "undefB"
is_subclass_of( STRING:undefB, if_a) = no
>>> With Defined class
is_a( OBJECT:derived_a, undefA) = no
is_a( STRING:derived_a, undefA) = no
is_a( STRING:derived_a, undefA, true) = no
is_subclass_of( OBJECT:derived_a, undefA) = no
is_subclass_of( STRING:derived_a, undefA) = no
is_subclass_of( STRING:derived_a, undefA,false) = no
>>> With Undefined
>>>> In __autoload: string(6) "undefB"
is_a( STRING:undefB, undefA,true) = no
is_a( STRING:undefB, undefA) = no
is_subclass_of( STRING:undefB, undefA,false) = no
>>>> In __autoload: string(6) "undefB"
is_subclass_of( STRING:undefB, undefA) = no
>>> With Defined class
is_a( OBJECT:derived_b, base) = yes
is_a( STRING:derived_b, base) = no
is_a( STRING:derived_b, base, true) = yes
is_subclass_of( OBJECT:derived_b, base) = yes
is_subclass_of( STRING:derived_b, base) = yes
is_subclass_of( STRING:derived_b, base,false) = no
>>> With Undefined
>>>> In __autoload: string(6) "undefB"
is_a( STRING:undefB, base,true) = no
is_a( STRING:undefB, base) = no
is_subclass_of( STRING:undefB, base,false) = no
>>>> In __autoload: string(6) "undefB"
is_subclass_of( STRING:undefB, base) = no
>>> With Defined class
is_a( OBJECT:derived_b, derived_a) = no
is_a( STRING:derived_b, derived_a) = no
is_a( STRING:derived_b, derived_a, true) = no
is_subclass_of( OBJECT:derived_b, derived_a) = no
is_subclass_of( STRING:derived_b, derived_a) = no
is_subclass_of( STRING:derived_b, derived_a,false) = no
>>> With Undefined
>>>> In __autoload: string(6) "undefB"
is_a( STRING:undefB, derived_a,true) = no
is_a( STRING:undefB, derived_a) = no
is_subclass_of( STRING:undefB, derived_a,false) = no
>>>> In __autoload: string(6) "undefB"
is_subclass_of( STRING:undefB, derived_a) = no
>>> With Defined class
is_a( OBJECT:derived_b, if_a) = yes
is_a( STRING:derived_b, if_a) = no
is_a( STRING:derived_b, if_a, true) = yes
is_subclass_of( OBJECT:derived_b, if_a) = yes
is_subclass_of( STRING:derived_b, if_a) = yes
is_subclass_of( STRING:derived_b, if_a,false) = no
>>> With Undefined
>>>> In __autoload: string(6) "undefB"
is_a( STRING:undefB, if_a,true) = no
is_a( STRING:undefB, if_a) = no
is_subclass_of( STRING:undefB, if_a,false) = no
>>>> In __autoload: string(6) "undefB"
is_subclass_of( STRING:undefB, if_a) = no
>>> With Defined class
is_a( OBJECT:derived_b, undefA) = no
is_a( STRING:derived_b, undefA) = no
is_a( STRING:derived_b, undefA, true) = no
is_subclass_of( OBJECT:derived_b, undefA) = no
is_subclass_of( STRING:derived_b, undefA) = no
is_subclass_of( STRING:derived_b, undefA,false) = no
>>> With Undefined
>>>> In __autoload: string(6) "undefB"
is_a( STRING:undefB, undefA,true) = no
is_a( STRING:undefB, undefA) = no
is_subclass_of( STRING:undefB, undefA,false) = no
>>>> In __autoload: string(6) "undefB"
is_subclass_of( STRING:undefB, undefA) = no

24
ext/standard/tests/class_object/is_a_error_001.phpt

@ -4,7 +4,7 @@ Test is_a() function : error conditions - wrong number of args
error_reporting=E_ALL | E_STRICT | E_DEPRECATED
--FILE--
<?php
/* Prototype : proto bool is_a(object object, string class_name)
/* Prototype : proto bool is_a(object object, string class_name, bool allow_string)
* Description: Returns true if the object is of this class or has this class as one of its parents
* Source code: Zend/zend_builtin_functions.c
* Alias to functions:
@ -12,13 +12,19 @@ error_reporting=E_ALL | E_STRICT | E_DEPRECATED
echo "*** Testing is_a() : error conditions ***\n";
//Test is_a with one more than the expected number of arguments
echo "\n-- Testing is_a() function with more than expected no. of arguments --\n";
$object = new stdclass();
$class_name = 'string_val';
$allow_string = false;
$extra_arg = 10;
var_dump( is_a($object, $class_name, $extra_arg) );
var_dump( is_a($object, $class_name, $allow_string, $object) );
//Test is_a with one more than the expected number of arguments
echo "\n-- Testing is_a() function with non-boolean in last position --\n";
var_dump( is_a($object, $class_name, $object) );
// Testing is_a with one less than the expected number of arguments
echo "\n-- Testing is_a() function with less than expected no. of arguments --\n";
@ -28,15 +34,21 @@ var_dump( is_a($object) );
echo "Done";
?>
--EXPECTF--
*** Testing is_a() : error conditions ***
-- Testing is_a() function with more than expected no. of arguments --
Warning: is_a() expects exactly 2 parameters, 3 given in %s on line 16
Warning: is_a() expects at most 3 parameters, 4 given in %s on line 17
NULL
-- Testing is_a() function with non-boolean in last position --
Warning: is_a() expects parameter 3 to be boolean, object given in %s on line 21
NULL
-- Testing is_a() function with less than expected no. of arguments --
Warning: is_a() expects exactly 2 parameters, 1 given in %s on line 21
Warning: is_a() expects at least 2 parameters, 1 given in %s on line 27
NULL
Done
Done

24
ext/standard/tests/class_object/is_subclass_of_error_001.phpt

@ -15,8 +15,18 @@ echo "*** Testing is_subclass_of() : error conditions ***\n";
echo "\n-- Testing is_subclass_of() function with more than expected no. of arguments --\n";
$object = new stdclass();
$class_name = 'string_val';
$allow_string = false;
$extra_arg = 10;
var_dump( is_subclass_of($object, $class_name, $extra_arg) );
var_dump( is_subclass_of($object, $class_name, $allow_string, $extra_arg) );
//Test is_subclass_of with invalid last argument
echo "\n-- Testing is_subclass_of() function with more than typo style invalid 3rd argument --\n";
var_dump( is_subclass_of($object, $class_name, $class_name) );
//Test is_subclass_of with invalid last argument
echo "\n-- Testing is_subclass_of() function with more than invalid 3rd argument --\n";
var_dump( is_subclass_of($object, $class_name, $object) );
// Testing is_subclass_of with one less than the expected number of arguments
echo "\n-- Testing is_subclass_of() function with less than expected no. of arguments --\n";
@ -30,11 +40,19 @@ echo "Done";
-- Testing is_subclass_of() function with more than expected no. of arguments --
Warning: is_subclass_of() expects exactly 2 parameters, 3 given in %s on line 16
Warning: is_subclass_of() expects at most 3 parameters, 4 given in %s on line 17
NULL
-- Testing is_subclass_of() function with more than typo style invalid 3rd argument --
bool(false)
-- Testing is_subclass_of() function with more than invalid 3rd argument --
Warning: is_subclass_of() expects parameter 3 to be boolean, object given in %s on line 26
NULL
-- Testing is_subclass_of() function with less than expected no. of arguments --
Warning: is_subclass_of() expects exactly 2 parameters, 1 given in %s on line 21
Warning: is_subclass_of() expects at least 2 parameters, 1 given in %s on line 31
NULL
Done
Loading…
Cancel
Save