Mercurial > hg > Members > shoshi > webvirt
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("&", "<", ">"), array("&amp;", "&lt;", "&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("&", "<", ">"), array("&amp;", "&lt;", "&gt;"), $this->__cleaned); | |
911 } | |
912 } |