Browse Source

Conflicts solved

pull/40/head
Paul Rock 6 years ago
parent
commit
f555e8cbd2
  1. 231
      .editorconfig
  2. 6
      .gitattributes
  3. 1
      .gitignore
  4. 4
      .travis.yml
  5. 12
      composer.json
  6. 123
      src/APILengthCoDec.php
  7. 127
      src/Client.php
  8. 40
      src/Interfaces/QueryInterface.php
  9. 32
      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

1
.gitignore

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

4
.travis.yml

@ -20,8 +20,8 @@ before_script:
- sudo apt-get install -y expect - sudo apt-get install -y expect
- docker pull evilfreelancer/docker-routeros:6.42 - docker pull evilfreelancer/docker-routeros:6.42
- docker pull evilfreelancer/docker-routeros:latest - 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 - docker ps -a
- sleep 60 - sleep 60
- ./preconf.tcl 12223 > /dev/null || true - ./preconf.tcl 12223 > /dev/null || true

12
composer.json

@ -47,6 +47,16 @@
"require-dev": { "require-dev": {
"limedeck/phpunit-detailed-printer": "^5.0", "limedeck/phpunit-detailed-printer": "^5.0",
"orchestra/testbench": "^4.0|^5.0", "orchestra/testbench": "^4.0|^5.0",
"phpunit/phpunit": "^8.0"
"phpunit/phpunit": "^8.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"
} }
} }

123
src/APILengthCoDec.php

@ -19,42 +19,45 @@ class APILengthCoDec
/** /**
* Encode string to length of string * Encode string to length of string
* *
* <<<<<<< HEAD
* =======
* 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
*
* >>>>>>> master
* @param int|float $length * @param int|float $length
* *
* @return string * @return string
*/ */
public static function encodeLength($length): 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) { 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)");
} }
@ -80,39 +83,35 @@ class APILengthCoDec
return BinaryStringHelper::IntegerToNBOBinaryString(0xF000000000 + $length); 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 remaining 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 remaining 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 remaining 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 remaining 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 remaining 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 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 // Read first byte
$firstByte = ord($stream->read(1)); $firstByte = ord($stream->read(1));
@ -192,7 +191,7 @@ class APILengthCoDec
} }
// Now the only solution is 5 most significance bits are set to 1 (11111xxx) // 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'); throw new \UnexpectedValueException('Control Word found');
} }
} }

127
src/Client.php

