source: Dev/branches/cakephp/cake/libs/view/helper.php @ 126

Last change on this file since 126 was 126, checked in by fpvanagthoven, 14 years ago

Cakephp branch.

File size: 24.9 KB
Line 
1<?php
2/**
3 * Backend for helpers.
4 *
5 * Internal methods for the Helpers.
6 *
7 * PHP versions 4 and 5
8 *
9 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
10 * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
11 *
12 * Licensed under The MIT License
13 * Redistributions of files must retain the above copyright notice.
14 *
15 * @copyright     Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
16 * @link          http://cakephp.org CakePHP(tm) Project
17 * @package       cake
18 * @subpackage    cake.cake.libs.view
19 * @since         CakePHP(tm) v 0.2.9
20 * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
21 */
22
23/**
24 * Included libs
25 */
26App::import('Core', 'Overloadable');
27
28/**
29 * Abstract base class for all other Helpers in CakePHP.
30 * Provides common methods and features.
31 *
32 * @package       cake
33 * @subpackage    cake.cake.libs.view
34 */
35class Helper extends Overloadable {
36
37/**
38 * List of helpers used by this helper
39 *
40 * @var array
41 */
42        var $helpers = null;
43
44/**
45 * Base URL
46 *
47 * @var string
48 */
49        var $base = null;
50
51/**
52 * Webroot path
53 *
54 * @var string
55 */
56        var $webroot = null;
57
58/**
59 * The current theme name if any.
60 *
61 * @var string
62 */
63        var $theme = null;
64
65/**
66 * URL to current action.
67 *
68 * @var string
69 */
70        var $here = null;
71
72/**
73 * Parameter array.
74 *
75 * @var array
76 */
77        var $params = array();
78
79/**
80 * Current action.
81 *
82 * @var string
83 */
84        var $action = null;
85
86/**
87 * Plugin path
88 *
89 * @var string
90 */
91        var $plugin = null;
92
93/**
94 * POST data for models
95 *
96 * @var array
97 */
98        var $data = null;
99
100/**
101 * List of named arguments
102 *
103 * @var array
104 */
105        var $namedArgs = null;
106
107/**
108 * URL argument separator character
109 *
110 * @var string
111 */
112        var $argSeparator = null;
113
114/**
115 * Contains model validation errors of form post-backs
116 *
117 * @access public
118 * @var array
119 */
120        var $validationErrors = null;
121
122/**
123 * Holds tag templates.
124 *
125 * @access public
126 * @var array
127 */
128        var $tags = array();
129
130/**
131 * Holds the content to be cleaned.
132 *
133 * @access private
134 * @var mixed
135 */
136        var $__tainted = null;
137
138/**
139 * Holds the cleaned content.
140 *
141 * @access private
142 * @var mixed
143 */
144        var $__cleaned = null;
145
146/**
147 * Default overload methods
148 *
149 * @access protected
150 */
151        function get__($name) {}
152        function set__($name, $value) {}
153        function call__($method, $params) {
154                trigger_error(sprintf(__('Method %1$s::%2$s does not exist', true), get_class($this), $method), E_USER_WARNING);
155        }
156
157/**
158 * Parses tag templates into $this->tags.
159 *
160 * @param $name file name inside app/config to load.
161 * @return array merged tags from config/$name.php
162 * @access public
163 */
164        function loadConfig($name = 'tags') {
165                if (file_exists(CONFIGS . $name .'.php')) {
166                        require(CONFIGS . $name .'.php');
167                        if (isset($tags)) {
168                                $this->tags = array_merge($this->tags, $tags);
169                        }
170                }
171                return $this->tags;
172        }
173
174/**
175 * Finds URL for specified action.
176 *
177 * Returns a URL pointing at the provided parameters.
178 *
179 * @param mixed $url Either a relative string url like `/products/view/23` or
180 *    an array of url parameters.  Using an array for urls will allow you to leverage
181 *    the reverse routing features of CakePHP.
182 * @param boolean $full If true, the full base URL will be prepended to the result
183 * @return string  Full translated URL with base path.
184 * @access public
185 * @link http://book.cakephp.org/view/1448/url
186 */
187        function url($url = null, $full = false) {
188                return h(Router::url($url, $full));
189        }
190
191/**
192 * Checks if a file exists when theme is used, if no file is found default location is returned
193 *
194 * @param string $file The file to create a webroot path to.
195 * @return string Web accessible path to file.
196 * @access public
197 */
198        function webroot($file) {
199                $asset = explode('?', $file);
200                $asset[1] = isset($asset[1]) ? '?' . $asset[1] : null;
201                $webPath = "{$this->webroot}" . $asset[0];
202                $file = $asset[0];
203
204                if (!empty($this->theme)) {
205                        $file = trim($file, '/');
206                        $theme = $this->theme . '/';
207
208                        if (DS === '\\') {
209                                $file = str_replace('/', '\\', $file);
210                        }
211
212                        if (file_exists(Configure::read('App.www_root') . 'theme' . DS . $this->theme . DS  . $file)) {
213                                $webPath = "{$this->webroot}theme/" . $theme . $asset[0];
214                        } else {
215                                $viewPaths = App::path('views');
216
217                                foreach ($viewPaths as $viewPath) {
218                                        $path = $viewPath . 'themed'. DS . $this->theme . DS  . 'webroot' . DS  . $file;
219
220                                        if (file_exists($path)) {
221                                                $webPath = "{$this->webroot}theme/" . $theme . $asset[0];
222                                                break;
223                                        }
224                                }
225                        }
226                }
227                if (strpos($webPath, '//') !== false) {
228                        return str_replace('//', '/', $webPath . $asset[1]);
229                }
230                return $webPath . $asset[1];
231        }
232
233/**
234 * Adds a timestamp to a file based resource based on the value of `Asset.timestamp` in
235 * Configure.  If Asset.timestamp is true and debug > 0, or Asset.timestamp == 'force'
236 * a timestamp will be added.
237 *
238 * @param string $path The file path to timestamp, the path must be inside WWW_ROOT
239 * @return string Path with a timestamp added, or not.
240 * @access public
241 */
242        function assetTimestamp($path) {
243                $timestampEnabled = (
244                        (Configure::read('Asset.timestamp') === true && Configure::read() > 0) ||
245                        Configure::read('Asset.timestamp') === 'force'
246                );
247                if (strpos($path, '?') === false && $timestampEnabled) {
248                        $filepath = preg_replace('/^' . preg_quote($this->webroot, '/') . '/', '', $path);
249                        $webrootPath = WWW_ROOT . str_replace('/', DS, $filepath);
250                        if (file_exists($webrootPath)) {
251                                return $path . '?' . @filemtime($webrootPath);
252                        }
253                        $segments = explode('/', ltrim($filepath, '/'));
254                        if ($segments[0] === 'theme') {
255                                $theme = $segments[1];
256                                unset($segments[0], $segments[1]);
257                                $themePath = App::themePath($theme) . 'webroot' . DS . implode(DS, $segments);
258                                return $path . '?' . @filemtime($themePath);
259                        } else {
260                                $plugin = $segments[0];
261                                unset($segments[0]);
262                                $pluginPath = App::pluginPath($plugin) . 'webroot' . DS . implode(DS, $segments);
263                                return $path . '?' . @filemtime($pluginPath);
264                        }
265                }
266                return $path;
267        }
268
269/**
270 * Used to remove harmful tags from content.  Removes a number of well known XSS attacks
271 * from content.  However, is not guaranteed to remove all possiblities.  Escaping
272 * content is the best way to prevent all possible attacks.
273 *
274 * @param mixed $output Either an array of strings to clean or a single string to clean.
275 * @return cleaned content for output
276 * @access public
277 */
278        function clean($output) {
279                $this->__reset();
280                if (empty($output)) {
281                        return null;
282                }
283                if (is_array($output)) {
284                        foreach ($output as $key => $value) {
285                                $return[$key] = $this->clean($value);
286                        }
287                        return $return;
288                }
289                $this->__tainted = $output;
290                $this->__clean();
291                return $this->__cleaned;
292        }
293
294/**
295 * Returns a space-delimited string with items of the $options array. If a
296 * key of $options array happens to be one of:
297 *
298 * - 'compact'
299 * - 'checked'
300 * - 'declare'
301 * - 'readonly'
302 * - 'disabled'
303 * - 'selected'
304 * - 'defer'
305 * - 'ismap'
306 * - 'nohref'
307 * - 'noshade'
308 * - 'nowrap'
309 * - 'multiple'
310 * - 'noresize'
311 *
312 * And its value is one of:
313 *
314 * - '1' (string)
315 * - 1 (integer)
316 * - true (boolean)
317 * - 'true' (string)
318 *
319 * Then the value will be reset to be identical with key's name.
320 * If the value is not one of these 3, the parameter is not output.
321 *
322 * 'escape' is a special option in that it controls the conversion of
323 *  attributes to their html-entity encoded equivalents.  Set to false to disable html-encoding.
324 *
325 * If value for any option key is set to `null` or `false`, that option will be excluded from output.
326 *
327 * @param array $options Array of options.
328 * @param array $exclude Array of options to be excluded, the options here will not be part of the return.
329 * @param string $insertBefore String to be inserted before options.
330 * @param string $insertAfter String to be inserted after options.
331 * @return string Composed attributes.
332 * @access public
333 */
334        function _parseAttributes($options, $exclude = null, $insertBefore = ' ', $insertAfter = null) {
335                if (is_array($options)) {
336                        $options = array_merge(array('escape' => true), $options);
337
338                        if (!is_array($exclude)) {
339                                $exclude = array();
340                        }
341                        $keys = array_diff(array_keys($options), array_merge($exclude, array('escape')));
342                        $values = array_intersect_key(array_values($options), $keys);
343                        $escape = $options['escape'];
344                        $attributes = array();
345
346                        foreach ($keys as $index => $key) {
347                                if ($values[$index] !== false && $values[$index] !== null) {
348                                        $attributes[] = $this->__formatAttribute($key, $values[$index], $escape);
349                                }
350                        }
351                        $out = implode(' ', $attributes);
352                } else {
353                        $out = $options;
354                }
355                return $out ? $insertBefore . $out . $insertAfter : '';
356        }
357
358/**
359 * Formats an individual attribute, and returns the string value of the composed attribute.
360 * Works with minimized attributes that have the same value as their name such as 'disabled' and 'checked'
361 *
362 * @param string $key The name of the attribute to create
363 * @param string $value The value of the attribute to create.
364 * @return string The composed attribute.
365 * @access private
366 */
367        function __formatAttribute($key, $value, $escape = true) {
368                $attribute = '';
369                $attributeFormat = '%s="%s"';
370                $minimizedAttributes = array('compact', 'checked', 'declare', 'readonly', 'disabled',
371                        'selected', 'defer', 'ismap', 'nohref', 'noshade', 'nowrap', 'multiple', 'noresize');
372                if (is_array($value)) {
373                        $value = '';
374                }
375
376                if (in_array($key, $minimizedAttributes)) {
377                        if ($value === 1 || $value === true || $value === 'true' || $value === '1' || $value == $key) {
378                                $attribute = sprintf($attributeFormat, $key, $key);
379                        }
380                } else {
381                        $attribute = sprintf($attributeFormat, $key, ($escape ? h($value) : $value));
382                }
383                return $attribute;
384        }
385
386/**
387 * Sets this helper's model and field properties to the dot-separated value-pair in $entity.
388 *
389 * @param mixed $entity A field name, like "ModelName.fieldName" or "ModelName.ID.fieldName"
390 * @param boolean $setScope Sets the view scope to the model specified in $tagValue
391 * @return void
392 * @access public
393 */
394        function setEntity($entity, $setScope = false) {
395                $view =& ClassRegistry::getObject('view');
396
397                if ($setScope) {
398                        $view->modelScope = false;
399                } elseif (!empty($view->entityPath) && $view->entityPath == $entity) {
400                        return;
401                }
402
403                if ($entity === null) {
404                        $view->model = null;
405                        $view->association = null;
406                        $view->modelId = null;
407                        $view->modelScope = false;
408                        $view->entityPath = null;
409                        return;
410                }
411
412                $view->entityPath = $entity;
413                $model = $view->model;
414                $sameScope = $hasField = false;
415                $parts = array_values(Set::filter(explode('.', $entity), true));
416
417                if (empty($parts)) {
418                        return;
419                }
420
421                $count = count($parts);
422                if ($count === 1) {
423                        $sameScope = true;
424                } else {
425                        if (is_numeric($parts[0])) {
426                                $sameScope = true;
427                        }
428                        $reverse = array_reverse($parts);
429                        $field = array_shift($reverse);
430                        while(!empty($reverse)) {
431                                $subject = array_shift($reverse);
432                                if (is_numeric($subject)) {
433                                        continue;
434                                }
435                                if (ClassRegistry::isKeySet($subject)) {
436                                        $model = $subject;
437                                        break;
438                                }
439                        }
440                }
441
442                if (ClassRegistry::isKeySet($model)) {
443                        $ModelObj =& ClassRegistry::getObject($model);
444                        for ($i = 0; $i < $count; $i++) {
445                                if (
446                                        is_a($ModelObj, 'Model') &&
447                                        ($ModelObj->hasField($parts[$i]) ||
448                                        array_key_exists($parts[$i], $ModelObj->validate))
449                                ) {
450                                        $hasField = $i;
451                                        if ($hasField === 0 || ($hasField === 1 && is_numeric($parts[0]))) {
452                                                $sameScope = true;
453                                        }
454                                        break;
455                                }
456                        }
457
458                        if ($sameScope === true && in_array($parts[0], array_keys($ModelObj->hasAndBelongsToMany))) {
459                                $sameScope = false;
460                        }
461                }
462
463                if (!$view->association && $parts[0] == $view->field && $view->field != $view->model) {
464                        array_unshift($parts, $model);
465                        $hasField = true;
466                }
467                $view->field = $view->modelId = $view->fieldSuffix = $view->association = null;
468
469                switch (count($parts)) {
470                        case 1:
471                                if ($view->modelScope === false) {
472                                        $view->model = $parts[0];
473                                } else {
474                                        $view->field = $parts[0];
475                                        if ($sameScope === false) {
476                                                $view->association = $parts[0];
477                                        }
478                                }
479                        break;
480                        case 2:
481                                if ($view->modelScope === false) {
482                                        list($view->model, $view->field) = $parts;
483                                } elseif ($sameScope === true && $hasField === 0) {
484                                        list($view->field, $view->fieldSuffix) = $parts;
485                                } elseif ($sameScope === true && $hasField === 1) {
486                                        list($view->modelId, $view->field) = $parts;
487                                } else {
488                                        list($view->association, $view->field) = $parts;
489                                }
490                        break;
491                        case 3:
492                                if ($sameScope === true && $hasField === 1) {
493                                        list($view->modelId, $view->field, $view->fieldSuffix) = $parts;
494                                } elseif ($hasField === 2) {
495                                        list($view->association, $view->modelId, $view->field) = $parts;
496                                } else {
497                                        list($view->association, $view->field, $view->fieldSuffix) = $parts;
498                                }
499                        break;
500                        case 4:
501                                if ($parts[0] === $view->model) {
502                                        list($view->model, $view->modelId, $view->field, $view->fieldSuffix) = $parts;
503                                } else {
504                                        list($view->association, $view->modelId, $view->field, $view->fieldSuffix) = $parts;
505                                }
506                        break;
507                        default:
508                                $reverse = array_reverse($parts);
509
510                                if ($hasField) {
511                                                $view->field = $field;
512                                                if (!is_numeric($reverse[1]) && $reverse[1] != $model) {
513                                                        $view->field = $reverse[1];
514                                                        $view->fieldSuffix = $field;
515                                                }
516                                }
517                                if (is_numeric($parts[0])) {
518                                        $view->modelId = $parts[0];
519                                } elseif ($view->model == $parts[0] && is_numeric($parts[1])) {
520                                        $view->modelId = $parts[1];
521                                }
522                                $view->association = $model;
523                        break;
524                }
525
526                if (!isset($view->model) || empty($view->model)) {
527                        $view->model = $view->association;
528                        $view->association = null;
529                } elseif ($view->model === $view->association) {
530                        $view->association = null;
531                }
532
533                if ($setScope) {
534                        $view->modelScope = true;
535                }
536        }
537
538/**
539 * Gets the currently-used model of the rendering context.
540 *
541 * @return string
542 * @access public
543 */
544        function model() {
545                $view =& ClassRegistry::getObject('view');
546                if (!empty($view->association)) {
547                        return $view->association;
548                } else {
549                        return $view->model;
550                }
551        }
552
553/**
554 * Gets the ID of the currently-used model of the rendering context.
555 *
556 * @return mixed
557 * @access public
558 */
559        function modelID() {
560                $view =& ClassRegistry::getObject('view');
561                return $view->modelId;
562        }
563
564/**
565 * Gets the currently-used model field of the rendering context.
566 *
567 * @return string
568 * @access public
569 */
570        function field() {
571                $view =& ClassRegistry::getObject('view');
572                return $view->field;
573        }
574
575/**
576 * Returns false if given FORM field has no errors. Otherwise it returns the constant set in
577 * the array Model->validationErrors.
578 *
579 * @param string $model Model name as a string
580 * @param string $field Fieldname as a string
581 * @param integer $modelID Unique index identifying this record within the form
582 * @return boolean True on errors.
583 */
584        function tagIsInvalid($model = null, $field = null, $modelID = null) {
585                $view =& ClassRegistry::getObject('view');
586                $errors = $this->validationErrors;
587                $entity = $view->entity();
588                if (!empty($entity)) {
589                        return Set::extract($errors, join('.', $entity));
590                }
591        }
592
593/**
594 * Generates a DOM ID for the selected element, if one is not set.
595 * Uses the current View::entity() settings to generate a CamelCased id attribute.
596 *
597 * @param mixed $options Either an array of html attributes to add $id into, or a string
598 *   with a view entity path to get a domId for.
599 * @param string $id The name of the 'id' attribute.
600 * @return mixed If $options was an array, an array will be returned with $id set.  If a string
601 *   was supplied, a string will be returned.
602 * @todo Refactor this method to not have as many input/output options.
603 */
604        function domId($options = null, $id = 'id') {
605                $view =& ClassRegistry::getObject('view');
606
607                if (is_array($options) && array_key_exists($id, $options) && $options[$id] === null) {
608                        unset($options[$id]);
609                        return $options;
610                } elseif (!is_array($options) && $options !== null) {
611                        $this->setEntity($options);
612                        return $this->domId();
613                }
614
615                $entity = $view->entity();
616                $model = array_shift($entity);
617                $dom = $model . join('', array_map(array('Inflector', 'camelize'), $entity));
618
619                if (is_array($options) && !array_key_exists($id, $options)) {
620                        $options[$id] = $dom;
621                } elseif ($options === null) {
622                        return $dom;
623                }
624                return $options;
625        }
626
627/**
628 * Gets the input field name for the current tag. Creates input name attributes
629 * using CakePHP's data[Model][field] formatting.
630 *
631 * @param mixed $options If an array, should be an array of attributes that $key needs to be added to.
632 *   If a string or null, will be used as the View entity.
633 * @param string $field
634 * @param string $key The name of the attribute to be set, defaults to 'name'
635 * @return mixed If an array was given for $options, an array with $key set will be returned.
636 *   If a string was supplied a string will be returned.
637 * @access protected
638 * @todo Refactor this method to not have as many input/output options.
639 */
640        function _name($options = array(), $field = null, $key = 'name') {
641                $view =& ClassRegistry::getObject('view');
642                if ($options === null) {
643                        $options = array();
644                } elseif (is_string($options)) {
645                        $field = $options;
646                        $options = 0;
647                }
648
649                if (!empty($field)) {
650                        $this->setEntity($field);
651                }
652
653                if (is_array($options) && array_key_exists($key, $options)) {
654                        return $options;
655                }
656
657                switch ($field) {
658                        case '_method':
659                                $name = $field;
660                        break;
661                        default:
662                                $name = 'data[' . implode('][', $view->entity()) . ']';
663                        break;
664                }
665
666                if (is_array($options)) {
667                        $options[$key] = $name;
668                        return $options;
669                } else {
670                        return $name;
671                }
672        }
673
674/**
675 * Gets the data for the current tag
676 *
677 * @param mixed $options If an array, should be an array of attributes that $key needs to be added to.
678 *   If a string or null, will be used as the View entity.
679 * @param string $field
680 * @param string $key The name of the attribute to be set, defaults to 'value'
681 * @return mixed If an array was given for $options, an array with $key set will be returned.
682 *   If a string was supplied a string will be returned.
683 * @access public
684 * @todo Refactor this method to not have as many input/output options.
685 */
686        function value($options = array(), $field = null, $key = 'value') {
687                if ($options === null) {
688                        $options = array();
689                } elseif (is_string($options)) {
690                        $field = $options;
691                        $options = 0;
692                }
693
694                if (is_array($options) && isset($options[$key])) {
695                        return $options;
696                }
697
698                if (!empty($field)) {
699                        $this->setEntity($field);
700                }
701
702                $view =& ClassRegistry::getObject('view');
703                $result = null;
704
705                $entity = $view->entity();
706                if (!empty($this->data) && !empty($entity)) {
707                        $result = Set::extract($this->data, join('.', $entity));
708                }
709
710                $habtmKey = $this->field();
711                if (empty($result) && isset($this->data[$habtmKey][$habtmKey]) && is_array($this->data[$habtmKey])) {
712                        $result = $this->data[$habtmKey][$habtmKey];
713                } elseif (empty($result) && isset($this->data[$habtmKey]) && is_array($this->data[$habtmKey])) {
714                        if (ClassRegistry::isKeySet($habtmKey)) {
715                                $model =& ClassRegistry::getObject($habtmKey);
716                                $result = $this->__selectedArray($this->data[$habtmKey], $model->primaryKey);
717                        }
718                }
719
720                if (is_array($result)) {
721                        if (array_key_exists($view->fieldSuffix, $result)) {
722                                $result = $result[$view->fieldSuffix];
723                        }
724                }
725
726                if (is_array($options)) {
727                        if ($result === null && isset($options['default'])) {
728                                $result = $options['default'];
729                        }
730                        unset($options['default']);
731                }
732
733                if (is_array($options)) {
734                        $options[$key] = $result;
735                        return $options;
736                } else {
737                        return $result;
738                }
739        }
740
741/**
742 * Sets the defaults for an input tag.  Will set the
743 * name, value, and id attributes for an array of html attributes. Will also
744 * add a 'form-error' class if the field contains validation errors.
745 *
746 * @param string $field The field name to initialize.
747 * @param array $options Array of options to use while initializing an input field.
748 * @return array Array options for the form input.
749 * @access protected
750 */
751        function _initInputField($field, $options = array()) {
752                if ($field !== null) {
753                        $this->setEntity($field);
754                }
755                $options = (array)$options;
756                $options = $this->_name($options);
757                $options = $this->value($options);
758                $options = $this->domId($options);
759                if ($this->tagIsInvalid()) {
760                        $options = $this->addClass($options, 'form-error');
761                }
762                return $options;
763        }
764
765/**
766 * Adds the given class to the element options
767 *
768 * @param array $options Array options/attributes to add a class to
769 * @param string $class The classname being added.
770 * @param string $key the key to use for class.
771 * @return array Array of options with $key set.
772 * @access public
773 */
774        function addClass($options = array(), $class = null, $key = 'class') {
775                if (isset($options[$key]) && trim($options[$key]) != '') {
776                        $options[$key] .= ' ' . $class;
777                } else {
778                        $options[$key] = $class;
779                }
780                return $options;
781        }
782
783/**
784 * Returns a string generated by a helper method
785 *
786 * This method can be overridden in subclasses to do generalized output post-processing
787 *
788 * @param string $str String to be output.
789 * @return string
790 * @deprecated This method will be removed in future versions.
791 */
792        function output($str) {
793                return $str;
794        }
795
796/**
797 * Before render callback. beforeRender is called before the view file is rendered.
798 *
799 * Overridden in subclasses.
800 *
801 * @return void
802 * @access public
803 */
804        function beforeRender() {
805        }
806
807/**
808 * After render callback.  afterRender is called after the view file is rendered
809 * but before the layout has been rendered.
810 *
811 * Overridden in subclasses.
812 *
813 * @return void
814 * @access public
815 */
816        function afterRender() {
817        }
818
819/**
820 * Before layout callback.  beforeLayout is called before the layout is rendered.
821 *
822 * Overridden in subclasses.
823 *
824 * @return void
825 * @access public
826 */
827        function beforeLayout() {
828        }
829
830/**
831 * After layout callback.  afterLayout is called after the layout has rendered.
832 *
833 * Overridden in subclasses.
834 *
835 * @return void
836 * @access public
837 */
838        function afterLayout() {
839        }
840
841/**
842 * Transforms a recordset from a hasAndBelongsToMany association to a list of selected
843 * options for a multiple select element
844 *
845 * @param mixed $data
846 * @param string $key
847 * @return array
848 * @access private
849 */
850        function __selectedArray($data, $key = 'id') {
851                if (!is_array($data)) {
852                        $model = $data;
853                        if (!empty($this->data[$model][$model])) {
854                                return $this->data[$model][$model];
855                        }
856                        if (!empty($this->data[$model])) {
857                                $data = $this->data[$model];
858                        }
859                }
860                $array = array();
861                if (!empty($data)) {
862                        foreach ($data as $var) {
863                                $array[$var[$key]] = $var[$key];
864                        }
865                }
866                return $array;
867        }
868
869/**
870 * Resets the vars used by Helper::clean() to null
871 *
872 * @return void
873 * @access private
874 */
875        function __reset() {
876                $this->__tainted = null;
877                $this->__cleaned = null;
878        }
879
880/**
881 * Removes harmful content from output
882 *
883 * @return void
884 * @access private
885 */
886        function __clean() {
887                if (get_magic_quotes_gpc()) {
888                        $this->__cleaned = stripslashes($this->__tainted);
889                } else {
890                        $this->__cleaned = $this->__tainted;
891                }
892
893                $this->__cleaned = str_replace(array("&amp;", "&lt;", "&gt;"), array("&amp;amp;", "&amp;lt;", "&amp;gt;"), $this->__cleaned);
894                $this->__cleaned = preg_replace('#(&\#*\w+)[\x00-\x20]+;#u', "$1;", $this->__cleaned);
895                $this->__cleaned = preg_replace('#(&\#x*)([0-9A-F]+);*#iu', "$1$2;", $this->__cleaned);
896                $this->__cleaned = html_entity_decode($this->__cleaned, ENT_COMPAT, "UTF-8");
897                $this->__cleaned = preg_replace('#(<[^>]+[\x00-\x20\"\'\/])(on|xmlns)[^>]*>#iUu', "$1>", $this->__cleaned);
898                $this->__cleaned = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([\`\'\"]*)[\\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iUu', '$1=$2nojavascript...', $this->__cleaned);
899                $this->__cleaned = preg_replace('#([a-z]*)[\x00-\x20]*=([\'\"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iUu', '$1=$2novbscript...', $this->__cleaned);
900                $this->__cleaned = preg_replace('#([a-z]*)[\x00-\x20]*=*([\'\"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#iUu','$1=$2nomozbinding...', $this->__cleaned);
901                $this->__cleaned = preg_replace('#([a-z]*)[\x00-\x20]*=([\'\"]*)[\x00-\x20]*data[\x00-\x20]*:#Uu', '$1=$2nodata...', $this->__cleaned);
902                $this->__cleaned = preg_replace('#(<[^>]+)style[\x00-\x20]*=[\x00-\x20]*([\`\'\"]*).*expression[\x00-\x20]*\([^>]*>#iU', "$1>", $this->__cleaned);
903                $this->__cleaned = preg_replace('#(<[^>]+)style[\x00-\x20]*=[\x00-\x20]*([\`\'\"]*).*behaviour[\x00-\x20]*\([^>]*>#iU', "$1>", $this->__cleaned);
904                $this->__cleaned = preg_replace('#(<[^>]+)style[\x00-\x20]*=[\x00-\x20]*([\`\'\"]*).*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*>#iUu', "$1>", $this->__cleaned);
905                $this->__cleaned = preg_replace('#</*\w+:\w[^>]*>#i', "", $this->__cleaned);
906                do {
907                        $oldstring = $this->__cleaned;
908                        $this->__cleaned = preg_replace('#</*(applet|meta|xml|blink|link|style|script|embed|object|iframe|frame|frameset|ilayer|layer|bgsound|title|base)[^>]*>#i', "", $this->__cleaned);
909                } while ($oldstring != $this->__cleaned);
910                $this->__cleaned = str_replace(array("&amp;", "&lt;", "&gt;"), array("&amp;amp;", "&amp;lt;", "&amp;gt;"), $this->__cleaned);
911        }
912}
Note: See TracBrowser for help on using the repository browser.