boenrobot
Repos
46
Followers
18
Following
1

This package allows you to read and write information from a RouterOS host using the MikroTik RouterOS API protocol.

214
111

A stream wrapper that ensures data integrity. Particularly useful for sockets.

8
3

Wrapper for shared memory and locking functionality across different PHP extensions.

6
5

Genetaror for ANSI color escape sequences.

5
0

Analyzes available menus/commands/arguments on a MikroTik RouterOS installation using SSH, outputted in JSON

9
3

Events

Created at 1 week ago
How to support duplicate column names?

IMHO, adding a fetch mode in general is worth it.

Keep the current default of taking the last value in an associate array (both for the sake of BC, but also for the sake of people coming from PDO), but add an indexed array option, which would return all column values mapped to the same indexes (i.e. count($queryResult->resultFields) === count($queryResult->resultRows[0])).

Adding a object mode could be worth it if that object combines the two other fetch modes, i.e. it provides ArrayAccess that would give the column at that index when given an integer, or the last column of that name if given a string. On such an object, count() and foreach behavior could perhaps default to the associative array behavior, but provide a setter to switch both to an indexed mode. This object mode would obviously be more memory consuming, since it would need to contain a reference to some "string to index" map which would add some overhead.

A "compact" object mode (akin to PDO's object mode) is not worth it I think, as in PHP, it has the same ergonomics as an associative array. If you need an stdClass, you can always just cast the associative array.

A "class" mode is also not worth it I think, as you still need to define a mapping anyway - might as well define it out of the build it fetch modes. Less magic = easier to reason about.

Created at 2 weeks ago
started
Created at 2 weeks ago
started
Created at 2 weeks ago
started
Created at 3 weeks ago

Initial commit

First sources.

Changed the plugin to handle any "library" type package with a "functionmap" in its composer.json's extra.

Handle the case where the same file defines multiple functions and/or appears more than once in "files": The file will be included once if at least one of the functions in it is needed, and will be removed if none of them are needed. Also, if one of the files in the map is included multiple times in the "files" section, all occurrences of it will be removed, or if needed by one function, but not all, appear at the bottom of the list (in order of the function map);

Files not part of the map will not be tweaked at all, which includes them being included multiple times if that's what specified.

Updated version constraints to allow for Composer's plugin API 2.0;

Fixed some typos.

Fixed Composer 2 compatibility.

Created at 3 weeks ago

Initial commit

Added sources.

Added composer.lock to .gitignore;

Added an install hook to the autoload generation, which should remove the file from the autoload list if not needed.

Added a dependency on a custom plugin that inspects "functionmap" in "extra";

Removed the Install.php script.

Fix signal usage, should appear on negative numbers only. Fix ignoring 0 fraction digits.

Merge pull request #1 from Nenillo/master

Fix signal usage, should appear on negative numbers only. Fix ignorin…

Created at 3 weeks ago

Initial commit

Added sources.

Added composer.lock to .gitignore;

Added an install hook to the autoload generation, which should remove the file from the autoload list if not needed.

Added a dependency on a custom plugin that inspects "functionmap" in "extra";

Removed the Install.php script.

Fix signal usage, should appear on negative numbers only. Fix ignoring 0 fraction digits.

Merge pull request #1 from Nenillo/master

Fix signal usage, should appear on negative numbers only. Fix ignorin…

Created at 3 weeks ago

Added sources.

Added composer.lock to .gitignore;

Added an install hook to the autoload generation, which should remove the file from the autoload list if not needed.

Added a dependency on a custom plugin that inspects "functionmap" in "extra";

Removed the Install.php script.

Fix signal usage, should appear on negative numbers only. Fix ignoring 0 fraction digits.

Merge pull request #1 from Nenillo/master

Fix signal usage, should appear on negative numbers only. Fix ignorin…

Created at 3 weeks ago

Added sources.

Added composer.lock to .gitignore;

Added an install hook to the autoload generation, which should remove the file from the autoload list if not needed.

Added a dependency on a custom plugin that inspects "functionmap" in "extra";

Removed the Install.php script.

Fix signal usage, should appear on negative numbers only. Fix ignoring 0 fraction digits.

Merge pull request #1 from Nenillo/master

Fix signal usage, should appear on negative numbers only. Fix ignorin…

Created at 3 weeks ago
Created at 3 weeks ago

First sources.

Changed the plugin to handle any "library" type package with a "functionmap" in its composer.json's extra.

Handle the case where the same file defines multiple functions and/or appears more than once in "files": The file will be included once if at least one of the functions in it is needed, and will be removed if none of them are needed. Also, if one of the files in the map is included multiple times in the "files" section, all occurrences of it will be removed, or if needed by one function, but not all, appear at the bottom of the list (in order of the function map);

Files not part of the map will not be tweaked at all, which includes them being included multiple times if that's what specified.

Updated version constraints to allow for Composer's plugin API 2.0;

Fixed some typos.

Fixed Composer 2 compatibility.

Created at 3 weeks ago
issue comment
Equivalent to "::class" for obtaining property and variable names as a string

However, I don't think this should be encouraged for variables as variable variables are almost never the right solution.

Agree about variable variables in general, but part of why they are almost always not the right solution is due to the lack of this feature though. i.e. other solutions can be statically analyzed, making them less error prone, while variable variables can't be.

If this feature is available with variables, for the purposes of variable variables, I think more developers who would otherwise use variable variables will see the error of their ways more easily. The more you try to use it with variables, the more easily you'd see you need an array or an object instead. And best of all - you could actually move away from variable variables with tool assistance more easily.

I'm also skeptical of a runtime check, as Foo::class does not trigger the autoloader and thus doesn't do any validation. So IMO neither should this construct.

Fine by me.

The syntax var::MyClass::$myStaticProp/var(MyClass::$myStaticProp) for static properties still makes sense. I guess var::$obj->myProp/var($obj->myProp) also makes sense even then.

Without an object reference var::MyClass->myProp/var(MyClass->myProp) could work, even though it looks a bit weird.

Created at 4 weeks ago
opened issue
Equivalent to "::class" for obtaining property and variable names as a string

Description

I understand this will require an RFC, but I don't have any know how on how to implement this (I'm just a poor PHP user), so I thought I outline the issue, and hopefully inspire someone more familiar with the engine to pick it up. Maybe not necessarily end with the proposed design.

