File indexing completed on 2024-12-22 05:36:21

0001 <?php
0002 
0003 /**
0004  * Represents a measurable length, with a string numeric magnitude
0005  * and a unit. This object is immutable.
0006  */
0007 class HTMLPurifier_Length
0008 {
0009 
0010     /**
0011      * String numeric magnitude.
0012      * @type string
0013      */
0014     protected $n;
0015 
0016     /**
0017      * String unit. False is permitted if $n = 0.
0018      * @type string|bool
0019      */
0020     protected $unit;
0021 
0022     /**
0023      * Whether or not this length is valid. Null if not calculated yet.
0024      * @type bool
0025      */
0026     protected $isValid;
0027 
0028     /**
0029      * Array Lookup array of units recognized by CSS 2.1
0030      * @type array
0031      */
0032     protected static $allowedUnits = array(
0033         'em' => true, 'ex' => true, 'px' => true, 'in' => true,
0034         'cm' => true, 'mm' => true, 'pt' => true, 'pc' => true
0035     );
0036 
0037     /**
0038      * @param string $n Magnitude
0039      * @param bool|string $u Unit
0040      */
0041     public function __construct($n = '0', $u = false)
0042     {
0043         $this->n = (string) $n;
0044         $this->unit = $u !== false ? (string) $u : false;
0045     }
0046 
0047     /**
0048      * @param string $s Unit string, like '2em' or '3.4in'
0049      * @return HTMLPurifier_Length
0050      * @warning Does not perform validation.
0051      */
0052     public static function make($s)
0053     {
0054         if ($s instanceof HTMLPurifier_Length) {
0055             return $s;
0056         }
0057         $n_length = strspn($s, '1234567890.+-');
0058         $n = substr($s, 0, $n_length);
0059         $unit = substr($s, $n_length);
0060         if ($unit === '') {
0061             $unit = false;
0062         }
0063         return new HTMLPurifier_Length($n, $unit);
0064     }
0065 
0066     /**
0067      * Validates the number and unit.
0068      * @return bool
0069      */
0070     protected function validate()
0071     {
0072         // Special case:
0073         if ($this->n === '+0' || $this->n === '-0') {
0074             $this->n = '0';
0075         }
0076         if ($this->n === '0' && $this->unit === false) {
0077             return true;
0078         }
0079         if (!ctype_lower($this->unit)) {
0080             $this->unit = strtolower($this->unit);
0081         }
0082         if (!isset(HTMLPurifier_Length::$allowedUnits[$this->unit])) {
0083             return false;
0084         }
0085         // Hack:
0086         $def = new HTMLPurifier_AttrDef_CSS_Number();
0087         $result = $def->validate($this->n, false, false);
0088         if ($result === false) {
0089             return false;
0090         }
0091         $this->n = $result;
0092         return true;
0093     }
0094 
0095     /**
0096      * Returns string representation of number.
0097      * @return string
0098      */
0099     public function toString()
0100     {
0101         if (!$this->isValid()) {
0102             return false;
0103         }
0104         return $this->n . $this->unit;
0105     }
0106 
0107     /**
0108      * Retrieves string numeric magnitude.
0109      * @return string
0110      */
0111     public function getN()
0112     {
0113         return $this->n;
0114     }
0115 
0116     /**
0117      * Retrieves string unit.
0118      * @return string
0119      */
0120     public function getUnit()
0121     {
0122         return $this->unit;
0123     }
0124 
0125     /**
0126      * Returns true if this length unit is valid.
0127      * @return bool
0128      */
0129     public function isValid()
0130     {
0131         if ($this->isValid === null) {
0132             $this->isValid = $this->validate();
0133         }
0134         return $this->isValid;
0135     }
0136 
0137     /**
0138      * Compares two lengths, and returns 1 if greater, -1 if less and 0 if equal.
0139      * @param HTMLPurifier_Length $l
0140      * @return int
0141      * @warning If both values are too large or small, this calculation will
0142      *          not work properly
0143      */
0144     public function compareTo($l)
0145     {
0146         if ($l === false) {
0147             return false;
0148         }
0149         if ($l->unit !== $this->unit) {
0150             $converter = new HTMLPurifier_UnitConverter();
0151             $l = $converter->convert($l, $this->unit);
0152             if ($l === false) {
0153                 return false;
0154             }
0155         }
0156         return $this->n - $l->n;
0157     }
0158 }
0159 
0160 // vim: et sw=4 sts=4