<?php

namespace Test {
    function printResult($name, $result) {
        print ' ' . str_pad($name, 26) . '=> ' . $result . "\n";
    }
}


namespace TestSelf {
        
    class A {
        static function whoBase() {
            return 'A';
        }
        
        static function whoOverridden() {
            return 'A';
        }
        
        static $varBase = 'A';
        
        static $varOverridden = 'A'; 
        
        static function testA() {
            \Test\printResult('self::whoBase()',  self::whoBase());
            \Test\printResult('self::whoOverridden()',  self::whoOverridden());
            \Test\printResult('self::$varBase',  self::$varBase);
            \Test\printResult('self::$varOverridden',  self::$varOverridden);
        }
    }

    class B extends A {
        static function whoOverridden() {
            return 'B';
        }
        
        static $varOverridden = 'B';
        
        static function testB() {
            \Test\printResult('self::whoBase()',  self::whoBase());
            \Test\printResult('self::whoOverridden()',  self::whoOverridden());
            \Test\printResult('self::$varBase',  self::$varBase);
            \Test\printResult('self::$varOverridden',  self::$varOverridden);
        }
    }

    echo "Test 'self' keyword.\n\n";
    echo "Class A::testA()\n";
    A::testA();
    echo "Class B::testA()\n";
    B::testA();
    echo "Class B::testB()\n";
    B::testB();
    echo "===============================\n";
}

Test 'self' keyword.

Class A::testA()
 self::whoBase()           => A
 self::whoOverridden()     => A
 self::$varBase            => A
 self::$varOverridden      => A
Class B::testA()
 self::whoBase()           => A
 self::whoOverridden()     => A
 self::$varBase            => A
 self::$varOverridden      => A
Class B::testB()
 self::whoBase()           => A
 self::whoOverridden()     => B
 self::$varBase            => A
 self::$varOverridden      => B
===============================
 namespace TestStatic {
        
    class A {
        static function whoBase() {
            return 'A';
        }
        
        static function whoOverridden() {
            return 'A';
        }
        
        static $varBase = 'A';
        
        static $varOverridden = 'A'; 
        
        static function testA() {
            \Test\printResult('static::whoBase()',  static::whoBase());
            \Test\printResult('static::whoOverridden()',  static::whoOverridden());
            \Test\printResult('static::$varBase',  static::$varBase);
            \Test\printResult('static::$varOverridden',  static::$varOverridden);
        }
        
        static function testAViaSelfReference() {
            self::testA();
        }
        
        static function testAViaExplicitReference() {
            A::testA();
        }
    }

    class B extends A {
        static function whoOverridden() {
            return 'B';
        }
        
        static $varOverridden = 'B';
        
        static function testB() {
            \Test\printResult('static::whoBase()',  static::whoBase());
            \Test\printResult('static::whoOverridden()',  static::whoOverridden());
            \Test\printResult('static::$varBase',  static::$varBase);
            \Test\printResult('static::$varOverridden',  static::$varOverridden);
        }
    }

    echo "Test 'static' keyword.\n\n";
    echo "Class A::testA()\n";
    A::testA();
    echo "Class B::testA()\n";
    B::testA();
    echo "Class B::testB()\n";
    B::testB();
    echo "Class B::testAViaSelfReference()\n";
    B::testAViaSelfReference();
    echo "Class B::testAViaExplicitReference()\n";
    B::testAViaExplicitReference();
    echo "===============================\n";
}

Test 'static' keyword.

Class A::testA()
 static::whoBase()         => A
 static::whoOverridden()   => A
 static::$varBase          => A
 static::$varOverridden    => A
Class B::testA()
 static::whoBase()         => A
 static::whoOverridden()   => B
 static::$varBase          => A
 static::$varOverridden    => B
Class B::testB()
 static::whoBase()         => A
 static::whoOverridden()   => B
 static::$varBase          => A
 static::$varOverridden    => B
Class B::testAViaSelfReference()
 static::whoBase()         => A
 static::whoOverridden()   => B
 static::$varBase          => A
 static::$varOverridden    => B
Class B::testAViaExplicitReference()
 static::whoBase()         => A
 static::whoOverridden()   => A
 static::$varBase          => A
 static::$varOverridden    => A
===============================
 namespace TestStaticMethodVariables {
        
    class A {
        static function count() {
            static $count = 1;
            return $count++;
        }
        
        static function selfCount() {
            return self::count();
        }
        
        static function staticCount() {
            return static::count();
        }
    }

    class B extends A {
    }

    echo "Test static method variables.\n\n";
    echo "Class A\n";
    \Test\printResult('A::count()', A::count());
    \Test\printResult('A::count()', A::count());
    \Test\printResult('A::count()', A::count());
    \Test\printResult('A::staticCount()', A::staticCount());
    \Test\printResult('A::selfCount()', A::selfCount());
    echo "Class B\n";
    \Test\printResult('B::count()', B::count());
    \Test\printResult('B::staticCount()', B::staticCount());
    \Test\printResult('B::selfCount()', B::selfCount());
    echo "===============================\n";
}
Test static method variables.

Class A
 A::count()                => 1
 A::count()                => 2
 A::count()                => 3
 A::staticCount()          => 4
 A::selfCount()            => 5
Class B
 B::count()                => 1
 B::staticCount()          => 2
 B::selfCount()            => 6
===============================
 namespace TestIntrospection {
        
    class A {
        static function getCalledClass() {
            return get_called_class();
        }
        
        static function getClass() {
            return get_class();
        }
        
        static function getClassConstant() {
            return __CLASS__;
        }
        
        static function staticGetCalledClass() {
            return static::getCalledClass();
        }        
        
        static function selfGetCalledClass() {
            return self::getCalledClass();
        }
        
        static function aGetCalledClass() {
            return A::getCalledClass();
        }
    }

    class B extends A {
    }

    echo "Test introspection functions.\n\n";
    echo "Class A\n";
    \Test\printResult('A::getCalledClass()',  A::getCalledClass());
    \Test\printResult('A::getClass()',  A::getClass());
    \Test\printResult('A::getClassConstant()',  A::getClassConstant());
    \Test\printResult('A::staticGetCalledClass()',  A::staticGetCalledClass());
    \Test\printResult('A::selfGetCalledClass()',  A::selfGetCalledClass());
    \Test\printResult('A::aGetCalledClass()',  A::aGetCalledClass());
            
    echo "Class B\n";
    \Test\printResult('B::getCalledClass()',  B::getCalledClass());
    \Test\printResult('B::getClass()',  B::getClass());
    \Test\printResult('B::getClassConstant()',  B::getClassConstant());
    \Test\printResult('B::staticGetCalledClass()',  B::staticGetCalledClass());
    \Test\printResult('B::selfGetCalledClass()',  B::selfGetCalledClass());
    \Test\printResult('B::aGetCalledClass()',  B::aGetCalledClass());
    echo "===============================\n";
}

===============================
Test introspection functions.

Class A
 A::getCalledClass()       => TestIntrospection\A
 A::getClass()             => TestIntrospection\A
 A::getClassConstant()     => TestIntrospection\A
 A::staticGetCalledClass() => TestIntrospection\A
 A::selfGetCalledClass()   => TestIntrospection\A
 A::aGetCalledClass()      => TestIntrospection\A
Class B
 B::getCalledClass()       => TestIntrospection\B
 B::getClass()             => TestIntrospection\A
 B::getClassConstant()     => TestIntrospection\A
 B::staticGetCalledClass() => TestIntrospection\B
 B::selfGetCalledClass()   => TestIntrospection\B
 B::aGetCalledClass()      => TestIntrospection\A
===============================