Problem

There is no way to get a reference to a property or variable symbol in a way that is subject to static analysis and/or easy refactors.

Precedent

Objects and classes

Objects and class symbols have ::class that gives the name of a class. IDEs can rename the class with this also including usages of ::class, ensuring that if a class name was expected, it would still point to the correct class after a rename. Static analyzers can warn if ::class is not used for functions/methods that are annotated as accepting a class string or the string is otherwise wrong (e.g. in PHPStan).

Methods and functions

Since PHP 8.1, methods and function symbols now have (...) that gives a callable. Again, this allows IDEs to rename a method/function while keeping the references to it valid, and also allows static analyzers to match it with annotated callables and report signature inconsistencies or a missing function in the case of plain strings (e.g. in PHPStan).

Properties and variables

There is no way in which you can reference the name of a property or a variable without resorting to an unannotated string, which breaks static analyzers. In the case of IDEs, they may try to be a bit smarter, but can also cause false renames in unrelated strings.

The closest thing one can do today would be to have the property/variable name in a constant, and then use the constant (plus for PHPStan to add an annotation for a property/variable name). Even this approach however would keep the value of the constant and the actual variable name not necessarily tied. One at bare minimum needs to change the property name and the constant value, while ensuring all places use the constant. It's also a bit less DX friendly - you are adding an extra boilerplate symbol - a constant - to address a limitation of the engine. This is just as unfriendly as doing the same for classes prior to the days of ::class.

Proposal

Enable the use of a keyword combined with :: or some more exotic syntax, that would take a variable or property and produce results similar to ::class - produce a string that is the property/variable name. Once this name is obtained, it could later be used in dynamic property accessors or variable variables.

The keyword var will be used to illustrate the point - it sounds like a relatively intuitive keyword for the use case, is an existing keyword, and it's short.

With regards to protected and private properties, and the interaction with __get and __set magic methods, for best DX, this syntax should allow the access of protected and private property names, even outside the object, but only if they are available inside the referenced object, and only if they are NOT dynamically defined or otherwise only accessible via magic methods. If one tries to actually access the protected/private property of that name (not just get its name), they are still subject to the normal access rules, same as if a literal string was supplied.

