Browse Source

Merge pull request #33 from Compolomus/Refactoring

Refactoring of Client class
tags/1.2.2 1.2.2
Paul Zloi 6 years ago
committed by GitHub
parent
commit
cbac8b7906
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 231
      .editorconfig
  2. 6
      .gitattributes
  3. 2
      .gitignore
  4. 4
      .travis.yml
  5. 12
      composer.json
  6. 5
      src/APIConnector.php
  7. 126
      src/APILengthCoDec.php
  8. 148
      src/Client.php
  9. 40
      src/Interfaces/QueryInterface.php
  10. 34
      src/Query.php

231
.editorconfig

@ -0,0 +1,231 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = false
max_line_length = 140
tab_width = 2
ij_continuation_indent_size = 2
ij_formatter_off_tag = @formatter:off
ij_formatter_on_tag = @formatter:on
ij_formatter_tags_enabled = false
ij_smart_tabs = false
ij_wrap_on_typing = false
[{*.ctp,*.hphp,*.inc,*.module,*.php,*.php4,*.php5,*.phtml}]
max_line_length = 999
ij_continuation_indent_size = 4
indent_size = 4
tab_width = 4
ij_php_align_assignments = true
ij_php_align_class_constants = true
ij_php_align_group_field_declarations = true
ij_php_align_inline_comments = true
ij_php_align_key_value_pairs = true
ij_php_align_multiline_array_initializer_expression = true
ij_php_align_multiline_binary_operation = false
ij_php_align_multiline_chained_methods = false
ij_php_align_multiline_extends_list = false
ij_php_align_multiline_for = true
ij_php_align_multiline_parameters = false
ij_php_align_multiline_parameters_in_calls = false
ij_php_align_multiline_ternary_operation = false
ij_php_align_phpdoc_comments = true
ij_php_align_phpdoc_param_names = true
ij_php_anonymous_brace_style = end_of_line
ij_php_api_weight = 28
ij_php_array_initializer_new_line_after_left_brace = true
ij_php_array_initializer_right_brace_on_new_line = true
ij_php_array_initializer_wrap = off
ij_php_assignment_wrap = off
ij_php_author_weight = 28
ij_php_binary_operation_sign_on_next_line = false
ij_php_binary_operation_wrap = off
ij_php_blank_lines_after_class_header = 0
ij_php_blank_lines_after_function = 1
ij_php_blank_lines_after_imports = 1
ij_php_blank_lines_after_opening_tag = 0
ij_php_blank_lines_after_package = 1
ij_php_blank_lines_around_class = 1
ij_php_blank_lines_around_constants = 0
ij_php_blank_lines_around_field = 0
ij_php_blank_lines_around_method = 1
ij_php_blank_lines_before_class_end = 0
ij_php_blank_lines_before_imports = 1
ij_php_blank_lines_before_method_body = 0
ij_php_blank_lines_before_package = 1
ij_php_blank_lines_before_return_statement = 0
ij_php_blank_lines_between_imports = 0
ij_php_block_brace_style = end_of_line
ij_php_call_parameters_new_line_after_left_paren = false
ij_php_call_parameters_right_paren_on_new_line = false
ij_php_call_parameters_wrap = normal
ij_php_catch_on_new_line = false
ij_php_category_weight = 28
ij_php_class_brace_style = next_line
ij_php_comma_after_last_array_element = false
ij_php_concat_spaces = true
ij_php_copyright_weight = 28
ij_php_deprecated_weight = 28
ij_php_do_while_brace_force = always
ij_php_else_if_style = combine
ij_php_else_on_new_line = false
ij_php_example_weight = 28
ij_php_extends_keyword_wrap = off
ij_php_extends_list_wrap = off
ij_php_fields_default_visibility = private
ij_php_filesource_weight = 28
ij_php_finally_on_new_line = false
ij_php_for_brace_force = always
ij_php_for_statement_new_line_after_left_paren = false
ij_php_for_statement_right_paren_on_new_line = false
ij_php_for_statement_wrap = off
ij_php_force_short_declaration_array_style = true
ij_php_global_weight = 28
ij_php_group_use_wrap = on_every_item
ij_php_if_brace_force = always
ij_php_if_lparen_on_next_line = false
ij_php_if_rparen_on_next_line = false
ij_php_ignore_weight = 28
ij_php_import_sorting = alphabetic
ij_php_indent_break_from_case = true
ij_php_indent_case_from_switch = true
ij_php_indent_code_in_php_tags = false
ij_php_internal_weight = 28
ij_php_keep_blank_lines_after_lbrace = 2
ij_php_keep_blank_lines_before_right_brace = 2
ij_php_keep_blank_lines_in_code = 2
ij_php_keep_blank_lines_in_declarations = 2
ij_php_keep_control_statement_in_one_line = true
ij_php_keep_first_column_comment = true
ij_php_keep_indents_on_empty_lines = false
ij_php_keep_line_breaks = true
ij_php_keep_rparen_and_lbrace_on_one_line = true
ij_php_keep_simple_methods_in_one_line = false
ij_php_lambda_brace_style = end_of_line
ij_php_license_weight = 28
ij_php_line_comment_add_space = false
ij_php_line_comment_at_first_column = true
ij_php_link_weight = 28
ij_php_lower_case_boolean_const = true
ij_php_lower_case_keywords = true
ij_php_lower_case_null_const = true
ij_php_method_brace_style = next_line
ij_php_method_call_chain_wrap = off
ij_php_method_parameters_new_line_after_left_paren = true
ij_php_method_parameters_right_paren_on_new_line = true
ij_php_method_parameters_wrap = on_every_item
ij_php_method_weight = 28
ij_php_modifier_list_wrap = false
ij_php_multiline_chained_calls_semicolon_on_new_line = false
ij_php_namespace_brace_style = 1
ij_php_new_line_after_php_opening_tag = false
ij_php_null_type_position = in_the_end
ij_php_package_weight = 28
ij_php_param_weight = 0
ij_php_parentheses_expression_new_line_after_left_paren = false
ij_php_parentheses_expression_right_paren_on_new_line = false
ij_php_phpdoc_blank_line_before_tags = true
ij_php_phpdoc_blank_lines_around_parameters = true
ij_php_phpdoc_keep_blank_lines = true
ij_php_phpdoc_param_spaces_between_name_and_description = 1
ij_php_phpdoc_param_spaces_between_tag_and_type = 1
ij_php_phpdoc_param_spaces_between_type_and_name = 1
ij_php_phpdoc_use_fqcn = true
ij_php_phpdoc_wrap_long_lines = false
ij_php_place_assignment_sign_on_next_line = false
ij_php_place_parens_for_constructor = 0
ij_php_property_read_weight = 28
ij_php_property_weight = 28
ij_php_property_write_weight = 28
ij_php_return_type_on_new_line = false
ij_php_return_weight = 1
ij_php_see_weight = 28
ij_php_since_weight = 28
ij_php_sort_phpdoc_elements = true
ij_php_space_after_colon = true
ij_php_space_after_colon_in_return_type = true
ij_php_space_after_comma = true
ij_php_space_after_for_semicolon = true
ij_php_space_after_quest = true
ij_php_space_after_type_cast = true
ij_php_space_after_unary_not = false
ij_php_space_before_array_initializer_left_brace = false
ij_php_space_before_catch_keyword = true
ij_php_space_before_catch_left_brace = true
ij_php_space_before_catch_parentheses = true
ij_php_space_before_class_left_brace = true
ij_php_space_before_closure_left_parenthesis = true
ij_php_space_before_colon = true
ij_php_space_before_colon_in_return_type = false
ij_php_space_before_comma = false
ij_php_space_before_do_left_brace = true
ij_php_space_before_else_keyword = true
ij_php_space_before_else_left_brace = true
ij_php_space_before_finally_keyword = true
ij_php_space_before_finally_left_brace = true
ij_php_space_before_for_left_brace = true
ij_php_space_before_for_parentheses = true
ij_php_space_before_for_semicolon = false
ij_php_space_before_if_left_brace = true
ij_php_space_before_if_parentheses = true
ij_php_space_before_method_call_parentheses = false
ij_php_space_before_method_left_brace = true
ij_php_space_before_method_parentheses = false
ij_php_space_before_quest = true
ij_php_space_before_short_closure_left_parenthesis = false
ij_php_space_before_switch_left_brace = true
ij_php_space_before_switch_parentheses = true
ij_php_space_before_try_left_brace = true
ij_php_space_before_unary_not = false
ij_php_space_before_while_keyword = true
ij_php_space_before_while_left_brace = true
ij_php_space_before_while_parentheses = true
ij_php_space_between_ternary_quest_and_colon = false
ij_php_spaces_around_additive_operators = true
ij_php_spaces_around_arrow = false
ij_php_spaces_around_assignment_in_declare = false
ij_php_spaces_around_assignment_operators = true
ij_php_spaces_around_bitwise_operators = true
ij_php_spaces_around_equality_operators = true
ij_php_spaces_around_logical_operators = true
ij_php_spaces_around_multiplicative_operators = true
ij_php_spaces_around_null_coalesce_operator = true
ij_php_spaces_around_relational_operators = true
ij_php_spaces_around_shift_operators = true
ij_php_spaces_around_unary_operator = false
ij_php_spaces_around_var_within_brackets = false
ij_php_spaces_within_array_initializer_braces = false
ij_php_spaces_within_brackets = false
ij_php_spaces_within_catch_parentheses = false
ij_php_spaces_within_for_parentheses = false
ij_php_spaces_within_if_parentheses = false
ij_php_spaces_within_method_call_parentheses = false
ij_php_spaces_within_method_parentheses = false
ij_php_spaces_within_parentheses = false
ij_php_spaces_within_short_echo_tags = true
ij_php_spaces_within_switch_parentheses = false
ij_php_spaces_within_while_parentheses = false
ij_php_special_else_if_treatment = false
ij_php_subpackage_weight = 28
ij_php_ternary_operation_signs_on_next_line = false
ij_php_ternary_operation_wrap = off
ij_php_throws_weight = 2
ij_php_todo_weight = 28
ij_php_unknown_tag_weight = 28
ij_php_upper_case_boolean_const = false
ij_php_upper_case_null_const = false
ij_php_uses_weight = 28
ij_php_var_weight = 28
ij_php_variable_naming_style = mixed
ij_php_version_weight = 28
ij_php_while_brace_force = always
ij_php_while_on_new_line = false
[{phpunit.xml.dist,*.jhm,*.rng,*.wsdl,*.fxml,*.xslt,*.jrxml,*.ant,*.xul,*.xsl,*.xsd,*.tld,*.jnlp,*.xml}]
ij_xml_block_comment_at_first_column = true
ij_xml_keep_indents_on_empty_lines = false
ij_xml_line_comment_at_first_column = true

