/library/Zend/Filter/Boolean.php

https://bitbucket.org/gencer/zf2 · PHP · 297 lines · 193 code · 34 blank · 70 comment · 64 complexity · 9ebe67d19d343668c616e2307e2d03a9 MD5 · raw file

  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\Filter;
  10. use Traversable;
  11. use Zend\Stdlib\ArrayUtils;
  12. class Boolean extends AbstractFilter
  13. {
  14. const TYPE_BOOLEAN = 1;
  15. const TYPE_INTEGER = 2;
  16. const TYPE_FLOAT = 4;
  17. const TYPE_STRING = 8;
  18. const TYPE_ZERO_STRING = 16;
  19. const TYPE_EMPTY_ARRAY = 32;
  20. const TYPE_NULL = 64;
  21. const TYPE_PHP = 127;
  22. const TYPE_FALSE_STRING = 128;
  23. const TYPE_LOCALIZED = 256;
  24. const TYPE_ALL = 511;
  25. /**
  26. * @var array
  27. */
  28. protected $constants = array(
  29. self::TYPE_BOOLEAN => 'boolean',
  30. self::TYPE_INTEGER => 'integer',
  31. self::TYPE_FLOAT => 'float',
  32. self::TYPE_STRING => 'string',
  33. self::TYPE_ZERO_STRING => 'zero',
  34. self::TYPE_EMPTY_ARRAY => 'array',
  35. self::TYPE_NULL => 'null',
  36. self::TYPE_PHP => 'php',
  37. self::TYPE_FALSE_STRING => 'false',
  38. self::TYPE_LOCALIZED => 'localized',
  39. self::TYPE_ALL => 'all',
  40. );
  41. /**
  42. * @var array
  43. */
  44. protected $options = array(
  45. 'type' => self::TYPE_PHP,
  46. 'casting' => true,
  47. 'translations' => array(),
  48. );
  49. /**
  50. * Constructor
  51. *
  52. * @param array|Traversable|int|null $typeOrOptions
  53. * @param bool $casting
  54. * @param array $translations
  55. */
  56. public function __construct($typeOrOptions = null, $casting = true, $translations = array())
  57. {
  58. if ($typeOrOptions !== null) {
  59. if ($typeOrOptions instanceof Traversable) {
  60. $typeOrOptions = ArrayUtils::iteratorToArray($typeOrOptions);
  61. }
  62. if (is_array($typeOrOptions)) {
  63. if (isset($typeOrOptions['type'])
  64. || isset($typeOrOptions['casting'])
  65. || isset($typeOrOptions['translations']))
  66. {
  67. $this->setOptions($typeOrOptions);
  68. } else {
  69. $this->setType($typeOrOptions);
  70. $this->setCasting($casting);
  71. $this->setTranslations($translations);
  72. }
  73. } else {
  74. $this->setType($typeOrOptions);
  75. $this->setCasting($casting);
  76. $this->setTranslations($translations);
  77. }
  78. }
  79. }
  80. /**
  81. * Set boolean types
  82. *
  83. * @param int|array $type
  84. * @throws Exception\InvalidArgumentException
  85. * @return self
  86. */
  87. public function setType($type = null)
  88. {
  89. if (is_array($type)) {
  90. $detected = 0;
  91. foreach ($type as $value) {
  92. if (is_int($value)) {
  93. $detected += $value;
  94. } elseif (in_array($value, $this->constants)) {
  95. $detected += array_search($value, $this->constants);
  96. }
  97. }
  98. $type = $detected;
  99. } elseif (is_string($type) && in_array($type, $this->constants)) {
  100. $type = array_search($type, $this->constants);
  101. }
  102. if (!is_int($type) || ($type < 0) || ($type > self::TYPE_ALL)) {
  103. throw new Exception\InvalidArgumentException(sprintf(
  104. 'Unknown type value "%s" (%s)',
  105. $type,
  106. gettype($type)
  107. ));
  108. }
  109. $this->options['type'] = $type;
  110. return $this;
  111. }
  112. /**
  113. * Returns defined boolean types
  114. *
  115. * @return int
  116. */
  117. public function getType()
  118. {
  119. return $this->options['type'];
  120. }
  121. /**
  122. * Set the working mode
  123. *
  124. * @param bool $flag When true this filter works like cast
  125. * When false it recognises only true and false
  126. * and all other values are returned as is
  127. * @return self
  128. */
  129. public function setCasting($flag = true)
  130. {
  131. $this->options['casting'] = (bool) $flag;
  132. return $this;
  133. }
  134. /**
  135. * Returns the casting option
  136. *
  137. * @return bool
  138. */
  139. public function getCasting()
  140. {
  141. return $this->options['casting'];
  142. }
  143. /**
  144. * @param array|Traversable $translations
  145. * @throws Exception\InvalidArgumentException
  146. * @return self
  147. */
  148. public function setTranslations($translations)
  149. {
  150. if (!is_array($translations) && !$translations instanceof Traversable) {
  151. throw new Exception\InvalidArgumentException(sprintf(
  152. '"%s" expects an array or Traversable; received "%s"',
  153. __METHOD__,
  154. (is_object($translations) ? get_class($translations) : gettype($translations))
  155. ));
  156. }
  157. foreach ($translations as $message => $flag) {
  158. $this->options['translations'][$message] = (bool) $flag;
  159. }
  160. return $this;
  161. }
  162. /**
  163. * @return array
  164. */
  165. public function getTranslations()
  166. {
  167. return $this->options['translations'];
  168. }
  169. /**
  170. * Defined by Zend\Filter\FilterInterface
  171. *
  172. * Returns a boolean representation of $value
  173. *
  174. * @param string $value
  175. * @return string
  176. */
  177. public function filter($value)
  178. {
  179. $type = $this->getType();
  180. $casting = $this->getCasting();
  181. // LOCALIZED
  182. if ($type >= self::TYPE_LOCALIZED) {
  183. $type -= self::TYPE_LOCALIZED;
  184. if (is_string($value)) {
  185. if (isset($this->options['translations'][$value])) {
  186. return (bool) $this->options['translations'][$value];
  187. }
  188. }
  189. }
  190. // FALSE_STRING ('false')
  191. if ($type >= self::TYPE_FALSE_STRING) {
  192. $type -= self::TYPE_FALSE_STRING;
  193. if (is_string($value) && (strtolower($value) == 'false')) {
  194. return false;
  195. }
  196. if (!$casting && is_string($value) && (strtolower($value) == 'true')) {
  197. return true;
  198. }
  199. }
  200. // NULL (null)
  201. if ($type >= self::TYPE_NULL) {
  202. $type -= self::TYPE_NULL;
  203. if ($value === null) {
  204. return false;
  205. }
  206. }
  207. // EMPTY_ARRAY (array())
  208. if ($type >= self::TYPE_EMPTY_ARRAY) {
  209. $type -= self::TYPE_EMPTY_ARRAY;
  210. if (is_array($value) && ($value == array())) {
  211. return false;
  212. }
  213. }
  214. // ZERO_STRING ('0')
  215. if ($type >= self::TYPE_ZERO_STRING) {
  216. $type -= self::TYPE_ZERO_STRING;
  217. if (is_string($value) && ($value == '0')) {
  218. return false;
  219. }
  220. if (!$casting && (is_string($value)) && ($value == '1')) {
  221. return true;
  222. }
  223. }
  224. // STRING ('')
  225. if ($type >= self::TYPE_STRING) {
  226. $type -= self::TYPE_STRING;
  227. if (is_string($value) && ($value == '')) {
  228. return false;
  229. }
  230. }
  231. // FLOAT (0.0)
  232. if ($type >= self::TYPE_FLOAT) {
  233. $type -= self::TYPE_FLOAT;
  234. if (is_float($value) && ($value == 0.0)) {
  235. return false;
  236. }
  237. if (!$casting && is_float($value) && ($value == 1.0)) {
  238. return true;
  239. }
  240. }
  241. // INTEGER (0)
  242. if ($type >= self::TYPE_INTEGER) {
  243. $type -= self::TYPE_INTEGER;
  244. if (is_int($value) && ($value == 0)) {
  245. return false;
  246. }
  247. if (!$casting && is_int($value) && ($value == 1)) {
  248. return true;
  249. }
  250. }
  251. // BOOLEAN (false)
  252. if ($type >= self::TYPE_BOOLEAN) {
  253. $type -= self::TYPE_BOOLEAN;
  254. if (is_bool($value)) {
  255. return $value;
  256. }
  257. }
  258. if ($casting) {
  259. return true;
  260. }
  261. return $value;
  262. }
  263. }