├── .gitignore
├── composer.json
├── composer.lock
├── config
└── mikrotik.php
├── phpunit.xml
├── readme.md
├── src
├── Commands
│ ├── Command.php
│ ├── Interfaces.php
│ └── Ip.php
├── Contracts
│ ├── ClientContract.php
│ ├── CommandContract.php
│ └── MikrotikContract.php
├── Core
│ ├── Client.php
│ ├── Collection.php
│ ├── QueryBuilder.php
│ └── Request.php
├── Entity
│ ├── Address.php
│ ├── Bridge.php
│ ├── Entity.php
│ ├── Ethernet.php
│ ├── GenericEntity.php
│ └── InterfaceEntity.php
├── Exceptions
│ ├── CommandException.php
│ ├── ConnectionException.php
│ ├── InvalidCommandException.php
│ └── WrongArgumentTypeException.php
├── Facades
│ └── MikrotikFacade.php
├── Mikrotik.php
├── MikrotikServiceProvider.php
└── Support
│ ├── EntityUtils.php
│ └── InterfaceEnums.php
└── tests
├── AuthTest.php
├── InterfacesCommandsTest.php
├── IpCommandsTest.php
├── StaticCommandTest.php
└── Traits
└── CreateApplication.php
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /public/storage
3 | /public/hot
4 | /storage/*.key
5 | /bootstrap
6 | /vendor
7 | /.idea
8 | Homestead.json
9 | Homestead.yaml
10 | .env
11 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jjsquady/mikrotikapi",
3 | "description": "An Mikrotik Api Wrapper",
4 | "minimum-stability": "dev",
5 | "prefer-stable": true,
6 | "license": "MIT",
7 | "authors": [
8 | {
9 | "name": "Jorge 'jjsquady' Junior",
10 | "email": "jjsquady@gmail.com"
11 | }
12 | ],
13 | "autoload": {
14 | "psr-4": {
15 | "jjsquady\\MikrotikApi\\": "src/"
16 | }
17 | },
18 | "autoload-dev": {
19 | "psr-4": {
20 | "jjsquady\\MikrotikApi\\Tests\\": "tests/"
21 | }
22 | },
23 |
24 | "require": {
25 | "php": "^7.4",
26 | "pear2/net_routeros": "1.0.0b6",
27 | "pear2/net_transmitter": "1.0.0b2"
28 | },
29 | "require-dev": {
30 | "laravel/framework": "^8.11",
31 | "orchestra/testbench": "^6.2",
32 | "phpunit/phpunit": "^9.4"
33 | },
34 | "extra": {
35 | "branch-alias": {
36 | "dev-master": "1.0-dev"
37 | },
38 | "laravel": {
39 | "providers": [
40 | "jjsquady\\MikrotikApi\\MikrotikServiceProvider"
41 | ],
42 | "aliases": {
43 | "Mikrotik": "jjsquady\\MikrotikApi\\Facades\\MikrotikFacade"
44 | }
45 | }
46 | },
47 | "config": {
48 | "sort-packages": true
49 | },
50 | "scripts": {
51 | "test": "vendor/bin/phpunit"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/config/mikrotik.php:
--------------------------------------------------------------------------------
1 | [
5 | 'host' => env('MK_API_HOST', null),
6 | 'user' => env('MK_API_USER', 'admin'),
7 | 'password' => env('MK_API_PASSWORD', ''),
8 | 'port' => env('MK_API_PORT', 8728)
9 | ],
10 | 'entities' => [
11 | 'interface' => \jjsquady\MikrotikApi\Entity\InterfaceEntity::class
12 | ]
13 | ];
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 | ./tests
15 |
16 |
17 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Mikrotik Api for Laravel 8.x
2 | WIP - Work In Progress
3 |
4 | Instalation
5 | ----
6 |
7 | Via composer:
8 | ```
9 | composer require jjsquady/mikrotikapi
10 | ```
11 |
12 | Or manually insert this block into your composer.json in require section:
13 | ```
14 | "require": {
15 | "jjsquady/mikrotikapi": "dev-master", // <- this line
16 | }
17 | ```
18 |
19 | Configuration on Laravel (< 5.4):
20 | ----
21 |
22 | Insert into `config/app.php` in `providers` array:
23 |
24 | ```
25 | jjsquady\MikrotikApi\MikrotikServiceProvider::class
26 | ```
27 |
28 | #### Use the Facade:
29 |
30 | Insert into `config/app.php` in `facades` array:
31 |
32 | ```
33 | 'Mikrotik' => jjsquady\MikrotikApi\Facades\MikrotikFacade::class
34 | ```
35 |
36 | **Note:** for Laravel 5.4+ this package comes with Package Discovery enabled.
37 |
38 |
39 | #### Publish the configuration file:
40 |
41 | ```
42 | php artisan vendor:publish --provider=jjsquady\MikrotikApi\MikrotikServiceProvider
43 | ```
44 |
45 | Basic Usage:
46 | ----
47 |
48 | Set up the host and credentials into .env file:
49 |
50 | ```$bash
51 | MK_API_HOST=
52 | MK_API_USER=
53 | MK_API_PASSWORD=
54 | MK_API_PORT=
55 | ```
56 |
57 | ```$php
58 |
59 | // create a connection with Mikrotik Router
60 |
61 | $conn = Mikrotik::connect()->getConnection();
62 |
63 | if($conn->isConnected()) {
64 | // you have access to Commands
65 | // and can call from here...
66 | }
67 | ```
68 |
69 | Getting interfaces:
70 | ---
71 | ```$php
72 | $conn = Mikrotik::connect()->getConnection();
73 |
74 | if($conn->isConnected()) {
75 | // Get all interfaces
76 | $interfaces = Interfaces::bind($conn)->get();
77 |
78 | // get() returns a Collection and you can use all methods available
79 |
80 | // you can send it to view
81 | return view("", [
82 | 'interfaces' => $interfaces
83 | ]);
84 | }
85 | ```
86 |
87 | This project its a work in progress... and its in early developing phase.
88 | I really get thankful with ur contribution.
89 |
90 | ##### Created by jjsquady (Jorge Junior)
91 | ##### (cc) 2017-2019
92 | ##### License: MIT
93 |
--------------------------------------------------------------------------------
/src/Commands/Command.php:
--------------------------------------------------------------------------------
1 | client = $client;
86 |
87 | $this->entityClass = $this->entityClass ?? GenericEntity::class;
88 |
89 | $this->entity = (new $this->entityClass);
90 |
91 | $this->rootPath = $this->entity->getPath();
92 |
93 | if(!$this->rootPath) {
94 | throw new CommandException('Command not found.');
95 | }
96 |
97 | $this->request = new Request($this->rootPath);
98 | }
99 |
100 | /**
101 | * @param $command
102 | * @param null $args
103 | * @return $this
104 | */
105 | private function executeCommand($command, $args = null)
106 | {
107 | $this->request = new Request($command);
108 |
109 | $this->processCommandArgs($args);
110 |
111 | $this->_response = $this->processCommand();
112 |
113 | return $this;
114 |
115 | }
116 |
117 | /**
118 | *
119 | * @return \jjsquady\MikrotikApi\Core\Collection
120 | */
121 | public function get()
122 | {
123 | $this->executeCommand($this->rootPath . '/print');
124 | return $this->convertArrayToEntities($this->_response);
125 | }
126 |
127 | public function remove($id)
128 | {
129 | $this->executeCommand($this->rootPath . '/remove', ['.id' => $id]);
130 | }
131 |
132 | public function find($attribute, $value = null)
133 | {
134 | // TODO: Implement find() method.
135 | }
136 |
137 | /**
138 | * @return mixed
139 | */
140 | public function getBaseCommand()
141 | {
142 | return $this->rootPath;
143 | }
144 |
145 | /**
146 | * @param array $args
147 | * @return string
148 | */
149 | protected function buildCommandPath(array $args)
150 | {
151 | if (!is_array($args)) {
152 | //TODO: throw exception
153 | }
154 |
155 | if (empty(array_last($args))) {
156 | return implode('', $args);
157 | }
158 |
159 | return implode("/", $args);
160 | }
161 |
162 | /**
163 | * @param $name
164 | * @param $arguments
165 | * @return QueryBuilder
166 | * @throws InvalidCommandException
167 | */
168 | public function __call($name, $arguments)
169 | {
170 | if (array_key_exists($name, $this->commands)) {
171 | $command = array_key_exists($name, $this->commandsAlias) ? $this->commandsAlias[$name] : $name;
172 | $fullCommand = $this->buildCommandPath([$this->base_command, $command]);
173 | return $this->buildNewQuery($this->commands[$name], $fullCommand);
174 | }
175 |
176 | throw new InvalidCommandException($name);
177 | }
178 |
179 | /**
180 | * @param $entityClass
181 | * @param $command
182 | * @return QueryBuilder
183 | */
184 | protected function buildNewQuery($entityClass, $command)
185 | {
186 | $this->query = new QueryBuilder($entityClass, $command, $this->client);
187 | return $this->query;
188 | }
189 |
190 | /**
191 | * @return \PEAR2\Net\RouterOS\ResponseCollection
192 | */
193 | private function processCommand()
194 | {
195 | return $this->client->sendSync($this->request);
196 | }
197 |
198 | /**
199 | * @param $args
200 | */
201 | private function processCommandArgs($args)
202 | {
203 | if (!is_array($args)) {
204 | return;
205 | }
206 |
207 | array_map(function ($arg) {
208 | $this->request->setArgument($arg);
209 | }, $args);
210 | }
211 |
212 | public static function bind(Client $client)
213 | {
214 | try {
215 |
216 | return new static($client);
217 |
218 | } catch (CommandException $e) {
219 |
220 | throw new CommandException($e);
221 |
222 | }
223 | }
224 |
225 | }
--------------------------------------------------------------------------------
/src/Commands/Interfaces.php:
--------------------------------------------------------------------------------
1 | entityClass = config('mikrotik.entities.interface');
28 |
29 | parent::__construct($client);
30 | }
31 |
32 | /**
33 | * @param $id
34 | * @throws CommandException
35 | */
36 | public function remove($id)
37 | {
38 | throw new CommandException('Interfaces cannot be removed.');
39 | }
40 | }
--------------------------------------------------------------------------------
/src/Commands/Ip.php:
--------------------------------------------------------------------------------
1 | Address::class,
29 | 'arp' => Arp::class,
30 | 'accounting' => Accounting::class
31 | ];
32 |
33 | public function address()
34 | {
35 | return $this->__call("address", null);
36 | }
37 |
38 | public function arp()
39 | {
40 | return $this->__call("arp", null);
41 | }
42 |
43 | }
--------------------------------------------------------------------------------
/src/Contracts/ClientContract.php:
--------------------------------------------------------------------------------
1 | connected = true;
32 |
33 | }catch (\Exception $exception) {
34 |
35 | $this->connected = false;
36 |
37 | throw new ConnectionException($exception->getMessage());
38 | }
39 | }
40 |
41 | /**
42 | * @return mixed
43 | */
44 | public function isConnected()
45 | {
46 | return $this->connected;
47 | }
48 | }
--------------------------------------------------------------------------------
/src/Core/Collection.php:
--------------------------------------------------------------------------------
1 | entityClass = $entityClassName;
28 | $this->client = $client;
29 | $this->directory = $directory;
30 | }
31 |
32 | public static function find($params)
33 | {
34 |
35 | }
36 |
37 | public static function where($property, $value = null, $operator = self::OP_EQ)
38 | {
39 |
40 | }
41 |
42 | public function all()
43 | {
44 | return $this->execute();
45 | }
46 |
47 | public function first()
48 | {
49 | return $this->all()->first();
50 | }
51 |
52 | public function get($args = array(), $query = null)
53 | {
54 | return $this->execute($args, $query);
55 | }
56 |
57 | private function execute($args = array(), $query = null)
58 | {
59 | $util = new Util($this->client);
60 |
61 | $util->setMenu($this->directory);
62 |
63 | $items = $util->getAll($args, $query);
64 |
65 | return $this->convertArrayToEntities($items, $this->entityClass);
66 | }
67 |
68 |
69 | }
--------------------------------------------------------------------------------
/src/Core/Request.php:
--------------------------------------------------------------------------------
1 | query = $query;
31 | }
32 | }
33 |
34 | public function getPath()
35 | {
36 | return $this->directory;
37 | }
38 |
39 | public function toArray()
40 | {
41 | return get_object_vars($this);
42 | }
43 |
44 | public function getDirectory()
45 | {
46 | return $this->directory;
47 | }
48 |
49 | /**
50 | * @return string
51 | */
52 | public function __toString()
53 | {
54 | return json_encode($this);
55 | }
56 |
57 | /**
58 | * @param $property
59 | * @return null
60 | */
61 | public function __get($property)
62 | {
63 | $propertyClean = $this->convertToDashes($property);
64 |
65 | if (isset($this->fillable)) {
66 | return $this->getFillableProperty($propertyClean);
67 | }
68 |
69 | return property_exists($this, $propertyClean) ? $this->{$propertyClean} : null;
70 | }
71 |
72 | public function setAttributes(array $attributes)
73 | {
74 | foreach ($attributes as $attribute => $value) {
75 | in_array($attribute, $this->fillable) ? $this->{$attribute} = $value : null;
76 | }
77 |
78 | return $this;
79 | }
80 |
81 | /**
82 | * If $fillable array its set, then looks into this array for properties
83 | * @param $property
84 | * @return null
85 | */
86 | private function getFillableProperty($property)
87 | {
88 | return in_array($property, $this->fillable) ?
89 | property_exists($this, $property) ?
90 | $this->{$property} :
91 | null :
92 | null;
93 | }
94 |
95 | /**
96 | * Convertes a camelCase property to hyphened-case (myProp -> my-prop)
97 | * @param $property
98 | * @return string
99 | */
100 | private function convertToDashes($property)
101 | {
102 | preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $property, $matches);
103 | $ret = $matches[0];
104 | foreach ($ret as &$match) {
105 | $match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
106 | }
107 | return implode('-', $ret);
108 | }
109 | }
--------------------------------------------------------------------------------
/src/Entity/Ethernet.php:
--------------------------------------------------------------------------------
1 | credentials = [
41 | 'host' => $host,
42 | 'username' => $username,
43 | 'password' => $password,
44 | 'port' => $port
45 | ];
46 | }
47 |
48 | /**
49 | * Connects to a MK host
50 | *
51 | * @return Mikrotik
52 | * @throws ConnectionException
53 | */
54 | public function connect()
55 | {
56 | $this->connection = new Client(...array_values($this->credentials));
57 |
58 | return $this;
59 | }
60 |
61 | /**
62 | * @return Client
63 | */
64 | public function getConnection()
65 | {
66 | return $this->connection;
67 | }
68 |
69 | /**
70 | * Get the credentials
71 | * @return array
72 | */
73 | public function getCredentials()
74 | {
75 | return $this->credentials;
76 | }
77 |
78 | }
--------------------------------------------------------------------------------
/src/MikrotikServiceProvider.php:
--------------------------------------------------------------------------------
1 | publishes([
21 | __DIR__ . '/../config/mikrotik.php' => config_path('mikrotik.php')
22 | ]);
23 | }
24 |
25 | /**
26 | * Register the application services.
27 | *
28 | * @return void
29 | */
30 | public function register()
31 | {
32 | $this->mergeConfigFrom(__DIR__ . '/../config/mikrotik.php', 'mikrotik');
33 |
34 | $this->app->singleton('mikontrollib', function($app) {
35 | return new Mikrotik(
36 | config('mikrotik.auth.host'),
37 | config('mikrotik.auth.user'),
38 | config('mikrotik.auth.password'),
39 | config('mikrotik.auth.port'),
40 | );
41 | });
42 | }
43 |
44 | public function provides()
45 | {
46 | return [
47 | 'mikontrollib'
48 | ];
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Support/EntityUtils.php:
--------------------------------------------------------------------------------
1 | getType() == Response::TYPE_DATA) {
37 | $collection->add(
38 | $this->entity->setAttributes($this->getEntityProperties($item))
39 | );
40 | }
41 | }
42 |
43 | return $collection;
44 | }
45 |
46 | /**
47 | * @param $array
48 | * @return array
49 | */
50 | private function getEntityProperties($array)
51 | {
52 | $attributes = [];
53 |
54 | foreach ($array as $property => $value) {
55 | $attributes[$property] = $value;
56 | }
57 |
58 | return $attributes;
59 | }
60 | }
--------------------------------------------------------------------------------
/src/Support/InterfaceEnums.php:
--------------------------------------------------------------------------------
1 | mikrotik = Mikrotik::connect();
31 |
32 | $this->client = $this->mikrotik->getClient();
33 | }
34 |
35 | public function test_if_connection_returns_client_instance()
36 | {
37 | $this->assertInstanceOf(Client::class, $this->client);
38 | }
39 |
40 | public function test_if_throws_connection_exception()
41 | {
42 | $this->expectException(ConnectionException::class);
43 |
44 | (new \jjsquady\MikrotikApi\Mikrotik(config('mikrotik.auth.host'), 'wronguser'))->connect();
45 |
46 | }
47 |
48 | public function test_getting_credentials()
49 | {
50 | $this->assertIsArray($this->mikrotik->getCredentials());
51 |
52 | $this->assertTrue(in_array('admin', $this->mikrotik->getCredentials()));
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/tests/InterfacesCommandsTest.php:
--------------------------------------------------------------------------------
1 | client = Mikrotik::connect()->getClient();
28 | }
29 |
30 | public function test_execute_command_sync_response_array()
31 | {
32 | $response = Interfaces::bind($this->client)
33 | ->get()
34 | ->toArray();
35 | $this->assertEquals(true, is_array($response));
36 | }
37 |
38 | public function test_returns_an_interface_entity_object()
39 | {
40 | $response = Interfaces::bind($this->client)->get()->first();
41 | $this->assertInstanceOf(InterfaceEntity::class, $response);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/IpCommandsTest.php:
--------------------------------------------------------------------------------
1 | jjsquady\MikrotikApi\Facades\MikrotikFacade::class
27 | ];
28 | }
29 |
30 | public function getConn()
31 | {
32 | $client = Mikrotik::connect(['192.168.0.20', 'admin', '']);
33 | return $client;
34 | }
35 |
36 | public function test_if_command_works()
37 | {
38 | $this->assertInstanceOf(Ip::class, new Ip($this->getConn()));
39 | }
40 |
41 | public function test_if_command_address_exists()
42 | {
43 | $ipcomm = new Ip($this->getConn());
44 | $this->assertInstanceOf(QueryBuilder::class, $ipcomm->address());
45 | }
46 |
47 | public function test_arp_method()
48 | {
49 | $ipcomm = new Ip($this->getConn());
50 | $this->assertInstanceOf(QueryBuilder::class, $ipcomm->arp());
51 | }
52 |
53 | public function test_accounting_method()
54 | {
55 | $ipcomm = new Ip($this->getConn());
56 | $this->assertInstanceOf(Collection::class, $ipcomm->accounting()->all());
57 | }
58 | }
--------------------------------------------------------------------------------
/tests/StaticCommandTest.php:
--------------------------------------------------------------------------------
1 | assertInstanceOf(Client::class, Mikrotik::connect()->getClient());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/tests/Traits/CreateApplication.php:
--------------------------------------------------------------------------------
1 | load();
22 | $app['config']->set('mikrotik.auth.host', $env['MK_API_HOST']);
23 | $app['config']->set('mikrotik.auth.user', $env['MK_API_USER']);
24 | $app['config']->set('mikrotik.auth.password', $env['MK_API_PASSWORD']);
25 | $app['config']->set('mikrotik.auth.port', $env['MK_API_PORT']);
26 | }
27 |
28 | protected function getPackageProviders($app)
29 | {
30 | return [\jjsquady\MikrotikApi\MikrotikServiceProvider::class];
31 | }
32 |
33 | protected function getPackageAliases($app)
34 | {
35 | return [
36 | 'Mikrotik' => \jjsquady\MikrotikApi\Facades\MikrotikFacade::class
37 | ];
38 | }
39 | }
--------------------------------------------------------------------------------