diff --git a/.gitignore b/.gitignore index f1d40ef..c0684bc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.idea /vendor /composer.lock tests/*/output \ No newline at end of file diff --git a/.scrutinizer.yml b/.scrutinizer.yml index d712254..e5389ea 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -4,9 +4,7 @@ checks: build: environment: php: - version: 7.2 - variables: - NETTE: default + version: 7.3 dependencies: before: @@ -16,7 +14,7 @@ build: tests: override: - - command: 'vendor/bin/tester tests -p php -c ./tests/php.ini-unix --coverage build/logs/clover.xml --coverage-src src' + command: 'vendor/bin/tester -s -p php -c ./tests/php.ini-unix tests --coverage build/logs/clover.xml --coverage-src src' coverage: file: build/logs/clover.xml format: php-clover diff --git a/.travis.composer.php b/.travis.composer.php deleted file mode 100644 index 764c713..0000000 --- a/.travis.composer.php +++ /dev/null @@ -1,21 +0,0 @@ -=7.2.0", - "nette/di" : "~2.4 || ~3.0", - "nette/utils" : "~2.5 || ~3.0", + "nette/di" : "~3.0", + "nette/utils" : "~3.0", - "binsoul/net-mqtt" : "~0.2", + "binsoul/net-mqtt" : "0.2.1", "react/promise" : "~2.7", "react/socket" : "~1.2", @@ -57,16 +55,16 @@ }, "require-dev" : { - "nette/bootstrap" : "~2.4 || ~3.0", - "nette/mail" : "~2.4 || ~3.0", - "nette/robot-loader" : "~2.4 || ~3.0", + "nette/bootstrap" : "~3.0", + "nette/mail" : "~3.0", + "nette/robot-loader" : "~3.0", "nette/safe-stream" : "~2.3", "nette/tester" : "~2.3", "tracy/tracy" : "~2.4", - "contributte/event-dispatcher": "~0.5", - "contributte/console": "~0.6", + "contributte/event-dispatcher" : "~0.5", + "contributte/console" : "~0.6", "pds/skeleton" : "~1.0" }, diff --git a/src/IPub/MQTTClient/Client/Client.php b/src/IPub/MQTTClient/Client/Client.php index f4e50a4..b717048 100644 --- a/src/IPub/MQTTClient/Client/Client.php +++ b/src/IPub/MQTTClient/Client/Client.php @@ -16,6 +16,8 @@ namespace IPub\MQTTClient\Client; +use Closure; + use Nette; use React\EventLoop; @@ -26,6 +28,7 @@ use BinSoul\Net\Mqtt; +use IPub\MQTTClient\Configuration; use IPub\MQTTClient\Exceptions; use IPub\MQTTClient\Flow; @@ -59,67 +62,67 @@ final class Client implements IClient use Nette\SmartObject; /** - * @var \Closure + * @var Closure */ public $onStart = []; /** - * @var \Closure + * @var Closure */ public $onOpen = []; /** - * @var \Closure + * @var Closure */ public $onConnect = []; /** - * @var \Closure + * @var Closure */ public $onDisconnect = []; /** - * @var \Closure + * @var Closure */ public $onClose = []; /** - * @var \Closure + * @var Closure */ public $onPing = []; /** - * @var \Closure + * @var Closure */ public $onPong = []; /** - * @var \Closure + * @var Closure */ public $onPublish = []; /** - * @var \Closure + * @var Closure */ public $onSubscribe = []; /** - * @var \Closure + * @var Closure */ public $onUnsubscribe = []; /** - * @var \Closure + * @var Closure */ public $onMessage = []; /** - * @var \Closure + * @var Closure */ public $onWarning = []; /** - * @var \Closure + * @var Closure */ public $onError = []; @@ -129,7 +132,7 @@ final class Client implements IClient private $loop; /** - * @var Configuration + * @var Configuration\Broker */ private $configuration; @@ -204,7 +207,7 @@ final class Client implements IClient private $writtenFlow; /** - * @var EventLoop\Timer\TimerInterface[] + * @var EventLoop\TimerInterface[] */ private $timer = []; @@ -215,13 +218,13 @@ final class Client implements IClient /** * @param EventLoop\LoopInterface $eventLoop - * @param Configuration $configuration + * @param Configuration\Broker $configuration * @param Mqtt\IdentifierGenerator|NULL $identifierGenerator * @param Mqtt\StreamParser|NULL $parser */ public function __construct( EventLoop\LoopInterface $eventLoop, - Configuration $configuration, + Configuration\Broker $configuration, Mqtt\IdentifierGenerator $identifierGenerator = NULL, Mqtt\StreamParser $parser = NULL ) { @@ -272,8 +275,10 @@ public function getLoop() : EventLoop\LoopInterface /** * {@inheritdoc} + * + * @throws Exceptions\InvalidStateException */ - public function setConfiguration(Configuration $configuration) : void + public function setConfiguration(Configuration\Broker $configuration) : void { if ($this->isConnected() || $this->isConnecting) { throw new Exceptions\InvalidStateException('Client is connecting or connected to the broker, therefore configuration could not be changed.'); @@ -284,6 +289,8 @@ public function setConfiguration(Configuration $configuration) : void /** * {@inheritdoc} + * + * @throws Exceptions\InvalidStateException */ public function getUri() : string { @@ -323,7 +330,7 @@ public function connect() : Promise\ExtendedPromiseInterface $connection = $this->configuration->getConnection(); if ($connection->getClientID() === '') { - $connection = $connection->withClientID($this->identifierGenerator->generateClientID()); + $connection->setClientID($this->identifierGenerator->generateClientID()); } $deferred = new Promise\Deferred; @@ -473,6 +480,8 @@ function (\Exception $e) use ($deferred) { * Establishes a network connection to a server * * @return Promise\ExtendedPromiseInterface + * + * @throws Exceptions\InvalidStateException */ private function establishConnection() : Promise\ExtendedPromiseInterface { diff --git a/src/IPub/MQTTClient/Client/IClient.php b/src/IPub/MQTTClient/Client/IClient.php index c87007d..506aed2 100644 --- a/src/IPub/MQTTClient/Client/IClient.php +++ b/src/IPub/MQTTClient/Client/IClient.php @@ -21,6 +21,8 @@ use BinSoul\Net\Mqtt; +use IPub\MQTTClient\Configuration; + /** * Connection client interface * @@ -42,11 +44,11 @@ function setLoop(EventLoop\LoopInterface $loop); function getLoop() : EventLoop\LoopInterface; /** - * @param Configuration $configuration + * @param Configuration\Broker $configuration * * @return void */ - function setConfiguration(Configuration $configuration) : void; + function setConfiguration(Configuration\Broker $configuration) : void; /** * Return the host diff --git a/src/IPub/MQTTClient/Commands/ClientCommand.php b/src/IPub/MQTTClient/Commands/ClientCommand.php index 3d08a70..df53575 100644 --- a/src/IPub/MQTTClient/Commands/ClientCommand.php +++ b/src/IPub/MQTTClient/Commands/ClientCommand.php @@ -26,6 +26,7 @@ use BinSoul\Net\Mqtt; use IPub\MQTTClient\Client; +use IPub\MQTTClient\Exceptions; use IPub\MQTTClient\Logger; /** @@ -73,6 +74,8 @@ public function __construct( * @param Log\LoggerInterface $logger * * @return void + * + * @throws Exceptions\InvalidStateException */ public function setLogger(Log\LoggerInterface $logger) : void { diff --git a/src/IPub/MQTTClient/Client/Configuration.php b/src/IPub/MQTTClient/Configuration/Broker.php similarity index 89% rename from src/IPub/MQTTClient/Client/Configuration.php rename to src/IPub/MQTTClient/Configuration/Broker.php index c5ecb33..f190c9b 100644 --- a/src/IPub/MQTTClient/Client/Configuration.php +++ b/src/IPub/MQTTClient/Configuration/Broker.php @@ -1,6 +1,6 @@ */ -final class Configuration +final class Broker { /** * Implement nette smart magic @@ -73,7 +71,7 @@ final class Configuration private $sslSettings = []; /** - * @var Mqtt\Connection + * @var Connection */ private $connection; @@ -85,7 +83,7 @@ final class Configuration * @param string $dnsAddress * @param bool $enableSSL * @param array $sslSettings - * @param Mqtt\Connection $connection + * @param Connection $connection */ public function __construct( string $httpHost = NULL, @@ -95,7 +93,7 @@ public function __construct( string $dnsAddress = '8.8.8.8', bool $enableSSL = FALSE, array $sslSettings, - Mqtt\Connection $connection + Connection $connection ) { $this->httpHost = $httpHost; $this->port = $port; @@ -181,9 +179,9 @@ public function getSSLConfiguration() : array } /** - * @return Mqtt\Connection + * @return Connection */ - public function getConnection() : Mqtt\Connection + public function getConnection() : Connection { return $this->connection; } diff --git a/src/IPub/MQTTClient/Configuration/Connection.php b/src/IPub/MQTTClient/Configuration/Connection.php new file mode 100644 index 0000000..9adae74 --- /dev/null +++ b/src/IPub/MQTTClient/Configuration/Connection.php @@ -0,0 +1,257 @@ + + */ +final class Connection implements Mqtt\Connection +{ + /** + * Implement nette smart magic + */ + use Nette\SmartObject; + + /** + * @var string + */ + private $username; + + /** + * @var string + */ + private $password; + + /** + * @var Mqtt\Message|NULL + */ + private $will = NULL; + + /** + * @var string + */ + private $clientID; + + /** + * @var int + */ + private $keepAlive; + + /** + * @var int + */ + private $protocol; + + /** + * @var bool + */ + private $clean; + + /** + * @param string $username + * @param string $password + * @param Mqtt\Message|NULL $will + * @param string $clientID + * @param int $keepAlive + * @param int $protocol + * @param bool $clean + */ + public function __construct( + string $username = '', + string $password = '', + Mqtt\Message $will = NULL, + string $clientID = '', + int $keepAlive = 60, + int $protocol = 4, + bool $clean = TRUE + ) { + $this->username = $username; + $this->password = $password; + $this->will = $will; + $this->clientID = $clientID; + $this->keepAlive = $keepAlive; + $this->protocol = $protocol; + $this->clean = $clean; + } + + /** + * @return int + */ + public function getProtocol() : int + { + return $this->protocol; + } + + /** + * @param string $clientID + * + * @return void + */ + public function setClientID(string $clientID) : void + { + $this->clientID = $clientID; + } + + /** + * @return string + */ + public function getClientID() : string + { + return $this->clientID; + } + + /** + * @return bool + */ + public function isCleanSession() : bool + { + return $this->clean; + } + + /** + * @param string $username + * + * @return void + */ + public function setUsername(string $username) : void + { + $this->username = $username; + } + + /** + * @return string + */ + public function getUsername() : string + { + return $this->username; + } + + /** + * @param string $password + * + * @return void + */ + public function setPassword(string $password) : void + { + $this->password = $password; + } + + /** + * @return string + */ + public function getPassword() : string + { + return $this->password; + } + + /** + * @param Mqtt\Message|NULL $will + * + * @return void + */ + public function setWill(?Mqtt\Message $will) : void + { + $this->will = $will; + } + + /** + * @return Mqtt\Message|NULL + */ + public function getWill() : ?Mqtt\Message + { + return $this->will; + } + + /** + * @return int + */ + public function getKeepAlive() : int + { + return $this->keepAlive; + } + + /** + * @param string $clientID + * + * @return self + */ + public function withClientID($clientID) : self + { + $this->clientID = $clientID; + + return $this; + } + + /** + * @param string $username + * @param string $password + * + * @return self + */ + public function withCredentials($username, $password) : self + { + $this->username = $username; + $this->password = $password; + + return $this; + } + + /** + * @param int $timeout + * + * @return self + */ + public function withKeepAlive($timeout) : self + { + $this->keepAlive = $timeout; + + return $this; + } + + /** + * @param int $protocol + * + * @return self + */ + public function withProtocol($protocol) : self + { + $this->protocol = $protocol; + + return $this; + } + + /** + * @param Mqtt\Message $will + * + * @return self + */ + public function withWill(Mqtt\Message $will) : self + { + $this->will = $will; + + return $this; + } +} diff --git a/src/IPub/MQTTClient/DI/MQTTClientExtension.php b/src/IPub/MQTTClient/DI/MQTTClientExtension.php index ee46b53..cd4aa39 100644 --- a/src/IPub/MQTTClient/DI/MQTTClientExtension.php +++ b/src/IPub/MQTTClient/DI/MQTTClientExtension.php @@ -18,9 +18,7 @@ use Nette; use Nette\DI; -use Nette\PhpGenerator as Code; - -use BinSoul\Net\Mqtt; +use Nette\Schema; use Symfony\Component\EventDispatcher; @@ -31,6 +29,7 @@ use IPub\MQTTClient; use IPub\MQTTClient\Client; use IPub\MQTTClient\Commands; +use IPub\MQTTClient\Configuration; use IPub\MQTTClient\Events; use IPub\MQTTClient\Logger; @@ -41,58 +40,49 @@ * @subpackage DI * * @author Adam Kadlec - * - * @method DI\ContainerBuilder getContainerBuilder() - * @method array getConfig(array $default) - * @method string prefix($id) */ final class MQTTClientExtension extends DI\CompilerExtension { /** - * @var array + * {@inheritdoc} */ - private $defaults = [ - 'broker' => [ - 'httpHost' => NULL, - 'port' => 1883, - 'address' => NULL, - 'dns' => [ - 'enable' => TRUE, - 'address' => '8.8.8.8', - ], - 'secured' => [ - 'enable' => FALSE, - 'sslSettings' => [], - ], - ], - 'connection' => [ - 'username' => '', - 'password' => '', - 'clientID' => '', - 'keepAlive' => 60, - 'protocol' => 4, - 'clean' => TRUE, - ], - 'loop' => NULL, - 'console' => FALSE, - 'symfonyEvents' => FALSE, - ]; + public function getConfigSchema() : Schema\Schema + { + return Schema\Expect::structure([ + 'broker' => Schema\Expect::structure([ + 'httpHost' => Schema\Expect::string()->nullable(), + 'port' => Schema\Expect::int(1883), + 'address' => Schema\Expect::string('127.0.0.1'), + 'dns' => Schema\Expect::structure([ + 'enable' => Schema\Expect::bool(TRUE), + 'address' => Schema\Expect::string('8.8.8.8'), + ]), + 'secured' => Schema\Expect::structure([ + 'enable' => Schema\Expect::bool(TRUE), + 'sslSettings' => Schema\Expect::array([]), + ]), + ]), + 'connection' => Schema\Expect::structure([ + 'username' => Schema\Expect::string(''), + 'password' => Schema\Expect::string(''), + 'clientID' => Schema\Expect::string(''), + 'keepAlive' => Schema\Expect::int(60), + 'protocol' => Schema\Expect::int(4), + 'clean' => Schema\Expect::bool(TRUE), + ]), + 'loop' => Schema\Expect::anyOf(Schema\Expect::string(), Schema\Expect::type(DI\Definitions\Statement::class))->nullable(), + ]); + } /** * {@inheritdoc} */ public function loadConfiguration() { - // Get container builder $builder = $this->getContainerBuilder(); - /** @var array $configuration */ - if (method_exists($this, 'validateConfig')) { - $configuration = $this->validateConfig($this->defaults); - } else { - $configuration = $this->getConfig($this->defaults); - } + $configuration = $this->getConfig(); - if ($configuration['loop'] === NULL) { + if ($configuration->loop === NULL) { if ($builder->getByType(React\EventLoop\LoopInterface::class) === NULL) { $loop = $builder->addDefinition($this->prefix('client.loop')) ->setType(React\EventLoop\LoopInterface::class) @@ -103,29 +93,33 @@ public function loadConfiguration() } } else { - $loop = $builder->getDefinition(ltrim($configuration['loop'], '@')); + $loop = is_string($configuration->loop) ? new DI\Definitions\Statement($configuration->loop) : $configuration->loop; } - $connection = new Mqtt\DefaultConnection( - $configuration['connection']['username'], - $configuration['connection']['password'], - NULL, - $configuration['connection']['clientID'], - $configuration['connection']['keepAlive'], - $configuration['connection']['protocol'], - $configuration['connection']['clean'] - ); + $connection = $builder->addDefinition($this->prefix('client.configuration.connection')) + ->setType(Configuration\Connection::class) + ->setArguments([ + 'username' => $configuration->connection->username, + 'password' => $configuration->connection->password, + 'will' => NULL, + 'clientID' => $configuration->connection->clientID, + 'keepAlive' => $configuration->connection->keepAlive, + 'protocol' => $configuration->connection->protocol, + 'clean' => $configuration->connection->clean, + ]); - $clientConfiguration = new Client\Configuration( - $configuration['broker']['httpHost'], - $configuration['broker']['port'], - $configuration['broker']['address'], - $configuration['broker']['dns']['enable'], - $configuration['broker']['dns']['address'], - $configuration['broker']['secured']['enable'], - $configuration['broker']['secured']['sslSettings'], - $connection - ); + $brokerConfiguration = $builder->addDefinition($this->prefix('client.configuration')) + ->setType(Configuration\Broker::class) + ->setArguments([ + 'httpHost' => $configuration->broker->httpHost, + 'port' => $configuration->broker->port, + 'address' => $configuration->broker->address, + 'enableDNS' => $configuration->broker->dns->enable, + 'dnsAddress' => $configuration->broker->dns->address, + 'enableSSL' => $configuration->broker->secured->enable, + 'sslSettings' => $configuration->broker->secured->sslSettings, + $connection, + ]); if ($builder->findByType(Log\LoggerInterface::class) === []) { $builder->addDefinition($this->prefix('server.logger')) @@ -136,17 +130,17 @@ public function loadConfiguration() ->setType(Client\Client::class) ->setArguments([ 'eventLoop' => $loop, - 'configuration' => $clientConfiguration, + 'configuration' => $brokerConfiguration, ]); - if ($configuration['console'] === TRUE) { + if (class_exists('Symfony\Component\Console\Command\Command')) { // Define all console commands $commands = [ 'client' => Commands\ClientCommand::class, ]; foreach ($commands as $name => $cmd) { - $builder->addDefinition($this->prefix('commands' . lcfirst($name))) + $builder->addDefinition($this->prefix('commands.' . lcfirst($name))) ->setType($cmd); } } @@ -159,23 +153,13 @@ public function beforeCompile() { parent::beforeCompile(); - // Get container builder - $builder = $this->getContainerBuilder(); - /** @var array $configuration */ - if (method_exists($this, 'validateConfig')) { - $configuration = $this->validateConfig($this->defaults); - } else { - $configuration = $this->getConfig($this->defaults); - } - - // Get container builder $builder = $this->getContainerBuilder(); - if ($configuration['symfonyEvents'] === TRUE) { + if (interface_exists('Symfony\Component\EventDispatcher\EventDispatcherInterface')) { $dispatcher = $builder->getDefinition($builder->getByType(EventDispatcher\EventDispatcherInterface::class)); $client = $builder->getDefinition($builder->getByType(Client\Client::class)); - assert($client instanceof DI\ServiceDefinition); + assert($client instanceof DI\Definitions\ServiceDefinition); $client->addSetup('?->onStart[] = function() {?->dispatch(new ?(...func_get_args()));}', [ '@self', @@ -251,8 +235,10 @@ public function beforeCompile() * * @return void */ - public static function register(Nette\Configurator $config, string $extensionName = 'mqttClient') - { + public static function register( + Nette\Configurator $config, + string $extensionName = 'mqttClient' + ) :void { $config->onCompile[] = function (Nette\Configurator $config, DI\Compiler $compiler) use ($extensionName) { $compiler->addExtension($extensionName, new MQTTClientExtension); }; diff --git a/src/IPub/MQTTClient/Flow/Envelope.php b/src/IPub/MQTTClient/Flow/Envelope.php index 8099eb7..8e4a9ba 100644 --- a/src/IPub/MQTTClient/Flow/Envelope.php +++ b/src/IPub/MQTTClient/Flow/Envelope.php @@ -31,7 +31,7 @@ final class Envelope implements Mqtt\Flow { /** - * @var Flow + * @var Mqtt\Flow */ private $flow; diff --git a/tests/IPubTests/MQTTClient/ExtensionTest.phpt b/tests/IPubTests/MQTTClient/ExtensionTest.phpt index e71cad4..a6ab4ff 100644 --- a/tests/IPubTests/MQTTClient/ExtensionTest.phpt +++ b/tests/IPubTests/MQTTClient/ExtensionTest.phpt @@ -55,12 +55,9 @@ class ExtensionTest extends Tester\TestCase $config = new Nette\Configurator; $config->setTempDirectory(TEMP_DIR); - if (getenv('NETTE') === 'default') { - $config->addConfig(__DIR__ . DS . 'files' . DS . 'config.neon'); + $config->addConfig(__DIR__ . DS . 'files' . DS . 'config.neon'); - } else { - $config->addConfig(__DIR__ . DS . 'files' . DS . 'config24.neon'); - } + MQTTClient\DI\MQTTClientExtension::register($config); return $config->createContainer(); } diff --git a/tests/IPubTests/MQTTClient/files/config.neon b/tests/IPubTests/MQTTClient/files/config.neon index 94b2ab0..078662f 100644 --- a/tests/IPubTests/MQTTClient/files/config.neon +++ b/tests/IPubTests/MQTTClient/files/config.neon @@ -1,13 +1,8 @@ extensions: - mqttClient : IPub\MQTTClient\DI\MQTTClientExtension - events : Contributte\EventDispatcher\DI\EventDispatcherExtension - console: Contributte\Console\DI\ConsoleExtension(%consoleMode%) + contributteEvents : Contributte\EventDispatcher\DI\EventDispatcherExtension + contributteConsole : Contributte\Console\DI\ConsoleExtension(%consoleMode%) -mqttClient: - console: true - symfonyEvents: true - -console: +contributteConsole: name: iPublikuj:Packages! version: '1.0' catchExceptions: true diff --git a/tests/IPubTests/MQTTClient/files/config24.neon b/tests/IPubTests/MQTTClient/files/config24.neon deleted file mode 100644 index cb44cb6..0000000 --- a/tests/IPubTests/MQTTClient/files/config24.neon +++ /dev/null @@ -1,18 +0,0 @@ -extensions: - mqttClient : IPub\MQTTClient\DI\MQTTClientExtension - events : Contributte\EventDispatcher\DI\EventDispatcherExtension - console: Contributte\Console\DI\ConsoleExtension(%consoleMode%) - -mqttClient: - console: true - symfonyEvents: true - -console: - name: iPublikuj:Packages! - version: '1.0' - catchExceptions: true - autoExit: true - url: null - lazy: false - helperSet: null - helpers: [] \ No newline at end of file