00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 App::import('Core', array('Helper', 'ClassRegistry'));
00029
00030
00031
00032
00033
00034
00035
00036
00037 class View extends Object {
00038
00039
00040
00041
00042
00043
00044 var $base = null;
00045
00046
00047
00048
00049
00050 var $here = null;
00051
00052
00053
00054
00055
00056
00057 var $plugin = null;
00058
00059
00060
00061
00062
00063
00064 var $name = null;
00065
00066
00067
00068
00069
00070
00071 var $action = null;
00072
00073
00074
00075
00076
00077 var $params = array();
00078
00079
00080
00081
00082
00083 var $passedArgs = array();
00084
00085
00086
00087
00088
00089 var $data = array();
00090
00091
00092
00093
00094
00095
00096 var $helpers = array('Html');
00097
00098
00099
00100
00101
00102 var $viewPath = null;
00103
00104
00105
00106
00107
00108
00109 var $viewVars = array();
00110
00111
00112
00113
00114
00115
00116 var $layout = 'default';
00117
00118
00119
00120
00121
00122 var $layoutPath = null;
00123
00124
00125
00126
00127
00128
00129 var $pageTitle = false;
00130
00131
00132
00133
00134
00135
00136 var $autoRender = true;
00137
00138
00139
00140
00141
00142
00143 var $autoLayout = true;
00144
00145
00146
00147
00148
00149 var $ext = '.ctp';
00150
00151
00152
00153
00154
00155 var $subDir = null;
00156
00157
00158
00159
00160
00161 var $themeWeb = null;
00162
00163
00164
00165
00166
00167
00168
00169 var $cacheAction = false;
00170
00171
00172
00173
00174
00175 var $validationErrors = array();
00176
00177
00178
00179
00180
00181 var $hasRendered = false;
00182
00183
00184
00185
00186
00187 var $loaded = array();
00188
00189
00190
00191
00192
00193 var $modelScope = false;
00194
00195
00196
00197
00198
00199 var $model = null;
00200
00201
00202
00203
00204
00205 var $association = null;
00206
00207
00208
00209
00210
00211 var $field = null;
00212
00213
00214
00215
00216
00217 var $fieldSuffix = null;
00218
00219
00220
00221
00222
00223 var $modelId = null;
00224
00225
00226
00227
00228
00229 var $uuids = array();
00230
00231
00232
00233
00234
00235 var $output = false;
00236
00237
00238
00239
00240
00241
00242 var $__passedVars = array(
00243 'viewVars', 'action', 'autoLayout', 'autoRender', 'ext', 'base', 'webroot',
00244 'helpers', 'here', 'layout', 'name', 'pageTitle', 'layoutPath', 'viewPath',
00245 'params', 'data', 'plugin', 'passedArgs', 'cacheAction'
00246 );
00247
00248
00249
00250
00251
00252
00253 var $__scripts = array();
00254
00255
00256
00257
00258
00259 var $__paths = array();
00260
00261
00262
00263
00264
00265 function __construct(&$controller, $register = true) {
00266 if (is_object($controller)) {
00267 $count = count($this->__passedVars);
00268 for ($j = 0; $j < $count; $j++) {
00269 $var = $this->__passedVars[$j];
00270 $this->{$var} = $controller->{$var};
00271 }
00272 }
00273 parent::__construct();
00274
00275 if ($register) {
00276 ClassRegistry::addObject('view', $this);
00277 }
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 function element($name, $params = array(), $loadHelpers = false) {
00299 $file = $plugin = $key = null;
00300
00301 if (isset($params['plugin'])) {
00302 $plugin = $params['plugin'];
00303 }
00304
00305 if (isset($this->plugin) && !$plugin) {
00306 $plugin = $this->plugin;
00307 }
00308
00309 if (isset($params['cache'])) {
00310 $expires = '+1 day';
00311
00312 if (is_array($params['cache'])) {
00313 $expires = $params['cache']['time'];
00314 $key = Inflector::slug($params['cache']['key']);
00315 } elseif ($params['cache'] !== true) {
00316 $expires = $params['cache'];
00317 $key = implode('_', array_keys($params));
00318 }
00319
00320 if ($expires) {
00321 $cacheFile = 'element_' . $key . '_' . $plugin . Inflector::slug($name);
00322 $cache = cache('views' . DS . $cacheFile, null, $expires);
00323
00324 if (is_string($cache)) {
00325 return $cache;
00326 }
00327 }
00328 }
00329 $paths = $this->_paths($plugin);
00330
00331 foreach ($paths as $path) {
00332 if (file_exists($path . 'elements' . DS . $name . $this->ext)) {
00333 $file = $path . 'elements' . DS . $name . $this->ext;
00334 break;
00335 } elseif (file_exists($path . 'elements' . DS . $name . '.thtml')) {
00336 $file = $path . 'elements' . DS . $name . '.thtml';
00337 break;
00338 }
00339 }
00340
00341 if (is_file($file)) {
00342 $params = array_merge_recursive($params, $this->loaded);
00343 $element = $this->_render($file, array_merge($this->viewVars, $params), $loadHelpers);
00344 if (isset($params['cache']) && isset($cacheFile) && isset($expires)) {
00345 cache('views' . DS . $cacheFile, $element, $expires);
00346 }
00347 return $element;
00348 }
00349 $file = $paths[0] . 'elements' . DS . $name . $this->ext;
00350
00351 if (Configure::read() > 0) {
00352 return "Not Found: " . $file;
00353 }
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 function render($action = null, $layout = null, $file = null) {
00365 if ($this->hasRendered) {
00366 return true;
00367 }
00368 $out = null;
00369
00370 if ($file != null) {
00371 $action = $file;
00372 }
00373
00374 if ($action !== false && $viewFileName = $this->_getViewFileName($action)) {
00375 if (substr($viewFileName, -3) === 'ctp' || substr($viewFileName, -5) === 'thtml') {
00376 $out = View::_render($viewFileName, $this->viewVars);
00377 } else {
00378 $out = $this->_render($viewFileName, $this->viewVars);
00379 }
00380 }
00381
00382 if ($layout === null) {
00383 $layout = $this->layout;
00384 }
00385
00386 if ($out !== false) {
00387 if ($layout && $this->autoLayout) {
00388 $out = $this->renderLayout($out, $layout);
00389 $isCached = (
00390 isset($this->loaded['cache']) &&
00391 (($this->cacheAction != false)) && (Configure::read('Cache.check') === true)
00392 );
00393
00394 if ($isCached) {
00395 $replace = array('<cake:nocache>', '</cake:nocache>');
00396 $out = str_replace($replace, '', $out);
00397 }
00398 }
00399 $this->hasRendered = true;
00400 } else {
00401 $out = $this->_render($viewFileName, $this->viewVars);
00402 $msg = __("Error in view %s, got: <blockquote>%s</blockquote>", true);
00403 trigger_error(sprintf($msg, $viewFileName, $out), E_USER_ERROR);
00404 }
00405 return $out;
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 function renderLayout($content_for_layout, $layout = null) {
00419 $layoutFileName = $this->_getLayoutFileName($layout);
00420 if (empty($layoutFileName)) {
00421 return $this->output;
00422 }
00423
00424 $debug = '';
00425
00426 if (isset($this->viewVars['cakeDebug']) && Configure::read() > 2) {
00427 $params = array('controller' => $this->viewVars['cakeDebug']);
00428 $debug = View::element('dump', $params, false);
00429 unset($this->viewVars['cakeDebug']);
00430 }
00431
00432 if ($this->pageTitle !== false) {
00433 $pageTitle = $this->pageTitle;
00434 } else {
00435 $pageTitle = Inflector::humanize($this->viewPath);
00436 }
00437 $data_for_layout = array_merge($this->viewVars, array(
00438 'title_for_layout' => $pageTitle,
00439 'content_for_layout' => $content_for_layout,
00440 'scripts_for_layout' => join("\n\t", $this->__scripts),
00441 'cakeDebug' => $debug
00442 ));
00443
00444 if (empty($this->loaded) && !empty($this->helpers)) {
00445 $loadHelpers = true;
00446 } else {
00447 $loadHelpers = false;
00448 $data_for_layout = array_merge($data_for_layout, $this->loaded);
00449 }
00450
00451 $this->_triggerHelpers('beforeLayout');
00452
00453 if (substr($layoutFileName, -3) === 'ctp' || substr($layoutFileName, -5) === 'thtml') {
00454 $this->output = View::_render($layoutFileName, $data_for_layout, $loadHelpers, true);
00455 } else {
00456 $this->output = $this->_render($layoutFileName, $data_for_layout, $loadHelpers);
00457 }
00458
00459 if ($this->output === false) {
00460 $this->output = $this->_render($layoutFileName, $data_for_layout);
00461 $msg = __("Error in layout %s, got: <blockquote>%s</blockquote>", true);
00462 trigger_error(sprintf($msg, $layoutFileName, $this->output), E_USER_ERROR);
00463 return false;
00464 }
00465
00466 $this->_triggerHelpers('afterLayout');
00467
00468 return $this->output;
00469 }
00470
00471
00472
00473
00474
00475
00476
00477 function _triggerHelpers($callback) {
00478 if (empty($this->loaded)) {
00479 return false;
00480 }
00481 $helpers = array_keys($this->loaded);
00482 foreach ($helpers as $helperName) {
00483 $helper =& $this->loaded[$helperName];
00484 if (is_object($helper)) {
00485 if (is_subclass_of($helper, 'Helper')) {
00486 $helper->{$callback}();
00487 }
00488 }
00489 }
00490 }
00491
00492
00493
00494
00495
00496
00497 function renderCache($filename, $timeStart) {
00498 ob_start();
00499 include ($filename);
00500
00501 if (Configure::read() > 0 && $this->layout != 'xml') {
00502 echo "<!-- Cached Render Time: " . round(getMicrotime() - $timeStart, 4) . "s -->";
00503 }
00504 $out = ob_get_clean();
00505
00506 if (preg_match('/^<!--cachetime:(\\d+)-->/', $out, $match)) {
00507 if (time() >= $match['1']) {
00508 @unlink($filename);
00509 unset ($out);
00510 return false;
00511 } else {
00512 if ($this->layout === 'xml') {
00513 header('Content-type: text/xml');
00514 }
00515 echo str_replace('<!--cachetime:' . $match['1'] . '-->', '', $out);
00516 return true;
00517 }
00518 }
00519 }
00520
00521
00522
00523
00524
00525
00526 function getVars() {
00527 return array_keys($this->viewVars);
00528 }
00529
00530
00531
00532
00533
00534
00535 function getVar($var) {
00536 if (!isset($this->viewVars[$var])) {
00537 return null;
00538 } else {
00539 return $this->viewVars[$var];
00540 }
00541 }
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551 function addScript($name, $content = null) {
00552 if (empty($content)) {
00553 if (!in_array($name, array_values($this->__scripts))) {
00554 $this->__scripts[] = $name;
00555 }
00556 } else {
00557 $this->__scripts[$name] = $content;
00558 }
00559 }
00560
00561
00562
00563
00564
00565
00566
00567
00568 function uuid($object, $url) {
00569 $c = 1;
00570 $url = Router::url($url);
00571 $hash = $object . substr(md5($object . $url), 0, 10);
00572 while (in_array($hash, $this->uuids)) {
00573 $hash = $object . substr(md5($object . $url . $c), 0, 10);
00574 $c++;
00575 }
00576 $this->uuids[] = $hash;
00577 return $hash;
00578 }
00579
00580
00581
00582
00583
00584 function entity() {
00585 $assoc = ($this->association) ? $this->association : $this->model;
00586 return array_values(Set::filter(
00587 array($assoc, $this->modelId, $this->field, $this->fieldSuffix)
00588 ));
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 function set($one, $two = null) {
00601 $data = null;
00602 if (is_array($one)) {
00603 if (is_array($two)) {
00604 $data = array_combine($one, $two);
00605 } else {
00606 $data = $one;
00607 }
00608 } else {
00609 $data = array($one => $two);
00610 }
00611
00612 if ($data == null) {
00613 return false;
00614 }
00615
00616 foreach ($data as $name => $value) {
00617 if ($name == 'title') {
00618 $this->pageTitle = $value;
00619 } else {
00620 $this->viewVars[$name] = $value;
00621 }
00622 }
00623 }
00624
00625
00626
00627
00628
00629
00630
00631 function error($code, $name, $message) {
00632 header ("HTTP/1.1 {$code} {$name}");
00633 print ($this->_render(
00634 $this->_getLayoutFileName('error'),
00635 array('code' => $code, 'name' => $name, 'message' => $message)
00636 ));
00637 }
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647 function _render($___viewFn, $___dataForView, $loadHelpers = true, $cached = false) {
00648 $loadedHelpers = array();
00649
00650 if ($this->helpers != false && $loadHelpers === true) {
00651 $loadedHelpers = $this->_loadHelpers($loadedHelpers, $this->helpers);
00652
00653 foreach (array_keys($loadedHelpers) as $helper) {
00654 $camelBackedHelper = Inflector::variable($helper);
00655 ${$camelBackedHelper} =& $loadedHelpers[$helper];
00656 $this->loaded[$camelBackedHelper] =& ${$camelBackedHelper};
00657 }
00658
00659 $this->_triggerHelpers('beforeRender');
00660 }
00661
00662 extract($___dataForView, EXTR_SKIP);
00663 ob_start();
00664
00665 if (Configure::read() > 0) {
00666 include ($___viewFn);
00667 } else {
00668 @include ($___viewFn);
00669 }
00670
00671 if ($loadHelpers === true) {
00672 $this->_triggerHelpers('afterRender');
00673 }
00674
00675 $out = ob_get_clean();
00676 $caching = (
00677 isset($this->loaded['cache']) &&
00678 (($this->cacheAction != false)) && (Configure::read('Cache.check') === true)
00679 );
00680
00681 if ($caching) {
00682 if (is_a($this->loaded['cache'], 'CacheHelper')) {
00683 $cache =& $this->loaded['cache'];
00684 $cache->base = $this->base;
00685 $cache->here = $this->here;
00686 $cache->helpers = $this->helpers;
00687 $cache->action = $this->action;
00688 $cache->controllerName = $this->name;
00689 $cache->layout = $this->layout;
00690 $cache->cacheAction = $this->cacheAction;
00691 $cache->cache($___viewFn, $out, $cached);
00692 }
00693 }
00694 return $out;
00695 }
00696
00697
00698
00699
00700
00701
00702
00703
00704 function &_loadHelpers(&$loaded, $helpers, $parent = null) {
00705 if (empty($loaded)) {
00706 $helpers[] = 'Session';
00707 }
00708
00709 foreach ($helpers as $i => $helper) {
00710 $options = array();
00711
00712 if (!is_int($i)) {
00713 $options = $helper;
00714 $helper = $i;
00715 }
00716 $plugin = $this->plugin;
00717
00718 if (strpos($helper, '.') !== false) {
00719 list($plugin, $helper) = explode('.', $helper);
00720 }
00721 $helperCn = $helper . 'Helper';
00722
00723 if (!isset($loaded[$helper])) {
00724 if (!class_exists($helperCn)) {
00725 $isLoaded = false;
00726 if (!is_null($plugin)) {
00727 $isLoaded = App::import('Helper', $plugin . '.' . $helper);
00728 }
00729 if (!$isLoaded) {
00730 if (!App::import('Helper', $helper)) {
00731 $this->cakeError('missingHelperFile', array(array(
00732 'helper' => $helper,
00733 'file' => Inflector::underscore($helper) . '.php',
00734 'base' => $this->base
00735 )));
00736 return false;
00737 }
00738 }
00739 if (!class_exists($helperCn)) {
00740 $this->cakeError('missingHelperClass', array(array(
00741 'helper' => $helper,
00742 'file' => Inflector::underscore($helper) . '.php',
00743 'base' => $this->base
00744 )));
00745 return false;
00746 }
00747 }
00748 $loaded[$helper] =& new $helperCn($options);
00749 $vars = array(
00750 'base', 'webroot', 'here', 'params', 'action', 'data', 'themeWeb', 'plugin'
00751 );
00752 $c = count($vars);
00753
00754 for ($j = 0; $j < $c; $j++) {
00755 $loaded[$helper]->{$vars[$j]} = $this->{$vars[$j]};
00756 }
00757
00758 if (!empty($this->validationErrors)) {
00759 $loaded[$helper]->validationErrors = $this->validationErrors;
00760 }
00761 if (is_array($loaded[$helper]->helpers) && !empty($loaded[$helper]->helpers)) {
00762 $loaded =& $this->_loadHelpers($loaded, $loaded[$helper]->helpers, $helper);
00763 }
00764 }
00765 if (isset($loaded[$parent])) {
00766 $loaded[$parent]->{$helper} =& $loaded[$helper];
00767 }
00768 }
00769 return $loaded;
00770 }
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780 function _getViewFileName($name = null) {
00781 $subDir = null;
00782
00783 if (!is_null($this->subDir)) {
00784 $subDir = $this->subDir . DS;
00785 }
00786
00787 if ($name === null) {
00788 $name = $this->action;
00789 }
00790 $name = str_replace('/', DS, $name);
00791
00792 if (strpos($name, DS) === false && $name[0] !== '.') {
00793 $name = $this->viewPath . DS . $subDir . Inflector::underscore($name);
00794 } elseif (strpos($name, DS) !== false) {
00795 if ($name{0} === DS || $name{1} === ':') {
00796 if (is_file($name)) {
00797 return $name;
00798 }
00799 $name = trim($name, DS);
00800 } else if ($name[0] === '.') {
00801 $name = substr($name, 3);
00802 } else {
00803 $name = $this->viewPath . DS . $subDir . $name;
00804 }
00805 }
00806
00807 $paths = $this->_paths(Inflector::underscore($this->plugin));
00808
00809 foreach ($paths as $path) {
00810 if (file_exists($path . $name . $this->ext)) {
00811 return $path . $name . $this->ext;
00812 } elseif (file_exists($path . $name . '.ctp')) {
00813 return $path . $name . '.ctp';
00814 } elseif (file_exists($path . $name . '.thtml')) {
00815 return $path . $name . '.thtml';
00816 }
00817 }
00818 $defaultPath = $paths[0];
00819
00820 if ($this->plugin) {
00821 $pluginPaths = Configure::read('pluginPaths');
00822 foreach ($paths as $path) {
00823 if (strpos($path, $pluginPaths[0]) === 0) {
00824 $defaultPath = $path;
00825 break;
00826 }
00827 }
00828 }
00829 return $this->_missingView($defaultPath . $name . $this->ext, 'missingView');
00830 }
00831
00832
00833
00834
00835
00836
00837
00838 function _getLayoutFileName($name = null) {
00839 if ($name === null) {
00840 $name = $this->layout;
00841 }
00842 $subDir = null;
00843
00844 if (!is_null($this->layoutPath)) {
00845 $subDir = $this->layoutPath . DS;
00846 }
00847 $paths = $this->_paths(Inflector::underscore($this->plugin));
00848 $file = 'layouts' . DS . $subDir . $name;
00849
00850 $exts = array($this->ext, '.ctp', '.thtml');
00851 foreach ($paths as $path) {
00852 foreach ($exts as $ext) {
00853 if (file_exists($path . $file . $ext)) {
00854 return $path . $file . $ext;
00855 }
00856 }
00857 }
00858 return $this->_missingView($paths[0] . $file . $this->ext, 'missingLayout');
00859 }
00860
00861
00862
00863
00864
00865
00866 function _missingView($file, $error = 'missingView') {
00867
00868 if ($error === 'missingView') {
00869 $this->cakeError('missingView', array(
00870 'className' => $this->name,
00871 'action' => $this->action,
00872 'file' => $file,
00873 'base' => $this->base
00874 ));
00875 return false;
00876 } elseif ($error === 'missingLayout') {
00877 $this->cakeError('missingLayout', array(
00878 'layout' => $this->layout,
00879 'file' => $file,
00880 'base' => $this->base
00881 ));
00882 return false;
00883 }
00884 }
00885
00886
00887
00888
00889
00890
00891
00892 function _paths($plugin = null, $cached = true) {
00893 if ($plugin === null && $cached === true && !empty($this->__paths)) {
00894 return $this->__paths;
00895 }
00896 $paths = array();
00897 $viewPaths = Configure::read('viewPaths');
00898
00899 if (!empty($plugin)) {
00900 $count = count($viewPaths);
00901 for ($i = 0; $i < $count; $i++) {
00902 $paths[] = $viewPaths[$i] . 'plugins' . DS . $plugin . DS;
00903 }
00904 $pluginPaths = Configure::read('pluginPaths');
00905 $count = count($pluginPaths);
00906
00907 for ($i = 0; $i < $count; $i++) {
00908 $paths[] = $pluginPaths[$i] . $plugin . DS . 'views' . DS;
00909 }
00910 }
00911 $paths = array_merge($paths, $viewPaths);
00912
00913 if (empty($this->__paths)) {
00914 $this->__paths = $paths;
00915 }
00916 return $paths;
00917 }
00918
00919
00920
00921
00922 function renderElement($name, $params = array(), $loadHelpers = false) {
00923 return $this->element($name, $params, $loadHelpers);
00924 }
00925 }
00926
00927 ?>