@ -5,11 +5,19 @@ namespace RouterOS;
use RouterOS\Exceptions\ClientException; use RouterOS\Exceptions\ClientException;
use RouterOS\Exceptions\ConfigException; use RouterOS\Exceptions\ConfigException;
use RouterOS\Exceptions\QueryException; use RouterOS\Exceptions\QueryException;
use RouterOS\Interfaces\QueryInterface;
use RouterOS\Helpers\ArrayHelper; use RouterOS\Helpers\ArrayHelper;
use function array_keys;
use function array_shift;
use function chr; use function chr;
use function count; use function count;
use function is_array; use function is_array;
use function is_string; 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 * Class Client for RouterOS management
@ -93,7 +101,6 @@ class Client implements Interfaces\ClientInterface
* @return \RouterOS\Client * @return \RouterOS\Client
* @throws \RouterOS\Exceptions\QueryException * @throws \RouterOS\Exceptions\QueryException
* @deprecated * @deprecated
* @codeCoverageIgnore
*/ */
public function write($query): Client public function write($query): Client
{ {
@ -115,10 +122,10 @@ class Client implements Interfaces\ClientInterface
/** /**
* Send write query to RouterOS (modern version of write) * 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 * @return \RouterOS\Client
* @throws \RouterOS\Exceptions\QueryException * @throws \RouterOS\Exceptions\QueryException
@ -138,48 +145,10 @@ class Client implements Interfaces\ClientInterface
// If array is multidimensional, then parse each line // If array is multidimensional, then parse each line
if (is_array($where[0])) { if (is_array($where[0])) {
foreach ($where as $item) { foreach ($where as $item) {
// 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');
}
$query->where($key, $operator, $value);
$query = $this->preQuery($item, $query);
} }
} else { } else {
// Null by default
$key = null;
$operator = null;
$value = null;
switch (count($where)) {
case 1:
[$key] = $where;
break;
case 2:
[$key, $operator] = $where;
break;
case 3:
[$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);
} }
} }
@ -199,6 +168,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, QueryInterface $query): QueryInterface
{
// 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 * Send write query object to RouterOS
* *
* @param \RouterOS\Query $query * @param \RouterOS\Query $query
@ -367,18 +370,12 @@ class Client implements Interfaces\ClientInterface
for ($j = $key + 1; $j <= $lines; $j++) { for ($j = $key + 1; $j <= $lines; $j++) {
// If we have lines after current one // If we have lines after current one
if (isset($response[$j])) { 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; break 2;
default: 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; break;
} }
} }
@ -386,12 +383,28 @@ 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 * 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): void
private function pregResponse(string $value, ?array &$matches): void
{ {
preg_match_all('/^[=|.](.*)=(.*)/', $value, $matches); preg_match_all('/^[=|.](.*)=(.*)/', $value, $matches);
} }
@ -458,7 +471,7 @@ class Client implements Interfaces\ClientInterface
* @param array $response * @param array $response
* *
* @return bool * @return bool
* @throws ConfigException
* @throws \RouterOS\Exceptions\ConfigException
*/ */
private function isLegacy(array $response): bool private function isLegacy(array $response): bool
{ {

40
src/Interfaces/QueryInterface.php

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

32
src/Query.php

@ -84,11 +84,11 @@ class Query implements QueryInterface
* @param bool|string|int $value Value which need to check (by default true) * @param bool|string|int $value Value which need to check (by default true)
* @param bool|string|int $operator It may be one from list [-,=,>,<] * @param bool|string|int $operator It may be one from list [-,=,>,<]
* *
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @throws \RouterOS\Exceptions\QueryException * @throws \RouterOS\Exceptions\QueryException
* @since 1.0.0 * @since 1.0.0
*/ */
public function where(string $key, $operator = null, $value = null): Query
public function where(string $key, $operator = null, $value = null): QueryInterface
{ {
return $this->world('?' . $key, $operator, $value); return $this->world('?' . $key, $operator, $value);
} }
@ -99,11 +99,11 @@ class Query implements QueryInterface
* @param string $key Key which need to find * @param string $key Key which need to find
* @param bool|string|int $value Value which need to check (by default true) * @param bool|string|int $value Value which need to check (by default true)
* *
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @throws \RouterOS\Exceptions\QueryException * @throws \RouterOS\Exceptions\QueryException
* @since 1.1 * @since 1.1
*/ */
public function equal(string $key, $value = null): Query
public function equal(string $key, $value = null): QueryInterface
{ {
return $this->world('=' . $key, null, $value); return $this->world('=' . $key, null, $value);
} }
@ -115,10 +115,10 @@ class Query implements QueryInterface
* @param bool|string|int $value Value which need to check (by default true) * @param bool|string|int $value Value which need to check (by default true)
* @param bool|string|int $operator It may be one from list [-,=,>,<] * @param bool|string|int $operator It may be one from list [-,=,>,<]
* *
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @throws \RouterOS\Exceptions\QueryException * @throws \RouterOS\Exceptions\QueryException
*/ */
private function world(string $key, $operator = null, $value = null): Query
private function world(string $key, $operator = null, $value = null): QueryInterface
{ {
if (null !== $operator && null === $value) { if (null !== $operator && null === $value) {
@ -151,10 +151,10 @@ class Query implements QueryInterface
* *
* @param string $operations * @param string $operations
* *
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @since 1.0.0 * @since 1.0.0
*/ */
public function operations(string $operations): Query
public function operations(string $operations): QueryInterface
{ {
$this->_operations = '?#' . $operations; $this->_operations = '?#' . $operations;
return $this; return $this;
@ -165,10 +165,10 @@ class Query implements QueryInterface
* *
* @param string $name * @param string $name
* *
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @since 1.0.0 * @since 1.0.0
*/ */
public function tag(string $name): Query
public function tag(string $name): QueryInterface
{ {
$this->_tag = '.tag=' . $name; $this->_tag = '.tag=' . $name;
return $this; return $this;
@ -179,9 +179,9 @@ class Query implements QueryInterface
* *
* @param string $word * @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; $this->_attributes[] = $word;
return $this; return $this;
@ -202,10 +202,10 @@ class Query implements QueryInterface
* *
* @param array $attributes * @param array $attributes
* *
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @since 0.7 * @since 0.7
*/ */
public function setAttributes(array $attributes): Query
public function setAttributes(array $attributes): QueryInterface
{ {
$this->_attributes = $attributes; $this->_attributes = $attributes;
return $this; return $this;
@ -226,10 +226,10 @@ class Query implements QueryInterface
* *
* @param string|null $endpoint * @param string|null $endpoint
* *
* @return \RouterOS\Query
* @return \RouterOS\Interfaces\QueryInterface
* @since 0.7 * @since 0.7
*/ */
public function setEndpoint(string $endpoint = null): Query
public function setEndpoint(string $endpoint = null): QueryInterface
{ {
$this->_endpoint = $endpoint; $this->_endpoint = $endpoint;
return $this; return $this;

Loading…
Cancel
Save