Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
 
3
/*
4
 * This file is part of the symfony package.
5
 * (c) 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
 * sfWidget is the base class for all widgets.
13
 *
14
 * @package    symfony
15
 * @subpackage widget
16
 * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
17
 * @version    SVN: $Id: sfWidget.class.php 22933 2009-10-11 22:42:56Z Kris.Wallsmith $
18
 */
19
abstract class sfWidget
20
{
21
  protected
22
    $requiredOptions = array(),
23
    $attributes      = array(),
24
    $options         = array();
25
 
26
  protected static
27
    $xhtml   = true,
28
    $charset = 'UTF-8';
29
 
30
  /**
31
   * Constructor.
32
   *
33
   * @param array $options     An array of options
34
   * @param array $attributes  An array of default HTML attributes
35
   *
36
   * @throws InvalidArgumentException when a option is not supported
37
   * @throws RuntimeException         when a required option is not given
38
   */
39
  public function __construct($options = array(), $attributes = array())
40
  {
41
    $this->configure($options, $attributes);
42
 
43
    $currentOptionKeys = array_keys($this->options);
44
    $optionKeys = array_keys($options);
45
 
46
    // check option names
47
    if ($diff = array_diff($optionKeys, array_merge($currentOptionKeys, $this->requiredOptions)))
48
    {
49
      throw new InvalidArgumentException(sprintf('%s does not support the following options: \'%s\'.', get_class($this), implode('\', \'', $diff)));
50
    }
51
 
52
    // check required options
53
    if ($diff = array_diff($this->requiredOptions, array_merge($currentOptionKeys, $optionKeys)))
54
    {
55
      throw new RuntimeException(sprintf('%s requires the following options: \'%s\'.', get_class($this), implode('\', \'', $diff)));
56
    }
57
 
58
    $this->options = array_merge($this->options, $options);
59
    $this->attributes = array_merge($this->attributes, $attributes);
60
  }
61
 
62
  /**
63
   * Configures the current widget.
64
   *
65
   * This method allows each widget to add options or HTML attributes
66
   * during widget creation.
67
   *
68
   * If some options and HTML attributes are given in the sfWidget constructor
69
   * they will take precedence over the options and HTML attributes you configure
70
   * in this method.
71
   *
72
   * @param array $options     An array of options
73
   * @param array $attributes  An array of HTML attributes
74
   *
75
   * @see __construct()
76
   */
77
  protected function configure($options = array(), $attributes = array())
78
  {
79
  }
80
 
81
  /**
82
   * Renders the widget as HTML.
83
   *
84
   * All subclasses must implement this method.
85
   *
86
   * @param  string $name       The name of the HTML widget
87
   * @param  mixed  $value      The value of the widget
88
   * @param  array  $attributes An array of HTML attributes
89
   * @param  array  $errors     An array of errors
90
   *
91
   * @return string A HTML representation of the widget
92
   */
93
  abstract public function render($name, $value = null, $attributes = array(), $errors = array());
94
 
95
  /**
96
   * Adds a required option.
97
   *
98
   * @param string $name  The option name
99
   *
100
   * @return sfWidget The current widget instance
101
   */
102
  public function addRequiredOption($name)
103
  {
104
    $this->requiredOptions[] = $name;
105
 
106
    return $this;
107
  }
108
 
109
  /**
110
   * Returns all required option names.
111
   *
112
   * @return array An array of required option names
113
   */
114
  public function getRequiredOptions()
115
  {
116
    return $this->requiredOptions;
117
  }
118
 
119
  /**
120
   * Adds a new option value with a default value.
121
   *
122
   * @param string $name   The option name
123
   * @param mixed  $value  The default value
124
   *
125
   * @return sfWidget The current widget instance
126
   */
127
  public function addOption($name, $value = null)
128
  {
129
    $this->options[$name] = $value;
130
 
131
    return $this;
132
  }
133
 
134
  /**
135
   * Changes an option value.
136
   *
137
   * @param string $name   The option name
138
   * @param mixed  $value  The value
139
   *
140
   * @return sfWidget The current widget instance
141
   *
142
   * @throws InvalidArgumentException when a option is not supported
143
   */
144
  public function setOption($name, $value)
145
  {
146
    if (!in_array($name, array_merge(array_keys($this->options), $this->requiredOptions)))
147
    {
148
      throw new InvalidArgumentException(sprintf('%s does not support the following option: \'%s\'.', get_class($this), $name));
149
    }
150
 
151
    $this->options[$name] = $value;
152
 
153
    return $this;
154
  }
155
 
156
  /**
157
   * Gets an option value.
158
   *
159
   * @param  string $name The option name
160
   *
161
   * @return mixed  The option value
162
   */
163
  public function getOption($name)
164
  {
165
    return isset($this->options[$name]) ? $this->options[$name] : null;
166
  }
167
 
168
  /**
169
   * Returns true if the option exists.
170
   *
171
   * @param  string $name  The option name
172
   *
173
   * @return bool true if the option exists, false otherwise
174
   */
175
  public function hasOption($name)
176
  {
177
    return array_key_exists($name, $this->options);
178
  }
179
 
180
  /**
181
   * Gets all options.
182
   *
183
   * @return array  An array of named options
184
   */
185
  public function getOptions()
186
  {
187
    return $this->options;
188
  }
189
 
190
  /**
191
   * Sets the options.
192
   *
193
   * @param array $options  An array of options
194
   *
195
   * @return sfWidget The current widget instance
196
   */
197
  public function setOptions($options)
198
  {
199
    $this->options = $options;
200
 
201
    return $this;
202
  }
203
 
204
  /**
205
   * Returns the default HTML attributes.
206
   *
207
   * @param array An array of HTML attributes
208
   */
209
  public function getAttributes()
210
  {
211
    return $this->attributes;
212
  }
213
 
214
  /**
215
   * Sets a default HTML attribute.
216
   *
217
   * @param string $name   The attribute name
218
   * @param string $value  The attribute value
219
   *
220
   * @return sfWidget The current widget instance
221
   */
222
  public function setAttribute($name, $value)
223
  {
224
    $this->attributes[$name] = $value;
225
 
226
    return $this;
227
  }
228
 
229
  /**
230
   * Returns the HTML attribute value for a given attribute name.
231
   *
232
   * @param  string $name  The attribute name.
233
   *
234
   * @return string The attribute value, or null if the attribute does not exist
235
   */
236
  public function getAttribute($name)
237
  {
238
    return isset($this->attributes[$name]) ? $this->attributes[$name] : null;
239
  }
240
 
241
  /**
242
   * Sets the HTML attributes.
243
   *
244
   * @param array $attributes  An array of HTML attributes
245
   *
246
   * @return sfWidget The current widget instance
247
   */
248
  public function setAttributes($attributes)
249
  {
250
    $this->attributes = $attributes;
251
 
252
    return $this;
253
  }
254
 
255
  /**
256
   * Gets the stylesheet paths associated with the widget.
257
   *
258
   * The array keys are files and values are the media names (separated by a ,):
259
   *
260
   *   array('/path/to/file.css' => 'all', '/another/file.css' => 'screen,print')
261
   *
262
   * @return array An array of stylesheet paths
263
   */
264
  public function getStylesheets()
265
  {
266
    return array();
267
  }
268
 
269
  /**
270
   * Gets the JavaScript paths associated with the widget.
271
   *
272
   * @return array An array of JavaScript paths
273
   */
274
  public function getJavaScripts()
275
  {
276
    return array();
277
  }
278
 
279
  /**
280
   * Sets the charset to use when rendering widgets.
281
   *
282
   * @param string $charset  The charset
283
   */
284
  static public function setCharset($charset)
285
  {
286
    self::$charset = $charset;
287
  }
288
 
289
  /**
290
   * Returns the charset to use when rendering widgets.
291
   *
292
   * @return string The charset (defaults to UTF-8)
293
   */
294
  static public function getCharset()
295
  {
296
    return self::$charset;
297
  }
298
 
299
  /**
300
   * Sets the XHTML generation flag.
301
   *
302
   * @param bool $boolean  true if widgets must be generated as XHTML, false otherwise
303
   */
304
  static public function setXhtml($boolean)
305
  {
306
    self::$xhtml = (boolean) $boolean;
307
  }
308
 
309
  /**
310
   * Returns whether to generate XHTML tags or not.
311
   *
312
   * @return bool true if widgets must be generated as XHTML, false otherwise
313
   */
314
  static public function isXhtml()
315
  {
316
    return self::$xhtml;
317
  }
318
 
319
  /**
320
   * Renders a HTML tag.
321
   *
322
   * @param string $tag         The tag name
323
   * @param array  $attributes  An array of HTML attributes to be merged with the default HTML attributes
324
   *
325
   * @param string An HTML tag string
326
   */
327
  public function renderTag($tag, $attributes = array())
328
  {
329
    if (empty($tag))
330
    {
331
      return '';
332
    }
333
 
334
    return sprintf('<%s%s%s', $tag, $this->attributesToHtml($attributes), self::$xhtml ? ' />' : (strtolower($tag) == 'input' ? '>' : sprintf('></%s>', $tag)));
335
  }
336
 
337
  /**
338
   * Renders a HTML content tag.
339
   *
340
   * @param string $tag         The tag name
341
   * @param string $content     The content of the tag
342
   * @param array  $attributes  An array of HTML attributes to be merged with the default HTML attributes
343
   *
344
   * @param string An HTML tag string
345
   */
346
  public function renderContentTag($tag, $content = null, $attributes = array())
347
  {
348
    if (empty($tag))
349
    {
350
      return '';
351
    }
352
 
353
    return sprintf('<%s%s>%s</%s>', $tag, $this->attributesToHtml($attributes), $content, $tag);
354
  }
355
 
356
  /**
357
   * Escapes a string.
358
   *
359
   * @param  string $value  string to escape
360
   * @return string escaped string
361
   */
362
  static public function escapeOnce($value)
363
  {
364
    return self::fixDoubleEscape(htmlspecialchars((string) $value, ENT_QUOTES, self::getCharset()));
365
  }
366
 
367
  /**
368
   * Fixes double escaped strings.
369
   *
370
   * @param  string $escaped  string to fix
371
   * @return string single escaped string
372
   */
373
  static public function fixDoubleEscape($escaped)
374
  {
375
    return preg_replace('/&amp;([a-z]+|(#\d+)|(#x[\da-f]+));/i', '&$1;', $escaped);
376
  }
377
 
378
  /**
379
   * Converts an array of attributes to its HTML representation.
380
   *
381
   * @param  array  $attributes An array of attributes
382
   *
383
   * @return string The HTML representation of the HTML attribute array.
384
   */
385
  public function attributesToHtml($attributes)
386
  {
387
    $attributes = array_merge($this->attributes, $attributes);
388
 
389
    return implode('', array_map(array($this, 'attributesToHtmlCallback'), array_keys($attributes), array_values($attributes)));
390
  }
391
 
392
  /**
393
   * Prepares an attribute key and value for HTML representation.
394
   *
395
   * It removes empty attributes, except for the value one.
396
   *
397
   * @param  string $k  The attribute key
398
   * @param  string $v  The attribute value
399
   *
400
   * @return string The HTML representation of the HTML key attribute pair.
401
   */
402
  protected function attributesToHtmlCallback($k, $v)
403
  {
404
    return false === $v || null === $v || ('' === $v && 'value' != $k) ? '' : sprintf(' %s="%s"', $k, $this->escapeOnce($v));
405
  }
406
}