PageRenderTime 56ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/log4php/helpers/LoggerOptionConverter.php

http://sabre-zarafa.googlecode.com/
PHP | 445 lines | 209 code | 44 blank | 192 comment | 72 complexity | b5db311d51fa6dece9c8e42510a0a500 MD5 | raw file
  1. <?php
  2. /**
  3. * Licensed to the Apache Software Foundation (ASF) under one or more
  4. * contributor license agreements. See the NOTICE file distributed with
  5. * this work for additional information regarding copyright ownership.
  6. * The ASF licenses this file to You under the Apache License, Version 2.0
  7. * (the "License"); you may not use this file except in compliance with
  8. * the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * @package log4php
  19. */
  20. /**
  21. * A convenience class to convert property values to specific types.
  22. *
  23. * @version $Revision: 31 $
  24. * @package log4php
  25. * @subpackage helpers
  26. * @since 0.5
  27. */
  28. class LoggerOptionConverter {
  29. const DELIM_START = '${';
  30. const DELIM_STOP = '}';
  31. const DELIM_START_LEN = 2;
  32. const DELIM_STOP_LEN = 1;
  33. /** String values which are converted to boolean TRUE. */
  34. private static $trueValues = array('1', 'true', 'yes', 'on');
  35. /** String values which are converted to boolean FALSE. */
  36. private static $falseValues = array('0', 'false', 'no', 'off');
  37. /**
  38. * Read a predefined var.
  39. *
  40. * It returns a value referenced by <var>$key</var> using this search criteria:
  41. * - if <var>$key</var> is a constant then return it. Else
  42. * - if <var>$key</var> is set in <var>$_ENV</var> then return it. Else
  43. * - return <var>$def</var>.
  44. *
  45. * @param string $key The key to search for.
  46. * @param string $def The default value to return.
  47. * @return string the string value of the system property, or the default
  48. * value if there is no property with that key.
  49. */
  50. public static function getSystemProperty($key, $def) {
  51. if(defined($key)) {
  52. return (string)constant($key);
  53. } else if(isset($_SERVER[$key])) {
  54. return (string)$_SERVER[$key];
  55. } else if(isset($_ENV[$key])) {
  56. return (string)$_ENV[$key];
  57. } else {
  58. return $def;
  59. }
  60. }
  61. /**
  62. * If <var>$value</var> is <i>true</i>, then <i>true</i> is
  63. * returned. If <var>$value</var> is <i>false</i>, then
  64. * <i>true</i> is returned. Otherwise, <var>$default</var> is
  65. * returned.
  66. *
  67. * <p>Case of value is unimportant.</p>
  68. *
  69. * @param string $value
  70. * @param boolean $default
  71. * @return boolean
  72. */
  73. public static function toBoolean($value, $default=true) {
  74. if (is_null($value)) {
  75. return $default;
  76. } elseif (is_string($value)) {
  77. $trimmedVal = strtolower(trim($value));
  78. if("1" == $trimmedVal or "true" == $trimmedVal or "yes" == $trimmedVal or "on" == $trimmedVal) {
  79. return true;
  80. } else if ("" == $trimmedVal or "0" == $trimmedVal or "false" == $trimmedVal or "no" == $trimmedVal or "off" == $trimmedVal) {
  81. return false;
  82. }
  83. } elseif (is_bool($value)) {
  84. return $value;
  85. } elseif (is_int($value)) {
  86. return !($value == 0); // true is everything but 0 like in C
  87. }
  88. return $default;
  89. }
  90. /** Converts $value to boolean, or throws an exception if not possible. */
  91. public static function toBooleanEx($value) {
  92. if (isset($value)) {
  93. if (is_bool($value)) {
  94. return $value;
  95. }
  96. $value = strtolower(trim($value));
  97. if (in_array($value, self::$trueValues)) {
  98. return true;
  99. }
  100. if (in_array($value, self::$falseValues)) {
  101. return false;
  102. }
  103. }
  104. throw new LoggerException("Given value [" . var_export($value, true) . "] cannot be converted to boolean.");
  105. }
  106. /**
  107. * @param string $value
  108. * @param integer $default
  109. * @return integer
  110. */
  111. public static function toInt($value, $default) {
  112. $value = trim($value);
  113. if(is_numeric($value)) {
  114. return (int)$value;
  115. } else {
  116. return $default;
  117. }
  118. }
  119. /**
  120. * Converts $value to integer, or throws an exception if not possible.
  121. * Floats cannot be converted to integer.
  122. */
  123. public static function toIntegerEx($value) {
  124. if (is_integer($value)) {
  125. return $value;
  126. }
  127. if (is_numeric($value) && ($value == (integer) $value)) {
  128. return (integer) $value;
  129. }
  130. throw new LoggerException("Given value [" . var_export($value, true) . "] cannot be converted to integer.");
  131. }
  132. /**
  133. * Converts $value to integer, or throws an exception if not possible.
  134. * Floats cannot be converted to integer.
  135. */
  136. public static function toPositiveIntegerEx($value) {
  137. if (is_integer($value) && $value > 0) {
  138. return $value;
  139. }
  140. if (is_numeric($value) && ($value == (integer) $value) && $value > 0) {
  141. return (integer) $value;
  142. }
  143. throw new LoggerException("Given value [" . var_export($value, true) . "] cannot be converted to a positive integer.");
  144. }
  145. /**
  146. * Converts a standard or custom priority level to a Level
  147. * object.
  148. *
  149. * <p> If <var>$value</var> is of form "<b>level#full_file_classname</b>",
  150. * where <i>full_file_classname</i> means the class filename with path
  151. * but without php extension, then the specified class' <i>toLevel()</i> method
  152. * is called to process the specified level string; if no '#'
  153. * character is present, then the default {@link LoggerLevel}
  154. * class is used to process the level value.</p>
  155. *
  156. * <p>As a special case, if the <var>$value</var> parameter is
  157. * equal to the string "NULL", then the value <i>null</i> will
  158. * be returned.</p>
  159. *
  160. * <p>If any error occurs while converting the value to a level,
  161. * the <var>$defaultValue</var> parameter, which may be
  162. * <i>null</i>, is returned.</p>
  163. *
  164. * <p>Case of <var>$value</var> is insignificant for the level level, but is
  165. * significant for the class name part, if present.</p>
  166. *
  167. * @param string $value
  168. * @param LoggerLevel $defaultValue
  169. * @return LoggerLevel a {@link LoggerLevel} or null
  170. */
  171. public static function toLevel($value, $defaultValue) {
  172. if($value === null) {
  173. return $defaultValue;
  174. }
  175. $hashIndex = strpos($value, '#');
  176. if($hashIndex === false) {
  177. if("NULL" == strtoupper($value)) {
  178. return null;
  179. } else {
  180. // no class name specified : use standard Level class
  181. return LoggerLevel::toLevel($value, $defaultValue);
  182. }
  183. }
  184. $result = $defaultValue;
  185. $clazz = substr($value, ($hashIndex + 1));
  186. $levelName = substr($value, 0, $hashIndex);
  187. // This is degenerate case but you never know.
  188. if("NULL" == strtoupper($levelName)) {
  189. return null;
  190. }
  191. $clazz = basename($clazz);
  192. if(class_exists($clazz)) {
  193. $result = @call_user_func(array($clazz, 'toLevel'), $levelName, $defaultValue);
  194. if(!$result instanceof LoggerLevel) {
  195. $result = $defaultValue;
  196. }
  197. }
  198. return $result;
  199. }
  200. /** Converts the value to a level. Throws an exception if not possible. */
  201. public static function toLevelEx($value) {
  202. if ($value instanceof LoggerLevel) {
  203. return $value;
  204. }
  205. $level = LoggerLevel::toLevel($value);
  206. if ($level === null) {
  207. throw new LoggerException("Given value [" . var_export($value, true) . "] cannot be converted to a logger level.");
  208. }
  209. return $level;
  210. }
  211. /**
  212. * @param string $value
  213. * @param float $default
  214. * @return float
  215. */
  216. public static function toFileSize($value, $default) {
  217. if($value === null) {
  218. return $default;
  219. }
  220. $s = strtoupper(trim($value));
  221. $multiplier = (float)1;
  222. if(($index = strpos($s, 'KB')) !== false) {
  223. $multiplier = 1024;
  224. $s = substr($s, 0, $index);
  225. } else if(($index = strpos($s, 'MB')) !== false) {
  226. $multiplier = 1024 * 1024;
  227. $s = substr($s, 0, $index);
  228. } else if(($index = strpos($s, 'GB')) !== false) {
  229. $multiplier = 1024 * 1024 * 1024;
  230. $s = substr($s, 0, $index);
  231. }
  232. if(is_numeric($s)) {
  233. return (float)$s * $multiplier;
  234. }
  235. return $default;
  236. }
  237. /**
  238. * Converts a value to a valid file size (integer).
  239. *
  240. * Supports 'KB', 'MB' and 'GB' suffixes, where KB = 1024 B etc.
  241. *
  242. * The final value will be rounded to the nearest integer.
  243. *
  244. * Examples:
  245. * - '100' => 100
  246. * - '100.12' => 100
  247. * - '100KB' => 102400
  248. * - '1.5MB' => 1572864
  249. *
  250. * @param mixed $value File size (optionally with suffix).
  251. * @return integer Parsed file size.
  252. */
  253. public static function toFileSizeEx($value) {
  254. if (empty($value)) {
  255. throw new LoggerException("Empty value cannot be converted to a file size.");
  256. }
  257. if (is_numeric($value)) {
  258. return (integer) $value;
  259. }
  260. if (!is_string($value)) {
  261. throw new LoggerException("Given value [" . var_export($value, true) . "] cannot be converted to a file size.");
  262. }
  263. $str = strtoupper(trim($value));
  264. $count = preg_match('/^([0-9.]+)(KB|MB|GB)?$/', $str, $matches);
  265. if ($count > 0) {
  266. $size = $matches[1];
  267. $unit = $matches[2];
  268. switch($unit) {
  269. case 'KB': $size *= pow(1024, 1); break;
  270. case 'MB': $size *= pow(1024, 2); break;
  271. case 'GB': $size *= pow(1024, 3); break;
  272. }
  273. return (integer) $size;
  274. }
  275. throw new LoggerException("Given value [$value] cannot be converted to a file size.");
  276. }
  277. /**
  278. * Converts a value to string, or throws an exception if not possible.
  279. *
  280. * Objects can be converted to string if they implement the magic
  281. * __toString() method.
  282. *
  283. */
  284. public static function toStringEx($value) {
  285. if (is_string($value)) {
  286. return $value;
  287. }
  288. if (is_numeric($value)) {
  289. return (string) $value;
  290. }
  291. if (is_object($value) && method_exists($value, '__toString')) {
  292. return (string) $value;
  293. }
  294. throw new LoggerException("Given value [" . var_export($value, true) . "] cannot be converted to string.");
  295. }
  296. /**
  297. * Find the value corresponding to <var>$key</var> in
  298. * <var>$props</var>. Then perform variable substitution on the
  299. * found value.
  300. *
  301. * @param string $key
  302. * @param array $props
  303. * @return string
  304. */
  305. public static function findAndSubst($key, $props) {
  306. $value = @$props[$key];
  307. // If coming from the LoggerConfiguratorIni, some options were
  308. // already mangled by parse_ini_file:
  309. //
  310. // not specified => never reaches this code
  311. // ""|off|false|null => string(0) ""
  312. // "1"|on|true => string(1) "1"
  313. // "true" => string(4) "true"
  314. // "false" => string(5) "false"
  315. //
  316. // As the integer 1 and the boolean true are therefore indistinguable
  317. // it's up to the setter how to deal with it, they can not be cast
  318. // into a boolean here. {@see toBoolean}
  319. // Even an empty value has to be given to the setter as it has been
  320. // explicitly set by the user and is different from an option which
  321. // has not been specified and therefore keeps its default value.
  322. //
  323. // if(!empty($value)) {
  324. return LoggerOptionConverter::substVars($value, $props);
  325. // }
  326. }
  327. /**
  328. * Perform variable substitution in string <var>$val</var> from the
  329. * values of keys found with the {@link getSystemProperty()} method.
  330. *
  331. * <p>The variable substitution delimeters are <b>${</b> and <b>}</b>.
  332. *
  333. * <p>For example, if the "MY_CONSTANT" contains "value", then
  334. * the call
  335. * <code>
  336. * $s = LoggerOptionConverter::substVars("Value of key is ${MY_CONSTANT}.");
  337. * </code>
  338. * will set the variable <i>$s</i> to "Value of key is value.".</p>
  339. *
  340. * <p>If no value could be found for the specified key, then the
  341. * <var>$props</var> parameter is searched, if the value could not
  342. * be found there, then substitution defaults to the empty string.</p>
  343. *
  344. * <p>For example, if {@link getSystemProperty()} cannot find any value for the key
  345. * "inexistentKey", then the call
  346. * <code>
  347. * $s = LoggerOptionConverter::substVars("Value of inexistentKey is [${inexistentKey}]");
  348. * </code>
  349. * will set <var>$s</var> to "Value of inexistentKey is []".</p>
  350. *
  351. * <p>A warn is thrown if <var>$val</var> contains a start delimeter "${"
  352. * which is not balanced by a stop delimeter "}" and an empty string is returned.</p>
  353. *
  354. * @param string $val The string on which variable substitution is performed.
  355. * @param array $props
  356. * @return string
  357. */
  358. // TODO: this method doesn't work correctly with key = true, it needs key = "true" which is odd
  359. public static function substVars($val, $props = null) {
  360. $sbuf = '';
  361. $i = 0;
  362. while(true) {
  363. $j = strpos($val, self::DELIM_START, $i);
  364. if($j === false) {
  365. // no more variables
  366. if($i == 0) { // this is a simple string
  367. return $val;
  368. } else { // add the tail string which contails no variables and return the result.
  369. $sbuf .= substr($val, $i);
  370. return $sbuf;
  371. }
  372. } else {
  373. $sbuf .= substr($val, $i, $j-$i);
  374. $k = strpos($val, self::DELIM_STOP, $j);
  375. if($k === false) {
  376. // LoggerOptionConverter::substVars() has no closing brace. Opening brace
  377. return '';
  378. } else {
  379. $j += self::DELIM_START_LEN;
  380. $key = substr($val, $j, $k - $j);
  381. // first try in System properties
  382. $replacement = LoggerOptionConverter::getSystemProperty($key, null);
  383. // then try props parameter
  384. if($replacement == null and $props !== null) {
  385. $replacement = @$props[$key];
  386. }
  387. if(!empty($replacement)) {
  388. // Do variable substitution on the replacement string
  389. // such that we can solve "Hello ${x2}" as "Hello p1"
  390. // the where the properties are
  391. // x1=p1
  392. // x2=${x1}
  393. $recursiveReplacement = LoggerOptionConverter::substVars($replacement, $props);
  394. $sbuf .= $recursiveReplacement;
  395. }
  396. $i = $k + self::DELIM_STOP_LEN;
  397. }
  398. }
  399. }
  400. }
  401. }