Development

/branches/1.3/lib/escaper/sfOutputEscaper.class.php

You must first sign up to be able to contribute.

root/branches/1.3/lib/escaper/sfOutputEscaper.class.php

Revision 21908, 6.3 kB (checked in by fabien, 5 years ago)

[1.3] made some optimizations by replacing is_null() by null ===

  • Property svn:mime-type set to text/x-php
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1 <?php
2
3 /*
4  * This file is part of the symfony package.
5  * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
6  *
7  * For the full copyright and license information, please view the LICENSE
8  * file that was distributed with this source code.
9  */
10
11 /**
12  * Abstract class that provides an interface for escaping of output.
13  *
14  * @package    symfony
15  * @subpackage view
16  * @author     Mike Squire <mike@somosis.co.uk>
17  * @version    SVN: $Id$
18  */
19 abstract class sfOutputEscaper
20 {
21   /**
22    * The value that is to be escaped.
23    *
24    * @var mixed
25    */
26   protected $value;
27
28   /**
29    * The escaping method that is going to be applied to the value and its
30    * children. This is actually the name of a PHP callable.
31    *
32    * @var string
33    */
34   protected $escapingMethod;
35
36   static protected $safeClasses = array();
37
38   /**
39    * Constructor stores the escaping method and value.
40    *
41    * Since sfOutputEscaper is an abstract class, instances cannot be created
42    * directly but the constructor will be inherited by sub-classes.
43    *
44    * @param string $escapingMethod  Escaping method
45    * @param string $value           Escaping value
46    */
47   public function __construct($escapingMethod, $value)
48   {
49     $this->value          = $value;
50     $this->escapingMethod = $escapingMethod;
51   }
52
53   /**
54    * Decorates a PHP variable with something that will escape any data obtained
55    * from it.
56    *
57    * The following cases are dealt with:
58    *
59    *    - The value is null or false: null or false is returned.
60    *    - The value is scalar: the result of applying the escaping method is
61    *      returned.
62    *    - The value is an array or an object that implements the ArrayAccess
63    *      interface: the array is decorated such that accesses to elements yield
64    *      an escaped value.
65    *    - The value implements the Traversable interface (either an Iterator, an
66    *      IteratorAggregate or an internal PHP class that implements
67    *      Traversable): decorated much like the array.
68    *    - The value is another type of object: decorated such that the result of
69    *      method calls is escaped.
70    *
71    * The escaping method is actually the name of a PHP callable. There are a set
72    * of standard escaping methods listed in the escaping helper
73    * (EscapingHelper.php).
74    *
75    * @param  string $escapingMethod  The escaping method (a PHP callable) to apply to the value
76    * @param  mixed  $value           The value to escape
77    *
78    * @return mixed Escaping value
79    *
80    * @throws InvalidArgumentException If the escaping fails
81    */
82   public static function escape($escapingMethod, $value)
83   {
84     if (null === $value)
85     {
86       return $value;
87     }
88
89     // Scalars are anything other than arrays, objects and resources.
90     if (is_scalar($value))
91     {
92       return call_user_func($escapingMethod, $value);
93     }
94
95     if (is_array($value))
96     {
97       return new sfOutputEscaperArrayDecorator($escapingMethod, $value);
98     }
99
100     if (is_object($value))
101     {
102       if ($value instanceof sfOutputEscaper)
103       {
104         // avoid double decoration
105         $copy = clone $value;
106
107         $copy->escapingMethod = $escapingMethod;
108
109         return $copy;
110       }
111       else if (self::isClassMarkedAsSafe(get_class($value)))
112       {
113         // the class or one of its children is marked as safe
114         // return the unescaped object
115         return $value;
116       }
117       else if ($value instanceof sfOutputEscaperSafe)
118       {
119         // do not escape objects marked as safe
120         // return the original object
121         return $value->getValue();
122       }
123       else if ($value instanceof Traversable)
124       {
125         return new sfOutputEscaperIteratorDecorator($escapingMethod, $value);
126       }
127       else
128       {
129         return new sfOutputEscaperObjectDecorator($escapingMethod, $value);
130       }
131     }
132
133     // it must be a resource; cannot escape that.
134     throw new InvalidArgumentException(sprintf('Unable to escape value "%s".', var_export($value, true)));
135   }
136
137   /**
138    * Unescapes a value that has been escaped previously with the escape() method.
139    *
140    * @param  mixed $value The value to unescape
141    *
142    * @return mixed Unescaped value
143    *
144    * @throws InvalidArgumentException If the escaping fails
145    */
146   static public function unescape($value)
147   {
148     if (null === $value || is_bool($value))
149     {
150       return $value;
151     }
152
153     if (is_scalar($value))
154     {
155       return html_entity_decode($value, ENT_QUOTES, sfConfig::get('sf_charset'));
156     }
157     elseif (is_array($value))
158     {
159       foreach ($value as $name => $v)
160       {
161         $value[$name] = self::unescape($v);
162       }
163
164       return $value;
165     }
166     elseif (is_object($value))
167     {
168       return $value instanceof sfOutputEscaper ? $value->getRawValue() : $value;
169     }
170
171     return $value;
172   }
173
174   /**
175    * Returns true if the class if marked as safe.
176    *
177    * @param  string  $class  A class name
178    *
179    * @return bool true if the class if safe, false otherwise
180    */
181   static public function isClassMarkedAsSafe($class)
182   {
183     if (in_array($class, self::$safeClasses))
184     {
185       return true;
186     }
187
188     foreach (self::$safeClasses as $safeClass)
189     {
190       if (is_subclass_of($class, $safeClass))
191       {
192         return true;
193       }
194     }
195
196     return false;
197   }
198
199   /**
200    * Marks an array of classes (and all its children) as being safe for output.
201    *
202    * @param array $classes  An array of class names
203    */
204   static public function markClassesAsSafe(array $classes)
205   {
206     self::$safeClasses = array_unique(array_merge(self::$safeClasses, $classes));
207   }
208
209   /**
210    * Marks a class (and all its children) as being safe for output.
211    *
212    * @param string $class  A class name
213    */
214   static public function markClassAsSafe($class)
215   {
216     self::markClassesAsSafe(array($class));
217   }
218
219   /**
220    * Returns the raw value associated with this instance.
221    *
222    * Concrete instances of sfOutputEscaper classes decorate a value which is
223    * stored by the constructor. This returns that original, unescaped, value.
224    *
225    * @return mixed The original value used to construct the decorator
226    */
227   public function getRawValue()
228   {
229     return $this->value;
230   }
231
232   /**
233    * Gets a value from the escaper.
234    *
235    * @param  string $var  Value to get
236    *
237    * @return mixed Value
238    */
239   public function __get($var)
240   {
241     return $this->escape($this->escapingMethod, $this->value->$var);
242   }
243 }
244
Note: See TracBrowser for help on using the browser.