e.g.

$myVar = 0;

class MyClass {
    public static $myStaticProp = 1;
    protected static $myProtectedStaticProp = 2;
    private static $myPrivateStaticProp = 3;

    public $myProp = 4;
    protected $myProtectedProp = 5;
    private $myPrivateProp = 6;

    public function out(string $prop)
    {
        return $this->{$prop};
    }
}

class MyExtendedClass extends MyClass {
    public static $myExtendedStaticProp = 11;
    protected static $myExtendedProtectedStaticProp = 12;
    private static $myExtendedPrivateStaticProp = 13;

    public $myExtendedProp = 14;
    protected $myExtendedProtectedProp = 15;
    private $myExtendedPrivateProp = 16;

    public function outExt(string $prop)
    {
        return $this->{$prop};
    }
}

$varName = var::$myVar; // $varName = 'myVar'
echo ${$varName};//Outputs 0

$publicStaticPropName = var::MyClass::$myStaticProp; // $publicStaticPropName = 'myStaticProp'
echo MyClass::${$publicStaticPropName};//Outputs 1

$protectedStaticPropName = var::MyClass::$myProtectedStaticProp; // $protectedStaticPropName = 'myProtectedStaticProp'
echo MyClass::${$protectedStaticPropName};//Runtime error; Protected static property is not accessible here

$className = MyExtendedClass::class;
$obj = new $className();
$propName = var::$obj->myProp; // $propName = 'myProp'
echo $obj->{$propName};//Outputs 4

$protectedPropName = var::$obj->myProtectedProp; // $protectedPropName = 'myProtectedProp'
echo $obj->{$protectedPropName};// Runtime error; Protected property is not accessible here
echo $obj->out($protectedPropName); //Outputs 5

$privatePropName = var::$obj->myPrivateProp; // Runtime error; myPrivateProp is not available from MyExtendedClass
$extendedPrivatePropName = $obj->myExtendedPrivateProp::use; // $extendedPrivatePropName = 'myExtendedPrivateProp'
echo $obj->outExt($extendedPrivatePropName);//Outputs 16

Use cases

The biggest practical use use today is in ORMs like doctrine. They rely on properties to hold the column values. Those property names are in turn referenced in queries, so that the query builder can build the proper query. One can't simply rename a property in a doctrine entity without also going through any place in the code that this property may be used. Admittedly, in a well organized code base, that would probably be just one file - the repository class, but even then - it may be multiple times in it, with a simple search & replace potentially being error prone if the property name is shared with that of a related entity also used in the same repo.

Specialized doctrine IDE plugins may help with that, but it would be better overall for the PHP ecosystem if any library could do this, for any purpose, without a specialized plugin.

Syntax choice

Due to the change in access rules for this (protected and private properties being allowed), a prefix is used. This enables IDEs to filter suggestions early, and for PHP itself to know that it will get a reference to a variable or property symbol on the right hand side of ::, which in turn removes potential ambiguities. Basically, the allowed forms on the right of var:: are variables accessible in the current scope, or any expression ending with "::$" or "->" on the same expression level. Anything else, including a single bracketed statement without anything after it can be assumed to evaluate to a literal, rather than a property or variable symbol.

e.g.

//sugar
$varName = var::(new $className)->myProp;
//desugar
new $className
$varName = 'myProp'

//sugar
$obj->{(var::(new $className)->myPropPointingToObject)}->myProp;
//desugar
new $className;
$obj->myPropPointingToObject->myProp;

//sugar
$obj->{(var::MyRelatedClass::$myRelatedProp) . 'Key'}->myProp
//desugar
$obj->myRelatedPropKey->myProp

// sugar
$obj->{var::$myVar};
//desugar
$obj->myVar;

// sagar
$obj->{var::($myVar)->myProp};
//desugar
$obj->myProp;

//sugar
$obj->{var::$myVar}::class
//desugar
$obj->myVar::class

//sugar
$obj->{var::$myVar}(...)
//desugar
$obj->myVar(...)