6
.gitattributes

@ -0,0 +1,6 @@
*.md text eol=lf
*.php text eol=lf
*.ini text eol=lf
*.json text eol=lf
*.yml text eol=lf
*.tcl text eol=lf

2
.gitignore

@ -1,3 +1,5 @@
/.idea/
/vendor/
/composer.lock
/clover.xml
/.phpunit.result.cache

4
.travis.yml

@ -20,8 +20,8 @@ before_script:
- sudo apt-get install -y expect
- docker pull evilfreelancer/docker-routeros:6.42
- docker pull evilfreelancer/docker-routeros:latest
- docker run -d -p 12223:23 -p 18728:8728 -p 18729:8729 -ti evilfreelancer/docker-routeros:6.42
- docker run -d -p 22223:23 -p 8728:8728 -p 8729:8729 -ti evilfreelancer/docker-routeros:latest
- docker run --device=/dev/net/tun --cap-add NET_ADMIN -d -p 12223:23 -p 18728:8728 -p 18729:8729 -ti evilfreelancer/docker-routeros:6.42
- docker run --device=/dev/net/tun --cap-add NET_ADMIN -d -p 22223:23 -p 8728:8728 -p 8729:8729 -ti evilfreelancer/docker-routeros:latest
- docker ps -a
- sleep 60
- ./preconf.tcl 12223 > /dev/null || true

