Jump to content
Mike Rockett

Unable to call wire() in namespaced classes

Recommended Posts

I'd like to add support for ProcessWire 2.8 in Jumplinks, but am unable to call wire() in any PSR-4 autoloaded class.

I'm using this to load my classes: $this->classLoader->addNamespace('Jumplinks', __DIR__ . '/src/Jumplinks');

In one of the classes given the Jumplinks\<Something> namespace, the file compiler does not compile wire() to \ProcessWire\wire().

Is this a known bug? Any way I can work around it?

Share this post


Link to post
Share on other sites

I've added this to my module file, directly after the classLoader instruction:

if (function_exists("\\ProcessWire\\wire")) {
    function wire() {
        return call_user_func_array("\\ProcessWire\\wire", func_get_args());
    }
}

It works, but I'm worried that it's the wrong way to do it...?

Share this post


Link to post
Share on other sites

Even better, I've done this instead:

Classes that use wire() outside of the ProcessWire namespace now extend or call \Jumplinks\Utility\BaseUtility::wire():

    /**
     * Call the global wire.
     * Retains support for PW 2.8.x and 3.x
     * @return mixed
     */
    public static function wire()
    {
        $wires = ["\\ProcessWire\\wire", 'wire'];
        foreach ($wires as $wire) {
            if (function_exists($wire)) {
                return call_user_func_array($wire, func_get_args());
            }
        }

        return Exception('Unable to call \ProcessWire\wire() or \wire().');
    }

Guess that's better?

Share this post


Link to post
Share on other sites

How about storing the result of the function selection in a static variable, so the computation does only happen once per request. The namespace won't magically switch mid request.

  • Like 1

Share this post


Link to post
Share on other sites
2 minutes ago, LostKobrakai said:

How about storing the result of the function selection in a static variable, so the computation does only happen once per request. The namespace won't magically switch mid request.

Yeah, I think that's a better idea. Thanks

Share this post


Link to post
Share on other sites

@LostKobrakai Does this look about right to you?

namespace Jumplinks\Utility;

class BaseUtility
{
    /**
     * Store the wire.
     * @var mixed
     */
    protected static $wire = null;

    /**
     * Store the wire if not already stored and then call it.
     *
     * @return mixed
     */
    public static function wire()
    {
        if (is_null(static::$wire)) {
            foreach (["\\ProcessWire\\wire", 'wire'] as $wire) {
                if (function_exists($wire)) {
                    static::$wire = $wire;
                }
            }
        }

        return call_user_func_array(static::$wire, func_get_args());
    }
}

Utilites then extend this class, and other classes that are not utilities simply call BaseUtility:wire().

Share this post


Link to post
Share on other sites

static:: (/late-) binding will result in each class doing their own calculation. You probably would want to use self:: so it's really a one time calculation for all of your classes.

  • Like 1

Share this post


Link to post
Share on other sites
39 minutes ago, LostKobrakai said:

static:: (/late-) binding will result in each class doing their own calculation. You probably would want to use self:: so it's really a one time calculation for all of your classes.

Of course - that makes sense. Thanks.

Share this post


Link to post
Share on other sites

Okay, so that's that one out of the way. But now what do I do for importing classes that may or may not be in the ProcessWire namespace?

For example, I need to use ProcessWire\NullPage and ProcessWire\InputfieldWrapper() in these autoloaded classes...

Edited by Mike Rockett
Add InputfieldWrapper

Share this post


Link to post
Share on other sites

So to answer the question of your entry post: namespaced files are never compiled. The compiler is mostly meant for 2.x to 3.x transition. As pw 2.x is namespaceless the compiler does only work on files without namespace (also makes things easier to control). So you would probably be fine if you could push all the 2.x / 3.x differences into a separate class without namespace.

<?php

class Bridge extends Wire {
  public function getNew($shortname) {
    switch($shortname) {
      case 'InputfieldWrapper':
        return new InputfieldWrapper();
      default:
        throw new WireException("Classname $shortname isn't setup or is invalid.");
    }
  }
}

 

  • Like 1

Share this post


Link to post
Share on other sites

That looks good - I could do that for NullPage and InputfieldWrapper, but I wouldn't be able to do it for wire() because it may not be called statically, and I don't want to create a new bridge for each class that uses it - unless that is the only way to go about it.

Update: I'm just using plain old wire()-> anyway, so no need for me to be calling it from the bridge itself. In fact, the bridge doesn't even need to extend Wire at all...

Edited by Mike Rockett

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...