Length.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. <?php
  2. /**
  3. * Represents a measurable length, with a string numeric magnitude
  4. * and a unit. This object is immutable.
  5. */
  6. class HTMLPurifier_Length
  7. {
  8. /**
  9. * String numeric magnitude.
  10. */
  11. protected $n;
  12. /**
  13. * String unit. False is permitted if $n = 0.
  14. */
  15. protected $unit;
  16. /**
  17. * Whether or not this length is valid. Null if not calculated yet.
  18. */
  19. protected $isValid;
  20. /**
  21. * Lookup array of units recognized by CSS 2.1
  22. */
  23. protected static $allowedUnits = array(
  24. 'em' => true, 'ex' => true, 'px' => true, 'in' => true,
  25. 'cm' => true, 'mm' => true, 'pt' => true, 'pc' => true
  26. );
  27. /**
  28. * @param number $n Magnitude
  29. * @param string $u Unit
  30. */
  31. public function __construct($n = '0', $u = false) {
  32. $this->n = (string) $n;
  33. $this->unit = $u !== false ? (string) $u : false;
  34. }
  35. /**
  36. * @param string $s Unit string, like '2em' or '3.4in'
  37. * @warning Does not perform validation.
  38. */
  39. static public function make($s) {
  40. if ($s instanceof HTMLPurifier_Length) return $s;
  41. $n_length = strspn($s, '1234567890.+-');
  42. $n = substr($s, 0, $n_length);
  43. $unit = substr($s, $n_length);
  44. if ($unit === '') $unit = false;
  45. return new HTMLPurifier_Length($n, $unit);
  46. }
  47. /**
  48. * Validates the number and unit.
  49. */
  50. protected function validate() {
  51. // Special case:
  52. if ($this->n === '+0' || $this->n === '-0') $this->n = '0';
  53. if ($this->n === '0' && $this->unit === false) return true;
  54. if (!ctype_lower($this->unit)) $this->unit = strtolower($this->unit);
  55. if (!isset(HTMLPurifier_Length::$allowedUnits[$this->unit])) return false;
  56. // Hack:
  57. $def = new HTMLPurifier_AttrDef_CSS_Number();
  58. $result = $def->validate($this->n, false, false);
  59. if ($result === false) return false;
  60. $this->n = $result;
  61. return true;
  62. }
  63. /**
  64. * Returns string representation of number.
  65. */
  66. public function toString() {
  67. if (!$this->isValid()) return false;
  68. return $this->n . $this->unit;
  69. }
  70. /**
  71. * Retrieves string numeric magnitude.
  72. */
  73. public function getN() {return $this->n;}
  74. /**
  75. * Retrieves string unit.
  76. */
  77. public function getUnit() {return $this->unit;}
  78. /**
  79. * Returns true if this length unit is valid.
  80. */
  81. public function isValid() {
  82. if ($this->isValid === null) $this->isValid = $this->validate();
  83. return $this->isValid;
  84. }
  85. /**
  86. * Compares two lengths, and returns 1 if greater, -1 if less and 0 if equal.
  87. * @warning If both values are too large or small, this calculation will
  88. * not work properly
  89. */
  90. public function compareTo($l) {
  91. if ($l === false) return false;
  92. if ($l->unit !== $this->unit) {
  93. $converter = new HTMLPurifier_UnitConverter();
  94. $l = $converter->convert($l, $this->unit);
  95. if ($l === false) return false;
  96. }
  97. return $this->n - $l->n;
  98. }
  99. }
  100. // vim: et sw=4 sts=4