12
composer.json

@ -46,6 +46,16 @@
},
"require-dev": {
"phpunit/phpunit": "^7.0",
"orchestra/testbench": "^3.0"
"orchestra/testbench": "^3.0",
"roave/security-advisories": "dev-master",
"squizlabs/php_codesniffer": "^3.5"
},
"scripts": {
"test": "phpunit --coverage-clover clover.xml",
"check": [
"@cs-check"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf"
}
}

5
src/APIConnector.php

@ -48,8 +48,9 @@ class APIConnector
/**
* Write word to stream
*
* @param string $word
* @return int return number of written bytes
* @param string $word
*
* @return int return number of written bytes
*/
public function writeWord(string $word): int
{

126
src/APILengthCoDec.php

@ -2,6 +2,7 @@
namespace RouterOS;
use DomainException;
use RouterOS\Interfaces\StreamInterface;
use RouterOS\Helpers\BinaryStringHelper;
@ -18,43 +19,44 @@ class APILengthCoDec
/**
* Encode string to length of string
*
* @param int|float $length
* Encode the length:
* - if length <= 0x7F (binary : 01111111 => 7 bits set to 1)
* - encode length with one byte
* - set the byte to length value, as length maximal value is 7 bits set to 1, the most significant bit is always 0
* - end
* - length <= 0x3FFF (binary : 00111111 11111111 => 14 bits set to 1)
* - encode length with two bytes
* - set length value to 0x8000 (=> 10000000 00000000)
* - add length : as length maximumal value is 14 bits to 1, this does not modify the 2 most significance bits (10)
* - end
* => minimal encoded value is 10000000 10000000
* - length <= 0x1FFFFF (binary : 00011111 11111111 11111111 => 21 bits set to 1)
* - encode length with three bytes
* - set length value to 0xC00000 (binary : 11000000 00000000 00000000)
* - add length : as length maximal value is 21 bits to 1, this does not modify the 3 most significance bits (110)
* - end
* => minimal encoded value is 11000000 01000000 00000000
* - length <= 0x0FFFFFFF (binary : 00001111 11111111 11111111 11111111 => 28 bits set to 1)
* - encode length with four bytes
* - set length value to 0xE0000000 (binary : 11100000 00000000 00000000 00000000)
* - add length : as length maximal value is 28 bits to 1, this does not modify the 4 most significance bits (1110)
* - end
* => minimal encoded value is 11100000 00100000 00000000 00000000
* - length <= 0x7FFFFFFFFF (binary : 00000111 11111111 11111111 11111111 11111111 => 35 bits set to 1)
* - encode length with five bytes
* - set length value to 0xF000000000 (binary : 11110000 00000000 00000000 00000000 00000000)
* - add length : as length maximal value is 35 bits to 1, this does not modify the 5 most significance bits (11110)
* - end
* - length > 0x7FFFFFFFFF : not supported
*
* @param int|float $length
*
* @return string
*/
public static function encodeLength($length): string
{
// Encode the length :
// - if length <= 0x7F (binary : 01111111 => 7 bits set to 1)
// - encode length with one byte
// - set the byte to length value, as length maximal value is 7 bits set to 1, the most significant bit is always 0
// - end
// - length <= 0x3FFF (binary : 00111111 11111111 => 14 bits set to 1)
// - encode length with two bytes
// - set length value to 0x8000 (=> 10000000 00000000)
// - add length : as length maximumal value is 14 bits to 1, this does not modify the 2 most significance bits (10)
// - end
// => minimal encoded value is 10000000 10000000
// - length <= 0x1FFFFF (binary : 00011111 11111111 11111111 => 21 bits set to 1)
// - encode length with three bytes
// - set length value to 0xC00000 (binary : 11000000 00000000 00000000)
// - add length : as length maximal vlaue is 21 bits to 1, this does not modify the 3 most significance bits (110)
// - end
// => minimal encoded value is 11000000 01000000 00000000
// - length <= 0x0FFFFFFF (binary : 00001111 11111111 11111111 11111111 => 28 bits set to 1)
// - encode length with four bytes
// - set length value to 0xE0000000 (binary : 11100000 00000000 00000000 00000000)
// - add length : as length maximal vlaue is 28 bits to 1, this does not modify the 4 most significance bits (1110)
// - end
// => minimal encoded value is 11100000 00100000 00000000 00000000
// - length <= 0x7FFFFFFFFF (binary : 00000111 11111111 11111111 11111111 11111111 => 35 bits set to 1)
// - encode length with five bytes
// - set length value to 0xF000000000 (binary : 11110000 00000000 00000000 00000000 00000000)
// - add length : as length maximal vlaue is 35 bits to 1, this does not modify the 5 most significance bits (11110)
// - end
// - length > 0x7FFFFFFFFF : not supported
if ($length < 0) {
throw new \DomainException("Length of word could not to be negative ($length)");
throw new DomainException("Length of word could not to be negative ($length)");
}
if ($length <= 0x7F) {
@ -78,39 +80,35 @@ class APILengthCoDec
return BinaryStringHelper::IntegerToNBOBinaryString(0xF000000000 + $length);
}
// Decode length of data when reading :
// The 5 firsts bits of the first byte specify how the length is encoded.
// The position of the first 0 value bit, starting from the most significant postion.
// - 0xxxxxxx => The 7 remainings bits of the first byte is the length :
// => min value of length is 0x00
// => max value of length is 0x7F (127 bytes)
// - 10xxxxxx => The 6 remainings bits of the first byte plus the next byte represent the lenght
// NOTE : the next byte MUST be at least 0x80 !!
// => min value of length is 0x80
// => max value of length is 0x3FFF (16,383 bytes, near 16 KB)
// - 110xxxxx => The 5 remainings bits of th first byte and the two next bytes represent the length
// => max value of length is 0x1FFFFF (2,097,151 bytes, near 2 MB)
// - 1110xxxx => The 4 remainings bits of the first byte and the three next bytes represent the length
// => max value of length is 0xFFFFFFF (268,435,455 bytes, near 270 MB)
// - 11110xxx => The 3 remainings bits of the first byte and the four next bytes represent the length
// => max value of length is 0x7FFFFFFF (2,147,483,647 byes, 2GB)
// - 11111xxx => This byte is not a length-encoded word but a control byte.
// => Extracted from Mikrotik API doc :
// it is a reserved control byte.
// After receiving unknown control byte API client cannot proceed, because it cannot know how to interpret following bytes
// Currently control bytes are not used
/**
* Decode length of data when reading :
* The 5 firsts bits of the first byte specify how the length is encoded.
* The position of the first 0 value bit, starting from the most significant postion.
* - 0xxxxxxx => The 7 remainings bits of the first byte is the length :
* => min value of length is 0x00
* => max value of length is 0x7F (127 bytes)
* - 10xxxxxx => The 6 remainings bits of the first byte plus the next byte represent the lenght
* NOTE : the next byte MUST be at least 0x80 !!
* => min value of length is 0x80
* => max value of length is 0x3FFF (16,383 bytes, near 16 KB)
* - 110xxxxx => The 5 remainings bits of th first byte and the two next bytes represent the length
* => max value of length is 0x1FFFFF (2,097,151 bytes, near 2 MB)
* - 1110xxxx => The 4 remainings bits of the first byte and the three next bytes represent the length
* => max value of length is 0xFFFFFFF (268,435,455 bytes, near 270 MB)
* - 11110xxx => The 3 remainings bits of the first byte and the four next bytes represent the length
* => max value of length is 0x7FFFFFFF (2,147,483,647 byes, 2GB)
* - 11111xxx => This byte is not a length-encoded word but a control byte.
* => Extracted from Mikrotik API doc:
* it is a reserved control byte.
* After receiving unknown control byte API client cannot proceed, because it cannot know how to interpret following bytes
* Currently control bytes are not used
*
* @param \RouterOS\Interfaces\StreamInterface $stream
*
* @return int
*/
public static function decodeLength(StreamInterface $stream): int
{
// if (false === is_resource($stream)) {
// throw new \InvalidArgumentException(
// sprintf(
// 'Argument must be a stream resource type. %s given.',
// gettype($stream)
// )
// );
// }
// Read first byte
$firstByte = ord($stream->read(1));
@ -190,7 +188,7 @@ class APILengthCoDec
}
// Now the only solution is 5 most significance bits are set to 1 (11111xxx)
// This is a control word, not implemented by Mikrotik for the moment
// This is a control word, not implemented by Mikrotik for the moment
throw new \UnexpectedValueException('Control Word found');
}
}

