Because the version 2 is a full API rewrites, and used namespaces, your old code cannot migrate without a little change.

We will try to explain how to do in few steps.

Containers

Version 1.x used customizable containers feature to store parsing results.

For example, in version 1.x when we wanted to retrieve user functions, we could either do :

Example 1. With standard container
<?php
require_once 'Bartlett/PHP/Reflect/Autoload.php';

$source = '/path/to/source_file.php';

$options = array();

$reflect = new PHP_Reflect($options);
$reflect->scan($source);

$functions = $reflect->getFunctions();
// OR
$functions = $reflect['functions'];
Example 2. With a non standard container
<?php
require_once 'Bartlett/PHP/Reflect/Autoload.php';

$source = '/path/to/source_file.php';

$options = array('containers' => array('function' => 'userFunctions');

$reflect = new PHP_Reflect($options);
$reflect->scan($source);

$functions = $reflect->getUserFunctions();
// OR
$functions = $reflect['userFunctions'];

In version 2.x, we have collections of data models that we can enumerate and exploit.

See API in developer’s guide v2.6
Example 3. Enumerate each user functions
<?php
require_once 'vendor/autoload.php';

use Bartlett\Reflect;
use Bartlett\Reflect\ProviderManager;
use Bartlett\Reflect\Provider\SymfonyFinderProvider;

use Symfony\Component\Finder\Finder;

$finder = new Finder();
$finder->files()
    ->name('source_file.php')
    ->in('/path/to/');

// Identify Data Source
$pm = new ProviderManager;
$pm->set('Sample', new SymfonyFinderProvider($finder));

$reflect = new Reflect;
$reflect->setProviderManager($pm);
$reflect->parse();

// Exploit results
foreach ($reflect->getPackages() as $package) {
    $functions = $package->getFunctions();
}

Properties

Version 1.x may provide a variable properties list. Version 2.x provides all properties anytime. It’s up to you to decide to use them or not.

For example, in version 1.x when we wanted to retrieve only keywords and signature of each class methods of a data source.

Example 4. Configure interface, class and method properties
<?php
require_once 'Bartlett/PHP/Reflect/Autoload.php';

$source = '/path/to/PEAR-1.9.2/PEAR.php';

$options = array(
    'properties' => array(
        'interface' => array(
            'parent', 'methods'
        ),
        'class' => array(
            'parent', 'methods', 'interfaces', 'package'
        ),
        'function' => array(
            'signature'
        ),
    )
);
$reflect = new PHP_Reflect($options);
$reflect->scan($source);

$classes = $reflect->getClasses();

print_r($classes['\\']['PEAR_Error']['methods']);
Script output
Array
(
    [PEAR_Error] => Array
        (
            [signature] => PEAR_Error($message = 'unknown error', $code = null,
                        $mode = null, $options = null, $userinfo = null)
        )

    [getMode] => Array
        (
            [signature] => getMode()
        )

    [getCallback] => Array
        (
            [signature] => getCallback()
        )

    [getMessage] => Array
        (
            [signature] => getMessage()
        )

    [getCode] => Array
        (
            [signature] => getCode()
        )

    [getType] => Array
        (
            [signature] => getType()
        )

    [getUserInfo] => Array
        (
            [signature] => getUserInfo()
        )

    [getDebugInfo] => Array
        (
            [signature] => getDebugInfo()
        )

    [getBacktrace] => Array
        (
            [signature] => getBacktrace($frame = null)
        )

    [addUserInfo] => Array
        (
            [signature] => addUserInfo($info)
        )

    [__toString] => Array
        (
            [signature] => __toString()
        )

    [toString] => Array
        (
            [signature] => toString()
        )
)

In version 2.x, when we did the same.

Example 5. Properties on demand
<?php
require_once 'vendor/autoload.php';

use Bartlett\Reflect;
use Bartlett\Reflect\ProviderManager;
use Bartlett\Reflect\Provider\SymfonyFinderProvider;

use Symfony\Component\Finder\Finder;

$finder = new Finder();
$finder->files()
    ->name('PEAR.php')
    ->in('/path/to/PEAR-1.9.2/');

// Identify Data Source
$pm = new ProviderManager;
$pm->set('PEAR192', new SymfonyFinderProvider($finder));

$reflect = new Reflect;
$reflect->setProviderManager($pm);
$reflect->parse();

// Exploit results
$out = array();

foreach ($reflect->getPackages() as $package) {
    foreach ($package->getClasses() as $class) {

        if ($class->getShortName() !== 'PEAR_Error') {
            continue;
        }

        foreach ($class->getMethods() as $method) {

            if ($method->isPrivate()) {
                $visibility = 'private';
            } elseif ($method->isProtected()) {
                $visibility = 'protected';
            } else {
                $visibility = 'public';
            }

            $name = $method->getShortName();

            $parameters = $method->getParameters();
            $args       = array();

            foreach ($parameters as $parameter) {

                $args[] = sprintf(
                    '%s%s%s',
                    $parameter->isPassedByReference() ? '&' : '',
                    '$' . $parameter->getName(),
                    $parameter->isDefaultValueAvailable() ? ' = ' . $parameter->getDefaultValue() : ''
                );
            }

            $out[$name] = array(
                'signature' => sprintf('%s %s(%s)', $visibility, $name, implode(',', $args))
            );
        }
    }
}
print_r($out);
Script output
Array
(
    [PEAR_Error] => Array
        (
            [signature] => public PEAR_Error($message = 'unknown error',$code = null,$mode = null,$options = null,$userinfo = null)
        )

    [getMode] => Array
        (
            [signature] => public getMode()
        )

    [getCallback] => Array
        (
            [signature] => public getCallback()
        )

    [getMessage] => Array
        (
            [signature] => public getMessage()
        )

    [getCode] => Array
        (
            [signature] => public getCode()
        )

    [getType] => Array
        (
            [signature] => public getType()
        )

    [getUserInfo] => Array
        (
            [signature] => public getUserInfo()
        )

    [getDebugInfo] => Array
        (
            [signature] => public getDebugInfo()
        )

    [getBacktrace] => Array
        (
            [signature] => public getBacktrace($frame = null)
        )

    [addUserInfo] => Array
        (
            [signature] => public addUserInfo($info)
        )

    [__toString] => Array
        (
            [signature] => public __toString()
        )

    [toString] => Array
        (
            [signature] => public toString()
        )

)

Summary

Let’s review what we’ve did :

  • Compared Containers configuration solutions, and how to do it with both versions 1.x and 2.x

  • Compared Properties configuration solutions, and how to do it with both versions 1.x and 2.x

  • Used some methods of the new API 2.x, to enumerate and exploit parsing results.

Next

For PHP developers only.

Read more
  • Want to learn more about Reflect API, to exploit results as you want, have a look on developer’s guide.