//sugar
$obj->{var::MyRelatedClass::${(var::MyOtherRelatedClassClass::myOtherRelatedProp) . 'Key'}}->myProp
//desugar inner most
$obj->{var::MyRelatedClass::${'myOtherRelatedPropKey'}}->myProp
//desugar further
$obj->myOtherRelatedPropKey->myProp

// A less useful in real situation case, but still perfectly fine syntax wise
//sugar
$obj->{(var::MyRelatedClass::${var::MyOtherRelatedClassClass::myOtherRelatedProp}) . 'Key'}->myProp
//desugar inner most
$obj->{(var::MyRelatedClass::${'myOtherRelatedProp'}) . 'Key'}->myProp
//desugar further
$obj->{'myOtherRelatedProp' . 'Key'}->myProp
//desugar final
$obj->myOtherRelatedPropKey->myProp


$obj->{var::($myVar)};//Parse error; ($myVar) evaluates to a literal with the value of $myVar

$obj->{var::$myVar::class};//Parse error; $var::class evaluates to a literal
$obj->{var::($myObj->{$myVar})::class};//Parse error; ($myObj->{$myVar})::class evaluates to a literal
$obj->{var::MyClass::MY_CONSTANT};//Parse error; MyClass::MY_CONSTANT evaluates to a literal

$obj->{(var::MyRelatedClass::${var::MyOtherRelatedClassClass::myOtherRelatedProp . 'Key'})}->myProp//Parse error; The final operator on the right of the inner var:: is concatenation
Created at 1 month ago
Created at 1 month ago
Created at 1 month ago

Emit the close event even when the reason is connection failure.

Merge branch 'close-connection-event' of https://github.com/boenrobot/thruway-client into fork

Created at 1 month ago
pull request opened
Emit the close event even when the reason is connection failure.

Right now, if there is a connection failure, there is no way to handle it in any custom way. You only get the log in the rejection promise and that's it.

This PR changes it so that the close event is emitted even on connection failures, with $reason = "unreachable".

Created at 1 month ago
create branch
boenrobot create branch close-connection-event
Created at 1 month ago

Handle case when session is null on receiving a message

Add a way to add custom Connector

Merge pull request #13 from Cube-Solutions/master

Handle case when session is null on receiving a message

Created at 1 month ago
issue comment
Test CHR & RouterOS (6.48.6/6.49.6/7.4) without results

This project was made in the ancient times of RouterOS 6.2, and hasn't been kept compatible since.

It should've in theory worked for any version, but I guess MikroTik changed their shh output in an incompatible fashion.

I was never the original author, and I don't have the time to maintain this.

I would happily welcome PRs, or even a pointer to a separate, more fully maintained project.

Created at 1 month ago

Added support for "eligible_authrole" and "eligible_authid" options in publish messages, in accordance with the standard. For backwards compatibility, the prefixed versions "_thruway_eligible_authroles" and "_thruway_eligible_authids" are still preferred if both prefixed and unprefixed variant are specified.

Created at 2 months ago
pull request opened
Added support for unprefixed "eligible_authroles" and "eligible_authids"

I don't see any reason why those shouldn't be supported, seeing as they are a thing in the WAMP spec now.

I'm guessing once upon a time, they weren't, so this prefixed version was added? I've added support for the unprefixed one in what I think is a backwards compatible fashion, for any users who are already using the prefixed version.

Created at 2 months ago
create branch
boenrobot create branch unprefixed-eligibles
Created at 2 months ago
Created at 2 months ago
pull request opened
Fixed required PHP version, to be a minimum of 7.1, not 7.2

As mentioned in #16, I'm pretty sure ">7.1" is a mistake, and it should be ">=7.1" instead.

Here it is in a separate PR.

Created at 2 months ago

Fixed required PHP version, to be a minimum of 7.1, not 7.2

Merge branch 'php-fix' of https://github.com/boenrobot/client into fork

Created at 2 months ago
create branch
boenrobot create branch php-fix
Created at 2 months ago
create branch
boenrobot create branch fork
Created at 2 months ago

Added support for optional "authextra" in hello packets (specified as an option to the constructor or via a setter);

Enabled onChallenge to optionally specify auth extra in the challenge response (modeled after autobahn's behavior).

Created at 2 months ago