148
src/Client.php

@ -7,6 +7,19 @@ use RouterOS\Exceptions\ConfigException;
use RouterOS\Exceptions\QueryException;
use RouterOS\Helpers\ArrayHelper;
use RouterOS\Interfaces\QueryInterface;
use function array_keys;
use function array_shift;
use function chr;
use function count;
use function is_array;
use function is_string;
use function md5;
use function pack;
use function preg_match_all;
use function sleep;
use function trim;
/**
* Class Client for RouterOS management
*
@ -35,7 +48,7 @@ class Client implements Interfaces\ClientInterface
/**
* Client constructor.
*
* @param array|\RouterOS\Config $config
* @param array|\RouterOS\Interfaces\ConfigInterface $config
*
* @throws \RouterOS\Exceptions\ClientException
* @throws \RouterOS\Exceptions\ConfigException
@ -44,7 +57,7 @@ class Client implements Interfaces\ClientInterface
public function __construct($config)
{
// If array then need create object
if (\is_array($config)) {
if (is_array($config)) {
$config = new Config($config);
}
@ -83,13 +96,12 @@ class Client implements Interfaces\ClientInterface
* @return \RouterOS\Client
* @throws \RouterOS\Exceptions\QueryException
* @deprecated
* @codeCoverageIgnore
*/
public function write($query): Client
{
if (\is_string($query)) {
if (is_string($query)) {
$query = new Query($query);
} elseif (\is_array($query)) {
} elseif (is_array($query)) {
$endpoint = array_shift($query);
$query = new Query($endpoint, $query);
}
@ -105,10 +117,10 @@ class Client implements Interfaces\ClientInterface
/**
* Send write query to RouterOS (modern version of write)
*
* @param string|Query $endpoint Path of API query or Query object
* @param array|null $where List of where filters
* @param string|null $operations Some operations which need make on response
* @param string|null $tag Mark query with tag
* @param string|\RouterOS\Query $endpoint Path of API query or Query object
* @param array|null $where List of where filters
* @param string|null $operations Some operations which need make on response
* @param string|null $tag Mark query with tag
*
* @return \RouterOS\Client
* @throws \RouterOS\Exceptions\QueryException
@ -128,48 +140,10 @@ class Client implements Interfaces\ClientInterface
// If array is multidimensional, then parse each line
if (is_array($where[0])) {
foreach ($where as $item) {
// Null by default
$key = null;
$operator = null;
$value = null;
switch (\count($item)) {
case 1:
list($key) = $item;
break;
case 2:
list($key, $operator) = $item;
break;
case 3:
list($key, $operator, $value) = $item;
break;
default:
throw new ClientException('From 1 to 3 parameters of "where" condition is allowed');
}
$query->where($key, $operator, $value);
$query = $this->preQuery($item, $query);
}
} else {
// Null by default
$key = null;
$operator = null;
$value = null;
switch (\count($where)) {
case 1:
list($key) = $where;
break;
case 2:
list($key, $operator) = $where;
break;
case 3:
list($key, $operator, $value) = $where;
break;
default:
throw new ClientException('From 1 to 3 parameters of "where" condition is allowed');
}
$query->where($key, $operator, $value);
$query = $this->preQuery($where, $query);
}
}
@ -189,6 +163,40 @@ class Client implements Interfaces\ClientInterface
}
/**
* Query helper
*
* @param array $item
* @param \RouterOS\Interfaces\QueryInterface $query
*
* @return \RouterOS\Query
* @throws \RouterOS\Exceptions\ClientException
* @throws \RouterOS\Exceptions\QueryException
*/
private function preQuery(array $item, Query $query): Query
{
// Null by default
$key = null;
$operator = null;
$value = null;
switch (count($item)) {
case 1:
[$key] = $item;
break;
case 2:
[$key, $operator] = $item;
break;
case 3:
[$key, $operator, $value] = $item;
break;
default:
throw new ClientException('From 1 to 3 parameters of "where" condition is allowed');
}
return $query->where($key, $operator, $value);
}
/**
* Send write query object to RouterOS
*
* @param \RouterOS\Query $query
@ -342,7 +350,7 @@ class Client implements Interfaces\ClientInterface
{
$result = [];
$i = -1;
$lines = \count($response);
$lines = count($response);
foreach ($response as $key => $value) {
switch ($value) {
case '!re':
@ -357,18 +365,12 @@ class Client implements Interfaces\ClientInterface
for ($j = $key + 1; $j <= $lines; $j++) {
// If we have lines after current one
if (isset($response[$j])) {
$this->pregResponse($response[$j], $matches);
if (isset($matches[1][0], $matches[2][0])) {
$result['after'][$matches[1][0]] = $matches[2][0];
}
$this->preParseResponse($response[$j], $result, $matches);
}
}
break 2;
default:
$this->pregResponse($value, $matches);
if (isset($matches[1][0], $matches[2][0])) {
$result[$i][$matches[1][0]] = $matches[2][0];
}
$this->preParseResponse($value, $result, $matches, $i);
break;
}
}
@ -376,14 +378,30 @@ class Client implements Interfaces\ClientInterface
}
/**
* Response helper
*
* @param string $value Value which should be parsed
* @param array $result Array with parsed response
* @param null|array $matches Matched words
* @param string|int $iterator Type of iterations or number of item
*/
private function preParseResponse(string $value, array &$result, ?array &$matches, $iterator = 'after'): void
{
$this->pregResponse($value, $matches);
if (isset($matches[1][0], $matches[2][0])) {
$result[$iterator][$matches[1][0]] = $matches[2][0];
}
}
/**
* Parse result from RouterOS by regular expression
*
* @param string $value
* @param array $matches
* @param string $value
* @param null|array $matches
*/
private function pregResponse(string $value, &$matches)
private function pregResponse(string $value, ?array &$matches): void
{
preg_match_all('/^[=|\.](.*)=(.*)/', $value, $matches);
preg_match_all('/^[=|.](.*)=(.*)/', $value, $matches);
}
/**
@ -406,7 +424,7 @@ class Client implements Interfaces\ClientInterface
// Now need use this hash for authorization
$query = new Query('/login', [
'=name=' . $this->config('user'),
'=response=00' . md5(\chr(0) . $this->config('pass') . pack('H*', $response['after']['ret']))
'=response=00' . md5(chr(0) . $this->config('pass') . pack('H*', $response['after']['ret']))
]);
} else {
// Just login with our credentials
@ -448,11 +466,11 @@ class Client implements Interfaces\ClientInterface
* @param array $response
*
* @return bool
* @throws ConfigException
* @throws \RouterOS\Exceptions\ConfigException
*/
private function isLegacy(array &$response): bool
{
return \count($response) > 1 && $response[0] === '!done' && !$this->config('legacy');
return count($response) > 1 && $response[0] === '!done' && !$this->config('legacy');
}
/**

40
src/Interfaces/QueryInterface.php

@ -2,8 +2,6 @@
namespace RouterOS\Interfaces;
use RouterOS\Query;
/**
* Interface QueryInterface
*
@ -19,38 +17,54 @@ interface QueryInterface
* @param bool|string|int $value Value which need to check (by default true)
* @param bool|string|int $operator It may be one from list [-,=,>,<]
*
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @throws \RouterOS\Exceptions\ClientException
* @since 1.0.0
*/
public function where(string $key, $operator = '=', $value = null);
public function where(string $key, $operator = '=', $value = null): QueryInterface;
/**
* Setter for write/update queries
*
* @param string $key Key which need to find
* @param bool|string|int $value Value which need to check (by default true)
*
* @return \RouterOS\Interfaces\QueryInterface
* @throws \RouterOS\Exceptions\QueryException
* @since 1.1
*/
public function equal(string $key, $value = null): QueryInterface;
/**
* Append additional operations
*
* @param string $operations
*
* @return \RouterOS\Interfaces\QueryInterface
*
* @since 1.0.0
*/
public function operations(string $operations);
public function operations(string $operations): QueryInterface;
/**
* Append tag to query (it should be at end)
*
* @param string $name
*
* @return \RouterOS\Interfaces\QueryInterface
*
* @since 1.0.0
*/
public function tag(string $name);
public function tag(string $name): QueryInterface;
/**
* Append to array yet another attribute of query
*
* @param string $word
*
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
*/
public function add(string $word): Query;
public function add(string $word): QueryInterface;
/**
* Get attributes array of current query
@ -64,27 +78,27 @@ interface QueryInterface
*
* @param array $attributes
*
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @since 0.7
*/
public function setAttributes(array $attributes): Query;
public function setAttributes(array $attributes): QueryInterface;
/**
* Get endpoint of current query
*
* @return string|null
*/
public function getEndpoint();
public function getEndpoint(): ?string;
/**
* Set endpoint of query
*
* @param string $endpoint
*
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @since 0.7
*/
public function setEndpoint(string $endpoint): Query;
public function setEndpoint(string $endpoint): QueryInterface;
/**
* Build body of query

34
src/Query.php

@ -81,11 +81,11 @@ class Query implements QueryInterface
* @param bool|string|int $value Value which need to check (by default true)
* @param bool|string|int $operator It may be one from list [-,=,>,<]
*
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @throws \RouterOS\Exceptions\QueryException
* @since 1.0.0
*/
public function where(string $key, $operator = null, $value = null): self
public function where(string $key, $operator = null, $value = null): QueryInterface
{
return $this->world('?' . $key, $operator, $value);
}
@ -96,11 +96,11 @@ class Query implements QueryInterface
* @param string $key Key which need to find
* @param bool|string|int $value Value which need to check (by default true)
*
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @throws \RouterOS\Exceptions\QueryException
* @since 1.1
*/
public function equal(string $key, $value = null): self
public function equal(string $key, $value = null): QueryInterface
{
return $this->world('=' . $key, null, $value);
}
@ -112,10 +112,10 @@ class Query implements QueryInterface
* @param bool|string|int $value Value which need to check (by default true)
* @param bool|string|int $operator It may be one from list [-,=,>,<]
*
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @throws \RouterOS\Exceptions\QueryException
*/
private function world(string $key, $operator = null, $value = null): self
private function world(string $key, $operator = null, $value = null): QueryInterface
{
if (null !== $operator && null === $value) {
@ -148,10 +148,10 @@ class Query implements QueryInterface
*
* @param string $operations
*
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @since 1.0.0
*/
public function operations(string $operations): self
public function operations(string $operations): QueryInterface
{
$this->_operations = '?#' . $operations;
return $this;
@ -162,10 +162,10 @@ class Query implements QueryInterface
*
* @param string $name
*
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @since 1.0.0
*/
public function tag(string $name): self
public function tag(string $name): QueryInterface
{
$this->_tag = '.tag=' . $name;
return $this;
@ -176,9 +176,9 @@ class Query implements QueryInterface
*
* @param string $word
*
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
*/
public function add(string $word): Query
public function add(string $word): QueryInterface
{
$this->_attributes[] = $word;
return $this;
@ -199,10 +199,10 @@ class Query implements QueryInterface
*
* @param array $attributes
*
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @since 0.7
*/
public function setAttributes(array $attributes): Query
public function setAttributes(array $attributes): QueryInterface
{
$this->_attributes = $attributes;
return $this;
@ -213,7 +213,7 @@ class Query implements QueryInterface
*
* @return string|null
*/
public function getEndpoint()
public function getEndpoint(): ?string
{
return $this->_endpoint;
}
@ -223,10 +223,10 @@ class Query implements QueryInterface
*
* @param string|null $endpoint
*
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @since 0.7
*/
public function setEndpoint(string $endpoint = null): Query
public function setEndpoint(string $endpoint = null): QueryInterface
{
$this->_endpoint = $endpoint;
return $this;

Loading…
Cancel
Save