comparison cake/libs/view/helper.php @ 0:261e66bd5a0c

hg init
author Shoshi TAMAKI <shoshi@cr.ie.u-ryukyu.ac.jp>
date Sun, 24 Jul 2011 21:08:31 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:261e66bd5a0c
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-2010, 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-2010, 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 */
26 App::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 */
35 class 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 }