diff --git a/.codeclimate.yml b/.codeclimate.yml deleted file mode 100644 index 3c42fa251..000000000 --- a/.codeclimate.yml +++ /dev/null @@ -1,19 +0,0 @@ -engines: - duplication: - enabled: true - config: - languages: - - php - fixme: - enabled: false - phpcodesniffer: - enabled: true - phpmd: - enabled: true - -ratings: - paths: - - "**.php" - -exclude_paths: -- test/**/* \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..7003a6f5e --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,50 @@ +name: Build +on: + push: + branches: + - master + - github-actions + pull_request: + branches: + - master + - github-actions +jobs: + build: + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: [ 'ubuntu-latest' ] + php-versions: [ '8.2', '8.3' ] + phpunit-versions: [ '10' ] + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup PHP with PECL extension + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + coverage: xdebug + tools: phpstan,phpunit:${{ matrix.phpunit-versions }} + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Setup problem matchers for PHPUnit + run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Install dependencies + run: composer install + + - run: phpunit --version + + - run: vendor/bin/phpunit --configuration phpunit.xml + - run: vendor/bin/phpstan analyze diff --git a/.gitignore b/.gitignore index 55501307a..20ade0290 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,13 @@ build docs/examples/quickstart/log.log resources/php.ini +/.phpunit.result.cache +/.phpunit.cache/ +/.idea/.gitignore +/.idea/modules.xml +/.idea/PAMI.iml +/.idea/php.xml +/.idea/php-test-framework.xml +/.idea/phpspec.xml +/.idea/phpunit.xml +/.idea/vcs.xml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 2052749a2..000000000 --- a/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -language: php -php: - - '5.4' - - '5.5' - - '5.6' - - '7.0' - -before_script: - - phpenv config-add test/resources/php.ini - -install: - - composer install - -script: - - vendor/bin/phing travis - -after_script: - - travis_retry php vendor/bin/coveralls -v - - vendor/bin/test-reporter - -addons: - code_climate: - repo_token: 5d81d5163c7f9b810b46451042cb0069d24c91a5887466ba774bf89a56f0187e \ No newline at end of file diff --git a/README.md b/README.md index 0be4e82b9..52eb404e1 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,5 @@ +[![Build](https://github.com/level23/PAMI/actions/workflows/build.yml/badge.svg)](https://github.com/level23/PAMI/actions/workflows/build.yml) [![License](https://poser.pugx.org/marcelog/PAMI/license)](https://packagist.org/packages/marcelog/PAMI) -[![Latest Stable Version](https://poser.pugx.org/marcelog/PAMI/v/stable)](https://packagist.org/packages/marcelog/PAMI) -[![Documentation Status](https://readthedocs.org/projects/pami/badge/?version=latest)](http://pami.readthedocs.org/en/latest/?badge=latest) - -[![Build Status](https://travis-ci.org/marcelog/PAMI.svg)](https://travis-ci.org/marcelog/PAMI) -[![Coverage Status](https://coveralls.io/repos/marcelog/PAMI/badge.svg?branch=master&service=github)](https://coveralls.io/github/marcelog/PAMI?branch=master) -[![Code Climate](https://codeclimate.com/github/marcelog/PAMI/badges/gpa.svg)](https://codeclimate.com/github/marcelog/PAMI) -[![Issue Count](https://codeclimate.com/github/marcelog/PAMI/badges/issue_count.svg)](https://codeclimate.com/github/marcelog/PAMI) - -[![Click here to lend your support to: PAMI and make a donation at pledgie.com !](https://pledgie.com/campaigns/30944.png?skin_name=chrome' border='0')](https://pledgie.com/campaigns/30944) # Introduction @@ -18,8 +10,8 @@ events, using an observer-listener pattern. The idea behind this, is to easily implement operator consoles, monitors, etc. either via SOA or ajax. -A port for nodejs is available at: http://marcelog.github.com/Nami -A port for erlang is available at: https://github.com/marcelog/erlami +This package was forked and updated to the latest PHP standards. The original can be found here: +[https://github.com/marcelog/PAMI](https://github.com/marcelog/PAMI) # Resources @@ -28,16 +20,14 @@ A port for erlang is available at: https://github.com/marcelog/erlami # PHP Versions -Note: PAMI Requires PHP 5.3+. PHP versions 5.3.9 and 5.3.10 WILL NOT WORK due -to a bug introduced in stream_get_line() in 5.3.9. Please use 5.3.11+ or up -to 5.3.8 (see README.PHP-5.3.9-and-5.3.10). +This PAMI requires PHP 8.2 or higher. # Installing Add this library to your [Composer](https://packagist.org/) configuration. In composer.json: ```json "require": { - "marcelog/pami": "2.*" +"level23/pami": "2.*" } ``` @@ -49,15 +39,15 @@ For an in-depth tutorial: http://marcelog.github.com/articles/pami_introduction_ // Make sure you include the composer autoload. require __DIR__ . '/vendor/autoload.php'; -$options = array( +$options = [ 'host' => '2.3.4.5', 'scheme' => 'tcp://', 'port' => 9999, 'username' => 'asd', 'secret' => 'asd', 'connect_timeout' => 10, - 'read_timeout' => 10 -); + 'read_timeout' => 10, +]; $client = new \PAMI\Client\Impl\ClientImpl($options); // Registering a closure @@ -316,7 +306,7 @@ vendor/bin/phing build ## Contributing To contribute: * Make sure you open a **concise** and **short** pull request. - * Throw in any needed unit tests to accomodate the new code or the +* Throw in any needed unit tests to accommodate the new code or the changes involved. * Run `phing` and make sure everything is ok before submitting the pull request (make phpmd and CodeSniffer happy, also make sure that phpDocumentor diff --git a/build.xml b/build.xml deleted file mode 100644 index fc6d7221a..000000000 --- a/build.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/composer.json b/composer.json index 83e4c798d..e1b87521a 100644 --- a/composer.json +++ b/composer.json @@ -1,38 +1,65 @@ { - "name": "marcelog/pami", + "name": "level23/pami", "type": "library", "description": "Asterisk Manager Interface (AMI) client for PHP, event driven, object oriented", - "keywords": ["asterisk","ami","client","telephony","voip","event","action","manager","monitor"], - "homepage": "http://marcelog.github.com/PAMI", + "keywords": [ + "asterisk", + "ami", + "client", + "telephony", + "voip", + "event", + "action", + "manager", + "monitor" + ], + "homepage": "https://github.com/level23/PAMI", "license": "Apache-2.0", "authors": [ + { + "name": "Richard Stellingwerff", + "email": "richard@level23.nl", + "homepage": "https://level23.github.com/", + "role": "Maintainer" + }, + { + "name": "Teye Heimans", + "email": "teye@level23.nl", + "homepage": "https://level23.github.com/", + "role": "Maintainer" + }, { "name": "Marcelo Gornstein", "email": "marcelog@gmail.com", - "homepage": "http://marcelog.github.com/", + "homepage": "https://marcelog.github.com/", "role": "Developer" } ], "autoload": { + "files": [ + "src/PAMI/Helpers/helpers.php" + ], "psr-4": { "PAMI\\": "src/PAMI" } }, + "autoload-dev": { + "files": [ + "src/PAMI/Helpers/helpers.php" + ], + "psr-4": { + "Tests\\": "tests/" + } + }, "require": { - "php": ">=5.3.3", + "php": "^8.2", "psr/log": ">= 1.0.0" }, "require-dev": { - "phpunit/phpunit": "4.*", - "monolog/monolog": "1.*", - "squizlabs/php_codesniffer": "2.*", - "phpdocumentor/phpdocumentor": "2.*", - "phing/phing": "2.*", - "phpmd/phpmd": "2.*", - "satooshi/php-coveralls": "1.0.1", - "evert/phpdoc-md" : "~0.1.1", - "codeclimate/php-test-reporter": "dev-master", - "sebastian/phpcpd": "*", - "marcelog/pagi": "2.*" + "phpunit/phpunit": "10", + "monolog/monolog": "3.5.*", + "mockery/mockery": "^1.6", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-mockery": "^1.1" } } diff --git a/composer.phar b/composer.phar deleted file mode 100755 index 5d4640ce9..000000000 Binary files a/composer.phar and /dev/null differ diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 000000000..c8dfe77a9 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,11 @@ +includes: + - vendor/phpstan/phpstan-mockery/extension.neon + +parameters: + level: 6 + checkMissingIterableValueType: true + ignoreErrors: + excludePaths: + paths: + - tests + - src diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 000000000..98512ed5f --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,31 @@ + + + + + src + + + src/PAMI/Application + vendor + + + + + tests/ + + + diff --git a/src/PAMI/AsyncAgi/AsyncClientImpl.php b/src/PAMI/AsyncAgi/AsyncClientImpl.php deleted file mode 100644 index fdf8ac5e1..000000000 --- a/src/PAMI/AsyncAgi/AsyncClientImpl.php +++ /dev/null @@ -1,170 +0,0 @@ - - * @license http://marcelog.github.com/PAMI/ Apache License 2.0 - * @link http://marcelog.github.com/PAMI/ - * - * Copyright 2011 Marcelo Gornstein - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -namespace PAMI\AsyncAgi; - -use PAMI\Client\IClient as PamiClient; -use PAGI\Client\AbstractClient as PagiClient; -use PAMI\Listener\IEventListener; -use PAMI\Message\Event\EventMessage; -use PAGI\Client\Result\Result; -use Psr\Log\LoggerInterface; -use Psr\Log\NullLogger; - -/** - * An AGI client implementation. - * - * PHP Version 5 - * - * @category Pami - * @package AsyncAgi - * @author Marcelo Gornstein - * @license http://marcelog.github.com/PAMI/ Apache License 2.0 - * @link http://marcelog.github.com/PAMI/ - */ -class AsyncClientImpl extends PagiClient implements IEventListener -{ - /** - * The pami client to be used. - * @var \PAMI\Client\IClient - */ - private $pamiClient; - /** - * The event that originated this async agi request. - * @var \PAMI\Message\Event\AsyncAGIEvent - */ - private $asyncAgiEvent; - /** - * The channel that originated this async agi request. - * @var string - */ - private $channel; - /** - * The listener id after registering with the pami client. - * @var string - */ - private $listenerId; - - /** - * Last CommandId issued, so we can track responses for agi commands. - * @var string - */ - private $lastCommandId; - - /** - * Filled when an async agi event has been received, with command id equal - * to the last command id sent. - * @var string - */ - private $lastAgiResult; - - /** - * Handles pami events. - * - * @param EventMessage $event - * - * @return void - */ - public function handle(EventMessage $event) - { - if ($event instanceof \PAMI\Message\Event\AsyncAGIEvent) { - if ($event->getCommandId() == $this->lastCommandId) { - $this->lastAgiResult = trim($event->getResult()); - } - } - } - - /** - * (non-PHPdoc) - * @see ClientImpl::send() - */ - protected function send($text) - { - $this->logger->debug('Sending: ' . $text); - $this->lastCommandId = uniqid(__CLASS__); - $action = new \PAMI\Message\Action\AGIAction($this->channel, $text, $this->lastCommandId); - $this->lastAgiResult = false; - $response = $this->pamiClient->send($action); - if (!$response->isSuccess()) { - throw new \PAGI\Exception\ChannelDownException($response->getMessage()); - } - while ($this->lastAgiResult === false) { - $this->pamiClient->process(); - usleep(1000); - } - return $this->getResultFromResultString($this->lastAgiResult); - } - - /** - * (non-PHPdoc) - * @see ClientImpl::open() - */ - protected function open() - { - $environment = $this->asyncAgiEvent->getEnvironment(); - $this->channel = $this->asyncAgiEvent->getChannel(); - foreach (explode("\n", $environment) as $line) { - if ($this->isEndOfEnvironmentVariables($line)) { - break; - } - $this->readEnvironmentVariable($line); - } - $this->listenerId = $this->pamiClient->registerEventListener($this); - $this->logger->debug(print_r($this->variables, true)); - } - - /** - * (non-PHPdoc) - * @see ClientImpl::close() - */ - protected function close() - { - $this->pamiClient->unregisterEventListener($this->listenerId); - } - - /** - * Constructor. - * - * Note: The client accepts an array with options. The available options are - * - * pamiClient => The PAMI client that will be used to run this async client. - * - * environment => Environment as received by the AsyncAGI Event. - * - * @param array $options Optional properties. - * - * @return void - */ - public function __construct(array $options = array()) - { - $this->options = $options; - $this->logger = new NullLogger; - $this->pamiClient = $options['pamiClient']; - $this->asyncAgiEvent = $options['asyncAgiEvent']; - $this->open(); - } -} diff --git a/src/PAMI/Client/IClient.php b/src/PAMI/Client/IClient.php index b9c3e5f3d..c48e69aed 100644 --- a/src/PAMI/Client/IClient.php +++ b/src/PAMI/Client/IClient.php @@ -26,11 +26,13 @@ * limitations under the License. * */ + namespace PAMI\Client; -use PAMI\Message\OutgoingMessage; use Psr\Log\LoggerInterface; -use Psr\Log\NullLogger; +use PAMI\Message\OutgoingMessage; +use PAMI\Listener\IEventListener; +use PAMI\Message\Response\ResponseMessage; /** * Interface for an ami client. @@ -49,8 +51,8 @@ interface IClient /** * Opens a tcp connection to ami. * - * @throws \PAMI\Client\Exception\ClientException * @return void + * @throws \PAMI\Client\Exception\ClientException */ public function open(); @@ -65,16 +67,16 @@ public function process(); /** * Registers the given listener so it can receive events. Returns the generated - * id for this new listener. You can pass in a an IEventListener, a Closure, + * id for this new listener. You can pass in an IEventListener, a Closure, * and an array containing the object and name of the method to invoke. Can specify * an optional predicate to invoke before calling the callback. * - * @param mixed $listener - * @param Closure|null $predicate + * @param callable|IEventListener $listener + * @param callable|null $predicate * * @return string */ - public function registerEventListener($listener, $predicate = null); + public function registerEventListener(callable|IEventListener $listener, ?callable $predicate = null): string; /** * Unregisters an event listener. @@ -83,32 +85,32 @@ public function registerEventListener($listener, $predicate = null); * * @return void */ - public function unregisterEventListener($listenerId); + public function unregisterEventListener(string $listenerId): void; /** * Closes the connection to ami. * * @return void */ - public function close(); + public function close(): void; /** * Sends a message to ami. * * @param OutgoingMessage $message Message to send. * - * @see ClientImpl::send() - * @throws \PAMI\Client\Exception\ClientException * @return \PAMI\Message\Response\ResponseMessage + * @throws \PAMI\Client\Exception\ClientException + * @see ClientImpl::send() */ - public function send(OutgoingMessage $message); + public function send(OutgoingMessage $message): ResponseMessage; /** * Sets the logger implementation. * - * @param Psr\Log\LoggerInterface $logger The PSR3-Logger + * @param \Psr\Log\LoggerInterface $logger The PSR3-Logger * * @return void */ - public function setLogger(LoggerInterface $logger); + public function setLogger(LoggerInterface $logger): void; } diff --git a/src/PAMI/Client/Impl/ClientImpl.php b/src/PAMI/Client/Impl/ClientImpl.php index 853e4b746..2bfc6feb2 100644 --- a/src/PAMI/Client/Impl/ClientImpl.php +++ b/src/PAMI/Client/Impl/ClientImpl.php @@ -28,19 +28,22 @@ * limitations under the License. * */ + namespace PAMI\Client\Impl; -use PAMI\Message\OutgoingMessage; +use PAMI\Stream\Stream; +use Psr\Log\NullLogger; +use PAMI\Client\IClient; use PAMI\Message\Message; +use Psr\Log\LoggerInterface; +use PAMI\Message\OutgoingMessage; use PAMI\Message\IncomingMessage; +use PAMI\Listener\IEventListener; use PAMI\Message\Action\LoginAction; +use PAMI\Message\Event\EventMessage; use PAMI\Message\Response\ResponseMessage; -use PAMI\Message\Event\Factory\Impl\EventFactoryImpl; -use PAMI\Listener\IEventListener; use PAMI\Client\Exception\ClientException; -use PAMI\Client\IClient; -use Psr\Log\LoggerInterface; -use Psr\Log\NullLogger; +use PAMI\Message\Event\Factory\Impl\EventFactoryImpl; /** * TCP Client implementation for AMI. @@ -58,158 +61,197 @@ class ClientImpl implements IClient { /** * PSR-3 logger. + * * @var LoggerInterface */ - private $logger; + private LoggerInterface $logger; /** * Hostname + * * @var string */ - private $host; + private string $host; /** * TCP Port. + * * @var integer */ - private $port; + private int $port; /** * Username + * * @var string */ - private $user; + private string $user; /** * Password + * * @var string */ - private $pass; + private string $pass; /** * Connection timeout, in seconds. + * * @var integer */ - private $cTimeout; + private int $cTimeout; /** * Connection scheme, like tcp:// or tls:// + * * @var string */ - private $scheme; + private string $scheme; /** * Event factory. + * * @var EventFactoryImpl */ - private $eventFactory; + private EventFactoryImpl $eventFactory; /** * R/W timeout, in milliseconds. + * * @var integer */ - private $rTimeout; + private int $rTimeout; /** * Our stream socket resource. - * @var resource - */ - private $socket; - - /** - * Our stream context resource. - * @var resource + * + * @var \PAMI\Stream\Stream */ - private $context; + private Stream $stream; /** * Our event listeners - * @var IEventListener[] + * + * @var array> */ - private $eventListeners; + private array $eventListeners; /** * The receiving queue. - * @var IncomingMessage[] + * + * @var array */ - private $incomingQueue; + private array $incomingQueue; /** * Our current received message. May be incomplete, will be completed * eventually with an EOM. + * * @var string */ - private $currentProcessingMessage; + private string $currentProcessingMessage = ''; /** * This should not happen. Asterisk may send responses without a * corresponding ActionId. + * * @var string */ - private $lastActionId; + private string $lastActionId; /** * Event mask to apply on login action. + * * @var string|null */ - private $eventMask; + private ?string $eventMask; + + /** + * Constructor. + * + * @param string[] $options Options for ami client. + * + */ + public function __construct(array $options) + { + $this->logger = new NullLogger; + $this->host = $options['host'] ?? ''; + $this->port = (int)$options['port']; + $this->user = $options['username'] ?? ''; + $this->pass = $options['secret'] ?? ''; + $this->cTimeout = intval($options['connect_timeout'] ?? 60); + $this->rTimeout = intval($options['read_timeout'] ?? 60); + $this->scheme = $options['scheme'] ?? 'tcp://'; + $this->eventMask = $options['event_mask'] ?? null; + $this->eventListeners = []; + $this->eventFactory = new EventFactoryImpl(); + $this->incomingQueue = []; + $this->lastActionId = ""; + } /** * Opens a tcp connection to ami. * - * @throws \PAMI\Client\Exception\ClientException * @return void + * @throws \PAMI\Client\Exception\ClientException */ - public function open() + public function open(): void { $cString = $this->scheme . $this->host . ':' . $this->port; - $this->context = stream_context_create(); - $errno = 0; - $errstr = ''; - $this->socket = @stream_socket_client( - $cString, - $errno, - $errstr, - $this->cTimeout, - STREAM_CLIENT_CONNECT, - $this->context - ); - if ($this->socket === false) { - throw new ClientException('Error connecting to ami: ' . $errstr); + + $this->stream = $this->makeStream($cString, $this->cTimeout); + + if (!$this->stream->isConnected()) { + throw new ClientException(sprintf( + 'Error connecting to ami: (%d) %s', + $this->stream->getErrorCode(), + $this->stream->getErrorMessage() + )); } + $msg = new LoginAction($this->user, $this->pass, $this->eventMask); - $asteriskId = @stream_get_line($this->socket, 1024, Message::EOL); - if (strstr($asteriskId, 'Asterisk') === false) { + + $asteriskId = $this->stream->getLine(); + if (!$asteriskId || !str_contains($asteriskId, 'Asterisk')) { throw new ClientException( "Unknown peer. Is this an ami?: $asteriskId" ); } + $response = $this->send($msg); if (!$response->isSuccess()) { throw new ClientException( 'Could not connect: ' . $response->getMessage() ); } - @stream_set_blocking($this->socket, 0); + $this->stream->setBlocking(false); + $this->currentProcessingMessage = ''; $this->logger->debug('Logged in successfully to ami.'); } + protected function makeStream(string $address, int $timeout = null): Stream + { + return new Stream($address, $this->cTimeout); + } + /** * Registers the given listener so it can receive events. Returns the generated - * id for this new listener. You can pass in a an IEventListener, a Closure, + * id for this new listener. You can pass in an IEventListener, a Closure, * and an array containing the object and name of the method to invoke. Can specify * an optional predicate to invoke before calling the callback. * - * @param mixed $listener - * @param \Closure|null $predicate + * @param callable|\PAMI\Listener\IEventListener $listener + * @param callable|null $predicate * * @return string */ - public function registerEventListener($listener, $predicate = null) + public function registerEventListener(callable|IEventListener $listener, ?callable $predicate = null): string { $listenerId = uniqid('PamiListener'); - $this->eventListeners[$listenerId] = array($listener, $predicate); + + $this->eventListeners[$listenerId] = [$listener, $predicate]; + return $listenerId; } @@ -220,7 +262,7 @@ public function registerEventListener($listener, $predicate = null) * * @return void */ - public function unregisterEventListener($listenerId) + public function unregisterEventListener(string $listenerId): void { if (isset($this->eventListeners[$listenerId])) { unset($this->eventListeners[$listenerId]); @@ -230,66 +272,83 @@ public function unregisterEventListener($listenerId) /** * Reads a complete message over the stream until EOM. * + * @return array * @throws ClientException - * @return \string[] */ - protected function getMessages() + protected function getMessages(): array { - $msgs = array(); + static $i = 0; + + $i++; + $messages = []; + // Read something. - $read = @fread($this->socket, 65535); - if ($read === false || @feof($this->socket)) { - throw new ClientException('Error reading'); + $read = $this->stream->read(); + + if ($read === false || $this->stream->endOfFile()) { + throw new ClientException('Error reading!'); } + $this->currentProcessingMessage .= $read; + // If we have a complete message, then return it. Save the rest for // later. while (($marker = strpos($this->currentProcessingMessage, Message::EOM))) { - $msg = substr($this->currentProcessingMessage, 0, $marker); + $msg = substr($this->currentProcessingMessage, 0, $marker); $this->currentProcessingMessage = substr( $this->currentProcessingMessage, $marker + strlen(Message::EOM) ); - $msgs[] = $msg; + $messages[] = $msg; } - return $msgs; + + return $messages; } /** * Main processing loop. Also called from send(), you should call this in * your own application in order to continue reading events and responses * from ami. + * + * @throws \PAMI\Client\Exception\ClientException */ - public function process() + public function process(): void { - $msgs = $this->getMessages(); - foreach ($msgs as $aMsg) { + $messages = $this->getMessages(); + + foreach ($messages as $message) { $this->logger->debug( - '------ Received: ------ ' . "\n" . $aMsg . "\n\n" + '------ Received: ------ ' . "\n" . $message . "\n\n" ); - $resPos = strpos($aMsg, 'Response:'); - $evePos = strpos($aMsg, 'Event:'); + $resPos = strpos($message, 'Response:'); + $evePos = strpos($message, 'Event:'); if (($resPos !== false) && - (($resPos < $evePos) || $evePos === false) + (($resPos < $evePos) || $evePos === false) ) { - $response = $this->messageToResponse($aMsg); + $response = $this->messageToResponse($message); + $this->incomingQueue[$response->getActionId()] = $response; } elseif ($evePos !== false) { - $event = $this->messageToEvent($aMsg); + $event = $this->messageToEvent($message); $response = $this->findResponse($event); - if ($response === false || $response->isComplete()) { + if ($response === null || $response->isComplete()) { $this->dispatch($event); } else { $response->addEvent($event); } } else { - // broken ami.. sending a response with events without + // broken ami... sending a response with events without // Event and ActionId $bMsg = 'Event: ResponseEvent' . "\r\n"; - $bMsg .= 'ActionId: ' . $this->lastActionId . "\r\n" . $aMsg; + $bMsg .= 'ActionId: ' . $this->lastActionId . "\r\n" . $message; $event = $this->messageToEvent($bMsg); $response = $this->findResponse($event); - $response->addEvent($event); + + if ($response) { + $response->addEvent($event); + } else { + $this->logger->debug('Unable to find an associated response for the given message.'); + } } $this->logger->debug('----------------'); } @@ -300,25 +359,26 @@ public function process() * * @param IncomingMessage $message Message sent by asterisk. * - * @return \PAMI\Message\Response\ResponseMessage + * @return \PAMI\Message\Response\ResponseMessage|null */ - protected function findResponse(IncomingMessage $message) + protected function findResponse(IncomingMessage $message): ?ResponseMessage { $actionId = $message->getActionId(); if (isset($this->incomingQueue[$actionId])) { return $this->incomingQueue[$actionId]; } - return false; + + return null; } /** - * Dispatchs the incoming message to a handler. + * Dispatches the incoming message to a handler. * - * @param \PAMI\Message\IncomingMessage $message Message to dispatch. + * @param \PAMI\Message\Event\EventMessage $message Message to dispatch. * * @return void */ - protected function dispatch(IncomingMessage $message) + protected function dispatch(EventMessage $message): void { foreach ($this->eventListeners as $data) { $listener = $data[0]; @@ -326,11 +386,9 @@ protected function dispatch(IncomingMessage $message) if (is_callable($predicate) && !call_user_func($predicate, $message)) { continue; } - if ($listener instanceof \Closure) { - $listener($message); - } elseif (is_array($listener)) { - $listener[0]->{$listener[1]}($message); - } else { + if (is_callable($listener)) { + call_user_func($listener, $message); + } elseif ($listener instanceof IEventListener) { $listener->handle($message); } } @@ -343,14 +401,14 @@ protected function dispatch(IncomingMessage $message) * * @return \PAMI\Message\Response\ResponseMessage */ - private function messageToResponse($msg) + private function messageToResponse(string $msg): ResponseMessage { $response = new ResponseMessage($msg); $actionId = $response->getActionId(); - if (is_null($actionId)) { - $actionId = $this->lastActionId; + if (empty($actionId)) { $response->setActionId($this->lastActionId); } + return $response; } @@ -361,7 +419,7 @@ private function messageToResponse($msg) * * @return \PAMI\Message\Event\EventMessage */ - private function messageToEvent($msg) + private function messageToEvent(string $msg): EventMessage { return $this->eventFactory->createFromRaw($msg); } @@ -370,14 +428,16 @@ private function messageToEvent($msg) * Returns a message (response) related to the given message. This uses * the ActionID tag (key). * - * @todo not suitable for multithreaded applications. + * @param \PAMI\Message\OutgoingMessage $message * - * @return \PAMI\Message\IncomingMessage + * @return false|\PAMI\Message\Response\ResponseMessage + * @todo not suitable for multi-threaded applications. */ - protected function getRelated(OutgoingMessage $message) + protected function getRelated(OutgoingMessage $message): false|ResponseMessage { $ret = false; - $id = $message->getActionID('ActionID'); + $id = $message->getActionID(); + if (isset($this->incomingQueue[$id])) { $response = $this->incomingQueue[$id]; if ($response->isComplete()) { @@ -385,6 +445,7 @@ protected function getRelated(OutgoingMessage $message) $ret = $response; } } + return $ret; } @@ -393,11 +454,11 @@ protected function getRelated(OutgoingMessage $message) * * @param \PAMI\Message\OutgoingMessage $message Message to send. * - * @see ClientImpl::send() - * @throws \PAMI\Client\Exception\ClientException * @return \PAMI\Message\Response\ResponseMessage + * @throws \PAMI\Client\Exception\ClientException + * @see ClientImpl::send() */ - public function send(OutgoingMessage $message) + public function send(OutgoingMessage $message): ResponseMessage { $messageToSend = $message->serialize(); $length = strlen($messageToSend); @@ -405,15 +466,16 @@ public function send(OutgoingMessage $message) '------ Sending: ------ ' . "\n" . $messageToSend . '----------' ); $this->lastActionId = $message->getActionId(); - if (@fwrite($this->socket, $messageToSend) < $length) { - throw new ClientException('Could not send message'); + if ($this->stream->write($messageToSend) < $length) { + throw new ClientException('Could not send message: ' . $messageToSend); } $read = 0; while ($read <= $this->rTimeout) { $this->process(); $response = $this->getRelated($message); - if ($response != false) { - $this->lastActionId = false; + if ($response) { + $this->lastActionId = ""; + return $response; } usleep(1000); // 1ms delay @@ -421,7 +483,7 @@ public function send(OutgoingMessage $message) $read++; } } - throw new ClientException('Read timeout'); + throw new ClientException('Read timeout. Buffer: "' . $this->currentProcessingMessage . '"'); } /** @@ -429,10 +491,10 @@ public function send(OutgoingMessage $message) * * @return void */ - public function close() + public function close(): void { $this->logger->debug('Closing connection to asterisk.'); - @stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR); + $this->stream->close(); } /** @@ -442,31 +504,8 @@ public function close() * * @return void */ - public function setLogger(LoggerInterface $logger) + public function setLogger(LoggerInterface $logger): void { $this->logger = $logger; } - - /** - * Constructor. - * - * @param string[] $options Options for ami client. - * - */ - public function __construct(array $options) - { - $this->logger = new NullLogger; - $this->host = $options['host']; - $this->port = (int) $options['port']; - $this->user = $options['username']; - $this->pass = $options['secret']; - $this->cTimeout = $options['connect_timeout']; - $this->rTimeout = $options['read_timeout']; - $this->scheme = isset($options['scheme']) ? $options['scheme'] : 'tcp://'; - $this->eventMask = isset($options['event_mask']) ? $options['event_mask'] : null; - $this->eventListeners = array(); - $this->eventFactory = new EventFactoryImpl(); - $this->incomingQueue = array(); - $this->lastActionId = false; - } } diff --git a/src/PAMI/Helpers/helpers.php b/src/PAMI/Helpers/helpers.php new file mode 100644 index 000000000..a370bb8ed --- /dev/null +++ b/src/PAMI/Helpers/helpers.php @@ -0,0 +1,55 @@ +setKey('Action', $what); - $this->setKey('ActionID', microtime(true)); + $this->setKey('ActionID', \getMicroTime()); } /** @@ -64,14 +65,14 @@ public function __construct($what) * The ActionID can be at most 69 characters long, according to * {@link https://issues.asterisk.org/jira/browse/14847 Asterisk Issue 14847}. * - * Therefore we'll throw an exception when the ActionID is too long. + * Therefore, we'll throw an exception when the ActionID is too long. * - * @param $actionID The Action ID to have this action known by + * @param string $actionID The Action ID to have this action known by * * @return void - * @throws PAMIException When the ActionID is more then 69 characters long + * @throws PAMIException When the ActionID is more than 69 characters long */ - public function setActionID($actionID) + public function setActionID($actionID): void { if (0 == strlen($actionID)) { throw new PAMIException('ActionID cannot be empty.'); diff --git a/src/PAMI/Message/Action/AgentLogoffAction.php b/src/PAMI/Message/Action/AgentLogoffAction.php index caa8821c7..2d82a6975 100644 --- a/src/PAMI/Message/Action/AgentLogoffAction.php +++ b/src/PAMI/Message/Action/AgentLogoffAction.php @@ -27,6 +27,7 @@ * limitations under the License. * */ + namespace PAMI\Message\Action; /** @@ -47,7 +48,7 @@ class AgentLogoffAction extends ActionMessage * Constructor. * * @param string $agent Agent ID of the agent to log off. - * @param string $soft Set to true to not hangup existing calls. + * @param bool $soft Set to true to not hangup existing calls. * * @return void */ diff --git a/src/PAMI/Message/Action/BridgeAction.php b/src/PAMI/Message/Action/BridgeAction.php index 43cd3b79a..7c23d6326 100644 --- a/src/PAMI/Message/Action/BridgeAction.php +++ b/src/PAMI/Message/Action/BridgeAction.php @@ -27,6 +27,7 @@ * limitations under the License. * */ + namespace PAMI\Message\Action; /** @@ -46,9 +47,9 @@ class BridgeAction extends ActionMessage /** * Constructor. * - * @param string $channel1 Channel1 - * @param string $channel1 Channel1 - * @param boolean $tone Play courtesy tone to Channel2 + * @param string $channel1 Channel1 + * @param string $channel2 Channel2 + * @param bool $tone Play courtesy tone to Channel2 * * @return void */ diff --git a/src/PAMI/Message/Action/DAHDIDialOffHookAction.php b/src/PAMI/Message/Action/DAHDIDialOffHookAction.php index c952ff1a3..bad759e4f 100644 --- a/src/PAMI/Message/Action/DAHDIDialOffHookAction.php +++ b/src/PAMI/Message/Action/DAHDIDialOffHookAction.php @@ -27,6 +27,7 @@ * limitations under the License. * */ + namespace PAMI\Message\Action; /** @@ -46,7 +47,8 @@ class DAHDIDialOffHookAction extends ActionMessage /** * Constructor. * - * @return void + * @param string $channel + * @param string $number */ public function __construct($channel, $number) { diff --git a/src/PAMI/Message/Action/DBDelTreeAction.php b/src/PAMI/Message/Action/DBDelTreeAction.php index a4d2f43db..19a827be0 100644 --- a/src/PAMI/Message/Action/DBDelTreeAction.php +++ b/src/PAMI/Message/Action/DBDelTreeAction.php @@ -27,6 +27,7 @@ * limitations under the License. * */ + namespace PAMI\Message\Action; /** @@ -46,8 +47,8 @@ class DBDelTreeAction extends ActionMessage /** * Constructor. * - * @param string $family Family. - * @param string $key Name (optional) + * @param string $family Family. + * @param string|bool $key Name (optional) * * @return void */ diff --git a/src/PAMI/Message/Action/DongleShowDevicesAction.php b/src/PAMI/Message/Action/DongleShowDevicesAction.php index 6f642c404..ec6d52ba0 100644 --- a/src/PAMI/Message/Action/DongleShowDevicesAction.php +++ b/src/PAMI/Message/Action/DongleShowDevicesAction.php @@ -46,11 +46,6 @@ class DongleShowDevicesAction extends ActionMessage /** * Constructor. * - * @param string $device Device name (like dongle01). - * @param string $number Destination number. - * @param string $message What to send. - * - * @return void */ public function __construct() { diff --git a/src/PAMI/Message/Action/GetConfigAction.php b/src/PAMI/Message/Action/GetConfigAction.php index 327389668..1f0938b25 100644 --- a/src/PAMI/Message/Action/GetConfigAction.php +++ b/src/PAMI/Message/Action/GetConfigAction.php @@ -27,6 +27,7 @@ * limitations under the License. * */ + namespace PAMI\Message\Action; /** @@ -46,8 +47,8 @@ class GetConfigAction extends ActionMessage /** * Constructor. * - * @param string $filename Configuration filename (e.g.: foo.conf). - * @param boolean $category Category in configuration file. + * @param string $filename Configuration filename (e.g.: foo.conf). + * @param string|bool $category Category in configuration file. * * @return void */ diff --git a/src/PAMI/Message/Action/GetVarAction.php b/src/PAMI/Message/Action/GetVarAction.php index dbf4620e4..227bfc34f 100644 --- a/src/PAMI/Message/Action/GetVarAction.php +++ b/src/PAMI/Message/Action/GetVarAction.php @@ -27,6 +27,7 @@ * limitations under the License. * */ + namespace PAMI\Message\Action; /** @@ -46,8 +47,8 @@ class GetVarAction extends ActionMessage /** * Constructor. * - * @param string $name Variable name. - * @param string $channel Optional channel name. + * @param string $name Variable name. + * @param string|bool $channel Optional channel name. * * @return void */ diff --git a/src/PAMI/Message/Action/OriginateAction.php b/src/PAMI/Message/Action/OriginateAction.php index 27de4057b..59ab301a0 100644 --- a/src/PAMI/Message/Action/OriginateAction.php +++ b/src/PAMI/Message/Action/OriginateAction.php @@ -106,7 +106,7 @@ public function setData($data) /** * Sets Timeout key. * - * @param integer $timeout How long to wait for call to be answered (in ms). + * @param integer|string $timeout How long to wait for call to be answered (in ms). * * @return void */ @@ -130,7 +130,7 @@ public function setCallerId($clid) /** * Sets Account key. * - * @param string Account code. + * @param string $account Account code. * * @return void */ @@ -142,7 +142,7 @@ public function setAccount($account) /** * Sets Async key. * - * @param boolean $async Set to true for fast origination. + * @param bool $async Set to true for fast origination. * * @return void */ diff --git a/src/PAMI/Message/Action/ParkAction.php b/src/PAMI/Message/Action/ParkAction.php index abb7444c4..1ff333555 100644 --- a/src/PAMI/Message/Action/ParkAction.php +++ b/src/PAMI/Message/Action/ParkAction.php @@ -48,8 +48,8 @@ class ParkAction extends ActionMessage * * @param string $channel1 Channel name to park. * @param string $channel2 Channel to announce park info to (and return to if timeout). - * @param integer $timeout Number of milliseconds to wait before callback. - * @param string $lot Parking lot to park channel in. + * @param integer|false $timeout Number of milliseconds to wait before callback. + * @param string|false $lot Parking lot to park channel in. * * @return void */ diff --git a/src/PAMI/Message/Action/PlayDTMFAction.php b/src/PAMI/Message/Action/PlayDTMFAction.php index 62891651a..bf935c067 100644 --- a/src/PAMI/Message/Action/PlayDTMFAction.php +++ b/src/PAMI/Message/Action/PlayDTMFAction.php @@ -27,6 +27,7 @@ * limitations under the License. * */ + namespace PAMI\Message\Action; /** @@ -46,10 +47,8 @@ class PlayDTMFAction extends ActionMessage /** * Constructor. * - * @param string $user AMI username. - * @param string $password AMI password. - * - * @return void + * @param string $channel + * @param string|int $digit */ public function __construct($channel, $digit) { diff --git a/src/PAMI/Message/Action/QueuePauseAction.php b/src/PAMI/Message/Action/QueuePauseAction.php index 48524569d..18cdfcc35 100644 --- a/src/PAMI/Message/Action/QueuePauseAction.php +++ b/src/PAMI/Message/Action/QueuePauseAction.php @@ -46,7 +46,9 @@ class QueuePauseAction extends ActionMessage /** * Constructor. * - * @return void + * @param string $interface + * @param bool|string $queue + * @param bool|string $reason */ public function __construct($interface, $queue = false, $reason = false) { diff --git a/src/PAMI/Message/Action/QueuePenaltyAction.php b/src/PAMI/Message/Action/QueuePenaltyAction.php index 6dae34e49..5734b71b2 100644 --- a/src/PAMI/Message/Action/QueuePenaltyAction.php +++ b/src/PAMI/Message/Action/QueuePenaltyAction.php @@ -27,6 +27,7 @@ * limitations under the License. * */ + namespace PAMI\Message\Action; /** @@ -46,10 +47,9 @@ class QueuePenaltyAction extends ActionMessage /** * Constructor. * - * @param string $queue Queue name. - * @param string $event Event. - * - * @return void + * @param string $interface + * @param string|bool $penalty + * @param string|bool $queue */ public function __construct($interface, $penalty, $queue = false) { diff --git a/src/PAMI/Message/Action/QueueReloadAction.php b/src/PAMI/Message/Action/QueueReloadAction.php index f2fb21072..29a2b9072 100644 --- a/src/PAMI/Message/Action/QueueReloadAction.php +++ b/src/PAMI/Message/Action/QueueReloadAction.php @@ -27,6 +27,7 @@ * limitations under the License. * */ + namespace PAMI\Message\Action; /** @@ -46,10 +47,10 @@ class QueueReloadAction extends ActionMessage /** * Constructor. * - * @param string $queue Queue name. - * @param boolean $members Reload members. - * @param boolean $rules Reload rules. - * @param boolean $parameters Reload parameters. + * @param string|false $queue Queue name. + * @param bool $members Reload members. + * @param bool $rules Reload rules. + * @param bool $parameters Reload parameters. * * @return void */ diff --git a/src/PAMI/Message/Action/QueueResetAction.php b/src/PAMI/Message/Action/QueueResetAction.php index 5028ae77f..fdb730449 100644 --- a/src/PAMI/Message/Action/QueueResetAction.php +++ b/src/PAMI/Message/Action/QueueResetAction.php @@ -46,7 +46,7 @@ class QueueResetAction extends ActionMessage /** * Constructor. * - * @param string $queue Queue name. + * @param string|false $queue Queue name. * * @return void */ diff --git a/src/PAMI/Message/Action/QueueRuleAction.php b/src/PAMI/Message/Action/QueueRuleAction.php index 2aa1d4668..e97ca5cfc 100644 --- a/src/PAMI/Message/Action/QueueRuleAction.php +++ b/src/PAMI/Message/Action/QueueRuleAction.php @@ -46,7 +46,7 @@ class QueueRuleAction extends ActionMessage /** * Constructor. * - * @param string $rule Rule. + * @param string|false $rule Rule. * * @return void */ diff --git a/src/PAMI/Message/Action/QueueStatusAction.php b/src/PAMI/Message/Action/QueueStatusAction.php index 72865643c..5391e0838 100644 --- a/src/PAMI/Message/Action/QueueStatusAction.php +++ b/src/PAMI/Message/Action/QueueStatusAction.php @@ -27,6 +27,7 @@ * limitations under the License. * */ + namespace PAMI\Message\Action; /** @@ -46,7 +47,8 @@ class QueueStatusAction extends ActionMessage /** * Constructor. * - * @param string $queue The queue (optional). + * @param string|false $queue The queue (optional). + * @param string|false $member * * @return void */ diff --git a/src/PAMI/Message/Action/QueueSummaryAction.php b/src/PAMI/Message/Action/QueueSummaryAction.php index f990c4700..dc6ded379 100644 --- a/src/PAMI/Message/Action/QueueSummaryAction.php +++ b/src/PAMI/Message/Action/QueueSummaryAction.php @@ -46,7 +46,7 @@ class QueueSummaryAction extends ActionMessage /** * Constructor. * - * @param string $queue The queue (optional). + * @param string|false $queue The queue (optional). * * @return void */ diff --git a/src/PAMI/Message/Action/QueueUnpauseAction.php b/src/PAMI/Message/Action/QueueUnpauseAction.php index c91329715..f555591d8 100644 --- a/src/PAMI/Message/Action/QueueUnpauseAction.php +++ b/src/PAMI/Message/Action/QueueUnpauseAction.php @@ -27,6 +27,7 @@ * limitations under the License. * */ + namespace PAMI\Message\Action; /** @@ -46,7 +47,9 @@ class QueueUnpauseAction extends ActionMessage /** * Constructor. * - * @return void + * @param string $interface + * @param bool|string $queue + * @param bool|string $reason */ public function __construct($interface, $queue = false, $reason = false) { diff --git a/src/PAMI/Message/Action/ReloadAction.php b/src/PAMI/Message/Action/ReloadAction.php index 112e6e4c1..56eff55b7 100644 --- a/src/PAMI/Message/Action/ReloadAction.php +++ b/src/PAMI/Message/Action/ReloadAction.php @@ -46,7 +46,7 @@ class ReloadAction extends ActionMessage /** * Constructor. * - * @param string $module Optional module name. + * @param string|bool $module Optional module name. * * @return void */ diff --git a/src/PAMI/Message/Action/SetVarAction.php b/src/PAMI/Message/Action/SetVarAction.php index f8a2caf79..090a28c04 100644 --- a/src/PAMI/Message/Action/SetVarAction.php +++ b/src/PAMI/Message/Action/SetVarAction.php @@ -48,7 +48,7 @@ class SetVarAction extends ActionMessage * * @param string $name Variable name. * @param string $value Variable value. - * @param string $channel Optional channel name. + * @param string|bool $channel Optional channel name. * * @return void */ diff --git a/src/PAMI/Message/Action/ShowDialPlanAction.php b/src/PAMI/Message/Action/ShowDialPlanAction.php index 155b7df1e..1c2ccbd22 100644 --- a/src/PAMI/Message/Action/ShowDialPlanAction.php +++ b/src/PAMI/Message/Action/ShowDialPlanAction.php @@ -46,8 +46,8 @@ class ShowDialPlanAction extends ActionMessage /** * Constructor. * - * @param string $context Show a specific context (optional) - * @param string $extension Show a specific extension (optional) + * @param string|bool $context Show a specific context (optional) + * @param string|bool $extension Show a specific extension (optional) * * @return void */ diff --git a/src/PAMI/Message/Action/StatusAction.php b/src/PAMI/Message/Action/StatusAction.php index fe7d33bf9..ec6d3cdb8 100644 --- a/src/PAMI/Message/Action/StatusAction.php +++ b/src/PAMI/Message/Action/StatusAction.php @@ -46,7 +46,7 @@ class StatusAction extends ActionMessage /** * Constructor. * - * @param string $channel Channel to query (optional) + * @param string|bool $channel Channel to query (optional) * * @return void */ diff --git a/src/PAMI/Message/Action/UpdateConfigAction.php b/src/PAMI/Message/Action/UpdateConfigAction.php index 221a85a35..b38a4ec75 100644 --- a/src/PAMI/Message/Action/UpdateConfigAction.php +++ b/src/PAMI/Message/Action/UpdateConfigAction.php @@ -43,6 +43,9 @@ */ class UpdateConfigAction extends ActionMessage { + /** + * @var int + */ protected static $counter = -1; /** @@ -80,10 +83,10 @@ public function setDstFilename($filename) $this->setKey('DstFilename', $filename); } - /** + /** * Sets Reload key. * - * @param string $input. + * @param bool $reload * * @return void */ @@ -109,7 +112,7 @@ public function setAction($input) /** * Sets Cat-XXXXXX key. * - * @param string $cat. + * @param string|int $input * * @return void */ @@ -173,6 +176,6 @@ public function setLine($input) */ protected function getPaddedCounter() { - return str_pad(UpdateConfigAction::$counter, 6, '0', STR_PAD_LEFT); + return str_pad((string)UpdateConfigAction::$counter, 6, '0', STR_PAD_LEFT); } } diff --git a/src/PAMI/Message/Action/UserEventAction.php b/src/PAMI/Message/Action/UserEventAction.php index 1e2879521..a1a46cf78 100644 --- a/src/PAMI/Message/Action/UserEventAction.php +++ b/src/PAMI/Message/Action/UserEventAction.php @@ -47,7 +47,7 @@ class UserEventAction extends ActionMessage * Constructor. * * @param string $userEvent UserEvent - * @param array $headers + * @param array $headers */ public function __construct($userEvent, array $headers = []) { diff --git a/src/PAMI/Message/Action/VGSMSMSTxAction.php b/src/PAMI/Message/Action/VGSMSMSTxAction.php index 2a9d208d6..b457ab0b9 100644 --- a/src/PAMI/Message/Action/VGSMSMSTxAction.php +++ b/src/PAMI/Message/Action/VGSMSMSTxAction.php @@ -109,7 +109,7 @@ public function setContent($content) /** * Sets X-SMS-Class key. Optional * - * @param string $sms_class Class of SMS to send. Values are 0, 1. 0 is Flash message. + * @param string $class Class of SMS to send. Values are 0, 1. 0 is Flash message. * * @return void */ @@ -118,11 +118,12 @@ public function setSmsClass($class) $this->setKey('X-SMS-Class', $class); } - /** * Sets X-SMS-Concatenate-RefID . Optional. Should be set with * setConcatSeqNum and setConcatSeqNum * + * @param string|int $refid + * * @return void */ public function setConcatRefId($refid) @@ -134,6 +135,8 @@ public function setConcatRefId($refid) * Sets X-SMS-Concatenate-Sequence-Number. Optional. Should be set with * setConcatSeqNum: setConcatTotalMsg * + * @param string $seqnum + * * @return void */ public function setConcatSeqNum($seqnum) @@ -145,6 +148,8 @@ public function setConcatSeqNum($seqnum) * Sets X-SMS-Concatenate-Total-Messages. Optional. Should be set with * setConcatRefId and setConcatSeqNum * + * @param string|int $totalmsg + * * @return void */ public function setConcatTotalMsg($totalmsg) @@ -155,7 +160,7 @@ public function setConcatTotalMsg($totalmsg) /** * Sets Account key. * - * @param string Account code. + * @param string $account Account code. * * @return void */ diff --git a/src/PAMI/Message/Event/AgentlogoffEvent.php b/src/PAMI/Message/Event/AgentlogoffEvent.php index 5c0d2f586..59c95c591 100644 --- a/src/PAMI/Message/Event/AgentlogoffEvent.php +++ b/src/PAMI/Message/Event/AgentlogoffEvent.php @@ -29,8 +29,6 @@ */ namespace PAMI\Message\Event; -use PAMI\Message\Event\EventMessage; - /** * Event triggered when an agent logs off. * @@ -78,7 +76,7 @@ public function getUniqueID() /** * Returns key: 'Logintime'. * - * @return integer + * @return string */ public function getLogintime() { diff --git a/src/PAMI/Message/Event/AgentsEvent.php b/src/PAMI/Message/Event/AgentsEvent.php index 24d404ad6..4671fc96d 100644 --- a/src/PAMI/Message/Event/AgentsEvent.php +++ b/src/PAMI/Message/Event/AgentsEvent.php @@ -29,8 +29,6 @@ */ namespace PAMI\Message\Event; -use PAMI\Message\Event\EventMessage; - /** * Event triggered for agents. * @@ -88,7 +86,7 @@ public function getChannel() /** * Returns key: 'LoggedInTime'. * - * @return integer + * @return string */ public function getLoggedInTime() { @@ -98,7 +96,7 @@ public function getLoggedInTime() /** * Returns key: 'TalkingTo'. * - * @return integer + * @return string */ public function getTalkingTo() { @@ -108,7 +106,7 @@ public function getTalkingTo() /** * Returns key: 'TalkingToChannel'. * - * @return integer + * @return string */ public function getTalkingToChannel() { diff --git a/src/PAMI/Message/Event/EventMessage.php b/src/PAMI/Message/Event/EventMessage.php index 182502b3f..2b0fddc1b 100644 --- a/src/PAMI/Message/Event/EventMessage.php +++ b/src/PAMI/Message/Event/EventMessage.php @@ -52,6 +52,6 @@ abstract class EventMessage extends IncomingMessage */ public function getName() { - return $this->getKey('Event'); + return $this->getKey('Event') ?? ''; } } diff --git a/src/PAMI/Message/Event/Factory/Impl/EventFactoryImpl.php b/src/PAMI/Message/Event/Factory/Impl/EventFactoryImpl.php index 4b9cf32a7..4f9b6afb0 100644 --- a/src/PAMI/Message/Event/Factory/Impl/EventFactoryImpl.php +++ b/src/PAMI/Message/Event/Factory/Impl/EventFactoryImpl.php @@ -30,9 +30,9 @@ */ namespace PAMI\Message\Event\Factory\Impl; -use PAMI\Message\Event\EventMessage; -use PAMI\Message\Event\UnknownEvent; use PAMI\Message\Message; +use PAMI\Message\Event\UnknownEvent; +use PAMI\Message\Event\EventMessage; /** * This factory knows which event to return according to a given raw message @@ -52,11 +52,11 @@ class EventFactoryImpl /** * This is our factory method. * - * @param string $message Literall message as received from ami. + * @param string $message Literal message as received from ami. * * @return EventMessage */ - public static function createFromRaw($message) + public static function createFromRaw(string $message): EventMessage { $eventStart = strpos($message, 'Event: ') + 7; $eventEnd = strpos($message, Message::EOL, $eventStart); diff --git a/src/PAMI/Message/Event/ListDialplanEvent.php b/src/PAMI/Message/Event/ListDialplanEvent.php index 025d310a2..b9f36855d 100644 --- a/src/PAMI/Message/Event/ListDialplanEvent.php +++ b/src/PAMI/Message/Event/ListDialplanEvent.php @@ -29,8 +29,6 @@ */ namespace PAMI\Message\Event; -use PAMI\Message\Event\EventMessage; - /** * Event triggered when an action ShowDialPlan is issued. * @@ -43,7 +41,7 @@ * @license http://marcelog.github.com/PAMI/ Apache License 2.0 * @link http://marcelog.github.com/PAMI/ */ -class ListDialPlanEvent extends EventMessage +class ListDialplanEvent extends EventMessage { /** * Returns key: 'Context'. diff --git a/src/PAMI/Message/Event/OriginateResponseEvent.php b/src/PAMI/Message/Event/OriginateResponseEvent.php index 0634401f8..7b881c8fa 100644 --- a/src/PAMI/Message/Event/OriginateResponseEvent.php +++ b/src/PAMI/Message/Event/OriginateResponseEvent.php @@ -29,8 +29,6 @@ */ namespace PAMI\Message\Event; -use PAMI\Message\Event\EventMessage; - /** * Response from an async originate. * @@ -110,7 +108,7 @@ public function getUniqueID() * * @return string */ - public function getActionID() + public function getActionID(): string { return $this->getKey('ActionID'); } diff --git a/src/PAMI/Message/Event/QueueMemberAddedEvent.php b/src/PAMI/Message/Event/QueueMemberAddedEvent.php index 394663923..6b627fddc 100644 --- a/src/PAMI/Message/Event/QueueMemberAddedEvent.php +++ b/src/PAMI/Message/Event/QueueMemberAddedEvent.php @@ -29,8 +29,6 @@ */ namespace PAMI\Message\Event; -use PAMI\Message\Event\EventMessage; - /** * Event triggered for a QueueMemberAdd action. * @@ -98,7 +96,7 @@ public function getMembership() /** * Returns key: 'Penalty'. * - * @return integer + * @return string */ public function getPenalty() { @@ -108,7 +106,7 @@ public function getPenalty() /** * Returns key: 'CallsTaken'. * - * @return integer + * @return string */ public function getCallsTaken() { @@ -118,7 +116,7 @@ public function getCallsTaken() /** * Returns key: 'LastCall'. * - * @return integer + * @return string */ public function getLastCall() { @@ -128,7 +126,7 @@ public function getLastCall() /** * Returns key: 'Status'. * - * @return integer + * @return string */ public function getStatus() { @@ -138,7 +136,7 @@ public function getStatus() /** * Returns key: 'Pause'. * - * @return boolean + * @return bool */ public function getPaused() { diff --git a/src/PAMI/Message/Event/QueueMemberEvent.php b/src/PAMI/Message/Event/QueueMemberEvent.php index bea6bc714..7404f4a95 100644 --- a/src/PAMI/Message/Event/QueueMemberEvent.php +++ b/src/PAMI/Message/Event/QueueMemberEvent.php @@ -29,8 +29,6 @@ */ namespace PAMI\Message\Event; -use PAMI\Message\Event\EventMessage; - /** * Event triggered for a QueueStatus action. * @@ -88,7 +86,7 @@ public function getMembership() /** * Returns key: 'Penalty'. * - * @return integer + * @return string */ public function getPenalty() { @@ -98,7 +96,7 @@ public function getPenalty() /** * Returns key: 'CallsTaken'. * - * @return integer + * @return string */ public function getCallsTaken() { @@ -108,7 +106,7 @@ public function getCallsTaken() /** * Returns key: 'Status'. * - * @return integer + * @return string */ public function getStatus() { @@ -118,7 +116,7 @@ public function getStatus() /** * Returns key: 'Pause'. * - * @return boolean + * @return bool */ public function getPaused() { diff --git a/src/PAMI/Message/Event/QueueMemberPausedEvent.php b/src/PAMI/Message/Event/QueueMemberPausedEvent.php index 3e54467b2..dde4376a0 100644 --- a/src/PAMI/Message/Event/QueueMemberPausedEvent.php +++ b/src/PAMI/Message/Event/QueueMemberPausedEvent.php @@ -29,8 +29,6 @@ */ namespace PAMI\Message\Event; -use PAMI\Message\Event\EventMessage; - /** * Event triggered for a change in a queue member (pause/unpause). * @@ -88,7 +86,7 @@ public function getMemberName() /** * Returns key: 'Paused'. * - * @return boolean + * @return bool */ public function getPaused() { diff --git a/src/PAMI/Message/Event/QueueMemberStatusEvent.php b/src/PAMI/Message/Event/QueueMemberStatusEvent.php index eb8e6c163..a45ab0838 100644 --- a/src/PAMI/Message/Event/QueueMemberStatusEvent.php +++ b/src/PAMI/Message/Event/QueueMemberStatusEvent.php @@ -29,8 +29,6 @@ */ namespace PAMI\Message\Event; -use PAMI\Message\Event\EventMessage; - /** * Event triggered for a status change in a queue. * @@ -98,7 +96,7 @@ public function getMembership() /** * Returns key: 'Penalty'. * - * @return integer + * @return string */ public function getPenalty() { @@ -108,7 +106,7 @@ public function getPenalty() /** * Returns key: 'CallsTaken'. * - * @return integer + * @return string */ public function getCallsTaken() { @@ -118,7 +116,7 @@ public function getCallsTaken() /** * Returns key: 'Status'. * - * @return integer + * @return string */ public function getStatus() { @@ -128,7 +126,7 @@ public function getStatus() /** * Returns key: 'Paused'. * - * @return boolean + * @return bool */ public function getPause() { diff --git a/src/PAMI/Message/Event/QueueParamsEvent.php b/src/PAMI/Message/Event/QueueParamsEvent.php index 8fdc6f45a..b839c2e06 100644 --- a/src/PAMI/Message/Event/QueueParamsEvent.php +++ b/src/PAMI/Message/Event/QueueParamsEvent.php @@ -29,8 +29,6 @@ */ namespace PAMI\Message\Event; -use PAMI\Message\Event\EventMessage; - /** * Event triggered for a QueueStatus action. * @@ -128,7 +126,7 @@ public function getServiceLevel() /** * Returns key: 'ServiceLevelPerf'. * - * @return float + * @return string */ public function getServiceLevelPerf() { diff --git a/src/PAMI/Message/Event/QueueSummaryEvent.php b/src/PAMI/Message/Event/QueueSummaryEvent.php index 2b8b54bd2..8c9bdfa38 100644 --- a/src/PAMI/Message/Event/QueueSummaryEvent.php +++ b/src/PAMI/Message/Event/QueueSummaryEvent.php @@ -29,8 +29,6 @@ */ namespace PAMI\Message\Event; -use PAMI\Message\Event\EventMessage; - /** * Event triggered for a QueueSummary action. * @@ -88,7 +86,7 @@ public function getCallers() /** * Returns key: 'HoldTime'. * - * @return integer + * @return string */ public function getHoldTime() { @@ -98,7 +96,7 @@ public function getHoldTime() /** * Returns key: 'LongestHoldTime'. * - * @return integer + * @return string */ public function getLongestHoldTime() { diff --git a/src/PAMI/Message/IncomingMessage.php b/src/PAMI/Message/IncomingMessage.php index 896df6601..c49c4c031 100644 --- a/src/PAMI/Message/IncomingMessage.php +++ b/src/PAMI/Message/IncomingMessage.php @@ -26,6 +26,7 @@ * limitations under the License. * */ + namespace PAMI\Message; /** @@ -43,37 +44,40 @@ abstract class IncomingMessage extends Message { /** * Holds original message. + * * @var string */ - protected $rawContent; + protected string $rawContent; /** * Metadata. Specific channel variables. - * @var string[] + * + * @var array */ - protected $channelVariables; + protected array $channelVariables; /** * Serialize function. * - * @return string[] + * @return array */ public function __sleep() { $ret = parent::__sleep(); $ret[] = 'rawContent'; + return $ret; } /** - * Returns key 'EventList'. In respones, this will surely be a "start". In + * Returns key 'EventList'. In responses, this will surely be a "start". In * events, should be a "complete". * * @return string */ - public function getEventList() + public function getEventList(): string { - return $this->getKey('EventList'); + return $this->getKey('EventList') ?? ''; } /** @@ -81,7 +85,7 @@ public function getEventList() * * @return string */ - public function getRawContent() + public function getRawContent(): string { return $this->rawContent; } @@ -90,11 +94,11 @@ public function getRawContent() * Returns the channel variables for all reported channels. * https://github.com/marcelog/PAMI/issues/85 * - * The channel names will be lowercased. + * The channel names will be lower-cased. * - * @return array + * @return array */ - public function getAllChannelVariables() + public function getAllChannelVariables(): array { return $this->channelVariables; } @@ -103,12 +107,12 @@ public function getAllChannelVariables() * Returns the channel variables for the given channel. * https://github.com/marcelog/PAMI/issues/85 * - * @param string $channel Channel name. If not given, will return variables - * for the "current" channel. + * @param string|null $channel Channel name. If not given, will return variables + * for the "current" channel. * - * @return array + * @return array|null */ - public function getChannelVariables($channel = null) + public function getChannelVariables(string $channel = null): ?array { if (is_null($channel)) { if (!isset($this->keys['channel'])) { @@ -121,6 +125,7 @@ public function getChannelVariables($channel = null) if (!isset($this->channelVariables[$channel])) { return null; } + return $this->channelVariables[$channel]; } } @@ -132,26 +137,29 @@ public function getChannelVariables($channel = null) * * @return void */ - public function __construct($rawContent) + public function __construct(string $rawContent) { parent::__construct(); - $this->channelVariables = array('default' => array()); + $this->channelVariables = ['default' => []]; + $this->rawContent = $rawContent; - $lines = explode(Message::EOL, $rawContent); + $lines = explode(Message::EOL, $rawContent); + foreach ($lines as $line) { $content = explode(':', $line); - $name = strtolower(trim($content[0])); + $name = strtolower(trim($content[0])); unset($content[0]); $value = isset($content[1]) ? trim(implode(':', $content)) : ''; + if (!strncmp($name, 'chanvariable', 12)) { // https://github.com/marcelog/PAMI/issues/85 - $matches = preg_match("/\(([^\)]*)\)/", $name, $captures); + $matches = preg_match("/\(([^)]*)\)/", $name, $captures); $chanName = 'default'; if ($matches > 0) { $chanName = $captures[1]; } $content = explode('=', $value); - $name = strtolower(trim($content[0])); + $name = strtolower(trim($content[0])); unset($content[0]); $value = isset($content[1]) ? trim(implode(':', $content)) : ''; $this->channelVariables[$chanName][$name] = $value; diff --git a/src/PAMI/Message/Message.php b/src/PAMI/Message/Message.php index bc8ed5317..80ff77d5a 100644 --- a/src/PAMI/Message/Message.php +++ b/src/PAMI/Message/Message.php @@ -26,6 +26,7 @@ * limitations under the License. * */ + namespace PAMI\Message; /** @@ -43,12 +44,13 @@ abstract class Message { /** * End Of Line means this token. + * * @var string */ const EOL = "\r\n"; - /** * End Of Message means this token. + * * @var string */ const EOM = "\r\n\r\n"; @@ -56,36 +58,40 @@ abstract class Message /** * Message content, line by line. This is what it gets sent * or received literally. + * * @var string[] */ - protected $lines; + protected array $lines; /** * Metadata. Message variables (key/value). + * * @var string[] */ - protected $variables; + protected array $variables; /** * Metadata. Message "keys" i.e: Action: login - * @var string[] + * + * @var array */ - protected $keys; + protected array $keys; /** * Created date (unix timestamp). + * * @var integer */ - protected $createdDate; + protected int $createdDate; /** * Serialize function. * - * @return string[] + * @return array */ public function __sleep() { - return array('lines', 'variables', 'keys', 'createdDate'); + return ['lines', 'variables', 'keys', 'createdDate']; } /** @@ -93,7 +99,7 @@ public function __sleep() * * @return integer */ - public function getCreatedDate() + public function getCreatedDate(): int { return $this->createdDate; } @@ -102,11 +108,11 @@ public function getCreatedDate() * Adds a variable to this message. * * @param string $key Variable name. - * @param string $value Variable value. + * @param mixed $value Variable value. * * @return void */ - public function setVariable($key, $value) + public function setVariable(string $key, mixed $value): void { $this->variables[$key] = $value; } @@ -116,28 +122,29 @@ public function setVariable($key, $value) * * @param string $key Variable name. * - * @return string + * @return mixed */ - public function getVariable($key) + public function getVariable(string $key): mixed { if (!isset($this->variables[$key])) { return null; } + return $this->variables[$key]; } /** * Adds a variable to this message. * - * @param string $key Key name (i.e: Action). - * @param string $value Key value. + * @param string $key Key name (i.e: Action). + * @param string|int|bool $value Key value. * * @return void */ - protected function setKey($key, $value) + protected function setKey(string $key, string|int|bool $value): void { - $key = strtolower((string)$key); - $this->keys[$key] = (string)$value; + $key = strtolower($key); + $this->keys[$key] = $value; } /** @@ -145,23 +152,24 @@ protected function setKey($key, $value) * * @param string $key Key name (i.e: Action). * - * @return string + * @return string|int|bool|null */ - public function getKey($key) + public function getKey(string $key): string|int|bool|null { $key = strtolower($key); if (!isset($this->keys[$key])) { return null; } + return (string)$this->keys[$key]; } /** * Returns all keys for this message. * - * @return string[] + * @return array */ - public function getKeys() + public function getKeys(): array { return $this->keys; } @@ -169,9 +177,9 @@ public function getKeys() /** * Returns all variabels for this message. * - * @return string[] + * @return array */ - public function getVariables() + public function getVariables(): array { return $this->variables; } @@ -179,9 +187,11 @@ public function getVariables() /** * Returns the end of message token appended to the end of a given message. * + * @param string $message + * * @return string */ - protected function finishMessage($message) + protected function finishMessage(string $message): string { return $message . self::EOL . self::EOL; } @@ -194,7 +204,7 @@ protected function finishMessage($message) * * @return string */ - private function serializeVariable($key, $value) + private function serializeVariable(string $key, string $value): string { return "Variable: $key=$value"; } @@ -205,9 +215,9 @@ private function serializeVariable($key, $value) * * @return string */ - public function serialize() + public function serialize(): string { - $result = array(); + $result = []; foreach ($this->getKeys() as $k => $v) { $result[] = $k . ': ' . $v; } @@ -220,8 +230,8 @@ public function serialize() $result[] = $this->serializeVariable($k, $v); } } - $mStr = $this->finishMessage(implode(self::EOL, $result)); - return $mStr; + + return $this->finishMessage(implode(self::EOL, $result)); } /** @@ -229,9 +239,9 @@ public function serialize() * * @return string */ - public function getActionID() + public function getActionID(): string { - return $this->getKey('ActionID'); + return $this->getKey('ActionID') ?? ''; } /** @@ -241,9 +251,9 @@ public function getActionID() */ public function __construct() { - $this->lines = array(); - $this->variables = array(); - $this->keys = array(); - $this->createdDate = time(); + $this->lines = []; + $this->variables = []; + $this->keys = []; + $this->createdDate = getTime(); } } diff --git a/src/PAMI/Message/Response/ResponseMessage.php b/src/PAMI/Message/Response/ResponseMessage.php index 0cb7110fe..388b2caf2 100644 --- a/src/PAMI/Message/Response/ResponseMessage.php +++ b/src/PAMI/Message/Response/ResponseMessage.php @@ -27,9 +27,9 @@ * limitations under the License. * */ + namespace PAMI\Message\Response; -use PAMI\Message\Message; use PAMI\Message\IncomingMessage; use PAMI\Message\Event\EventMessage; @@ -49,15 +49,17 @@ class ResponseMessage extends IncomingMessage { /** * Child events. - * @var EventMessage[] + * + * @var array */ - private $events; + private array $events; /** * Is this response completed? (with all its events). - * @var boolean + * + * @var bool */ - private $completed; + private bool $completed; /** * Serialize function. @@ -69,6 +71,7 @@ public function __sleep() $ret = parent::__sleep(); $ret[] = 'completed'; $ret[] = 'events'; + return $ret; } @@ -77,9 +80,9 @@ public function __sleep() * if it's not a list OR it's a list with its last child event containing * an EventList = Complete. * - * @return boolean + * @return bool */ - public function isComplete() + public function isComplete(): bool { return $this->completed; } @@ -91,7 +94,7 @@ public function isComplete() * * @return void */ - public function addEvent(EventMessage $event) + public function addEvent(EventMessage $event): void { $this->events[] = $event; if (stristr($event->getEventList(), 'complete') !== false @@ -107,7 +110,7 @@ public function addEvent(EventMessage $event) * * @return EventMessage[] */ - public function getEvents() + public function getEvents(): array { return $this->events; } @@ -115,11 +118,11 @@ public function getEvents() /** * Checks if the Response field has the word Error in it. * - * @return boolean + * @return bool */ - public function isSuccess() + public function isSuccess(): bool { - return stristr($this->getKey('Response'), 'Error') === false; + return stristr($this->getKey('Response') ?? '', 'Error') === false; } /** @@ -127,14 +130,13 @@ public function isSuccess() * word 'start' in it. Another way is to have a Message key, like: * Message: Result will follow * - * @return boolean + * @return bool */ - public function isList() + public function isList(): bool { return - stristr($this->getKey('EventList'), 'start') !== false - || stristr($this->getMessage(), 'follow') !== false - ; + stristr($this->getKey('EventList') ?? '', 'start') !== false + || stristr($this->getMessage(), 'follow') !== false; } /** @@ -142,9 +144,9 @@ public function isList() * * @return string */ - public function getMessage() + public function getMessage(): string { - return $this->getKey('Message'); + return $this->getKey('Message') ?? ''; } /** @@ -155,7 +157,7 @@ public function getMessage() * * @return void */ - public function setActionId($actionId) + public function setActionId(string $actionId): void { $this->setKey('ActionId', $actionId); } @@ -167,11 +169,10 @@ public function setActionId($actionId) * * @return void */ - public function __construct($rawContent) + public function __construct(string $rawContent) { parent::__construct($rawContent); - $this->events = array(); - $this->eventsCount = 0; + $this->events = []; $this->completed = !$this->isList(); } } diff --git a/src/PAMI/Stream/Stream.php b/src/PAMI/Stream/Stream.php new file mode 100644 index 000000000..d486d75a9 --- /dev/null +++ b/src/PAMI/Stream/Stream.php @@ -0,0 +1,90 @@ +context = $context ?? stream_context_create(); + + $this->socket = stream_socket_client( + $address, + $this->errorCode, + $this->errorMessage, + $timeout, + $flags, + $this->context + ); + } + + public function isConnected(): bool + { + return $this->socket !== false; + } + + public function getErrorCode(): ?int + { + return $this->errorCode; + } + + public function getErrorMessage(): ?string + { + return $this->errorMessage; + } + + public function setBlocking(bool $enable = true): bool + { + return stream_set_blocking($this->socket, $enable); + } + + public function getLine(int $length = 1024, string $eol = "\r\n"): false|string + { + return stream_get_line($this->socket, $length, $eol); + } + + public function read(int $length = 65535): false|string + { + // Read something. + return fread($this->socket, $length); + } + + public function write(string $message): false|int + { + return fwrite($this->socket, $message); + } + + public function endOfFile(): bool + { + return feof($this->socket); + } + + public function close(): bool + { + return stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR); + } +} \ No newline at end of file diff --git a/test/actions/Test_Actions.php b/test/actions/Test_Actions.php deleted file mode 100644 index 28f9138df..000000000 --- a/test/actions/Test_Actions.php +++ /dev/null @@ -1,1718 +0,0 @@ - - * @license http://marcelog.github.com/ Apache License 2.0 - * @version SVN: $Id$ - * @link http://marcelog.github.com/ - * - * Copyright 2011 Marcelo Gornstein - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -namespace PAMI\Client\Impl { -/** - * This class will test some actions. - * - * PHP Version 5 - * - * @category Pami - * @package Test - * @subpackage Action - * @author Marcelo Gornstein - * @license http://marcelog.github.com/ Apache License 2.0 - * @link http://marcelog.github.com/ - */ -class Test_Actions extends \PHPUnit_Framework_TestCase -{ - private $_properties = array(); - - public function setUp() - { - global $mockTime; - $this->_properties = array(); - $mockTime = true; - } - - private function _start(array $write, \PAMI\Message\Action\ActionMessage $action) - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $writeLogin = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $writeLogin); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->open(); - if ($action instanceof \PAMI\Message\Action\DBGetAction) { - $event = array( - 'Response: Success', - 'EventList: start', - 'ActionID: 1432.123', - '', - 'Event: DBGetResponse', - 'ActionID: 1432.123', - '' - ); - } else { - $event = array( - 'Response: Success', - 'ActionID: 1432.123', - '' - ); - } - setFgetsMock($event, $write); - $result = $client->send($action); - $this->assertTrue($result instanceof \PAMI\Message\Response\ResponseMessage); - return $client; - } - /** - * @test - */ - public function can_absolute_timeout() - { - $write = array( - "action: AbsoluteTimeout\r\nactionid: 1432.123\r\nchannel: SIP/asd\r\ntimeout: 10\r\n" - ); - $action = new \PAMI\Message\Action\AbsoluteTimeoutAction('SIP/asd', 10); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_login() - { - $write = array(implode("\r\n", array( - 'action: Login', - 'actionid: 1432.123', - 'username: foo', - 'secret: bar', - '' - ))); - $action = new \PAMI\Message\Action\LoginAction('foo', 'bar'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_login_with_events() - { - $write = array(implode("\r\n", array( - 'action: Login', - 'actionid: 1432.123', - 'username: foo', - 'secret: bar', - 'events: all', - '' - ))); - $action = new \PAMI\Message\Action\LoginAction('foo', 'bar', 'all'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_agent_logoff() - { - $write = array(implode("\r\n", array( - 'action: AgentLogoff', - 'actionid: 1432.123', - 'agent: asd', - 'soft: true', - '' - ))); - $action = new \PAMI\Message\Action\AgentLogoffAction('asd', true); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_agents() - { - $write = array(implode("\r\n", array( - 'action: Agents', - 'actionid: 1432.123', - '' - ))); - $action = new \PAMI\Message\Action\AgentsAction; - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_atxfer() - { - $write = array(implode("\r\n", array( - 'action: Atxfer', - 'actionid: 1432.123', - 'channel: channel', - 'exten: exten', - 'context: context', - 'priority: priority', - '' - ))); - $action = new \PAMI\Message\Action\AttendedTransferAction('channel', 'exten', 'context', 'priority'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_blindTransfer() - { - $write = array(implode("\r\n", array( - 'action: BlindTransfer', - 'actionid: 1432.123', - 'channel: channel', - 'exten: exten', - 'context: context', - '' - ))); - $action = new \PAMI\Message\Action\BlindTransferAction('channel', 'exten', 'context'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_bridge() - { - $write = array(implode("\r\n", array( - 'action: Bridge', - 'actionid: 1432.123', - 'channel1: channel1', - 'channel2: channel2', - 'tone: true', - '' - ))); - $action = new \PAMI\Message\Action\BridgeAction('channel1', 'channel2', true); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_bridge_info() - { - $bridge_uniqueid = '57cb3a7e-0fa3-4e28-924f-d7728b0d7a9a'; - - $write = array(implode("\r\n", array( - 'action: BridgeInfo', - 'actionid: 1432.123', - 'bridgeuniqueid: '. $bridge_uniqueid, - '' - ))); - $action = new \PAMI\Message\Action\BridgeInfoAction($bridge_uniqueid); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_challenge() - { - $write = array(implode("\r\n", array( - 'action: Challenge', - 'actionid: 1432.123', - 'authtype: test', - '' - ))); - $action = new \PAMI\Message\Action\ChallengeAction('test'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_change_monitor() - { - $write = array(implode("\r\n", array( - 'action: ChangeMonitor', - 'actionid: 1432.123', - 'channel: channel', - 'file: file', - '' - ))); - $action = new \PAMI\Message\Action\ChangeMonitorAction('channel', 'file', true); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_command() - { - $write = array(implode("\r\n", array( - 'action: Command', - 'actionid: 1432.123', - 'command: command', - '' - ))); - $action = new \PAMI\Message\Action\CommandAction('command'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_confbridge_list() - { - $conference = 'conf-59dba3997444e5'; - $write = array(implode("\r\n", array( - 'action: ConfbridgeList', - 'actionid: 1432.123', - 'conference: ' . $conference, - '' - ))); - $action = new \PAMI\Message\Action\ConfbridgeListAction($conference); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_confbridge_mute() - { - $write = array(implode("\r\n", array( - 'action: ConfbridgeMute', - 'actionid: 1432.123', - 'channel: channel', - 'conference: conference', - '' - ))); - $action = new \PAMI\Message\Action\ConfbridgeMuteAction('channel', 'conference'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_confbridge_unmute() - { - $write = array(implode("\r\n", array( - 'action: ConfbridgeUnmute', - 'actionid: 1432.123', - 'channel: channel', - 'conference: conference', - '' - ))); - $action = new \PAMI\Message\Action\ConfbridgeUnmuteAction('channel', 'conference'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_core_settings() - { - $write = array(implode("\r\n", array( - 'action: CoreSettings', - 'actionid: 1432.123', - '' - ))); - $action = new \PAMI\Message\Action\CoreSettingsAction; - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dongle_show_devices() - { - $write = array(implode("\r\n", array( - 'action: DongleShowDevices', - 'actionid: 1432.123', - '' - ))); - $action = new \PAMI\Message\Action\DongleShowDevicesAction; - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dongle_reload() - { - $write = array(implode("\r\n", array( - 'action: DongleReload', - 'actionid: 1432.123', - 'when: when', - '' - ))); - $action = new \PAMI\Message\Action\DongleReloadAction('when'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dongle_restart() - { - $write = array(implode("\r\n", array( - 'action: DongleRestart', - 'actionid: 1432.123', - 'when: when', - 'device: device', - '' - ))); - $action = new \PAMI\Message\Action\DongleRestartAction('when', 'device'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dongle_reset() - { - $write = array(implode("\r\n", array( - 'action: DongleReset', - 'actionid: 1432.123', - 'device: device', - '' - ))); - $action = new \PAMI\Message\Action\DongleResetAction('device'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dongle_send_pdu() - { - $write = array(implode("\r\n", array( - 'action: DongleSendPDU', - 'actionid: 1432.123', - 'device: device', - 'pdu: pdu', - '' - ))); - $action = new \PAMI\Message\Action\DongleSendPDUAction('device', 'pdu'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dongle_send_ussd() - { - $write = array(implode("\r\n", array( - 'action: DongleSendUSSD', - 'actionid: 1432.123', - 'device: device', - 'ussd: ussd', - '' - ))); - $action = new \PAMI\Message\Action\DongleSendUSSDAction('device', 'ussd'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dongle_stop() - { - $write = array(implode("\r\n", array( - 'action: DongleStop', - 'actionid: 1432.123', - 'when: when', - 'device: device', - '' - ))); - $action = new \PAMI\Message\Action\DongleStopAction('when', 'device'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dongle_start() - { - $write = array(implode("\r\n", array( - 'action: DongleStart', - 'actionid: 1432.123', - 'device: device', - '' - ))); - $action = new \PAMI\Message\Action\DongleStartAction('device'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dongle_sms_send() - { - $write = array(implode("\r\n", array( - 'action: DongleSendSMS', - 'actionid: 1432.123', - 'device: device', - 'number: number', - 'message: message', - '' - ))); - $action = new \PAMI\Message\Action\DongleSendSMSAction('device', 'number', 'message'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_core_status() - { - $write = array(implode("\r\n", array( - 'action: CoreStatus', - 'actionid: 1432.123', - '' - ))); - $action = new \PAMI\Message\Action\CoreStatusAction; - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_create_config() - { - $write = array(implode("\r\n", array( - 'action: CreateConfig', - 'actionid: 1432.123', - 'filename: file.conf', - '' - ))); - $action = new \PAMI\Message\Action\CreateConfigAction('file.conf'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dahdi_dndoff() - { - $write = array(implode("\r\n", array( - 'action: DAHDIDNDOff', - 'actionid: 1432.123', - 'dahdichannel: channel', - '' - ))); - $action = new \PAMI\Message\Action\DAHDIDNDOffAction('channel'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dahdi_dndon() - { - $write = array(implode("\r\n", array( - 'action: DAHDIDNDOn', - 'actionid: 1432.123', - 'dahdichannel: channel', - '' - ))); - $action = new \PAMI\Message\Action\DAHDIDNDOnAction('channel'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dahdi_dialoffhook() - { - $write = array(implode("\r\n", array( - 'action: DAHDIDialOffhook', - 'actionid: 1432.123', - 'dahdichannel: channel', - 'number: number', - '' - ))); - $action = new \PAMI\Message\Action\DAHDIDialOffHookAction('channel', 'number'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dahdi_hangup() - { - $write = array(implode("\r\n", array( - 'action: DAHDIHangup', - 'actionid: 1432.123', - 'dahdichannel: channel', - '' - ))); - $action = new \PAMI\Message\Action\DAHDIHangupAction('channel'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dahdi_restart() - { - $write = array(implode("\r\n", array( - 'action: DAHDIRestart', - 'actionid: 1432.123', - '' - ))); - $action = new \PAMI\Message\Action\DAHDIRestartAction; - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dahdi_show_channels() - { - $write = array(implode("\r\n", array( - 'action: DAHDIShowChannels', - 'actionid: 1432.123', - '' - ))); - $action = new \PAMI\Message\Action\DAHDIShowChannelsAction; - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dahdi_transfer() - { - $write = array(implode("\r\n", array( - 'action: DAHDITransfer', - 'actionid: 1432.123', - 'dahdichannel: channel', - '' - ))); - $action = new \PAMI\Message\Action\DAHDITransferAction('channel'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dbdel() - { - $write = array(implode("\r\n", array( - 'action: DBDel', - 'actionid: 1432.123', - 'family: family', - 'key: key', - '' - ))); - $action = new \PAMI\Message\Action\DBDelAction('family', 'key'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dbdeltree() - { - $write = array(implode("\r\n", array( - 'action: DBDelTree', - 'actionid: 1432.123', - 'family: family', - 'key: key', - '' - ))); - $action = new \PAMI\Message\Action\DBDelTreeAction('family', 'key'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dbget() - { - $write = array(implode("\r\n", array( - 'action: DBGet', - 'actionid: 1432.123', - 'family: family', - 'key: key', - '' - ))); - $action = new \PAMI\Message\Action\DBGetAction('family', 'key'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_dbput() - { - $write = array(implode("\r\n", array( - 'action: DBPut', - 'actionid: 1432.123', - 'family: family', - 'key: key', - 'val: val', - '' - ))); - $action = new \PAMI\Message\Action\DBPutAction('family', 'key', 'val'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_events_off() - { - $write = array(implode("\r\n", array( - 'action: Events', - 'actionid: 1432.123', - 'eventmask: off', - '' - ))); - $action = new \PAMI\Message\Action\EventsAction; - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_events() - { - $write = array(implode("\r\n", array( - 'action: Events', - 'actionid: 1432.123', - 'eventmask: a,b,c', - '' - ))); - $action = new \PAMI\Message\Action\EventsAction(array('a', 'b', 'c')); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_extension_state() - { - $write = array(implode("\r\n", array( - 'action: ExtensionState', - 'actionid: 1432.123', - 'exten: exten', - 'context: context', - '' - ))); - $action = new \PAMI\Message\Action\ExtensionStateAction('exten', 'context'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_get_config() - { - $write = array(implode("\r\n", array( - 'action: GetConfig', - 'actionid: 1432.123', - 'filename: file.conf', - 'category: category', - '' - ))); - $action = new \PAMI\Message\Action\GetConfigAction('file.conf', 'category'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_get_configjson() - { - $write = array(implode("\r\n", array( - 'action: GetConfigJSON', - 'actionid: 1432.123', - 'filename: file.conf', - '' - ))); - $action = new \PAMI\Message\Action\GetConfigJSONAction('file.conf', 'category'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_get_var() - { - $write = array(implode("\r\n", array( - 'action: Getvar', - 'actionid: 1432.123', - 'variable: var', - 'channel: channel', - '' - ))); - $action = new \PAMI\Message\Action\GetVarAction('var', 'channel'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_hangup() - { - $write = array(implode("\r\n", array( - 'action: Hangup', - 'actionid: 1432.123', - 'channel: channel', - '' - ))); - $action = new \PAMI\Message\Action\HangupAction('channel'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_hangup_with_cause() - { - $write = array(implode("\r\n", array( - 'action: Hangup', - 'actionid: 1432.123', - 'channel: channel', - 'cause: 5', - '' - ))); - $action = new \PAMI\Message\Action\HangupAction('channel', 5); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_jabbersend() - { - $write = array(implode("\r\n", array( - 'action: JabberSend', - 'actionid: 1432.123', - 'jabber: jabber', - 'jid: jid', - 'screenname: jid', - 'message: message', - '' - ))); - $action = new \PAMI\Message\Action\JabberSendAction('jabber', 'jid', 'message'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_list_categories() - { - $write = array(implode("\r\n", array( - 'action: ListCategories', - 'actionid: 1432.123', - 'filename: file.conf', - '' - ))); - $action = new \PAMI\Message\Action\ListCategoriesAction('file.conf'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_list_commands() - { - $write = array(implode("\r\n", array( - 'action: ListCommands', - 'actionid: 1432.123', - '' - ))); - $action = new \PAMI\Message\Action\ListCommandsAction; - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_local_optimize_away() - { - $write = array(implode("\r\n", array( - 'action: LocalOptimizeAway', - 'actionid: 1432.123', - 'channel: channel', - '' - ))); - $action = new \PAMI\Message\Action\LocalOptimizeAwayAction('channel'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_mailbox_count() - { - $write = array(implode("\r\n", array( - 'action: MailboxCount', - 'actionid: 1432.123', - 'mailbox: mailbox', - '' - ))); - $action = new \PAMI\Message\Action\MailboxCountAction('mailbox'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_mailbox_status() - { - $write = array(implode("\r\n", array( - 'action: MailboxStatus', - 'actionid: 1432.123', - 'mailbox: mailbox', - '' - ))); - $action = new \PAMI\Message\Action\MailboxStatusAction('mailbox'); - $client = $this->_start($write, $action); - } - - /** - * @test - */ - public function can_meetme_list() - { - $write = array(implode("\r\n", array( - 'action: MeetmeList', - 'actionid: 1432.123', - 'conference: conference', - '' - ))); - $action = new \PAMI\Message\Action\MeetmeListAction('conference'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_meetme_mute() - { - $write = array(implode("\r\n", array( - 'action: MeetmeMute', - 'actionid: 1432.123', - 'meetme: meetme', - 'usernum: usernum', - '' - ))); - $action = new \PAMI\Message\Action\MeetmeMuteAction('meetme', 'usernum'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_meetme_unmute() - { - $write = array(implode("\r\n", array( - 'action: MeetmeUnmute', - 'actionid: 1432.123', - 'meetme: meetme', - 'usernum: usernum', - '' - ))); - $action = new \PAMI\Message\Action\MeetmeUnmuteAction('meetme', 'usernum'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_mix_monitor() - { - $write = array(implode("\r\n", array( - 'action: MixMonitor', - 'actionid: 1432.123', - 'channel: channel', - 'file: file', - 'options: options', - '' - ))); - $action = new \PAMI\Message\Action\MixMonitorAction('channel'); - $action->setFile('file'); - $action->setOptions(array('o', 'p', 't', 'i', 'o', 'n', 's')); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_module_check() - { - $write = array(implode("\r\n", array( - 'action: ModuleCheck', - 'actionid: 1432.123', - 'module: module', - '' - ))); - $action = new \PAMI\Message\Action\ModuleCheckAction('module'); - $client = $this->_start($write, $action); - } - - /** - * @test - */ - public function can_module_load() - { - $write = array(implode("\r\n", array( - 'action: ModuleLoad', - 'actionid: 1432.123', - 'module: module', - 'loadtype: load', - '' - ))); - $action = new \PAMI\Message\Action\ModuleLoadAction('module'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_module_reload() - { - $write = array(implode("\r\n", array( - 'action: ModuleLoad', - 'actionid: 1432.123', - 'module: module', - 'loadtype: reload', - '' - ))); - $action = new \PAMI\Message\Action\ModuleReloadAction('module'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_module_unload() - { - $write = array(implode("\r\n", array( - 'action: ModuleLoad', - 'actionid: 1432.123', - 'module: module', - 'loadtype: unload', - '' - ))); - $action = new \PAMI\Message\Action\ModuleUnloadAction('module'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_monitor() - { - $write = array(implode("\r\n", array( - 'action: Monitor', - 'actionid: 1432.123', - 'channel: channel', - 'mix: true', - 'format: wav', - 'file: file', - '' - ))); - $action = new \PAMI\Message\Action\MonitorAction('channel', 'file'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_voicemail_users_list() - { - $write = array(implode("\r\n", array( - 'action: VoicemailUsersList', - 'actionid: 1432.123', - '' - ))); - $action = new \PAMI\Message\Action\VoicemailUsersListAction; - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_pause_monitor() - { - $write = array(implode("\r\n", array( - 'action: PauseMonitor', - 'actionid: 1432.123', - 'channel: channel', - '' - ))); - $action = new \PAMI\Message\Action\PauseMonitorAction('channel'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_unpause_monitor() - { - $write = array(implode("\r\n", array( - 'action: UnpauseMonitor', - 'actionid: 1432.123', - 'channel: channel', - '' - ))); - $action = new \PAMI\Message\Action\UnpauseMonitorAction('channel'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_stop_monitor() - { - $write = array(implode("\r\n", array( - 'action: StopMonitor', - 'actionid: 1432.123', - 'channel: channel', - '' - ))); - $action = new \PAMI\Message\Action\StopMonitorAction('channel'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_stop_mix_monitor() - { - $write = array(implode("\r\n", array( - 'action: StopMixMonitor', - 'actionid: 1432.123', - 'channel: channel', - 'mixmonitorid: mix_monitor', - '' - ))); - $action = new \PAMI\Message\Action\StopMixMonitorAction('channel'); - $action->setMixMonitorId('mix_monitor'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_status() - { - $write = array(implode("\r\n", array( - 'action: Status', - 'actionid: 1432.123', - 'channel: channel', - '' - ))); - $action = new \PAMI\Message\Action\StatusAction('channel'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_show_dialplan() - { - $write = array(implode("\r\n", array( - 'action: ShowDialPlan', - 'actionid: 1432.123', - 'context: context', - 'extension: extension', - '' - ))); - $action = new \PAMI\Message\Action\ShowDialPlanAction('context', 'extension'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_set_var() - { - $write = array(implode("\r\n", array( - 'action: Setvar', - 'actionid: 1432.123', - 'variable: variable', - 'value: value', - 'channel: channel', - '' - ))); - $action = new \PAMI\Message\Action\SetVarAction('variable', 'value', 'channel'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_reload() - { - $write = array(implode("\r\n", array( - 'action: Reload', - 'actionid: 1432.123', - 'module: module', - '' - ))); - $action = new \PAMI\Message\Action\ReloadAction('module'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_ping() - { - $write = array(implode("\r\n", array( - 'action: Ping', - 'actionid: 1432.123', - '' - ))); - $action = new \PAMI\Message\Action\PingAction; - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_send_text() - { - $write = array(implode("\r\n", array( - 'action: SendText', - 'actionid: 1432.123', - 'channel: channel', - 'message: message', - '' - ))); - $action = new \PAMI\Message\Action\SendTextAction('channel', 'message'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_sip_show_registry() - { - $write = array(implode("\r\n", array( - 'action: SIPshowregistry', - 'actionid: 1432.123', - '' - ))); - $action = new \PAMI\Message\Action\SIPShowRegistryAction; - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_sip_peers() - { - $write = array(implode("\r\n", array( - 'action: Sippeers', - 'actionid: 1432.123', - '' - ))); - $action = new \PAMI\Message\Action\SIPPeersAction; - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_sip_notify() - { - $write = array(implode("\r\n", array( - 'action: SIPnotify', - 'actionid: 1432.123', - 'channel: channel', - '' - ))); - $action = new \PAMI\Message\Action\SIPNotifyAction('channel'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_sip_show_peer() - { - $write = array(implode("\r\n", array( - 'action: SIPshowpeer', - 'actionid: 1432.123', - 'peer: peer', - '' - ))); - $action = new \PAMI\Message\Action\SIPShowPeerAction('peer'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_sip_qualify_peer() - { - $write = array(implode("\r\n", array( - 'action: Sipqualifypeer', - 'actionid: 1432.123', - 'peer: peer', - '' - ))); - $action = new \PAMI\Message\Action\SIPQualifyPeerAction('peer'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_vgsm_sms_tx() - { - $write = array(implode("\r\n", array( - 'action: vgsm_sms_tx', - 'actionid: 1432.123', - 'account: account', - 'x-sms-concatenate-total-messages: totalmsg', - 'x-sms-concatenate-sequence-number: seqnum', - 'x-sms-concatenate-refid: refid', - 'x-sms-class: class', - 'content: content', - 'x-sms-me: me', - 'content-transfer-encoding: encoding', - 'content-type: type', - 'to: to', - '' - ))); - $action = new \PAMI\Message\Action\VGSMSMSTxAction; - $action->setAccount('account'); - $action->setConcatTotalMsg('totalmsg'); - $action->setConcatSeqNum('seqnum'); - $action->setConcatRefId('refid'); - $action->setSmsClass('class'); - $action->setContent('content'); - $action->setMe('me'); - $action->setContentEncoding('encoding'); - $action->setContentType('type'); - $action->setTo('to'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_parked_calls() - { - $write = array(implode("\r\n", array( - 'action: ParkedCalls', - 'actionid: 1432.123', - '' - ))); - $action = new \PAMI\Message\Action\ParkedCallsAction; - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_queues() - { - $write = array(implode("\r\n", array( - 'action: Queues', - 'actionid: 1432.123', - '' - ))); - $action = new \PAMI\Message\Action\QueuesAction; - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_redirect() - { - $write = array(implode("\r\n", array( - 'action: Redirect', - 'actionid: 1432.123', - 'channel: channel', - 'exten: extension', - 'context: context', - 'priority: priority', - 'extrapriority: extrapriority', - 'extracontext: extracontext', - 'extraexten: extraextension', - 'extrachannel: extrachannel', - '' - ))); - $action = new \PAMI\Message\Action\RedirectAction('channel', 'extension', 'context', 'priority'); - $action->setExtraPriority('extrapriority'); - $action->setExtraContext('extracontext'); - $action->setExtraExtension('extraextension'); - $action->setExtraChannel('extrachannel'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_queue_unpause() - { - $write = array(implode("\r\n", array( - 'action: QueuePause', - 'actionid: 1432.123', - 'queue: queue', - 'reason: reason', - 'interface: interface', - 'paused: false', - '' - ))); - $action = new \PAMI\Message\Action\QueueUnpauseAction('interface', 'queue', 'reason'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_queue_pause() - { - $write = array(implode("\r\n", array( - 'action: QueuePause', - 'actionid: 1432.123', - 'queue: queue', - 'reason: reason', - 'interface: interface', - 'paused: true', - '' - ))); - $action = new \PAMI\Message\Action\QueuePauseAction('interface', 'queue', 'reason'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_queue_summary() - { - $write = array(implode("\r\n", array( - 'action: QueueSummary', - 'actionid: 1432.123', - 'queue: queue', - '' - ))); - $action = new \PAMI\Message\Action\QueueSummaryAction('queue'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_queue_status() - { - $write = array(implode("\r\n", array( - 'action: QueueStatus', - 'actionid: 1432.123', - 'queue: queue', - 'member: member', - '' - ))); - $action = new \PAMI\Message\Action\QueueStatusAction('queue', 'member'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_queue_reset() - { - $write = array(implode("\r\n", array( - 'action: QueueReset', - 'actionid: 1432.123', - 'queue: queue', - '' - ))); - $action = new \PAMI\Message\Action\QueueResetAction('queue'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_queue_rule() - { - $write = array(implode("\r\n", array( - 'action: QueueRule', - 'actionid: 1432.123', - 'rule: rule', - '' - ))); - $action = new \PAMI\Message\Action\QueueRuleAction('rule'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_queue_remove() - { - $write = array(implode("\r\n", array( - 'action: QueueRemove', - 'actionid: 1432.123', - 'queue: queue', - 'interface: interface', - '' - ))); - $action = new \PAMI\Message\Action\QueueRemoveAction('queue', 'interface'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_queue_reload() - { - $write = array(implode("\r\n", array( - 'action: QueueReload', - 'actionid: 1432.123', - 'queue: queue', - 'members: yes', - 'rules: yes', - 'parameters: yes', - '' - ))); - $action = new \PAMI\Message\Action\QueueReloadAction('queue', true, true, true); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_queue_penalty() - { - $write = array(implode("\r\n", array( - 'action: QueuePenalty', - 'actionid: 1432.123', - 'interface: interface', - 'penalty: penalty', - 'queue: queue', - '' - ))); - $action = new \PAMI\Message\Action\QueuePenaltyAction('interface', 'penalty', 'queue'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_queue_log() - { - $write = array(implode("\r\n", array( - 'action: QueueLog', - 'actionid: 1432.123', - 'event: event', - 'queue: queue', - 'message: message', - 'interface: member', - 'uniqueid: uniqueid', - '' - ))); - $action = new \PAMI\Message\Action\QueueLogAction('queue', 'event'); - $action->setMessage('message'); - $action->setMemberName('member'); - $action->setUniqueId('uniqueid'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_queue_add() - { - $write = array(implode("\r\n", array( - 'action: QueueAdd', - 'actionid: 1432.123', - 'interface: interface', - 'queue: queue', - 'paused: true', - 'membername: member', - 'penalty: penalty', - 'stateinterface: state', - '' - ))); - $action = new \PAMI\Message\Action\QueueAddAction('queue', 'interface'); - $action->setPaused('true'); - $action->setMemberName('member'); - $action->setPenalty('penalty'); - $action->setStateInterface('state'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_play_dtmf() - { - $write = array(implode("\r\n", array( - 'action: PlayDTMF', - 'actionid: 1432.123', - 'channel: channel', - 'digit: 1', - '' - ))); - $action = new \PAMI\Message\Action\PlayDTMFAction('channel', '1'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_park() - { - $write = array(implode("\r\n", array( - 'action: Park', - 'actionid: 1432.123', - 'channel: channel1', - 'channel2: channel2', - 'timeout: timeout', - 'parkinglot: lot', - '' - ))); - $action = new \PAMI\Message\Action\ParkAction('channel1', 'channel2', 'timeout', 'lot'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_agi() - { - $write = array(implode("\r\n", array( - 'action: AGI', - 'actionid: 1432.123', - 'channel: channel1', - 'command: an agi command', - 'commandid: blah', - '' - ))); - $action = new \PAMI\Message\Action\AGIAction('channel1', 'an agi command', 'blah'); - $client = $this->_start($write, $action); - } - /** - * @test - */ - public function can_originate() - { - $write = array(implode("\r\n", array( - 'action: Originate', - 'actionid: 1432.123', - 'channel: channel', - 'codecs: a,b', - 'async: true', - 'account: account', - 'callerid: clid', - 'timeout: timeout', - 'data: data', - 'application: app', - 'priority: priority', - 'context: context', - 'exten: extension', - 'Variable: a=b', - '' - ))); - $action = new \PAMI\Message\Action\OriginateAction('channel'); - $action->setCodecs(array('a', 'b')); - $action->setAsync(true); - $action->setAccount('account'); - $action->setCallerId('clid'); - $action->setTimeout('timeout'); - $action->setData('data'); - $action->setApplication('app'); - $action->setPriority('priority'); - $action->setContext('context'); - $action->setExtension('extension'); - $action->setVariable('a', 'b'); - $client = $this->_start($write, $action); - } - - /** - * @test - */ - public function can_logoff() - { - $write = array(implode("\r\n", array( - 'action: Logoff', - 'actionid: 1432.123', - '' - ))); - $action = new \PAMI\Message\Action\LogoffAction(); - $client = $this->_start($write, $action); - } - - /** - * @test - */ - public function can_user_event() - { - $write = array(implode("\r\n", array( - 'action: UserEvent', - 'actionid: 1432.123', - 'userevent: FooEvent', - 'foo: Bar', - 'bar: Foo', - '' - ))); - $action = new \PAMI\Message\Action\UserEventAction('FooEvent', ['Foo' => 'Bar', 'Bar' => 'Foo']); - $client = $this->_start($write, $action); - } - - /** - * @test - */ - public function can_wait_event() - { - $write = array(implode("\r\n", array( - 'action: WaitEvent', - 'actionid: 1432.123', - 'timeout: 20', - '' - ))); - $action = new \PAMI\Message\Action\WaitEventAction(20); - $client = $this->_start($write, $action); - } - - /** - * @test - */ - public function can_set_actionid() - { - $action = new \PAMI\Message\Action\PingAction(); - // ActionID is between 0 and 69 characters long. - $actionID = '121234567890123456789012345678901234567890'; - $action->setActionID($actionID); - $this->assertSame($actionID, $action->getActionID()); - } - - /** - * @test - * @expectedException \PAMI\Exception\PAMIException - */ - public function cannot_set_actionid_longer_than_69_characters() - { - $action = new \PAMI\Message\Action\PingAction(); - // A 70-character long ActionID - $action->setActionID('1234567890123456789012345678901234567890123456789012345678901234567890'); - } - - /** - * @test - * @expectedException \PAMI\Exception\PAMIException - */ - public function cannot_set_empty_actionid() - { - $action = new \PAMI\Message\Action\PingAction(); - // An empty ActionID - $action->setActionID(''); - } - - /** - * @test - */ - public function can_update_config() - { - $number = 9876; - $writeCreate = array( implode("\r\n", array( - 'action: UpdateConfig', - 'actionid: 1432.123', - 'srcfilename: sip.conf', - 'dstfilename: sip.conf', - 'action-000000: NewCat', - 'cat-000000: '.$number, - 'action-000001: Append', - 'cat-000001: '.$number, - 'var-000001: username', - 'value-000001: test', - 'action-000002: Append', - 'cat-000002: '.$number, - 'var-000002: secret', - 'value-000002: secret', - '' - )) ); - - $actionCreate = new \PAMI\Message\Action\UpdateConfigAction(); - - $actionCreate->setSrcFilename('sip.conf'); - $actionCreate->setDstFilename('sip.conf'); - - $actionCreate->setAction('NewCat'); - $actionCreate->setCat($number); - - $actionCreate->setAction('Append'); - $actionCreate->setCat($number); - $actionCreate->setVar('username'); - $actionCreate->setValue('test'); - - $actionCreate->setAction('Append'); - $actionCreate->setCat($number); - $actionCreate->setVar('secret'); - $actionCreate->setValue('secret'); - - $client = $this->_start($writeCreate, $actionCreate); - - $writeDelete = array( implode("\r\n", array( - 'action: UpdateConfig', - 'actionid: 1432.123', - 'srcfilename: sip.conf', - 'dstfilename: sip.conf', - 'reload: yes', - 'action-000000: DelCat', - 'cat-000000: '.$number, - '' - )) ); - - $actionDelete = new \PAMI\Message\Action\UpdateConfigAction(); - - $actionDelete->setSrcFilename('sip.conf'); - $actionDelete->setDstFilename('sip.conf'); - $actionDelete->setReload(true); - $actionDelete->setAction('DelCat'); - $actionDelete->setCat($number); - - $client = $this->_start($writeDelete, $actionDelete); - } -} -} diff --git a/test/client/Test_Client.php b/test/client/Test_Client.php deleted file mode 100644 index feec27b9f..000000000 --- a/test/client/Test_Client.php +++ /dev/null @@ -1,1123 +0,0 @@ - - * @license http://marcelog.github.com/ Apache License 2.0 - * @version SVN: $Id$ - * @link http://marcelog.github.com/ - * - * Copyright 2011 Marcelo Gornstein - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -namespace { - $mockTime = false; - $mockTimeCount = false; - $mockTimeReturn = false; - $mock_stream_socket_client = false; - $mock_stream_set_blocking = false; - $mockFwrite = false; - $mockFwriteReturn = false; - $mockFwriteCount = 0; - $mockFgets = false; - $mockFgetsCount = 0; - $mockFreadReturn = false; - $standardAMIStart = array( - 'Asterisk Call Manager/1.1', - 'Response: Success', - 'ActionID: 1432.123', - 'Message: Authentication accepted', - '', - 'Response: Goodbye', - 'ActionID: 1432.123', - 'Message: Thanks for all the fish.', - '' - ); - $standardAMIStartBadLogin = array( - 'Asterisk Call Manager/1.1', - 'Response: Error', // also tests behavior when asterisk does not return an actionid - 'Message: Authentication accepted', - '' - ); -} -namespace PAMI\Message\Action { - function microtime() { - global $mockTime; - global $mockTimeCount; - global $mockTimeReturn; - if (isset($mockTime) && $mockTime === true) { - return 1432.123; - } else { - return call_user_func_array('\microtime', func_get_args()); - } - } -} - -namespace PAMI\Client\Impl { - function microtime() { - global $mockTime; - global $mockTimeCount; - global $mockTimeReturn; - if (isset($mockTime) && $mockTime === true) { - return 1432.123; - } else { - return call_user_func_array('\microtime', func_get_args()); - } - } - function stream_socket_client($remote_socket, &$errno = null, &$errstr = null, $timeout = null, $flags = null, $context = null) { - global $mock_stream_socket_client; - if (isset($mock_stream_socket_client) && $mock_stream_socket_client === true) { - } else { - return \stream_socket_client($remote_socket, $errno, $errstr, $timeout, $flags, $context); - } - } - function stream_socket_shutdown() { - return true; - } - function stream_set_blocking() { - global $mock_stream_set_blocking; - if (isset($mock_stream_set_blocking) && $mock_stream_set_blocking === true) { - return true; - } else { - return call_user_func_array('\stream_set_blocking', func_get_args()); - } - } - function fwrite() { - global $mockFwrite; - global $mockFwriteCount; - global $mockFwriteReturn; - if (isset($mockFwrite) && $mockFwrite === true) { - $args = func_get_args(); - if (isset($mockFwriteReturn[$mockFwriteCount]) && $mockFwriteReturn[$mockFwriteCount] !== false) { - if ($mockFwriteReturn[$mockFwriteCount] === 'fwrite error') { - $mockFwriteCount++; - return 0; - } - $str = $mockFwriteReturn[$mockFwriteCount] . "\r\n"; - if ($str !== $args[1]) { - throw new \Exception( - 'Mocked: ' . PHP_EOL . PHP_EOL . print_r($mockFwriteReturn[$mockFwriteCount], true) . PHP_EOL . PHP_EOL - . ' is different from: ' . PHP_EOL . PHP_EOL . print_r($args[1], true) - ); - } - } - $mockFwriteCount++; - return strlen($args[1]); - } else { - return call_user_func_array('\fwrite', func_get_args()); - } - } - function stream_get_line() { - global $mockFgets; - global $mockFgetsCount; - global $mockFgetsReturn; - if (isset($mockFgets) && $mockFgets === true) { - $result = $mockFgetsReturn[$mockFgetsCount]; - $mockFgetsCount++; - return is_string($result) ? $result . "\r\n" : $result; - } else { - return call_user_func_array('\stream_get_line', func_get_args()); - } - } - function feof($resource) { - global $mockFgets; - if (isset($mockFgets) && $mockFgets === true) { - return false; - } - return \feof($resource); - } - - function fread() { - global $mockFgets; - global $mockFgetsCount; - global $mockFgetsReturn; - if (isset($mockFgets) && $mockFgets === true) { - $result = $mockFgetsReturn[$mockFgetsCount]; - $mockFgetsCount++; - if (is_integer($result)) { - sleep($result); - return ''; - } - return is_string($result) ? $result . "\r\n" : $result; - } else { - return call_user_func_array('\fread', func_get_args()); - } - } - function setFgetsMock(array $readValues, $writeValues) - { - global $mockFgets; - global $mockFopen; - global $mockFgetsCount; - global $mockFgetsReturn; - global $mockFwrite; - global $mockFwriteCount; - global $mockFwriteReturn; - $mockFgets = true; - $mockFopen = true; - $mockFwrite = true; - $mockFgetsCount = 0; - $mockFgetsReturn = $readValues; - $mockFwriteCount = 0; - $mockFwriteReturn = $writeValues; - } -/** - * This class will test the ami client - * - * PHP Version 5 - * - * @category Pami - * @package Test - * @subpackage Client - * @author Marcelo Gornstein - * @license http://marcelog.github.com/ Apache License 2.0 - * @link http://marcelog.github.com/ - */ -class Test_Client extends \PHPUnit_Framework_TestCase -{ - private $_properties = array(); - - public function setUp() - { - $this->_properties = array(); - } - - /** - * @test - */ - public function can_get_client() - { - $options = array( - 'host' => 'tcp://1.1.1.1', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $client = new \PAMI\Client\Impl\ClientImpl($options); - } - /** - * @test - */ - public function can_connect_timeout() - { - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 3, - 'read_timeout' => 10 - ); - $start = time(); - try - { - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->open(); - } catch(\Exception $e) { - } - $length = time() - $start; - $this->assertTrue($length >= 2 && $length <= 5); - } - /** - * @test - * @expectedException \PAMI\Client\Exception\ClientException - */ - public function can_detect_other_peer() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $read = array('Whatever'); - $write = array(); - setFgetsMock($read, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->open(); - } - /** - * @test - */ - public function can_register_event_listener() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->registerEventListener(new SomeListenerClass); - $client->open(); - $event = array( - 'Event: PeerStatus', - 'Privilege: system,all', - 'ChannelType: SIP', - 'Peer: SIP/someguy', - 'PeerStatus: Registered', - '' - ); - setFgetsMock($event, $event); - for($i = 0; $i < 6; $i++) { - $client->process(); - } - $event = SomeListenerClass::$event; - $this->assertEquals($event->getName(), 'PeerStatus'); - $this->assertTrue($event instanceof \PAMI\Message\Event\PeerStatusEvent); - } - - /** - * @test - */ - public function can_register_closure_event_listener() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $resultVariable = false; - $client->registerEventListener(function ($event) use (&$resultVariable) { - $resultVariable = $event; - }); - $client->open(); - $event = array( - 'Event: PeerStatus', - 'Privilege: system,all', - 'ChannelType: SIP', - 'Peer: SIP/someguy', - 'PeerStatus: Registered', - '' - ); - setFgetsMock($event, $event); - for($i = 0; $i < 6; $i++) { - $client->process(); - } - $this->assertEquals($resultVariable->getName(), 'PeerStatus'); - $this->assertTrue($resultVariable instanceof \PAMI\Message\Event\PeerStatusEvent); - } - - /** - * @test - */ - public function can_register_method_event_listener() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $resultVariable = false; - $listener = new SomeListenerClass; - $client->registerEventListener(array($listener, 'handle')); - $client->open(); - $event = array( - 'Event: PeerStatus', - 'Privilege: system,all', - 'ChannelType: SIP', - 'Peer: SIP/someguy', - 'PeerStatus: Registered', - '' - ); - setFgetsMock($event, $event); - for($i = 0; $i < 6; $i++) { - $client->process(); - } - $event = SomeListenerClass::$event; - $this->assertEquals($event->getName(), 'PeerStatus'); - $this->assertTrue($event instanceof \PAMI\Message\Event\PeerStatusEvent); - } - - /** - * @test - */ - public function can_unregister_event_listener() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - SomeListenerClass::$event = null; - $id = $client->registerEventListener(new SomeListenerClass); - $client->open(); - $event = array( - 'Event: PeerStatus', - 'Privilege: system,all', - 'ChannelType: SIP', - 'Peer: SIP/someguy', - 'PeerStatus: Registered', - '' - ); - setFgetsMock($event, $event); - $client->unregisterEventListener($id); - for($i = 0; $i < 6; $i++) { - $client->process(); - } - $event = SomeListenerClass::$event; - $this->assertNull(SomeListenerClass::$event); - } - - /** - * @test - */ - public function can_filter_with_predicate() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $resultVariable = false; - $client->registerEventListener( - function ($event) use (&$resultVariable) { - $resultVariable = $event; - }, - function ($event) { - return false; - } - ); - $client->open(); - $event = array( - 'Event: PeerStatus', - 'Privilege: system,all', - 'ChannelType: SIP', - 'Peer: SIP/someguy', - 'PeerStatus: Registered', - '' - ); - setFgetsMock($event, $event); - for($i = 0; $i < 6; $i++) { - $client->process(); - } - $this->assertFalse($resultVariable); - } - - /** - * @test - */ - public function can_login() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->open(); - $client->close(); - } - /** - * @test - * @expectedException \PAMI\Client\Exception\ClientException - */ - public function cannot_send() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $write = array( - 'fwrite error' - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->open(); - } - - /** - * @test - * @expectedException \PAMI\Client\Exception\ClientException - */ - public function cannot_login() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStartBadLogin; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStartBadLogin, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->open(); - } - /** - * @test - * @expectedException \PAMI\Client\Exception\ClientException - */ - public function cannot_read() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->open(); - setFgetsMock(array(false), $write); - $client->send(new \PAMI\Message\Action\LoginAction('asd', 'asd')); - } - /** - * @test - * @expectedException \PAMI\Client\Exception\ClientException - */ - public function cannot_read_by_read_timeout() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 1 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->open(); - setFgetsMock(array(10, 4), $write); - $start = \time(); - $client->send(new \PAMI\Message\Action\LoginAction('asd', 'asd')); - $this->assertEquals(\time() - $start, 10); - } - /** - * @test - */ - public function can_get_response_with_associated_events() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->registerEventListener(new SomeListenerClass); - $client->open(); - $event = array( - 'Response: Success', - 'ActionID: 1432.123', - 'Eventlist: start', - 'Message: Channels will follow', - '', - 'Event: CoreShowChannelsComplete', - 'EventList: Complete', - 'ListItems: 0', - 'ActionID: 1432.123', - '' - ); - $write = array( - "action: CoreShowChannels\r\nactionid: 1432.123\r\n" - ); - setFgetsMock($event, $write); - $result = $client->send(new \PAMI\Message\Action\CoreShowChannelsAction); - $this->assertTrue($result instanceof \PAMI\Message\Response\ResponseMessage); - $events = $result->getEvents(); - $this->assertEquals(count($events), 1); - $this->assertTrue($events[0] instanceof \PAMI\Message\Event\CoreShowChannelsCompleteEvent); - $this->assertEquals( - $events[0]->getRawContent(), implode("\r\n", array( - 'Event: CoreShowChannelsComplete', - 'EventList: Complete', - 'ListItems: 0', - 'ActionID: 1432.123', - )) - ); - } - - /** - * @test - */ - public function can_serialize_response_and_events() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->registerEventListener(new SomeListenerClass); - $client->open(); - $event = array( - 'Response: Success', - 'ActionID: 1432.123', - 'Eventlist: start', - 'Message: Channels will follow', - '', - 'Event: CoreShowChannelsComplete', - 'EventList: Complete', - 'ListItems: 0', - 'ActionID: 1432.123', - '' - ); - $write = array( - "action: CoreShowChannels\r\nactionid: 1432.123\r\n" - ); - setFgetsMock($event, $write); - $result = $client->send(new \PAMI\Message\Action\CoreShowChannelsAction); - $ser = serialize($result); - $result2 = unserialize($ser); - $events = $result2->getEvents(); - $this->assertEquals($result2->getMessage(), 'Channels will follow'); - $this->assertEquals($events[0]->getName(), 'CoreShowChannelsComplete'); - $this->assertEquals($events[0]->getListItems(), 0); - } - - /** - * @test - */ - public function can_get_response_events_without_actionid_and_event() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 1000, - 'read_timeout' => 1000 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->registerEventListener(new SomeListenerClass); - $client->open(); - $event = array( - 'Response: Success', - 'ActionID: 1432.123', - 'Eventlist: start', - 'Message: Channels will follow', - '', - 'Channel: pepe', - 'Count: Blah', - '', - 'Event: CoreShowChannelsComplete', - 'EventList: Complete', - 'ListItems: 0', - 'ActionID: 1432.123', - '' - ); - $write = array( - "action: CoreShowChannels\r\nactionid: 1432.123\r\n" - ); - setFgetsMock($event, $write); - $result = $client->send(new \PAMI\Message\Action\CoreShowChannelsAction); - $events = $result->getEvents(); - $this->assertEquals($events[0]->getName(), 'ResponseEvent'); - $this->assertEquals($events[0]->getKey('Channel'), 'pepe'); - $this->assertEquals($events[0]->getKey('Count'), 'Blah'); - $this->assertEquals($events[1]->getName(), 'CoreShowChannelsComplete'); - $this->assertEquals($events[1]->getListItems(), 0); - } - - /** - * @test - */ - public function can_get_set_variable() - { - $now = time(); - $action = new \PAMI\Message\Action\LoginAction('a', 'b'); - $this->assertEquals($now, $action->getCreatedDate()); - $action->setVariable('variable', 'value'); - $this->assertEquals($action->getVariable('variable'), 'value'); - $this->assertNull($action->getVariable('variable2')); - } - - /** - * @test - */ - public function can_get_set_variable_with_multiple_values() - { - global $mockTime; - $mockTime = true; - $now = time(); - $action = new \PAMI\Message\Action\LoginAction('a', 'b'); - $this->assertEquals($now, $action->getCreatedDate()); - $action->setVariable('variable', array('value1', 'value2')); - $text - = "action: Login\r\n" - . "actionid: 1432.123\r\n" - . "username: a\r\n" - . "secret: b\r\n" - . "Variable: variable=value1\r\n" - . "Variable: variable=value2\r\n" - . "\r\n" - ; - $this->assertEquals($text, $action->serialize()); - } - - /** - * @test - */ - public function can_report_unknown_event() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->registerEventListener(new SomeListenerClass); - $client->open(); - $event = array( - 'Event: MyOwnImaginaryEvent', - 'Privilege: system,all', - 'ChannelType: SIP', - '' - ); - setFgetsMock($event, $event); - for($i = 0; $i < 4; $i++) { - $client->process(); - } - $this->assertTrue(SomeListenerClass::$event instanceof \PAMI\Message\Event\UnknownEvent); - - } - - /** - * @test - * @group channel_vars - * ChanVariable is sent without a channel name and without a "channel" - * key. - * https://github.com/marcelog/PAMI/issues/85 - */ - public function can_get_channel_variables_without_default_channel_name() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->registerEventListener(new SomeListenerClass); - $client->open(); - $event = array( - 'Event: Dial', - 'Privilege: call,all', - 'SubEvent: Begin', - 'Destination: SIP/jw1034-00000010', - 'CallerIDNum: 1201', - 'CallerIDName: ', - 'ConnectedLineNum: strategy-sequential', - 'ConnectedLineName: ', - 'UniqueID: pbx-1439974866.33', - 'DestUniqueID: pbx-1439974866.34', - 'Dialstring: jw1034', - 'ChanVariable: var1', - 'ChanVariable: var2=v2', - '' - ); - setFgetsMock($event, $event); - for($i = 0; $i < 14; $i++) { - $client->process(); - } - $event = SomeListenerClass::$event; - $varChan = array( - 'var1' => '', - 'var2' => 'v2' - ); - $channelVars = array( - 'default' => $varChan - ); - $this->assertEquals($channelVars, $event->getAllChannelVariables()); - $this->assertEquals($varChan, $event->getChannelVariables()); - $this->assertEquals($varChan, $event->getChannelVariables('default')); - } - - - /** - * @test - * @group channel_vars - * ChanVariable is sent without a channel name but with a "channel" key. - * https://github.com/marcelog/PAMI/issues/85 - */ - public function can_get_channel_variables_with_default_channel_name() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->registerEventListener(new SomeListenerClass); - $client->open(); - $event = array( - 'Event: Dial', - 'Privilege: call,all', - 'Channel: Local/0@pbx_dial_callroute_to_endpoint-00000008;2', - 'SubEvent: Begin', - 'Destination: SIP/jw1034-00000010', - 'CallerIDNum: 1201', - 'CallerIDName: ', - 'ConnectedLineNum: strategy-sequential', - 'ConnectedLineName: ', - 'UniqueID: pbx-1439974866.33', - 'DestUniqueID: pbx-1439974866.34', - 'Dialstring: jw1034', - 'ChanVariable: var1', - 'ChanVariable: var2=v2', - '' - ); - setFgetsMock($event, $event); - for($i = 0; $i < 15; $i++) { - $client->process(); - } - $event = SomeListenerClass::$event; - $varChan = array( - 'var1' => '', - 'var2' => 'v2' - ); - $channelVars = array( - 'local/0@pbx_dial_callroute_to_endpoint-00000008;2' => $varChan - ); - $this->assertEquals($channelVars, $event->getAllChannelVariables()); - $this->assertEquals($varChan, $event->getChannelVariables()); - $this->assertEquals( - $varChan, - $event->getChannelVariables( - 'Local/0@pbx_dial_callroute_to_endpoint-00000008;2' - ) - ); - } - - /** - * @test - * @group channel_vars - * ChanVariable is sent with a channel name and with a "channel" key. - * https://github.com/marcelog/PAMI/issues/85 - */ - public function can_get_channel_variables() - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->registerEventListener(new SomeListenerClass); - $client->open(); - $event = array( - 'Event: Dial', - 'Privilege: call,all', - 'SubEvent: Begin', - 'Channel: Local/0@pbx_dial_callroute_to_endpoint-00000008;2', - 'Destination: SIP/jw1034-00000010', - 'CallerIDNum: 1201', - 'CallerIDName: ', - 'ConnectedLineNum: strategy-sequential', - 'ConnectedLineName: ', - 'UniqueID: pbx-1439974866.33', - 'DestUniqueID: pbx-1439974866.34', - 'Dialstring: jw1034', - 'ChanVariable: var1', - 'ChanVariable: var2=value2', - 'ChanVariable(Local/0@pbx_dial_callroute_to_endpoint-00000008;2): var3=value3', - 'ChanVariable(Local/0@pbx_dial_callroute_to_endpoint-00000008;2): var4=value4', - 'ChanVariable(Local/0@pbx_dial_callroute_to_endpoint-00000008;2): var5=value5', - 'ChanVariable(SIP/jw1034-00000010): var12=value12', - 'ChanVariable(SIP/jw1034-00000010): var22=value22', - 'ChanVariable(SIP/jw1034-00000010): var32=value32', - '' - ); - setFgetsMock($event, $event); - for($i = 0; $i < 21; $i++) { - $client->process(); - } - $event = SomeListenerClass::$event; - $varChan1 = array( - 'var1' => '', - 'var2' => 'value2', - 'var3' => 'value3', - 'var4' => 'value4', - 'var5' => 'value5' - ); - $varChan2 = array( - 'var12' => 'value12', - 'var22' => 'value22', - 'var32' => 'value32' - ); - $channelVars = array( - 'local/0@pbx_dial_callroute_to_endpoint-00000008;2' => $varChan1, - 'sip/jw1034-00000010' => $varChan2 - ); - $this->assertEquals($varChan1, $event->getChannelVariables()); - $this->assertEquals($channelVars, $event->getAllChannelVariables()); - } -} -class SomeListenerClass implements \PAMI\Listener\IEventListener -{ - public static $event; - - public function handle(\PAMI\Message\Event\EventMessage $event) - { - self::$event = $event; - } -} -} diff --git a/test/events/Test_Events.php b/test/events/Test_Events.php deleted file mode 100644 index 580fccd13..000000000 --- a/test/events/Test_Events.php +++ /dev/null @@ -1,1573 +0,0 @@ - - * @license http://marcelog.github.com/ Apache License 2.0 - * @version SVN: $Id$ - * @link http://marcelog.github.com/ - * - * Copyright 2011 Marcelo Gornstein - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -namespace PAMI\Client\Impl { -/** - * This class will test some events. - * - * PHP Version 5 - * - * @category Pami - * @package Test - * @subpackage Event - * @author Marcelo Gornstein - * @license http://marcelog.github.com/ Apache License 2.0 - * @link http://marcelog.github.com/ - */ -class Test_Events extends \PHPUnit_Framework_TestCase -{ - private $_properties = array(); - - public function setUp() - { - $this->_properties = array(); - } - /** - * @test - */ - public function can_report_events() - { - $eventNames = array( - 'AsyncAGI', 'AGIExec', 'VarSet', 'Unlink', 'vgsm_sms_rx', 'vgsm_net_state', - 'vgsm_me_state', 'DTMF', 'Bridge', 'VoicemailUserEntryComplete', - 'StatusComplete', 'ParkedCallsComplete', 'DBGetResponse', - 'VoicemailUserEntry', 'Transfer', 'Status', 'ShowDialPlanComplete', - 'Rename', 'RegistrationsComplete', 'RTPSenderStat', 'RTPReceiverStat', - 'RTCPSent', 'RTCPReceiverStat', 'RTCPReceived', 'QueueSummaryComplete', - 'QueueStatusComplete', 'DAHDIShowChannelsComplete', 'QueueSummary', - 'QueueParams', 'QueueMemberStatus', 'QueueMemberRemoved', - 'QueueMemberPaused', 'QueueMember', 'QueueMemberAdded', 'PeerlistComplete', - 'PeerStatus', 'PeerEntry', 'OriginateResponse', 'Newstate', 'Newexten', - 'Newchannel', 'NewCallerid', 'NewAccountCode', 'MusicOnHold', - 'MessageWaiting', 'Masquerade', 'ListDialplan', 'Leave', 'Join', - 'Hold', 'Hangup', 'ExtensionStatus', 'Dial', 'DAHDIShowChannels', - 'CoreShowChannelsComplete', 'CoreShowChannel', 'ChannelUpdate', - 'Agents', 'AgentsComplete', 'Agentlogoff', 'Agentlogin', 'AgentConnect', - 'DongleSMSStatus', 'FullyBooted', 'DongleShowDevicesComplete', 'DongleDeviceEntry', - 'DongleNewUSSDBase64', 'DongleNewUSSD', 'DongleUSSDStatus', 'DongleNewCUSD', - 'DongleStatus', 'CEL', 'JabberEvent', 'Registry', 'UserEvent', - 'ParkedCall', 'UnParkedCall', 'Link', - 'AGIExecStart', - 'AGIExecEnd', - 'AsyncAGIStart', - 'AsyncAGIExec', - 'AsyncAGIEnd', - 'QueueCallerJoin', - 'QueueCallerLeave', - 'AttendedTransfer', - 'BlindTransfer', - 'DialBegin', - 'DialEnd', - 'DTMFBegin', - 'DTMFEnd', - 'BridgeCreate', - 'BridgeDestroy', - 'BridgeEnter', - 'BridgeLeave', - 'MusicOnHoldStart', - 'MusicOnHoldStop', - 'ConfbridgeStart', - 'ConfbridgeEnd', - 'ConfbridgeJoin', - 'ConfbridgeLeave', - 'ConfbridgeMute', - 'ConfbridgeUnmute', - 'ConfbridgeTalking', - 'ConfbridgeList', - 'ConfbridgeListComplete', - 'BridgeInfoChannel', - 'BridgeInfoComplete', - ); - $eventTranslatedValues = array( - 'QueueMemberStatus' => array( - 'Paused' => true - ), - 'QueueMemberPaused' => array( - 'Paused' => true - ), - 'QueueMember' => array( - 'Paused' => true - ), - 'QueueMemberAdded' => array( - 'Paused' => true - ), - ); - $eventValues = array( - 'UserEvent' => array( - 'Privilege' => 'Privilege', - 'UniqueID' => 'UniqueID', - 'UserEvent' => 'UserEvent' - ), - 'Registry' => array( - 'Channel' => 'Channel', - 'Domain' => 'Domain', - 'Status' => 'Status' - ), - 'JabberEvent' => array( - 'Privilege' => 'Privilege', - 'Account' => 'Account', - 'Packet' => 'Packet' - ), - 'AsyncAGI' => array( - 'Env' => 'Env', - 'Channel' => 'Channel', - 'CommandId' => 'CommandId', - 'Privilege' => 'Privilege', - 'SubEvent' => 'SubEvent', - 'Result' => 'Result' - ), - 'FullyBooted' => array(), - 'DongleUSSDStatus' => array( - 'Privilege' => 'Privilege', - 'Id' => 'Id', - 'Device' => 'Device', - 'Status' => 'Status' - ), - 'DongleNewUSSDBase64' => array( - 'Device' => 'Device', - 'Message' => 'Message', - 'Privilege' => 'Privilege' - ), - 'DongleNewCUSD' => array( - 'Device' => 'Device', - 'Message' => 'Message', - 'Privilege' => 'Privilege' - ), - 'DongleNewUSSD' => array( - 'Device' => 'Device', - 'LineCount' => 'LineCount', - 'Privilege' => 'Privilege' - ), - 'DongleDeviceEntry' => array( - 'Device' => 'Device', - 'AudioSetting' => 'AudioSetting', - 'DataSetting' => 'DataSetting', - 'IMEISetting' => 'IMEISetting', - 'IMSISetting' => 'IMSISetting', - 'ChannelLanguage' => 'ChannelLanguage', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Group' => 'Group', - 'RXGain' => 'RXGain', - 'TXGain' => 'TXGain', - 'U2DIAG' => 'U2DIAG', - 'UseCallingPres' => 'UseCallingPres', - 'DefaultCallingPres' => 'DefaultCallingPres', - 'AutoDeleteSMS' => 'AutoDeleteSMS', - 'DisableSMS' => 'DisableSMS', - 'ResetDongle' => 'ResetDongle', - 'SMSPDU' => 'SMSPDU', - 'CallWaitingSetting' => 'CallWaitingSetting', - 'DTMF' => 'DTMF', - 'MinimalDTMFGap' => 'MinimalDTMFGap', - 'MinimalDTMFDuration' => 'MinimalDTMFDuration', - 'MinimalDTMFInterval' => 'MinimalDTMFInterval', - 'State' => 'State', - 'AudioState' => 'AudioState', - 'DataState' => 'DataState', - 'Voice' => 'Voice', - 'SMS' => 'SMS', - 'Manufacturer' => 'Manufacturer', - 'Model' => 'Model', - 'Firmware' => 'Firmware', - 'IMEIState' => 'IMEIState', - 'IMSIState' => 'IMSIState', - 'GSMRegistrationStatus' => 'GSMRegistrationStatus', - 'RSSI' => 'RSSI', - 'Mode' => 'Mode', - 'Submode' => 'Submode', - 'ProviderName' => 'ProviderName', - 'LocationAreaCode' => 'LocationAreaCode', - 'CellID' => 'CellID', - 'SubscriberNumber' => 'SubscriberNumber', - 'SMSServiceCenter' => 'SMSServiceCenter', - 'UseUCS2Encoding' => 'UseUCS2Encoding', - 'USSDUse7BitEncoding' => 'USSDUse7BitEncoding', - 'USSDUseUCS2Decoding' => 'USSDUseUCS2Decoding', - 'TasksInQueue' => 'TasksInQueue', - 'CommandsInQueue' => 'CommandsInQueue', - 'CallWaitingState' => 'CallWaitingState', - 'CurrentDeviceState' => 'CurrentDeviceState', - 'DesiredDeviceState' => 'DesiredDeviceState', - 'CallsChannels' => 'CallsChannels', - 'Active' => 'Active', - 'Held' => 'Held', - 'Dialing' => 'Dialing', - 'Alerting' => 'Alerting', - 'Incoming' => 'Incoming', - 'Waiting' => 'Waiting', - 'Releasing' => 'Releasing', - 'Initializing' => 'Initializing' - ), - 'DongleShowDevicesComplete' => array('ListItems' => 'items'), - 'DongleSMSStatus' => array( - 'Privilege' => 'Privilege', - 'Id' => 'Id', - 'Device' => 'Device', - 'Status' => 'Status' - ), - 'DongleStatus' => array( - 'Privilege' => 'Privilege', - 'Device' => 'Device', - 'Status' => 'Status' - ), - 'AgentConnect' => array( - 'HoldTime' => 'HoldTime', - 'Privilege' => 'Privilege', - 'BridgedChannel' => 'BridgedChannel', - 'RingTime' => 'RingTime', - 'Member' => 'Member', - 'MemberName' => 'MemberName', - 'UniqueID' => 'UniqueID', - 'Channel' => 'Channel', - 'Queue' => 'Queue' - ), - 'Agentlogoff' => array( - 'Logintime' => 'Logintime', - 'UniqueID' => 'UniqueID', - 'Agent' => 'Agent', - 'Privilege' => 'Privilege', - ), - 'Agentlogin' => array( - 'UniqueID' => 'UniqueID', - 'Agent' => 'Agent', - 'Privilege' => 'Privilege', - 'Channel' => 'Channel', - ), - 'AgentsComplete' => array(), - 'Agents' => array( - 'TalkingToChannel' => 'TalkingToChannel', - 'TalkingTo' => 'TalkingTo', - 'LoggedInTime' => 'LoggedInTime', - 'LoggedInChan' => 'LoggedInChan', - 'Name' => 'Name', - 'Status' => 'Status', - 'Agent' => 'Agent' - ), - 'ChannelUpdate' => array( - 'Privilege' => 'Privilege', - 'Channel' => 'Channel', - 'ChannelType' => 'ChannelType', - 'UniqueID' => 'UniqueID', - 'SIPfullcontact' => 'SIPfullcontact', - 'SIPcallid' => 'SIPcallid' - ), - 'CoreShowChannel' => array( - 'UniqueID' => 'UniqueID', - 'Privilege' => 'Privilege', - 'Channel' => 'Channel', - 'AccountCode' => 'AccountCode', - 'Priority' => 'Priority', - 'Extension' => 'Extension', - 'Context' => 'Context', - 'CallerIDNum' => 'CallerIDNum', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'ChannelState' => 'ChannelState', - 'ApplicationData' => 'ApplicationData', - 'Application' => 'Application', - 'BridgedUniqueID' => 'BridgedUniqueID', - 'BridgedChannel' => 'BridgedChannel', - 'Duration' => 'Duration', - ), - 'DAHDIShowChannels' => array( - 'Channel' => 'Channel', - 'Context' => 'Context', - 'Alarm' => 'Alarm', - 'DND' => 'DND', - 'SignallingCode' => 'SignallingCode', - 'Signalling' => 'Signalling' - ), - 'Dial' => array( - 'Privilege' => 'Privilege', - 'Destination' => 'Destination', - 'SubEvent' => 'SubEvent', - 'CallerIdName' => 'CallerIdName', - 'CallerIdNum' => 'CallerIdNum', - 'Channel' => 'Channel', - 'DialStatus' => 'DialStatus', - 'DialString' => 'DialString', - 'UniqueID' => 'UniqueID', - 'DestUniqueID' => 'DestUniqueID', - ), - 'ExtensionStatus' => array( - 'Privilege' => 'Privilege', - 'Status' => 'Status', - 'Exten' => 'Extension', - 'Hint' => 'Hint', - 'Context' => 'Context', - ), - 'Hangup' => array( - 'CallerIdName' => 'CallerIdName', - 'CallerIdNum' => 'CallerIdNum', - 'Channel' => 'Channel', - 'Privilege' => 'Privilege', - 'UniqueID' => 'UniqueID', - 'Cause' => 'Cause', - 'cause-txt' => 'cause-txt' - ), - 'Hold' => array( - 'Privilege' => 'Privilege', - 'UniqueID' => 'UniqueID', - 'Status' => 'Status', - 'Channel' => 'Channel', - ), - 'Join' => array( - 'CallerIdName' => 'CallerIdName', - 'CallerIdNum' => 'CallerIdNum', - 'UniqueID' => 'UniqueID', - 'Position' => 'Position', - 'Queue' => 'Queue', - 'Channel' => 'Channel', - 'Privilege' => 'Privilege', - 'Count' => 'Count', - ), - 'Leave' => array( - 'Channel' => 'Channel', - 'Privilege' => 'Privilege', - 'UniqueID' => 'UniqueID', - 'Count' => 'Count', - 'Queue' => 'Queue' - ), - 'ListDialplan' => array( - 'AppData' => 'AppData', - 'Application' => 'Application', - 'Priority' => 'Priority', - 'Extension' => 'Extension', - 'Context' => 'Context', - 'Registrar' => 'Registrar', - 'IncludeContext' => 'IncludeContext' - ), - 'Masquerade' => array( - 'OriginalState' => 'OriginalState', - 'Original' => 'Original', - 'CloneState' => 'CloneState', - 'Clone' => 'Clone', - 'Privilege' => 'Privilege', - ), - 'MessageWaiting' => array( - 'Privilege' => 'Privilege', - 'Waiting' => 'Waiting', - 'Mailbox' => 'Mailbox', - ), - 'MusicOnHold' => array( - 'Channel' => 'Channel', - 'Privilege' => 'Privilege', - 'UniqueID' => 'UniqueID', - 'State' => 'State', - ), - 'NewAccountCode' => array( - 'Channel' => 'Channel', - 'Privilege' => 'Privilege', - 'UniqueID' => 'UniqueID', - 'AccountCode' => 'AccountCode', - 'OldAccountCode' => 'OldAccountCode', - ), - 'NewCallerid' => array( - 'UniqueID' => 'UniqueID', - 'CallerIdName' => 'CallerIdName', - 'CallerIdNum' => 'CallerIdNum', - 'Channel' => 'Channel', - 'Privilege' => 'Privilege', - 'CID-CallingPres' => 'CID-CallingPres' - ), - 'Newchannel' => array( - 'UniqueID' => 'UniqueID', - 'CallerIdName' => 'CallerIdName', - 'CallerIdNum' => 'CallerIdNum', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'ChannelState' => 'ChannelState', - 'AccountCode' => 'AccountCode', - 'Channel' => 'Channel', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Privilege' => 'Privilege' - ), - 'Newexten' => array( - 'Channel' => 'Channel', - 'Privilege' => 'Privilege', - 'AppData' => 'AppData', - 'Application' => 'Application', - 'Priority' => 'Priority', - 'Extension' => 'Extension', - 'Exten' => 'Exten', - 'Context' => 'Context', - 'UniqueID' => 'UniqueID', - ), - 'Newstate' => array( - 'CallerIdName' => 'CallerIdName', - 'CallerIdNum' => 'CallerIdNum', - 'UniqueID' => 'UniqueID', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'ChannelState' => 'ChannelState', - 'Channel' => 'Channel', - 'Privilege' => 'Privilege', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName' - ), - 'OriginateResponse' => array( - 'CallerIdName' => 'CallerIdName', - 'CallerIdNum' => 'CallerIdNum', - 'Response' => 'Response', - 'ActionID' => 'ActionID', - 'UniqueID' => 'UniqueID', - 'Reason' => 'Reason', - 'Channel' => 'Channel', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Privilege' => 'Privilege' - ), - 'PeerEntry' => array( - 'RealtimeDevice' => 'RealtimeDevice', - 'Status' => 'Status', - 'ACL' => 'ACL', - 'TextSupport' => 'TextSupport', - 'VideoSupport' => 'VideoSupport', - 'NatSupport' => 'NatSupport', - 'Dynamic' => 'Dynamic', - 'IPPort' => 'IPPort', - 'IPAddress' => 'IPAddress', - 'ChanObjectType' => 'ChanObjectType', - 'ObjectName' => 'ObjectName', - 'ChannelType' => 'ChannelType', - ), - 'PeerStatus' => array( - 'Privilege' => 'Privilege', - 'ChannelType' => 'ChannelType', - 'Peer' => 'Peer', - 'PeerStatus' => 'PeerStatus' - ), - 'QueueMemberRemoved' => array( - 'MemberName' => 'MemberName', - 'Location' => 'Location', - 'Queue' => 'Queue', - 'Privilege' => 'Privilege' - ), - 'QueueMemberPaused' => array( - 'MemberName' => 'MemberName', - 'Location' => 'Location', - 'Queue' => 'Queue', - 'Privilege' => 'Privilege', - 'Paused' => 1, - ), - 'QueueMember' => array( - 'Name' => 'Name', - 'Location' => 'Location', - 'Queue' => 'Queue', - 'Paused' => 1, - 'Status' => 'Status', - 'CallsTaken' => 'CallsTaken', - 'Penalty' => 'Penalty', - 'Membership' => 'Membership', - ), - 'QueueMemberAdded' => array( - 'MemberName' => 'MemberName', - 'LastCall' => 'LastCall', - 'Location' => 'Location', - 'Queue' => 'Queue', - 'Paused' => 1, - 'Status' => 'Status', - 'CallsTaken' => 'CallsTaken', - 'Penalty' => 'Penalty', - 'Membership' => 'Membership', - 'Privilege' => 'Privilege' - ), - 'QueueMemberStatus' => array( - 'Paused' => 1, - 'Status' => 'Status', - 'CallsTaken' => 'CallsTaken', - 'Penalty' => 'Penalty', - 'Membership' => 'Membership', - 'MemberName' => 'MemberName', - 'Location' => 'Location', - 'Queue' => 'Queue', - 'Privilege' => 'Privilege' - ), - 'QueueParams' => array( - 'Completed' => '4', - 'HoldTime' => '5', - 'Calls' => '6', - 'Strategy' => 'Strategy', - 'Max' => '6', - 'Queue' => 'Queue', - 'Weight' => '2', - 'ServiceLevelPerf' => 'ServiceLevelPerf', - 'ServiceLevel' => '1', - 'Abandoned' => '3' - ), - 'QueueSummaryComplete' => array(), - 'QueueSummary' => array( - 'LongestHoldTime' => 'LongestHoldTime', - 'HoldTime' => 'HoldTime', - 'Callers' => 'Callers', - 'Available' => 'Available', - 'LoggedIn' => 'LoggedIn', - 'Queue' => 'Queue', - ), - 'QueueStatusComplete' => array(), - 'DAHDIShowChannelsComplete' => array('items' => 'ListItems'), - 'PeerlistComplete' => array('ListItems' => 'ListItems'), - 'CoreShowChannelsComplete' => array('ListItems' => 'ListItems'), - 'RTCPReceived' => array( - 'DLSR' => 'DLSR', - 'RTT' => 'RTT', - 'LastSR' => 'LastSR', - 'IAJitter' => 'IAJitter', - 'SequenceNumberCycles' => 'SequenceNumberCycles', - 'HighestSequence' => 'HighestSequence', - 'PacketsLost' => 'PacketsLost', - 'FractionLost' => 'FractionLost', - 'SenderSSRC' => 'SenderSSRC', - 'ReceptionReports' => 'ReceptionReports', - 'PT' => 'PT', - 'Privilege' => 'Privilege', - 'From' => 'From', - ), - 'RTCPReceiverStat' => array( - 'RRCount' => 'RRCount', - 'Jitter' => 'Jitter', - 'LostPackets' => 'LostPackets', - 'ReceivedPackets' => 'ReceivedPackets', - 'SSRC' => 'SSRC', - 'Privilege' => 'Privilege', - 'Transit' => 'Transit' - ), - 'RTCPSent' => array( - 'DLSR' => 'DLSR', - 'TheirLastSR' => 'TheirLastSR', - 'IAJitter' => 'IAJitter', - 'CumulativeLoss' => 'CumulativeLoss', - 'FractionLost' => 'FractionLost', - 'ReportBlock' => 'ReportBlock', - 'SentOctets' => 'SentOctets', - 'SentPackets' => 'SentPackets', - 'SentRTP' => 'SentRTP', - 'SentNTP' => 'SentNTP', - 'OurSSRC' => 'OurSSRC', - 'To' => 'To', - 'Privilege' => 'Privilege' - ), - 'RTPSenderStat' => array( - 'SRCount' => 'SRCount', - 'RTT' => 'RTT', - 'Jitter' => 'Jitter', - 'LostPackets' => 'LostPackets', - 'SentPackets' => 'SentPackets', - 'SSRC' => 'SSRC', - 'Privilege' => 'Privilege' - ), - 'RTPReceiverStat' => array( - 'RRCount' => 'RRCount', - 'Jitter' => 'Jitter', - 'LostPackets' => 'LostPackets', - 'ReceivedPackets' => 'ReceivedPackets', - 'SSRC' => 'SSRC', - 'Privilege' => 'Privilege', - 'Transit' => 'Transit' - ), - 'Rename' => array( - 'UniqueID' => 'UniqueID', - 'Oldname' => 'Oldname', - 'Newname' => 'Newname', - 'Channel' => 'Channel', - 'Privilege' => 'Privilege' - ), - 'ShowDialPlanComplete' => array( - 'listcontexts' => 'listcontexts', - 'listpriorities' => 'listpriorities', - 'listextensions' => 'listextensions', - 'listitems' => 'listitems', - 'privilege' => 'privilege' - ), - 'Status' => array( - 'BridgedUniqueID' => 'BridgedUniqueID', - 'BridgedChannel' => 'BridgedChannel', - 'Seconds' => 'Seconds', - 'AccountCode' => 'AccountCode', - 'Duration' => 'Duration', - 'CallerIDNum' => 'CallerIDNum', - 'ApplicationData' => 'ApplicationData', - 'Application' => 'Application', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'ChannelState' => 'ChannelState', - 'Priority' => 'Priority', - 'Extension' => 'Extension', - 'Context' => 'Context', - 'UniqueID' => 'UniqueID', - 'Privilege' => 'Privilege', - 'Channel' => 'Channel' - ), - 'Transfer' => array( - 'TransferContext' => 'TransferContext', - 'TransferExten' => 'TransferExten', - 'TargetUniqueid' => 'TargetUniqueid', - 'UniqueID' => 'UniqueID', - 'SIP-Callid' => 'SIP-Callid', - 'TargetChannel' => 'TargetChannel', - 'Channel' => 'Channel', - 'TransferType' => 'TransferType', - 'TransferMethod' => 'TransferMethod', - 'Privilege' => 'Privilege' - ), - 'VoicemailUserEntryComplete' => array(), - 'VoicemailUserEntry' => array( - 'VmContext' => 'VmContext', - 'VoicemailBox' => 'VoicemailBox', - 'Fullname' => 'Fullname', - 'Email' => 'Email', - 'Pager' => 'Pager', - 'ServerEmail' => 'ServerEmail', - 'MailCommand' => 'MailCommand', - 'Language' => 'Language', - 'Timezone' => 'Timezone', - 'Callback' => 'Callback', - 'DialOut' => 'DialOut', - 'UniqueID' => 'UniqueID', - 'ExitContext' => 'ExitContext', - 'SayDurationMin' => 'SayDurationMin', - 'SayEnvelope' => 'SayEnvelope', - 'SayCID' => 'SayCID', - 'AttachMessage' => 'AttachMessage', - 'AttachmentFormat' => 'AttachmentFormat', - 'DeleteMessage' => 'DeleteMessage', - 'VolumeGain' => 'VolumeGain', - 'CanReview' => 'CanReview', - 'CallOperator' => 'CallOperator', - 'MaxMessageCount' => 'MaxMessageCount', - 'MaxMessageLength' => 'MaxMessageLength', - 'NewMessageCount' => 'NewMessageCount' - ), - 'DBGetResponse' => array( - 'Family' => 'Family', - 'Key' => 'Key', - 'Val' => 'Val' - ), - 'ParkedCallsComplete' => array(), - 'StatusComplete' => array('Items' => 'Items'), - 'RegistrationsComplete' => array('ListItems' => 'ListItems'), - 'DTMF' => array( - 'Privilege' => 'Privilege', - 'UniqueID' => 'UniqueID', - 'Channel' => 'Channel', - 'Direction' => 'Direction', - 'End' => 'End', - 'Begin' => 'Begin', - 'Digit' => 'Digit' - ), - 'AGIExec' => array( - 'Privilege' => 'Privilege', - 'CommandId' => 'CommandId', - 'SubEvent' => 'SubEvent', - 'Channel' => 'Channel', - 'Command' => 'Command', - 'Result' => 'Result', - 'ResultCode' => 'ResultCode' - ), - 'VarSet' => array( - 'Privilege' => 'Privilege', - 'Channel' => 'Channel', - 'Variable' => 'Variable', - 'Value' => 'Value', - 'UniqueID' => 'UniqueID' - ), - 'Unlink' => array( - 'Privilege' => 'Privilege', - 'CallerID1' => 'CallerID1', - 'CallerID2' => 'CallerID2', - 'UniqueID1' => 'UniqueID1', - 'UniqueID2' => 'UniqueID2', - 'Channel1' => 'Channel1', - 'Channel2' => 'Channel2', - ), - 'Bridge' => array( - 'Privilege' => 'Privilege', - 'CallerID1' => 'CallerID1', - 'CallerID2' => 'CallerID2', - 'UniqueID1' => 'UniqueID1', - 'UniqueID2' => 'UniqueID2', - 'Channel1' => 'Channel1', - 'Channel2' => 'Channel2', - 'BridgeState' => 'BridgeStart', - 'BridgeType' => 'BridgeType' - ), - 'vgsm_sms_rx' => array( - 'Privilege' => 'Privilege', - 'X-SMS-Status-Report-Indication' => 'X-SMS-Status-Report-Indication', - 'X-SMS-User-Data-Header-Indicator' => 'X-SMS-User-Data-Header-Indicator', - 'X-SMS-Reply-Path' => 'X-SMS-Reply-Path', - 'X-SMS-More-Messages-To-Send' => 'X-SMS-More-Messages-To-Send', - 'X-SMS-SMCC-Number' => 'X-SMS-SMCC-Number', - 'X-SMS-SMCC-TON' => 'X-SMS-SMCC-TON', - 'X-SMS-SMCC-NP' => 'X-SMS-SMCC-NP', - 'X-SMS-Sender-Number' => 'X-SMS-Sender-Number', - 'X-SMS-Sender-TON' => 'X-SMS-Sender-TON', - 'X-SMS-Sender-NP' => 'X-SMS-Sender-NP', - 'X-SMS-Message-Type' => 'X-SMS-Message-Type', - 'Content' => 'Content', - 'Date' => 'Date', - 'Content-Transfer-Encoding' => 'ContentEncoding', - 'Content-Type' => 'ContentType', - 'MIME-Version' => 'MIME-Version', - 'Subject' => 'Subject', - 'From' => 'From', - 'Received' => 'Received' - ), - 'vgsm_net_state' => array( - 'Privilege' => 'Privilege', - 'X-vGSM-GSM-Registration' => 'X-vGSM-GSM-Registration', - ), - 'vgsm_me_state' => array( - 'Privilege' => 'Privilege', - 'X-vGSM-ME-State-Change-Reason' => 'X-vGSM-ME-State-Change-Reason', - 'X-vGSM-ME-Old-State' => 'X-vGSM-ME-Old-State', - 'X-vGSM-ME-State' => 'X-vGSM-ME-State', - ), - 'CEL' => array( - 'AMAFlags' => 'AMAFlags', - 'AccountCode' => 'AccountCode', - 'AppData' => 'AppData', - 'Application' => 'Application', - 'CallerIDani' => 'CallerIDani', - 'CallerIDdnid' => 'CallerIDdnid', - 'CallerIDname' => 'CallerIDname', - 'CallerIDnum' => 'CallerIDnum', - 'CallerIDrdnis' => 'CallerIDrdnis', - 'Channel' => 'Channel', - 'Context' => 'Context', - 'Event' => 'Event', - 'EventName' => 'EventName', - 'EventTime' => 'EventTime', - 'Exten' => 'Exten', - 'Extra' => 'Extra', - 'LinkedID' => 'LinkedID', - 'Peer' => 'Peer', - 'PeerAccount' => 'PeerAccount', - 'Privilege' => 'Privilege', - 'Timestamp' => 'Timestamp', - 'UniqueID' => 'UniqueID', - 'Userfield' => 'Userfield', - ), - 'ParkedCall' => array( - 'Privilege' => 'Privilege', - 'Parkinglot' => 'Parkinglot', - 'From' => 'From', - 'Timeout' => 'ParkingTimeout', - 'ConnectedLineNum' => 'ParkeeConnectedLineNum', - 'ConnectedLineName' => 'ParkeeConnectedLineName', - 'Channel' => 'ParkeeChannel', - 'CallerIDNum' => 'ParkeeCallerIDNum', - 'CallerIDName' => 'ParkeeCallerIDName', - 'UniqueID' => 'ParkeeUniqueid', - 'Exten' => 'ParkingSpace', - 'ParkeeChannel' => 'ParkeeChannel', - 'ParkeeChannelState' => 'ParkeeChannelState', - 'ParkeeChannelStateDesc' => 'ParkeeChannelStateDesc', - 'ParkeeCallerIDNum' => 'ParkeeCallerIDNum', - 'ParkeeCallerIDName' => 'ParkeeCallerIDName', - 'ParkeeConnectedLineNum' => 'ParkeeConnectedLineNum', - 'ParkeeConnectedLineName' => 'ParkeeConnectedLineName', - 'ParkeeAccountCode' => 'ParkeeAccountCode', - 'ParkeeContext' => 'ParkeeContext', - 'ParkeeExten' => 'ParkeeExten', - 'ParkeePriority' => 'ParkeePriority', - 'ParkeeUniqueid' => 'ParkeeUniqueid', - 'ParkerDialString' => 'ParkerDialString', - 'ParkingSpace' => 'ParkingSpace', - 'ParkingTimeout' => 'ParkingTimeout', - 'ParkingDuration' => 'ParkingDuration', - ), - 'UnParkedCall' => array( - 'Privilege' => 'Privilege', - 'Parkinglot' => 'Parkinglot', - 'From' => 'RetrieverChannel', - 'ConnectedLineNum' => 'ParkeeConnectedLineNum', - 'ConnectedLineName' => 'ParkeeConnectedLineName', - 'Channel' => 'ParkeeChannel', - 'CallerIDNum' => 'ParkeeCallerIDNum', - 'CallerIDName' => 'ParkeeCallerIDName', - 'UniqueID' => 'ParkeeUniqueid', - 'Exten' => 'ParkingSpace', - 'ParkeeChannel' => 'ParkeeChannel', - 'ParkeeChannelState' => 'ParkeeChannelState', - 'ParkeeChannelStateDesc' => 'ParkeeChannelStateDesc', - 'ParkeeCallerIDNum' => 'ParkeeCallerIDNum', - 'ParkeeCallerIDName' => 'ParkeeCallerIDName', - 'ParkeeConnectedLineNum' => 'ParkeeConnectedLineNum', - 'ParkeeConnectedLineName' => 'ParkeeConnectedLineName', - 'ParkeeAccountCode' => 'ParkeeAccountCode', - 'ParkeeContext' => 'ParkeeContext', - 'ParkeeExten' => 'ParkeeExten', - 'ParkeePriority' => 'ParkeePriority', - 'ParkeeUniqueid' => 'ParkeeUniqueid', - 'ParkerDialString' => 'ParkerDialString', - 'ParkingSpace' => 'ParkingSpace', - 'ParkingTimeout' => 'ParkingTimeout', - 'ParkingDuration' => 'ParkingDuration', - 'ParkerChannel' => 'ParkerChannel', - 'ParkerChannelState' => 'ParkerChannelState', - 'ParkerChannelStateDesc' => 'ParkerChannelStateDesc', - 'ParkerCallerIDNum' => 'ParkerCallerIDNum', - 'ParkerCallerIDName' => 'ParkerCallerIDName', - 'ParkerConnectedLineNum' => 'ParkerConnectedLineNum', - 'ParkerConnectedLineName' => 'ParkerConnectedLineName', - 'ParkerAccountCode' => 'ParkerAccountCode', - 'ParkerContext' => 'ParkerContext', - 'ParkerExten' => 'ParkerExten', - 'ParkerPriority' => 'ParkerPriority', - 'ParkerUniqueid' => 'ParkerUniqueid', - 'RetrieverChannel' => 'RetrieverChannel', - 'RetrieverChannelState' => 'RetrieverChannelState', - 'RetrieverChannelStateDesc' => 'RetrieverChannelStateDesc', - 'RetrieverCallerIDNum' => 'RetrieverCallerIDNum', - 'RetrieverCallerIDName' => 'RetrieverCallerIDName', - 'RetrieverConnectedLineNum' => 'RetrieverConnectedLineNum', - 'RetrieverConnectedLineName' => 'RetrieverConnectedLineName', - 'RetrieverAccountCode' => 'RetrieverAccountCode', - 'RetrieverContext' => 'RetrieverContext', - 'RetrieverExten' => 'RetrieverExten', - 'RetrieverPriority' => 'RetrieverPriority', - 'RetrieverUniqueid' => 'RetrieverUniqueid', - ), - 'Link' => array( - 'Privilege' => 'Privilege', - 'CallerID1' => 'CallerID1', - 'CallerID2' => 'CallerID2', - 'UniqueID1' => 'UniqueID1', - 'UniqueID2' => 'UniqueID2', - 'Channel1' => 'Channel1', - 'Channel2' => 'Channel2' - ), - 'AGIExecStart' => array( - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'Command' => 'Command', - 'CommandId' => 'CommandId', - ), - 'AGIExecEnd' => array( - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'Command' => 'Command', - 'CommandId' => 'CommandId', - 'ResultCode' => 'ResultCode', - 'Result' => 'Result', - ), - 'AsyncAGIStart' => array( - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'Env' => 'Env', - ), - 'AsyncAGIExec' => array( - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'CommandID' => 'CommandID', - 'Result' => 'Result', - ), - 'AsyncAGIEnd' => array( - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - ), - 'QueueCallerJoin' => array( - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'Queue' => 'Queue', - 'Position' => 'Position', - 'Count' => 'Count', - ), - 'QueueCallerLeave' => array( - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'Queue' => 'Queue', - 'Count' => 'Count', - 'Position' => 'Position', - ), - 'AttendedTransfer' => array( - 'Result' => 'Result', - 'OrigTransfererChannel' => 'OrigTransfererChannel', - 'OrigTransfererChannelState' => 'OrigTransfererChannelState', - 'OrigTransfererChannelStateDesc' => 'OrigTransfererChannelStateDesc', - 'OrigTransfererCallerIDNum' => 'OrigTransfererCallerIDNum', - 'OrigTransfererCallerIDName' => 'OrigTransfererCallerIDName', - 'OrigTransfererConnectedLineNum' => 'OrigTransfererConnectedLineNum', - 'OrigTransfererConnectedLineName' => 'OrigTransfererConnectedLineName', - 'OrigTransfererAccountCode' => 'OrigTransfererAccountCode', - 'OrigTransfererContext' => 'OrigTransfererContext', - 'OrigTransfererExten' => 'OrigTransfererExten', - 'OrigTransfererPriority' => 'OrigTransfererPriority', - 'OrigTransfererUniqueid' => 'OrigTransfererUniqueid', - 'OrigBridgeUniqueid' => 'OrigBridgeUniqueid', - 'OrigBridgeType' => 'OrigBridgeType', - 'OrigBridgeTechnology' => 'OrigBridgeTechnology', - 'OrigBridgeCreator' => 'OrigBridgeCreator', - 'OrigBridgeName' => 'OrigBridgeName', - 'OrigBridgeNumChannels' => 'OrigBridgeNumChannels', - 'SecondTransfererChannel' => 'SecondTransfererChannel', - 'SecondTransfererChannelState' => 'SecondTransfererChannelState', - 'SecondTransfererChannelStateDesc' => 'SecondTransfererChannelStateDesc', - 'SecondTransfererCallerIDNum' => 'SecondTransfererCallerIDNum', - 'SecondTransfererCallerIDName' => 'SecondTransfererCallerIDName', - 'SecondTransfererConnectedLineNum' => 'SecondTransfererConnectedLineNum', - 'SecondTransfererConnectedLineName' => 'SecondTransfererConnectedLineName', - 'SecondTransfererAccountCode' => 'SecondTransfererAccountCode', - 'SecondTransfererContext' => 'SecondTransfererContext', - 'SecondTransfererExten' => 'SecondTransfererExten', - 'SecondTransfererPriority' => 'SecondTransfererPriority', - 'SecondTransfererUniqueid' => 'SecondTransfererUniqueid', - 'SecondBridgeUniqueid' => 'SecondBridgeUniqueid', - 'SecondBridgeType' => 'SecondBridgeType', - 'SecondBridgeTechnology' => 'SecondBridgeTechnology', - 'SecondBridgeCreator' => 'SecondBridgeCreator', - 'SecondBridgeName' => 'SecondBridgeName', - 'SecondBridgeNumChannels' => 'SecondBridgeNumChannels', - 'DestType' => 'DestType', - 'DestBridgeUniqueid' => 'DestBridgeUniqueid', - 'DestApp' => 'DestApp', - 'LocalOneChannel' => 'LocalOneChannel', - 'LocalOneChannelState' => 'LocalOneChannelState', - 'LocalOneChannelStateDesc' => 'LocalOneChannelStateDesc', - 'LocalOneCallerIDNum' => 'LocalOneCallerIDNum', - 'LocalOneCallerIDName' => 'LocalOneCallerIDName', - 'LocalOneConnectedLineNum' => 'LocalOneConnectedLineNum', - 'LocalOneConnectedLineName' => 'LocalOneConnectedLineName', - 'LocalOneAccountCode' => 'LocalOneAccountCode', - 'LocalOneContext' => 'LocalOneContext', - 'LocalOneExten' => 'LocalOneExten', - 'LocalOnePriority' => 'LocalOnePriority', - 'LocalOneUniqueid' => 'LocalOneUniqueid', - 'LocalTwoChannel' => 'LocalTwoChannel', - 'LocalTwoChannelState' => 'LocalTwoChannelState', - 'LocalTwoChannelStateDesc' => 'LocalTwoChannelStateDesc', - 'LocalTwoCallerIDNum' => 'LocalTwoCallerIDNum', - 'LocalTwoCallerIDName' => 'LocalTwoCallerIDName', - 'LocalTwoConnectedLineNum' => 'LocalTwoConnectedLineNum', - 'LocalTwoConnectedLineName' => 'LocalTwoConnectedLineName', - 'LocalTwoAccountCode' => 'LocalTwoAccountCode', - 'LocalTwoContext' => 'LocalTwoContext', - 'LocalTwoExten' => 'LocalTwoExten', - 'LocalTwoPriority' => 'LocalTwoPriority', - 'LocalTwoUniqueid' => 'LocalTwoUniqueid', - 'DestTransfererChannel' => 'DestTransfererChannel', - 'TransfereeChannel' => 'TransfereeChannel', - 'TransfereeChannelState' => 'TransfereeChannelState', - 'TransfereeChannelStateDesc' => 'TransfereeChannelStateDesc', - 'TransfereeCallerIDNum' => 'TransfereeCallerIDNum', - 'TransfereeCallerIDName' => 'TransfereeCallerIDName', - 'TransfereeConnectedLineNum' => 'TransfereeConnectedLineNum', - 'TransfereeConnectedLineName' => 'TransfereeConnectedLineName', - 'TransfereeAccountCode' => 'TransfereeAccountCode', - 'TransfereeContext' => 'TransfereeContext', - 'TransfereeExten' => 'TransfereeExten', - 'TransfereePriority' => 'TransfereePriority', - 'TransfereeUniqueid' => 'TransfereeUniqueid', - ), - 'BlindTransfer' => array( - 'Result' => 'Result', - 'TransfererChannel' => 'TransfererChannel', - 'TransfererChannelState' => 'TransfererChannelState', - 'TransfererChannelStateDesc' => 'TransfererChannelStateDesc', - 'TransfererCallerIDNum' => 'TransfererCallerIDNum', - 'TransfererCallerIDName' => 'TransfererCallerIDName', - 'TransfererConnectedLineNum' => 'TransfererConnectedLineNum', - 'TransfererConnectedLineName' => 'TransfererConnectedLineName', - 'TransfererAccountCode' => 'TransfererAccountCode', - 'TransfererContext' => 'TransfererContext', - 'TransfererExten' => 'TransfererExten', - 'TransfererPriority' => 'TransfererPriority', - 'TransfererUniqueid' => 'TransfererUniqueid', - 'TransfereeChannel' => 'TransfereeChannel', - 'TransfereeChannelState' => 'TransfereeChannelState', - 'TransfereeChannelStateDesc' => 'TransfereeChannelStateDesc', - 'TransfereeCallerIDNum' => 'TransfereeCallerIDNum', - 'TransfereeCallerIDName' => 'TransfereeCallerIDName', - 'TransfereeConnectedLineNum' => 'TransfereeConnectedLineNum', - 'TransfereeConnectedLineName' => 'TransfereeConnectedLineName', - 'TransfereeAccountCode' => 'TransfereeAccountCode', - 'TransfereeContext' => 'TransfereeContext', - 'TransfereeExten' => 'TransfereeExten', - 'TransfereePriority' => 'TransfereePriority', - 'TransfereeUniqueid' => 'TransfereeUniqueid', - 'BridgeUniqueid' => 'BridgeUniqueid', - 'BridgeType' => 'BridgeType', - 'BridgeTechnology' => 'BridgeTechnology', - 'BridgeCreator' => 'BridgeCreator', - 'BridgeName' => 'BridgeName', - 'BridgeNumChannels' => 'BridgeNumChannels', - 'IsExternal' => 'IsExternal', - 'Context' => 'Context', - 'Extension' => 'Extension', - ), - 'DialBegin' => array( - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'DestChannel' => 'DestChannel', - 'DestChannelState' => 'DestChannelState', - 'DestChannelStateDesc' => 'DestChannelStateDesc', - 'DestCallerIDNum' => 'DestCallerIDNum', - 'DestCallerIDName' => 'DestCallerIDName', - 'DestConnectedLineNum' => 'DestConnectedLineNum', - 'DestConnectedLineName' => 'DestConnectedLineName', - 'DestAccountCode' => 'DestAccountCode', - 'DestContext' => 'DestContext', - 'DestExten' => 'DestExten', - 'DestPriority' => 'DestPriority', - 'DestUniqueid' => 'DestUniqueid', - 'DialString' => 'DialString', - ), - 'DialEnd' => array( - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'DestChannel' => 'DestChannel', - 'DestChannelState' => 'DestChannelState', - 'DestChannelStateDesc' => 'DestChannelStateDesc', - 'DestCallerIDNum' => 'DestCallerIDNum', - 'DestCallerIDName' => 'DestCallerIDName', - 'DestConnectedLineNum' => 'DestConnectedLineNum', - 'DestConnectedLineName' => 'DestConnectedLineName', - 'DestAccountCode' => 'DestAccountCode', - 'DestContext' => 'DestContext', - 'DestExten' => 'DestExten', - 'DestPriority' => 'DestPriority', - 'DestUniqueid' => 'DestUniqueid', - 'DialStatus' => 'DialStatus', - ), - 'DTMFBegin' => array( - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'Digit' => 'Digit', - 'Direction' => 'Direction', - ), - 'DTMFEnd' => array( - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'Digit' => 'Digit', - 'DurationMs' => 'DurationMs', - 'Direction' => 'Direction', - ), - 'BridgeCreate' => array( - 'BridgeUniqueid' => 'BridgeUniqueid', - 'BridgeType' => 'BridgeType', - 'BridgeTechnology' => 'BridgeTechnology', - 'BridgeCreator' => 'BridgeCreator', - 'BridgeName' => 'BridgeName', - 'BridgeNumChannels' => 'BridgeNumChannels', - ), - 'BridgeDestroy' => array( - 'BridgeUniqueid' => 'BridgeUniqueid', - 'BridgeType' => 'BridgeType', - 'BridgeTechnology' => 'BridgeTechnology', - 'BridgeCreator' => 'BridgeCreator', - 'BridgeName' => 'BridgeName', - 'BridgeNumChannels' => 'BridgeNumChannels', - ), - 'BridgeEnter' => array( - 'BridgeUniqueid' => 'BridgeUniqueid', - 'BridgeType' => 'BridgeType', - 'BridgeTechnology' => 'BridgeTechnology', - 'BridgeCreator' => 'BridgeCreator', - 'BridgeName' => 'BridgeName', - 'BridgeNumChannels' => 'BridgeNumChannels', - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'SwapUniqueid' => 'SwapUniqueid', - ), - 'BridgeLeave' => array( - 'BridgeUniqueid' => 'BridgeUniqueid', - 'BridgeType' => 'BridgeType', - 'BridgeTechnology' => 'BridgeTechnology', - 'BridgeCreator' => 'BridgeCreator', - 'BridgeName' => 'BridgeName', - 'BridgeNumChannels' => 'BridgeNumChannels', - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - ), - 'MusicOnHoldStart' => array( - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'Class' => 'Class', - ), - 'MusicOnHoldStop' => array( - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - ), - 'ConfbridgeStart' => array( - 'Conference' => 'Conference', - 'BridgeUniqueid' => 'BridgeUniqueid', - 'BridgeType' => 'BridgeType', - 'BridgeTechnology' => 'BridgeTechnology', - 'BridgeCreator' => 'BridgeCreator', - 'BridgeName' => 'BridgeName', - 'BridgeNumChannels' => 'BridgeNumChannels', - ), - 'ConfbridgeEnd' => array( - 'Conference' => 'Conference', - 'BridgeUniqueid' => 'BridgeUniqueid', - 'BridgeType' => 'BridgeType', - 'BridgeTechnology' => 'BridgeTechnology', - 'BridgeCreator' => 'BridgeCreator', - 'BridgeName' => 'BridgeName', - 'BridgeNumChannels' => 'BridgeNumChannels', - ), - 'ConfbridgeJoin' => array( - 'Conference' => 'Conference', - 'BridgeUniqueid' => 'BridgeUniqueid', - 'BridgeType' => 'BridgeType', - 'BridgeTechnology' => 'BridgeTechnology', - 'BridgeCreator' => 'BridgeCreator', - 'BridgeName' => 'BridgeName', - 'BridgeNumChannels' => 'BridgeNumChannels', - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'Linkedid' => 'Linkedid', - 'Admin' => 'Admin', - ), - 'ConfbridgeLeave' => array( - 'Conference' => 'Conference', - 'BridgeUniqueid' => 'BridgeUniqueid', - 'BridgeType' => 'BridgeType', - 'BridgeTechnology' => 'BridgeTechnology', - 'BridgeCreator' => 'BridgeCreator', - 'BridgeName' => 'BridgeName', - 'BridgeNumChannels' => 'BridgeNumChannels', - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'Linkedid' => 'Linkedid', - 'Admin' => 'Admin', - ), - 'ConfbridgeMute' => array( - 'Conference' => 'Conference', - 'BridgeUniqueid' => 'BridgeUniqueid', - 'BridgeType' => 'BridgeType', - 'BridgeTechnology' => 'BridgeTechnology', - 'BridgeCreator' => 'BridgeCreator', - 'BridgeName' => 'BridgeName', - 'BridgeNumChannels' => 'BridgeNumChannels', - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'Linkedid' => 'Linkedid', - 'Admin' => 'Admin', - ), - 'ConfbridgeUnmute' => array( - 'Conference' => 'Conference', - 'BridgeUniqueid' => 'BridgeUniqueid', - 'BridgeType' => 'BridgeType', - 'BridgeTechnology' => 'BridgeTechnology', - 'BridgeCreator' => 'BridgeCreator', - 'BridgeName' => 'BridgeName', - 'BridgeNumChannels' => 'BridgeNumChannels', - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'Linkedid' => 'Linkedid', - 'Admin' => 'Admin', - ), - 'ConfbridgeTalking' => array( - 'Conference' => 'Conference', - 'BridgeUniqueid' => 'BridgeUniqueid', - 'BridgeType' => 'BridgeType', - 'BridgeTechnology' => 'BridgeTechnology', - 'BridgeCreator' => 'BridgeCreator', - 'BridgeName' => 'BridgeName', - 'BridgeNumChannels' => 'BridgeNumChannels', - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'Linkedid' => 'Linkedid', - 'TalkingStatus' => 'TalkingStatus', - 'Admin' => 'Admin', - ), - 'ConfbridgeList' => array( - 'Conference' => 'Conference', - 'Channel' => 'Channel', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'MarkedUser' => 'MarkedUser', - 'WaitMarked' => 'WaitMarked', - 'EndMarked' => 'EndMarked', - 'Waiting' => 'Waiting', - 'Muted' => 'Muted', - 'AnsweredTime' => 'AnsweredTime', - 'Admin' => 'Admin', - ), - 'ConfbridgeListComplete' => array('ListItems' => 'ListItems'), - 'BridgeInfoChannel' => array( - 'Channel' => 'Channel', - 'ChannelState' => 'ChannelState', - 'ChannelStateDesc' => 'ChannelStateDesc', - 'CallerIDNum' => 'CallerIDNum', - 'CallerIDName' => 'CallerIDName', - 'ConnectedLineNum' => 'ConnectedLineNum', - 'ConnectedLineName' => 'ConnectedLineName', - 'AccountCode' => 'AccountCode', - 'Context' => 'Context', - 'Exten' => 'Exten', - 'Priority' => 'Priority', - 'Uniqueid' => 'Uniqueid', - 'Linkedid' => 'Linkedid', - ), - 'BridgeInfoComplete' => array( - 'BridgeUniqueid' => 'BridgeUniqueid', - 'BridgeType' => 'BridgeType', - 'BridgeTechnology' => 'BridgeTechnology', - 'BridgeCreator' => 'BridgeCreator', - 'BridgeName' => 'BridgeName', - 'BridgeNumChannels' => 'BridgeNumChannels', - 'BridgeVideoSourceMode' => 'BridgeVideoSourceMode', - 'BridgeVideoSource' => 'BridgeVideoSource', - ), - ); - $eventGetters = array( - 'UserEvent' => array( - 'UserEvent' => 'UserEventName' - ), - 'AsyncAGI' => array( - 'Env' => 'Environment' - ), - 'Agents' => array( - 'LoggedInChan' => 'Channel' - ), - 'ExtensionStatus' => array( - 'Exten' => 'Extension' - ), - 'Hangup' => array( - 'cause-txt' => 'CauseText' - ), - 'ListDialplan' => array( - 'AppData' => 'ApplicationData', - ), - 'NewCallerid' => array( - 'CID-CallingPres' => 'CallerIdPres' - ), - 'Newchannel' => array('Exten' => 'Extension'), - 'Newexten' => array( - 'AppData' => 'ApplicationData', - ), - 'QueueMemberStatus' => array( - 'Paused' => 'Pause' - ), - 'QueueMember' => array( - 'Name' => 'MemberName' - ), - 'AGIExec' => array(), - 'Transfer' => array( - 'SIP-Callid' => 'SipCallID', - ), - 'VoicemailUserEntry' => array( - 'VmContext' => 'VoicemailContext', - ), - 'PeerEntry' => array('ChanObjectType' => 'ChannelObjectType'), - 'VarSet' => array('Variable' => 'VariableName'), - 'StatusComplete' => array('Items' => 'ListItems'), - 'DBGetResponse' => array('Key' => 'KeyName', 'Val' => 'Value'), - 'vgsm_sms_rx' => array( - 'X-SMS-Status-Report-Indication' => 'StatusReportIndication', - 'X-SMS-User-Data-Header-Indicator' => 'DataHeaderIndicator', - 'X-SMS-Reply-Path' => 'ReplyPath', - 'X-SMS-More-Messages-To-Send' => 'MoreMessagesToSend', - 'X-SMS-SMCC-Number' => 'SMCCNumber', - 'X-SMS-SMCC-TON' => 'SMCCTON', - 'X-SMS-SMCC-NP' => 'SMCCNP', - 'X-SMS-Sender-Number' => 'SenderNumber', - 'X-SMS-Sender-TON' => 'SenderTON', - 'X-SMS-Sender-NP' => 'SenderNP', - 'X-SMS-Message-Type' => 'MessageType', - 'Content-Transfer-Encoding' => 'ContentEncoding', - 'Content-Type' => 'ContentType', - 'MIME-Version' => 'MIMEVersion' - ), - 'DAHDIShowChannelsComplete' => array('items' => 'ListItems'), - 'vgsm_net_state' => array('X-vGSM-GSM-Registration' => 'State'), - 'vgsm_me_state' => array( - 'X-vGSM-ME-State-Change-Reason' => 'Reason', - 'X-vGSM-ME-Old-State' => 'OldState', - 'X-vGSM-ME-State' => 'State', - ), - 'ParkedCall' => array('Exten' => 'Extension'), - 'UnParkedCall' => array('Exten' => 'Extension'), - 'AGIExecStart' => array( - - ), - ); - foreach ($eventNames as $eventName) { - $this->_testEvent($eventName, $eventGetters, $eventValues[$eventName], $eventTranslatedValues); - } - } - - private function _testEvent($eventName, array $getters, array $values, array $translatedValues) - { - global $mock_stream_socket_client; - global $mock_stream_set_blocking; - global $mockTime; - global $standardAMIStart; - $eventClass = "\\PAMI\\Message\\Event\\" . $eventName . 'Event'; - $mockTime = true; - $mock_stream_socket_client = true; - $mock_stream_set_blocking = true; - $options = array( - 'host' => '2.3.4.5', - 'scheme' => 'tcp://', - 'port' => 9999, - 'username' => 'asd', - 'secret' => 'asd', - 'connect_timeout' => 10, - 'read_timeout' => 10 - ); - $write = array( - "action: Login\r\nactionid: 1432.123\r\nusername: asd\r\nsecret: asd\r\n" - ); - setFgetsMock($standardAMIStart, $write); - $client = new \PAMI\Client\Impl\ClientImpl($options); - $client->registerEventListener(new SomeListenerClass); - $client->open(); - $message = array(); - $message[] = 'Event: ' . $eventName; - foreach ($values as $key => $value) { - $message[] = $key . ': ' . $value; - } - $message[] = ''; - setFgetsMock($message, $message); - for($i = 0; $i < count($message); $i++) { - $client->process(); - } - $event = SomeListenerClass::$event; - foreach ($values as $key => $value) { - if (isset($getters[$eventName][$key])) { - $methodName = 'get' . $getters[$eventName][$key]; - } else { - $methodName = 'get' . $key; - } - if (isset($translatedValues[$eventName][$key])) { - $value = $translatedValues[$eventName][$key]; - } - - $this->assertTrue( - method_exists($event, $methodName), - sprintf('Method %s doesn\'t exixt in event %s', $methodName, get_class($event)) - ); - - $this->assertEquals($event->$methodName(), $value, $eventName); - } - } -} -} diff --git a/test/resources/php.ini b/test/resources/php.ini deleted file mode 100644 index 2e67c2995..000000000 --- a/test/resources/php.ini +++ /dev/null @@ -1 +0,0 @@ -date.timezone = "UTC" \ No newline at end of file diff --git a/test/resources/phpunit.xml b/test/resources/phpunit.xml deleted file mode 100644 index 44574e675..000000000 --- a/test/resources/phpunit.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - ../../src - - ../../src/PAMI/Application - ../../vendor - - - - - - ../client - - - ../actions - - - ../events - - - - - - - diff --git a/tests/ActionsTest.php b/tests/ActionsTest.php new file mode 100644 index 000000000..153842d10 --- /dev/null +++ b/tests/ActionsTest.php @@ -0,0 +1,1891 @@ + + * @license http://marcelog.github.com/ Apache License 2.0 + * @version SVN: $Id$ + * @link http://marcelog.github.com/ + * + * Copyright 2011 Marcelo Gornstein + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +namespace Tests; + +use Mockery; +use PAMI\Stream\Stream; +use Psr\Log\LoggerInterface; +use PAMI\Client\Impl\ClientImpl; +use PAMI\Exception\PAMIException; +use PAMI\Message\Action\AGIAction; +use PAMI\Message\Action\PingAction; +use PAMI\Message\Action\ParkAction; +use PAMI\Message\Action\DBPutAction; +use PAMI\Message\Action\DBGetAction; +use PAMI\Message\Action\DBDelAction; +use PAMI\Message\Action\LoginAction; +use PAMI\Message\Action\LogoffAction; +use PAMI\Message\Action\QueuesAction; +use PAMI\Message\Action\ReloadAction; +use PAMI\Message\Action\SetVarAction; +use PAMI\Message\Action\StatusAction; +use PAMI\Message\Action\HangupAction; +use PAMI\Message\Action\GetVarAction; +use PAMI\Message\Action\EventsAction; +use PAMI\Message\Action\BridgeAction; +use PAMI\Message\Action\AgentsAction; +use PAMI\Message\Action\ActionMessage; +use PAMI\Message\Action\MonitorAction; +use PAMI\Message\Action\CommandAction; +use PAMI\Message\Action\PlayDTMFAction; +use PAMI\Message\Action\QueueAddAction; +use PAMI\Message\Action\QueueLogAction; +use PAMI\Message\Action\RedirectAction; +use PAMI\Message\Action\SIPPeersAction; +use PAMI\Message\Action\SendTextAction; +use PAMI\Message\Action\WaitEventAction; +use PAMI\Message\Action\UserEventAction; +use PAMI\Message\Action\OriginateAction; +use PAMI\Message\Action\QueueRuleAction; +use PAMI\Message\Action\VGSMSMSTxAction; +use PAMI\Message\Action\SIPNotifyAction; +use PAMI\Message\Action\GetConfigAction; +use PAMI\Message\Action\DBDelTreeAction; +use PAMI\Message\Action\ChallengeAction; +use PAMI\Message\Action\QueueResetAction; +use PAMI\Message\Action\QueuePauseAction; +use PAMI\Message\Action\ModuleLoadAction; +use PAMI\Message\Action\MixMonitorAction; +use PAMI\Message\Action\MeetmeMuteAction; +use PAMI\Message\Action\MeetmeListAction; +use PAMI\Message\Action\JabberSendAction; +use PAMI\Message\Action\DAHDIDNDOnAction; +use PAMI\Message\Action\CoreStatusAction; +use PAMI\Message\Action\DongleStopAction; +use PAMI\Message\Action\BridgeInfoAction; +use PAMI\Message\Action\QueueReloadAction; +use PAMI\Message\Action\QueueRemoveAction; +use PAMI\Message\Action\QueueStatusAction; +use PAMI\Message\Action\ParkedCallsAction; +use PAMI\Message\Action\SIPShowPeerAction; +use PAMI\Message\Action\StopMonitorAction; +use PAMI\Message\Action\ModuleCheckAction; +use PAMI\Message\Action\DAHDIHangupAction; +use PAMI\Message\Action\DAHDIDNDOffAction; +use PAMI\Message\Action\DongleStartAction; +use PAMI\Message\Action\DongleResetAction; +use PAMI\Message\Action\AgentLogoffAction; +use PAMI\Message\Action\UpdateConfigAction; +use PAMI\Message\Action\QueuePenaltyAction; +use PAMI\Message\Action\QueueSummaryAction; +use PAMI\Message\Action\QueueUnpauseAction; +use PAMI\Message\Action\ShowDialPlanAction; +use PAMI\Message\Action\PauseMonitorAction; +use PAMI\Message\Action\ModuleUnloadAction; +use PAMI\Message\Action\ModuleReloadAction; +use PAMI\Message\Action\MeetmeUnmuteAction; +use PAMI\Message\Action\MailboxCountAction; +use PAMI\Message\Action\ListCommandsAction; +use PAMI\Message\Action\DAHDIRestartAction; +use PAMI\Message\Action\CreateConfigAction; +use PAMI\Message\Action\DongleReloadAction; +use PAMI\Message\Action\CoreSettingsAction; +use PAMI\Message\Action\MailboxStatusAction; +use PAMI\Message\Action\GetConfigJSONAction; +use PAMI\Message\Action\DAHDITransferAction; +use PAMI\Message\Action\DongleSendSMSAction; +use PAMI\Message\Action\DongleSendPDUAction; +use PAMI\Message\Action\DongleRestartAction; +use PAMI\Message\Action\ChangeMonitorAction; +use PAMI\Message\Action\BlindTransferAction; +use Mockery\Adapter\Phpunit\MockeryTestCase; +use PAMI\Message\Action\SIPQualifyPeerAction; +use PAMI\Message\Action\StopMixMonitorAction; +use PAMI\Message\Action\UnpauseMonitorAction; +use PAMI\Message\Action\ListCategoriesAction; +use PAMI\Message\Action\ExtensionStateAction; +use PAMI\Message\Action\DongleSendUSSDAction; +use PAMI\Message\Action\ConfbridgeMuteAction; +use PAMI\Message\Action\ConfbridgeListAction; +use PAMI\Message\Action\SIPShowRegistryAction; +use PAMI\Message\Action\AbsoluteTimeoutAction; +use PAMI\Message\Action\DAHDIDialOffHookAction; +use PAMI\Message\Action\ConfbridgeUnmuteAction; +use PAMI\Message\Action\AttendedTransferAction; +use PAMI\Message\Action\LocalOptimizeAwayAction; +use PAMI\Message\Action\DAHDIShowChannelsAction; +use PAMI\Message\Action\DongleShowDevicesAction; +use PAMI\Message\Action\VoicemailUsersListAction; + +/** + * This class will test some actions. + * + * PHP Version 5 + * + * @category Pami + * @package Test + * @subpackage Action + * @author Marcelo Gornstein + * @license http://marcelog.github.com/ Apache License 2.0 + * @link http://marcelog.github.com/ + */ +class ActionsTest extends MockeryTestCase +{ + protected string $microTime; + + protected function setUp(): void + { + parent::setUp(); + + $this->microTime = (string)microtime(true); + setMockedMicroTime($this->microTime); + } + + /** + * @param array $expectedWrite + * @param \PAMI\Message\Action\ActionMessage $action + * + * @return void + * @throws \PAMI\Client\Exception\ClientException + */ + protected function testSendAction(array $expectedWrite, ActionMessage $action): void + { + $options = [ + 'host' => '2.3.4.5', + 'scheme' => 'tcp://', + 'port' => 9999, + 'username' => 'asd', + 'secret' => 'asd', + 'connect_timeout' => 10, + 'read_timeout' => 10, + ]; + $stream = Mockery::mock(Stream::class); + + $logger = Mockery::mock(LoggerInterface::class); + + $client = Mockery::mock(ClientImpl::class, [$options]); + $client->makePartial(); + $client->shouldAllowMockingProtectedMethods(); + + $writeLogin = "action: Login\r\n" . + "actionid: " . $this->microTime . "\r\n" . + "username: asd\r\n" . + "secret: asd\r\n\r\n"; + + $client->setLogger($logger); + + $client->shouldReceive('makeStream')->andReturn($stream); + + $stream->shouldReceive('getLine') + ->once() + ->andReturn('Asterisk 1234'); + + $logger->shouldReceive('debug') + ->zeroOrMoreTimes() + ->withArgs(function (string $message) { + + return str_starts_with($message, '------ Sending: ------'); + }); + + $stream->shouldReceive('write') + ->once() + ->with($writeLogin) + ->andReturn(strlen($writeLogin)); + + $logger->shouldReceive('debug') + ->zeroOrMoreTimes() + ->withArgs(function (string $message) { + + return str_starts_with($message, '------ Received: ------') || $message == '----------------'; + }); + + $stream->shouldReceive('read') + ->times(5) + ->andReturn( + "Asterisk Call Manager/1.1\r\n", + "Response: Success\r\n", + "ActionID: " . $this->microTime . "\r\n", + "Message: Authentication accepted\r\n", + "\r\n\r\n" + ); + + $stream->shouldReceive('endOfFile') + ->andReturnFalse(); + + $stream->shouldReceive('setBlocking') + ->once() + ->with(false); + + $stream->shouldReceive('isConnected') + ->andReturnTrue(); + + $logger->shouldReceive('debug') + ->once() + ->withArgs(function (string $message) { + return 'Logged in successfully to ami.' == $message; + }); + + $client->open(); + + // End of login/open sequence. + + if ($action instanceof DBGetAction) { + $responses = [ + "Response: Success\r\n", + "EventList: start\r\n", + "ActionID: " . $this->microTime . "\r\n", + "\r\n", + "Event: DBGetResponse\r\n", + "ActionID: " . $this->microTime . "\r\n", + "\r\n", + ]; + } else { + $responses = [ + "Response: Success\r\n", + "ActionID: " . $this->microTime . "\r\n", + "\r\n", + ]; + } + + foreach ($expectedWrite as $write) { + $write .= "\r\n"; + $this->assertEquals($write, $action->serialize()); + + $stream->shouldReceive('write') + ->with($write) + ->andReturn(strlen($write)); + } + + $responses[] = "\r\n\r\n"; + + $stream->shouldReceive('read') + ->andReturn(...$responses); + + $client->send($action); + } + + public function testCanAbsoluteTimeout(): void + { + $write = [ + "action: AbsoluteTimeout\r\n" . + "actionid: " . $this->microTime . "\r\n" . + "channel: SIP/asd\r\n" . + "timeout: 10\r\n", + ]; + $action = new AbsoluteTimeoutAction('SIP/asd', 10); + $this->testSendAction($write, $action); + } + + public function testCanLogin(): void + { + $write = [ + implode("\r\n", [ + 'action: Login', + 'actionid: ' . $this->microTime, + 'username: foo', + 'secret: bar', + '', + ]), + ]; + $action = new LoginAction('foo', 'bar'); + $this->testSendAction($write, $action); + } + + public function testCanLoginWithEvents(): void + { + $write = [ + implode("\r\n", [ + 'action: Login', + 'actionid: ' . $this->microTime, + 'username: foo', + 'secret: bar', + 'events: all', + '', + ]), + ]; + $action = new LoginAction('foo', 'bar', 'all'); + $this->testSendAction($write, $action); + } + + public function testCanAgentLogoff(): void + { + $write = [ + implode("\r\n", [ + 'action: AgentLogoff', + 'actionid: ' . $this->microTime, + 'agent: asd', + 'soft: true', + '', + ]), + ]; + $action = new AgentLogoffAction('asd', true); + $this->testSendAction($write, $action); + } + + public function testCanAgents(): void + { + $write = [ + implode("\r\n", [ + 'action: Agents', + 'actionid: ' . $this->microTime, + '', + ]), + ]; + $action = new AgentsAction; + $this->testSendAction($write, $action); + } + + public function testCanAtxfer(): void + { + $write = [ + implode("\r\n", [ + 'action: Atxfer', + 'actionid: ' . $this->microTime, + 'channel: channel', + 'exten: exten', + 'context: context', + 'priority: priority', + '', + ]), + ]; + $action = new AttendedTransferAction('channel', 'exten', 'context', 'priority'); + $this->testSendAction($write, $action); + } + + public function testCanBlindTransfer(): void + { + $write = [ + implode("\r\n", [ + 'action: BlindTransfer', + 'actionid: ' . $this->microTime, + 'channel: channel', + 'exten: exten', + 'context: context', + '', + ]), + ]; + $action = new BlindTransferAction('channel', 'exten', 'context'); + $this->testSendAction($write, $action); + } + + public function testCanBridge(): void + { + $write = [ + implode("\r\n", [ + 'action: Bridge', + 'actionid: ' . $this->microTime, + 'channel1: channel1', + 'channel2: channel2', + 'tone: true', + '', + ]), + ]; + $action = new BridgeAction('channel1', 'channel2', true); + $this->testSendAction($write, $action); + } + + public function testCanBridgeInfo(): void + { + $bridge_uniqueid = '57cb3a7e-0fa3-4e28-924f-d7728b0d7a9a'; + + $write = [ + implode("\r\n", [ + 'action: BridgeInfo', + 'actionid: ' . $this->microTime, + 'bridgeuniqueid: ' . $bridge_uniqueid, + '', + ]), + ]; + $action = new BridgeInfoAction($bridge_uniqueid); + $this->testSendAction($write, $action); + } + + public function testCanChallenge(): void + { + $write = [ + implode("\r\n", [ + 'action: Challenge', + 'actionid: ' . $this->microTime, + 'authtype: test', + '', + ]), + ]; + $action = new ChallengeAction('test'); + $this->testSendAction($write, $action); + } + + public function testCanChangeMonitor(): void + { + $write = [ + implode("\r\n", [ + 'action: ChangeMonitor', + 'actionid: ' . $this->microTime, + 'channel: channel', + 'file: file', + '', + ]), + ]; + $action = new ChangeMonitorAction('channel', 'file'); + $this->testSendAction($write, $action); + } + + public function testCanCommand(): void + { + $write = [ + implode("\r\n", [ + 'action: Command', + 'actionid: ' . $this->microTime, + 'command: command', + '', + ]), + ]; + $action = new CommandAction('command'); + $this->testSendAction($write, $action); + } + + public function testCanConfbridgeList(): void + { + $conference = 'conf-59dba3997444e5'; + $write = [ + implode("\r\n", [ + 'action: ConfbridgeList', + 'actionid: ' . $this->microTime, + 'conference: ' . $conference, + '', + ]), + ]; + + $action = new ConfbridgeListAction($conference); + $this->testSendAction($write, $action); + } + + public function testCanConfbridgeMute(): void + { + $write = [ + implode("\r\n", [ + 'action: ConfbridgeMute', + 'actionid: ' . $this->microTime, + 'channel: channel', + 'conference: conference', + '', + ]), + ]; + $action = new ConfbridgeMuteAction('channel', 'conference'); + $this->testSendAction($write, $action); + } + + public function testCanConfbridgeUnmute(): void + { + $write = [ + implode("\r\n", [ + 'action: ConfbridgeUnmute', + 'actionid: ' . $this->microTime, + 'channel: channel', + 'conference: conference', + '', + ]), + ]; + $action = new ConfbridgeUnmuteAction('channel', 'conference'); + $this->testSendAction($write, $action); + } + + public function testCanCoreSettings(): void + { + $write = [ + implode("\r\n", [ + 'action: CoreSettings', + 'actionid: ' . $this->microTime, + '', + ]), + ]; + $action = new CoreSettingsAction; + $this->testSendAction($write, $action); + } + + public function testCanDongleShowDevices(): void + { + $write = [ + implode("\r\n", [ + 'action: DongleShowDevices', + 'actionid: ' . $this->microTime, + '', + ]), + ]; + $action = new DongleShowDevicesAction; + $this->testSendAction($write, $action); + } + + public function testCanDongleReload(): void + { + $write = [ + implode("\r\n", [ + 'action: DongleReload', + 'actionid: ' . $this->microTime, + 'when: when', + '', + ]), + ]; + $action = new DongleReloadAction('when'); + $this->testSendAction($write, $action); + } + + public function testCanDongleRestart(): void + { + $write = [ + implode("\r\n", [ + 'action: DongleRestart', + 'actionid: ' . $this->microTime, + 'when: when', + 'device: device', + '', + ]), + ]; + $action = new DongleRestartAction('when', 'device'); + $this->testSendAction($write, $action); + } + + public function testCanDongleReset(): void + { + $write = [ + implode("\r\n", [ + 'action: DongleReset', + 'actionid: ' . $this->microTime, + 'device: device', + '', + ]), + ]; + $action = new DongleResetAction('device'); + $this->testSendAction($write, $action); + } + + public function testCanDongleSendPdu(): void + { + $write = [ + implode("\r\n", [ + 'action: DongleSendPDU', + 'actionid: ' . $this->microTime, + 'device: device', + 'pdu: pdu', + '', + ]), + ]; + $action = new DongleSendPDUAction('device', 'pdu'); + $this->testSendAction($write, $action); + } + + public function testCanDongleSendUssd(): void + { + $write = [ + implode("\r\n", [ + 'action: DongleSendUSSD', + 'actionid: ' . $this->microTime, + 'device: device', + 'ussd: ussd', + '', + ]), + ]; + $action = new DongleSendUSSDAction('device', 'ussd'); + $this->testSendAction($write, $action); + } + + public function testCanDongleStop(): void + { + $write = [ + implode("\r\n", [ + 'action: DongleStop', + 'actionid: ' . $this->microTime, + 'when: when', + 'device: device', + '', + ]), + ]; + $action = new DongleStopAction('when', 'device'); + $this->testSendAction($write, $action); + } + + public function testCanDongleStart(): void + { + $write = [ + implode("\r\n", [ + 'action: DongleStart', + 'actionid: ' . $this->microTime, + 'device: device', + '', + ]), + ]; + $action = new DongleStartAction('device'); + $this->testSendAction($write, $action); + } + + public function testCanDongleSmsSend(): void + { + $write = [ + implode("\r\n", [ + 'action: DongleSendSMS', + 'actionid: ' . $this->microTime, + 'device: device', + 'number: number', + 'message: message', + '', + ]), + ]; + $action = new DongleSendSMSAction('device', 'number', 'message'); + $this->testSendAction($write, $action); + } + + public function testCanCoreStatus(): void + { + $write = [ + implode("\r\n", [ + 'action: CoreStatus', + 'actionid: ' . $this->microTime, + '', + ]), + ]; + $action = new CoreStatusAction; + $this->testSendAction($write, $action); + } + + public function testCanCreateConfig(): void + { + $write = [ + implode("\r\n", [ + 'action: CreateConfig', + 'actionid: ' . $this->microTime, + 'filename: file.conf', + '', + ]), + ]; + $action = new CreateConfigAction('file.conf'); + $this->testSendAction($write, $action); + } + + public function testCanDahdiDndoff(): void + { + $write = [ + implode("\r\n", [ + 'action: DAHDIDNDOff', + 'actionid: ' . $this->microTime, + 'dahdichannel: channel', + '', + ]), + ]; + $action = new DAHDIDNDOffAction('channel'); + $this->testSendAction($write, $action); + } + + public function testCanDahdiDndon(): void + { + $write = [ + implode("\r\n", [ + 'action: DAHDIDNDOn', + 'actionid: ' . $this->microTime, + 'dahdichannel: channel', + '', + ]), + ]; + $action = new DAHDIDNDOnAction('channel'); + $this->testSendAction($write, $action); + } + + public function testCanDahdiDialoffhook(): void + { + $write = [ + implode("\r\n", [ + 'action: DAHDIDialOffhook', + 'actionid: ' . $this->microTime, + 'dahdichannel: channel', + 'number: number', + '', + ]), + ]; + $action = new DAHDIDialOffHookAction('channel', 'number'); + $this->testSendAction($write, $action); + } + + public function testCanDahdiHangup(): void + { + $write = [ + implode("\r\n", [ + 'action: DAHDIHangup', + 'actionid: ' . $this->microTime, + 'dahdichannel: channel', + '', + ]), + ]; + $action = new DAHDIHangupAction('channel'); + $this->testSendAction($write, $action); + } + + public function testCanDahdiRestart(): void + { + $write = [ + implode("\r\n", [ + 'action: DAHDIRestart', + 'actionid: ' . $this->microTime, + '', + ]), + ]; + $action = new DAHDIRestartAction; + $this->testSendAction($write, $action); + } + + public function testCanDahdiShowChannels(): void + { + $write = [ + implode("\r\n", [ + 'action: DAHDIShowChannels', + 'actionid: ' . $this->microTime, + '', + ]), + ]; + $action = new DAHDIShowChannelsAction; + $this->testSendAction($write, $action); + } + + public function testCanDahdiTransfer(): void + { + $write = [ + implode("\r\n", [ + 'action: DAHDITransfer', + 'actionid: ' . $this->microTime, + 'dahdichannel: channel', + '', + ]), + ]; + $action = new DAHDITransferAction('channel'); + $this->testSendAction($write, $action); + } + + public function testCanDbdel(): void + { + $write = [ + implode("\r\n", [ + 'action: DBDel', + 'actionid: ' . $this->microTime, + 'family: family', + 'key: key', + '', + ]), + ]; + $action = new DBDelAction('family', 'key'); + $this->testSendAction($write, $action); + } + + public function testCanDbdeltree(): void + { + $write = [ + implode("\r\n", [ + 'action: DBDelTree', + 'actionid: ' . $this->microTime, + 'family: family', + 'key: key', + '', + ]), + ]; + $action = new DBDelTreeAction('family', 'key'); + $this->testSendAction($write, $action); + } + + public function testCanDbget(): void + { + $write = [ + implode("\r\n", [ + 'action: DBGet', + 'actionid: ' . $this->microTime, + 'family: family', + 'key: key', + '', + ]), + ]; + $action = new DBGetAction('family', 'key'); + $this->testSendAction($write, $action); + } + + public function testCanDbput(): void + { + $write = [ + implode("\r\n", [ + 'action: DBPut', + 'actionid: ' . $this->microTime, + 'family: family', + 'key: key', + 'val: val', + '', + ]), + ]; + $action = new DBPutAction('family', 'key', 'val'); + $this->testSendAction($write, $action); + } + + public function testCanEventsOff(): void + { + $write = [ + implode("\r\n", [ + 'action: Events', + 'actionid: ' . $this->microTime, + 'eventmask: off', + '', + ]), + ]; + $action = new EventsAction; + $this->testSendAction($write, $action); + } + + public function testCanEvents(): void + { + $write = [ + implode("\r\n", [ + 'action: Events', + 'actionid: ' . $this->microTime, + 'eventmask: a,b,c', + '', + ]), + ]; + $action = new EventsAction(['a', 'b', 'c']); + $this->testSendAction($write, $action); + } + + public function testCanExtensionState(): void + { + $write = [ + implode("\r\n", [ + 'action: ExtensionState', + 'actionid: ' . $this->microTime, + 'exten: exten', + 'context: context', + '', + ]), + ]; + $action = new ExtensionStateAction('exten', 'context'); + $this->testSendAction($write, $action); + } + + public function testCanGetConfig(): void + { + $write = [ + implode("\r\n", [ + 'action: GetConfig', + 'actionid: ' . $this->microTime, + 'filename: file.conf', + 'category: category', + '', + ]), + ]; + $action = new GetConfigAction('file.conf', 'category'); + $this->testSendAction($write, $action); + } + + public function testCanGetConfigjson(): void + { + $write = [ + implode("\r\n", [ + 'action: GetConfigJSON', + 'actionid: ' . $this->microTime, + 'filename: file.conf', + '', + ]), + ]; + $action = new GetConfigJSONAction('file.conf'); + $this->testSendAction($write, $action); + } + + public function testCanGetVar(): void + { + $write = [ + implode("\r\n", [ + 'action: Getvar', + 'actionid: ' . $this->microTime, + 'variable: var', + 'channel: channel', + '', + ]), + ]; + $action = new GetVarAction('var', 'channel'); + $this->testSendAction($write, $action); + } + + public function testCanHangup(): void + { + $write = [ + implode("\r\n", [ + 'action: Hangup', + 'actionid: ' . $this->microTime, + 'channel: channel', + '', + ]), + ]; + $action = new HangupAction('channel'); + $this->testSendAction($write, $action); + } + + public function testCanHangupWithCause(): void + { + $write = [ + implode("\r\n", [ + 'action: Hangup', + 'actionid: ' . $this->microTime, + 'channel: channel', + 'cause: 5', + '', + ]), + ]; + $action = new HangupAction('channel', 5); + $this->testSendAction($write, $action); + } + + public function testCanJabbersend(): void + { + $write = [ + implode("\r\n", [ + 'action: JabberSend', + 'actionid: ' . $this->microTime, + 'jabber: jabber', + 'jid: jid', + 'screenname: jid', + 'message: message', + '', + ]), + ]; + $action = new JabberSendAction('jabber', 'jid', 'message'); + $this->testSendAction($write, $action); + } + + public function testCanListCategories(): void + { + $write = [ + implode("\r\n", [ + 'action: ListCategories', + 'actionid: ' . $this->microTime, + 'filename: file.conf', + '', + ]), + ]; + $action = new ListCategoriesAction('file.conf'); + $this->testSendAction($write, $action); + } + + public function testCanListCommands(): void + { + $write = [ + implode("\r\n", [ + 'action: ListCommands', + 'actionid: ' . $this->microTime, + '', + ]), + ]; + $action = new ListCommandsAction; + $this->testSendAction($write, $action); + } + + public function testCanLocalOptimizeAway(): void + { + $write = [ + implode("\r\n", [ + 'action: LocalOptimizeAway', + 'actionid: ' . $this->microTime, + 'channel: channel', + '', + ]), + ]; + $action = new LocalOptimizeAwayAction('channel'); + $this->testSendAction($write, $action); + } + + public function testCanMailbox_count(): void + { + $write = [ + implode("\r\n", [ + 'action: MailboxCount', + 'actionid: ' . $this->microTime, + 'mailbox: mailbox', + '', + ]), + ]; + $action = new MailboxCountAction('mailbox'); + $this->testSendAction($write, $action); + } + + public function testCanMailboxStatus(): void + { + $write = [ + implode("\r\n", [ + 'action: MailboxStatus', + 'actionid: ' . $this->microTime, + 'mailbox: mailbox', + '', + ]), + ]; + $action = new MailboxStatusAction('mailbox'); + $this->testSendAction($write, $action); + } + + public function testCanMeetmeList(): void + { + $write = [ + implode("\r\n", [ + 'action: MeetmeList', + 'actionid: ' . $this->microTime, + 'conference: conference', + '', + ]), + ]; + $action = new MeetmeListAction('conference'); + $this->testSendAction($write, $action); + } + + public function testCanMeetmeMute(): void + { + $write = [ + implode("\r\n", [ + 'action: MeetmeMute', + 'actionid: ' . $this->microTime, + 'meetme: meetme', + 'usernum: usernum', + '', + ]), + ]; + $action = new MeetmeMuteAction('meetme', 'usernum'); + $this->testSendAction($write, $action); + } + + public function testCanMeetmeUnmute(): void + { + $write = [ + implode("\r\n", [ + 'action: MeetmeUnmute', + 'actionid: ' . $this->microTime, + 'meetme: meetme', + 'usernum: usernum', + '', + ]), + ]; + $action = new MeetmeUnmuteAction('meetme', 'usernum'); + $this->testSendAction($write, $action); + } + + public function testCanMixMonitor(): void + { + $write = [ + implode("\r\n", [ + 'action: MixMonitor', + 'actionid: ' . $this->microTime, + 'channel: channel', + 'file: file', + 'options: options', + '', + ]), + ]; + $action = new MixMonitorAction('channel'); + $action->setFile('file'); + $action->setOptions(['o', 'p', 't', 'i', 'o', 'n', 's']); + $this->testSendAction($write, $action); + } + + public function testCanModuleCheck(): void + { + $write = [ + implode("\r\n", [ + 'action: ModuleCheck', + 'actionid: ' . $this->microTime, + 'module: module', + '', + ]), + ]; + $action = new ModuleCheckAction('module'); + $this->testSendAction($write, $action); + } + + public function testCanModuleLoad(): void + { + $write = [ + implode("\r\n", [ + 'action: ModuleLoad', + 'actionid: ' . $this->microTime, + 'module: module', + 'loadtype: load', + '', + ]), + ]; + $action = new ModuleLoadAction('module'); + $this->testSendAction($write, $action); + } + + public function testCanModuleReload(): void + { + $write = [ + implode("\r\n", [ + 'action: ModuleLoad', + 'actionid: ' . $this->microTime, + 'module: module', + 'loadtype: reload', + '', + ]), + ]; + $action = new ModuleReloadAction('module'); + $this->testSendAction($write, $action); + } + + public function testCanModuleUnload(): void + { + $write = [ + implode("\r\n", [ + 'action: ModuleLoad', + 'actionid: ' . $this->microTime, + 'module: module', + 'loadtype: unload', + '', + ]), + ]; + $action = new ModuleUnloadAction('module'); + $this->testSendAction($write, $action); + } + + public function testCanMonitor(): void + { + $write = [ + implode("\r\n", [ + 'action: Monitor', + 'actionid: ' . $this->microTime, + 'channel: channel', + 'mix: true', + 'format: wav', + 'file: file', + '', + ]), + ]; + $action = new MonitorAction('channel', 'file'); + $this->testSendAction($write, $action); + } + + public function testCanVoicemailUsersList(): void + { + $write = [ + implode("\r\n", [ + 'action: VoicemailUsersList', + 'actionid: ' . $this->microTime, + '', + ]), + ]; + $action = new VoicemailUsersListAction; + $this->testSendAction($write, $action); + } + + public function testCanPause_monitor(): void + { + $write = [ + implode("\r\n", [ + 'action: PauseMonitor', + 'actionid: ' . $this->microTime, + 'channel: channel', + '', + ]), + ]; + $action = new PauseMonitorAction('channel'); + $this->testSendAction($write, $action); + } + + public function testCanUnpauseMonitor(): void + { + $write = [ + implode("\r\n", [ + 'action: UnpauseMonitor', + 'actionid: ' . $this->microTime, + 'channel: channel', + '', + ]), + ]; + $action = new UnpauseMonitorAction('channel'); + $this->testSendAction($write, $action); + } + + public function testCanStopMonitor(): void + { + $write = [ + implode("\r\n", [ + 'action: StopMonitor', + 'actionid: ' . $this->microTime, + 'channel: channel', + '', + ]), + ]; + $action = new StopMonitorAction('channel'); + $this->testSendAction($write, $action); + } + + public function testCanStopMixMonitor(): void + { + $write = [ + implode("\r\n", [ + 'action: StopMixMonitor', + 'actionid: ' . $this->microTime, + 'channel: channel', + 'mixmonitorid: mix_monitor', + '', + ]), + ]; + $action = new StopMixMonitorAction('channel'); + $action->setMixMonitorId('mix_monitor'); + $this->testSendAction($write, $action); + } + + public function testCanStatus(): void + { + $write = [ + implode("\r\n", [ + 'action: Status', + 'actionid: ' . $this->microTime, + 'channel: channel', + '', + ]), + ]; + $action = new StatusAction('channel'); + $this->testSendAction($write, $action); + } + + public function testCanShowDialplan(): void + { + $write = [ + implode("\r\n", [ + 'action: ShowDialPlan', + 'actionid: ' . $this->microTime, + 'context: context', + 'extension: extension', + '', + ]), + ]; + $action = new ShowDialPlanAction('context', 'extension'); + $this->testSendAction($write, $action); + } + + public function testCanSetVar(): void + { + $write = [ + implode("\r\n", [ + 'action: Setvar', + 'actionid: ' . $this->microTime, + 'variable: variable', + 'value: value', + 'channel: channel', + '', + ]), + ]; + $action = new SetVarAction('variable', 'value', 'channel'); + $this->testSendAction($write, $action); + } + + public function testCanReload(): void + { + $write = [ + implode("\r\n", [ + 'action: Reload', + 'actionid: ' . $this->microTime, + 'module: module', + '', + ]), + ]; + $action = new ReloadAction('module'); + $this->testSendAction($write, $action); + } + + public function testCanPing(): void + { + $write = [ + implode("\r\n", [ + 'action: Ping', + 'actionid: ' . $this->microTime, + '', + ]), + ]; + $action = new PingAction; + $this->testSendAction($write, $action); + } + + public function testCanSendText(): void + { + $write = [ + implode("\r\n", [ + 'action: SendText', + 'actionid: ' . $this->microTime, + 'channel: channel', + 'message: message', + '', + ]), + ]; + $action = new SendTextAction('channel', 'message'); + $this->testSendAction($write, $action); + } + + public function testCanSipShowRegistry(): void + { + $write = [ + implode("\r\n", [ + 'action: SIPshowregistry', + 'actionid: ' . $this->microTime, + '', + ]), + ]; + $action = new SIPShowRegistryAction; + $this->testSendAction($write, $action); + } + + public function testCanSipPeers(): void + { + $write = [ + implode("\r\n", [ + 'action: Sippeers', + 'actionid: ' . $this->microTime, + '', + ]), + ]; + $action = new SIPPeersAction; + $this->testSendAction($write, $action); + } + + public function testCanSipNotify(): void + { + $write = [ + implode("\r\n", [ + 'action: SIPnotify', + 'actionid: ' . $this->microTime, + 'channel: channel', + '', + ]), + ]; + $action = new SIPNotifyAction('channel'); + $this->testSendAction($write, $action); + } + + public function testCanSipShowPeer(): void + { + $write = [ + implode("\r\n", [ + 'action: SIPshowpeer', + 'actionid: ' . $this->microTime, + 'peer: peer', + '', + ]), + ]; + $action = new SIPShowPeerAction('peer'); + $this->testSendAction($write, $action); + } + + public function testCanSipQualifyPeer(): void + { + $write = [ + implode("\r\n", [ + 'action: Sipqualifypeer', + 'actionid: ' . $this->microTime, + 'peer: peer', + '', + ]), + ]; + $action = new SIPQualifyPeerAction('peer'); + $this->testSendAction($write, $action); + } + + public function testCanVgsmSmsTx(): void + { + $write = [ + implode("\r\n", [ + 'action: vgsm_sms_tx', + 'actionid: ' . $this->microTime, + 'account: account', + 'x-sms-concatenate-total-messages: totalmsg', + 'x-sms-concatenate-sequence-number: seqnum', + 'x-sms-concatenate-refid: refid', + 'x-sms-class: class', + 'content: content', + 'x-sms-me: me', + 'content-transfer-encoding: encoding', + 'content-type: type', + 'to: to', + '', + ]), + ]; + $action = new VGSMSMSTxAction; + $action->setAccount('account'); + $action->setConcatTotalMsg('totalmsg'); + $action->setConcatSeqNum('seqnum'); + $action->setConcatRefId('refid'); + $action->setSmsClass('class'); + $action->setContent('content'); + $action->setMe('me'); + $action->setContentEncoding('encoding'); + $action->setContentType('type'); + $action->setTo('to'); + $this->testSendAction($write, $action); + } + + public function testCanParkedCalls(): void + { + $write = [ + implode("\r\n", [ + 'action: ParkedCalls', + 'actionid: ' . $this->microTime, + '', + ]), + ]; + $action = new ParkedCallsAction; + $this->testSendAction($write, $action); + } + + public function testCanQueues(): void + { + $write = [ + implode("\r\n", [ + 'action: Queues', + 'actionid: ' . $this->microTime, + '', + ]), + ]; + $action = new QueuesAction; + $this->testSendAction($write, $action); + } + + public function testCanRedirect(): void + { + $write = [ + implode("\r\n", [ + 'action: Redirect', + 'actionid: ' . $this->microTime, + 'channel: channel', + 'exten: extension', + 'context: context', + 'priority: priority', + 'extrapriority: extrapriority', + 'extracontext: extracontext', + 'extraexten: extraextension', + 'extrachannel: extrachannel', + '', + ]), + ]; + $action = new RedirectAction('channel', 'extension', 'context', 'priority'); + $action->setExtraPriority('extrapriority'); + $action->setExtraContext('extracontext'); + $action->setExtraExtension('extraextension'); + $action->setExtraChannel('extrachannel'); + $this->testSendAction($write, $action); + } + + public function testCanQueueUnpause(): void + { + $write = [ + implode("\r\n", [ + 'action: QueuePause', + 'actionid: ' . $this->microTime, + 'queue: queue', + 'reason: reason', + 'interface: interface', + 'paused: false', + '', + ]), + ]; + $action = new QueueUnpauseAction('interface', 'queue', 'reason'); + $this->testSendAction($write, $action); + } + + public function testCanQueuePause(): void + { + $write = [ + implode("\r\n", [ + 'action: QueuePause', + 'actionid: ' . $this->microTime, + 'queue: queue', + 'reason: reason', + 'interface: interface', + 'paused: true', + '', + ]), + ]; + $action = new QueuePauseAction('interface', 'queue', 'reason'); + $this->testSendAction($write, $action); + } + + public function testCanQueueSummary(): void + { + $write = [ + implode("\r\n", [ + 'action: QueueSummary', + 'actionid: ' . $this->microTime, + 'queue: queue', + '', + ]), + ]; + $action = new QueueSummaryAction('queue'); + $this->testSendAction($write, $action); + } + + public function testCanQueueStatus(): void + { + $write = [ + implode("\r\n", [ + 'action: QueueStatus', + 'actionid: ' . $this->microTime, + 'queue: queue', + 'member: member', + '', + ]), + ]; + $action = new QueueStatusAction('queue', 'member'); + $this->testSendAction($write, $action); + } + + public function testCanQueueReset(): void + { + $write = [ + implode("\r\n", [ + 'action: QueueReset', + 'actionid: ' . $this->microTime, + 'queue: queue', + '', + ]), + ]; + $action = new QueueResetAction('queue'); + $this->testSendAction($write, $action); + } + + public function testCanQueueRule(): void + { + $write = [ + implode("\r\n", [ + 'action: QueueRule', + 'actionid: ' . $this->microTime, + 'rule: rule', + '', + ]), + ]; + $action = new QueueRuleAction('rule'); + $this->testSendAction($write, $action); + } + + public function testCanQueueRemove(): void + { + $write = [ + implode("\r\n", [ + 'action: QueueRemove', + 'actionid: ' . $this->microTime, + 'queue: queue', + 'interface: interface', + '', + ]), + ]; + $action = new QueueRemoveAction('queue', 'interface'); + $this->testSendAction($write, $action); + } + + public function testCanQueueReload(): void + { + $write = [ + implode("\r\n", [ + 'action: QueueReload', + 'actionid: ' . $this->microTime, + 'queue: queue', + 'members: yes', + 'rules: yes', + 'parameters: yes', + '', + ]), + ]; + $action = new QueueReloadAction('queue', true, true, true); + $this->testSendAction($write, $action); + } + + public function testCanQueuePenalty(): void + { + $write = [ + implode("\r\n", [ + 'action: QueuePenalty', + 'actionid: ' . $this->microTime, + 'interface: interface', + 'penalty: penalty', + 'queue: queue', + '', + ]), + ]; + $action = new QueuePenaltyAction('interface', 'penalty', 'queue'); + $this->testSendAction($write, $action); + } + + public function testCanQueueLog(): void + { + $write = [ + implode("\r\n", [ + 'action: QueueLog', + 'actionid: ' . $this->microTime, + 'event: event', + 'queue: queue', + 'message: message', + 'interface: member', + 'uniqueid: uniqueid', + '', + ]), + ]; + $action = new QueueLogAction('queue', 'event'); + $action->setMessage('message'); + $action->setMemberName('member'); + $action->setUniqueId('uniqueid'); + $this->testSendAction($write, $action); + } + + public function testCanQueueAdd(): void + { + $write = [ + implode("\r\n", [ + 'action: QueueAdd', + 'actionid: ' . $this->microTime, + 'interface: interface', + 'queue: queue', + 'paused: true', + 'membername: member', + 'penalty: penalty', + 'stateinterface: state', + '', + ]), + ]; + $action = new QueueAddAction('queue', 'interface'); + $action->setPaused('true'); + $action->setMemberName('member'); + $action->setPenalty('penalty'); + $action->setStateInterface('state'); + $this->testSendAction($write, $action); + } + + public function testCanPlayDtmf(): void + { + $write = [ + implode("\r\n", [ + 'action: PlayDTMF', + 'actionid: ' . $this->microTime, + 'channel: channel', + 'digit: 1', + '', + ]), + ]; + $action = new PlayDTMFAction('channel', '1'); + $this->testSendAction($write, $action); + } + + public function testCanPark(): void + { + $write = [ + implode("\r\n", [ + 'action: Park', + 'actionid: ' . $this->microTime, + 'channel: channel1', + 'channel2: channel2', + 'timeout: 12', + 'parkinglot: lot', + '', + ]), + ]; + $action = new ParkAction('channel1', 'channel2', 12, 'lot'); + $this->testSendAction($write, $action); + } + + public function testCanAgi(): void + { + $write = [ + implode("\r\n", [ + 'action: AGI', + 'actionid: ' . $this->microTime, + 'channel: channel1', + 'command: an agi command', + 'commandid: blah', + '', + ]), + ]; + $action = new AGIAction('channel1', 'an agi command', 'blah'); + $this->testSendAction($write, $action); + } + + public function testCanOriginate(): void + { + $write = [ + implode("\r\n", [ + 'action: Originate', + 'actionid: ' . $this->microTime, + 'channel: channel', + 'codecs: a,b', + 'async: true', + 'account: account', + 'callerid: clid', + 'timeout: timeout', + 'data: data', + 'application: app', + 'priority: priority', + 'context: context', + 'exten: extension', + 'Variable: a=b', + '', + ]), + ]; + $action = new OriginateAction('channel'); + $action->setCodecs(['a', 'b']); + $action->setAsync(true); + $action->setAccount('account'); + $action->setCallerId('clid'); + $action->setTimeout('timeout'); + $action->setData('data'); + $action->setApplication('app'); + $action->setPriority('priority'); + $action->setContext('context'); + $action->setExtension('extension'); + $action->setVariable('a', 'b'); + $this->testSendAction($write, $action); + } + + public function testCanLogoff(): void + { + $write = [ + implode("\r\n", [ + 'action: Logoff', + 'actionid: ' . $this->microTime, + '', + ]), + ]; + $action = new LogoffAction(); + $this->testSendAction($write, $action); + } + + public function testCanUserEvent(): void + { + $write = [ + implode("\r\n", [ + 'action: UserEvent', + 'actionid: ' . $this->microTime, + 'userevent: FooEvent', + 'foo: Bar', + 'bar: Foo', + '', + ]), + ]; + $action = new UserEventAction('FooEvent', ['Foo' => 'Bar', 'Bar' => 'Foo']); + $this->testSendAction($write, $action); + } + + public function testCanWaitEvent(): void + { + $write = [ + implode("\r\n", [ + 'action: WaitEvent', + 'actionid: ' . $this->microTime, + 'timeout: 20', + '', + ]), + ]; + $action = new WaitEventAction(20); + $this->testSendAction($write, $action); + } + + public function testCanSetActionid(): void + { + $action = new PingAction(); + // ActionID is between 0 and 69 characters long. + $actionID = '121234567890123456789012345678901234567890'; + $action->setActionID($actionID); + $this->assertSame($actionID, $action->getActionID()); + } + + public function testCannotSetActionidLongerThan69Characters(): void + { + $this->expectException(PAMIException::class); + $action = new PingAction(); + // A 70-character long ActionID + $action->setActionID('1234567890123456789012345678901234567890123456789012345678901234567890'); + } + + public function testCannotSetEmptyActionid(): void + { + $this->expectException(PAMIException::class); + $action = new PingAction(); + // An empty ActionID + $action->setActionID(''); + } + + public function testCanUpdateConfig(): void + { + $number = 9876; + $writeCreate = [ + implode("\r\n", [ + 'action: UpdateConfig', + 'actionid: ' . $this->microTime, + 'srcfilename: sip.conf', + 'dstfilename: sip.conf', + 'action-000000: NewCat', + 'cat-000000: ' . $number, + 'action-000001: Append', + 'cat-000001: ' . $number, + 'var-000001: username', + 'value-000001: test', + 'action-000002: Append', + 'cat-000002: ' . $number, + 'var-000002: secret', + 'value-000002: secret', + '', + ]), + ]; + + $actionCreate = new UpdateConfigAction(); + + $actionCreate->setSrcFilename('sip.conf'); + $actionCreate->setDstFilename('sip.conf'); + + $actionCreate->setAction('NewCat'); + $actionCreate->setCat($number); + + $actionCreate->setAction('Append'); + $actionCreate->setCat($number); + $actionCreate->setVar('username'); + $actionCreate->setValue('test'); + + $actionCreate->setAction('Append'); + $actionCreate->setCat($number); + $actionCreate->setVar('secret'); + $actionCreate->setValue('secret'); + + $this->testSendAction($writeCreate, $actionCreate); + + $writeDelete = [ + implode("\r\n", [ + 'action: UpdateConfig', + 'actionid: ' . $this->microTime, + 'srcfilename: sip.conf', + 'dstfilename: sip.conf', + 'reload: yes', + 'action-000000: DelCat', + 'cat-000000: ' . $number, + '', + ]), + ]; + + $actionDelete = new UpdateConfigAction(); + + $actionDelete->setSrcFilename('sip.conf'); + $actionDelete->setDstFilename('sip.conf'); + $actionDelete->setReload(true); + $actionDelete->setAction('DelCat'); + $actionDelete->setCat($number); + + $this->testSendAction($writeDelete, $actionDelete); + } +} + diff --git a/tests/ClientTest.php b/tests/ClientTest.php new file mode 100644 index 000000000..a45c3fee0 --- /dev/null +++ b/tests/ClientTest.php @@ -0,0 +1,881 @@ + + * @license http://marcelog.github.com/ Apache License 2.0 + * @link http://marcelog.github.com/ + */ +class ClientTest extends MockeryTestCase +{ + protected string $microTime; + + protected int $time; + + protected function setUp(): void + { + parent::setUp(); + + SomeListenerClass::$event = null; + + $this->microTime = (string)microtime(true); + setMockedMicroTime($this->microTime); + + $this->time = time(); + setMockedTime($this->time); + } + + /** + * @return array{0: ClientImpl|MockInterface|LegacyMockInterface, 1: Stream|MockInterface|LegacyMockInterface} + * @throws \PAMI\Client\Exception\ClientException + */ + protected function makeClientAndStream(): array + { + $options = [ + 'host' => '2.3.4.5', + 'scheme' => 'tcp://', + 'port' => 9999, + 'username' => 'asd', + 'secret' => 'asd', + 'connect_timeout' => 10, + 'read_timeout' => 20, + ]; + $write = + "action: Login\r\n" . + "actionid: " . $this->microTime . "\r\n" . + "username: asd\r\n" . + "secret: asd\r\n\r\n"; + + $stream = Mockery::mock(Stream::class); + + $client = Mockery::mock(ClientImpl::class, [$options]); + $client->makePartial(); + $client->shouldAllowMockingProtectedMethods(); + + $client->shouldReceive('makeStream')->andReturn($stream); + + $stream->shouldReceive('getLine') + ->once() + ->andReturn('Asterisk 1234'); + + $stream->shouldReceive('write') + ->once() + ->with($write) + ->andReturn(strlen($write)); + + $stream->shouldReceive('read') + ->times(5) + ->andReturn( + "Asterisk Call Manager/1.1\r\n", + "Response: Success\r\n", + "ActionID: " . $this->microTime . "\r\n", + "Message: Authentication accepted\r\n", + "\r\n\r\n" + ); + + $stream->shouldReceive('endOfFile') + ->andReturnFalse(); + + $stream->shouldReceive('setBlocking') + ->once() + ->with(false); + + $stream->shouldReceive('isConnected') + ->andReturnTrue(); + + $client->open(); + + return [$client, $stream]; + } + + public function testCanGetClient(): void + { + $options = [ + 'host' => 'tcp://1.1.1.1', + 'port' => 9999, + 'username' => 'asd', + 'secret' => 'asd', + 'connect_timeout' => 10, + 'read_timeout' => 10, + ]; + $client = new ClientImpl($options); + + $this->assertInstanceOf(IClient::class, $client); + } + + public function testCanConnectTimeout(): void + { + $this->expectException(\ErrorException::class); + $this->expectExceptionMessage('timed out'); + + set_error_handler( + /** + * @throws \ErrorException + */ + function (int $errno, string $errstr, string $errfile, int $errline) { + throw new \ErrorException($errstr, $errno, 1, $errfile, $errline); + }); + + $options = [ + 'host' => '2.3.4.5', + 'scheme' => 'tcp://', + 'port' => 9999, + 'username' => 'asd', + 'secret' => 'asd', + 'connect_timeout' => 3, + 'read_timeout' => 10, + ]; + $start = time(); + + $client = new ClientImpl($options); + $client->open(); + + $length = time() - $start; + $this->assertTrue($length >= 2 && $length <= 5); + + restore_error_handler(); + } + + public function testCanDetectOtherPeer(): void + { + $this->expectException(ClientException::class); + $this->expectExceptionMessage('Unknown peer. Is this an ami?'); + + $options = [ + 'host' => '2.3.4.5', + 'scheme' => 'tcp://', + 'port' => 9999, + 'username' => 'asd', + 'secret' => 'asd', + 'connect_timeout' => 10, + 'read_timeout' => 10, + ]; + + $stream = Mockery::mock(Stream::class); + + $client = Mockery::mock(ClientImpl::class, [$options]); + $client->makePartial(); + $client->shouldAllowMockingProtectedMethods(); + + $client->shouldReceive('makeStream')->andReturn($stream); + + $stream->shouldReceive('isConnected')->andReturnTrue(); + + $stream->shouldReceive('getLine') + ->once() + ->andReturn('Whatever'); + + $client->open(); + } + + /** + * @throws \PAMI\Client\Exception\ClientException + */ + public function testCanRegisterEventListener(): void + { + [$client, $stream] = $this->makeClientAndStream(); + + $client->registerEventListener(new SomeListenerClass); + + $events = [ + implode("\r\n", [ + 'Event: PeerStatus', + 'Privilege: system,all', + 'ChannelType: SIP', + 'Peer: SIP/someguy', + 'PeerStatus: Registered', + '', + ]), + "\r\n\r\n", + ]; + + $stream->shouldReceive('read')->andReturn(...$events); + + for ($i = 0; $i < 6; $i++) { + $client->process(); + } + $event = SomeListenerClass::$event; + $this->assertEquals('PeerStatus', $event->getName()); + $this->assertTrue($event instanceof PeerStatusEvent); + } + + /** + * @throws \PAMI\Client\Exception\ClientException + */ + public function testCanRegisterClosureEventListener(): void + { + [$client, $stream] = $this->makeClientAndStream(); + + $resultVariable = false; + $client->registerEventListener(function ($event) use (&$resultVariable) { + $resultVariable = $event; + }); + + $events = [ + implode("\r\n", [ + 'Event: PeerStatus', + 'Privilege: system,all', + 'ChannelType: SIP', + 'Peer: SIP/someguy', + 'PeerStatus: Registered', + '', + ]), + "\r\n\r\n", + ]; + + $stream->shouldReceive('read')->andReturn(...$events); + for ($i = 0; $i < 6; $i++) { + $client->process(); + } + $this->assertEquals('PeerStatus', $resultVariable->getName()); + $this->assertTrue($resultVariable instanceof PeerStatusEvent); + } + + /** + * @throws \PAMI\Client\Exception\ClientException + */ + public function testCanRegisterMethodEventListener(): void + { + [$client, $stream] = $this->makeClientAndStream(); + + $listener = new SomeListenerClass; + $client->registerEventListener([$listener, 'handle']); + $events = [ + implode("\r\n", [ + 'Event: PeerStatus', + 'Privilege: system,all', + 'ChannelType: SIP', + 'Peer: SIP/someguy', + 'PeerStatus: Registered', + '', + ]), + "\r\n\r\n", + ]; + + $stream->shouldReceive('read')->andReturn(...$events); + for ($i = 0; $i < 6; $i++) { + $client->process(); + } + $event = SomeListenerClass::$event; + $this->assertEquals('PeerStatus', $event->getName()); + $this->assertTrue($event instanceof PeerStatusEvent); + } + + /** + * @throws \PAMI\Client\Exception\ClientException + */ + public function testCanUnregisterEventListener(): void + { + [$client, $stream] = $this->makeClientAndStream(); + + $id = $client->registerEventListener(new SomeListenerClass); + + $client->unregisterEventListener($id); + + $events = [ + implode("\r\n", [ + 'Event: PeerStatus', + 'Privilege: system,all', + 'ChannelType: SIP', + 'Peer: SIP/someguy', + 'PeerStatus: Registered', + '', + ]), + "\r\n\r\n", + ]; + + $stream->shouldReceive('read')->andReturn(...$events); + for ($i = 0; $i < 6; $i++) { + $client->process(); + } + + $this->assertNull(SomeListenerClass::$event); + } + + /** + * @throws \PAMI\Client\Exception\ClientException + */ + public function testCanFilterWithPredicate(): void + { + [$client, $stream] = $this->makeClientAndStream(); + + $resultVariable = false; + $client->registerEventListener( + function ($event) use (&$resultVariable) { + $resultVariable = $event; + }, + function () { + return false; + } + ); + + $events = [ + implode("\r\n", [ + 'Event: PeerStatus', + 'Privilege: system,all', + 'ChannelType: SIP', + 'Peer: SIP/someguy', + 'PeerStatus: Registered', + '', + ]), + "\r\n\r\n", + ]; + + $stream->shouldReceive('read')->andReturn(...$events); + for ($i = 0; $i < 6; $i++) { + $client->process(); + } + + $this->assertFalse($resultVariable); + } + + /** + * @throws \PAMI\Client\Exception\ClientException + */ + public function testCanLogin(): void + { + [$client, $stream] = $this->makeClientAndStream(); + + $stream->shouldReceive('close')->once(); + + $client->close(); + } + + public function testCannotSend(): void + { + $this->expectException(ClientException::class); + $this->expectExceptionMessage('Could not send message'); + + $options = [ + 'host' => '2.3.4.5', + 'scheme' => 'tcp://', + 'port' => 9999, + 'username' => 'asd', + 'secret' => 'asd', + 'connect_timeout' => 10, + 'read_timeout' => 10, + ]; + + $stream = Mockery::mock(Stream::class); + + $client = Mockery::mock(ClientImpl::class, [$options]); + $client->makePartial(); + $client->shouldAllowMockingProtectedMethods(); + + $client->shouldReceive('makeStream')->andReturn($stream); + + $stream->shouldReceive('getLine') + ->once() + ->andReturn('Asterisk 1234'); + + $stream->shouldReceive('isConnected') + ->andReturnTrue(); + + $stream->shouldReceive('write') + ->once() + ->andReturn(1); // wrong write length + + $client->open(); + } + + public function testCannotLogin(): void + { + $this->expectException(ClientException::class); + + $options = [ + 'host' => '2.3.4.5', + 'scheme' => 'tcp://', + 'port' => 9999, + 'username' => 'asd', + 'secret' => 'asd', + 'connect_timeout' => 10, + 'read_timeout' => 10, + ]; + $write = + "action: Login\r\n" . + "actionid: " . $this->microTime . "\r\n" . + "username: asd\r\n" . + "secret: asd\r\n\r\n"; + + $stream = Mockery::mock(Stream::class); + + $client = Mockery::mock(ClientImpl::class, [$options]); + $client->makePartial(); + $client->shouldAllowMockingProtectedMethods(); + + $client->shouldReceive('makeStream')->andReturn($stream); + + $stream->shouldReceive('getLine') + ->once() + ->andReturn('Asterisk 1234'); + + $stream->shouldReceive('write') + ->once() + ->with($write) + ->andReturn(strlen($write)); + + $stream->shouldReceive('read') + ->andReturn( + "Asterisk Call Manager/1.1\r\n", + "Response: Error\r\n", // also tests behavior when asterisk does not return an actionid + "Message: Authentication accepted\r\n", + "\r\n", + "\r\n\r\n" + ); + + $stream->shouldReceive('isConnected') + ->andReturnTrue(); + + $stream->shouldReceive('endOfFile') + ->andReturnFalse(); + + $client->open(); + } + + public function testCannotRead(): void + { + $this->expectException(ClientException::class); + $this->expectExceptionMessage('Error reading'); + + $options = [ + 'host' => '2.3.4.5', + 'scheme' => 'tcp://', + 'port' => 9999, + 'username' => 'asd', + 'secret' => 'asd', + 'connect_timeout' => 10, + 'read_timeout' => 10, + ]; + $write = + "action: Login\r\n" . + "actionid: " . $this->microTime . "\r\n" . + "username: asd\r\n" . + "secret: asd\r\n\r\n"; + + $stream = Mockery::mock(Stream::class); + + $client = Mockery::mock(ClientImpl::class, [$options]); + $client->makePartial(); + $client->shouldAllowMockingProtectedMethods(); + + $client->shouldReceive('makeStream')->andReturn($stream); + + $stream->shouldReceive('getLine') + ->once() + ->andReturn('Asterisk 1234'); + + $stream->shouldReceive('write') + ->once() + ->with($write) + ->andReturn(strlen($write)); + + $stream->shouldReceive('read') + ->andReturnFalse(); + + $stream->shouldReceive('isConnected') + ->andReturnTrue(); + + $stream->shouldReceive('endOfFile') + ->andReturnFalse(); + + $client->open(); + } + + /** + * @throws \PAMI\Client\Exception\ClientException + */ + public function testCanGetResponseWithAssociatedEvents(): void + { + [$client, $stream] = $this->makeClientAndStream(); + + $action = new CoreShowChannelsAction(); + + $write = + "action: CoreShowChannels\r\n" . + "actionid: " . $this->microTime . "\r\n" . + "\r\n"; + + $this->assertEquals($write, $action->serialize()); + + $stream->shouldReceive('write') + ->with($write) + ->andReturn(strlen($write)); + + $event = [ + "Response: Success\r\n", + "ActionID: " . $this->microTime . "\r\n", + "Eventlist: start\r\n", + "Message: Channels will follow\r\n", + "\r\n", + "Event: CoreShowChannelsComplete\r\n", + "EventList: Complete\r\n", + "ListItems: 0\r\n", + "ActionID: " . $this->microTime . "\r\n", + "\r\n", + "\r\n\r\n", + ]; + + $stream->shouldReceive('read')->andReturn(...$event); + + $result = $client->send($action); + + $events = $result->getEvents(); + + $this->assertCount(1, $events); + $this->assertTrue($events[0] instanceof CoreShowChannelsCompleteEvent); + $this->assertEquals( + $events[0]->getRawContent(), implode("\r\n", [ + 'Event: CoreShowChannelsComplete', + 'EventList: Complete', + 'ListItems: 0', + 'ActionID: ' . $this->microTime, + ]) + ); + } + + /** + * @throws \PAMI\Client\Exception\ClientException + */ + public function testCanSerializeResponseAndEvents(): void + { + [$client, $stream] = $this->makeClientAndStream(); + + $client->registerEventListener(new SomeListenerClass); + + $action = new CoreShowChannelsAction; + $write = + "action: CoreShowChannels\r\n" . + "actionid: " . $this->microTime . "\r\n" . + "\r\n"; + + $this->assertEquals($write, $action->serialize()); + + $stream->shouldReceive('write') + ->with($write) + ->andReturn(strlen($write)); + + $event = [ + "Response: Success\r\n", + "ActionID: " . $this->microTime . "\r\n", + "Eventlist: start\r\n", + "Message: Channels will follow\r\n", + "\r\n", + "Event: CoreShowChannelsComplete\r\n", + "EventList: Complete\r\n", + "ListItems: 0\r\n", + "ActionID: " . $this->microTime . "\r\n", + "\r\n", + "\r\n\r\n", + ]; + + $stream->shouldReceive('read')->andReturn(...$event); + + $result = $client->send($action); + + $ser = serialize($result); + $result2 = unserialize($ser); + + /** @var array $events */ + $events = $result2->getEvents(); + $this->assertEquals('Channels will follow', $result2->getMessage()); + + $event = $events[0]; + + $this->assertEquals('CoreShowChannelsComplete', $event->getName()); + $this->assertEquals(0, $event->getListItems()); + } + + /** + * @throws \PAMI\Client\Exception\ClientException + */ + public function testCanGetResponseEventsWithoutActionidAndEvent(): void + { + [$client, $stream] = $this->makeClientAndStream(); + + $client->registerEventListener(new SomeListenerClass); + + $event = [ + "Response: Success\r\n", + "ActionID: " . $this->microTime . "\r\n", + "Eventlist: start\r\n", + "Message: Channels will follow\r\n", + "\r\n", + "Channel: pepe\r\n", + "Count: Blah\r\n", + "\r\n", + "Event: CoreShowChannelsComplete\r\n", + "EventList: Complete\r\n", + "ListItems: 0\r\n", + "ActionID: " . $this->microTime . "\r\n", + "\r\n", + "\r\n\r\n", + ]; + + $write = + "action: CoreShowChannels\r\n" . + "actionid: " . $this->microTime . "\r\n" . + "\r\n"; + + $stream->shouldReceive('write') + ->with($write) + ->andReturn(strlen($write)); + + $stream->shouldReceive('read')->andReturn(...$event); + + $action = new CoreShowChannelsAction; + + $this->assertEquals($write, $action->serialize()); + + $result = $client->send($action); + + /** @var array $events */ + $events = $result->getEvents(); + + $this->assertEquals('ResponseEvent', $events[0]->getName()); + $this->assertEquals('pepe', $events[0]->getKey('Channel')); + $this->assertEquals('Blah', $events[0]->getKey('Count')); + $this->assertEquals('CoreShowChannelsComplete', $events[1]->getName()); + $this->assertEquals(0, $events[1]->getListItems()); + } + + public function testCanGetSetVariable(): void + { + $now = time(); + $action = new LoginAction('a', 'b'); + $this->assertEquals($now, $action->getCreatedDate()); + $action->setVariable('variable', 'value'); + $this->assertEquals('value', $action->getVariable('variable')); + $this->assertNull($action->getVariable('variable2')); + } + + public function testCanGetSetVariableWithMultipleValues(): void + { + $action = new LoginAction('a', 'b'); + $this->assertEquals($this->time, $action->getCreatedDate()); + $action->setVariable('variable', ['value1', 'value2']); + $text + = "action: Login\r\n" + . "actionid: " . $this->microTime . "\r\n" + . "username: a\r\n" + . "secret: b\r\n" + . "Variable: variable=value1\r\n" + . "Variable: variable=value2\r\n" + . "\r\n"; + $this->assertEquals($text, $action->serialize()); + } + + /** + * @throws \PAMI\Client\Exception\ClientException + */ + public function testCanReportUnknownEvent(): void + { + [$client, $stream] = $this->makeClientAndStream(); + + $client->registerEventListener(new SomeListenerClass); + + $event = [ + "Event: MyOwnImaginaryEvent\r\n", + "Privilege: system,all\r\n", + "ChannelType: SIP\r\n", + "\r\n", + "\r\n\r\n", + ]; + + $stream->shouldReceive('read')->andReturn(...$event); + + for ($i = 0; $i < 4; $i++) { + $client->process(); + } + $this->assertTrue(SomeListenerClass::$event instanceof UnknownEvent); + } + + /** + * @group channel_vars + * ChanVariable is sent without a channel name and without a "channel" + * key. + * https://github.com/marcelog/PAMI/issues/85 + * @throws \PAMI\Client\Exception\ClientException + */ + public function testCanGetChannelVariablesWithoutDefaultChannelName(): void + { + [$client, $stream] = $this->makeClientAndStream(); + + $client->registerEventListener(new SomeListenerClass); + + $event = [ + "Event: Dial\r\n", + "Privilege: call,all\r\n", + "SubEvent: Begin\r\n", + "Destination: SIP/jw1034-00000010\r\n", + "CallerIDNum: 1201\r\n", + "CallerIDName: \r\n", + "ConnectedLineNum: strategy-sequential\r\n", + "ConnectedLineName: \r\n", + "UniqueID: pbx-1439974866.33\r\n", + "DestUniqueID: pbx-1439974866.34\r\n", + "Dialstring: jw1034\r\n", + "ChanVariable: var1\r\n", + "ChanVariable: var2=v2\r\n", + "\r\n", + "\r\n\r\n", + ]; + + $stream->shouldReceive('read')->andReturn(...$event); + + for ($i = 0; $i < 14; $i++) { + $client->process(); + } + $event = SomeListenerClass::$event; + $varChan = [ + 'var1' => '', + 'var2' => 'v2', + ]; + $channelVars = [ + 'default' => $varChan, + ]; + $this->assertEquals($channelVars, $event->getAllChannelVariables()); + $this->assertEquals($varChan, $event->getChannelVariables()); + $this->assertEquals($varChan, $event->getChannelVariables('default')); + } + + /** + * @group channel_vars + * ChanVariable is sent without a channel name but with a "channel" key. + * https://github.com/marcelog/PAMI/issues/85 + * @throws \PAMI\Client\Exception\ClientException + */ + public function testCanGetChannelVariablesWithDefaultChannelName(): void + { + [$client, $stream] = $this->makeClientAndStream(); + + $client->registerEventListener(new SomeListenerClass); + + $event = [ + "Event: Dial\r\n", + "Privilege: call,all\r\n", + "Channel: Local/0@pbx_dial_callroute_to_endpoint-00000008;2\r\n", + "SubEvent: Begin\r\n", + "Destination: SIP/jw1034-00000010\r\n", + "CallerIDNum: 1201\r\n", + "CallerIDName: \r\n", + "ConnectedLineNum: strategy-sequential\r\n", + "ConnectedLineName: \r\n", + "UniqueID: pbx-1439974866.33\r\n", + "DestUniqueID: pbx-1439974866.34\r\n", + "Dialstring: jw1034\r\n", + "ChanVariable: var1\r\n", + "ChanVariable: var2=v2\r\n", + "\r\n", + "\r\n\r\n", + ]; + $stream->shouldReceive('read')->andReturn(...$event); + + for ($i = 0; $i < 15; $i++) { + $client->process(); + } + $event = SomeListenerClass::$event; + $varChan = [ + 'var1' => '', + 'var2' => 'v2', + ]; + $channelVars = [ + 'local/0@pbx_dial_callroute_to_endpoint-00000008;2' => $varChan, + ]; + $this->assertEquals($channelVars, $event->getAllChannelVariables()); + $this->assertEquals($varChan, $event->getChannelVariables()); + $this->assertEquals( + $varChan, + $event->getChannelVariables( + 'Local/0@pbx_dial_callroute_to_endpoint-00000008;2' + ) + ); + } + + /** + * @group channel_vars + * ChanVariable is sent with a channel name and with a "channel" key. + * https://github.com/marcelog/PAMI/issues/85 + * @throws \PAMI\Client\Exception\ClientException + */ + public function testCanGetChannelVariables(): void + { + [$client, $stream] = $this->makeClientAndStream(); + + $client->registerEventListener(new SomeListenerClass); + + $event = [ + "Event: Dial\r\n", + "Privilege: call,all\r\n", + "SubEvent: Begin\r\n", + "Channel: Local/0@pbx_dial_callroute_to_endpoint-00000008;2\r\n", + "Destination: SIP/jw1034-00000010\r\n", + "CallerIDNum: 1201\r\n", + "CallerIDName: \r\n", + "ConnectedLineNum: strategy-sequential\r\n", + "ConnectedLineName: \r\n", + "UniqueID: pbx-1439974866.33\r\n", + "DestUniqueID: pbx-1439974866.34\r\n", + "Dialstring: jw1034\r\n", + "ChanVariable: var1\r\n", + "ChanVariable: var2=value2\r\n", + "ChanVariable(Local/0@pbx_dial_callroute_to_endpoint-00000008;2): var3=value3\r\n", + "ChanVariable(Local/0@pbx_dial_callroute_to_endpoint-00000008;2): var4=value4\r\n", + "ChanVariable(Local/0@pbx_dial_callroute_to_endpoint-00000008;2): var5=value5\r\n", + "ChanVariable(SIP/jw1034-00000010): var12=value12\r\n", + "ChanVariable(SIP/jw1034-00000010): var22=value22\r\n", + "ChanVariable(SIP/jw1034-00000010): var32=value32\r\n", + "\r\n", + "\r\n\r\n", + ]; + + $stream->shouldReceive('read')->andReturn(...$event); + + for ($i = 0; $i < 21; $i++) { + $client->process(); + } + $event = SomeListenerClass::$event; + $varChan1 = [ + 'var1' => '', + 'var2' => 'value2', + 'var3' => 'value3', + 'var4' => 'value4', + 'var5' => 'value5', + ]; + $varChan2 = [ + 'var12' => 'value12', + 'var22' => 'value22', + 'var32' => 'value32', + ]; + $channelVars = [ + 'local/0@pbx_dial_callroute_to_endpoint-00000008;2' => $varChan1, + 'sip/jw1034-00000010' => $varChan2, + ]; + $this->assertEquals($varChan1, $event->getChannelVariables()); + $this->assertEquals($channelVars, $event->getAllChannelVariables()); + } +} + + diff --git a/tests/EventsTest.php b/tests/EventsTest.php new file mode 100644 index 000000000..fa331fa2c --- /dev/null +++ b/tests/EventsTest.php @@ -0,0 +1,1694 @@ + + * @license http://marcelog.github.com/ Apache License 2.0 + * @version SVN: $Id$ + * @link http://marcelog.github.com/ + * + * Copyright 2011 Marcelo Gornstein + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +namespace Tests; + +use Mockery; +use PAMI\Stream\Stream; +use PAMI\Client\Impl\ClientImpl; +use Tests\Resources\SomeListenerClass; +use Mockery\Adapter\Phpunit\MockeryTestCase; + +/** + * This class will test some events. + * + * PHP Version 5 + * + * @category Pami + * @package Test + * @subpackage Event + * @author Marcelo Gornstein + * @license http://marcelog.github.com/ Apache License 2.0 + * @link http://marcelog.github.com/ + */ +class EventsTest extends MockeryTestCase +{ + protected string $microTime; + + public function setUp(): void + { + parent::setUp(); + + $this->microTime = (string)microtime(true); + setMockedMicroTime($this->microTime); + } + + public function testCanReportEvents(): void + { + $eventNames = [ + 'AsyncAGI', + 'AGIExec', + 'VarSet', + 'Unlink', + 'vgsm_sms_rx', + 'vgsm_net_state', + 'vgsm_me_state', + 'DTMF', + 'Bridge', + 'VoicemailUserEntryComplete', + 'StatusComplete', + 'ParkedCallsComplete', + 'DBGetResponse', + 'VoicemailUserEntry', + 'Transfer', + 'Status', + 'ShowDialPlanComplete', + 'Rename', + 'RegistrationsComplete', + 'RTPSenderStat', + 'RTPReceiverStat', + 'RTCPSent', + 'RTCPReceiverStat', + 'RTCPReceived', + 'QueueSummaryComplete', + 'QueueStatusComplete', + 'DAHDIShowChannelsComplete', + 'QueueSummary', + 'QueueParams', + 'QueueMemberStatus', + 'QueueMemberRemoved', + 'QueueMemberPaused', + 'QueueMember', + 'QueueMemberAdded', + 'PeerlistComplete', + 'PeerStatus', + 'PeerEntry', + 'OriginateResponse', + 'Newstate', + 'Newexten', + 'Newchannel', + 'NewCallerid', + 'NewAccountCode', + 'MusicOnHold', + 'MessageWaiting', + 'Masquerade', + 'ListDialplan', + 'Leave', + 'Join', + 'Hold', + 'Hangup', + 'ExtensionStatus', + 'Dial', + 'DAHDIShowChannels', + 'CoreShowChannelsComplete', + 'CoreShowChannel', + 'ChannelUpdate', + 'Agents', + 'AgentsComplete', + 'Agentlogoff', + 'Agentlogin', + 'AgentConnect', + 'DongleSMSStatus', + 'FullyBooted', + 'DongleShowDevicesComplete', + 'DongleDeviceEntry', + 'DongleNewUSSDBase64', + 'DongleNewUSSD', + 'DongleUSSDStatus', + 'DongleNewCUSD', + 'DongleStatus', + 'CEL', + 'JabberEvent', + 'Registry', + 'UserEvent', + 'ParkedCall', + 'UnParkedCall', + 'Link', + 'AGIExecStart', + 'AGIExecEnd', + 'AsyncAGIStart', + 'AsyncAGIExec', + 'AsyncAGIEnd', + 'QueueCallerJoin', + 'QueueCallerLeave', + 'AttendedTransfer', + 'BlindTransfer', + 'DialBegin', + 'DialEnd', + 'DTMFBegin', + 'DTMFEnd', + 'BridgeCreate', + 'BridgeDestroy', + 'BridgeEnter', + 'BridgeLeave', + 'MusicOnHoldStart', + 'MusicOnHoldStop', + 'ConfbridgeStart', + 'ConfbridgeEnd', + 'ConfbridgeJoin', + 'ConfbridgeLeave', + 'ConfbridgeMute', + 'ConfbridgeUnmute', + 'ConfbridgeTalking', + 'ConfbridgeList', + 'ConfbridgeListComplete', + 'BridgeInfoChannel', + 'BridgeInfoComplete', + ]; + $eventTranslatedValues = [ + 'QueueMemberStatus' => [ + 'Paused' => true, + ], + 'QueueMemberPaused' => [ + 'Paused' => true, + ], + 'QueueMember' => [ + 'Paused' => true, + ], + 'QueueMemberAdded' => [ + 'Paused' => true, + ], + ]; + $eventValues = [ + 'UserEvent' => [ + 'Privilege' => 'Privilege', + 'UniqueID' => 'UniqueID', + 'UserEvent' => 'UserEvent', + ], + 'Registry' => [ + 'Channel' => 'Channel', + 'Domain' => 'Domain', + 'Status' => 'Status', + ], + 'JabberEvent' => [ + 'Privilege' => 'Privilege', + 'Account' => 'Account', + 'Packet' => 'Packet', + ], + 'AsyncAGI' => [ + 'Env' => 'Env', + 'Channel' => 'Channel', + 'CommandId' => 'CommandId', + 'Privilege' => 'Privilege', + 'SubEvent' => 'SubEvent', + 'Result' => 'Result', + ], + 'FullyBooted' => [], + 'DongleUSSDStatus' => [ + 'Privilege' => 'Privilege', + 'Id' => 'Id', + 'Device' => 'Device', + 'Status' => 'Status', + ], + 'DongleNewUSSDBase64' => [ + 'Device' => 'Device', + 'Message' => 'Message', + 'Privilege' => 'Privilege', + ], + 'DongleNewCUSD' => [ + 'Device' => 'Device', + 'Message' => 'Message', + 'Privilege' => 'Privilege', + ], + 'DongleNewUSSD' => [ + 'Device' => 'Device', + 'LineCount' => 'LineCount', + 'Privilege' => 'Privilege', + ], + 'DongleDeviceEntry' => [ + 'Device' => 'Device', + 'AudioSetting' => 'AudioSetting', + 'DataSetting' => 'DataSetting', + 'IMEISetting' => 'IMEISetting', + 'IMSISetting' => 'IMSISetting', + 'ChannelLanguage' => 'ChannelLanguage', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Group' => 'Group', + 'RXGain' => 'RXGain', + 'TXGain' => 'TXGain', + 'U2DIAG' => 'U2DIAG', + 'UseCallingPres' => 'UseCallingPres', + 'DefaultCallingPres' => 'DefaultCallingPres', + 'AutoDeleteSMS' => 'AutoDeleteSMS', + 'DisableSMS' => 'DisableSMS', + 'ResetDongle' => 'ResetDongle', + 'SMSPDU' => 'SMSPDU', + 'CallWaitingSetting' => 'CallWaitingSetting', + 'DTMF' => 'DTMF', + 'MinimalDTMFGap' => 'MinimalDTMFGap', + 'MinimalDTMFDuration' => 'MinimalDTMFDuration', + 'MinimalDTMFInterval' => 'MinimalDTMFInterval', + 'State' => 'State', + 'AudioState' => 'AudioState', + 'DataState' => 'DataState', + 'Voice' => 'Voice', + 'SMS' => 'SMS', + 'Manufacturer' => 'Manufacturer', + 'Model' => 'Model', + 'Firmware' => 'Firmware', + 'IMEIState' => 'IMEIState', + 'IMSIState' => 'IMSIState', + 'GSMRegistrationStatus' => 'GSMRegistrationStatus', + 'RSSI' => 'RSSI', + 'Mode' => 'Mode', + 'Submode' => 'Submode', + 'ProviderName' => 'ProviderName', + 'LocationAreaCode' => 'LocationAreaCode', + 'CellID' => 'CellID', + 'SubscriberNumber' => 'SubscriberNumber', + 'SMSServiceCenter' => 'SMSServiceCenter', + 'UseUCS2Encoding' => 'UseUCS2Encoding', + 'USSDUse7BitEncoding' => 'USSDUse7BitEncoding', + 'USSDUseUCS2Decoding' => 'USSDUseUCS2Decoding', + 'TasksInQueue' => 'TasksInQueue', + 'CommandsInQueue' => 'CommandsInQueue', + 'CallWaitingState' => 'CallWaitingState', + 'CurrentDeviceState' => 'CurrentDeviceState', + 'DesiredDeviceState' => 'DesiredDeviceState', + 'CallsChannels' => 'CallsChannels', + 'Active' => 'Active', + 'Held' => 'Held', + 'Dialing' => 'Dialing', + 'Alerting' => 'Alerting', + 'Incoming' => 'Incoming', + 'Waiting' => 'Waiting', + 'Releasing' => 'Releasing', + 'Initializing' => 'Initializing', + ], + 'DongleShowDevicesComplete' => ['ListItems' => 'items'], + 'DongleSMSStatus' => [ + 'Privilege' => 'Privilege', + 'Id' => 'Id', + 'Device' => 'Device', + 'Status' => 'Status', + ], + 'DongleStatus' => [ + 'Privilege' => 'Privilege', + 'Device' => 'Device', + 'Status' => 'Status', + ], + 'AgentConnect' => [ + 'HoldTime' => 'HoldTime', + 'Privilege' => 'Privilege', + 'BridgedChannel' => 'BridgedChannel', + 'RingTime' => 'RingTime', + 'Member' => 'Member', + 'MemberName' => 'MemberName', + 'UniqueID' => 'UniqueID', + 'Channel' => 'Channel', + 'Queue' => 'Queue', + ], + 'Agentlogoff' => [ + 'Logintime' => 'Logintime', + 'UniqueID' => 'UniqueID', + 'Agent' => 'Agent', + 'Privilege' => 'Privilege', + ], + 'Agentlogin' => [ + 'UniqueID' => 'UniqueID', + 'Agent' => 'Agent', + 'Privilege' => 'Privilege', + 'Channel' => 'Channel', + ], + 'AgentsComplete' => [], + 'Agents' => [ + 'TalkingToChannel' => 'TalkingToChannel', + 'TalkingTo' => 'TalkingTo', + 'LoggedInTime' => 'LoggedInTime', + 'LoggedInChan' => 'LoggedInChan', + 'Name' => 'Name', + 'Status' => 'Status', + 'Agent' => 'Agent', + ], + 'ChannelUpdate' => [ + 'Privilege' => 'Privilege', + 'Channel' => 'Channel', + 'ChannelType' => 'ChannelType', + 'UniqueID' => 'UniqueID', + 'SIPfullcontact' => 'SIPfullcontact', + 'SIPcallid' => 'SIPcallid', + ], + 'CoreShowChannel' => [ + 'UniqueID' => 'UniqueID', + 'Privilege' => 'Privilege', + 'Channel' => 'Channel', + 'AccountCode' => 'AccountCode', + 'Priority' => 'Priority', + 'Extension' => 'Extension', + 'Context' => 'Context', + 'CallerIDNum' => 'CallerIDNum', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'ChannelState' => 'ChannelState', + 'ApplicationData' => 'ApplicationData', + 'Application' => 'Application', + 'BridgedUniqueID' => 'BridgedUniqueID', + 'BridgedChannel' => 'BridgedChannel', + 'Duration' => 'Duration', + ], + 'DAHDIShowChannels' => [ + 'Channel' => 'Channel', + 'Context' => 'Context', + 'Alarm' => 'Alarm', + 'DND' => 'DND', + 'SignallingCode' => 'SignallingCode', + 'Signalling' => 'Signalling', + ], + 'Dial' => [ + 'Privilege' => 'Privilege', + 'Destination' => 'Destination', + 'SubEvent' => 'SubEvent', + 'CallerIdName' => 'CallerIdName', + 'CallerIdNum' => 'CallerIdNum', + 'Channel' => 'Channel', + 'DialStatus' => 'DialStatus', + 'DialString' => 'DialString', + 'UniqueID' => 'UniqueID', + 'DestUniqueID' => 'DestUniqueID', + ], + 'ExtensionStatus' => [ + 'Privilege' => 'Privilege', + 'Status' => 'Status', + 'Exten' => 'Extension', + 'Hint' => 'Hint', + 'Context' => 'Context', + ], + 'Hangup' => [ + 'CallerIdName' => 'CallerIdName', + 'CallerIdNum' => 'CallerIdNum', + 'Channel' => 'Channel', + 'Privilege' => 'Privilege', + 'UniqueID' => 'UniqueID', + 'Cause' => 'Cause', + 'cause-txt' => 'cause-txt', + ], + 'Hold' => [ + 'Privilege' => 'Privilege', + 'UniqueID' => 'UniqueID', + 'Status' => 'Status', + 'Channel' => 'Channel', + ], + 'Join' => [ + 'CallerIdName' => 'CallerIdName', + 'CallerIdNum' => 'CallerIdNum', + 'UniqueID' => 'UniqueID', + 'Position' => 'Position', + 'Queue' => 'Queue', + 'Channel' => 'Channel', + 'Privilege' => 'Privilege', + 'Count' => 'Count', + ], + 'Leave' => [ + 'Channel' => 'Channel', + 'Privilege' => 'Privilege', + 'UniqueID' => 'UniqueID', + 'Count' => 'Count', + 'Queue' => 'Queue', + ], + 'ListDialplan' => [ + 'AppData' => 'AppData', + 'Application' => 'Application', + 'Priority' => 'Priority', + 'Extension' => 'Extension', + 'Context' => 'Context', + 'Registrar' => 'Registrar', + 'IncludeContext' => 'IncludeContext', + ], + 'Masquerade' => [ + 'OriginalState' => 'OriginalState', + 'Original' => 'Original', + 'CloneState' => 'CloneState', + 'Clone' => 'Clone', + 'Privilege' => 'Privilege', + ], + 'MessageWaiting' => [ + 'Privilege' => 'Privilege', + 'Waiting' => 'Waiting', + 'Mailbox' => 'Mailbox', + ], + 'MusicOnHold' => [ + 'Channel' => 'Channel', + 'Privilege' => 'Privilege', + 'UniqueID' => 'UniqueID', + 'State' => 'State', + ], + 'NewAccountCode' => [ + 'Channel' => 'Channel', + 'Privilege' => 'Privilege', + 'UniqueID' => 'UniqueID', + 'AccountCode' => 'AccountCode', + 'OldAccountCode' => 'OldAccountCode', + ], + 'NewCallerid' => [ + 'UniqueID' => 'UniqueID', + 'CallerIdName' => 'CallerIdName', + 'CallerIdNum' => 'CallerIdNum', + 'Channel' => 'Channel', + 'Privilege' => 'Privilege', + 'CID-CallingPres' => 'CID-CallingPres', + ], + 'Newchannel' => [ + 'UniqueID' => 'UniqueID', + 'CallerIdName' => 'CallerIdName', + 'CallerIdNum' => 'CallerIdNum', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'ChannelState' => 'ChannelState', + 'AccountCode' => 'AccountCode', + 'Channel' => 'Channel', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Privilege' => 'Privilege', + ], + 'Newexten' => [ + 'Channel' => 'Channel', + 'Privilege' => 'Privilege', + 'AppData' => 'AppData', + 'Application' => 'Application', + 'Priority' => 'Priority', + 'Extension' => 'Extension', + 'Exten' => 'Exten', + 'Context' => 'Context', + 'UniqueID' => 'UniqueID', + ], + 'Newstate' => [ + 'CallerIdName' => 'CallerIdName', + 'CallerIdNum' => 'CallerIdNum', + 'UniqueID' => 'UniqueID', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'ChannelState' => 'ChannelState', + 'Channel' => 'Channel', + 'Privilege' => 'Privilege', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + ], + 'OriginateResponse' => [ + 'CallerIdName' => 'CallerIdName', + 'CallerIdNum' => 'CallerIdNum', + 'Response' => 'Response', + 'ActionID' => 'ActionID', + 'UniqueID' => 'UniqueID', + 'Reason' => 'Reason', + 'Channel' => 'Channel', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Privilege' => 'Privilege', + ], + 'PeerEntry' => [ + 'RealtimeDevice' => 'RealtimeDevice', + 'Status' => 'Status', + 'ACL' => 'ACL', + 'TextSupport' => 'TextSupport', + 'VideoSupport' => 'VideoSupport', + 'NatSupport' => 'NatSupport', + 'Dynamic' => 'Dynamic', + 'IPPort' => 'IPPort', + 'IPAddress' => 'IPAddress', + 'ChanObjectType' => 'ChanObjectType', + 'ObjectName' => 'ObjectName', + 'ChannelType' => 'ChannelType', + ], + 'PeerStatus' => [ + 'Privilege' => 'Privilege', + 'ChannelType' => 'ChannelType', + 'Peer' => 'Peer', + 'PeerStatus' => 'PeerStatus', + ], + 'QueueMemberRemoved' => [ + 'MemberName' => 'MemberName', + 'Location' => 'Location', + 'Queue' => 'Queue', + 'Privilege' => 'Privilege', + ], + 'QueueMemberPaused' => [ + 'MemberName' => 'MemberName', + 'Location' => 'Location', + 'Queue' => 'Queue', + 'Privilege' => 'Privilege', + 'Paused' => 1, + ], + 'QueueMember' => [ + 'Name' => 'Name', + 'Location' => 'Location', + 'Queue' => 'Queue', + 'Paused' => 1, + 'Status' => 'Status', + 'CallsTaken' => 'CallsTaken', + 'Penalty' => 'Penalty', + 'Membership' => 'Membership', + ], + 'QueueMemberAdded' => [ + 'MemberName' => 'MemberName', + 'LastCall' => 'LastCall', + 'Location' => 'Location', + 'Queue' => 'Queue', + 'Paused' => 1, + 'Status' => 'Status', + 'CallsTaken' => 'CallsTaken', + 'Penalty' => 'Penalty', + 'Membership' => 'Membership', + 'Privilege' => 'Privilege', + ], + 'QueueMemberStatus' => [ + 'Paused' => 1, + 'Status' => 'Status', + 'CallsTaken' => 'CallsTaken', + 'Penalty' => 'Penalty', + 'Membership' => 'Membership', + 'MemberName' => 'MemberName', + 'Location' => 'Location', + 'Queue' => 'Queue', + 'Privilege' => 'Privilege', + ], + 'QueueParams' => [ + 'Completed' => '4', + 'HoldTime' => '5', + 'Calls' => '6', + 'Strategy' => 'Strategy', + 'Max' => '6', + 'Queue' => 'Queue', + 'Weight' => '2', + 'ServiceLevelPerf' => 'ServiceLevelPerf', + 'ServiceLevel' => '1', + 'Abandoned' => '3', + ], + 'QueueSummaryComplete' => [], + 'QueueSummary' => [ + 'LongestHoldTime' => 'LongestHoldTime', + 'HoldTime' => 'HoldTime', + 'Callers' => 'Callers', + 'Available' => 'Available', + 'LoggedIn' => 'LoggedIn', + 'Queue' => 'Queue', + ], + 'QueueStatusComplete' => [], + 'DAHDIShowChannelsComplete' => ['items' => 'ListItems'], + 'PeerlistComplete' => ['ListItems' => 'ListItems'], + 'CoreShowChannelsComplete' => ['ListItems' => 'ListItems'], + 'RTCPReceived' => [ + 'DLSR' => 'DLSR', + 'RTT' => 'RTT', + 'LastSR' => 'LastSR', + 'IAJitter' => 'IAJitter', + 'SequenceNumberCycles' => 'SequenceNumberCycles', + 'HighestSequence' => 'HighestSequence', + 'PacketsLost' => 'PacketsLost', + 'FractionLost' => 'FractionLost', + 'SenderSSRC' => 'SenderSSRC', + 'ReceptionReports' => 'ReceptionReports', + 'PT' => 'PT', + 'Privilege' => 'Privilege', + 'From' => 'From', + ], + 'RTCPReceiverStat' => [ + 'RRCount' => 'RRCount', + 'Jitter' => 'Jitter', + 'LostPackets' => 'LostPackets', + 'ReceivedPackets' => 'ReceivedPackets', + 'SSRC' => 'SSRC', + 'Privilege' => 'Privilege', + 'Transit' => 'Transit', + ], + 'RTCPSent' => [ + 'DLSR' => 'DLSR', + 'TheirLastSR' => 'TheirLastSR', + 'IAJitter' => 'IAJitter', + 'CumulativeLoss' => 'CumulativeLoss', + 'FractionLost' => 'FractionLost', + 'ReportBlock' => 'ReportBlock', + 'SentOctets' => 'SentOctets', + 'SentPackets' => 'SentPackets', + 'SentRTP' => 'SentRTP', + 'SentNTP' => 'SentNTP', + 'OurSSRC' => 'OurSSRC', + 'To' => 'To', + 'Privilege' => 'Privilege', + ], + 'RTPSenderStat' => [ + 'SRCount' => 'SRCount', + 'RTT' => 'RTT', + 'Jitter' => 'Jitter', + 'LostPackets' => 'LostPackets', + 'SentPackets' => 'SentPackets', + 'SSRC' => 'SSRC', + 'Privilege' => 'Privilege', + ], + 'RTPReceiverStat' => [ + 'RRCount' => 'RRCount', + 'Jitter' => 'Jitter', + 'LostPackets' => 'LostPackets', + 'ReceivedPackets' => 'ReceivedPackets', + 'SSRC' => 'SSRC', + 'Privilege' => 'Privilege', + 'Transit' => 'Transit', + ], + 'Rename' => [ + 'UniqueID' => 'UniqueID', + 'Oldname' => 'Oldname', + 'Newname' => 'Newname', + 'Channel' => 'Channel', + 'Privilege' => 'Privilege', + ], + 'ShowDialPlanComplete' => [ + 'listcontexts' => 'listcontexts', + 'listpriorities' => 'listpriorities', + 'listextensions' => 'listextensions', + 'listitems' => 'listitems', + 'privilege' => 'privilege', + ], + 'Status' => [ + 'BridgedUniqueID' => 'BridgedUniqueID', + 'BridgedChannel' => 'BridgedChannel', + 'Seconds' => 'Seconds', + 'AccountCode' => 'AccountCode', + 'Duration' => 'Duration', + 'CallerIDNum' => 'CallerIDNum', + 'ApplicationData' => 'ApplicationData', + 'Application' => 'Application', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'ChannelState' => 'ChannelState', + 'Priority' => 'Priority', + 'Extension' => 'Extension', + 'Context' => 'Context', + 'UniqueID' => 'UniqueID', + 'Privilege' => 'Privilege', + 'Channel' => 'Channel', + ], + 'Transfer' => [ + 'TransferContext' => 'TransferContext', + 'TransferExten' => 'TransferExten', + 'TargetUniqueid' => 'TargetUniqueid', + 'UniqueID' => 'UniqueID', + 'SIP-Callid' => 'SIP-Callid', + 'TargetChannel' => 'TargetChannel', + 'Channel' => 'Channel', + 'TransferType' => 'TransferType', + 'TransferMethod' => 'TransferMethod', + 'Privilege' => 'Privilege', + ], + 'VoicemailUserEntryComplete' => [], + 'VoicemailUserEntry' => [ + 'VmContext' => 'VmContext', + 'VoicemailBox' => 'VoicemailBox', + 'Fullname' => 'Fullname', + 'Email' => 'Email', + 'Pager' => 'Pager', + 'ServerEmail' => 'ServerEmail', + 'MailCommand' => 'MailCommand', + 'Language' => 'Language', + 'Timezone' => 'Timezone', + 'Callback' => 'Callback', + 'DialOut' => 'DialOut', + 'UniqueID' => 'UniqueID', + 'ExitContext' => 'ExitContext', + 'SayDurationMin' => 'SayDurationMin', + 'SayEnvelope' => 'SayEnvelope', + 'SayCID' => 'SayCID', + 'AttachMessage' => 'AttachMessage', + 'AttachmentFormat' => 'AttachmentFormat', + 'DeleteMessage' => 'DeleteMessage', + 'VolumeGain' => 'VolumeGain', + 'CanReview' => 'CanReview', + 'CallOperator' => 'CallOperator', + 'MaxMessageCount' => 'MaxMessageCount', + 'MaxMessageLength' => 'MaxMessageLength', + 'NewMessageCount' => 'NewMessageCount', + ], + 'DBGetResponse' => [ + 'Family' => 'Family', + 'Key' => 'Key', + 'Val' => 'Val', + ], + 'ParkedCallsComplete' => [], + 'StatusComplete' => ['Items' => 'Items'], + 'RegistrationsComplete' => ['ListItems' => 'ListItems'], + 'DTMF' => [ + 'Privilege' => 'Privilege', + 'UniqueID' => 'UniqueID', + 'Channel' => 'Channel', + 'Direction' => 'Direction', + 'End' => 'End', + 'Begin' => 'Begin', + 'Digit' => 'Digit', + ], + 'AGIExec' => [ + 'Privilege' => 'Privilege', + 'CommandId' => 'CommandId', + 'SubEvent' => 'SubEvent', + 'Channel' => 'Channel', + 'Command' => 'Command', + 'Result' => 'Result', + 'ResultCode' => 'ResultCode', + ], + 'VarSet' => [ + 'Privilege' => 'Privilege', + 'Channel' => 'Channel', + 'Variable' => 'Variable', + 'Value' => 'Value', + 'UniqueID' => 'UniqueID', + ], + 'Unlink' => [ + 'Privilege' => 'Privilege', + 'CallerID1' => 'CallerID1', + 'CallerID2' => 'CallerID2', + 'UniqueID1' => 'UniqueID1', + 'UniqueID2' => 'UniqueID2', + 'Channel1' => 'Channel1', + 'Channel2' => 'Channel2', + ], + 'Bridge' => [ + 'Privilege' => 'Privilege', + 'CallerID1' => 'CallerID1', + 'CallerID2' => 'CallerID2', + 'UniqueID1' => 'UniqueID1', + 'UniqueID2' => 'UniqueID2', + 'Channel1' => 'Channel1', + 'Channel2' => 'Channel2', + 'BridgeState' => 'BridgeStart', + 'BridgeType' => 'BridgeType', + ], + 'vgsm_sms_rx' => [ + 'Privilege' => 'Privilege', + 'X-SMS-Status-Report-Indication' => 'X-SMS-Status-Report-Indication', + 'X-SMS-User-Data-Header-Indicator' => 'X-SMS-User-Data-Header-Indicator', + 'X-SMS-Reply-Path' => 'X-SMS-Reply-Path', + 'X-SMS-More-Messages-To-Send' => 'X-SMS-More-Messages-To-Send', + 'X-SMS-SMCC-Number' => 'X-SMS-SMCC-Number', + 'X-SMS-SMCC-TON' => 'X-SMS-SMCC-TON', + 'X-SMS-SMCC-NP' => 'X-SMS-SMCC-NP', + 'X-SMS-Sender-Number' => 'X-SMS-Sender-Number', + 'X-SMS-Sender-TON' => 'X-SMS-Sender-TON', + 'X-SMS-Sender-NP' => 'X-SMS-Sender-NP', + 'X-SMS-Message-Type' => 'X-SMS-Message-Type', + 'Content' => 'Content', + 'Date' => 'Date', + 'Content-Transfer-Encoding' => 'ContentEncoding', + 'Content-Type' => 'ContentType', + 'MIME-Version' => 'MIME-Version', + 'Subject' => 'Subject', + 'From' => 'From', + 'Received' => 'Received', + ], + 'vgsm_net_state' => [ + 'Privilege' => 'Privilege', + 'X-vGSM-GSM-Registration' => 'X-vGSM-GSM-Registration', + ], + 'vgsm_me_state' => [ + 'Privilege' => 'Privilege', + 'X-vGSM-ME-State-Change-Reason' => 'X-vGSM-ME-State-Change-Reason', + 'X-vGSM-ME-Old-State' => 'X-vGSM-ME-Old-State', + 'X-vGSM-ME-State' => 'X-vGSM-ME-State', + ], + 'CEL' => [ + 'AMAFlags' => 'AMAFlags', + 'AccountCode' => 'AccountCode', + 'AppData' => 'AppData', + 'Application' => 'Application', + 'CallerIDani' => 'CallerIDani', + 'CallerIDdnid' => 'CallerIDdnid', + 'CallerIDname' => 'CallerIDname', + 'CallerIDnum' => 'CallerIDnum', + 'CallerIDrdnis' => 'CallerIDrdnis', + 'Channel' => 'Channel', + 'Context' => 'Context', + 'Event' => 'Event', + 'EventName' => 'EventName', + 'EventTime' => 'EventTime', + 'Exten' => 'Exten', + 'Extra' => 'Extra', + 'LinkedID' => 'LinkedID', + 'Peer' => 'Peer', + 'PeerAccount' => 'PeerAccount', + 'Privilege' => 'Privilege', + 'Timestamp' => 'Timestamp', + 'UniqueID' => 'UniqueID', + 'Userfield' => 'Userfield', + ], + 'ParkedCall' => [ + 'Privilege' => 'Privilege', + 'Parkinglot' => 'Parkinglot', + 'From' => 'From', + 'Timeout' => 'ParkingTimeout', + 'ConnectedLineNum' => 'ParkeeConnectedLineNum', + 'ConnectedLineName' => 'ParkeeConnectedLineName', + 'Channel' => 'ParkeeChannel', + 'CallerIDNum' => 'ParkeeCallerIDNum', + 'CallerIDName' => 'ParkeeCallerIDName', + 'UniqueID' => 'ParkeeUniqueid', + 'Exten' => 'ParkingSpace', + 'ParkeeChannel' => 'ParkeeChannel', + 'ParkeeChannelState' => 'ParkeeChannelState', + 'ParkeeChannelStateDesc' => 'ParkeeChannelStateDesc', + 'ParkeeCallerIDNum' => 'ParkeeCallerIDNum', + 'ParkeeCallerIDName' => 'ParkeeCallerIDName', + 'ParkeeConnectedLineNum' => 'ParkeeConnectedLineNum', + 'ParkeeConnectedLineName' => 'ParkeeConnectedLineName', + 'ParkeeAccountCode' => 'ParkeeAccountCode', + 'ParkeeContext' => 'ParkeeContext', + 'ParkeeExten' => 'ParkeeExten', + 'ParkeePriority' => 'ParkeePriority', + 'ParkeeUniqueid' => 'ParkeeUniqueid', + 'ParkerDialString' => 'ParkerDialString', + 'ParkingSpace' => 'ParkingSpace', + 'ParkingTimeout' => 'ParkingTimeout', + 'ParkingDuration' => 'ParkingDuration', + ], + 'UnParkedCall' => [ + 'Privilege' => 'Privilege', + 'Parkinglot' => 'Parkinglot', + 'From' => 'RetrieverChannel', + 'ConnectedLineNum' => 'ParkeeConnectedLineNum', + 'ConnectedLineName' => 'ParkeeConnectedLineName', + 'Channel' => 'ParkeeChannel', + 'CallerIDNum' => 'ParkeeCallerIDNum', + 'CallerIDName' => 'ParkeeCallerIDName', + 'UniqueID' => 'ParkeeUniqueid', + 'Exten' => 'ParkingSpace', + 'ParkeeChannel' => 'ParkeeChannel', + 'ParkeeChannelState' => 'ParkeeChannelState', + 'ParkeeChannelStateDesc' => 'ParkeeChannelStateDesc', + 'ParkeeCallerIDNum' => 'ParkeeCallerIDNum', + 'ParkeeCallerIDName' => 'ParkeeCallerIDName', + 'ParkeeConnectedLineNum' => 'ParkeeConnectedLineNum', + 'ParkeeConnectedLineName' => 'ParkeeConnectedLineName', + 'ParkeeAccountCode' => 'ParkeeAccountCode', + 'ParkeeContext' => 'ParkeeContext', + 'ParkeeExten' => 'ParkeeExten', + 'ParkeePriority' => 'ParkeePriority', + 'ParkeeUniqueid' => 'ParkeeUniqueid', + 'ParkerDialString' => 'ParkerDialString', + 'ParkingSpace' => 'ParkingSpace', + 'ParkingTimeout' => 'ParkingTimeout', + 'ParkingDuration' => 'ParkingDuration', + 'ParkerChannel' => 'ParkerChannel', + 'ParkerChannelState' => 'ParkerChannelState', + 'ParkerChannelStateDesc' => 'ParkerChannelStateDesc', + 'ParkerCallerIDNum' => 'ParkerCallerIDNum', + 'ParkerCallerIDName' => 'ParkerCallerIDName', + 'ParkerConnectedLineNum' => 'ParkerConnectedLineNum', + 'ParkerConnectedLineName' => 'ParkerConnectedLineName', + 'ParkerAccountCode' => 'ParkerAccountCode', + 'ParkerContext' => 'ParkerContext', + 'ParkerExten' => 'ParkerExten', + 'ParkerPriority' => 'ParkerPriority', + 'ParkerUniqueid' => 'ParkerUniqueid', + 'RetrieverChannel' => 'RetrieverChannel', + 'RetrieverChannelState' => 'RetrieverChannelState', + 'RetrieverChannelStateDesc' => 'RetrieverChannelStateDesc', + 'RetrieverCallerIDNum' => 'RetrieverCallerIDNum', + 'RetrieverCallerIDName' => 'RetrieverCallerIDName', + 'RetrieverConnectedLineNum' => 'RetrieverConnectedLineNum', + 'RetrieverConnectedLineName' => 'RetrieverConnectedLineName', + 'RetrieverAccountCode' => 'RetrieverAccountCode', + 'RetrieverContext' => 'RetrieverContext', + 'RetrieverExten' => 'RetrieverExten', + 'RetrieverPriority' => 'RetrieverPriority', + 'RetrieverUniqueid' => 'RetrieverUniqueid', + ], + 'Link' => [ + 'Privilege' => 'Privilege', + 'CallerID1' => 'CallerID1', + 'CallerID2' => 'CallerID2', + 'UniqueID1' => 'UniqueID1', + 'UniqueID2' => 'UniqueID2', + 'Channel1' => 'Channel1', + 'Channel2' => 'Channel2', + ], + 'AGIExecStart' => [ + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'Command' => 'Command', + 'CommandId' => 'CommandId', + ], + 'AGIExecEnd' => [ + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'Command' => 'Command', + 'CommandId' => 'CommandId', + 'ResultCode' => 'ResultCode', + 'Result' => 'Result', + ], + 'AsyncAGIStart' => [ + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'Env' => 'Env', + ], + 'AsyncAGIExec' => [ + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'CommandID' => 'CommandID', + 'Result' => 'Result', + ], + 'AsyncAGIEnd' => [ + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + ], + 'QueueCallerJoin' => [ + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'Queue' => 'Queue', + 'Position' => 'Position', + 'Count' => 'Count', + ], + 'QueueCallerLeave' => [ + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'Queue' => 'Queue', + 'Count' => 'Count', + 'Position' => 'Position', + ], + 'AttendedTransfer' => [ + 'Result' => 'Result', + 'OrigTransfererChannel' => 'OrigTransfererChannel', + 'OrigTransfererChannelState' => 'OrigTransfererChannelState', + 'OrigTransfererChannelStateDesc' => 'OrigTransfererChannelStateDesc', + 'OrigTransfererCallerIDNum' => 'OrigTransfererCallerIDNum', + 'OrigTransfererCallerIDName' => 'OrigTransfererCallerIDName', + 'OrigTransfererConnectedLineNum' => 'OrigTransfererConnectedLineNum', + 'OrigTransfererConnectedLineName' => 'OrigTransfererConnectedLineName', + 'OrigTransfererAccountCode' => 'OrigTransfererAccountCode', + 'OrigTransfererContext' => 'OrigTransfererContext', + 'OrigTransfererExten' => 'OrigTransfererExten', + 'OrigTransfererPriority' => 'OrigTransfererPriority', + 'OrigTransfererUniqueid' => 'OrigTransfererUniqueid', + 'OrigBridgeUniqueid' => 'OrigBridgeUniqueid', + 'OrigBridgeType' => 'OrigBridgeType', + 'OrigBridgeTechnology' => 'OrigBridgeTechnology', + 'OrigBridgeCreator' => 'OrigBridgeCreator', + 'OrigBridgeName' => 'OrigBridgeName', + 'OrigBridgeNumChannels' => 'OrigBridgeNumChannels', + 'SecondTransfererChannel' => 'SecondTransfererChannel', + 'SecondTransfererChannelState' => 'SecondTransfererChannelState', + 'SecondTransfererChannelStateDesc' => 'SecondTransfererChannelStateDesc', + 'SecondTransfererCallerIDNum' => 'SecondTransfererCallerIDNum', + 'SecondTransfererCallerIDName' => 'SecondTransfererCallerIDName', + 'SecondTransfererConnectedLineNum' => 'SecondTransfererConnectedLineNum', + 'SecondTransfererConnectedLineName' => 'SecondTransfererConnectedLineName', + 'SecondTransfererAccountCode' => 'SecondTransfererAccountCode', + 'SecondTransfererContext' => 'SecondTransfererContext', + 'SecondTransfererExten' => 'SecondTransfererExten', + 'SecondTransfererPriority' => 'SecondTransfererPriority', + 'SecondTransfererUniqueid' => 'SecondTransfererUniqueid', + 'SecondBridgeUniqueid' => 'SecondBridgeUniqueid', + 'SecondBridgeType' => 'SecondBridgeType', + 'SecondBridgeTechnology' => 'SecondBridgeTechnology', + 'SecondBridgeCreator' => 'SecondBridgeCreator', + 'SecondBridgeName' => 'SecondBridgeName', + 'SecondBridgeNumChannels' => 'SecondBridgeNumChannels', + 'DestType' => 'DestType', + 'DestBridgeUniqueid' => 'DestBridgeUniqueid', + 'DestApp' => 'DestApp', + 'LocalOneChannel' => 'LocalOneChannel', + 'LocalOneChannelState' => 'LocalOneChannelState', + 'LocalOneChannelStateDesc' => 'LocalOneChannelStateDesc', + 'LocalOneCallerIDNum' => 'LocalOneCallerIDNum', + 'LocalOneCallerIDName' => 'LocalOneCallerIDName', + 'LocalOneConnectedLineNum' => 'LocalOneConnectedLineNum', + 'LocalOneConnectedLineName' => 'LocalOneConnectedLineName', + 'LocalOneAccountCode' => 'LocalOneAccountCode', + 'LocalOneContext' => 'LocalOneContext', + 'LocalOneExten' => 'LocalOneExten', + 'LocalOnePriority' => 'LocalOnePriority', + 'LocalOneUniqueid' => 'LocalOneUniqueid', + 'LocalTwoChannel' => 'LocalTwoChannel', + 'LocalTwoChannelState' => 'LocalTwoChannelState', + 'LocalTwoChannelStateDesc' => 'LocalTwoChannelStateDesc', + 'LocalTwoCallerIDNum' => 'LocalTwoCallerIDNum', + 'LocalTwoCallerIDName' => 'LocalTwoCallerIDName', + 'LocalTwoConnectedLineNum' => 'LocalTwoConnectedLineNum', + 'LocalTwoConnectedLineName' => 'LocalTwoConnectedLineName', + 'LocalTwoAccountCode' => 'LocalTwoAccountCode', + 'LocalTwoContext' => 'LocalTwoContext', + 'LocalTwoExten' => 'LocalTwoExten', + 'LocalTwoPriority' => 'LocalTwoPriority', + 'LocalTwoUniqueid' => 'LocalTwoUniqueid', + 'DestTransfererChannel' => 'DestTransfererChannel', + 'TransfereeChannel' => 'TransfereeChannel', + 'TransfereeChannelState' => 'TransfereeChannelState', + 'TransfereeChannelStateDesc' => 'TransfereeChannelStateDesc', + 'TransfereeCallerIDNum' => 'TransfereeCallerIDNum', + 'TransfereeCallerIDName' => 'TransfereeCallerIDName', + 'TransfereeConnectedLineNum' => 'TransfereeConnectedLineNum', + 'TransfereeConnectedLineName' => 'TransfereeConnectedLineName', + 'TransfereeAccountCode' => 'TransfereeAccountCode', + 'TransfereeContext' => 'TransfereeContext', + 'TransfereeExten' => 'TransfereeExten', + 'TransfereePriority' => 'TransfereePriority', + 'TransfereeUniqueid' => 'TransfereeUniqueid', + ], + 'BlindTransfer' => [ + 'Result' => 'Result', + 'TransfererChannel' => 'TransfererChannel', + 'TransfererChannelState' => 'TransfererChannelState', + 'TransfererChannelStateDesc' => 'TransfererChannelStateDesc', + 'TransfererCallerIDNum' => 'TransfererCallerIDNum', + 'TransfererCallerIDName' => 'TransfererCallerIDName', + 'TransfererConnectedLineNum' => 'TransfererConnectedLineNum', + 'TransfererConnectedLineName' => 'TransfererConnectedLineName', + 'TransfererAccountCode' => 'TransfererAccountCode', + 'TransfererContext' => 'TransfererContext', + 'TransfererExten' => 'TransfererExten', + 'TransfererPriority' => 'TransfererPriority', + 'TransfererUniqueid' => 'TransfererUniqueid', + 'TransfereeChannel' => 'TransfereeChannel', + 'TransfereeChannelState' => 'TransfereeChannelState', + 'TransfereeChannelStateDesc' => 'TransfereeChannelStateDesc', + 'TransfereeCallerIDNum' => 'TransfereeCallerIDNum', + 'TransfereeCallerIDName' => 'TransfereeCallerIDName', + 'TransfereeConnectedLineNum' => 'TransfereeConnectedLineNum', + 'TransfereeConnectedLineName' => 'TransfereeConnectedLineName', + 'TransfereeAccountCode' => 'TransfereeAccountCode', + 'TransfereeContext' => 'TransfereeContext', + 'TransfereeExten' => 'TransfereeExten', + 'TransfereePriority' => 'TransfereePriority', + 'TransfereeUniqueid' => 'TransfereeUniqueid', + 'BridgeUniqueid' => 'BridgeUniqueid', + 'BridgeType' => 'BridgeType', + 'BridgeTechnology' => 'BridgeTechnology', + 'BridgeCreator' => 'BridgeCreator', + 'BridgeName' => 'BridgeName', + 'BridgeNumChannels' => 'BridgeNumChannels', + 'IsExternal' => 'IsExternal', + 'Context' => 'Context', + 'Extension' => 'Extension', + ], + 'DialBegin' => [ + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'DestChannel' => 'DestChannel', + 'DestChannelState' => 'DestChannelState', + 'DestChannelStateDesc' => 'DestChannelStateDesc', + 'DestCallerIDNum' => 'DestCallerIDNum', + 'DestCallerIDName' => 'DestCallerIDName', + 'DestConnectedLineNum' => 'DestConnectedLineNum', + 'DestConnectedLineName' => 'DestConnectedLineName', + 'DestAccountCode' => 'DestAccountCode', + 'DestContext' => 'DestContext', + 'DestExten' => 'DestExten', + 'DestPriority' => 'DestPriority', + 'DestUniqueid' => 'DestUniqueid', + 'DialString' => 'DialString', + ], + 'DialEnd' => [ + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'DestChannel' => 'DestChannel', + 'DestChannelState' => 'DestChannelState', + 'DestChannelStateDesc' => 'DestChannelStateDesc', + 'DestCallerIDNum' => 'DestCallerIDNum', + 'DestCallerIDName' => 'DestCallerIDName', + 'DestConnectedLineNum' => 'DestConnectedLineNum', + 'DestConnectedLineName' => 'DestConnectedLineName', + 'DestAccountCode' => 'DestAccountCode', + 'DestContext' => 'DestContext', + 'DestExten' => 'DestExten', + 'DestPriority' => 'DestPriority', + 'DestUniqueid' => 'DestUniqueid', + 'DialStatus' => 'DialStatus', + ], + 'DTMFBegin' => [ + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'Digit' => 'Digit', + 'Direction' => 'Direction', + ], + 'DTMFEnd' => [ + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'Digit' => 'Digit', + 'DurationMs' => 'DurationMs', + 'Direction' => 'Direction', + ], + 'BridgeCreate' => [ + 'BridgeUniqueid' => 'BridgeUniqueid', + 'BridgeType' => 'BridgeType', + 'BridgeTechnology' => 'BridgeTechnology', + 'BridgeCreator' => 'BridgeCreator', + 'BridgeName' => 'BridgeName', + 'BridgeNumChannels' => 'BridgeNumChannels', + ], + 'BridgeDestroy' => [ + 'BridgeUniqueid' => 'BridgeUniqueid', + 'BridgeType' => 'BridgeType', + 'BridgeTechnology' => 'BridgeTechnology', + 'BridgeCreator' => 'BridgeCreator', + 'BridgeName' => 'BridgeName', + 'BridgeNumChannels' => 'BridgeNumChannels', + ], + 'BridgeEnter' => [ + 'BridgeUniqueid' => 'BridgeUniqueid', + 'BridgeType' => 'BridgeType', + 'BridgeTechnology' => 'BridgeTechnology', + 'BridgeCreator' => 'BridgeCreator', + 'BridgeName' => 'BridgeName', + 'BridgeNumChannels' => 'BridgeNumChannels', + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'SwapUniqueid' => 'SwapUniqueid', + ], + 'BridgeLeave' => [ + 'BridgeUniqueid' => 'BridgeUniqueid', + 'BridgeType' => 'BridgeType', + 'BridgeTechnology' => 'BridgeTechnology', + 'BridgeCreator' => 'BridgeCreator', + 'BridgeName' => 'BridgeName', + 'BridgeNumChannels' => 'BridgeNumChannels', + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + ], + 'MusicOnHoldStart' => [ + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'Class' => 'Class', + ], + 'MusicOnHoldStop' => [ + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + ], + 'ConfbridgeStart' => [ + 'Conference' => 'Conference', + 'BridgeUniqueid' => 'BridgeUniqueid', + 'BridgeType' => 'BridgeType', + 'BridgeTechnology' => 'BridgeTechnology', + 'BridgeCreator' => 'BridgeCreator', + 'BridgeName' => 'BridgeName', + 'BridgeNumChannels' => 'BridgeNumChannels', + ], + 'ConfbridgeEnd' => [ + 'Conference' => 'Conference', + 'BridgeUniqueid' => 'BridgeUniqueid', + 'BridgeType' => 'BridgeType', + 'BridgeTechnology' => 'BridgeTechnology', + 'BridgeCreator' => 'BridgeCreator', + 'BridgeName' => 'BridgeName', + 'BridgeNumChannels' => 'BridgeNumChannels', + ], + 'ConfbridgeJoin' => [ + 'Conference' => 'Conference', + 'BridgeUniqueid' => 'BridgeUniqueid', + 'BridgeType' => 'BridgeType', + 'BridgeTechnology' => 'BridgeTechnology', + 'BridgeCreator' => 'BridgeCreator', + 'BridgeName' => 'BridgeName', + 'BridgeNumChannels' => 'BridgeNumChannels', + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'Linkedid' => 'Linkedid', + 'Admin' => 'Admin', + ], + 'ConfbridgeLeave' => [ + 'Conference' => 'Conference', + 'BridgeUniqueid' => 'BridgeUniqueid', + 'BridgeType' => 'BridgeType', + 'BridgeTechnology' => 'BridgeTechnology', + 'BridgeCreator' => 'BridgeCreator', + 'BridgeName' => 'BridgeName', + 'BridgeNumChannels' => 'BridgeNumChannels', + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'Linkedid' => 'Linkedid', + 'Admin' => 'Admin', + ], + 'ConfbridgeMute' => [ + 'Conference' => 'Conference', + 'BridgeUniqueid' => 'BridgeUniqueid', + 'BridgeType' => 'BridgeType', + 'BridgeTechnology' => 'BridgeTechnology', + 'BridgeCreator' => 'BridgeCreator', + 'BridgeName' => 'BridgeName', + 'BridgeNumChannels' => 'BridgeNumChannels', + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'Linkedid' => 'Linkedid', + 'Admin' => 'Admin', + ], + 'ConfbridgeUnmute' => [ + 'Conference' => 'Conference', + 'BridgeUniqueid' => 'BridgeUniqueid', + 'BridgeType' => 'BridgeType', + 'BridgeTechnology' => 'BridgeTechnology', + 'BridgeCreator' => 'BridgeCreator', + 'BridgeName' => 'BridgeName', + 'BridgeNumChannels' => 'BridgeNumChannels', + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'Linkedid' => 'Linkedid', + 'Admin' => 'Admin', + ], + 'ConfbridgeTalking' => [ + 'Conference' => 'Conference', + 'BridgeUniqueid' => 'BridgeUniqueid', + 'BridgeType' => 'BridgeType', + 'BridgeTechnology' => 'BridgeTechnology', + 'BridgeCreator' => 'BridgeCreator', + 'BridgeName' => 'BridgeName', + 'BridgeNumChannels' => 'BridgeNumChannels', + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'Linkedid' => 'Linkedid', + 'TalkingStatus' => 'TalkingStatus', + 'Admin' => 'Admin', + ], + 'ConfbridgeList' => [ + 'Conference' => 'Conference', + 'Channel' => 'Channel', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'MarkedUser' => 'MarkedUser', + 'WaitMarked' => 'WaitMarked', + 'EndMarked' => 'EndMarked', + 'Waiting' => 'Waiting', + 'Muted' => 'Muted', + 'AnsweredTime' => 'AnsweredTime', + 'Admin' => 'Admin', + ], + 'ConfbridgeListComplete' => ['ListItems' => 'ListItems'], + 'BridgeInfoChannel' => [ + 'Channel' => 'Channel', + 'ChannelState' => 'ChannelState', + 'ChannelStateDesc' => 'ChannelStateDesc', + 'CallerIDNum' => 'CallerIDNum', + 'CallerIDName' => 'CallerIDName', + 'ConnectedLineNum' => 'ConnectedLineNum', + 'ConnectedLineName' => 'ConnectedLineName', + 'AccountCode' => 'AccountCode', + 'Context' => 'Context', + 'Exten' => 'Exten', + 'Priority' => 'Priority', + 'Uniqueid' => 'Uniqueid', + 'Linkedid' => 'Linkedid', + ], + 'BridgeInfoComplete' => [ + 'BridgeUniqueid' => 'BridgeUniqueid', + 'BridgeType' => 'BridgeType', + 'BridgeTechnology' => 'BridgeTechnology', + 'BridgeCreator' => 'BridgeCreator', + 'BridgeName' => 'BridgeName', + 'BridgeNumChannels' => 'BridgeNumChannels', + 'BridgeVideoSourceMode' => 'BridgeVideoSourceMode', + 'BridgeVideoSource' => 'BridgeVideoSource', + ], + ]; + $eventGetters = [ + 'UserEvent' => [ + 'UserEvent' => 'UserEventName', + ], + 'AsyncAGI' => [ + 'Env' => 'Environment', + ], + 'Agents' => [ + 'LoggedInChan' => 'Channel', + ], + 'ExtensionStatus' => [ + 'Exten' => 'Extension', + ], + 'Hangup' => [ + 'cause-txt' => 'CauseText', + ], + 'ListDialplan' => [ + 'AppData' => 'ApplicationData', + ], + 'NewCallerid' => [ + 'CID-CallingPres' => 'CallerIdPres', + ], + 'Newchannel' => ['Exten' => 'Extension'], + 'Newexten' => [ + 'AppData' => 'ApplicationData', + ], + 'QueueMemberStatus' => [ + 'Paused' => 'Pause', + ], + 'QueueMember' => [ + 'Name' => 'MemberName', + ], + 'AGIExec' => [], + 'Transfer' => [ + 'SIP-Callid' => 'SipCallID', + ], + 'VoicemailUserEntry' => [ + 'VmContext' => 'VoicemailContext', + ], + 'PeerEntry' => ['ChanObjectType' => 'ChannelObjectType'], + 'VarSet' => ['Variable' => 'VariableName'], + 'StatusComplete' => ['Items' => 'ListItems'], + 'DBGetResponse' => ['Key' => 'KeyName', 'Val' => 'Value'], + 'vgsm_sms_rx' => [ + 'X-SMS-Status-Report-Indication' => 'StatusReportIndication', + 'X-SMS-User-Data-Header-Indicator' => 'DataHeaderIndicator', + 'X-SMS-Reply-Path' => 'ReplyPath', + 'X-SMS-More-Messages-To-Send' => 'MoreMessagesToSend', + 'X-SMS-SMCC-Number' => 'SMCCNumber', + 'X-SMS-SMCC-TON' => 'SMCCTON', + 'X-SMS-SMCC-NP' => 'SMCCNP', + 'X-SMS-Sender-Number' => 'SenderNumber', + 'X-SMS-Sender-TON' => 'SenderTON', + 'X-SMS-Sender-NP' => 'SenderNP', + 'X-SMS-Message-Type' => 'MessageType', + 'Content-Transfer-Encoding' => 'ContentEncoding', + 'Content-Type' => 'ContentType', + 'MIME-Version' => 'MIMEVersion', + ], + 'DAHDIShowChannelsComplete' => ['items' => 'ListItems'], + 'vgsm_net_state' => ['X-vGSM-GSM-Registration' => 'State'], + 'vgsm_me_state' => [ + 'X-vGSM-ME-State-Change-Reason' => 'Reason', + 'X-vGSM-ME-Old-State' => 'OldState', + 'X-vGSM-ME-State' => 'State', + ], + 'ParkedCall' => ['Exten' => 'Extension'], + 'UnParkedCall' => ['Exten' => 'Extension'], + 'AGIExecStart' => [ + + ], + ]; + foreach ($eventNames as $eventName) { + $this->testEvent($eventName, $eventGetters, $eventValues[$eventName], $eventTranslatedValues); + } + } + + /** + * @param string $eventName + * @param array> $getters + * @param array $values + * @param array> $translatedValues + * + * @throws \PAMI\Client\Exception\ClientException + */ + private function testEvent(string $eventName, array $getters, array $values, array $translatedValues): void + { + $eventClass = "PAMI\\Message\\Event\\" . str_replace(' ', '', + ucwords(str_replace('_', ' ', $eventName))) . 'Event'; + + $options = [ + 'host' => '2.3.4.5', + 'scheme' => 'tcp://', + 'port' => 9999, + 'username' => 'asd', + 'secret' => 'asd', + 'connect_timeout' => 10, + 'read_timeout' => 20, + ]; + $write = + "action: Login\r\n" . + "actionid: " . $this->microTime . "\r\n" . + "username: asd\r\n" . + "secret: asd\r\n\r\n"; + + $stream = Mockery::mock(Stream::class); + + $client = Mockery::mock(ClientImpl::class, [$options]); + $client->makePartial(); + $client->shouldAllowMockingProtectedMethods(); + + $client->shouldReceive('makeStream')->andReturn($stream); + + $stream->shouldReceive('getLine') + ->once() + ->andReturn('Asterisk 1234'); + + $stream->shouldReceive('write') + ->once() + ->with($write) + ->andReturn(strlen($write)); + + $stream->shouldReceive('read') + ->times(5) + ->andReturn( + "Asterisk Call Manager/1.1\r\n", + "Response: Success\r\n", + "ActionID: " . $this->microTime . "\r\n", + "Message: Authentication accepted\r\n", + "\r\n\r\n" + ); + + $stream->shouldReceive('endOfFile') + ->andReturnFalse(); + + $stream->shouldReceive('setBlocking') + ->once() + ->with(false); + + $stream->shouldReceive('isConnected') + ->andReturnTrue(); + + $client->open(); + + $client->registerEventListener(new SomeListenerClass); + + $message = []; + $message[] = 'Event: ' . $eventName . "\r\n"; + foreach ($values as $key => $value) { + $message[] = $key . ': ' . $value . "\r\n"; + } + $message[] = "\r\n"; + + $stream->shouldReceive('read')->andReturn(...$message); + + for ($i = 0; $i < count($message); $i++) { + $client->process(); + } + + $event = SomeListenerClass::$event; + foreach ($values as $key => $value) { + if (isset($getters[$eventName][$key])) { + $methodName = 'get' . $getters[$eventName][$key]; + } else { + $methodName = 'get' . $key; + } + if (isset($translatedValues[$eventName][$key])) { + $value = $translatedValues[$eventName][$key]; + } + + $this->assertTrue( + method_exists($event, $methodName), + sprintf( + "Method %s doesn't exist in event %s. Data: %s. Messages:\r\n%s", + $methodName, + get_class($event), + var_export(func_get_args(), true), + implode("", $message) + ) + ); + + $this->assertEquals($event->$methodName(), $value, $eventName); + } + + $this->assertEquals($eventClass, get_class($event)); + } +} diff --git a/tests/Resources/SomeListenerClass.php b/tests/Resources/SomeListenerClass.php new file mode 100644 index 000000000..aed89cb37 --- /dev/null +++ b/tests/Resources/SomeListenerClass.php @@ -0,0 +1,16 @@ +