Files
Sample
admin
docs
pages
qrcode
system
autoload
PEAR2
Cache
Console
Net
RouterOS
Client.php
Communicator.php
DataFlowException.php
Exception.php
InvalidArgumentException.php
LengthException.php
Message.php
NotSupportedException.php
Query.php
Registry.php
Request.php
Response.php
ResponseCollection.php
SocketException.php
UnexpectedValueException.php
Util.php
Transmitter
Autoload.php
Admin.php
App.php
Paginator.php
Password.php
Router.php
Timezone.php
User.php
Validator.php
index.html
controllers
install
lan
uploads
vendors
boot.php
config.sample.php
cron.php
index.html
orm.php
ui
.gitignore
LICENSE
README.md
index.php
mitrobill/system/autoload/PEAR2/Net/RouterOS/Query.php

268 lines
8.4 KiB
PHP
Raw Normal View History

2017-03-11 02:51:06 +07:00
<?php
/**
* RouterOS API client implementation.
*
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
*
* PHP version 5
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 1.0.0b5
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
/**
* The namespace declaration.
*/
namespace PEAR2\Net\RouterOS;
/**
* Refers to transmitter direction constants.
*/
use PEAR2\Net\Transmitter as T;
/**
* Represents a query for RouterOS requests.
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
class Query
{
/**
* Checks if the property exists.
*/
const OP_EX = '';
/**
* Checks if the property does not exist.
*/
const OP_NEX = '-';
/**
* Checks if the property equals a certain value.
*/
const OP_EQ = '=';
/**
* Checks if the property is less than a certain value.
*/
const OP_LT = '<';
/**
* Checks if the property is greather than a certain value.
*/
const OP_GT = '>';
/**
* @var array An array of the words forming the query. Each value is an
* array with the first member being the predicate (operator and name),
* and the second member being the value for the predicate.
*/
protected $words = array();
/**
* This class is not to be instantiated normally, but by static methods
* instead. Use {@link static::where()} to create an instance of it.
*/
private function __construct()
{
}
/**
* Sanitizes the operator of a condition.
*
* @param string $operator The operator to sanitize.
*
* @return string The sanitized operator.
*/
protected static function sanitizeOperator($operator)
{
$operator = (string) $operator;
switch ($operator) {
case Query::OP_EX:
case Query::OP_NEX:
case Query::OP_EQ:
case Query::OP_LT:
case Query::OP_GT:
return $operator;
default:
throw new UnexpectedValueException(
'Unknown operator specified',
UnexpectedValueException::CODE_ACTION_UNKNOWN,
null,
$operator
);
}
}
/**
* Creates a new query with an initial condition.
*
* @param string $name The name of the property to test.
* @param string|resource|null $value Value of the property as a string
* or seekable stream. Not required for existence tests.
* If a seekable stream is provided, it is sent from its current
* posistion to its end, and the pointer is seeked back to its current
* position after sending.
* Non seekable streams, as well as all other types, are casted to a
* string.
* @param string $operator One of the OP_* constants.
* Describes the operation to perform.
*
* @return static A new query object.
*/
public static function where(
$name,
$value = null,
$operator = self::OP_EX
) {
$query = new static;
return $query->addWhere($name, $value, $operator);
}
/**
* Negates the query.
*
* @return $this The query object.
*/
public function not()
{
$this->words[] = array('#!', null);
return $this;
}
/**
* Adds a condition as an alternative to the query.
*
* @param string $name The name of the property to test.
* @param string|resource|null $value Value of the property as a string
* or seekable stream. Not required for existence tests.
* If a seekable stream is provided, it is sent from its current
* posistion to its end, and the pointer is seeked back to its current
* position after sending.
* Non seekable streams, as well as all other types, are casted to a
* string.
* @param string $operator One of the OP_* constants.
* Describes the operation to perform.
*
* @return $this The query object.
*/
public function orWhere($name, $value = null, $operator = self::OP_EX)
{
$this->addWhere($name, $value, $operator)->words[] = array('#|', null);
return $this;
}
/**
* Adds a condition in addition to the query.
*
* @param string $name The name of the property to test.
* @param string|resource|null $value Value of the property as a string
* or seekable stream. Not required for existence tests.
* If a seekable stream is provided, it is sent from its current
* posistion to its end, and the pointer is seeked back to its current
* position after sending.
* Non seekable streams, as well as all other types, are casted to a
* string.
* @param string $operator One of the OP_* constants.
* Describes the operation to perform.
*
* @return $this The query object.
*/
public function andWhere($name, $value = null, $operator = self::OP_EX)
{
$this->addWhere($name, $value, $operator)->words[] = array('#&', null);
return $this;
}
/**
* Sends the query over a communicator.
*
* @param Communicator $com The communicator to send the query over.
*
* @return int The number of bytes sent.
*/
public function send(Communicator $com)
{
if ($com->getTransmitter()->isPersistent()) {
$old = $com->getTransmitter()->lock(T\Stream::DIRECTION_SEND);
$bytes = $this->_send($com);
$com->getTransmitter()->lock($old, true);
return $bytes;
}
return $this->_send($com);
}
/**
* Sends the query over a communicator.
*
* The only difference with the non private equivalent is that this one does
* not do locking.
*
* @param Communicator $com The communicator to send the query over.
*
* @return int The number of bytes sent.
*/
private function _send(Communicator $com)
{
if (!$com->getTransmitter()->isAcceptingData()) {
throw new SocketException(
'Transmitter is invalid. Sending aborted.',
SocketException::CODE_QUERY_SEND_FAIL
);
}
$bytes = 0;
foreach ($this->words as $queryWord) {
list($predicate, $value) = $queryWord;
$prefix = '?' . $predicate;
if (null === $value) {
$bytes += $com->sendWord($prefix);
} else {
$prefix .= '=';
if (is_string($value)) {
$bytes += $com->sendWord($prefix . $value);
} else {
$bytes += $com->sendWordFromStream($prefix, $value);
}
}
}
return $bytes;
}
/**
* Adds a condition.
*
* @param string $name The name of the property to test.
* @param string|resource|null $value Value of the property as a string
* or seekable stream. Not required for existence tests.
* If a seekable stream is provided, it is sent from its current
* posistion to its end, and the pointer is seeked back to its current
* position after sending.
* Non seekable streams, as well as all other types, are casted to a
* string.
* @param string $operator One of the ACTION_* constants.
* Describes the operation to perform.
*
* @return $this The query object.
*/
protected function addWhere($name, $value, $operator)
{
$this->words[] = array(
static::sanitizeOperator($operator)
. Message::sanitizeAttributeName($name),
(null === $value ? null : Message::sanitizeAttributeValue($value))
);
return $this;
}
}