ResourceHandlers#

ResourceHandlers is a convenience base class intended to help you register multiple resource handlers via a single static call (registerDefaults()).

It does not itself define any handlers; instead, you must extend it and implement named registerXxx() methods. When you call YourSubclass::registerDefaults(), it automatically invokes every static method that begins with "register".

Why?#

When your application or library needs to support many resource types (e.g. streams, cURL handles, XML parsers, GD images, sockets, etc.), you can:

  1. Group them in one “bundle” class that extends ResourceHandlers.

  2. Inside it, write one registerXxx() method per resource type: - e.g. registerStream(), registerCurl(), registerXmlParser(), etc.

  3. Call YourSubclass::registerDefaults() to register all of them at once.

This approach keeps your resource‐wrapper logic organized and self-documenting.

Class API#

void ResourceHandlers::registerDefaults()

Iterates over all public static methods on self::class whose names start with "register", except registerDefaults itself and invokes each one. In other words, every registerXxx() method in your subclass runs.

Does nothing if no registerXxx() methods exist.

You cannot instantiate ResourceHandlers (its constructor is private). It exists only to host static registration methods.

Example: Registering a Stream Handler#

Suppose you want to support PHP streams:

namespace App\Serializer;

use Infocyph\InterMix\Serializer\ResourceHandlers;
use Infocyph\InterMix\Serializer\ValueSerializer;

class MyResourceHandlers extends ResourceHandlers
{
    /**
     * Handles stream resources (both file‐ and network‐based).
     */
    public static function registerStream(): void
    {
        ValueSerializer::registerResourceHandler(
            'stream',
            // ---------- wrapFn -----------------------------------
            function ($res): array {
                $meta = stream_get_meta_data($res);
                rewind($res);
                return [
                    'mode'    => $meta['mode'],
                    'content' => stream_get_contents($res),
                ];
            },
            // -------- restoreFn ---------------------------------
            function (array $data) {
                $s = fopen('php://memory', $data['mode']);
                fwrite($s, $data['content']);
                rewind($s);
                return $s;
            }
        );
    }
}

Once you have that subclass, you can register the handler in two ways:

  1. Call ``registerStream()`` directly:

    MyResourceHandlers::registerStream();
    
  2. Call ``registerDefaults()`` to pick up every ``registerXxx()``:

    MyResourceHandlers::registerDefaults();
    // → automatically calls registerStream(), plus any other registerXxx()
    

    Then use ValueSerializer as usual:

    $fp     = fopen('php://memory','r+');
    fwrite($fp,'hello'); rewind($fp);
    
    $blob    = ValueSerializer::serialize($fp);
    $restored = ValueSerializer::unserialize($blob);
    echo stream_get_contents($restored); // "hello"
    

Adding More Resource Types#

To support additional resources:

  1. Extend ResourceHandlers.

  2. Add a new public static method named registerFoo() where “Foo” is any string you like (e.g. registerCurl(), registerXmlParser(), etc.).

  3. Inside it, call:

    ValueSerializer::registerResourceHandler(
        '<type>',    // e.g. 'curl'
        fn($res): array => /* wrap logic */,
        fn(array $data) => /* restore logic */
    );
    
  4. If you want all handlers applied at once, simply call:

    MyResourceHandlers::registerDefaults();
    

Example: cURL Handler#

namespace App\Serializer;

use Infocyph\InterMix\Serializer\ResourceHandlers;
use Infocyph\InterMix\Serializer\ValueSerializer;

class MyResourceHandlers extends ResourceHandlers
{
    public static function registerCurl(): void
    {
        if (!extension_loaded('curl')) {
            return;
        }
        ValueSerializer::registerResourceHandler(
            'curl',
            // wrapFn: store only the effective URL
            function ($ch): array {
                return ['url' => curl_getinfo($ch, CURLINFO_EFFECTIVE_URL)];
            },
            // restoreFn: open a new cURL handle with the same URL
            function (array $data) {
                return curl_init($data['url'] ?? '');
            }
        );
    }
}

// Usage:
MyResourceHandlers::registerDefaults();
// now you can ValueSerializer::serialize($my_curl_handle) safely.

Empty‐State and Testing#

  • By default, no resource handlers are registered. If you call ValueSerializer::wrap($someResource) before any registerResourceHandler(), you get an InvalidArgumentException.

  • You can always start with a clean slate:

    use Infocyph\InterMix\Serializer\ValueSerializer;
    
    ValueSerializer::clearResourceHandlers(); // removes all handlers