* @copyright 2011 Vasil Rangelov * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @version 1.0.0b6 * @link http://pear2.php.net/PEAR2_Net_RouterOS */ /** * The namespace declaration. */ namespace PEAR2\Net\RouterOS; /** * Values at {@link Script::escapeValue()} can be casted from this type. */ use DateTime; /** * Values at {@link Script::escapeValue()} can be casted from this type. */ use DateInterval; /** * Used at {@link Script::escapeValue()} to get the proper time. */ use DateTimeZone; /** * Used to reliably write to streams at {@link Script::prepare()}. */ use PEAR2\Net\Transmitter\Stream; /** * Used to catch DateTime and DateInterval exceptions at * {@link Script::parseValue()}. */ use Exception as E; /** * Scripting class. * * Provides functionality related to parsing and composing RouterOS scripts and * values. * * @category Net * @package PEAR2_Net_RouterOS * @author Vasil Rangelov * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @link http://pear2.php.net/PEAR2_Net_RouterOS */ class Script { /** * Parses a value from a RouterOS scripting context. * * Turns a value from RouterOS into an equivalent PHP value, based on * determining the type in the same way RouterOS would determine it for a * literal. * * This method is intended to be the very opposite of * {@link static::escapeValue()}. That is, results from that method, if * given to this method, should produce equivalent results. * * @param string $value The value to be parsed. * Must be a literal of a value, * e.g. what {@link static::escapeValue()} will give you. * @param DateTimeZone|null $timezone The timezone which any resulting * DateTime object (either the main value, or values within an array) * will use. Defaults to UTC. * * @return mixed Depending on RouterOS type detected: * - "nil" (the string "[]") or "nothing" (empty string) - NULL. * - "num" - int or double for large values. * - "bool" - a boolean. * - "array" - an array, with the keys and values processed recursively. * - "time" - a {@link DateInterval} object. * - "date" (pseudo type; string in the form "M/j/Y") - a DateTime * object with the specified date, at midnight. * - "datetime" (pseudo type; string in the form "M/j/Y H:i:s") - a * DateTime object with the specified date and time. * - "str" (a quoted string) - a string, with the contents escaped. * - Unrecognized type - casted to a string, unmodified. */ public static function parseValue($value, DateTimeZone $timezone = null) { $value = static::parseValueToSimple($value); if (!is_string($value)) { return $value; } try { return static::parseValueToArray($value, $timezone); } catch (ParserException $e) { try { return static::parseValueToDateInterval($value); } catch (ParserException $e) { try { return static::parseValueToDateTime($value, $timezone); } catch (ParserException $e) { return static::parseValueToString($value); } } } } /** * Parses a RouterOS value into a PHP string. * * @param string $value The value to be parsed. * Must be a literal of a value, * e.g. what {@link static::escapeValue()} will give you. * * @return string If a quoted string is provided, it would be parsed. * Otherwise, the value is casted to a string, and returned unmodified. */ public static function parseValueToString($value) { $value = (string)$value; if ('"' === $value[0] && '"' === $value[strlen($value) - 1]) { return str_replace( array('\"', '\\\\', "\\\n", "\\\r\n", "\\\r"), array('"', '\\'), substr($value, 1, -1) ); } return $value; } /** * Parses a RouterOS value into a PHP simple type. * * Parses a RouterOS value into a PHP simple type. "Simple" types being * scalar types, plus NULL. * * @param string $value The value to be parsed. Must be a literal of a * value, e.g. what {@link static::escapeValue()} will give you. * * @return string|bool|int|double|null Depending on RouterOS type detected: * - "nil" (the string "[]") or "nothing" (empty string) - NULL. * - "num" - int or double for large values. * - "bool" - a boolean. * - Unrecognized type - casted to a string, unmodified. */ public static function parseValueToSimple($value) { $value = (string)$value; if (in_array($value, array('', '[]'), true)) { return null; } elseif (in_array($value, array('true', 'false', 'yes', 'no'), true)) { return $value === 'true' || $value === 'yes'; } elseif ($value === (string)($num = (int)$value) || $value === (string)($num = (double)$value) ) { return $num; } return $value; } /** * Parses a RouterOS value into a PHP DateTime object * * Parses a RouterOS value into a PHP DateTime object. * * @param string $value The value to be parsed. * Must be a literal of a value, * e.g. what {@link static::escapeValue()} will give you. * @param DateTimeZone|null $timezone The timezone which the resulting * DateTime object will use. Defaults to UTC. * * @return DateTime Depending on RouterOS type detected: * - "date" (pseudo type; string in the form "M/j/Y") - a DateTime * object with the specified date, at midnight UTC time (regardless * of timezone provided). * - "datetime" (pseudo type; string in the form "M/j/Y H:i:s") - a * DateTime object with the specified date and time, * with the specified timezone. * * @throws ParserException When the value is not of a recognized type. */ public static function parseValueToDateTime( $value, DateTimeZone $timezone = null ) { $previous = null; $value = (string)$value; if ('' !== $value && preg_match( '#^ (?jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec) / (?\d\d?) / (?\d{4}) (?: \s+(?