marcelog / PAMI

PHP Asterisk Manager Interface ( AMI ) supports synchronous command ( action )/ responses and asynchronous events using the pattern observer-listener. Supports commands with responses with multiple events. Very suitable for development of operator consoles and / or asterisk / channels / peers monitoring through SOA, etc
http://marcelog.github.com/PAMI
Apache License 2.0
402 stars 281 forks source link

Error: implode(): Argument #2 ($array) must be of type ?array, string given #212

Open gutorsantos opened 2 years ago

gutorsantos commented 2 years ago

I have been working on a Laravel project and I had to use PAMI, by the way it's a great library! However, recently I got this error

[2022-01-21 09:55:06] ERROR: implode(): Argument #2 ($array) must be of type ?array, string given {"userId":8,"exception":"[object] (TypeError(code: 0): implode(): Argument #2 ($array) must be of type ?array, string given at .../marcelog/pami/src/PAMI/Message/Event/Factory/Impl/EventFactoryImpl.php:72)

I'm using the following settings:

OS: Ubuntu 20.04
Laravel 8
PHP 8+ (at least 8 or newer)

After a few days of headache and tests, I finally found what was occurring. I went to the error line on EventFactoryImpl.php. At beginning, I was thinking Asterisk server was returning a wrong message, after some tests and verifications I concluded it was not the server. In order that, I went to php documentation and found the order of implode function arguments was wrong. According to the documentation the function signature is as follows:

implode(string $separator, array $array): string

As we can see on code, the order is inverted:

    public static function createFromRaw($message)
    {
        $eventStart = strpos($message, 'Event: ') + 7;
        $eventEnd = strpos($message, Message::EOL, $eventStart);
        if ($eventEnd === false) {
            $eventEnd = strlen($message);
        }
        $name = substr($message, $eventStart, $eventEnd - $eventStart);
        $parts = explode('_', $name);
        $totalParts = count($parts);
        for ($i = 0; $i < $totalParts; $i++) {
            $parts[$i] = ucfirst($parts[$i]);
        }
        $name = implode($parts, '');    # trouble line
        $className = '\\PAMI\\Message\\Event\\' . $name . 'Event';
        if (class_exists($className, true)) {
            return new $className($message);
        }
        return new UnknownEvent($message);
    }

Because of that I made a slightly change, reverting the order.

    public static function createFromRaw($message)
    {
        $eventStart = strpos($message, 'Event: ') + 7;
        $eventEnd = strpos($message, Message::EOL, $eventStart);
        if ($eventEnd === false) {
            $eventEnd = strlen($message);
        }
        $name = substr($message, $eventStart, $eventEnd - $eventStart);
        $parts = explode('_', $name);
        $totalParts = count($parts);
        for ($i = 0; $i < $totalParts; $i++) {
            $parts[$i] = ucfirst($parts[$i]);
        }
        $name = implode('', $parts);    # changed line
        $className = '\\PAMI\\Message\\Event\\' . $name . 'Event';
        if (class_exists($className, true)) {
            return new $className($message);
        }
        return new UnknownEvent($message);
    }

Hope this can help someone. And also be fixed in this wonderful project.

Thanks!

lorismich commented 2 years ago

Confirmed!

vcandela commented 2 years ago

They only need to Implement the Change in the repository, when they believe that this

91Abdullah commented 2 years ago

@lorismich where did you merged this PR because I can't find it in your fork?

lorismich commented 2 years ago

@lorismich where did you merged this PR because I can't find it in your fork? @91Abdullah
I reopened the PR here: https://github.com/marcelog/PAMI/pull/213